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 <[email protected]> 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@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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
