1//===- lib/MC/MCWasmStreamer.cpp - Wasm 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 Wasm .o object files.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/MC/MCWasmStreamer.h"
14#include "llvm/MC/MCAsmBackend.h"
15#include "llvm/MC/MCAssembler.h"
16#include "llvm/MC/MCCodeEmitter.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCFixup.h"
20#include "llvm/MC/MCObjectStreamer.h"
21#include "llvm/MC/MCSection.h"
22#include "llvm/MC/MCSectionWasm.h"
23#include "llvm/MC/MCSymbol.h"
24#include "llvm/MC/MCSymbolWasm.h"
25#include "llvm/MC/TargetRegistry.h"
26#include "llvm/Support/ErrorHandling.h"
27
28namespace llvm {
29class MCContext;
30class MCStreamer;
31class MCSubtargetInfo;
32} // namespace llvm
33
34using namespace llvm;
35
36MCWasmStreamer::~MCWasmStreamer() = default; // anchor.
37
38void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
39 auto *Symbol = static_cast<MCSymbolWasm *>(S);
40 MCObjectStreamer::emitLabel(Symbol, Loc);
41
42 const MCSectionWasm &Section =
43 static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
44 if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
45 Symbol->setTLS();
46}
47
48void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment &F,
49 uint64_t Offset) {
50 auto *Symbol = static_cast<MCSymbolWasm *>(S);
51 MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
52
53 const MCSectionWasm &Section =
54 static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
55 if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
56 Symbol->setTLS();
57}
58
59void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
60 MCAssembler &Asm = getAssembler();
61 auto *SectionWasm = static_cast<const MCSectionWasm *>(Section);
62 const MCSymbol *Grp = SectionWasm->getGroup();
63 if (Grp)
64 Asm.registerSymbol(Symbol: *Grp);
65
66 this->MCObjectStreamer::changeSection(Section, Subsection);
67 Asm.registerSymbol(Symbol: *Section->getBeginSymbol());
68}
69
70bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
71 assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
72 auto *Symbol = static_cast<MCSymbolWasm *>(S);
73
74 // Adding a symbol attribute always introduces the symbol; note that an
75 // important side effect of calling registerSymbol here is to register the
76 // symbol with the assembler.
77 getAssembler().registerSymbol(Symbol: *Symbol);
78
79 switch (Attribute) {
80 case MCSA_LazyReference:
81 case MCSA_Reference:
82 case MCSA_SymbolResolver:
83 case MCSA_PrivateExtern:
84 case MCSA_WeakDefinition:
85 case MCSA_WeakDefAutoPrivate:
86 case MCSA_Invalid:
87 case MCSA_IndirectSymbol:
88 case MCSA_Protected:
89 case MCSA_Exported:
90 return false;
91
92 case MCSA_Hidden:
93 Symbol->setHidden(true);
94 break;
95
96 case MCSA_Weak:
97 case MCSA_WeakReference:
98 Symbol->setWeak(true);
99 Symbol->setExternal(true);
100 break;
101
102 case MCSA_Global:
103 Symbol->setExternal(true);
104 break;
105
106 case MCSA_ELF_TypeFunction:
107 Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
108 break;
109
110 case MCSA_ELF_TypeTLS:
111 Symbol->setTLS();
112 break;
113
114 case MCSA_ELF_TypeObject:
115 case MCSA_Cold:
116 break;
117
118 case MCSA_NoDeadStrip:
119 Symbol->setNoStrip();
120 break;
121
122 default:
123 // unrecognized directive
124 llvm_unreachable("unexpected MCSymbolAttr");
125 return false;
126 }
127
128 return true;
129}
130
131void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
132 Align ByteAlignment) {
133 getContext().reportError(L: getStartTokLoc(),
134 Msg: "common symbols are not yet implemented for Wasm: " +
135 S->getName());
136}
137
138void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
139 static_cast<MCSymbolWasm *>(Symbol)->setSize(Value);
140}
141
142void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
143 Align ByteAlignment) {
144 getContext().reportError(L: getStartTokLoc(),
145 Msg: "local common symbols are not yet implemented "
146 "for Wasm: " +
147 S->getName());
148}
149
150void MCWasmStreamer::emitIdent(StringRef IdentString) {
151 // TODO(sbc): Add the ident section once we support mergable strings
152 // sections in the object format
153}
154
155void MCWasmStreamer::finishImpl() {
156 emitFrames();
157
158 this->MCObjectStreamer::finishImpl();
159}
160
161MCStreamer *llvm::createWasmStreamer(MCContext &Context,
162 std::unique_ptr<MCAsmBackend> &&MAB,
163 std::unique_ptr<MCObjectWriter> &&OW,
164 std::unique_ptr<MCCodeEmitter> &&CE) {
165 MCWasmStreamer *S =
166 new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
167 return S;
168}
169