[llvm-branch-commits] [clang] [llvm] WebAssembly: Respect target-abi module flag (PR #224312)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Sep 17 06:57:53 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-webassembly
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
Previously this relied on the TargetABI MCOptions field and ignored
the IR flag.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/224312.diff
10 Files Affected:
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
- (added) clang/test/CodeGen/WebAssembly/target-abi-module-flag.c (+14)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+4-2)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp (+2-1)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp (+4-3)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h (+7-1)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (+11-6)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h (+2-5)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp (+2-4)
- (added) llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll (+17)
``````````diff
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6fd2c8533eb061..3520e10dcda091 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1518,7 +1518,7 @@ void CodeGenModule::Release() {
// non-empty value.
if (StringRef ABIStr = Target.getABI();
!ABIStr.empty() && (T.isARM() || T.isThumb() || T.isRISCV() ||
- T.isPPC() || T.isLoongArch())) {
+ T.isPPC() || T.isLoongArch() || T.isWasm())) {
getModule().addModuleFlag(llvm::Module::Error, "target-abi",
llvm::MDString::get(VMContext, ABIStr));
}
diff --git a/clang/test/CodeGen/WebAssembly/target-abi-module-flag.c b/clang/test/CodeGen/WebAssembly/target-abi-module-flag.c
new file mode 100644
index 00000000000000..e0de201e7a67a8
--- /dev/null
+++ b/clang/test/CodeGen/WebAssembly/target-abi-module-flag.c
@@ -0,0 +1,14 @@
+// Check that clang emits the "target-abi" module flag for WebAssembly
+
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-abi experimental-mv -emit-llvm -o - %s | FileCheck --check-prefix=MULTIVALUE %s
+// RUN: %clang_cc1 -triple wasm64-unknown-unknown -target-abi experimental-mv -emit-llvm -o - %s | FileCheck --check-prefix=MULTIVALUE %s
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-abi mvp -emit-llvm -o - %s | FileCheck --check-prefix=MVP %s
+
+// No -target-abi: WebAssembly's default ABI is empty, so no flag is emitted.
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -emit-llvm -o - %s | FileCheck --check-prefix=NONE %s
+
+// MULTIVALUE: !{i32 1, !"target-abi", !"experimental-mv"}
+// MVP: !{i32 1, !"target-abi", !"mvp"}
+// NONE-NOT: !"target-abi"
+
+int x;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 6bb03c614af191..c20c6675f970cf 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -225,7 +225,8 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
// module-wide subtarget to compute legal value types.
auto &WasmTM = static_cast<const WebAssemblyTargetMachine &>(TM);
const WebAssemblySubtarget *ST = WasmTM.getSubtargetImpl(
- WasmTM.getTargetCPU(), WasmTM.getTargetFeatureString());
+ WasmTM.getTargetCPU(), WasmTM.getTargetFeatureString(),
+ WasmTM.getTargetABIName(*GV->getParent()) == "experimental-mv");
const WebAssemblyTargetLowering &TLI = *ST->getTargetLowering();
computeLegalValueVTs(TLI, GV->getParent()->getContext(),
GV->getDataLayout(), GlobalVT, VTs);
@@ -612,7 +613,8 @@ void WebAssemblyAsmPrinter::EmitTargetFeatures(Module &M) {
// If we never compiled a single function, Subtarget is null.
if (!Subtarget) {
Subtarget = static_cast<WebAssemblyTargetMachine &>(TM).getSubtargetImpl(
- TM.getTargetCPU(), TM.getTargetFeatureString());
+ TM.getTargetCPU(), TM.getTargetFeatureString(),
+ TM.getTargetABIName(M) == "experimental-mv");
}
for (const SubtargetFeatureKV &KV : Subtarget->getAllProcessorFeatures()) {
EmitFeature(KV.key());
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
index 08479e0f27617f..92eeff4bc477bc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
@@ -177,7 +177,8 @@ static bool coalesceFeaturesAndStripAtomics(Module &M,
// In cooperative threading mode, thread locals are meaningful even without
// atomics.
const WebAssemblySubtarget *ST = WasmTM->getSubtargetImpl(
- WasmTM->getTargetCPU(), WasmTM->getTargetFeatureString());
+ WasmTM->getTargetCPU(), WasmTM->getTargetFeatureString(),
+ WasmTM->getTargetABIName(M) == "experimental-mv");
bool CooperativeThreading = ST->hasCooperativeMultithreading();
if (!Features[WebAssembly::FeatureAtomics]) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp
index 1f964259fd4cad..b16b47ccb5a86e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp
@@ -52,10 +52,11 @@ WebAssemblySubtarget::initializeSubtargetDependencies(StringRef CPU,
WebAssemblySubtarget::WebAssemblySubtarget(const Triple &TT, StringRef CPU,
StringRef FS,
- const TargetMachine &TM)
+ const TargetMachine &TM,
+ bool UsesMultivalueABI)
: WebAssemblyGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
- TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
- TLInfo(TM, *this) {
+ TargetTriple(TT), UsesMultivalueABI(UsesMultivalueABI),
+ InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this) {
CallLoweringInfo.reset(new WebAssemblyCallLowering(*getTargetLowering()));
Legalizer.reset(new WebAssemblyLegalizerInfo(*this));
auto *RBI = new WebAssemblyRegisterBankInfo(*getRegisterInfo());
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
index 149c49dd344731..f9ecf561134f03 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
@@ -63,6 +63,10 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
/// What processor and OS we're targeting.
Triple TargetTriple;
+ /// Whether the multivalue ABI is in use, derived from the "target-abi" module
+ /// flag.
+ bool UsesMultivalueABI = false;
+
WebAssemblyFrameLowering FrameLowering;
WebAssemblyInstrInfo InstrInfo;
WebAssemblySelectionDAGInfo TSInfo;
@@ -80,7 +84,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
/// This constructor initializes the data members to match that
/// of the specified triple.
WebAssemblySubtarget(const Triple &TT, StringRef CPU, StringRef FS,
- const TargetMachine &TM);
+ const TargetMachine &TM, bool UsesMultivalueABI);
const WebAssemblySelectionDAGInfo *getSelectionDAGInfo() const override {
return &TSInfo;
@@ -130,6 +134,8 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
bool hasTailCall() const { return HasTailCall; }
bool hasWideArithmetic() const { return HasWideArithmetic; }
+ bool usesMultivalueABI() const { return UsesMultivalueABI; }
+
/// Parses features string setting specified subtarget options. Definition of
/// function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 066e8329e7f39d..a732049357a7f9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -190,8 +190,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
: CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
getEffectiveRelocModel(RM),
getEffectiveCodeModel(CM, CodeModel::Large), OL),
- TLOF(new WebAssemblyTargetObjectFile()),
- UsesMultivalueABI(Options.MCOptions.getABIName() == "experimental-mv") {
+ TLOF(new WebAssemblyTargetObjectFile()) {
// WebAssembly type-checks instructions, but a noreturn function with a return
// type that doesn't match the context will cause a check failure. So we lower
// LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
@@ -221,10 +220,13 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.
const WebAssemblySubtarget *
-WebAssemblyTargetMachine::getSubtargetImpl(StringRef CPU, StringRef FS) const {
- auto &I = SubtargetMap[CPU.str() + FS.str()];
+WebAssemblyTargetMachine::getSubtargetImpl(StringRef CPU, StringRef FS,
+ bool UsesMultivalueABI) const {
+ auto &I =
+ SubtargetMap[CPU.str() + FS.str() + (UsesMultivalueABI ? "+mv" : "")];
if (!I) {
- I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
+ I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this,
+ UsesMultivalueABI);
}
return I.get();
}
@@ -237,7 +239,10 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
StringRef CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString() : TargetCPU;
StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS;
- return getSubtargetImpl(CPU, FS);
+ bool UsesMultivalueABI =
+ getTargetABIName(*F.getParent()) == "experimental-mv";
+
+ return getSubtargetImpl(CPU, FS, UsesMultivalueABI);
}
namespace {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
index f21dc4b81dda45..cb35cea91de324 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
@@ -33,7 +33,6 @@ extern cl::opt<bool> WasmUseLegacyEH; // Legacy Wasm EH
class WebAssemblyTargetMachine final : public CodeGenTargetMachineImpl {
std::unique_ptr<TargetLoweringObjectFile> TLOF;
mutable StringMap<std::unique_ptr<WebAssemblySubtarget>> SubtargetMap;
- bool UsesMultivalueABI = false;
public:
WebAssemblyTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
@@ -44,8 +43,8 @@ class WebAssemblyTargetMachine final : public CodeGenTargetMachineImpl {
~WebAssemblyTargetMachine() override;
- const WebAssemblySubtarget *getSubtargetImpl(StringRef CPU,
- StringRef FS) const;
+ const WebAssemblySubtarget *getSubtargetImpl(StringRef CPU, StringRef FS,
+ bool UsesMultivalueABI) const;
const WebAssemblySubtarget *
getSubtargetImpl(const Function &F) const override;
@@ -72,8 +71,6 @@ class WebAssemblyTargetMachine final : public CodeGenTargetMachineImpl {
SMDiagnostic &Error,
SMRange &SourceRange) const override;
- bool usesMultivalueABI() const { return UsesMultivalueABI; }
-
void registerPassBuilderCallbacks(PassBuilder &PbB) override;
Error buildCodeGenPipeline(ModulePassManager &MPM, ModuleAnalysisManager &MAM,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
index ac8df67fe7557c..4c0a776e3a750f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
@@ -13,7 +13,7 @@
#include "WebAssemblyUtilities.h"
#include "WebAssemblyMachineFunctionInfo.h"
-#include "WebAssemblyTargetMachine.h"
+#include "WebAssemblySubtarget.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCContext.h"
@@ -185,9 +185,7 @@ unsigned WebAssembly::getCopyOpcodeForRegClass(const TargetRegisterClass *RC) {
bool WebAssembly::canLowerMultivalueReturn(
const WebAssemblySubtarget *Subtarget) {
- const auto &TM = static_cast<const WebAssemblyTargetMachine &>(
- Subtarget->getTargetLowering()->getTargetMachine());
- return Subtarget->hasMultivalue() && TM.usesMultivalueABI();
+ return Subtarget->hasMultivalue() && Subtarget->usesMultivalueABI();
}
bool WebAssembly::canLowerReturn(size_t ResultSize,
diff --git a/llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll b/llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll
new file mode 100644
index 00000000000000..c27e464ef55c56
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll
@@ -0,0 +1,17 @@
+; RUN: llc -mattr=+multivalue < %s | FileCheck %s
+
+; Test that the multivalue ABI can be selected via the "target-abi"
+; module flag
+
+target triple = "wasm32-unknown-unknown"
+
+%pair = type { i32, i64 }
+
+; CHECK-LABEL: pair_const:
+; CHECK-NEXT: .functype pair_const () -> (i32, i64)
+define %pair @pair_const() {
+ ret %pair { i32 42, i64 42 }
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"experimental-mv"}
``````````
</details>
https://github.com/llvm/llvm-project/pull/224312
More information about the llvm-branch-commits
mailing list