1 //===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file assembles .s files and emits XCOFF .o object files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/MC/MCXCOFFStreamer.h" 14 #include "llvm/BinaryFormat/XCOFF.h" 15 #include "llvm/MC/MCAsmBackend.h" 16 #include "llvm/MC/MCAssembler.h" 17 #include "llvm/MC/MCCodeEmitter.h" 18 #include "llvm/MC/MCDirectives.h" 19 #include "llvm/MC/MCObjectWriter.h" 20 #include "llvm/MC/MCSectionXCOFF.h" 21 #include "llvm/MC/MCSymbolXCOFF.h" 22 #include "llvm/MC/TargetRegistry.h" 23 #include "llvm/Support/Casting.h" 24 25 using namespace llvm; 26 27 MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context, 28 std::unique_ptr<MCAsmBackend> MAB, 29 std::unique_ptr<MCObjectWriter> OW, 30 std::unique_ptr<MCCodeEmitter> Emitter) 31 : MCObjectStreamer(Context, std::move(MAB), std::move(OW), 32 std::move(Emitter)) {} 33 34 bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym, 35 MCSymbolAttr Attribute) { 36 auto *Symbol = cast<MCSymbolXCOFF>(Sym); 37 getAssembler().registerSymbol(*Symbol); 38 39 switch (Attribute) { 40 case MCSA_Global: 41 case MCSA_Extern: 42 Symbol->setStorageClass(XCOFF::C_EXT); 43 Symbol->setExternal(true); 44 break; 45 case MCSA_LGlobal: 46 Symbol->setStorageClass(XCOFF::C_HIDEXT); 47 Symbol->setExternal(true); 48 break; 49 case llvm::MCSA_Weak: 50 Symbol->setStorageClass(XCOFF::C_WEAKEXT); 51 Symbol->setExternal(true); 52 break; 53 case llvm::MCSA_Hidden: 54 Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN); 55 break; 56 case llvm::MCSA_Protected: 57 Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED); 58 break; 59 case llvm::MCSA_Exported: 60 Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED); 61 break; 62 default: 63 report_fatal_error("Not implemented yet."); 64 } 65 return true; 66 } 67 68 void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility( 69 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) { 70 71 emitSymbolAttribute(Symbol, Linkage); 72 73 // When the caller passes `MCSA_Invalid` for the visibility, do not emit one. 74 if (Visibility == MCSA_Invalid) 75 return; 76 77 emitSymbolAttribute(Symbol, Visibility); 78 } 79 80 void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 81 unsigned ByteAlignment) { 82 getAssembler().registerSymbol(*Symbol); 83 Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() != 84 XCOFF::C_HIDEXT); 85 Symbol->setCommon(Size, ByteAlignment); 86 87 // Default csect align is 4, but common symbols have explicit alignment values 88 // and we should honor it. 89 cast<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment( 90 Align(ByteAlignment)); 91 92 // Emit the alignment and storage for the variable to the section. 93 emitValueToAlignment(ByteAlignment); 94 emitZeros(Size); 95 } 96 97 void MCXCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 98 uint64_t Size, unsigned ByteAlignment, 99 SMLoc Loc) { 100 report_fatal_error("Zero fill not implemented for XCOFF."); 101 } 102 103 void MCXCOFFStreamer::emitInstToData(const MCInst &Inst, 104 const MCSubtargetInfo &STI) { 105 MCAssembler &Assembler = getAssembler(); 106 SmallVector<MCFixup, 4> Fixups; 107 SmallString<256> Code; 108 raw_svector_ostream VecOS(Code); 109 Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); 110 111 // Add the fixups and data. 112 MCDataFragment *DF = getOrCreateDataFragment(&STI); 113 const size_t ContentsSize = DF->getContents().size(); 114 auto &DataFragmentFixups = DF->getFixups(); 115 for (auto &Fixup : Fixups) { 116 Fixup.setOffset(Fixup.getOffset() + ContentsSize); 117 DataFragmentFixups.push_back(Fixup); 118 } 119 120 DF->setHasInstructions(STI); 121 DF->getContents().append(Code.begin(), Code.end()); 122 } 123 124 MCStreamer *llvm::createXCOFFStreamer(MCContext &Context, 125 std::unique_ptr<MCAsmBackend> &&MAB, 126 std::unique_ptr<MCObjectWriter> &&OW, 127 std::unique_ptr<MCCodeEmitter> &&CE, 128 bool RelaxAll) { 129 MCXCOFFStreamer *S = new MCXCOFFStreamer(Context, std::move(MAB), 130 std::move(OW), std::move(CE)); 131 if (RelaxAll) 132 S->getAssembler().setRelaxAll(true); 133 return S; 134 } 135 136 void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, 137 uint64_t Size, 138 MCSymbol *CsectSym, 139 unsigned ByteAlignment) { 140 emitCommonSymbol(CsectSym, Size, ByteAlignment); 141 } 142