Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -74,6 +74,7 @@ uint32_t Index; WasmGlobalType Type; WasmInitExpr InitExpr; + StringRef Comdat; // from the "comdat info" section }; struct WasmImport { @@ -224,6 +225,7 @@ enum : unsigned { WASM_COMDAT_DATA = 0x0, WASM_COMDAT_FUNCTION = 0x1, + WASM_COMDAT_GLOBAL = 0x2, }; // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -1209,7 +1209,22 @@ // A "true" Wasm global (currently just __stack_pointer) unsigned WasmIndex; if (WS.isDefined()) { - report_fatal_error("don't yet support defined globals"); + // A definition. Write out the Global definition. + WasmIndex = NumGlobalImports + Globals.size(); + WasmGlobal G; + G.Type = WS.getGlobalType(); + // TODO G.InitialValue should come from somewhere, maybe the MCSymbol. + // This code is waiting to be used though; I expect thread-local-storage + // will want to declare Wasm globals. + G.InitialValue = 0; + WasmIndices[&WS] = WasmIndex; + Globals.push_back(G); + + auto &Section = static_cast(WS.getSection()); + if (const MCSymbolWasm *C = Section.getGroup()) { + Comdats[C->getName()].emplace_back( + WasmComdatEntry{wasm::WASM_COMDAT_GLOBAL, WasmIndex}); + } } else { // An import; the index was assigned above WasmIndex = WasmIndices.find(&WS)->second; Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -535,6 +535,15 @@ object_error::parse_failed); getDefinedFunction(Index).Comdat = Name; break; + case wasm::WASM_COMDAT_GLOBAL: + if (!isDefinedGlobalIndex(Index)) + return make_error("COMDAT global index out of range", + object_error::parse_failed); + if (!getDefinedGlobal(Index).Comdat.empty()) + return make_error("Global in two COMDATs", + object_error::parse_failed); + getDefinedGlobal(Index).Comdat = Name; + break; } } } Index: lib/ObjectYAML/WasmYAML.cpp =================================================================== --- lib/ObjectYAML/WasmYAML.cpp +++ lib/ObjectYAML/WasmYAML.cpp @@ -374,6 +374,7 @@ #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_COMDAT_##X); ECase(FUNCTION); ECase(DATA); + ECase(GLOBAL); #undef ECase } Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -74,6 +74,13 @@ WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index}); } } + for (auto &G : Obj.globals()) { + if (!G.Comdat.empty()) { + auto &Comdat = LinkingSec->Comdats[ComdatIndexes[G.Comdat]]; + Comdat.Entries.emplace_back( + WasmYAML::ComdatEntry{wasm::WASM_COMDAT_GLOBAL, G.Index}); + } + } uint32_t SegmentIndex = 0; for (const object::WasmSegment &Segment : Obj.dataSegments()) { if (!Segment.Data.Name.empty()) {