-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Partial support for common linkage for WebAssembly #151478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-webassembly Author: None (serge-sans-paille) ChangesEmulate common linkage through weak linkage, the only difference between the two being mostly similar according to langref, with the notable exception that common linkage implies zero initializer. This is needed for fortran-to-web-assembly projects used in the python community, esp. https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/libflang Full diff: https://github.com/llvm/llvm-project/pull/151478.diff 2 Files Affected:
diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp
index e3ef1117b4125..c5249db753ec6 100644
--- a/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/llvm/lib/MC/MCWasmStreamer.cpp
@@ -14,6 +14,7 @@
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectStreamer.h"
@@ -131,7 +132,29 @@ bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
Align ByteAlignment) {
- llvm_unreachable("Common symbols are not yet implemented for Wasm");
+ auto *Symbol = cast<MCSymbolWasm>(S);
+
+ pushSection();
+
+ // Common symbols are very close to weak symbols, so manually build a weak
+ // symbol.
+ MCSectionWasm *SW = getContext().getWasmSection(".bss.common." + S->getName(),
+ SectionKind::getData());
+ SW->setAlignment(ByteAlignment);
+ getAssembler().registerSection(*SW);
+
+ switchSection(SW);
+
+ MCDataFragment *DF = getOrCreateDataFragment();
+ DF->setContents(std::vector<char>(Size, '\0'));
+ Symbol->setFragment(DF);
+
+ Symbol->setSize(MCConstantExpr::create(Size, getContext(), false, 8));
+ Symbol->setWeak(true);
+ Symbol->setExternal(true);
+ getAssembler().registerSymbol(*Symbol);
+
+ popSection();
}
void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
diff --git a/llvm/test/MC/WebAssembly/common.ll b/llvm/test/MC/WebAssembly/common.ll
new file mode 100644
index 0000000000000..50e7298684ccb
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/common.ll
@@ -0,0 +1,69 @@
+; RUN; llc -mcpu=mvp -filetype=obj %s -o - | obj2yaml | FileCheck %s
+; RUN; llc -mcpu=mvp -filetype=asm %s -asm-verbose=false -o - | FileCheck --check-prefix=ASM %s
+; RUN: llc -mcpu=mvp -filetype=asm %s -o - | llvm-mc -triple=wasm32 -filetype=obj -o - | obj2yaml | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+;target triple = "x86_64-redhat-linux-gnu"
+@b = common dso_local global [10 x i32] zeroinitializer, align 4
+@c = common dso_local global [20 x i32] zeroinitializer, align 32
+
+; CHECK-ASM: .file "common.ll"
+; CHECK-ASM: .type b,@object
+; CHECK-ASM: .comm b,40,2
+; CHECK-ASM: .type c,@object
+; CHECK-ASM: .comm c,80,5
+
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x1
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: IMPORT
+; CHECK-NEXT: Imports:
+; CHECK-NEXT: - Module: env
+; CHECK-NEXT: Field: __linear_memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Memory:
+; CHECK-NEXT: Minimum: 0x1
+; CHECK-NEXT: - Type: DATACOUNT
+; CHECK-NEXT: Count: 2
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 6
+; CHECK-NEXT: InitFlags: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 0
+; CHECK-NEXT: Content: '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
+; CHECK-NEXT: - SectionOffset: 52
+; CHECK-NEXT: InitFlags: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 64
+; CHECK-NEXT: Content: '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: Version: 2
+; CHECK-NEXT: SymbolTable:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Kind: DATA
+; CHECK-NEXT: Name: b
+; CHECK-NEXT: Flags: [ BINDING_WEAK ]
+; CHECK-NEXT: Segment: 0
+; CHECK-NEXT: Size: 40
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Kind: DATA
+; CHECK-NEXT: Name: c
+; CHECK-NEXT: Flags: [ BINDING_WEAK ]
+; CHECK-NEXT: Segment: 1
+; CHECK-NEXT: Size: 80
+; CHECK-NEXT: SegmentInfo:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: .bss.common.b
+; CHECK-NEXT: Alignment: 2
+; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: .bss.common.c
+; CHECK-NEXT: Alignment: 5
+; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: ...
|
Emulate common linkage through weak linkage, the only difference between the two being mostly similar according to langref, with the notable exception that common linkage implies zero initializer. This is needed for fortran-to-web-assembly projects used in the python community, esp. https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/libflang
ce491c5
to
2bcf69a
Compare
@MaskRay I'm new to MC code, don't hesitate to propose a better approach! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's 2025, and I suggest that we don't implement COMMON symbols in new object file formats. https://maskray.me/blog/2022-02-06-all-about-common-symbols
GCC since 10 and Clang since 11 default to -fno-common.
In ELF, for a definition in a relocatable object file, the precedence is STB_GLOBAL > COMMON > STB_WEAK.
Using weak isn't super appropriate.
LAPACK and other key scientific codebases make use of common variables. If we want Flang to be able to build SciPy, or GNU Octave, or other such tools to WebAssembly, having some support for them will be required unfortunately. |
@MaskRay yes, common is old and should not be used for new code. However, there is still a lot of software in production that uses common. If common symbols should not be used in LLVM anymore, what do you recommend Fortran compilers to emit instead? This applies to both Flang and LFortran. |
I assume that the Fortran compiler that emits |
That would require changing the compilers (Flang, LFortran), which currently use common linkage. |
Emulate common linkage through weak linkage, the only difference between the two being mostly similar according to langref, with the notable exception that common linkage implies zero initializer.
This is needed for fortran-to-web-assembly projects used in the python community, esp.
https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten/libflang