https://github.com/Changqing-JING updated https://github.com/llvm/llvm-project/pull/200722
>From d21d4c1cb0766c4d451169f3c8c10ebc7647296f Mon Sep 17 00:00:00 2001 From: Changqing Jing <[email protected]> Date: Tue, 2 Jun 2026 09:59:07 +0800 Subject: [PATCH] [clang][WebAssembly] support custom module name of import globals --- clang/lib/CodeGen/Targets/WebAssembly.cpp | 45 +++++++++++++++++++ .../WebAssembly/wasm-global-import-module.cpp | 19 ++++++++ llvm/include/llvm/MC/MCSymbolWasm.h | 4 -- .../WebAssembly/WebAssemblyAsmPrinter.cpp | 22 ++++++++- .../import-module-global-metadata.ll | 24 ++++++++++ 5 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp create mode 100644 llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index ebe996a4edd8d..6ba23eff096c1 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -8,10 +8,49 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/DiagnosticFrontend.h" using namespace clang; using namespace clang::CodeGen; +namespace { + +void warnInvalidWebAssemblyImportModuleAnnotation(const AnnotateAttr *AA, + CodeGenModule &CGM) { + CGM.getDiags().Report(AA->getLocation(), diag::warn_fe_backend_unsupported) + << "ignoring 'annotate(\"wasm-import-module\", ...)' because it " + "requires exactly one string literal argument"; +} + +void maybeSetWebAssemblyImportModuleMetadata(const VarDecl *VD, + llvm::GlobalVariable *GV, + CodeGen::CodeGenModule &CGM) { + for (const auto *AA : VD->specific_attrs<AnnotateAttr>()) { + if (AA->getAnnotation() != "wasm-import-module") + continue; + + if (AA->args_size() != 1) { + warnInvalidWebAssemblyImportModuleAnnotation(AA, CGM); + continue; + } + + const auto *Module = dyn_cast<StringLiteral>( + (*AA->args_begin())->IgnoreUnlessSpelledInSource()); + if (!Module) { + warnInvalidWebAssemblyImportModuleAnnotation(AA, CGM); + continue; + } + + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + GV->setMetadata( + "wasm.import.module", + llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, Module->getString()))); + } +} + +} // namespace + //===----------------------------------------------------------------------===// // WebAssembly ABI Implementation // @@ -57,6 +96,12 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); + if (const auto *VD = dyn_cast_or_null<VarDecl>(D)) { + if (auto *Global = dyn_cast<llvm::GlobalVariable>(GV)) + maybeSetWebAssemblyImportModuleMetadata(VD, Global, CGM); + return; + } + if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (const auto *Attr = FD->getAttr<WebAssemblyImportModuleAttr>()) { llvm::Function *Fn = cast<llvm::Function>(GV); diff --git a/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp b/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp new file mode 100644 index 0000000000000..62fe13af9e27a --- /dev/null +++ b/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -verify -o - %s | FileCheck %s + +extern "C" { +extern const int [[clang::address_space(1)]] imported_g + __attribute__((annotate("wasm-import-module", "js"))); +extern const int [[clang::address_space(1)]] bad_arity + __attribute__((annotate("wasm-import-module"))); // expected-warning {{ignoring 'annotate("wasm-import-module", ...)' because it requires exactly one string literal argument}} +extern const int [[clang::address_space(1)]] bad_type + __attribute__((annotate("wasm-import-module", 42))); // expected-warning {{ignoring 'annotate("wasm-import-module", ...)' because it requires exactly one string literal argument}} +extern const int [[clang::address_space(1)]] default_g; + +int get() { return imported_g + bad_arity + bad_type + default_g; } +} + +// CHECK: @imported_g = external addrspace(1) constant i32, align 4, !wasm.import.module ![[MD:[0-9]+]] +// CHECK: @bad_arity = external addrspace(1) constant i32, align 4 +// CHECK: @bad_type = external addrspace(1) constant i32, align 4 +// CHECK: @default_g = external addrspace(1) constant i32, align 4 +// CHECK: ![[MD]] = !{!"js"} \ No newline at end of file diff --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h index 5c9f14e5e6d64..9173aa4bc7a60 100644 --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -92,10 +92,6 @@ class MCSymbolWasm : public MCSymbol { StringRef getImportModule() const { if (ImportModule) return *ImportModule; - // Use a default module name of "env" for now, for compatibility with - // existing tools. - // TODO(sbc): Find a way to specify a default value in the object format - // without picking a hardcoded value like this. return "env"; } void setImportModule(StringRef Name) { ImportModule = Name; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index edea99e629407..7d216531e49f3 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -55,6 +55,18 @@ using namespace llvm; #define DEBUG_TYPE "asm-printer" +static StringRef getWasmImportModuleMetadata(const GlobalVariable &GV) { + MDNode *MD = GV.getMetadata("wasm.import.module"); + if (!MD || MD->getNumOperands() == 0) + return {}; + + auto *Name = dyn_cast<MDString>(MD->getOperand(0)); + if (!Name) + return {}; + + return Name->getString(); +} + extern cl::opt<bool> WasmKeepRegisters; //===----------------------------------------------------------------------===// @@ -211,6 +223,14 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration()); emitSymbolType(Sym); + if (GV->isDeclaration()) { + StringRef ImportModule = getWasmImportModuleMetadata(*GV); + if (!ImportModule.empty()) { + Sym->setImportModule(OutContext.allocateString(ImportModule)); + getTargetStreamer()->emitImportModule(Sym, ImportModule); + } + } + if (GV->hasInitializer()) { assert(getSymbolPreferLocal(*GV) == Sym); emitLinkage(GV, Sym); @@ -477,7 +497,7 @@ void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) { OutStreamer->switchSection(Producers); OutStreamer->emitULEB128IntValue(FieldCount); for (auto &Producers : {std::make_pair("language", &Languages), - std::make_pair("processed-by", &Tools)}) { + std::make_pair("processed-by", &Tools)}) { if (Producers.second->empty()) continue; OutStreamer->emitULEB128IntValue(strlen(Producers.first)); diff --git a/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll b/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll new file mode 100644 index 0000000000000..35691585a7960 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck --check-prefix=ASM %s +; RUN: llc < %s --filetype=obj | obj2yaml | FileCheck --check-prefix=OBJ %s + +target triple = "wasm32-unknown-unknown" + +@imported_g = external addrspace(1) global i32, !wasm.import.module !0 + +define i32 @get() { + %v = load i32, ptr addrspace(1) @imported_g + ret i32 %v +} + +; ASM: .globaltype imported_g, i32 +; ASM-NEXT: .import_module imported_g, "js" + +; OBJ: - Type: IMPORT +; OBJ: Imports: +; OBJ: - Module: js +; OBJ-NEXT: Field: imported_g +; OBJ-NEXT: Kind: GLOBAL +; OBJ-NEXT: GlobalType: I32 +; OBJ-NEXT: GlobalMutable: true + +!0 = !{!"js"} \ No newline at end of file _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
