[clang] [llvm] [SystemZ, Clang] Enable verification of int args extensions by default. (PR #223755)
Jonas Paulsson via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 14 15:58:32 PDT 2026
https://github.com/JonPsson1 updated https://github.com/llvm/llvm-project/pull/223755
>From 2127ac3f7b76e984d613edbb1a03d8ae04838e52 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Tue, 15 Sep 2026 18:34:54 +0200
Subject: [PATCH 01/10] [SystemZ, Clang] Enable verification of integer args
extensions by default.
This has been temporarily disabled behind a CL option with hopes to enable it
by default globally, which unfortunately did not yet seem like a good idea.
At least now the Clang frontend will verify this always, and hopefully more
frontends will enable this over time.
---
clang/lib/CodeGen/BackendUtil.cpp | 1 +
.../CodeGen/SystemZ/systemz-abi-intargs.c | 28 ++++++++++++++
llvm/include/llvm/Target/TargetOptions.h | 7 ++--
.../Target/SystemZ/SystemZISelLowering.cpp | 38 ++++++++++---------
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 1 +
llvm/tools/llc/lib/llcdriver.cpp | 4 --
6 files changed, 53 insertions(+), 26 deletions(-)
create mode 100644 clang/test/CodeGen/SystemZ/systemz-abi-intargs.c
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index f07e4ee84b9b65..19678141651917 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -511,6 +511,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
Options.MCOptions.PPCUseFullRegisterNames =
CodeGenOpts.PPCUseFullRegisterNames;
Options.MisExpect = CodeGenOpts.MisExpect;
+ Options.VerifyArgABICompliance = true;
return true;
}
diff --git a/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c b/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c
new file mode 100644
index 00000000000000..1b9ec7776c02e6
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple s390x-linux-gnu -S -O3 %s -o - \
+// RUN: -mllvm -debug-only=systemz-lower 2>&1 | FileCheck %s
+//
+// REQUIRES: systemz-registered-target, asserts
+//
+// Check that clang verifies the extensions of narrow integer arguments by default.
+
+int __attribute__ ((noinline)) foo(int Arg, unsigned Arg2) {
+ return Arg + Arg2;
+}
+
+int fun(short *Arg, unsigned char *Arg2) {
+ return foo(*Arg, *Arg2);
+}
+
+// CHECK: Return argument verified as ABI compliant : noundef signext i32 @foo(i32 signext, i32 zeroext)
+// CHECK: Outgoing call arguments verified as ABI compliant: noundef signext i32 @foo(i32 signext, i32 zeroext)
+
+// CHECK-LABEL: foo:
+// CHECK: ar %r3, %r2
+// CHECK-NEXT: lgfr %r2, %r3
+// CHECK-NEXT: br %r14
+//
+// CHECK-LABEL: fun:
+// CHECK: lgh %r2, 0(%r2)
+// CHECK-NEXT: llgc %r3, 0(%r3)
+// CHECK-NEXT: jg foo at PLT
+
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 264db07ded991f..0bec4ba6203d30 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -134,7 +134,7 @@ class TargetOptions {
ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
XRayFunctionIndex(true), DebugStrictDwarf(false), JMCInstrument(false),
EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
- VerifyArgABICompliance(true) {}
+ VerifyArgABICompliance(false) {}
/// NoZerosInBSS - By default some codegens place zero-initialized data to
/// .bss section. This flag disables such behaviour (necessary, e.g. for
@@ -291,9 +291,8 @@ class TargetOptions {
unsigned XCOFFReadOnlyPointers : 1;
/// When set to true, call/return argument extensions of narrow integers
- /// are verified in the target backend if it cares about them. This is
- /// not done with internal tools like llc that run many tests that ignore
- /// (lack) these extensions.
+ /// are verified in the target backend if it cares about them. This is off
+ /// by default and enabled explicitly by each front-end separately.
unsigned VerifyArgABICompliance : 1;
/// Name of the stack usage file (i.e., .su file) if user passes
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 1813f9b97ceaa7..c15d8190d130f5 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11490,7 +11490,7 @@ SDValue SystemZTargetLowering::lowerVECREDUCE_ADD(SDValue Op,
DAG.getConstant(OpVT.getVectorNumElements() - 1, DL, MVT::i32));
}
-static void printFunctionArgExts(const Function *F, raw_fd_ostream &OS) {
+static void printFunctionArgExts(const Function *F, raw_ostream &OS) {
FunctionType *FT = F->getFunctionType();
const AttributeList &Attrs = F->getAttributes();
if (Attrs.hasRetAttrs())
@@ -11518,14 +11518,21 @@ bool SystemZTargetLowering::isInternal(const Function *Fn) const {
return Itr->second;
}
+bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
+ if (!Subtarget.isTargetELF())
+ return false;
+
+ if (EnableIntArgExtCheck.getNumOccurrences())
+ return EnableIntArgExtCheck;
+
+ return getTargetMachine().Options.VerifyArgABICompliance;
+}
+
void SystemZTargetLowering::
verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F, SDValue Callee) const {
- // Temporarily only do the check when explicitly requested, until it can be
- // enabled by default.
- if (!EnableIntArgExtCheck)
+ if (!enableNarrowIntArgsVerification())
return;
-
bool IsInternal = false;
const Function *CalleeFn = nullptr;
if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
@@ -11542,37 +11549,32 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
printFunctionArgExts(F, errs());
llvm_unreachable("");
}
+ LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
+ if (CalleeFn != nullptr)
+ printFunctionArgExts(CalleeFn, dbgs());
+ else
+ dbgs() << "-\n";);
}
void SystemZTargetLowering::
verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F) const {
- // Temporarily only do the check when explicitly requested, until it can be
- // enabled by default.
- if (!EnableIntArgExtCheck)
+ if (!enableNarrowIntArgsVerification())
return;
-
if (!isInternal(F) && !verifyNarrowIntegerArgs(Outs)) {
errs() << "ERROR: Missing extension attribute of returned "
<< "value from function:\n";
printFunctionArgExts(F, errs());
llvm_unreachable("");
}
+ LLVM_DEBUG(dbgs() << "Return argument verified as ABI compliant : ";
+ printFunctionArgExts(F, dbgs()));
}
// Verify that narrow integer arguments are extended as required by the ABI.
// Return false if an error is found.
bool SystemZTargetLowering::verifyNarrowIntegerArgs(
const SmallVectorImpl<ISD::OutputArg> &Outs) const {
- if (!Subtarget.isTargetELF())
- return true;
-
- if (EnableIntArgExtCheck.getNumOccurrences()) {
- if (!EnableIntArgExtCheck)
- return true;
- } else if (!getTargetMachine().Options.VerifyArgABICompliance)
- return true;
-
for (unsigned i = 0; i < Outs.size(); ++i) {
MVT VT = Outs[i].VT;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 65463c48f3c4ad..c3f7cee4508a37 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -465,6 +465,7 @@ class SystemZTargetLowering : public TargetLowering {
const TargetRegisterClass *getRepRegClassFor(MVT VT) const override;
private:
+ bool enableNarrowIntArgsVerification() const;
bool isInternal(const Function *Fn) const;
mutable std::map<const Function *, bool> IsInternalCache;
void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
diff --git a/llvm/tools/llc/lib/llcdriver.cpp b/llvm/tools/llc/lib/llcdriver.cpp
index 241c5148bd4ab6..2deda8a93360ac 100644
--- a/llvm/tools/llc/lib/llcdriver.cpp
+++ b/llvm/tools/llc/lib/llcdriver.cpp
@@ -695,10 +695,6 @@ static int compileModule(char **argv, SmallVectorImpl<PassPlugin> &PluginList,
// Return a copy of the output filename via the output param
OutputFilename = Out->outputFilename();
- // Tell target that this tool is not necessarily used with argument ABI
- // compliance (i.e. narrow integer argument extensions).
- Target->Options.VerifyArgABICompliance = 0;
-
std::unique_ptr<ToolOutputFile> DwoOut;
if (!SplitDwarfOutputFile.empty()) {
std::error_code EC;
>From 1935f799e1354e9a44d52864eeb37da4c5f04e59 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <Jonas.Paulsson2 at ibm.com>
Date: Tue, 15 Sep 2026 18:45:36 +0200
Subject: [PATCH 02/10] clang-format
---
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index c15d8190d130f5..45218dbc44897f 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11550,10 +11550,8 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
llvm_unreachable("");
}
LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
- if (CalleeFn != nullptr)
- printFunctionArgExts(CalleeFn, dbgs());
- else
- dbgs() << "-\n";);
+ if (CalleeFn != nullptr) printFunctionArgExts(CalleeFn, dbgs());
+ else dbgs() << "-\n";);
}
void SystemZTargetLowering::
>From 24487784277ec733fa48aec44aacd051c61d2e8b Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Tue, 15 Sep 2026 19:04:55 +0200
Subject: [PATCH 03/10] Skip this if NDEBUG is defined
---
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 45218dbc44897f..c937667a187c1b 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11519,6 +11519,10 @@ bool SystemZTargetLowering::isInternal(const Function *Fn) const {
}
bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
+#ifdef NDEBUG
+ return false;
+#endif
+
if (!Subtarget.isTargetELF())
return false;
>From ddf46d0c7b590d14586ebbc9693c6b108a18bf12 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Wed, 16 Sep 2026 17:15:55 +0200
Subject: [PATCH 04/10] Move down NDEBUG check to respect CL option.
---
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index c937667a187c1b..6451a6e4da189a 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11519,16 +11519,16 @@ bool SystemZTargetLowering::isInternal(const Function *Fn) const {
}
bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
-#ifdef NDEBUG
- return false;
-#endif
-
if (!Subtarget.isTargetELF())
return false;
if (EnableIntArgExtCheck.getNumOccurrences())
return EnableIntArgExtCheck;
+#ifdef NDEBUG
+ return false;
+#endif
+
return getTargetMachine().Options.VerifyArgABICompliance;
}
>From ad54f9ac5dd3e15995f01b422083aaf48f421507 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Fri, 25 Sep 2026 13:28:10 +0200
Subject: [PATCH 05/10] Check for C CallingConv instead of isInternal().
---
.../Target/SystemZ/SystemZISelLowering.cpp | 23 ++++++-------------
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 2 --
llvm/test/CodeGen/SystemZ/args-14.ll | 7 +++---
3 files changed, 10 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 6451a6e4da189a..aea74cc2650c28 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11508,16 +11508,6 @@ static void printFunctionArgExts(const Function *F, raw_ostream &OS) {
OS << ")\n";
}
-bool SystemZTargetLowering::isInternal(const Function *Fn) const {
- std::map<const Function *, bool>::iterator Itr = IsInternalCache.find(Fn);
- if (Itr == IsInternalCache.end())
- Itr = IsInternalCache
- .insert(std::pair<const Function *, bool>(
- Fn, (Fn->hasLocalLinkage() && !Fn->hasAddressTaken())))
- .first;
- return Itr->second;
-}
-
bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
if (!Subtarget.isTargetELF())
return false;
@@ -11537,12 +11527,12 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F, SDValue Callee) const {
if (!enableNarrowIntArgsVerification())
return;
- bool IsInternal = false;
const Function *CalleeFn = nullptr;
if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
- if ((CalleeFn = dyn_cast<Function>(G->getGlobal())))
- IsInternal = isInternal(CalleeFn);
- if (!IsInternal && !verifyNarrowIntegerArgs(Outs)) {
+ CalleeFn = dyn_cast<Function>(G->getGlobal());
+ if (CalleeFn && CalleeFn->getCallingConv() != CallingConv::C)
+ return;
+ if (!verifyNarrowIntegerArgs(Outs)) {
errs() << "ERROR: Missing extension attribute of passed "
<< "value in call to function:\n" << "Callee: ";
if (CalleeFn != nullptr)
@@ -11561,9 +11551,10 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
void SystemZTargetLowering::
verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F) const {
- if (!enableNarrowIntArgsVerification())
+ if (!enableNarrowIntArgsVerification() ||
+ F->getCallingConv() != CallingConv::C)
return;
- if (!isInternal(F) && !verifyNarrowIntegerArgs(Outs)) {
+ if (!verifyNarrowIntegerArgs(Outs)) {
errs() << "ERROR: Missing extension attribute of returned "
<< "value from function:\n";
printFunctionArgExts(F, errs());
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index c3f7cee4508a37..986f8626871b00 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -466,8 +466,6 @@ class SystemZTargetLowering : public TargetLowering {
private:
bool enableNarrowIntArgsVerification() const;
- bool isInternal(const Function *Fn) const;
- mutable std::map<const Function *, bool> IsInternalCache;
void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F, SDValue Callee) const;
void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
diff --git a/llvm/test/CodeGen/SystemZ/args-14.ll b/llvm/test/CodeGen/SystemZ/args-14.ll
index 84e7523e788de4..7948bcc67402b9 100644
--- a/llvm/test/CodeGen/SystemZ/args-14.ll
+++ b/llvm/test/CodeGen/SystemZ/args-14.ll
@@ -27,13 +27,12 @@ define noext i32 @callee_NoExtRet_i32() {
ret i32 -1
}
-; An internal function is not checked for an extension attribute.
-define internal i32 @callee_NoExtRet_internal(i32 %Arg) {
+; Only the C CallingConv strictly requires extension attributes.
+define internal fastcc i32 @callee_NoExtRet_fastcc(i32 %Arg) {
ret i32 %Arg
}
-; A call to an internal function is ok without argument extension.
define void @caller_internal() {
- call i32 @callee_NoExtRet_internal(i32 0)
+ call fastcc i32 @callee_NoExtRet_fastcc(i32 0)
ret void
}
>From e51067c09f503e35d8994ce0a22c7e774cf5fb3d Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Mon, 28 Sep 2026 10:44:34 +0200
Subject: [PATCH 06/10] Patch improved:
- Check for SystemZ C ABI with C CallingConv and "not fully internal".
- In (common) case with a Function prototype, check that if the prototype
argument has ZExt or SExt, then the correpsonding OutputArg should
also have it.
- Check against both ZExt and SExt flags set, which is not impossible to
end up with.
- Also handle vararg and indirect calls.
- More tests added, also reflecting cases where (currently) the ext attribute
found in the prototype is added to the call site (passing test).
---
.../Target/SystemZ/SystemZISelLowering.cpp | 102 +++++++++++++-----
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 13 ++-
llvm/test/CodeGen/SystemZ/args-14.ll | 45 ++++++--
llvm/test/CodeGen/SystemZ/args-15.ll | 4 +-
llvm/test/CodeGen/SystemZ/args-16.ll | 12 ++-
llvm/test/CodeGen/SystemZ/args-17.ll | 4 +-
llvm/test/CodeGen/SystemZ/args-18.ll | 8 +-
llvm/test/CodeGen/SystemZ/args-19.ll | 16 ++-
llvm/test/CodeGen/SystemZ/args-20.ll | 8 +-
.../test/CodeGen/SystemZ/args-21-SExt-ZExt.ll | 19 ++++
.../test/CodeGen/SystemZ/args-21-ZExt-SExt.ll | 19 ++++
llvm/test/CodeGen/SystemZ/args-21.ll | 21 ----
llvm/test/CodeGen/SystemZ/args-24.ll | 95 ++++++++++++++++
llvm/test/CodeGen/SystemZ/args-25.ll | 31 ++++++
llvm/test/CodeGen/SystemZ/args-26.ll | 20 ++++
llvm/test/CodeGen/SystemZ/args-27.ll | 20 ++++
llvm/test/CodeGen/SystemZ/args-28.ll | 20 ++++
llvm/test/CodeGen/SystemZ/args-29.ll | 21 ++++
llvm/test/CodeGen/SystemZ/args-30.ll | 16 +++
19 files changed, 415 insertions(+), 79 deletions(-)
create mode 100644 llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
delete mode 100644 llvm/test/CodeGen/SystemZ/args-21.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-24.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-25.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-26.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-27.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-28.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-29.ll
create mode 100644 llvm/test/CodeGen/SystemZ/args-30.ll
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index aea74cc2650c28..6da70c60d20cc3 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -2391,7 +2391,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
IsTailCall = false;
// Integer args <=32 bits should have an extension attribute.
- verifyNarrowIntegerArgs_Call(Outs, &MF.getFunction(), Callee);
+ verifyNarrowIntegerArgs_Call(CLI, Outs, &MF.getFunction(), Callee);
// Analyze the operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -2650,7 +2650,7 @@ SystemZTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
MachineFunction &MF = DAG.getMachineFunction();
// Integer args <=32 bits should have an extension attribute.
- verifyNarrowIntegerArgs_Ret(Outs, &MF.getFunction());
+ verifyNarrowIntegerArgs_Ret(CallConv, Outs, &MF.getFunction());
// Assign locations to each returned value.
SmallVector<CCValAssign, 16> RetLocs;
@@ -11505,9 +11505,21 @@ static void printFunctionArgExts(const Function *F, raw_ostream &OS) {
if (ArgAttrs.hasAttribute(A))
OS << " " << Attribute::getNameFromAttrKind(A);
}
+ if (F->isVarArg())
+ OS << ", ...";
OS << ")\n";
}
+bool SystemZTargetLowering::isInternal(const Function *Fn) const {
+ std::map<const Function *, bool>::iterator Itr = IsInternalCache.find(Fn);
+ if (Itr == IsInternalCache.end())
+ Itr = IsInternalCache
+ .insert(std::pair<const Function *, bool>(
+ Fn, (Fn->hasLocalLinkage() && !Fn->hasAddressTaken())))
+ .first;
+ return Itr->second;
+}
+
bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
if (!Subtarget.isTargetELF())
return false;
@@ -11522,25 +11534,30 @@ bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
return getTargetMachine().Options.VerifyArgABICompliance;
}
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
- const Function *F, SDValue Callee) const {
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Call(
+ CallLoweringInfo &CLI, const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const Function *F, SDValue Callee) const {
if (!enableNarrowIntArgsVerification())
return;
+ bool IsInternal = false;
const Function *CalleeFn = nullptr;
if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
- CalleeFn = dyn_cast<Function>(G->getGlobal());
- if (CalleeFn && CalleeFn->getCallingConv() != CallingConv::C)
- return;
- if (!verifyNarrowIntegerArgs(Outs)) {
- errs() << "ERROR: Missing extension attribute of passed "
- << "value in call to function:\n" << "Callee: ";
+ if ((CalleeFn = dyn_cast<Function>(G->getGlobal()))) {
+ IsInternal = isInternal(CalleeFn);
+ assert(CalleeFn->getCallingConv() == CLI.CallConv &&
+ "Wrong calling convention used.");
+ }
+ bool C_ABI = CLI.CallConv == CallingConv::C && !IsInternal;
+ if (!verifyNarrowIntegerArgs(C_ABI, Outs, CalleeFn, /*IsRet=*/false)) {
+ errs() << "Callee: ";
if (CalleeFn != nullptr)
printFunctionArgExts(CalleeFn, errs());
else
errs() << "-\n";
- errs() << "Caller: ";
+ errs() << "Caller: ";
printFunctionArgExts(F, errs());
+ if (CLI.CB)
+ errs() << " " << *CLI.CB;
llvm_unreachable("");
}
LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
@@ -11548,15 +11565,14 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
else dbgs() << "-\n";);
}
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
- const Function *F) const {
- if (!enableNarrowIntArgsVerification() ||
- F->getCallingConv() != CallingConv::C)
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Ret(
+ CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const Function *F) const {
+ if (!enableNarrowIntArgsVerification())
return;
- if (!verifyNarrowIntegerArgs(Outs)) {
- errs() << "ERROR: Missing extension attribute of returned "
- << "value from function:\n";
+ bool C_ABI = CallConv == CallingConv::C && !isInternal(F);
+ if (!verifyNarrowIntegerArgs(C_ABI, Outs, F, /*IsRet=*/true)) {
+ errs() << "Returning from function: ";
printFunctionArgExts(F, errs());
llvm_unreachable("");
}
@@ -11564,19 +11580,47 @@ verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
printFunctionArgExts(F, dbgs()));
}
-// Verify that narrow integer arguments are extended as required by the ABI.
-// Return false if an error is found.
+// Verify that narrow integer arguments are extended according to the
+// function header (calllee for a call, containing function for a ret).
+// If C_ABI is true, an extension attribute must be present.
bool SystemZTargetLowering::verifyNarrowIntegerArgs(
- const SmallVectorImpl<ISD::OutputArg> &Outs) const {
+ bool C_ABI, const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const Function *FunHeader, bool IsRet) const {
for (unsigned i = 0; i < Outs.size(); ++i) {
- MVT VT = Outs[i].VT;
+ EVT OrigArgVT = Outs[i].ArgVT;
+ if (!OrigArgVT.isInteger() || OrigArgVT.getSizeInBits() >= 64)
+ continue;
+ assert(Outs[i].VT == MVT::i32 && "Unexpected integer argument VT.");
ISD::ArgFlagsTy Flags = Outs[i].Flags;
- if (VT.isInteger()) {
- assert((VT == MVT::i32 || VT.getSizeInBits() >= 64) &&
- "Unexpected integer argument VT.");
- if (VT == MVT::i32 &&
- !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt())
+ unsigned OrigIdx = Outs[i].OrigArgIndex;
+
+ // Per the C ABI there must be an extension.
+ if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
+ errs() << "ERROR: (C ABI violiation) missing extension attribute on arg "
+ << OrigIdx << ".\n";
+ return false;
+ }
+
+ // Flags should reflect the attributes of the function header.
+ if (FunHeader) {
+ const AttributeList &FunAttrs = FunHeader->getAttributes();
+ const AttributeSet Attrs =
+ IsRet ? FunAttrs.getRetAttrs() : FunAttrs.getParamAttrs(OrigIdx);
+ if (Attrs.hasAttribute(Attribute::SExt) && !Flags.isSExt()) {
+ errs() << "ERROR : Missing SExt on arg " << OrigIdx << ".\n";
+ return false;
+ }
+ if (Attrs.hasAttribute(Attribute::ZExt) && !Flags.isZExt()) {
+ errs() << "ERROR : Missing ZExt on arg " << OrigIdx << ".\n";
return false;
+ }
+ }
+
+ // Flags should not end up with both kinds of extensions.
+ if (Flags.isSExt() && Flags.isZExt()) {
+ errs() << "ERROR : SExt and ZExt are incompatible (arg " << OrigIdx
+ << ").\n";
+ return false;
}
}
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 986f8626871b00..e1dc04615954fb 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -466,12 +466,17 @@ class SystemZTargetLowering : public TargetLowering {
private:
bool enableNarrowIntArgsVerification() const;
- void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
+ bool isInternal(const Function *Fn) const;
+ mutable std::map<const Function *, bool> IsInternalCache;
+ void verifyNarrowIntegerArgs_Call(CallLoweringInfo &CLI,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F, SDValue Callee) const;
- void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
+ void verifyNarrowIntegerArgs_Ret(CallingConv::ID CallConv,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *F) const;
- bool
- verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs) const;
+ bool verifyNarrowIntegerArgs(bool C_ABI,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const Function *FunHeader, bool IsRet) const;
public:
};
diff --git a/llvm/test/CodeGen/SystemZ/args-14.ll b/llvm/test/CodeGen/SystemZ/args-14.ll
index 7948bcc67402b9..c1b4930009c0b6 100644
--- a/llvm/test/CodeGen/SystemZ/args-14.ll
+++ b/llvm/test/CodeGen/SystemZ/args-14.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
; Test that it works to pass structs as outgoing call arguments when the
; NoExt attribute is given, either in the call instruction or in the
@@ -7,32 +8,60 @@ define void @caller() {
call void @bar_Struct_32(i32 noext 123)
call void @bar_Struct_16(i16 123)
call void @bar_Struct_8(i8 noext 123)
+ call void @bar_Struct_32_addrtaken(i32 noext 123)
ret void
}
declare void @bar_Struct_32(i32 %Arg)
declare void @bar_Struct_16(i16 noext %Arg)
declare void @bar_Struct_8(i8 %Arg)
+define internal void @bar_Struct_32_addrtaken(i32 noext %Arg) {
+ ret void
+}
; Test that it works to return values with the NoExt attribute.
-define noext i8 @callee_NoExtRet_i8() {
+define noext i8 @fun_NoExtRet_i8() {
ret i8 -1
}
-define noext i16 @callee_NoExtRet_i16() {
+define noext i16 @fun_NoExtRet_i16() {
ret i16 -1
}
-define noext i32 @callee_NoExtRet_i32() {
+define noext i32 @fun_NoExtRet_i32() {
+ ret i32 -1
+}
+
+define internal noext i32 @fun_NoExtRet_i32_addrtaken() {
ret i32 -1
}
-; Only the C CallingConv strictly requires extension attributes.
-define internal fastcc i32 @callee_NoExtRet_fastcc(i32 %Arg) {
- ret i32 %Arg
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+ call void @ExtFun(ptr @bar_Struct_32_addrtaken)
+ call void @ExtFun(ptr @fun_NoExtRet_i32_addrtaken)
+ ret void
+}
+
+; A function that is internal or has a non-C ABI is not checked for an
+; extension attribute.
+define void @caller_non_C_abi(ptr %fptr) {
+ call void @foo_internal(i32 0)
+ call fastcc void @foo_fastcc(i32 0)
+ call fastcc void %fptr(i32 0)
+ ret void
}
-define void @caller_internal() {
- call fastcc i32 @callee_NoExtRet_fastcc(i32 0)
+define internal void @foo_internal(i32 %Arg) {
ret void
}
+
+declare fastcc void @foo_fastcc(i32 %Arg)
+
+define internal i8 @fun_NoRetAttr_internal() {
+ ret i8 -1
+}
+
+define fastcc i8 @fun_NoRetAttr_fastcc() {
+ ret i8 -1
+}
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll b/llvm/test/CodeGen/SystemZ/args-15.ll
index 64217a2a29a6f9..6021a42c226a6b 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
ret i32 -1
}
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i32 @callee_MissingRetAttr()
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i32 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll b/llvm/test/CodeGen/SystemZ/args-16.ll
index 846100146e7908..ae75c00c7fd424 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -4,11 +4,17 @@
;
; Test detection of missing extension of an i16 return value.
-define i16 @callee_MissingRetAttr() {
+define internal i16 @callee_MissingRetAttr() {
ret i16 -1
}
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i16 @callee_MissingRetAttr()
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+ call void @ExtFun(ptr @callee_MissingRetAttr)
+ ret void
+}
+
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i16 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll b/llvm/test/CodeGen/SystemZ/args-17.ll
index 4231d7e9e4772d..58a42c71fd1bc0 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
ret i8 -1
}
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i8 @callee_MissingRetAttr()
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i8 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll b/llvm/test/CodeGen/SystemZ/args-18.ll
index bd368fa056c6c9..8e828c0849d69d 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,6 +11,8 @@ define void @caller() {
declare void @bar_Struct(i32 %Arg)
-; CHECK: ERROR: Missing extension attribute of passed value in call to function:
-; CHECK: Callee: void @bar_Struct(i32)
-; CHECK: Caller: void @caller()
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i32)
+; CHECK: Caller: void @caller()
+; CHECK: call void @bar_Struct(i32 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll b/llvm/test/CodeGen/SystemZ/args-19.ll
index 8b5f421f59fdd8..48efda164ba6ec 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -9,8 +9,16 @@ define void @caller() {
ret void
}
-declare void @bar_Struct(i16 %Arg)
+define internal void @bar_Struct(i16 %Arg) { ret void }
-; CHECK: ERROR: Missing extension attribute of passed value in call to function:
-; CHECK: Callee: void @bar_Struct(i16)
-; CHECK: Caller: void @caller()
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+ call void @ExtFun(ptr @bar_Struct)
+ ret void
+}
+
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i16)
+; CHECK: Caller: void @caller()
+; CHECK: call void @bar_Struct(i16 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll b/llvm/test/CodeGen/SystemZ/args-20.ll
index ed6f2e52bf6ee9..9868a2c256bc7c 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,6 +11,8 @@ define void @caller() {
declare void @bar_Struct(i8 %Arg)
-; CHECK: ERROR: Missing extension attribute of passed value in call to function:
-; CHECK: Callee: void @bar_Struct(i8)
-; CHECK: Caller: void @caller()
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i8)
+; CHECK: Caller: void @caller()
+; CHECK: call void @bar_Struct(i8 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
new file mode 100644
index 00000000000000..8ab28218b96d18
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
@@ -0,0 +1,19 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test detection of a call making the wrong kind of extension.
+
+define i64 @fun(i32 signext %Arg) {
+ %S = sext i32 %Arg to i64
+ ret i64 %S
+}
+
+define i64 @foo(i32 %Arg) {
+ %res = call i64 @fun(i32 zeroext %Arg)
+ ret i64 %res
+}
+
+; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
+; CHECK: Callee: i64 @fun(i32 signext)
+; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
new file mode 100644
index 00000000000000..ce24e4e7b64b18
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
@@ -0,0 +1,19 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test detection of a call making the wrong kind of extension.
+
+define internal i64 @fun(i32 zeroext %Arg) {
+ %S = zext i32 %Arg to i64
+ ret i64 %S
+}
+
+define i64 @foo(i32 %Arg) {
+ %res = call i64 @fun(i32 signext %Arg)
+ ret i64 %res
+}
+
+; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
+; CHECK: Callee: i64 @fun(i32 zeroext)
+; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll b/llvm/test/CodeGen/SystemZ/args-21.ll
deleted file mode 100644
index da5c8fe5ffc7fc..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ /dev/null
@@ -1,21 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN: | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of missing extension involving an internal function which is
-; passed as a function pointer to an external function.
-
-define internal i32 @bar(i32 %Arg) {
- ret i32 %Arg
-}
-
-declare void @ExtFun(ptr %FunPtr);
-
-define void @foo() {
- call void @ExtFun(ptr @bar)
- ret void
-}
-
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i32 @bar(i32)
-; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-24.ll b/llvm/test/CodeGen/SystemZ/args-24.ll
new file mode 100644
index 00000000000000..44e3593ad5b056
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-24.ll
@@ -0,0 +1,95 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
+;
+; The parameter attributes should match between the call and Function
+; declaration as seen by the instruction selector. One of the attributes
+; should be present with a normal C-ABI call, but internal/non-C calls can
+; also omit the attribute. This seems to work so that the call gets the
+; sign/zero extension attribute if the callee prototype has it even if it was
+; omitted on the call IR instruction.
+
+define void @caller(i32 %Arg32) {
+ ; C Calling Convention
+ call void @bar_should_NoExt(i32 %Arg32)
+ call void @bar_should_NoExt(i32 noext %Arg32)
+ call void @bar_should_NoExt(i32 signext %Arg32)
+ call void @bar_should_NoExt(i32 zeroext %Arg32)
+ call void @bar_should_SExt(i32 %Arg32)
+ call void @bar_should_SExt(i32 noext %Arg32)
+ call void @bar_should_SExt(i32 signext %Arg32)
+ call void @bar_should_ZExt(i32 %Arg32)
+ call void @bar_should_ZExt(i32 noext %Arg32)
+ call void @bar_should_ZExt(i32 zeroext %Arg32)
+
+ ; Internal callee but address taken.
+ call void @bar_should_NoExt_addrtaken(i32 %Arg32)
+ call void @bar_should_NoExt_addrtaken(i32 noext %Arg32)
+ call void @bar_should_NoExt_addrtaken(i32 signext %Arg32)
+ call void @bar_should_NoExt_addrtaken(i32 zeroext %Arg32)
+ call void @bar_should_SExt_addrtaken(i32 %Arg32)
+ call void @bar_should_SExt_addrtaken(i32 noext %Arg32)
+ call void @bar_should_SExt_addrtaken(i32 signext %Arg32)
+ call void @bar_should_ZExt_addrtaken(i32 %Arg32)
+ call void @bar_should_ZExt_addrtaken(i32 noext %Arg32)
+ call void @bar_should_ZExt_addrtaken(i32 zeroext %Arg32)
+
+ ; Internal callee: No extension is ok.
+ call void @bar_internal(i32 %Arg32)
+ call void @bar_internal(i32 noext %Arg32)
+ call void @bar_internal(i32 signext %Arg32)
+ call void @bar_internal(i32 zeroext %Arg32)
+ call void @bar_should_NoExt_internal(i32 %Arg32)
+ call void @bar_should_NoExt_internal(i32 noext %Arg32)
+ call void @bar_should_NoExt_internal(i32 signext %Arg32)
+ call void @bar_should_NoExt_internal(i32 zeroext %Arg32)
+ call void @bar_should_SExt_internal(i32 %Arg32)
+ call void @bar_should_SExt_internal(i32 noext %Arg32)
+ call void @bar_should_SExt_internal(i32 signext %Arg32)
+ call void @bar_should_ZExt_internal(i32 %Arg32)
+ call void @bar_should_ZExt_internal(i32 noext %Arg32)
+ call void @bar_should_ZExt_internal(i32 zeroext %Arg32)
+
+ ; Same with a fastcc: No extension is ok.
+ call fastcc void @bar_fastcc(i32 %Arg32)
+ call fastcc void @bar_fastcc(i32 noext %Arg32)
+ call fastcc void @bar_fastcc(i32 signext %Arg32)
+ call fastcc void @bar_fastcc(i32 zeroext %Arg32)
+ call fastcc void @bar_should_NoExt_fastcc(i32 %Arg32)
+ call fastcc void @bar_should_NoExt_fastcc(i32 noext %Arg32)
+ call fastcc void @bar_should_NoExt_fastcc(i32 signext %Arg32)
+ call fastcc void @bar_should_NoExt_fastcc(i32 zeroext %Arg32)
+ call fastcc void @bar_should_SExt_fastcc(i32 %Arg32)
+ call fastcc void @bar_should_SExt_fastcc(i32 noext %Arg32)
+ call fastcc void @bar_should_SExt_fastcc(i32 signext %Arg32)
+ call fastcc void @bar_should_ZExt_fastcc(i32 %Arg32)
+ call fastcc void @bar_should_ZExt_fastcc(i32 noext %Arg32)
+ call fastcc void @bar_should_ZExt_fastcc(i32 zeroext %Arg32)
+
+ ret void
+}
+
+declare void @bar_should_NoExt(i32 noext %Arg32)
+declare void @bar_should_SExt(i32 signext %Arg32)
+declare void @bar_should_ZExt(i32 zeroext %Arg32)
+
+define internal void @bar_should_NoExt_addrtaken(i32 noext %Arg32) { ret void }
+define internal void @bar_should_SExt_addrtaken(i32 signext %Arg32) { ret void }
+define internal void @bar_should_ZExt_addrtaken(i32 zeroext %Arg32) { ret void }
+
+define internal void @bar_internal(i32 %Arg32) { ret void }
+define internal void @bar_should_NoExt_internal(i32 noext %Arg32) { ret void }
+define internal void @bar_should_SExt_internal(i32 signext %Arg32) { ret void }
+define internal void @bar_should_ZExt_internal(i32 zeroext %Arg32) { ret void }
+
+declare fastcc void @bar_fastcc(i32 %Arg32)
+declare fastcc void @bar_should_NoExt_fastcc(i32 noext %Arg32)
+declare fastcc void @bar_should_SExt_fastcc(i32 signext %Arg32)
+declare fastcc void @bar_should_ZExt_fastcc(i32 zeroext %Arg32)
+
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+ call void @ExtFun(ptr @bar_should_NoExt_addrtaken)
+ call void @ExtFun(ptr @bar_should_SExt_addrtaken)
+ call void @ExtFun(ptr @bar_should_ZExt_addrtaken)
+ ret void
+}
diff --git a/llvm/test/CodeGen/SystemZ/args-25.ll b/llvm/test/CodeGen/SystemZ/args-25.ll
new file mode 100644
index 00000000000000..ab5351ff3ebfe1
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-25.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
+;
+; Test that the lowering of returns as seen by the instruction selector works
+; in accordance to the function header.
+
+define noext i32 @fun_NoExtRet_ccc() { ret i32 0 }
+define signext i32 @fun_SignExtRet_ccc() { ret i32 0 }
+define zeroext i32 @fun_ZeroExtRet_ccc() { ret i32 0 }
+
+define internal noext i32 @fun_NoExtRet_addrtaken() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_addrtaken() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_addrtaken() { ret i32 0 }
+
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+ call void @ExtFun(ptr @fun_NoExtRet_addrtaken)
+ call void @ExtFun(ptr @fun_SignExtRet_addrtaken)
+ call void @ExtFun(ptr @fun_ZeroExtRet_addrtaken)
+ ret void
+}
+
+define internal i32 @fun_internal() { ret i32 0 }
+define internal noext i32 @fun_NoExtRet_internal() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_internal() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_internal() { ret i32 0 }
+
+define fastcc i32 @fun_fastcc() { ret i32 0 }
+define internal noext i32 @fun_NoExtRet_fastcc() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_fastcc() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_fastcc() { ret i32 0 }
diff --git a/llvm/test/CodeGen/SystemZ/args-26.ll b/llvm/test/CodeGen/SystemZ/args-26.ll
new file mode 100644
index 00000000000000..e78a020bd184af
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-26.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with wrong extension type on a fixed argument.
+
+define i64 @caller(i32 %Arg) {
+ %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
+ ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+ %S = zext i32 %Arg to i64
+ ret i64 %S
+}
+
+; CHECK: ERROR : Missing ZExt on arg 0.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK: %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll b/llvm/test/CodeGen/SystemZ/args-27.ll
new file mode 100644
index 00000000000000..e37b2ad3e96aa9
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with missing extension type on a fixed argument.
+
+define i64 @caller(i32 %Arg) {
+ %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
+ ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+ %S = zext i32 %Arg to i64
+ ret i64 %S
+}
+
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK: %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll b/llvm/test/CodeGen/SystemZ/args-28.ll
new file mode 100644
index 00000000000000..128f993624fb50
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with missing extension type on a vararg.
+
+define i64 @caller(i32 %Arg) {
+ %res = call i64 @bar(i32 zeroext %Arg, i32 0)
+ ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+ %S = zext i32 %Arg to i64
+ ret i64 %S
+}
+
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 1.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK: %res = call i64 @bar(i32 zeroext %Arg, i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-29.ll b/llvm/test/CodeGen/SystemZ/args-29.ll
new file mode 100644
index 00000000000000..f164ec34e3d622
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-29.ll
@@ -0,0 +1,21 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with the wrong extension kind on an argument, and also
+; test that the split i128 arg (z10) does not mess things up.
+
+define i64 @caller(i32 %Arg) {
+ %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+ ret i64 %res
+}
+
+define i64 @bar(i32 noext %A0, i128 %A1, i32 zeroext %A2, ...) {
+ %S = zext i32 %A2 to i64
+ ret i64 %S
+}
+
+; CHECK: ERROR : Missing ZExt on arg 2.
+; CHECK: Callee: i64 @bar(i32 noext, i128, i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK: %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
diff --git a/llvm/test/CodeGen/SystemZ/args-30.ll b/llvm/test/CodeGen/SystemZ/args-30.ll
new file mode 100644
index 00000000000000..c9949e4282c2ac
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-30.ll
@@ -0,0 +1,16 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN: | FileCheck %s
+; REQUIRES: asserts
+;
+; Test an indirect call: even without the function prototype we can check that
+; a C ABI call has some kind of extension.
+
+define void @caller(ptr %fptr) {
+ call void %fptr(i32 0)
+ ret void
+}
+
+; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: -
+; CHECK: Caller: void @caller(ptr)
+; CHECK: call void %fptr(i32 0)
>From 9877f2aa2dda43abb040544cf62b5093af7f30ba Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Fri, 9 Oct 2026 18:59:44 +0200
Subject: [PATCH 07/10] Remove check against SExt+ZExt for now.
---
.../Target/SystemZ/SystemZISelLowering.cpp | 7 -------
.../test/CodeGen/SystemZ/args-21-SExt-ZExt.ll | 19 -------------------
.../test/CodeGen/SystemZ/args-21-ZExt-SExt.ll | 19 -------------------
3 files changed, 45 deletions(-)
delete mode 100644 llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
delete mode 100644 llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 6da70c60d20cc3..986831da3e2d7a 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11615,13 +11615,6 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
return false;
}
}
-
- // Flags should not end up with both kinds of extensions.
- if (Flags.isSExt() && Flags.isZExt()) {
- errs() << "ERROR : SExt and ZExt are incompatible (arg " << OrigIdx
- << ").\n";
- return false;
- }
}
return true;
diff --git a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
deleted file mode 100644
index 8ab28218b96d18..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN: | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of a call making the wrong kind of extension.
-
-define i64 @fun(i32 signext %Arg) {
- %S = sext i32 %Arg to i64
- ret i64 %S
-}
-
-define i64 @foo(i32 %Arg) {
- %res = call i64 @fun(i32 zeroext %Arg)
- ret i64 %res
-}
-
-; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
-; CHECK: Callee: i64 @fun(i32 signext)
-; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
deleted file mode 100644
index ce24e4e7b64b18..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN: | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of a call making the wrong kind of extension.
-
-define internal i64 @fun(i32 zeroext %Arg) {
- %S = zext i32 %Arg to i64
- ret i64 %S
-}
-
-define i64 @foo(i32 %Arg) {
- %res = call i64 @fun(i32 signext %Arg)
- ret i64 %res
-}
-
-; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
-; CHECK: Callee: i64 @fun(i32 zeroext)
-; CHECK: Caller: i64 @foo(i32)
>From 0a4507724823449ffa16952d39b5137067cf022f Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <Jonas.Paulsson2 at ibm.com>
Date: Fri, 9 Oct 2026 16:32:59 -0700
Subject: [PATCH 08/10] Rename test.
---
llvm/test/CodeGen/SystemZ/{args-30.ll => args-21.ll} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename llvm/test/CodeGen/SystemZ/{args-30.ll => args-21.ll} (100%)
diff --git a/llvm/test/CodeGen/SystemZ/args-30.ll b/llvm/test/CodeGen/SystemZ/args-21.ll
similarity index 100%
rename from llvm/test/CodeGen/SystemZ/args-30.ll
rename to llvm/test/CodeGen/SystemZ/args-21.ll
>From ba7f6628ff2be0e581c80635af8aa2f52b0a0721 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Tue, 13 Oct 2026 23:26:50 +0200
Subject: [PATCH 09/10] Updated per review.
---
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 10 +++++-----
llvm/test/CodeGen/SystemZ/args-15.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-16.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-17.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-18.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-19.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-20.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-21.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-27.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-28.ll | 2 +-
10 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 986831da3e2d7a..9521f879f433a4 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11542,11 +11542,8 @@ void SystemZTargetLowering::verifyNarrowIntegerArgs_Call(
bool IsInternal = false;
const Function *CalleeFn = nullptr;
if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
- if ((CalleeFn = dyn_cast<Function>(G->getGlobal()))) {
+ if ((CalleeFn = dyn_cast<Function>(G->getGlobal())))
IsInternal = isInternal(CalleeFn);
- assert(CalleeFn->getCallingConv() == CLI.CallConv &&
- "Wrong calling convention used.");
- }
bool C_ABI = CLI.CallConv == CallingConv::C && !IsInternal;
if (!verifyNarrowIntegerArgs(C_ABI, Outs, CalleeFn, /*IsRet=*/false)) {
errs() << "Callee: ";
@@ -11586,6 +11583,9 @@ void SystemZTargetLowering::verifyNarrowIntegerArgs_Ret(
bool SystemZTargetLowering::verifyNarrowIntegerArgs(
bool C_ABI, const SmallVectorImpl<ISD::OutputArg> &Outs,
const Function *FunHeader, bool IsRet) const {
+ if (IsRet && Outs.size() != 1)
+ return true;
+
for (unsigned i = 0; i < Outs.size(); ++i) {
EVT OrigArgVT = Outs[i].ArgVT;
if (!OrigArgVT.isInteger() || OrigArgVT.getSizeInBits() >= 64)
@@ -11596,7 +11596,7 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
// Per the C ABI there must be an extension.
if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
- errs() << "ERROR: (C ABI violiation) missing extension attribute on arg "
+ errs() << "ERROR: (C ABI violation) missing extension attribute on arg "
<< OrigIdx << ".\n";
return false;
}
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll b/llvm/test/CodeGen/SystemZ/args-15.ll
index 6021a42c226a6b..89273057b3345a 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
ret i32 -1
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Returning from function: i32 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll b/llvm/test/CodeGen/SystemZ/args-16.ll
index ae75c00c7fd424..bbc15904aaff16 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -14,7 +14,7 @@ define void @foo() {
ret void
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Returning from function: i16 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll b/llvm/test/CodeGen/SystemZ/args-17.ll
index 58a42c71fd1bc0..69b913ca34b531 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
ret i8 -1
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Returning from function: i8 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll b/llvm/test/CodeGen/SystemZ/args-18.ll
index 8e828c0849d69d..070f63b3da2ed4 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,7 +11,7 @@ define void @caller() {
declare void @bar_Struct(i32 %Arg)
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i32)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i32 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll b/llvm/test/CodeGen/SystemZ/args-19.ll
index 48efda164ba6ec..2c666336c44114 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -17,7 +17,7 @@ define void @foo() {
ret void
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i16)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i16 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll b/llvm/test/CodeGen/SystemZ/args-20.ll
index 9868a2c256bc7c..a7d0f333530eb5 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,7 +11,7 @@ define void @caller() {
declare void @bar_Struct(i8 %Arg)
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i8)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i8 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll b/llvm/test/CodeGen/SystemZ/args-21.ll
index c9949e4282c2ac..a5cc0cb8afeff6 100644
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ b/llvm/test/CodeGen/SystemZ/args-21.ll
@@ -10,7 +10,7 @@ define void @caller(ptr %fptr) {
ret void
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: -
; CHECK: Caller: void @caller(ptr)
; CHECK: call void %fptr(i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll b/llvm/test/CodeGen/SystemZ/args-27.ll
index e37b2ad3e96aa9..2a1b83a570ada7 100644
--- a/llvm/test/CodeGen/SystemZ/args-27.ll
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
ret i64 %S
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: i64 @bar(i32 zeroext, ...)
; CHECK: Caller: i64 @caller(i32)
; CHECK: %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll b/llvm/test/CodeGen/SystemZ/args-28.ll
index 128f993624fb50..8cf803effc5f58 100644
--- a/llvm/test/CodeGen/SystemZ/args-28.ll
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
ret i64 %S
}
-; CHECK: ERROR: (C ABI violiation) missing extension attribute on arg 1.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 1.
; CHECK: Callee: i64 @bar(i32 zeroext, ...)
; CHECK: Caller: i64 @caller(i32)
; CHECK: %res = call i64 @bar(i32 zeroext %Arg, i32 0)
>From 0c7b3e7ec0eb23132e4562e9478fd609e99af168 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Wed, 14 Oct 2026 20:13:10 +0200
Subject: [PATCH 10/10] Fix diagnostic messages.
---
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 9 +++++----
llvm/test/CodeGen/SystemZ/args-15.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-16.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-17.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-18.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-19.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-20.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-21.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-26.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-27.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-28.ll | 2 +-
llvm/test/CodeGen/SystemZ/args-29.ll | 10 +++++-----
12 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 9521f879f433a4..dc0f412cccbd32 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11596,8 +11596,9 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
// Per the C ABI there must be an extension.
if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
- errs() << "ERROR: (C ABI violation) missing extension attribute on arg "
- << OrigIdx << ".\n";
+ errs() << "ERROR: (C ABI violation) missing extension attribute on "
+ << (IsRet ? "return value" : Twine("arg ") + Twine(OrigIdx))
+ << ".\n";
return false;
}
@@ -11607,11 +11608,11 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
const AttributeSet Attrs =
IsRet ? FunAttrs.getRetAttrs() : FunAttrs.getParamAttrs(OrigIdx);
if (Attrs.hasAttribute(Attribute::SExt) && !Flags.isSExt()) {
- errs() << "ERROR : Missing SExt on arg " << OrigIdx << ".\n";
+ errs() << "ERROR: Missing SExt on arg " << OrigIdx << ".\n";
return false;
}
if (Attrs.hasAttribute(Attribute::ZExt) && !Flags.isZExt()) {
- errs() << "ERROR : Missing ZExt on arg " << OrigIdx << ".\n";
+ errs() << "ERROR: Missing ZExt on arg " << OrigIdx << ".\n";
return false;
}
}
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll b/llvm/test/CodeGen/SystemZ/args-15.ll
index 89273057b3345a..6e69f9ef5ac813 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
ret i32 -1
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
; CHECK: Returning from function: i32 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll b/llvm/test/CodeGen/SystemZ/args-16.ll
index bbc15904aaff16..c2c4e88a3bfcd9 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -14,7 +14,7 @@ define void @foo() {
ret void
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
; CHECK: Returning from function: i16 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll b/llvm/test/CodeGen/SystemZ/args-17.ll
index 69b913ca34b531..e0759f126ee528 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
ret i8 -1
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
; CHECK: Returning from function: i8 @callee_MissingRetAttr()
; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll b/llvm/test/CodeGen/SystemZ/args-18.ll
index 070f63b3da2ed4..f166130121d6a9 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,7 +11,7 @@ define void @caller() {
declare void @bar_Struct(i32 %Arg)
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i32)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i32 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll b/llvm/test/CodeGen/SystemZ/args-19.ll
index 2c666336c44114..7f1ac319700761 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -17,7 +17,7 @@ define void @foo() {
ret void
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i16)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i16 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll b/llvm/test/CodeGen/SystemZ/args-20.ll
index a7d0f333530eb5..fa631f535d1d5d 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,7 +11,7 @@ define void @caller() {
declare void @bar_Struct(i8 %Arg)
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: void @bar_Struct(i8)
; CHECK: Caller: void @caller()
; CHECK: call void @bar_Struct(i8 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll b/llvm/test/CodeGen/SystemZ/args-21.ll
index a5cc0cb8afeff6..c4892dc420fd07 100644
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ b/llvm/test/CodeGen/SystemZ/args-21.ll
@@ -10,7 +10,7 @@ define void @caller(ptr %fptr) {
ret void
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: -
; CHECK: Caller: void @caller(ptr)
; CHECK: call void %fptr(i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-26.ll b/llvm/test/CodeGen/SystemZ/args-26.ll
index e78a020bd184af..31b35413c2fe0d 100644
--- a/llvm/test/CodeGen/SystemZ/args-26.ll
+++ b/llvm/test/CodeGen/SystemZ/args-26.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
ret i64 %S
}
-; CHECK: ERROR : Missing ZExt on arg 0.
+; CHECK: ERROR: Missing ZExt on arg 0.
; CHECK: Callee: i64 @bar(i32 zeroext, ...)
; CHECK: Caller: i64 @caller(i32)
; CHECK: %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll b/llvm/test/CodeGen/SystemZ/args-27.ll
index 2a1b83a570ada7..78ea8f53054f88 100644
--- a/llvm/test/CodeGen/SystemZ/args-27.ll
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
ret i64 %S
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
; CHECK: Callee: i64 @bar(i32 zeroext, ...)
; CHECK: Caller: i64 @caller(i32)
; CHECK: %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll b/llvm/test/CodeGen/SystemZ/args-28.ll
index 8cf803effc5f58..3999c46886cbb7 100644
--- a/llvm/test/CodeGen/SystemZ/args-28.ll
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
ret i64 %S
}
-; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 1.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 1.
; CHECK: Callee: i64 @bar(i32 zeroext, ...)
; CHECK: Caller: i64 @caller(i32)
; CHECK: %res = call i64 @bar(i32 zeroext %Arg, i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-29.ll b/llvm/test/CodeGen/SystemZ/args-29.ll
index f164ec34e3d622..ef0a8030187b0f 100644
--- a/llvm/test/CodeGen/SystemZ/args-29.ll
+++ b/llvm/test/CodeGen/SystemZ/args-29.ll
@@ -6,16 +6,16 @@
; test that the split i128 arg (z10) does not mess things up.
define i64 @caller(i32 %Arg) {
- %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+ %res = call i64 @bar(i32 noext %Arg, i128 0, i32 zeroext %Arg)
ret i64 %res
}
-define i64 @bar(i32 noext %A0, i128 %A1, i32 zeroext %A2, ...) {
+define i64 @bar(i32 noext %A0, i128 %A1, i32 signext %A2, ...) {
%S = zext i32 %A2 to i64
ret i64 %S
}
-; CHECK: ERROR : Missing ZExt on arg 2.
-; CHECK: Callee: i64 @bar(i32 noext, i128, i32 zeroext, ...)
+; CHECK: ERROR: Missing SExt on arg 2.
+; CHECK: Callee: i64 @bar(i32 noext, i128, i32 signext, ...)
; CHECK: Caller: i64 @caller(i32)
-; CHECK: %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+; CHECK: %res = call i64 @bar(i32 noext %Arg, i128 0, i32 zeroext %Arg)
More information about the cfe-commits
mailing list