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