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 // XCOFF doesn't support the cold feature. 41 case MCSA_Cold: 42 return false; 43 44 case MCSA_Global: 45 case MCSA_Extern: 46 Symbol->setStorageClass(XCOFF::C_EXT); 47 Symbol->setExternal(true); 48 break; 49 case MCSA_LGlobal: 50 Symbol->setStorageClass(XCOFF::C_HIDEXT); 51 Symbol->setExternal(true); 52 break; 53 case llvm::MCSA_Weak: 54 Symbol->setStorageClass(XCOFF::C_WEAKEXT); 55 Symbol->setExternal(true); 56 break; 57 case llvm::MCSA_Hidden: 58 Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN); 59 break; 60 case llvm::MCSA_Protected: 61 Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED); 62 break; 63 case llvm::MCSA_Exported: 64 Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED); 65 break; 66 default: 67 report_fatal_error("Not implemented yet."); 68 } 69 return true; 70 } 71 72 void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility( 73 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) { 74 75 emitSymbolAttribute(Symbol, Linkage); 76 77 // When the caller passes `MCSA_Invalid` for the visibility, do not emit one. 78 if (Visibility == MCSA_Invalid) 79 return; 80 81 emitSymbolAttribute(Symbol, Visibility); 82 } 83 84 void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) { 85 // Add a Fixup here to later record a relocation of type R_REF to prevent the 86 // ref symbol from being garbage collected (by the binder). 87 MCDataFragment *DF = getOrCreateDataFragment(); 88 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); 89 std::optional<MCFixupKind> MaybeKind = 90 getAssembler().getBackend().getFixupKind("R_REF"); 91 if (!MaybeKind) 92 report_fatal_error("failed to get fixup kind for R_REF relocation"); 93 94 MCFixupKind Kind = *MaybeKind; 95 MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, Kind); 96 DF->getFixups().push_back(Fixup); 97 } 98 99 void MCXCOFFStreamer::emitXCOFFRenameDirective(const MCSymbol *Name, 100 StringRef Rename) { 101 const MCSymbolXCOFF *Symbol = cast<const MCSymbolXCOFF>(Name); 102 if (!Symbol->hasRename()) 103 report_fatal_error("Only explicit .rename is supported for XCOFF."); 104 } 105 106 void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, 107 const MCSymbol *Trap, 108 unsigned Lang, unsigned Reason, 109 unsigned FunctionSize, 110 bool hasDebug) { 111 getAssembler().getWriter().addExceptionEntry(Symbol, Trap, Lang, Reason, 112 FunctionSize, hasDebug); 113 } 114 115 void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) { 116 getAssembler().getWriter().addCInfoSymEntry(Name, Metadata); 117 } 118 119 void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 120 Align ByteAlignment) { 121 getAssembler().registerSymbol(*Symbol); 122 Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() != 123 XCOFF::C_HIDEXT); 124 Symbol->setCommon(Size, ByteAlignment); 125 126 // Default csect align is 4, but common symbols have explicit alignment values 127 // and we should honor it. 128 cast<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment( 129 ByteAlignment); 130 131 // Emit the alignment and storage for the variable to the section. 132 emitValueToAlignment(ByteAlignment); 133 emitZeros(Size); 134 } 135 136 void MCXCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 137 uint64_t Size, Align ByteAlignment, 138 SMLoc Loc) { 139 report_fatal_error("Zero fill not implemented for XCOFF."); 140 } 141 142 void MCXCOFFStreamer::emitInstToData(const MCInst &Inst, 143 const MCSubtargetInfo &STI) { 144 MCAssembler &Assembler = getAssembler(); 145 SmallVector<MCFixup, 4> Fixups; 146 SmallString<256> Code; 147 Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI); 148 149 // Add the fixups and data. 150 MCDataFragment *DF = getOrCreateDataFragment(&STI); 151 const size_t ContentsSize = DF->getContents().size(); 152 auto &DataFragmentFixups = DF->getFixups(); 153 for (auto &Fixup : Fixups) { 154 Fixup.setOffset(Fixup.getOffset() + ContentsSize); 155 DataFragmentFixups.push_back(Fixup); 156 } 157 158 DF->setHasInstructions(STI); 159 DF->getContents().append(Code.begin(), Code.end()); 160 } 161 162 MCStreamer *llvm::createXCOFFStreamer(MCContext &Context, 163 std::unique_ptr<MCAsmBackend> &&MAB, 164 std::unique_ptr<MCObjectWriter> &&OW, 165 std::unique_ptr<MCCodeEmitter> &&CE, 166 bool RelaxAll) { 167 MCXCOFFStreamer *S = new MCXCOFFStreamer(Context, std::move(MAB), 168 std::move(OW), std::move(CE)); 169 if (RelaxAll) 170 S->getAssembler().setRelaxAll(true); 171 return S; 172 } 173 174 void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, 175 uint64_t Size, 176 MCSymbol *CsectSym, 177 Align Alignment) { 178 emitCommonSymbol(CsectSym, Size, Alignment); 179 } 180