xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file assembles .s files and emits Wasm .o object files.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/MC/MCWasmStreamer.h"
1481ad6265SDimitry Andric #include "llvm/ADT/SmallString.h"
1581ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
2081ad6265SDimitry Andric #include "llvm/MC/MCFixup.h"
2181ad6265SDimitry Andric #include "llvm/MC/MCFragment.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSectionWasm.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
290b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
310b57cec5SDimitry Andric 
3281ad6265SDimitry Andric namespace llvm {
3381ad6265SDimitry Andric class MCContext;
3481ad6265SDimitry Andric class MCStreamer;
3581ad6265SDimitry Andric class MCSubtargetInfo;
3681ad6265SDimitry Andric } // namespace llvm
3781ad6265SDimitry Andric 
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric MCWasmStreamer::~MCWasmStreamer() = default; // anchor.
410b57cec5SDimitry Andric 
42349cc55cSDimitry Andric void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
43349cc55cSDimitry Andric   auto *Symbol = cast<MCSymbolWasm>(S);
44349cc55cSDimitry Andric   MCObjectStreamer::emitLabel(Symbol, Loc);
45349cc55cSDimitry Andric 
46349cc55cSDimitry Andric   const MCSectionWasm &Section =
47349cc55cSDimitry Andric       static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
48349cc55cSDimitry Andric   if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
49349cc55cSDimitry Andric     Symbol->setTLS();
50349cc55cSDimitry Andric }
51349cc55cSDimitry Andric 
52*0fca6ea1SDimitry Andric void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,
53349cc55cSDimitry Andric                                     uint64_t Offset) {
54349cc55cSDimitry Andric   auto *Symbol = cast<MCSymbolWasm>(S);
55349cc55cSDimitry Andric   MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
56349cc55cSDimitry Andric 
57349cc55cSDimitry Andric   const MCSectionWasm &Section =
58349cc55cSDimitry Andric       static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
59349cc55cSDimitry Andric   if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
60349cc55cSDimitry Andric     Symbol->setTLS();
61349cc55cSDimitry Andric }
62349cc55cSDimitry Andric 
635ffd83dbSDimitry Andric void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
640b57cec5SDimitry Andric   // Let the target do whatever target specific stuff it needs to do.
650b57cec5SDimitry Andric   getAssembler().getBackend().handleAssemblerFlag(Flag);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   // Do any generic stuff we need to do.
680b57cec5SDimitry Andric   llvm_unreachable("invalid assembler flag!");
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
71*0fca6ea1SDimitry Andric void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
720b57cec5SDimitry Andric   MCAssembler &Asm = getAssembler();
730b57cec5SDimitry Andric   auto *SectionWasm = cast<MCSectionWasm>(Section);
740b57cec5SDimitry Andric   const MCSymbol *Grp = SectionWasm->getGroup();
750b57cec5SDimitry Andric   if (Grp)
760b57cec5SDimitry Andric     Asm.registerSymbol(*Grp);
770b57cec5SDimitry Andric 
785ffd83dbSDimitry Andric   this->MCObjectStreamer::changeSection(Section, Subsection);
790b57cec5SDimitry Andric   Asm.registerSymbol(*Section->getBeginSymbol());
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
825ffd83dbSDimitry Andric void MCWasmStreamer::emitWeakReference(MCSymbol *Alias,
830b57cec5SDimitry Andric                                        const MCSymbol *Symbol) {
840b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
850b57cec5SDimitry Andric   const MCExpr *Value = MCSymbolRefExpr::create(
860b57cec5SDimitry Andric       Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
870b57cec5SDimitry Andric   Alias->setVariableValue(Value);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
905ffd83dbSDimitry Andric bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
910b57cec5SDimitry Andric   assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolWasm>(S);
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Adding a symbol attribute always introduces the symbol; note that an
960b57cec5SDimitry Andric   // important side effect of calling registerSymbol here is to register the
970b57cec5SDimitry Andric   // symbol with the assembler.
980b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   switch (Attribute) {
1010b57cec5SDimitry Andric   case MCSA_LazyReference:
1020b57cec5SDimitry Andric   case MCSA_Reference:
1030b57cec5SDimitry Andric   case MCSA_SymbolResolver:
1040b57cec5SDimitry Andric   case MCSA_PrivateExtern:
1050b57cec5SDimitry Andric   case MCSA_WeakDefinition:
1060b57cec5SDimitry Andric   case MCSA_WeakDefAutoPrivate:
1070b57cec5SDimitry Andric   case MCSA_Invalid:
1080b57cec5SDimitry Andric   case MCSA_IndirectSymbol:
1090b57cec5SDimitry Andric   case MCSA_Protected:
11081ad6265SDimitry Andric   case MCSA_Exported:
1110b57cec5SDimitry Andric     return false;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   case MCSA_Hidden:
1140b57cec5SDimitry Andric     Symbol->setHidden(true);
1150b57cec5SDimitry Andric     break;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   case MCSA_Weak:
1180b57cec5SDimitry Andric   case MCSA_WeakReference:
1190b57cec5SDimitry Andric     Symbol->setWeak(true);
1200b57cec5SDimitry Andric     Symbol->setExternal(true);
1210b57cec5SDimitry Andric     break;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   case MCSA_Global:
1240b57cec5SDimitry Andric     Symbol->setExternal(true);
1250b57cec5SDimitry Andric     break;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   case MCSA_ELF_TypeFunction:
1280b57cec5SDimitry Andric     Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
1290b57cec5SDimitry Andric     break;
1300b57cec5SDimitry Andric 
131349cc55cSDimitry Andric   case MCSA_ELF_TypeTLS:
132349cc55cSDimitry Andric     Symbol->setTLS();
133349cc55cSDimitry Andric     break;
134349cc55cSDimitry Andric 
1350b57cec5SDimitry Andric   case MCSA_ELF_TypeObject:
1360b57cec5SDimitry Andric   case MCSA_Cold:
1370b57cec5SDimitry Andric     break;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   case MCSA_NoDeadStrip:
1408bcb0991SDimitry Andric     Symbol->setNoStrip();
1410b57cec5SDimitry Andric     break;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   default:
1440b57cec5SDimitry Andric     // unrecognized directive
1450b57cec5SDimitry Andric     llvm_unreachable("unexpected MCSymbolAttr");
1460b57cec5SDimitry Andric     return false;
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   return true;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1525ffd83dbSDimitry Andric void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
153bdd1243dSDimitry Andric                                       Align ByteAlignment) {
1540b57cec5SDimitry Andric   llvm_unreachable("Common symbols are not yet implemented for Wasm");
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
1580b57cec5SDimitry Andric   cast<MCSymbolWasm>(Symbol)->setSize(Value);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1615ffd83dbSDimitry Andric void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
162bdd1243dSDimitry Andric                                            Align ByteAlignment) {
1630b57cec5SDimitry Andric   llvm_unreachable("Local common symbols are not yet implemented for Wasm");
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1665ffd83dbSDimitry Andric void MCWasmStreamer::emitIdent(StringRef IdentString) {
1670b57cec5SDimitry Andric   // TODO(sbc): Add the ident section once we support mergable strings
1680b57cec5SDimitry Andric   // sections in the object format
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1715ffd83dbSDimitry Andric void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
1720b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI) {
1735ffd83dbSDimitry Andric   this->MCObjectStreamer::emitInstToFragment(Inst, STI);
174349cc55cSDimitry Andric   MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
175349cc55cSDimitry Andric 
176349cc55cSDimitry Andric   for (auto &Fixup : F.getFixups())
177349cc55cSDimitry Andric     fixSymbolsInTLSFixups(Fixup.getValue());
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1805ffd83dbSDimitry Andric void MCWasmStreamer::emitInstToData(const MCInst &Inst,
1810b57cec5SDimitry Andric                                     const MCSubtargetInfo &STI) {
1820b57cec5SDimitry Andric   MCAssembler &Assembler = getAssembler();
1830b57cec5SDimitry Andric   SmallVector<MCFixup, 4> Fixups;
1840b57cec5SDimitry Andric   SmallString<256> Code;
18506c3fb27SDimitry Andric   Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
1860b57cec5SDimitry Andric 
187349cc55cSDimitry Andric   for (auto &Fixup : Fixups)
188349cc55cSDimitry Andric     fixSymbolsInTLSFixups(Fixup.getValue());
189349cc55cSDimitry Andric 
1900b57cec5SDimitry Andric   // Append the encoded instruction to the current data fragment (or create a
1910b57cec5SDimitry Andric   // new such fragment if the current fragment is not a data fragment).
1920b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   // Add the fixups and data.
1950b57cec5SDimitry Andric   for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
1960b57cec5SDimitry Andric     Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size());
1970b57cec5SDimitry Andric     DF->getFixups().push_back(Fixups[I]);
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric   DF->setHasInstructions(STI);
2000b57cec5SDimitry Andric   DF->getContents().append(Code.begin(), Code.end());
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2035ffd83dbSDimitry Andric void MCWasmStreamer::finishImpl() {
2045ffd83dbSDimitry Andric   emitFrames(nullptr);
2050b57cec5SDimitry Andric 
2065ffd83dbSDimitry Andric   this->MCObjectStreamer::finishImpl();
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
209349cc55cSDimitry Andric void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
210349cc55cSDimitry Andric   switch (expr->getKind()) {
211349cc55cSDimitry Andric   case MCExpr::Target:
212349cc55cSDimitry Andric   case MCExpr::Constant:
213349cc55cSDimitry Andric     break;
214349cc55cSDimitry Andric 
215349cc55cSDimitry Andric   case MCExpr::Binary: {
216349cc55cSDimitry Andric     const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
217349cc55cSDimitry Andric     fixSymbolsInTLSFixups(be->getLHS());
218349cc55cSDimitry Andric     fixSymbolsInTLSFixups(be->getRHS());
219349cc55cSDimitry Andric     break;
220349cc55cSDimitry Andric   }
221349cc55cSDimitry Andric 
222349cc55cSDimitry Andric   case MCExpr::SymbolRef: {
223349cc55cSDimitry Andric     const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
224349cc55cSDimitry Andric     switch (symRef.getKind()) {
225349cc55cSDimitry Andric     case MCSymbolRefExpr::VK_WASM_TLSREL:
226349cc55cSDimitry Andric     case MCSymbolRefExpr::VK_WASM_GOT_TLS:
227349cc55cSDimitry Andric       getAssembler().registerSymbol(symRef.getSymbol());
228349cc55cSDimitry Andric       cast<MCSymbolWasm>(symRef.getSymbol()).setTLS();
229349cc55cSDimitry Andric       break;
230349cc55cSDimitry Andric     default:
231349cc55cSDimitry Andric       break;
232349cc55cSDimitry Andric     }
233349cc55cSDimitry Andric     break;
234349cc55cSDimitry Andric   }
235349cc55cSDimitry Andric 
236349cc55cSDimitry Andric   case MCExpr::Unary:
237349cc55cSDimitry Andric     fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
238349cc55cSDimitry Andric     break;
239349cc55cSDimitry Andric   }
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2425ffd83dbSDimitry Andric void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) {
2430b57cec5SDimitry Andric   llvm_unreachable("Generic Wasm doesn't support this directive");
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2465ffd83dbSDimitry Andric void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
2470b57cec5SDimitry Andric   llvm_unreachable("Wasm doesn't support this directive");
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2505ffd83dbSDimitry Andric void MCWasmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
251bdd1243dSDimitry Andric                                   uint64_t Size, Align ByteAlignment,
2520b57cec5SDimitry Andric                                   SMLoc Loc) {
2530b57cec5SDimitry Andric   llvm_unreachable("Wasm doesn't support this directive");
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2565ffd83dbSDimitry Andric void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
257bdd1243dSDimitry Andric                                     uint64_t Size, Align ByteAlignment) {
2580b57cec5SDimitry Andric   llvm_unreachable("Wasm doesn't support this directive");
2590b57cec5SDimitry Andric }
260349cc55cSDimitry Andric 
261349cc55cSDimitry Andric MCStreamer *llvm::createWasmStreamer(MCContext &Context,
262349cc55cSDimitry Andric                                      std::unique_ptr<MCAsmBackend> &&MAB,
263349cc55cSDimitry Andric                                      std::unique_ptr<MCObjectWriter> &&OW,
264*0fca6ea1SDimitry Andric                                      std::unique_ptr<MCCodeEmitter> &&CE) {
265349cc55cSDimitry Andric   MCWasmStreamer *S =
266349cc55cSDimitry Andric       new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
267349cc55cSDimitry Andric   return S;
268349cc55cSDimitry Andric }
269