https://github.com/Changqing-JING updated https://github.com/llvm/llvm-project/pull/200720
>From 0c49fe895b6c2b04bd8053c14d81c9dd422bac6e Mon Sep 17 00:00:00 2001 From: Changqing Jing <[email protected]> Date: Mon, 1 Jun 2026 13:39:26 +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 ++++++++ .../WebAssembly/WebAssemblyAsmPrinter.cpp | 28 ++++++++++-- .../import-module-global-metadata.ll | 24 ++++++++++ 4 files changed, 112 insertions(+), 4 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/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index edea99e629407..f7942fb15bc19 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); @@ -236,8 +256,7 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) { if (Name == "__stack_pointer" || Name == "__tls_base" || Name == "__memory_base" || Name == "__table_base" || Name == "__tls_size" || Name == "__tls_align") { - bool Mutable = - Name == "__stack_pointer" || Name == "__tls_base"; + bool Mutable = Name == "__stack_pointer" || Name == "__tls_base"; WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); WasmSym->setGlobalType(wasm::WasmGlobalType{ uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64 @@ -477,7 +496,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)); @@ -586,7 +605,8 @@ void WebAssemblyAsmPrinter::EmitFunctionAttributes(Module &M) { // Emit a custom section for each unique attribute. for (const auto &[Name, Symbols] : CustomSections) { MCSectionWasm *CustomSection = OutContext.getWasmSection( - ".custom_section.llvm.func_attr.annotate." + Name, SectionKind::getMetadata()); + ".custom_section.llvm.func_attr.annotate." + Name, + SectionKind::getMetadata()); OutStreamer->pushSection(); OutStreamer->switchSection(CustomSection); 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
