llvm.org GIT mirror llvm / 8bcdd04
[WebAssembly] Add support for the event section Summary: This adds support for the 'event section' specified in the exception handling proposal. (This was named 'exception section' first, but later renamed to 'event section' to take possibilities of other kinds of events into consideration. But currently we only store exception info in this section.) The event section is added between the global section and the export section. This is for ease of validation per request of the V8 team. This patch: - Creates the event symbol type, which is a weak symbol - Makes 'throw' instruction take the event symbol '__cpp_exception' - Adds relocation support for events - Adds WasmObjectWriter / WasmObjectFile (Reader) support - Adds obj2yaml / yaml2obj support - Adds '.eventtype' printing support Reviewers: dschuff, sbc100, aardappel Subscribers: jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D54096 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346825 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 9 months ago
34 changed file(s) with 714 addition(s) and 122 deletion(s). Raw diff Collapse all Expand all
7474 StringRef SymbolName; // from the "linking" section
7575 };
7676
77 struct WasmEventType {
78 // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible.
79 uint32_t Attribute;
80 uint32_t SigIndex;
81 };
82
83 struct WasmEvent {
84 uint32_t Index;
85 WasmEventType Type;
86 StringRef SymbolName; // from the "linking" section
87 };
88
7789 struct WasmImport {
7890 StringRef Module;
7991 StringRef Field;
8395 WasmGlobalType Global;
8496 WasmTable Table;
8597 WasmLimits Memory;
98 WasmEventType Event;
8699 };
87100 };
88101
177190 WASM_SEC_START = 8, // Start function declaration
178191 WASM_SEC_ELEM = 9, // Elements section
179192 WASM_SEC_CODE = 10, // Function bodies (code)
180 WASM_SEC_DATA = 11 // Data segments
193 WASM_SEC_DATA = 11, // Data segments
194 WASM_SEC_EVENT = 12 // Event declarations
181195 };
182196
183197 // Type immediate encodings used in various contexts.
199213 WASM_EXTERNAL_TABLE = 0x1,
200214 WASM_EXTERNAL_MEMORY = 0x2,
201215 WASM_EXTERNAL_GLOBAL = 0x3,
216 WASM_EXTERNAL_EVENT = 0x4,
202217 };
203218
204219 // Opcodes used in initializer expressions.
242257 WASM_SYMBOL_TYPE_DATA = 0x1,
243258 WASM_SYMBOL_TYPE_GLOBAL = 0x2,
244259 WASM_SYMBOL_TYPE_SECTION = 0x3,
260 WASM_SYMBOL_TYPE_EVENT = 0x4,
261 };
262
263 // Kinds of event attributes.
264 enum WasmEventAttribute : unsigned {
265 WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0,
245266 };
246267
247268 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
None
1 #ifndef WASM_RELOC
21 #error "WASM_RELOC must be defined"
32 #endif
1211 WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7)
1312 WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8)
1413 WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9)
14 WASM_RELOC(R_WEBASSEMBLY_EVENT_INDEX_LEB, 10)
1919 #include "llvm/IR/BasicBlock.h"
2020
2121 namespace llvm {
22
23 enum EventTag { CPP_EXCEPTION = 0, C_LONGJMP = 1 };
2224
2325 using BBOrMBB = PointerUnion;
2426
287287 VK_WebAssembly_FUNCTION, // Function table index, rather than virtual addr
288288 VK_WebAssembly_GLOBAL, // Global object index
289289 VK_WebAssembly_TYPEINDEX,// Type table index
290 VK_WebAssembly_EVENT, // Event index
290291
291292 VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo
292293 VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
2020 bool IsComdat = false;
2121 std::string ModuleName;
2222 wasm::WasmSignature *Signature = nullptr;
23 wasm::WasmGlobalType GlobalType;
24 bool GlobalTypeSet = false;
23 Optional GlobalType;
24 Optional EventType;
2525
2626 /// An expression describing how to calculate the size of a symbol. If a
2727 /// symbol has no size this field will be NULL.
4141 bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; }
4242 bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
4343 bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; }
44 bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; }
4445 wasm::WasmSymbolType getType() const { return Type; }
4546 void setType(wasm::WasmSymbolType type) { Type = type; }
4647
6061 void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; }
6162
6263 const wasm::WasmGlobalType &getGlobalType() const {
63 assert(GlobalTypeSet);
64 return GlobalType;
64 assert(GlobalType.hasValue());
65 return GlobalType.getValue();
6566 }
67 void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
6668
67 void setGlobalType(wasm::WasmGlobalType GT) {
68 GlobalTypeSet = true;
69 GlobalType = GT;
69 const wasm::WasmEventType &getEventType() const {
70 assert(EventType.hasValue());
71 return EventType.getValue();
7072 }
73 void setEventType(wasm::WasmEventType ET) { EventType = ET; }
7174 };
7275
7376 } // end namespace llvm
332332 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
333333 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
334334 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
335 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
335336 // For wasm section, its offset at 0 -- ignoring Value
336337 return 0;
337338 }
3737 public:
3838 WasmSymbol(const wasm::WasmSymbolInfo &Info,
3939 const wasm::WasmSignature *FunctionType,
40 const wasm::WasmGlobalType *GlobalType)
41 : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}
40 const wasm::WasmGlobalType *GlobalType,
41 const wasm::WasmEventType *EventType)
42 : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType),
43 EventType(EventType) {}
4244
4345 const wasm::WasmSymbolInfo &Info;
4446 const wasm::WasmSignature *FunctionType;
4547 const wasm::WasmGlobalType *GlobalType;
48 const wasm::WasmEventType *EventType;
4649
4750 bool isTypeFunction() const {
4851 return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
5760 bool isTypeSection() const {
5861 return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
5962 }
63
64 bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; }
6065
6166 bool isDefined() const { return !isUndefined(); }
6267
129134 ArrayRef tables() const { return Tables; }
130135 ArrayRef memories() const { return Memories; }
131136 ArrayRef globals() const { return Globals; }
137 ArrayRef events() const { return Events; }
132138 ArrayRef exports() const { return Exports; }
133139 ArrayRef syms() const { return Symbols; }
134140 const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
140146 uint32_t startFunction() const { return StartFunction; }
141147 uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
142148 uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
149 uint32_t getNumImportedEvents() const { return NumImportedEvents; }
143150
144151 void moveSymbolNext(DataRefImpl &Symb) const override;
145152
204211 bool isDefinedFunctionIndex(uint32_t Index) const;
205212 bool isValidGlobalIndex(uint32_t Index) const;
206213 bool isDefinedGlobalIndex(uint32_t Index) const;
214 bool isValidEventIndex(uint32_t Index) const;
215 bool isDefinedEventIndex(uint32_t Index) const;
207216 bool isValidFunctionSymbol(uint32_t Index) const;
208217 bool isValidGlobalSymbol(uint32_t Index) const;
218 bool isValidEventSymbol(uint32_t Index) const;
209219 bool isValidDataSymbol(uint32_t Index) const;
210220 bool isValidSectionSymbol(uint32_t Index) const;
211221 wasm::WasmFunction &getDefinedFunction(uint32_t Index);
212222 wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
223 wasm::WasmEvent &getDefinedEvent(uint32_t Index);
213224
214225 const WasmSection &getWasmSection(DataRefImpl Ref) const;
215226 const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
225236 Error parseTableSection(ReadContext &Ctx);
226237 Error parseMemorySection(ReadContext &Ctx);
227238 Error parseGlobalSection(ReadContext &Ctx);
239 Error parseEventSection(ReadContext &Ctx);
228240 Error parseExportSection(ReadContext &Ctx);
229241 Error parseStartSection(ReadContext &Ctx);
230242 Error parseElemSection(ReadContext &Ctx);
245257 std::vector Tables;
246258 std::vector Memories;
247259 std::vector Globals;
260 std::vector Events;
248261 std::vector Imports;
249262 std::vector Exports;
250263 std::vector ElemSegments;
257270 wasm::WasmLinkingData LinkingData;
258271 uint32_t NumImportedGlobals = 0;
259272 uint32_t NumImportedFunctions = 0;
273 uint32_t NumImportedEvents = 0;
260274 uint32_t CodeSection = 0;
261275 uint32_t DataSection = 0;
262276 uint32_t GlobalSection = 0;
277 uint32_t EventSection = 0;
263278 };
264279
265280 } // end namespace object
7373 wasm::WasmInitExpr InitExpr;
7474 };
7575
76 struct Event {
77 uint32_t Index;
78 uint32_t Attribute;
79 uint32_t SigIndex;
80 };
81
7682 struct Import {
7783 StringRef Module;
7884 StringRef Field;
8288 Global GlobalImport;
8389 Table TableImport;
8490 Limits Memory;
91 Event EventImport;
8592 };
8693 };
8794
259266 }
260267
261268 std::vector Globals;
269 };
270
271 struct EventSection : Section {
272 EventSection() : Section(wasm::WASM_SEC_EVENT) {}
273
274 static bool classof(const Section *S) {
275 return S->Type == wasm::WASM_SEC_EVENT;
276 }
277
278 std::vector Events;
262279 };
263280
264281 struct ExportSection : Section {
338355 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
339356 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
340357 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
358 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Event)
341359
342360 namespace llvm {
343361 namespace yaml {
470488 static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
471489 };
472490
491 template <> struct MappingTraits {
492 static void mapping(IO &IO, WasmYAML::Event &Event);
493 };
494
473495 } // end namespace yaml
474496 } // end namespace llvm
475497
1818 return "WASM_SYMBOL_TYPE_DATA";
1919 case wasm::WASM_SYMBOL_TYPE_SECTION:
2020 return "WASM_SYMBOL_TYPE_SECTION";
21 case wasm::WASM_SYMBOL_TYPE_EVENT:
22 return "WASM_SYMBOL_TYPE_EVENT";
2123 }
2224 llvm_unreachable("unknown symbol type");
2325 }
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "WasmException.h"
15 #include "llvm/IR/Mangler.h"
16 #include "llvm/MC/MCContext.h"
1517 #include "llvm/MC/MCStreamer.h"
1618 using namespace llvm;
19
20 void WasmException::endModule() {
21 // This is the symbol used in 'throw' and 'if_except' instruction to denote
22 // this is a C++ exception. This symbol has to be emitted somewhere once in
23 // the module. Check if the symbol has already been created, i.e., we have at
24 // least one 'throw' or 'if_except' instruction in the module, and emit the
25 // symbol only if so.
26 SmallString<60> NameStr;
27 Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
28 if (Asm->OutContext.lookupSymbol(NameStr)) {
29 MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception");
30 Asm->OutStreamer->EmitLabel(ExceptionSym);
31 }
32 }
1733
1834 void WasmException::markFunctionEnd() {
1935 // Get rid of any dead landing pads.
2323 public:
2424 WasmException(AsmPrinter *A) : EHStreamer(A) {}
2525
26 void endModule() override {}
26 void endModule() override;
2727 void beginFunction(const MachineFunction *MF) override {}
2828 virtual void markFunctionEnd() override;
2929 void endFunction(const MachineFunction *MF) override;
305305 case VK_WebAssembly_FUNCTION: return "FUNCTION";
306306 case VK_WebAssembly_GLOBAL: return "GLOBAL";
307307 case VK_WebAssembly_TYPEINDEX: return "TYPEINDEX";
308 case VK_WebAssembly_EVENT: return "EVENT";
308309 case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
309310 case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
310311 case VK_AMDGPU_REL32_LO: return "rel32@lo";
420421 .Case("function", VK_WebAssembly_FUNCTION)
421422 .Case("global", VK_WebAssembly_GLOBAL)
422423 .Case("typeindex", VK_WebAssembly_TYPEINDEX)
424 .Case("event", VK_WebAssembly_EVENT)
423425 .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
424426 .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
425427 .Case("rel32@lo", VK_AMDGPU_REL32_LO)
5555 uint32_t Index;
5656 };
5757
58 // The signature of a wasm function, in a struct capable of being used as a
59 // DenseMap key.
60 // TODO: Consider using WasmSignature directly instead.
61 struct WasmFunctionType {
58 // The signature of a wasm function or event, in a struct capable of being used
59 // as a DenseMap key.
60 // TODO: Consider using wasm::WasmSignature directly instead.
61 struct WasmSignature {
6262 // Support empty and tombstone instances, needed by DenseMap.
6363 enum { Plain, Empty, Tombstone } State;
6464
6868 // The parameter types of the function.
6969 SmallVector Params;
7070
71 WasmFunctionType() : State(Plain) {}
72
73 bool operator==(const WasmFunctionType &Other) const {
71 WasmSignature() : State(Plain) {}
72
73 bool operator==(const WasmSignature &Other) const {
7474 return State == Other.State && Returns == Other.Returns &&
7575 Params == Other.Params;
7676 }
7777 };
7878
79 // Traits for using WasmFunctionType in a DenseMap.
80 struct WasmFunctionTypeDenseMapInfo {
81 static WasmFunctionType getEmptyKey() {
82 WasmFunctionType FuncTy;
83 FuncTy.State = WasmFunctionType::Empty;
84 return FuncTy;
85 }
86 static WasmFunctionType getTombstoneKey() {
87 WasmFunctionType FuncTy;
88 FuncTy.State = WasmFunctionType::Tombstone;
89 return FuncTy;
90 }
91 static unsigned getHashValue(const WasmFunctionType &FuncTy) {
92 uintptr_t Value = FuncTy.State;
93 for (wasm::ValType Ret : FuncTy.Returns)
79 // Traits for using WasmSignature in a DenseMap.
80 struct WasmSignatureDenseMapInfo {
81 static WasmSignature getEmptyKey() {
82 WasmSignature Sig;
83 Sig.State = WasmSignature::Empty;
84 return Sig;
85 }
86 static WasmSignature getTombstoneKey() {
87 WasmSignature Sig;
88 Sig.State = WasmSignature::Tombstone;
89 return Sig;
90 }
91 static unsigned getHashValue(const WasmSignature &Sig) {
92 uintptr_t Value = Sig.State;
93 for (wasm::ValType Ret : Sig.Returns)
9494 Value += DenseMapInfo::getHashValue(uint32_t(Ret));
95 for (wasm::ValType Param : FuncTy.Params)
95 for (wasm::ValType Param : Sig.Params)
9696 Value += DenseMapInfo::getHashValue(uint32_t(Param));
9797 return Value;
9898 }
99 static bool isEqual(const WasmFunctionType &LHS,
100 const WasmFunctionType &RHS) {
99 static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
101100 return LHS == RHS;
102101 }
103102 };
117116
118117 // A wasm function to be written into the function section.
119118 struct WasmFunction {
120 uint32_t Type;
119 uint32_t SigIndex;
121120 const MCSymbolWasm *Sym;
122121 };
123122
215214 // Maps function symbols to the table element index space. Used
216215 // for TABLE_INDEX relocation types (i.e. address taken functions).
217216 DenseMap TableIndices;
218 // Maps function/global symbols to the function/global/section index space.
217 // Maps function/global symbols to the function/global/event/section index
218 // space.
219219 DenseMap WasmIndices;
220220 // Maps data symbols to the Wasm segment and offset/size with the segment.
221221 DenseMap DataLocations;
230230 // Map from section to defining function symbol.
231231 DenseMap SectionFunctions;
232232
233 DenseMap
234 FunctionTypeIndices;
235 SmallVector FunctionTypes;
233 DenseMap SignatureIndices;
234 SmallVector Signatures;
236235 SmallVector Globals;
237236 SmallVector DataSegments;
238237 unsigned NumFunctionImports = 0;
239238 unsigned NumGlobalImports = 0;
239 unsigned NumEventImports = 0;
240240 uint32_t SectionCount = 0;
241241
242242 // TargetObjectWriter wrappers.
265265 TableIndices.clear();
266266 DataLocations.clear();
267267 CustomSectionsRelocations.clear();
268 FunctionTypeIndices.clear();
269 FunctionTypes.clear();
268 SignatureIndices.clear();
269 Signatures.clear();
270270 Globals.clear();
271271 DataSegments.clear();
272272 SectionFunctions.clear();
293293
294294 void writeValueType(wasm::ValType Ty) { W.OS << static_cast(Ty); }
295295
296 void writeTypeSection(ArrayRefFunctionType> FunctionTypes);
296 void writeTypeSection(ArrayRefSignature> Signatures);
297297 void writeImportSection(ArrayRef Imports, uint32_t DataSize,
298298 uint32_t NumElements);
299299 void writeFunctionSection(ArrayRef Functions);
303303 void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
304304 ArrayRef Functions);
305305 void writeDataSection();
306 void writeEventSection(ArrayRef Events);
306307 void writeRelocSection(uint32_t SectionIndex, StringRef Name,
307308 std::vector &Relocations);
308309 void writeLinkingMetaDataSection(
321322
322323 uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
323324 uint32_t getFunctionType(const MCSymbolWasm &Symbol);
325 uint32_t getEventType(const MCSymbolWasm &Symbol);
324326 uint32_t registerFunctionType(const MCSymbolWasm &Symbol);
327 uint32_t registerEventType(const MCSymbolWasm &Symbol);
325328 };
326329
327330 } // end anonymous namespace
580583 return getRelocationIndexValue(RelEntry);
581584 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
582585 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
583 // Provisional value is function/global Wasm index
586 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
587 // Provisional value is function/global/event Wasm index
584588 if (!WasmIndices.count(RelEntry.Symbol))
585589 report_fatal_error("symbol not found in wasm index space: " +
586590 RelEntry.Symbol->getName());
677681 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
678682 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
679683 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
684 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
680685 WritePatchableLEB(Stream, Value, Offset);
681686 break;
682687 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
695700 }
696701 }
697702
698 void WasmObjectWriter::writeTypeSection(
699 ArrayRef FunctionTypes) {
700 if (FunctionTypes.empty())
703 void WasmObjectWriter::writeTypeSection(ArrayRef Signatures) {
704 if (Signatures.empty())
701705 return;
702706
703707 SectionBookkeeping Section;
704708 startSection(Section, wasm::WASM_SEC_TYPE);
705709
706 encodeULEB128(FunctionTypes.size(), W.OS);
707
708 for (const WasmFunctionType &FuncTy : FunctionTypes) {
710 encodeULEB128(Signatures.size(), W.OS);
711
712 for (const WasmSignature &Sig : Signatures) {
709713 W.OS << char(wasm::WASM_TYPE_FUNC);
710 encodeULEB128(FuncTy.Params.size(), W.OS);
711 for (wasm::ValType Ty : FuncTy.Params)
714 encodeULEB128(Sig.Params.size(), W.OS);
715 for (wasm::ValType Ty : Sig.Params)
712716 writeValueType(Ty);
713 encodeULEB128(FuncTy.Returns.size(), W.OS);
714 for (wasm::ValType Ty : FuncTy.Returns)
717 encodeULEB128(Sig.Returns.size(), W.OS);
718 for (wasm::ValType Ty : Sig.Returns)
715719 writeValueType(Ty);
716720 }
717721
752756 encodeULEB128(0, W.OS); // flags
753757 encodeULEB128(NumElements, W.OS); // initial
754758 break;
759 case wasm::WASM_EXTERNAL_EVENT:
760 encodeULEB128(Import.Event.Attribute, W.OS);
761 encodeULEB128(Import.Event.SigIndex, W.OS);
762 break;
755763 default:
756764 llvm_unreachable("unsupported import kind");
757765 }
769777
770778 encodeULEB128(Functions.size(), W.OS);
771779 for (const WasmFunction &Func : Functions)
772 encodeULEB128(Func.Type, W.OS);
780 encodeULEB128(Func.SigIndex, W.OS);
773781
774782 endSection(Section);
775783 }
789797 W.OS << char(wasm::WASM_OPCODE_I32_CONST);
790798 encodeSLEB128(Global.InitialValue, W.OS);
791799 W.OS << char(wasm::WASM_OPCODE_END);
800 }
801
802 endSection(Section);
803 }
804
805 void WasmObjectWriter::writeEventSection(ArrayRef Events) {
806 if (Events.empty())
807 return;
808
809 SectionBookkeeping Section;
810 startSection(Section, wasm::WASM_SEC_EVENT);
811
812 encodeULEB128(Events.size(), W.OS);
813 for (const wasm::WasmEventType &Event : Events) {
814 encodeULEB128(Event.Attribute, W.OS);
815 encodeULEB128(Event.SigIndex, W.OS);
792816 }
793817
794818 endSection(Section);
955979 switch (Sym.Kind) {
956980 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
957981 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
982 case wasm::WASM_SYMBOL_TYPE_EVENT:
958983 encodeULEB128(Sym.ElementIndex, W.OS);
959984 if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
960985 writeString(Sym.Name);
10461071 return TypeIndices[&Symbol];
10471072 }
10481073
1074 uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) {
1075 assert(Symbol.isEvent());
1076 assert(TypeIndices.count(&Symbol));
1077 return TypeIndices[&Symbol];
1078 }
1079
10491080 uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
10501081 assert(Symbol.isFunction());
10511082
1052 WasmFunctionType F;
1083 WasmSignature S;
10531084 const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
10541085 if (auto *Sig = ResolvedSym->getSignature()) {
1055 F.Returns = Sig->Returns;
1056 F.Params = Sig->Params;
1057 }
1058
1059 auto Pair =
1060 FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
1086 S.Returns = Sig->Returns;
1087 S.Params = Sig->Params;
1088 }
1089
1090 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
10611091 if (Pair.second)
1062 FunctionTypes.push_back(F);
1092 Signatures.push_back(S);
10631093 TypeIndices[&Symbol] = Pair.first->second;
10641094
10651095 LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
10661096 << " new:" << Pair.second << "\n");
1097 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1098 return Pair.first->second;
1099 }
1100
1101 uint32_t WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
1102 assert(Symbol.isEvent());
1103
1104 // TODO Currently we don't generate imported exceptions, but if we do, we
1105 // should have a way of infering types of imported exceptions.
1106 WasmSignature S;
1107 if (auto *Sig = Symbol.getSignature()) {
1108 S.Returns = Sig->Returns;
1109 S.Params = Sig->Params;
1110 }
1111
1112 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1113 if (Pair.second)
1114 Signatures.push_back(S);
1115 TypeIndices[&Symbol] = Pair.first->second;
1116
1117 LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second
1118 << "\n");
10671119 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
10681120 return Pair.first->second;
10691121 }
10991151 SmallVector TableElems;
11001152 SmallVector Imports;
11011153 SmallVector Exports;
1154 SmallVector Events;
11021155 SmallVector SymbolInfos;
11031156 SmallVector, 2> InitFuncs;
11041157 std::map> Comdats;
11271180 TableImport.Table.ElemType = wasm::WASM_TYPE_ANYFUNC;
11281181 Imports.push_back(TableImport);
11291182
1130 // Populate FunctionTypeIndices, and Imports and WasmIndices for undefined
1183 // Populate SignatureIndices, and Imports and WasmIndices for undefined
11311184 // symbols. This must be done before populating WasmIndices for defined
11321185 // symbols.
11331186 for (const MCSymbol &S : Asm.symbols()) {
11371190 // (because wasm always needs a type signature).
11381191 if (WS.isFunction())
11391192 registerFunctionType(WS);
1193
1194 if (WS.isEvent())
1195 registerEventType(WS);
11401196
11411197 if (WS.isTemporary())
11421198 continue;
11621218 Import.Global = WS.getGlobalType();
11631219 Imports.push_back(Import);
11641220 WasmIndices[&WS] = NumGlobalImports++;
1221 } else if (WS.isEvent()) {
1222 if (WS.isWeak())
1223 report_fatal_error("undefined event symbol cannot be weak");
1224
1225 wasm::WasmImport Import;
1226 Import.Module = WS.getModuleName();
1227 Import.Field = WS.getName();
1228 Import.Kind = wasm::WASM_EXTERNAL_EVENT;
1229 Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
1230 Import.Event.SigIndex = getEventType(WS);
1231 Imports.push_back(Import);
1232 WasmIndices[&WS] = NumEventImports++;
11651233 }
11661234 }
11671235 }
12531321 // A definition. Write out the function body.
12541322 Index = NumFunctionImports + Functions.size();
12551323 WasmFunction Func;
1256 Func.Type = getFunctionType(WS);
1324 Func.SigIndex = getFunctionType(WS);
12571325 Func.Sym = &WS;
12581326 WasmIndices[&WS] = Index;
12591327 Functions.push_back(Func);
12691337 }
12701338
12711339 LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
1340
12721341 } else if (WS.isData()) {
12731342 if (WS.isTemporary() && !WS.getSize())
12741343 continue;
12981367 static_cast(Size)};
12991368 DataLocations[&WS] = Ref;
13001369 LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
1370
13011371 } else if (WS.isGlobal()) {
13021372 // A "true" Wasm global (currently just __stack_pointer)
13031373 if (WS.isDefined())
13061376 // An import; the index was assigned above
13071377 LLVM_DEBUG(dbgs() << " -> global index: "
13081378 << WasmIndices.find(&WS)->second << "\n");
1379
1380 } else if (WS.isEvent()) {
1381 // C++ exception symbol (__cpp_exception)
1382 unsigned Index;
1383 if (WS.isDefined()) {
1384 Index = NumEventImports + Events.size();
1385 wasm::WasmEventType Event;
1386 Event.SigIndex = getEventType(WS);
1387 Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
1388 WasmIndices[&WS] = Index;
1389 Events.push_back(Event);
1390 } else {
1391 // An import; the index was assigned above.
1392 Index = WasmIndices.find(&WS)->second;
1393 }
1394 LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second
1395 << "\n");
1396
13091397 } else {
13101398 assert(WS.isSection());
13111399 }
13391427 DataLocations[&WS] = Ref;
13401428 LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
13411429 } else {
1342 report_fatal_error("don't yet support global aliases");
1430 report_fatal_error("don't yet support global/event aliases");
13431431 }
13441432 }
13451433
14721560 // Write out the Wasm header.
14731561 writeHeader(Asm);
14741562
1475 writeTypeSection(FunctionTypes);
1563 writeTypeSection(Signatures);
14761564 writeImportSection(Imports, DataSize, TableElems.size());
14771565 writeFunctionSection(Functions);
14781566 // Skip the "table" section; we import the table instead.
14791567 // Skip the "memory" section; we import the memory instead.
14801568 writeGlobalSection();
1569 writeEventSection(Events);
14811570 writeExportSection(Exports);
14821571 writeElemSection(TableElems);
14831572 writeCodeSection(Asm, Layout, Functions);
294294 return parseMemorySection(Ctx);
295295 case wasm::WASM_SEC_GLOBAL:
296296 return parseGlobalSection(Ctx);
297 case wasm::WASM_SEC_EVENT:
298 return parseEventSection(Ctx);
297299 case wasm::WASM_SEC_EXPORT:
298300 return parseExportSection(Ctx);
299301 case wasm::WASM_SEC_START:
438440
439441 std::vector ImportedGlobals;
440442 std::vector ImportedFunctions;
443 std::vector ImportedEvents;
441444 ImportedGlobals.reserve(Imports.size());
442445 ImportedFunctions.reserve(Imports.size());
446 ImportedEvents.reserve(Imports.size());
443447 for (auto &I : Imports) {
444448 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
445449 ImportedFunctions.emplace_back(&I);
446450 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
447451 ImportedGlobals.emplace_back(&I);
452 else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
453 ImportedEvents.emplace_back(&I);
448454 }
449455
450456 while (Count--) {
451457 wasm::WasmSymbolInfo Info;
452458 const wasm::WasmSignature *FunctionType = nullptr;
453459 const wasm::WasmGlobalType *GlobalType = nullptr;
460 const wasm::WasmEventType *EventType = nullptr;
454461
455462 Info.Kind = readUint8(Ctx);
456463 Info.Flags = readVaruint32(Ctx);
531538 break;
532539 }
533540
541 case wasm::WASM_SYMBOL_TYPE_EVENT: {
542 Info.ElementIndex = readVaruint32(Ctx);
543 if (!isValidEventIndex(Info.ElementIndex) ||
544 IsDefined != isDefinedEventIndex(Info.ElementIndex))
545 return make_error("invalid event symbol index",
546 object_error::parse_failed);
547 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
548 wasm::WASM_SYMBOL_BINDING_WEAK)
549 return make_error("undefined weak global symbol",
550 object_error::parse_failed);
551 if (IsDefined) {
552 Info.Name = readString(Ctx);
553 unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
554 wasm::WasmEvent &Event = Events[EventIndex];
555 EventType = &Event.Type;
556 if (Event.SymbolName.empty())
557 Event.SymbolName = Info.Name;
558
559 } else {
560 wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
561 EventType = &Import.Event;
562 Info.Name = Import.Field;
563 }
564 break;
565 }
566
534567 default:
535568 return make_error("Invalid symbol type",
536569 object_error::parse_failed);
544577 object_error::parse_failed);
545578 LinkingData.SymbolTable.emplace_back(Info);
546579 Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
547 GlobalType);
580 GlobalType, EventType);
548581 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
549582 }
550583
634667 return make_error("Bad relocation global index",
635668 object_error::parse_failed);
636669 break;
670 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
671 if (!isValidEventSymbol(Reloc.Index))
672 return make_error("Bad relocation event index",
673 object_error::parse_failed);
674 break;
637675 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
638676 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
639677 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
754792 return make_error("Invalid table element type",
755793 object_error::parse_failed);
756794 break;
795 case wasm::WASM_EXTERNAL_EVENT:
796 NumImportedEvents++;
797 Im.Event.Attribute = readVarint32(Ctx);
798 Im.Event.SigIndex = readVarint32(Ctx);
799 break;
757800 default:
758801 return make_error("Unexpected import kind",
759802 object_error::parse_failed);
830873 return Error::success();
831874 }
832875
876 Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
877 EventSection = Sections.size();
878 uint32_t Count = readVarint32(Ctx);
879 Events.reserve(Count);
880 while (Count--) {
881 wasm::WasmEvent Event;
882 Event.Index = NumImportedEvents + Events.size();
883 Event.Type.Attribute = readVaruint32(Ctx);
884 Event.Type.SigIndex = readVarint32(Ctx);
885 Events.push_back(Event);
886 }
887
888 if (Ctx.Ptr != Ctx.End)
889 return make_error("Event section ended prematurely",
890 object_error::parse_failed);
891 return Error::success();
892 }
893
833894 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
834895 uint32_t Count = readVaruint32(Ctx);
835896 Exports.reserve(Count);
849910 return make_error("Invalid global export",
850911 object_error::parse_failed);
851912 break;
913 case wasm::WASM_EXTERNAL_EVENT:
914 if (!isValidEventIndex(Ex.Index))
915 return make_error("Invalid event export",
916 object_error::parse_failed);
917 break;
852918 case wasm::WASM_EXTERNAL_MEMORY:
853919 case wasm::WASM_EXTERNAL_TABLE:
854920 break;
880946 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
881947 }
882948
949 bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
950 return Index < NumImportedEvents + Events.size();
951 }
952
953 bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
954 return Index >= NumImportedEvents && isValidEventIndex(Index);
955 }
956
883957 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
884958 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
885959 }
886960
887961 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
888962 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
963 }
964
965 bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
966 return Index < Symbols.size() && Symbols[Index].isTypeEvent();
889967 }
890968
891969 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
904982 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
905983 assert(isDefinedGlobalIndex(Index));
906984 return Globals[Index - NumImportedGlobals];
985 }
986
987 wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
988 assert(isDefinedEventIndex(Index));
989 return Events[Index - NumImportedEvents];
907990 }
908991
909992 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
10691152 switch (Sym.Info.Kind) {
10701153 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
10711154 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1155 case wasm::WASM_SYMBOL_TYPE_EVENT:
10721156 return Sym.Info.ElementIndex;
10731157 case wasm::WASM_SYMBOL_TYPE_DATA: {
10741158 // The value of a data symbol is the segment offset, plus the symbol
11111195 return SymbolRef::ST_Data;
11121196 case wasm::WASM_SYMBOL_TYPE_SECTION:
11131197 return SymbolRef::ST_Debug;
1198 case wasm::WASM_SYMBOL_TYPE_EVENT:
1199 return SymbolRef::ST_Other;
11141200 }
11151201
11161202 llvm_unreachable("Unknown WasmSymbol::SymbolType");
11341220 case wasm::WASM_SYMBOL_TYPE_DATA:
11351221 Ref.d.a = DataSection;
11361222 break;
1137 case wasm::WASM_SYMBOL_TYPE_SECTION: {
1223 case wasm::WASM_SYMBOL_TYPE_SECTION:
11381224 Ref.d.a = Sym.Info.ElementIndex;
11391225 break;
1140 }
1226 case wasm::WASM_SYMBOL_TYPE_EVENT:
1227 Ref.d.a = EventSection;
1228 break;
11411229 default:
11421230 llvm_unreachable("Unknown WasmSymbol::SymbolType");
11431231 }
11601248 ECase(TABLE);
11611249 ECase(MEMORY);
11621250 ECase(GLOBAL);
1251 ECase(EVENT);
11631252 ECase(EXPORT);
11641253 ECase(START);
11651254 ECase(ELEM);
9797 static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
9898 commonSectionMapping(IO, Section);
9999 IO.mapOptional("Globals", Section.Globals);
100 }
101
102 static void sectionMapping(IO &IO, WasmYAML::EventSection &Section) {
103 commonSectionMapping(IO, Section);
104 IO.mapOptional("Events", Section.Events);
100105 }
101106
102107 static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
186191 Section.reset(new WasmYAML::GlobalSection());
187192 sectionMapping(IO, *cast(Section.get()));
188193 break;
194 case wasm::WASM_SEC_EVENT:
195 if (!IO.outputting())
196 Section.reset(new WasmYAML::EventSection());
197 sectionMapping(IO, *cast(Section.get()));
198 break;
189199 case wasm::WASM_SEC_EXPORT:
190200 if (!IO.outputting())
191201 Section.reset(new WasmYAML::ExportSection());
226236 ECase(TABLE);
227237 ECase(MEMORY);
228238 ECase(GLOBAL);
239 ECase(EVENT);
229240 ECase(EXPORT);
230241 ECase(START);
231242 ECase(ELEM);
306317 } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
307318 IO.mapRequired("GlobalType", Import.GlobalImport.Type);
308319 IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
320 } else if (Import.Kind == wasm::WASM_EXTERNAL_EVENT) {
321 IO.mapRequired("EventAttribute", Import.EventImport.Attribute);
322 IO.mapRequired("EventSigIndex", Import.EventImport.SigIndex);
309323 } else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
310324 IO.mapRequired("Table", Import.TableImport);
311325 } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY) {
398412 IO.mapRequired("Function", Info.ElementIndex);
399413 } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL) {
400414 IO.mapRequired("Global", Info.ElementIndex);
415 } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT) {
416 IO.mapRequired("Event", Info.ElementIndex);
401417 } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) {
402418 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
403419 IO.mapRequired("Segment", Info.DataRef.Segment);
411427 }
412428 }
413429
430 void MappingTraits::mapping(IO &IO, WasmYAML::Event &Event) {
431 IO.mapRequired("Index", Event.Index);
432 IO.mapRequired("Attribute", Event.Attribute);
433 IO.mapRequired("SigIndex", Event.SigIndex);
434 }
435
414436 void ScalarBitSetTraits::bitset(
415437 IO &IO, WasmYAML::LimitFlags &Value) {
416438 #define BCase(X) IO.bitSetCase(Value, #X, wasm::WASM_LIMITS_FLAG_##X)
442464 ECase(DATA);
443465 ECase(GLOBAL);
444466 ECase(SECTION);
467 ECase(EVENT);
445468 #undef ECase
446469 }
447470
466489 ECase(TABLE);
467490 ECase(MEMORY);
468491 ECase(GLOBAL);
492 ECase(EVENT);
469493 #undef ECase
470494 }
471495
8585 const MCOperand &MO = MI.getOperand(i);
8686 if (MO.isReg()) {
8787 /* nothing to encode */
88
8889 } else if (MO.isImm()) {
8990 if (i < Desc.getNumOperands()) {
9091 assert(Desc.TSFlags == 0 &&
127128 WebAssemblyII::VariableOpImmediateIsLabel));
128129 encodeULEB128(uint64_t(MO.getImm()), OS);
129130 }
131
130132 } else if (MO.isFPImm()) {
131133 assert(i < Desc.getNumOperands() &&
132134 "Unexpected floating-point immediate as a non-fixed operand");
143145 double d = MO.getFPImm();
144146 support::endian::write(OS, d, support::little);
145147 }
148
146149 } else if (MO.isExpr()) {
147150 const MCOperandInfo &Info = Desc.OpInfo[i];
148151 llvm::MCFixupKind FixupKind;
149152 size_t PaddedSize = 5;
150 if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
153 switch (Info.OperandType) {
154 case WebAssembly::OPERAND_I32IMM:
151155 FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
152 } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
156 break;
157 case WebAssembly::OPERAND_I64IMM:
153158 FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
154159 PaddedSize = 10;
155 } else if (Info.OperandType == WebAssembly::OPERAND_FUNCTION32 ||
156 Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
157 Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
160 break;
161 case WebAssembly::OPERAND_FUNCTION32:
162 case WebAssembly::OPERAND_OFFSET32:
163 case WebAssembly::OPERAND_TYPEINDEX:
164 case WebAssembly::OPERAND_GLOBAL:
165 case WebAssembly::OPERAND_EVENT:
158166 FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
159 } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
160 FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
161 } else {
167 break;
168 default:
162169 llvm_unreachable("unexpected symbolic operand kind");
163170 }
164171 Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
7676 OPERAND_SIGNATURE,
7777 /// type signature immediate for call_indirect.
7878 OPERAND_TYPEINDEX,
79 /// Event index.
80 OPERAND_EVENT,
7981 };
8082 } // end namespace WebAssembly
8183
9698 // Flags to indicate the type of the symbol being referenced
9799 MO_SYMBOL_FUNCTION = 0x1,
98100 MO_SYMBOL_GLOBAL = 0x2,
99 MO_SYMBOL_MASK = 0x3,
101 MO_SYMBOL_EVENT = 0x4,
102 MO_SYMBOL_MASK = 0x7,
100103 };
101104 } // end namespace WebAssemblyII
102105
9999 }
100100
101101 void WebAssemblyTargetAsmStreamer::emitGlobalType(MCSymbolWasm *Sym) {
102 assert(Sym->isGlobal());
102103 OS << "\t.globaltype\t" << Sym->getName() << ", " <<
103104 WebAssembly::TypeToString(
104105 static_cast(Sym->getGlobalType().Type)) <<
105106 '\n';
107 }
108
109 void WebAssemblyTargetAsmStreamer::emitEventType(MCSymbolWasm *Sym) {
110 assert(Sym->isEvent());
111 OS << "\t.eventtype\t" << Sym->getName();
112 if (Sym->getSignature()->Returns.empty())
113 OS << ", void";
114 else {
115 assert(Sym->getSignature()->Returns.size() == 1);
116 OS << ", "
117 << WebAssembly::TypeToString(Sym->getSignature()->Returns.front());
118 }
119 for (auto Ty : Sym->getSignature()->Params)
120 OS << ", " << WebAssembly::TypeToString(Ty);
121 OS << '\n';
106122 }
107123
108124 void WebAssemblyTargetAsmStreamer::emitImportModule(MCSymbolWasm *Sym,
158174 // Not needed.
159175 }
160176
177 void WebAssemblyTargetWasmStreamer::emitEventType(MCSymbolWasm *Sym) {
178 // Not needed.
179 }
161180 void WebAssemblyTargetWasmStreamer::emitImportModule(MCSymbolWasm *Sym,
162181 StringRef ModuleName) {
163182 Sym->setModuleName(ModuleName);
4444 virtual void emitIndIdx(const MCExpr *Value) = 0;
4545 /// .globaltype
4646 virtual void emitGlobalType(MCSymbolWasm *Sym) = 0;
47 /// .eventtype
48 virtual void emitEventType(MCSymbolWasm *Sym) = 0;
4749 /// .import_module
4850 virtual void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) = 0;
4951
6567 void emitIndirectFunctionType(MCSymbolWasm *Symbol) override;
6668 void emitIndIdx(const MCExpr *Value) override;
6769 void emitGlobalType(MCSymbolWasm *Sym) override;
70 void emitEventType(MCSymbolWasm *Sym) override;
6871 void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override;
6972 };
7073
8083 void emitIndirectFunctionType(MCSymbolWasm *Symbol) override;
8184 void emitIndIdx(const MCExpr *Value) override;
8285 void emitGlobalType(MCSymbolWasm *Sym) override;
86 void emitEventType(MCSymbolWasm *Sym) override;
8387 void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override;
8488 };
8589
8585 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
8686 }
8787
88 static bool IsEventType(const MCValue &Target) {
89 const MCSymbolRefExpr *RefA = Target.getSymA();
90 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_EVENT;
91 }
92
8893 unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
8994 const MCFixup &Fixup) const {
9095 // WebAssembly functions are not allocated in the data address space. To
105110 return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB;
106111 if (IsFunction)
107112 return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB;
113 if (IsEventType(Target))
114 return wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB;
108115 return wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB;
109116 case FK_Data_4:
110117 if (IsFunction)
7878
7979 void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
8080 for (auto &It : OutContext.getSymbols()) {
81 // Emit a .globaltype declaration.
81 // Emit a .globaltype and .eventtype declaration.
8282 auto Sym = cast(It.getValue());
83 if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) {
83 if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL)
8484 getTargetStreamer()->emitGlobalType(Sym);
85 }
85 else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT)
86 getTargetStreamer()->emitEventType(Sym);
8687 }
8788
8889 for (const auto &F : M) {
2424 HANDLE_NODETYPE(VEC_SHL)
2525 HANDLE_NODETYPE(VEC_SHR_S)
2626 HANDLE_NODETYPE(VEC_SHR_U)
27 HANDLE_NODETYPE(THROW)
2728
2829 // add memory opcodes starting at ISD::FIRST_TARGET_MEMORY_OPCODE here...
2323 #include "llvm/CodeGen/MachineModuleInfo.h"
2424 #include "llvm/CodeGen/MachineRegisterInfo.h"
2525 #include "llvm/CodeGen/SelectionDAG.h"
26 #include "llvm/CodeGen/WasmEHFuncInfo.h"
2627 #include "llvm/IR/DiagnosticInfo.h"
2728 #include "llvm/IR/DiagnosticPrinter.h"
2829 #include "llvm/IR/Function.h"
233234
234235 // Exception handling intrinsics
235236 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
237 setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
236238
237239 setMaxAtomicSizeInBitsSupported(64);
238240 }
881883 case ISD::EXTRACT_VECTOR_ELT:
882884 case ISD::INSERT_VECTOR_ELT:
883885 return LowerAccessVectorElement(Op, DAG);
886 case ISD::INTRINSIC_VOID:
887 return LowerINTRINSIC_VOID(Op, DAG);
884888 case ISD::VECTOR_SHUFFLE:
885889 return LowerVECTOR_SHUFFLE(Op, DAG);
886890 case ISD::SHL:
10451049 }
10461050
10471051 SDValue
1052 WebAssemblyTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
1053 SelectionDAG &DAG) const {
1054 MachineFunction &MF = DAG.getMachineFunction();
1055 unsigned IntNo = cast(Op.getOperand(1))->getZExtValue();
1056 SDLoc DL(Op);
1057
1058 switch (IntNo) {
1059 default:
1060 return {}; // Don't custom lower most intrinsics.
1061
1062 case Intrinsic::wasm_throw: {
1063 int Tag = cast(Op.getOperand(2).getNode())->getZExtValue();
1064 switch (Tag) {
1065 case CPP_EXCEPTION: {
1066 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1067 MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1068 const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1069 SDValue SymNode =
1070 DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1071 DAG.getTargetExternalSymbol(
1072 SymName, PtrVT, WebAssemblyII::MO_SYMBOL_EVENT));
1073 return DAG.getNode(WebAssemblyISD::THROW, DL,
1074 MVT::Other, // outchain type
1075 {
1076 Op.getOperand(0), // inchain
1077 SymNode, // exception symbol
1078 Op.getOperand(3) // thrown value
1079 });
1080 }
1081 default:
1082 llvm_unreachable("Invalid tag!");
1083 }
1084 break;
1085 }
1086 }
1087 }
1088
1089 SDValue
10481090 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
10491091 SelectionDAG &DAG) const {
10501092 SDLoc DL(Op);
9797 SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
9898 SDValue LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const;
9999 SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
100 SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
100101 SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
101102 SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const;
102103 SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
145145
146146 // Throwing an exception: throw / rethrow
147147 let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
148 defm THROW_I32 : I<(outs), (ins i32imm:$tag, I32:$val),
149 (outs), (ins i32imm:$tag),
150 [(int_wasm_throw imm:$tag, I32:$val)],
148 defm THROW_I32 : I<(outs), (ins event_op:$tag, I32:$val),
149 (outs), (ins event_op:$tag),
150 [(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag),
151 I32:$val)],
151152 "throw \t$tag, $val", "throw \t$tag",
152153 0x08>;
153 defm THROW_I64 : I<(outs), (ins i32imm:$tag, I64:$val),
154 (outs), (ins i32imm:$tag),
155 [(int_wasm_throw imm:$tag, I64:$val)],
154 defm THROW_I64 : I<(outs), (ins event_op:$tag, I64:$val),
155 (outs), (ins event_op:$tag),
156 [(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag),
157 I64:$val)],
156158 "throw \t$tag, $val", "throw \t$tag",
157159 0x08>;
158160 defm RETHROW : NRI<(outs), (ins bb_op:$dst), [], "rethrow \t$dst", 0x09>;
6363 def SDT_WebAssemblyReturn : SDTypeProfile<0, -1, []>;
6464 def SDT_WebAssemblyWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
6565 SDTCisPtrTy<0>]>;
66 def SDT_WebAssemblyThrow : SDTypeProfile<0, 2, [SDTCisPtrTy<0>]>;
6667
6768 //===----------------------------------------------------------------------===//
6869 // WebAssembly-specific DAG Nodes.
8990 SDT_WebAssemblyReturn, [SDNPHasChain]>;
9091 def WebAssemblywrapper : SDNode<"WebAssemblyISD::Wrapper",
9192 SDT_WebAssemblyWrapper>;
93 def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
94 [SDNPHasChain]>;
9295
9396 //===----------------------------------------------------------------------===//
9497 // WebAssembly-specific Operands.
139142 def P2Align : Operand {
140143 let PrintMethod = "printWebAssemblyP2AlignOperand";
141144 }
145
146 let OperandType = "OPERAND_EVENT" in
147 def event_op : Operand;
148
142149 } // OperandType = "OPERAND_P2ALIGN"
143150
144151 let OperandType = "OPERAND_SIGNATURE" in {
7474 cast(Printer.GetExternalSymbolSymbol(Name));
7575 const WebAssemblySubtarget &Subtarget = Printer.getSubtarget();
7676
77 // __stack_pointer is a global variable; all other external symbols used by
78 // CodeGen are functions. It's OK to hardcode knowledge of specific symbols
79 // here; this method is precisely there for fetching the signatures of known
80 // Clang-provided symbols.
77 // Except for the two exceptions (__stack_pointer and __cpp_exception), all
78 // other external symbols used by CodeGen are functions. It's OK to hardcode
79 // knowledge of specific symbols here; this method is precisely there for
80 // fetching the signatures of known Clang-provided symbols.
8181 if (strcmp(Name, "__stack_pointer") == 0) {
8282 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
8383 WasmSym->setGlobalType(wasm::WasmGlobalType{
8989
9090 SmallVector Returns;
9191 SmallVector Params;
92 GetLibcallSignature(Subtarget, Name, Returns, Params);
92 if (strcmp(Name, "__cpp_exception") == 0) {
93 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_EVENT);
94 // We can't confirm its signature index for now because there can be
95 // imported exceptions. Set it to be 0 for now.
96 WasmSym->setEventType(
97 {wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION, /* SigIndex */ 0});
98 // We may have multiple C++ compilation units to be linked together, each of
99 // which defines the exception symbol. To resolve them, we declare them as
100 // weak.
101 WasmSym->setWeak(true);
102 WasmSym->setExternal(true);
103
104 // All C++ exceptions are assumed to have a single i32 (for wasm32) or i64
105 // (for wasm64) param type and void return type. The reaon is, all C++
106 // exception values are pointers, and to share the type section with
107 // functions, exceptions are assumed to have void return type.
108 Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64
109 : wasm::ValType::I32);
110 } else { // Function symbols
111 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
112 GetLibcallSignature(Subtarget, Name, Returns, Params);
113 }
93114 auto Signature =
94115 make_unique(std::move(Returns), std::move(Params));
95116 WasmSym->setSignature(Signature.get());
96117 Printer.addSignature(std::move(Signature));
97 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
98118
99119 return WasmSym;
100120 }
101121
102122 MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
103123 int64_t Offset,
104 bool IsFunc,
105 bool IsGlob) const {
124 bool IsFunc, bool IsGlob,
125 bool IsEvent) const {
106126 MCSymbolRefExpr::VariantKind VK =
107127 IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION
108128 : IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
109 : MCSymbolRefExpr::VK_None;
129 : IsEvent ? MCSymbolRefExpr::VK_WebAssembly_EVENT
130 : MCSymbolRefExpr::VK_None;
110131
111132 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
112133
115136 report_fatal_error("Function addresses with offsets not supported");
116137 if (IsGlob)
117138 report_fatal_error("Global indexes with offsets not supported");
139 if (IsEvent)
140 report_fatal_error("Event indexes with offsets not supported");
118141 Expr =
119142 MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
120143 }
217240 "WebAssembly does not use target flags on GlobalAddresses");
218241 MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
219242 MO.getGlobal()->getValueType()->isFunctionTy(),
220 false);
243 false, false);
221244 break;
222245 case MachineOperand::MO_ExternalSymbol:
223246 // The target flag indicates whether this is a symbol for a
227250 MCOp = LowerSymbolOperand(
228251 GetExternalSymbolSymbol(MO), /*Offset=*/0,
229252 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_FUNCTION) != 0,
230 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0);
253 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0,
254 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_EVENT) != 0);
231255 break;
232256 case MachineOperand::MO_MCSymbol:
233257 // This is currently used only for LSDA symbols (GCC_except_table),
234258 // because global addresses or other external symbols are handled above.
235259 assert(MO.getTargetFlags() == 0 &&
236260 "WebAssembly does not use target flags on MCSymbol");
237 MCOp = LowerSymbolOperand(MO.getMCSymbol(), /*Offset=*/0, false, false);
261 MCOp = LowerSymbolOperand(MO.getMCSymbol(), /*Offset=*/0, false, false,
262 false);
238263 break;
239264 }
240265
3333 MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
3434 MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
3535 MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
36 bool IsGlob) const;
36 bool IsGlob, bool IsEvent) const;
3737
3838 public:
3939 WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)
1212
1313 ; CHECK-LABEL: test_throw:
1414 ; CHECK-NEXT: i32.const $push0=, 0
15 ; CHECK-NEXT: throw 0, $pop0
15 ; CHECK-NEXT: throw __cpp_exception@EVENT, $pop0
1616 define void @test_throw() {
1717 call void @llvm.wasm.throw(i32 0, i8* null)
1818 ret void
258258 declare void @__clang_call_terminate(i8*)
259259 declare void @_ZSt9terminatev()
260260 declare %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* returned)
261
262 ; CHECK: __cpp_exception:
263 ; CHECK: .eventtype __cpp_exception, void, i32
0 ; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o - | obj2yaml | FileCheck %s
1 ; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o - | llvm-readobj -s | FileCheck -check-prefix=SEC %s
2
3 target triple = "wasm32-unknown-unknown"
4
5 declare void @llvm.wasm.throw(i32, i8*)
6
7 define i32 @test_throw0(i8* %p) {
8 call void @llvm.wasm.throw(i32 0, i8* %p)
9 ret i32 0
10 }
11
12 define i32 @test_throw1(i8* %p) {
13 call void @llvm.wasm.throw(i32 0, i8* %p)
14 ret i32 1
15 }
16
17 ; CHECK: Sections:
18 ; CHECK-NEXT: - Type: TYPE
19 ; CHECK-NEXT: Signatures:
20 ; CHECK-NEXT: - Index: 0
21 ; CHECK-NEXT: ReturnType: I32
22 ; CHECK-NEXT: ParamTypes:
23 ; CHECK-NEXT: - I32
24 ; CHECK-NEXT: - Index: 1
25 ; CHECK-NEXT: ReturnType: NORESULT
26 ; CHECK-NEXT: ParamTypes:
27 ; CHECK-NEXT: - I32
28
29 ; CHECK: - Type: EVENT
30 ; CHECK-NEXT: Events:
31 ; CHECK-NEXT: - Index: 0
32 ; CHECK-NEXT: Attribute: 0
33 ; CHECK-NEXT: SigIndex: 1
34
35 ; CHECK-NEXT: - Type: CODE
36 ; CHECK-NEXT: Relocations:
37 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_EVENT_INDEX_LEB
38 ; CHECK-NEXT: Index: 1
39 ; CHECK-NEXT: Offset: 0x00000006
40 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_EVENT_INDEX_LEB
41 ; CHECK-NEXT: Index: 1
42 ; CHECK-NEXT: Offset: 0x00000013
43
44 ; CHECK: - Type: CUSTOM
45 ; CHECK-NEXT: Name: linking
46 ; CHECK-NEXT: Version: 1
47 ; CHECK-NEXT: SymbolTable:
48
49 ; CHECK: - Index: 1
50 ; CHECK-NEXT: Kind: EVENT
51 ; CHECK-NEXT: Name: __cpp_exception
52 ; CHECK-NEXT: Flags: [ BINDING_WEAK ]
53 ; CHECK-NEXT: Event: 0
54
55 ; SEC: Type: EVENT (0xC)
56 ; SEC-NEXT: Size: 3
57 ; SEC-NEXT: Offset: 97
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1
2 --- !WASM
3 FileHeader:
4 Version: 0x00000001
5 Sections:
6 - Type: TYPE
7 Signatures:
8 - Index: 0
9 ReturnType: I32
10 ParamTypes:
11 - I32
12 - Index: 1
13 ReturnType: NORESULT
14 ParamTypes:
15 - I32
16 - Type: FUNCTION
17 FunctionTypes: [ 0 ]
18 - Type: EVENT
19 Events:
20 - Index: 0
21 Attribute: 0
22 SigIndex: 1
23 - Type: CODE
24 Relocations:
25 - Type: R_WEBASSEMBLY_EVENT_INDEX_LEB
26 Index: 1
27 Offset: 0x00000006
28 Functions:
29 - Index: 0
30 Locals:
31 Body: 200008808080800041000B
32 - Type: CUSTOM
33 Name: linking
34 Version: 1
35 SymbolTable:
36 - Index: 0
37 Kind: FUNCTION
38 Name: test_throw0
39 Flags: [ ]
40 Function: 0
41 - Index: 1
42 Kind: EVENT
43 Name: __cpp_exception
44 Flags: [ BINDING_WEAK ]
45 Event: 0
46 ...
47
48 # CHECK: --- !WASM
49 # CHECK-NEXT: FileHeader:
50 # CHECK-NEXT: Version: 0x00000001
51 # CHECK-NEXT: Sections:
52 # CHECK-NEXT: - Type: TYPE
53 # CHECK-NEXT: Signatures:
54 # CHECK-NEXT: - Index: 0
55 # CHECK-NEXT: ReturnType: I32
56 # CHECK-NEXT: ParamTypes:
57 # CHECK-NEXT: - I32
58 # CHECK-NEXT: - Index: 1
59 # CHECK-NEXT: ReturnType: NORESULT
60 # CHECK-NEXT: ParamTypes:
61 # CHECK-NEXT: - I32
62 # CHECK-NEXT: - Type: FUNCTION
63 # CHECK-NEXT: FunctionTypes: [ 0 ]
64 # CHECK-NEXT: - Type: EVENT
65 # CHECK-NEXT: Events:
66 # CHECK-NEXT: - Index: 0
67 # CHECK-NEXT: Attribute: 0
68 # CHECK-NEXT: SigIndex: 1
69 # CHECK-NEXT: - Type: CODE
70 # CHECK-NEXT: Relocations:
71 # CHECK-NEXT: - Type: R_WEBASSEMBLY_EVENT_INDEX_LEB
72 # CHECK-NEXT: Index: 1
73 # CHECK-NEXT: Offset: 0x00000006
74 # CHECK-NEXT: Functions:
75 # CHECK-NEXT: - Index: 0
76 # CHECK-NEXT: Locals:
77 # CHECK-NEXT: Body: 200008808080800041000B
78 # CHECK-NEXT: - Type: CUSTOM
79 # CHECK-NEXT: Name: linking
80 # CHECK-NEXT: Version: 1
81 # CHECK-NEXT: SymbolTable:
82 # CHECK-NEXT: - Index: 0
83 # CHECK-NEXT: Kind: FUNCTION
84 # CHECK-NEXT: Name: test_throw0
85 # CHECK-NEXT: Flags: [ ]
86 # CHECK-NEXT: Function: 0
87 # CHECK-NEXT: - Index: 1
88 # CHECK-NEXT: Kind: EVENT
89 # CHECK-NEXT: Name: __cpp_exception
90 # CHECK-NEXT: Flags: [ BINDING_WEAK ]
91 # CHECK-NEXT: Event: 0
2424 static const EnumEntry WasmSymbolTypes[] = {
2525 #define ENUM_ENTRY(X) \
2626 { #X, wasm::WASM_SYMBOL_TYPE_##X }
27 ENUM_ENTRY(FUNCTION),
28 ENUM_ENTRY(DATA),
29 ENUM_ENTRY(GLOBAL),
30 ENUM_ENTRY(SECTION),
27 ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA), ENUM_ENTRY(GLOBAL),
28 ENUM_ENTRY(SECTION), ENUM_ENTRY(EVENT),
3129 #undef ENUM_ENTRY
3230 };
3331
3432 static const EnumEntry WasmSectionTypes[] = {
3533 #define ENUM_ENTRY(X) \
3634 { #X, wasm::WASM_SEC_##X }
37 ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
38 ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
39 ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EXPORT), ENUM_ENTRY(START),
40 ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE), ENUM_ENTRY(DATA),
35 ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
36 ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
37 ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EVENT), ENUM_ENTRY(EXPORT),
38 ENUM_ENTRY(START), ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE),
39 ENUM_ENTRY(DATA),
4140 #undef ENUM_ENTRY
4241 };
4342
106106 break;
107107 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
108108 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
109 case wasm::WASM_SYMBOL_TYPE_EVENT:
109110 Info.ElementIndex = Symbol.ElementIndex;
110111 break;
111112 case wasm::WASM_SYMBOL_TYPE_SECTION:
181182 Im.GlobalImport.Type = Import.Global.Type;
182183 Im.GlobalImport.Mutable = Import.Global.Mutable;
183184 break;
185 case wasm::WASM_EXTERNAL_EVENT:
186 Im.EventImport.Attribute = Import.Event.Attribute;
187 Im.EventImport.SigIndex = Import.Event.SigIndex;
188 break;
184189 case wasm::WASM_EXTERNAL_TABLE:
185190 Im.TableImport = make_table(Import.Table);
186191 break;
228233 GlobalSec->Globals.push_back(G);
229234 }
230235 S = std::move(GlobalSec);
236 break;
237 }
238 case wasm::WASM_SEC_EVENT: {
239 auto EventSec = make_unique();
240 for (auto &Event : Obj.events()) {
241 WasmYAML::Event E;
242 E.Index = Event.Index;
243 E.Attribute = Event.Type.Attribute;
244 E.SigIndex = Event.Type.SigIndex;
245 EventSec->Events.push_back(E);
246 }
247 S = std::move(EventSec);
231248 break;
232249 }
233250 case wasm::WASM_SEC_START: {
3636 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
3737 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
3838 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
3940 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
4041 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
4142 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
4849 WasmYAML::Object &Obj;
4950 uint32_t NumImportedFunctions = 0;
5051 uint32_t NumImportedGlobals = 0;
52 uint32_t NumImportedEvents = 0;
5153 };
5254
5355 static int writeUint64(raw_ostream &OS, uint64_t Value) {
151153 switch (Info.Kind) {
152154 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
153155 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
156 case wasm::WASM_SYMBOL_TYPE_EVENT:
154157 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
155158 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
156159 writeStringRef(Info.Name, SubSection.GetStream());
291294 writeUint8(OS, Import.GlobalImport.Mutable);
292295 NumImportedGlobals++;
293296 break;
297 case wasm::WASM_EXTERNAL_EVENT:
298 writeUint32(OS, Import.EventImport.Attribute);
299 writeUint32(OS, Import.EventImport.SigIndex);
300 NumImportedGlobals++;
301 break;
294302 case wasm::WASM_EXTERNAL_MEMORY:
295303 writeLimits(Import.Memory, OS);
296304 break;
364372 writeUint8(OS, Global.Type);
365373 writeUint8(OS, Global.Mutable);
366374 writeInitExpr(Global.InitExpr, OS);
375 }
376 return 0;
377 }
378
379 int WasmWriter::writeSectionContent(raw_ostream &OS,
380 WasmYAML::EventSection &Section) {
381 encodeULEB128(Section.Events.size(), OS);
382 uint32_t ExpectedIndex = NumImportedEvents;
383 for (auto &Event : Section.Events) {
384 if (Event.Index != ExpectedIndex) {
385 errs() << "Unexpected event index: " << Event.Index << "\n";
386 return 1;
387 }
388 ++ExpectedIndex;
389 encodeULEB128(Event.Attribute, OS);
390 encodeULEB128(Event.SigIndex, OS);
367391 }
368392 return 0;
369393 }
473497 writeUint32(OS, Obj.Header.Version);
474498
475499 // Write each section
476 uint32_t LastType = 0;
477500 for (const std::unique_ptr &Sec : Obj.Sections) {
478 uint32_t Type = Sec->Type;
479 if (Type != wasm::WASM_SEC_CUSTOM) {
480 if (Type < LastType) {
481 errs() << "Out of order section type: " << Type << "\n";
482 return 1;
483 }
484 LastType = Type;
485 }
486
487501 encodeULEB128(Sec->Type, OS);
488502 std::string OutString;
489503 raw_string_ostream StringStream(OutString);
506520 if (auto Err = writeSectionContent(StringStream, *S))
507521 return Err;
508522 } else if (auto S = dyn_cast(Sec.get())) {
523 if (auto Err = writeSectionContent(StringStream, *S))
524 return Err;
525 } else if (auto S = dyn_cast(Sec.get())) {
509526 if (auto Err = writeSectionContent(StringStream, *S))
510527 return Err;
511528 } else if (auto S = dyn_cast(Sec.get())) {