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