[clang] [llvm] [Clang][WebAssembly] Add wasm_global declaration attribute (PR #221909)

Changqing Jing via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 8 23:51:40 PDT 2026


https://github.com/Changqing-JING updated https://github.com/llvm/llvm-project/pull/221909

>From cd8486de0e3d4fd9e8b61dddc00681aabf0c071f Mon Sep 17 00:00:00 2001
From: Changqing Jing <changqing.jing at bmw.com>
Date: Tue, 8 Sep 2026 15:42:28 +0800
Subject: [PATCH 1/3] [Clang][WebAssembly] Add wasm_global declaration
 attribute

---
 clang/include/clang/Basic/Attr.td                |  6 ++++++
 clang/include/clang/Basic/AttrDocs.td            | 12 ++++++++++++
 clang/include/clang/Sema/SemaWasm.h              |  1 +
 clang/lib/CodeGen/Targets/WebAssembly.cpp        |  9 +++++++++
 clang/lib/Sema/SemaDeclAttr.cpp                  |  3 +++
 clang/lib/Sema/SemaWasm.cpp                      | 10 ++++++++++
 .../WebAssembly/wasm-global-attribute.cpp        | 16 ++++++++++++++++
 .../llvm/Support}/WasmAddressSpaces.h            | 14 ++++++--------
 .../WebAssembly/Utils/WebAssemblyTypeUtilities.h |  2 +-
 .../Target/WebAssembly/WebAssemblyFastISel.cpp   |  2 +-
 .../WebAssembly/WebAssemblyRefTypeMem2Local.cpp  |  2 +-
 11 files changed, 66 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CodeGen/WebAssembly/wasm-global-attribute.cpp
 rename llvm/{lib/Target/WebAssembly/Utils => include/llvm/Support}/WasmAddressSpaces.h (73%)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a576411097b9d..f4c04614092ba 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2602,6 +2602,12 @@ def WebAssemblyImportName : InheritableAttr,
   let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>;
 }
 
+def WebAssemblyGlobal : InheritableAttr, TargetSpecificAttr<TargetWebAssembly> {
+  let Spellings = [Clang<"wasm_global">];
+  let Documentation = [WebAssemblyGlobalDocs];
+  let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
+}
+
 def NoSplitStack : InheritableAttr {
   let Spellings = [GCC<"no_split_stack">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 285cf02c047cd..23f3c688ea707 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7340,6 +7340,18 @@ request a specific field name be used instead.
   }];
 }
 
+def WebAssemblyGlobalDocs : Documentation {
+  let Category = DocCatVariable;
+  let Content = [{
+Clang supports the `[[clang::wasm_global]]` attribute for the WebAssembly
+target. This attribute declares that a variable is stored as a WebAssembly
+global rather than in linear memory.
+
+WebAssembly globals can be imported or exported using the
+`import_module`, `import_name`, and `export_name` attributes.
+  }];
+}
+
 def ArtificialDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
diff --git a/clang/include/clang/Sema/SemaWasm.h b/clang/include/clang/Sema/SemaWasm.h
index c70cda259029e..41245ef649e84 100644
--- a/clang/include/clang/Sema/SemaWasm.h
+++ b/clang/include/clang/Sema/SemaWasm.h
@@ -50,6 +50,7 @@ class SemaWasm : public SemaBase {
   void handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL);
   void handleWebAssemblyImportModuleAttr(Decl *D, const ParsedAttr &AL);
   void handleWebAssemblyImportNameAttr(Decl *D, const ParsedAttr &AL);
+  void handleWebAssemblyGlobalAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp
index 8f6f58bfb807e..f51edfc620baa 100644
--- a/clang/lib/CodeGen/Targets/WebAssembly.cpp
+++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp
@@ -9,6 +9,7 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -55,6 +56,14 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
   }
 
+  LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
+                                  const VarDecl *D) const override {
+    if (D && D->hasAttr<WebAssemblyGlobalAttr>())
+      return getLangASFromTargetAS(
+          llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR);
+    return TargetCodeGenInfo::getGlobalVarAddressSpace(CGM, D);
+  }
+
   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
                            CodeGen::CodeGenModule &CGM) const override {
     TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d4206acd060a0..0cca26219475a 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7750,6 +7750,9 @@ ProcessDeclAttribute(Sema &S, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_WebAssemblyImportName:
     S.Wasm().handleWebAssemblyImportNameAttr(D, AL);
     break;
+  case ParsedAttr::AT_WebAssemblyGlobal:
+    S.Wasm().handleWebAssemblyGlobalAttr(D, AL);
+    break;
   case ParsedAttr::AT_IBOutlet:
     S.ObjC().handleIBOutlet(D, AL);
     break;
diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp
index cfc0a08a50e5a..d0fae91fa4727 100644
--- a/clang/lib/Sema/SemaWasm.cpp
+++ b/clang/lib/Sema/SemaWasm.cpp
@@ -20,6 +20,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Attr.h"
 #include "clang/Sema/Sema.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 
 namespace clang {
 
@@ -457,4 +458,13 @@ void SemaWasm::handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL) {
   D->addAttr(UsedAttr::CreateImplicit(Context));
 }
 
+void SemaWasm::handleWebAssemblyGlobalAttr(Decl *D, const ParsedAttr &AL) {
+  ASTContext &Context = getASTContext();
+  auto *VD = cast<VarDecl>(D);
+  VD->setType(Context.getAddrSpaceQualType(
+      VD->getType(), getLangASFromTargetAS(
+                         llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR)));
+  D->addAttr(::new (Context) WebAssemblyGlobalAttr(Context, AL));
+}
+
 } // namespace clang
diff --git a/clang/test/CodeGen/WebAssembly/wasm-global-attribute.cpp b/clang/test/CodeGen/WebAssembly/wasm-global-attribute.cpp
new file mode 100644
index 0000000000000..e61056d9ba848
--- /dev/null
+++ b/clang/test/CodeGen/WebAssembly/wasm-global-attribute.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+int exported_g [[clang::wasm_global]] = 42;
+
+extern const int imported_g [[clang::wasm_global]]
+    __attribute__((import_module("env"), import_name("imported_g")));
+
+int get_import(void) { return imported_g; }
+}
+
+// CHECK: @exported_g = addrspace(1) global i32 42, align 4
+// CHECK: @imported_g = external addrspace(1) constant i32, align 4 #0
+// CHECK: define{{.*}} @get_import()
+// CHECK: load i32, ptr addrspace(1) @imported_g
+// CHECK: attributes #0 = { "wasm-import-module"="env" "wasm-import-name"="imported_g" }
\ No newline at end of file
diff --git a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h b/llvm/include/llvm/Support/WasmAddressSpaces.h
similarity index 73%
rename from llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h
rename to llvm/include/llvm/Support/WasmAddressSpaces.h
index d2ab2c0f9e777..8738b4e88520d 100644
--- a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h
+++ b/llvm/include/llvm/Support/WasmAddressSpaces.h
@@ -1,4 +1,4 @@
-//===--- llvm/CodeGen/WasmAddressSpaces.h -----------------------*- C++ -*-===//
+//===---------------- WasmAddressSpaces.h ----------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,22 +6,21 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Address Spaces for WebAssembly Type Handling
+// Address spaces for WebAssembly IR and type handling.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WASMADDRESSSPACES_H
-#define LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WASMADDRESSSPACES_H
+#ifndef LLVM_SUPPORT_WASMADDRESSSPACES_H
+#define LLVM_SUPPORT_WASMADDRESSSPACES_H
 
 namespace llvm {
-
 namespace WebAssembly {
 
 enum WasmAddressSpace : unsigned {
   // Default address space, for pointers to linear memory (stack, heap, data).
   WASM_ADDRESS_SPACE_DEFAULT = 0,
   // A non-integral address space for pointers to named objects outside of
-  // linear memory: WebAssembly globals or WebAssembly locals.  Loads and stores
+  // linear memory: WebAssembly globals or WebAssembly locals. Loads and stores
   // to these pointers are lowered to global.get / global.set or local.get /
   // local.set, as appropriate.
   WASM_ADDRESS_SPACE_VAR = 1
@@ -38,7 +37,6 @@ inline bool isValidAddressSpace(unsigned AS) {
 }
 
 } // namespace WebAssembly
-
 } // namespace llvm
 
-#endif // LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WASMADDRESSSPACES_H
+#endif // LLVM_SUPPORT_WASMADDRESSSPACES_H
\ No newline at end of file
diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
index 47ba91df81161..72342393e410a 100644
--- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
+++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
@@ -16,11 +16,11 @@
 #define LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYTYPEUTILITIES_H
 
 #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
-#include "WasmAddressSpaces.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/CodeGenTypes/MachineValueType.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 
 namespace llvm {
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index db03f5874234c..075330081b5ca 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -16,7 +16,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
-#include "Utils/WasmAddressSpaces.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblySubtarget.h"
 #include "WebAssemblyUtilities.h"
@@ -33,6 +32,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/GlobalVariable.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/Operator.h"
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRefTypeMem2Local.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRefTypeMem2Local.cpp
index 2c162308700af..6fdb04760514e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRefTypeMem2Local.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRefTypeMem2Local.cpp
@@ -12,7 +12,6 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "Utils/WasmAddressSpaces.h"
 #include "Utils/WebAssemblyTypeUtilities.h"
 #include "WebAssembly.h"
 #include "llvm/IR/Analysis.h"
@@ -22,6 +21,7 @@
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Pass.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 using namespace llvm;
 
 #define DEBUG_TYPE "wasm-ref-type-mem2local"

>From dbfb4e5ab68181c99c3c3f097dedad4a948aaf9a Mon Sep 17 00:00:00 2001
From: Changqing Jing <changqing.jing at bmw.com>
Date: Tue, 8 Sep 2026 15:56:09 +0800
Subject: [PATCH 2/3] Fix

---
 clang/lib/CodeGen/Targets/WebAssembly.cpp           | 3 +--
 clang/lib/Sema/SemaWasm.cpp                         | 4 ++--
 llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp
index f51edfc620baa..05f2391dc7e38 100644
--- a/clang/lib/CodeGen/Targets/WebAssembly.cpp
+++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp
@@ -59,8 +59,7 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
   LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
                                   const VarDecl *D) const override {
     if (D && D->hasAttr<WebAssemblyGlobalAttr>())
-      return getLangASFromTargetAS(
-          llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR);
+      return getLangASFromTargetAS(llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR);
     return TargetCodeGenInfo::getGlobalVarAddressSpace(CGM, D);
   }
 
diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp
index d0fae91fa4727..42c8957585ea0 100644
--- a/clang/lib/Sema/SemaWasm.cpp
+++ b/clang/lib/Sema/SemaWasm.cpp
@@ -462,8 +462,8 @@ void SemaWasm::handleWebAssemblyGlobalAttr(Decl *D, const ParsedAttr &AL) {
   ASTContext &Context = getASTContext();
   auto *VD = cast<VarDecl>(D);
   VD->setType(Context.getAddrSpaceQualType(
-      VD->getType(), getLangASFromTargetAS(
-                         llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR)));
+      VD->getType(),
+      getLangASFromTargetAS(llvm::WebAssembly::WASM_ADDRESS_SPACE_VAR)));
   D->addAttr(::new (Context) WebAssemblyGlobalAttr(Context, AL));
 }
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 075330081b5ca..3eea32411a808 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -32,10 +32,10 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/GlobalVariable.h"
-#include "llvm/Support/WasmAddressSpaces.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/Operator.h"
+#include "llvm/Support/WasmAddressSpaces.h"
 
 using namespace llvm;
 

>From 6ef09373116ab5b09e2b306d92869ef8c9742f94 Mon Sep 17 00:00:00 2001
From: Changqing Jing <changqing.jing at bmw.com>
Date: Wed, 9 Sep 2026 14:51:25 +0800
Subject: [PATCH 3/3] fix

---
 clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 8f8c1aa3d3f9c..2285f3602b863 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -236,6 +236,7 @@
 // CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
 // CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function)
 // CHECK-NEXT: WebAssemblyExportName (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
+// CHECK-NEXT: WebAssemblyGlobal (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: WebAssemblyImportModule (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: WebAssemblyImportName (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: WorkGroupSizeHint (SubjectMatchRule_function)



More information about the cfe-commits mailing list