[llvm] Partial support for common linkage for WebAssembly (PR #151478)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 31 04:36:14 PDT 2025


https://github.com/serge-sans-paille updated https://github.com/llvm/llvm-project/pull/151478

>From 2bcf69a2f60d2a2a17d99390222e11882f9493b0 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Wed, 9 Apr 2025 07:43:08 +0200
Subject: [PATCH] Partial support for common linkage for WebAssembly

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
---
 llvm/lib/MC/MCWasmStreamer.cpp     | 25 ++++++++++-
 llvm/test/MC/WebAssembly/common.ll | 69 ++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/MC/WebAssembly/common.ll

diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp
index e3ef1117b4125..559552d71bfe2 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);
+
+  MCFragment *F = getCurrentFragment();
+  F->appendContents(Size, '\0');
+  Symbol->setFragment(F);
+
+  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"
+ at b = common dso_local global [10 x i32] zeroinitializer, align 4
+ at c = common dso_local global [20 x i32] zeroinitializer, align 32
+
+; CHECK-ASM: .file	"common.ll"
+; CHECK-ASM: .type	b, at object
+; CHECK-ASM: .comm	b,40,2
+; CHECK-ASM: .type	c, at 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: ...



More information about the llvm-commits mailing list