diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll --- a/lld/test/wasm/call-indirect.ll +++ b/lld/test/wasm/call-indirect.ll @@ -154,7 +154,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 diff --git a/lld/test/wasm/comdats.ll b/lld/test/wasm/comdats.ll --- a/lld/test/wasm/comdats.ll +++ b/lld/test/wasm/comdats.ll @@ -92,7 +92,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll --- a/lld/test/wasm/data-layout.ll +++ b/lld/test/wasm/data-layout.ll @@ -37,20 +37,20 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: Content: '0100000000000000000000000000000003000000000000002804000024040000' ; CHECK-NEXT: - SectionOffset: 45 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1056 ; CHECK-NEXT: Content: '0000000000000000' ; CHECK-NEXT: - SectionOffset: 59 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1064 ; CHECK-NEXT: Content: 68656C6C6F0A00 @@ -93,37 +93,37 @@ ; RELOC-NEXT: Addend: 4 ; RELOC-NEXT: Segments: ; RELOC-NEXT: - SectionOffset: 6 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 0 ; RELOC-NEXT: Content: '01000000' ; RELOC-NEXT: - SectionOffset: 15 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 16 ; RELOC-NEXT: Content: '03000000' ; RELOC-NEXT: - SectionOffset: 24 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 24 ; RELOC-NEXT: Content: '28000000' ; RELOC-NEXT: - SectionOffset: 33 -; RELOC-NEXT: MemoryIndex: 0 -; RELOC-NEXT: Offset: +; RELOC-NEXT: Flags: 0 +; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 28 ; RELOC-NEXT: Content: '0000000000000000' ; RELOC-NEXT: - SectionOffset: 46 -; RELOC-NEXT: MemoryIndex: 0 -; RELOC-NEXT: Offset: +; RELOC-NEXT: Flags: 0 +; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 36 ; RELOC-NEXT: Content: '20000000' ; RELOC-NEXT: - SectionOffset: 55 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 40 diff --git a/lld/test/wasm/gc-sections.ll b/lld/test/wasm/gc-sections.ll --- a/lld/test/wasm/gc-sections.ll +++ b/lld/test/wasm/gc-sections.ll @@ -66,8 +66,8 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: Content: '02000000' @@ -129,8 +129,8 @@ ; NO-GC: - Type: DATA ; NO-GC-NEXT: Segments: ; NO-GC-NEXT: - SectionOffset: 7 -; NO-GC-NEXT: MemoryIndex: 0 -; NO-GC-NEXT: Offset: +; NO-GC-NEXT: Flags: 0 +; NO-GC-NEXT: Offset: ; NO-GC-NEXT: Opcode: I32_CONST ; NO-GC-NEXT: Value: 1024 ; NO-GC-NEXT: Content: '010000000000000002000000' diff --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll --- a/lld/test/wasm/local-symbols.ll +++ b/lld/test/wasm/local-symbols.ll @@ -101,7 +101,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test --- a/lld/test/wasm/locals-duplicate.test +++ b/lld/test/wasm/locals-duplicate.test @@ -187,7 +187,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 @@ -363,19 +363,19 @@ ; RELOC-NEXT: - Type: DATA ; RELOC-NEXT: Segments: ; RELOC-NEXT: - SectionOffset: 6 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 0 ; RELOC-NEXT: Content: '0000000000000000' ; RELOC-NEXT: - SectionOffset: 19 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 8 ; RELOC-NEXT: Content: '0000000000000000' ; RELOC-NEXT: - SectionOffset: 32 -; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Flags: 0 ; RELOC-NEXT: Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 16 diff --git a/lld/test/wasm/many-functions.ll b/lld/test/wasm/many-functions.ll --- a/lld/test/wasm/many-functions.ll +++ b/lld/test/wasm/many-functions.ll @@ -802,13 +802,13 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '01000000' ; CHECK-NEXT: - SectionOffset: 15 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 4 diff --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll --- a/lld/test/wasm/relocatable.ll +++ b/lld/test/wasm/relocatable.ll @@ -120,37 +120,37 @@ ; CHECK-NEXT: Offset: 0x0000002D ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: 68656C6C6F0A00 ; CHECK-NEXT: - SectionOffset: 18 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000' ; CHECK-NEXT: - SectionOffset: 27 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 12 ; CHECK-NEXT: Content: '02000000' ; CHECK-NEXT: - SectionOffset: 36 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 ; CHECK-NEXT: Content: '03000000' ; CHECK-NEXT: - SectionOffset: 45 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 24 ; CHECK-NEXT: Content: '00000000' ; CHECK-NEXT: - SectionOffset: 54 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 28 diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -75,7 +75,7 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET ; CHECK-NEXT: Index: 1 diff --git a/lld/test/wasm/weak-symbols.ll b/lld/test/wasm/weak-symbols.ll --- a/lld/test/wasm/weak-symbols.ll +++ b/lld/test/wasm/weak-symbols.ll @@ -118,7 +118,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -131,12 +131,13 @@ }; struct WasmDataSegment { - uint32_t MemoryIndex; - WasmInitExpr Offset; + uint32_t Flags; + uint32_t MemoryIndex; // present if flags == 2 + WasmInitExpr Offset; // if flags != 1 ArrayRef Content; StringRef Name; // from the "segment info" section uint32_t Alignment; - uint32_t Flags; + uint32_t LinkerFlags; uint32_t Comdat; // from the "comdat info" section }; diff --git a/llvm/include/llvm/MC/MCSectionWasm.h b/llvm/include/llvm/MC/MCSectionWasm.h --- a/llvm/include/llvm/MC/MCSectionWasm.h +++ b/llvm/include/llvm/MC/MCSectionWasm.h @@ -42,6 +42,10 @@ // segment uint32_t SegmentIndex = 0; + // For data sections, the flags determining whether the corresponding wasm + // data segment is active or passive and the present metadata fields. + uint32_t InitFlags = 0; + friend class MCContext; MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin) @@ -79,6 +83,9 @@ uint32_t getSegmentIndex() const { return SegmentIndex; } void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; } + bool getInitFlags() const { return InitFlags; } + void setInitFlags(bool V = true) { InitFlags = V; } + static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; } }; diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h --- a/llvm/include/llvm/ObjectYAML/WasmYAML.h +++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h @@ -111,8 +111,9 @@ }; struct DataSegment { - uint32_t MemoryIndex; uint32_t SectionOffset; + uint32_t Flags; + uint32_t MemoryIndex; wasm::WasmInitExpr Offset; yaml::BinaryRef Content; }; diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -106,9 +106,10 @@ struct WasmDataSegment { MCSectionWasm *Section; StringRef Name; + uint32_t Flags; uint32_t Offset; uint32_t Alignment; - uint32_t Flags; + uint32_t LinkerFlags; SmallVector Data; }; @@ -899,10 +900,15 @@ encodeULEB128(DataSegments.size(), W.OS); // count for (const WasmDataSegment &Segment : DataSegments) { - encodeULEB128(0, W.OS); // memory index - W.OS << char(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(Segment.Offset, W.OS); // offset - W.OS << char(wasm::WASM_OPCODE_END); + Segment.Section->setInitFlags(Segment.Flags); + encodeULEB128(Segment.Flags, W.OS); // flags + if (Segment.Flags == 2) + encodeULEB128(0, W.OS); // memory index + if (Segment.Flags != 1) { + W.OS << char(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(Segment.Offset, W.OS); // offset + W.OS << char(wasm::WASM_OPCODE_END); + } encodeULEB128(Segment.Data.size(), W.OS); // size Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset); W.OS << Segment.Data; // data @@ -1013,7 +1019,7 @@ for (const WasmDataSegment &Segment : DataSegments) { writeString(Segment.Name); encodeULEB128(Segment.Alignment, W.OS); - encodeULEB128(Segment.Flags, W.OS); + encodeULEB128(Segment.LinkerFlags, W.OS); } endSection(SubSection); } @@ -1253,11 +1259,12 @@ DataSegments.emplace_back(); WasmDataSegment &Segment = DataSegments.back(); Segment.Name = SectionName; + Segment.Flags = Section.getInitFlags(); Segment.Offset = DataSize; Segment.Section = &Section; addData(Segment.Data, Section); Segment.Alignment = Log2_32(Section.getAlignment()); - Segment.Flags = 0; + Segment.LinkerFlags = 0; DataSize += Segment.Data.size(); Section.setSegmentIndex(SegmentIndex); diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -421,7 +421,7 @@ for (uint32_t I = 0; I < Count; I++) { DataSegments[I].Data.Name = readString(Ctx); DataSegments[I].Data.Alignment = readVaruint32(Ctx); - DataSegments[I].Data.Flags = readVaruint32(Ctx); + DataSegments[I].Data.LinkerFlags = readVaruint32(Ctx); } break; } @@ -1164,9 +1164,15 @@ DataSegments.reserve(Count); while (Count--) { WasmSegment Segment; - Segment.Data.MemoryIndex = readVaruint32(Ctx); - if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) - return Err; + Segment.Data.Flags = readVaruint32(Ctx); + Segment.Data.MemoryIndex = Segment.Data.Flags == 2 ? readVaruint32(Ctx) : 0; + if (Segment.Data.Flags != 1) { + if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) + return Err; + } else { + Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Data.Offset.Value.Int32 = 0; + } uint32_t Size = readVaruint32(Ctx); if (Size > (size_t)(Ctx.End - Ctx.Ptr)) return make_error("Invalid segment size", @@ -1175,7 +1181,7 @@ // The rest of these Data fields are set later, when reading in the linking // metadata section. Segment.Data.Alignment = 0; - Segment.Data.Flags = 0; + Segment.Data.LinkerFlags = 0; Segment.Data.Comdat = UINT32_MAX; Segment.SectionOffset = Ctx.Ptr - Ctx.Start; Ctx.Ptr += Size; diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -403,8 +403,18 @@ void MappingTraits::mapping( IO &IO, WasmYAML::DataSegment &Segment) { IO.mapOptional("SectionOffset", Segment.SectionOffset); - IO.mapRequired("MemoryIndex", Segment.MemoryIndex); - IO.mapRequired("Offset", Segment.Offset); + IO.mapRequired("Flags", Segment.Flags); + if (Segment.Flags == 2) { + IO.mapRequired("MemoryIndex", Segment.MemoryIndex); + } else { + Segment.MemoryIndex = 0; + } + if (Segment.Flags != 1) { + IO.mapRequired("Offset", Segment.Offset); + } else { + Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Offset.Value.Int32 = 0; + } IO.mapRequired("Content", Segment.Content); } diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -286,6 +286,17 @@ return Name; } + int64_t expectInt() { + if (!Lexer.is(AsmToken::Integer)) { + error("Expected integer, got: ", Lexer.getTok()); + return -1; + } + auto &Int = Lexer.getTok(); + int64_t Val = Int.getIntVal(); + Parser.Lex(); + return Val; + } + Optional parseType(const StringRef &Type) { // FIXME: can't use StringSwitch because wasm::ValType doesn't have a // "invalid" value. @@ -651,6 +662,16 @@ return expect(AsmToken::EndOfStatement, "EOL"); } + if (DirectiveID.getString() == ".init_flags") { + int64_t Val = expectInt(); + auto *Section = cast(Out.getCurrentSectionOnly()); + if (!Section->isWasmData()) + return error(".init_flags directive only allowed in data sections"); + Section->setInitFlags(uint32_t(Val)); + TOut.emitInitFlags(Section); + return expect(AsmToken::EndOfStatement, "EOL"); + } + return true; // We didn't process this directive. } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -17,6 +17,7 @@ #include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSectionWasm.h" #include "llvm/Support/MachineValueType.h" namespace llvm { @@ -49,6 +50,9 @@ virtual void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) = 0; + /// .init_flags + virtual void emitInitFlags(const MCSectionWasm *Section) = 0; + protected: void emitValueType(wasm::ValType Type); }; @@ -71,6 +75,7 @@ void emitEventType(const MCSymbolWasm *Sym) override; void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override; void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override; + void emitInitFlags(const MCSectionWasm *Section) override; }; /// This part is for Wasm object output @@ -88,6 +93,7 @@ StringRef ImportModule) override {} void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override {} + void emitInitFlags(const MCSectionWasm *Section) override {}; }; /// This part is for null output @@ -104,6 +110,7 @@ void emitEventType(const MCSymbolWasm *) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {} void emitImportName(const MCSymbolWasm *, StringRef) override {} + void emitInitFlags(const MCSectionWasm *) override {} }; } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -123,6 +123,10 @@ << ImportName << '\n'; } +void WebAssemblyTargetAsmStreamer::emitInitFlags(const MCSectionWasm *Section) { + OS << "\t.init_flags\t" << Section->getInitFlags() << '\n'; +} + void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -61,6 +61,7 @@ void EmitProducerInfo(Module &M); void EmitJumpTableInfo() override; void EmitConstantPool() override; + void EmitGlobalVariable(const GlobalVariable *GV) override; void EmitFunctionBodyStart() override; void EmitInstruction(const MachineInstr *MI) override; const MCExpr *lowerConstant(const Constant *CV) override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -39,6 +39,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + using namespace llvm; #define DEBUG_TYPE "asm-printer" @@ -220,6 +222,18 @@ // Nothing to do; jump tables are incorporated into the instruction stream. } +void WebAssemblyAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + if (TM.Options.ThreadModel != ThreadModel::Single && GV->hasInitializer()) { + SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); + MCSection *Section = getObjFileLowering().SectionForGlobal(GV, GVKind, TM); + OutStreamer->SwitchSection(Section); + auto WasmSection = cast(Section); + WasmSection->setInitFlags(); + getTargetStreamer()->emitInitFlags(WasmSection); + } + AsmPrinter::EmitGlobalVariable(GV); +} + void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { const Function &F = MF->getFunction(); SmallVector ResultVTs; diff --git a/llvm/test/CodeGen/WebAssembly/global.ll b/llvm/test/CodeGen/WebAssembly/global.ll --- a/llvm/test/CodeGen/WebAssembly/global.ll +++ b/llvm/test/CodeGen/WebAssembly/global.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s +; RUN: llc < %s -asm-verbose=false -thread-model=single -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,SINGLE +; RUN: llc < %s -asm-verbose=false -thread-model=posix -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,THREADS ; Test that globals assemble as expected. @@ -190,8 +191,10 @@ @ptr = global i32* getelementptr inbounds ([128 x i32], [128 x i32]* @arr, i32 0, i32 20), align 4 ; Constant global. +; THREADS: .section .rodata.rom, +; THREADS: .init_flags 1 ; CHECK: .type rom,@object{{$}} -; CHECK: .section .rodata.rom, +; SINGLE: .section .rodata.rom, ; CHECK: .globl rom{{$}} ; CHECK: .p2align 4{{$}} ; CHECK: rom: @@ -203,8 +206,10 @@ ; CHECK: array: ; CHECK-NEXT: .skip 8 ; CHECK-NEXT: .size array, 8 +; THREADS: .section .rodata.pointer_to_array, +; THREADS-NEXT: .init_flags 1 ; CHECK: .type pointer_to_array,@object -; CHECK-NEXT: .section .rodata.pointer_to_array, +; SINGLE-NEXT: .section .rodata.pointer_to_array, ; CHECK-NEXT: .globl pointer_to_array ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: pointer_to_array: diff --git a/llvm/test/MC/WebAssembly/bss.ll b/llvm/test/MC/WebAssembly/bss.ll --- a/llvm/test/MC/WebAssembly/bss.ll +++ b/llvm/test/MC/WebAssembly/bss.ll @@ -12,25 +12,25 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '00000000' ; CHECK-NEXT: - SectionOffset: 15 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 4 ; CHECK-NEXT: Content: '00000000' ; CHECK-NEXT: - SectionOffset: 24 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '' ; CHECK-NEXT: - SectionOffset: 29 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 diff --git a/llvm/test/MC/WebAssembly/comdat.ll b/llvm/test/MC/WebAssembly/comdat.ll --- a/llvm/test/MC/WebAssembly/comdat.ll +++ b/llvm/test/MC/WebAssembly/comdat.ll @@ -68,7 +68,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 diff --git a/llvm/test/MC/WebAssembly/explicit-sections.ll b/llvm/test/MC/WebAssembly/explicit-sections.ll --- a/llvm/test/MC/WebAssembly/explicit-sections.ll +++ b/llvm/test/MC/WebAssembly/explicit-sections.ll @@ -13,20 +13,20 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '08000000' ; CHECK-NEXT: - SectionOffset: 15 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000030000000700000000000000' ; CHECK-NEXT: - SectionOffset: 36 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 24 ; CHECK-NEXT: Content: '08000000' diff --git a/llvm/test/MC/WebAssembly/external-data.ll b/llvm/test/MC/WebAssembly/external-data.ll --- a/llvm/test/MC/WebAssembly/external-data.ll +++ b/llvm/test/MC/WebAssembly/external-data.ll @@ -17,14 +17,14 @@ ; CHECK-NEXT: Offset: 0x00000013 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '0700000000000000' ; CHECK-NEXT: - SectionOffset: 19 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '00000000' diff --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll --- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll +++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll @@ -103,8 +103,8 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '01040000' diff --git a/llvm/test/MC/WebAssembly/init-flags.ll b/llvm/test/MC/WebAssembly/init-flags.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/init-flags.ll @@ -0,0 +1,26 @@ +; RUN: llc -filetype=obj %s -thread-model=single -mattr=-bulk-memory -o - | obj2yaml | FileCheck %s --check-prefix=NO-BULK +; RUN: llc -filetype=obj %s -thread-model=posix -mattr=+bulk-memory -o - | obj2yaml | FileCheck %s --check-prefix=BULK + +; Test that enabling bulk memory causes data sections to be marked +; with .cond_init, and that round tripping through the assembler and +; disassembler preserves that information. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +@str = private unnamed_addr constant [7 x i8] c"Hello!\00", align 1 + +; NO-BULK: - Type: DATA +; NO-BULK-NEXT: Segments: +; NO-BULK-NEXT: - SectionOffset: 6 +; NO-BULK-NEXT: Flags: 0 +; NO-BULK-NEXT: Offset: +; NO-BULK-NEXT: Opcode: I32_CONST +; NO-BULK-NEXT: Value: 0 +; NO-BULK-NEXT: Content: 48656C6C6F2100 + +; BULK: - Type: DATA +; BULK-NEXT: Segments: +; BULK-NEXT: - SectionOffset: 3 +; BULK-NEXT: Flags: 1 +; BULK-NEXT: Content: 48656C6C6F2100 diff --git a/llvm/test/MC/WebAssembly/unnamed-data.ll b/llvm/test/MC/WebAssembly/unnamed-data.ll --- a/llvm/test/MC/WebAssembly/unnamed-data.ll +++ b/llvm/test/MC/WebAssembly/unnamed-data.ll @@ -19,26 +19,26 @@ ; CHECK-NEXT: Offset: 0x00000025 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: 68656C6C6F00 ; CHECK-NEXT: - SectionOffset: 17 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 6 ; CHECK-NEXT: Content: 776F726C6400 ; CHECK-NEXT: - SectionOffset: 28 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 ; CHECK-NEXT: Content: '00000000' ; CHECK-NEXT: - SectionOffset: 37 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 24 ; CHECK-NEXT: Content: '06000000' diff --git a/llvm/test/MC/WebAssembly/weak-alias.ll b/llvm/test/MC/WebAssembly/weak-alias.ll --- a/llvm/test/MC/WebAssembly/weak-alias.ll +++ b/llvm/test/MC/WebAssembly/weak-alias.ll @@ -119,19 +119,19 @@ ; CHECK-NEXT: Offset: 0x00000018 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '07000000' ; CHECK-NEXT: - SectionOffset: 15 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000' ; CHECK-NEXT: - SectionOffset: 24 -; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 diff --git a/llvm/test/ObjectYAML/wasm/data_section.yaml b/llvm/test/ObjectYAML/wasm/data_section.yaml --- a/llvm/test/ObjectYAML/wasm/data_section.yaml +++ b/llvm/test/ObjectYAML/wasm/data_section.yaml @@ -8,11 +8,19 @@ - Initial: 0x00000003 - Type: DATA Segments: - - MemoryIndex: 0 + - Flags: 0 Offset: Opcode: I32_CONST Value: 4 Content: '10001000' + - Flags: 1 + Content: '01010101' + - Flags: 2 + MemoryIndex: 0 + Offset: + Opcode: I32_CONST + Value: 8 + Content: '00110011' Relocations: - Type: R_WASM_MEMORY_ADDR_I32 Index: 0 @@ -49,10 +57,20 @@ # CHECK-NEXT: Offset: 0x00000006 # CHECK-NEXT: Addend: -6 # CHECK-NEXT: Segments: -# CHECK-NEXT: - SectionOffset: 6 -# CHECK-NEXT: MemoryIndex: 0 +# CHECK-NEXT: - SectionOffset: 6 +# CHECK-NEXT: Flags: 0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 4 +# CHECK-NEXT: Content: '10001000' +# CHECK-NEXT: - SectionOffset: 12 +# CHECK-NEXT: Flags: 1 +# CHECK-NEXT: Content: '01010101' +# CHECK-NEXT: - SectionOffset: 22 +# CHECK-NEXT: Flags: 2 +# CHECK-NEXT: MemoryIndex: 0 # CHECK-NEXT: Offset: -# CHECK-NEXT: Opcode: I32_CONST -# CHECK-NEXT: Value: 4 -# CHECK-NEXT: Content: '10001000' +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 8 +# CHECK-NEXT: Content: '00110011' # CHECK-NEXT: - Type: CUSTOM diff --git a/llvm/test/ObjectYAML/wasm/linking_section.yaml b/llvm/test/ObjectYAML/wasm/linking_section.yaml --- a/llvm/test/ObjectYAML/wasm/linking_section.yaml +++ b/llvm/test/ObjectYAML/wasm/linking_section.yaml @@ -17,12 +17,12 @@ SigIndex: 0 - Type: DATA Segments: - - MemoryIndex: 0 + - Flags: 0 Offset: Opcode: I32_CONST Value: 4 Content: '10001000' - - MemoryIndex: 0 + - Flags: 0 Offset: Opcode: I32_CONST Value: 8 diff --git a/llvm/test/tools/llvm-nm/wasm/exports.yaml b/llvm/test/tools/llvm-nm/wasm/exports.yaml --- a/llvm/test/tools/llvm-nm/wasm/exports.yaml +++ b/llvm/test/tools/llvm-nm/wasm/exports.yaml @@ -30,7 +30,7 @@ - Type: DATA Segments: - SectionOffset: 6 - MemoryIndex: 0 + Flags: 0 Offset: Opcode: I32_CONST Value: 0 diff --git a/llvm/test/tools/llvm-nm/wasm/weak-symbols.yaml b/llvm/test/tools/llvm-nm/wasm/weak-symbols.yaml --- a/llvm/test/tools/llvm-nm/wasm/weak-symbols.yaml +++ b/llvm/test/tools/llvm-nm/wasm/weak-symbols.yaml @@ -36,7 +36,7 @@ - Type: DATA Segments: - SectionOffset: 6 - MemoryIndex: 0 + Flags: 0 Offset: Opcode: I32_CONST Value: 0 diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp --- a/llvm/tools/obj2yaml/wasm2yaml.cpp +++ b/llvm/tools/obj2yaml/wasm2yaml.cpp @@ -93,7 +93,7 @@ SegmentInfo.Name = Segment.Data.Name; SegmentInfo.Index = SegmentIndex; SegmentInfo.Alignment = Segment.Data.Alignment; - SegmentInfo.Flags = Segment.Data.Flags; + SegmentInfo.Flags = Segment.Data.LinkerFlags; LinkingSec->SegmentInfos.push_back(SegmentInfo); } if (Segment.Data.Comdat != UINT32_MAX) { @@ -334,6 +334,7 @@ for (const object::WasmSegment &Segment : Obj.dataSegments()) { WasmYAML::DataSegment Seg; Seg.SectionOffset = Segment.SectionOffset; + Seg.Flags = Segment.Data.Flags; Seg.MemoryIndex = Segment.Data.MemoryIndex; Seg.Offset = Segment.Data.Offset; Seg.Content = yaml::BinaryRef(Segment.Data.Content); diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp --- a/llvm/tools/yaml2obj/yaml2wasm.cpp +++ b/llvm/tools/yaml2obj/yaml2wasm.cpp @@ -487,8 +487,11 @@ WasmYAML::DataSection &Section) { encodeULEB128(Section.Segments.size(), OS); for (auto &Segment : Section.Segments) { - encodeULEB128(Segment.MemoryIndex, OS); - writeInitExpr(Segment.Offset, OS); + encodeULEB128(Segment.Flags, OS); + if (Segment.Flags == 2) + encodeULEB128(Segment.MemoryIndex, OS); + if (Segment.Flags != 1) + writeInitExpr(Segment.Offset, OS); encodeULEB128(Segment.Content.binary_size(), OS); Segment.Content.writeAsBinary(OS); }