For object files, emitting the .shared_memory directive sets the
shared bit on the __linear_memory import symbol, so memory flags are
also added to wasm symbols. The directive is emitted in the AsmPrinter
if the thread model is multithreaded to communicate to the linker that
this object is built for a multithreaded context. Depends on D57938.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
- Build Status
Buildable 28295 Build 28294: arc lint + arc unit
Event Timeline
llvm/include/llvm/MC/MCSymbolWasm.h | ||
---|---|---|
26 | Seems strange to attach this to a symol. | |
llvm/test/MC/WebAssembly/assembler-binary.ll | ||
25 | This looks like its starting a new section. Could we call this ".shared_memory"? Or is there some other place in the asm syntax there this attribute might be specified? Actually do we need this to be in the .s format at all? seems like it could be specified as an assembler flag? Like the march/mcpu stuff.. that doesn't live in the .s format right? | |
llvm/test/MC/WebAssembly/event-section.ll | ||
1–2 | Can we make this the default instead? |
llvm/include/llvm/MC/MCSymbolWasm.h | ||
---|---|---|
26 | Different kinds of symbols already store their special information in this object, such as their Signatures or Types. I think it makes sense for memory imports to do the same. | |
llvm/test/MC/WebAssembly/assembler-binary.ll | ||
25 | Yes, calling it ".shared_memory" would be fine, although it is really meant to communicate that the entire module was produced to be thread-aware, not just that the memory is shared. That this corresponds to the shared bit being set in the object file is mostly an implementation detail. I'm open to suggestions for other places this information might live, but up at the top of the file seemed appropriate because it applies to the entire module. I believe the march/mcpu options are not recorded in the .s format because they only affect codegen, which has already taken place by the time you have an assembly file. In contrast, for webassembly the information that code was produced by a thread-aware toolchain needs to be propagated through to the linker alongside that code, whether or not there is a separate assembly step in between. There is no way to propagate this information through an intermediate assembly step except by assembler directive. | |
llvm/test/MC/WebAssembly/event-section.ll | ||
1–2 | I'm not sure we can. The option and its default value are are statically defined in include/llvm/CodeGen/CommandFlags.inc, and I don't think it's possible to make the default value of an option like that depend on the value of another option. |
@sbc100 I'm looking at the linker to figure out how to implement shared memory-aware linking, and it looks like the linker doesn't even look in the imports section of the wobject. Why even bother importing __linear_memory in object files at all? Is it just to make the object file a spec-compliant wasm? I think I'm going to have to make the linker look at the import section for the sole purpose of fetching out this shared bit on the memory import. This isn't a problem, but it did surprise me.
Yes, its purely to make the object file valid.
I'm tempted to have the linker driven by a flag for this rather then driven by the input file.
If you were going to check that kind of think I would do it when cheking the format of the object file. Perhaps is lld::wasm::createObjectFile.
llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | ||
---|---|---|
654 | This applies to the most recent symbol? Seems many directives we have explicitly refer to the symbol they're changing, like .functype, .eventtype, .globaltype, so would it make sense for this to that too? Or is there only ever one such flag and one such symbol, ever? |
llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | ||
---|---|---|
654 | There is meant to only ever be one such flag for the entire module, and the only memory import is the __linear_memory symbol that this affects. Currently the ObjectFileWriter unconditionally emits __linear_memory, and this only modifies the flags it is emitted with. |
llvm/lib/MC/WasmObjectWriter.cpp | ||
---|---|---|
756 | I guess this makes sense for completeness, but an object file really doesn't make sense to have a max for its memory. |
llvm/lib/MC/WasmObjectWriter.cpp | ||
---|---|---|
756 | Yeah, unfortunately it is necessary if we want object files to validate. Also unfortunately, it is invalid to have the limits be shared but not have a max, so we have to just come up with some arbitrary max. |
llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp | ||
---|---|---|
163 | It still seems wrong to attach this information to a symbol, is there not some module level state we can attach it too? I don't think __linear_memory should be and MCSymbol at all. We don't have a symbol type for a memory. It looks like it is referenced in WasmObjectWriter.cpp but I can't see why it would be. |
An alternative to the approach taken in this CL that explicitly records that the object is thread-aware in a new metadata section is presented here: https://github.com/WebAssembly/tool-conventions/pull/99
llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp | ||
---|---|---|
163 | Changing approaches to use a target features section would make this change to MCSymbol unnecessary (although WasmObjectWriter would still treat __linear_memory as a symbol). |
llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp | ||
---|---|---|
163 | Not if I can land this first :) https://reviews.llvm.org/D58487 Seriously though, is there some other place we can attach the "shared" attribute so that it can later be read by the object writer? I don't think we need to block on the target features section.. I'm still happy with the flag on the memory import, just that we set that flag based on something other than an MCSymbol? (Not sure how reasonable this request is). |
It looks like we have consensus that a target features section would be a good idea, so I'm closing out this CL.
Seems strange to attach this to a symol.