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 @@ -243,7 +243,7 @@ WASM_OPCODE_F64_CONST = 0x44, }; -enum : unsigned { +enum : uint8_t { WASM_LIMITS_FLAG_HAS_MAX = 0x1, WASM_LIMITS_FLAG_IS_SHARED = 0x2, }; diff --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -23,6 +23,7 @@ wasm::WasmSignature *Signature = nullptr; Optional GlobalType; Optional EventType; + uint8_t MemFlags = 0; /// An expression describing how to calculate the size of a symbol. If a /// symbol has no size this field will be NULL. @@ -78,6 +79,9 @@ } void setImportName(StringRef Name) { ImportName = Name; } + uint8_t getMemFlags() const { return MemFlags; } + void setMemFlags(uint8_t F) { MemFlags = F; } + const wasm::WasmSignature *getSignature() const { return Signature; } void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } 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 @@ -750,8 +750,10 @@ W.OS << char(Import.Global.Mutable ? 1 : 0); break; case wasm::WASM_EXTERNAL_MEMORY: - encodeULEB128(0, W.OS); // flags - encodeULEB128(NumPages, W.OS); // initial + encodeULEB128(Import.Memory.Flags, W.OS); // flags + encodeULEB128(NumPages, W.OS); // initial + if (Import.Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) + encodeULEB128(NumPages, W.OS); // max break; case wasm::WASM_EXTERNAL_TABLE: W.OS << char(Import.Table.ElemType); @@ -1170,6 +1172,7 @@ MemImport.Module = MemorySym->getImportModule(); MemImport.Field = MemorySym->getImportName(); MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; + MemImport.Memory.Flags = MemorySym->getMemFlags(); Imports.push_back(MemImport); // For now, always emit the table section, since indirect calls are not 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 @@ -651,6 +651,11 @@ return expect(AsmToken::EndOfStatement, "EOL"); } + if (DirectiveID.getString() == ".shared_memory") { + TOut.emitSharedMemory(); + 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 @@ -49,6 +49,9 @@ virtual void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) = 0; + /// .shared_memory + virtual void emitSharedMemory() = 0; + protected: void emitValueType(wasm::ValType Type); }; @@ -71,6 +74,7 @@ void emitEventType(const MCSymbolWasm *Sym) override; void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override; void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override; + void emitSharedMemory() override; }; /// This part is for Wasm object output @@ -88,6 +92,7 @@ StringRef ImportModule) override {} void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override {} + void emitSharedMemory() override; }; /// This part is for null output @@ -104,6 +109,7 @@ void emitEventType(const MCSymbolWasm *) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {} void emitImportName(const MCSymbolWasm *, StringRef) override {} + void emitSharedMemory() 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::emitSharedMemory() { + OS << "\t.shared_memory\n"; +} + void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } @@ -150,3 +154,11 @@ void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) { llvm_unreachable(".indidx encoding not yet implemented"); } + +void WebAssemblyTargetWasmStreamer::emitSharedMemory() { + // __linear_memory is always included in the object, this just makes it shared + auto Sym = cast( + getStreamer().getContext().getOrCreateSymbol("__linear_memory")); + Sym->setMemFlags(wasm::WASM_LIMITS_FLAG_HAS_MAX | + wasm::WASM_LIMITS_FLAG_IS_SHARED); +} 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 @@ -57,6 +57,7 @@ // AsmPrinter Implementation. //===------------------------------------------------------------------===// + void EmitStartOfAsmFile(Module &M) override; void EmitEndOfAsmFile(Module &M) override; void EmitProducerInfo(Module &M); void EmitJumpTableInfo() 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 @@ -81,6 +81,12 @@ // WebAssemblyAsmPrinter Implementation. //===----------------------------------------------------------------------===// +void WebAssemblyAsmPrinter::EmitStartOfAsmFile(Module &M) { + if (TM.Options.ThreadModel != ThreadModel::Single) { + getTargetStreamer()->emitSharedMemory(); + } +} + void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { for (auto &It : OutContext.getSymbols()) { // Emit a .globaltype and .eventtype declaration. diff --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll --- a/llvm/test/MC/WebAssembly/assembler-binary.ll +++ b/llvm/test/MC/WebAssembly/assembler-binary.ll @@ -21,14 +21,17 @@ ; Checking assembly is not the point of this test, but if something breaks ; it is easier to spot it here than in the yaml output. -; ASM: .text -; ASM: .file "assembler-binary.ll" -; ASM: .globl foo -; ASM: foo: -; ASM-NEXT: .functype foo (i32) -> () -; ASM-NEXT: call bar@FUNCTION -; ASM-NEXT: end_function -; ASM: .functype bar () -> () +; ASM: .text +; ASM: .shared +; ASM-NEXT: .file "assembler-binary.ll" +; ASM-DAG: .section .text.foo,"",@ +; ASM-DAG: .globl foo + +; ASM: foo: +; ASM-NEXT: .functype foo (i32) -> () +; ASM-NEXT: call bar@FUNCTION +; ASM-NEXT: end_function +; ASM: .functype bar () -> () ; CHECK: --- !WASM @@ -50,7 +53,9 @@ ; CHECK-NEXT: Field: __linear_memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Memory: +; CHECK-NEXT: Flags: [ HAS_MAX, IS_SHARED ] ; CHECK-NEXT: Initial: 0x00000000 +; CHECK-NEXT: Maximum: 0x00000000 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __indirect_function_table ; CHECK-NEXT: Kind: TABLE diff --git a/llvm/test/MC/WebAssembly/custom-sections.ll b/llvm/test/MC/WebAssembly/custom-sections.ll --- a/llvm/test/MC/WebAssembly/custom-sections.ll +++ b/llvm/test/MC/WebAssembly/custom-sections.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o - | llvm-readobj -s | FileCheck %s +; RUN: llc -filetype=obj -thread-model=single %s -o - | llvm-readobj -s | FileCheck %s ; Test the mechanism for defining user custom sections. diff --git a/llvm/test/MC/WebAssembly/event-section.ll b/llvm/test/MC/WebAssembly/event-section.ll --- a/llvm/test/MC/WebAssembly/event-section.ll +++ b/llvm/test/MC/WebAssembly/event-section.ll @@ -1,5 +1,5 @@ -; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o - | obj2yaml | FileCheck %s -; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o - | llvm-readobj -s | FileCheck -check-prefix=SEC %s +; RUN: llc -filetype=obj -thread-model=single -exception-model=wasm -mattr=+exception-handling %s -o - | obj2yaml | FileCheck %s +; RUN: llc -filetype=obj -thread-model=single -exception-model=wasm -mattr=+exception-handling %s -o - | llvm-readobj -s | FileCheck -check-prefix=SEC %s target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/ObjectYAML/wasm/memory_section.yaml b/llvm/test/ObjectYAML/wasm/memory_section.yaml --- a/llvm/test/ObjectYAML/wasm/memory_section.yaml +++ b/llvm/test/ObjectYAML/wasm/memory_section.yaml @@ -9,6 +9,10 @@ Initial: 0x00000002 Maximum: 0x000000FF - Initial: 0x00000003 + - Flags: [ HAS_MAX, IS_SHARED ] + Initial: 0x00000042 + Maximum: 0x00000042 + ... # CHECK: --- !WASM # CHECK: FileHeader: @@ -20,4 +24,7 @@ # CHECK: Initial: 0x00000002 # CHECK: Maximum: 0x000000FF # CHECK: - Initial: 0x00000003 +# CHECK: - Flags: [ HAS_MAX, IS_SHARED ] +# CHECK: Initial: 0x00000042 +# CHECK: Maximum: 0x00000042 # CHECK: ...