1 //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file assembles .s files and emits Wasm .o object files. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/MC/MCWasmStreamer.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/SmallPtrSet.h" 17 #include "llvm/MC/MCAsmBackend.h" 18 #include "llvm/MC/MCAsmLayout.h" 19 #include "llvm/MC/MCAssembler.h" 20 #include "llvm/MC/MCCodeEmitter.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCObjectStreamer.h" 25 #include "llvm/MC/MCSection.h" 26 #include "llvm/MC/MCSectionWasm.h" 27 #include "llvm/MC/MCSymbol.h" 28 #include "llvm/MC/MCSymbolWasm.h" 29 #include "llvm/MC/MCValue.h" 30 #include "llvm/Support/Casting.h" 31 #include "llvm/Support/Debug.h" 32 #include "llvm/Support/ErrorHandling.h" 33 #include "llvm/Support/TargetRegistry.h" 34 #include "llvm/Support/raw_ostream.h" 35 36 using namespace llvm; 37 38 MCWasmStreamer::~MCWasmStreamer() {} 39 40 void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) { 41 flushPendingLabels(DF, DF->getContents().size()); 42 43 for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { 44 EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() + 45 DF->getContents().size()); 46 DF->getFixups().push_back(EF->getFixups()[i]); 47 } 48 if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) 49 DF->setHasInstructions(*EF->getSubtargetInfo()); 50 DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); 51 } 52 53 void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 54 // Let the target do whatever target specific stuff it needs to do. 55 getAssembler().getBackend().handleAssemblerFlag(Flag); 56 57 // Do any generic stuff we need to do. 58 llvm_unreachable("invalid assembler flag!"); 59 } 60 61 void MCWasmStreamer::ChangeSection(MCSection *Section, 62 const MCExpr *Subsection) { 63 MCAssembler &Asm = getAssembler(); 64 auto *SectionWasm = static_cast<const MCSectionWasm *>(Section); 65 const MCSymbol *Grp = SectionWasm->getGroup(); 66 if (Grp) 67 Asm.registerSymbol(*Grp); 68 69 this->MCObjectStreamer::ChangeSection(Section, Subsection); 70 Asm.registerSymbol(*Section->getBeginSymbol()); 71 } 72 73 void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias, 74 const MCSymbol *Symbol) { 75 getAssembler().registerSymbol(*Symbol); 76 const MCExpr *Value = MCSymbolRefExpr::create( 77 Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); 78 Alias->setVariableValue(Value); 79 } 80 81 bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { 82 assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported"); 83 84 auto *Symbol = cast<MCSymbolWasm>(S); 85 86 // Adding a symbol attribute always introduces the symbol; note that an 87 // important side effect of calling registerSymbol here is to register the 88 // symbol with the assembler. 89 getAssembler().registerSymbol(*Symbol); 90 91 switch (Attribute) { 92 case MCSA_LazyReference: 93 case MCSA_Reference: 94 case MCSA_SymbolResolver: 95 case MCSA_PrivateExtern: 96 case MCSA_WeakDefinition: 97 case MCSA_WeakDefAutoPrivate: 98 case MCSA_Invalid: 99 case MCSA_IndirectSymbol: 100 case MCSA_Protected: 101 return false; 102 103 case MCSA_Hidden: 104 Symbol->setHidden(true); 105 break; 106 107 case MCSA_Weak: 108 case MCSA_WeakReference: 109 Symbol->setWeak(true); 110 Symbol->setExternal(true); 111 break; 112 113 case MCSA_Global: 114 Symbol->setExternal(true); 115 break; 116 117 case MCSA_ELF_TypeFunction: 118 Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); 119 break; 120 121 case MCSA_ELF_TypeObject: 122 Symbol->setType(wasm::WASM_SYMBOL_TYPE_DATA); 123 break; 124 125 default: 126 // unrecognized directive 127 llvm_unreachable("unexpected MCSymbolAttr"); 128 return false; 129 } 130 131 return true; 132 } 133 134 void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, 135 unsigned ByteAlignment) { 136 llvm_unreachable("Common symbols are not yet implemented for Wasm"); 137 } 138 139 void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 140 cast<MCSymbolWasm>(Symbol)->setSize(Value); 141 } 142 143 void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, 144 unsigned ByteAlignment) { 145 llvm_unreachable("Local common symbols are not yet implemented for Wasm"); 146 } 147 148 void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, 149 SMLoc Loc) { 150 MCObjectStreamer::EmitValueImpl(Value, Size, Loc); 151 } 152 153 void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 154 unsigned ValueSize, 155 unsigned MaxBytesToEmit) { 156 MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize, 157 MaxBytesToEmit); 158 } 159 160 void MCWasmStreamer::EmitIdent(StringRef IdentString) { 161 // TODO(sbc): Add the ident section once we support mergable strings 162 // sections in the object format 163 } 164 165 void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst, 166 const MCSubtargetInfo &STI) { 167 this->MCObjectStreamer::EmitInstToFragment(Inst, STI); 168 } 169 170 void MCWasmStreamer::EmitInstToData(const MCInst &Inst, 171 const MCSubtargetInfo &STI) { 172 MCAssembler &Assembler = getAssembler(); 173 SmallVector<MCFixup, 4> Fixups; 174 SmallString<256> Code; 175 raw_svector_ostream VecOS(Code); 176 Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); 177 178 // Append the encoded instruction to the current data fragment (or create a 179 // new such fragment if the current fragment is not a data fragment). 180 MCDataFragment *DF = getOrCreateDataFragment(); 181 182 // Add the fixups and data. 183 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 184 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 185 DF->getFixups().push_back(Fixups[i]); 186 } 187 DF->setHasInstructions(STI); 188 DF->getContents().append(Code.begin(), Code.end()); 189 } 190 191 void MCWasmStreamer::FinishImpl() { 192 EmitFrames(nullptr); 193 194 this->MCObjectStreamer::FinishImpl(); 195 } 196 197 MCStreamer *llvm::createWasmStreamer(MCContext &Context, 198 std::unique_ptr<MCAsmBackend> &&MAB, 199 std::unique_ptr<MCObjectWriter> &&OW, 200 std::unique_ptr<MCCodeEmitter> &&CE, 201 bool RelaxAll) { 202 MCWasmStreamer *S = 203 new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); 204 if (RelaxAll) 205 S->getAssembler().setRelaxAll(true); 206 return S; 207 } 208 209 void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) { 210 llvm_unreachable("Generic Wasm doesn't support this directive"); 211 } 212 213 void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 214 llvm_unreachable("Wasm doesn't support this directive"); 215 } 216 217 void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 218 uint64_t Size, unsigned ByteAlignment, 219 SMLoc Loc) { 220 llvm_unreachable("Wasm doesn't support this directive"); 221 } 222 223 void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 224 uint64_t Size, unsigned ByteAlignment) { 225 llvm_unreachable("Wasm doesn't support this directive"); 226 } 227