[llvm] d88a7a0 - WebAssembly: Respect target-abi module flag (#224312)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 00:18:20 PDT 2026
Author: Matt Arsenault
Date: 2026-09-23T09:18:14+02:00
New Revision: d88a7a003f0cea42b6233da0447392d15459e192
URL: https://github.com/llvm/llvm-project/commit/d88a7a003f0cea42b6233da0447392d15459e192
DIFF: https://github.com/llvm/llvm-project/commit/d88a7a003f0cea42b6233da0447392d15459e192.diff
LOG: WebAssembly: Respect target-abi module flag (#224312)
Previously this relied on the TargetABI MCOptions field and ignored
the IR flag.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
Added:
clang/test/CodeGen/WebAssembly/target-abi-module-flag.c
llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll
Modified:
clang/lib/CodeGen/CodeGenModule.cpp
llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp
llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 70445dd65ea2b..7274a8588670f 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1534,7 +1534,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 0000000000000..e0de201e7a67a
--- /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 6bb03c614af19..84bab9487f0c8 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()));
const WebAssemblyTargetLowering &TLI = *ST->getTargetLowering();
computeLegalValueVTs(TLI, GV->getParent()->getContext(),
GV->getDataLayout(), GlobalVT, VTs);
@@ -612,7 +613,7 @@ 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));
}
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 08479e0f27617..2cdd7d908994b 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));
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 1f964259fd4ca..ed9473b47e5bd 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,
+ StringRef ABIName)
: WebAssemblyGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
- TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
- TLInfo(TM, *this) {
+ TargetTriple(TT), TargetABI(WebAssembly::getABI(ABIName)),
+ 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 149c49dd34473..4b62f56d7bea7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
@@ -20,6 +20,7 @@
#include "WebAssemblyISelLowering.h"
#include "WebAssemblyInstrInfo.h"
#include "WebAssemblySelectionDAGInfo.h"
+#include "WebAssemblyUtilities.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
@@ -63,6 +64,9 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
/// What processor and OS we're targeting.
Triple TargetTriple;
+ /// The ABI in use.
+ WebAssembly::WebAssemblyABI TargetABI = WebAssembly::WebAssemblyABI::MVP;
+
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, StringRef ABIName);
const WebAssemblySelectionDAGInfo *getSelectionDAGInfo() const override {
return &TSInfo;
@@ -130,6 +134,10 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
bool hasTailCall() const { return HasTailCall; }
bool hasWideArithmetic() const { return HasWideArithmetic; }
+ bool usesMultivalueABI() const {
+ return TargetABI == WebAssembly::WebAssemblyABI::ExperimentalMV;
+ }
+
/// 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 41f628f0c97e0..8363d9c0a53cd 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -173,8 +173,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
: CodeGenTargetMachineImpl(T, 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
@@ -204,10 +203,12 @@ 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,
+ StringRef ABIName) const {
+ auto &I = SubtargetMap[CPU.str() + FS.str() + ABIName.str()];
if (!I) {
- I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
+ I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this,
+ ABIName);
}
return I.get();
}
@@ -220,7 +221,7 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
StringRef CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString() : TargetCPU;
StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS;
- return getSubtargetImpl(CPU, FS);
+ return getSubtargetImpl(CPU, FS, getTargetABIName(*F.getParent()));
}
namespace {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
index d74a218503316..0cced5a8a105d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
@@ -32,7 +32,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,
@@ -43,8 +42,8 @@ class WebAssemblyTargetMachine final : public CodeGenTargetMachineImpl {
~WebAssemblyTargetMachine() override;
- const WebAssemblySubtarget *getSubtargetImpl(StringRef CPU,
- StringRef FS) const;
+ const WebAssemblySubtarget *getSubtargetImpl(StringRef CPU, StringRef FS,
+ StringRef ABIName) const;
const WebAssemblySubtarget *
getSubtargetImpl(const Function &F) const override;
@@ -71,8 +70,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 ac8df67fe7557..4c0a776e3a750 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/lib/Target/WebAssembly/WebAssemblyUtilities.h b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
index 14ef9d142f36e..24eddeb980ae0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.h
@@ -15,6 +15,7 @@
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYUTILITIES_H
#define LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYUTILITIES_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/CommandLine.h"
@@ -35,6 +36,17 @@ class SelectionDAG;
namespace WebAssembly {
+enum class WebAssemblyABI {
+ MVP,
+ ExperimentalMV,
+};
+
+/// Parse an ABI name into the corresponding enum.
+inline WebAssemblyABI getABI(StringRef Name) {
+ return Name == "experimental-mv" ? WebAssemblyABI::ExperimentalMV
+ : WebAssemblyABI::MVP;
+}
+
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI);
bool mayThrow(const MachineInstr &MI);
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 0000000000000..00372ecf73dab
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/multivalue-module-abi.ll
@@ -0,0 +1,32 @@
+; RUN: split-file %s %t
+; RUN: llc -mattr=+multivalue < %t/mv.ll | FileCheck %s --check-prefix=MV
+; RUN: llc -mattr=+multivalue < %t/mvp.ll | FileCheck %s --check-prefix=MVP
+
+; Test that the ABI is selected from the "target-abi" module flag: the
+; multivalue return is lowered directly only for "experimental-mv".
+
+;--- mv.ll
+target triple = "wasm32-unknown-unknown"
+
+%pair = type { i32, i64 }
+
+; MV: .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"}
+
+;--- mvp.ll
+target triple = "wasm32-unknown-unknown"
+
+%pair = type { i32, i64 }
+
+; MVP: .functype pair_const (i32) -> ()
+define %pair @pair_const() {
+ ret %pair { i32 42, i64 42 }
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"mvp"}
More information about the llvm-commits
mailing list