[PowerPC] Fix the calling convention for i1 arguments on PPC32

Summary:
Integer types smaller than i32 must be extended to i32 by default.
The feature "crbits" introduced at r202451 handles i1 as a special case,
but it did not extend properly.
The caller was, therefore, passing i1 stack arguments by writing 0/1 to
the first byte of the 4-byte stack object and callee was
reading the first byte for the value.

"crbits" is enabled if the optimization level is greater than 1,
which is very common in "release builds".
Such discrepancies with ABI specification also introduces
potential incompatibility with programs or libraries
built with other compilers e.g. GCC.

Fixes PR38661

Reviewers: hfinkel, cuviper

Subscribers: sylvestre.ledru, glaubitz, nagisa, nemanjai, kbarton, llvm-commits

Differential Revision: https://reviews.llvm.org/D51108

llvm-svn: 342288
This commit is contained in:
Lion Yang 2018-09-14 21:26:05 +00:00
parent a3937b231d
commit c68f78d5d8
2 changed files with 39 additions and 5 deletions

View File

@ -3511,9 +3511,14 @@ SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
// Argument stored in memory.
assert(VA.isMemLoc());
// Get the extended size of the argument type in stack
unsigned ArgSize = VA.getLocVT().getStoreSize();
int FI = MFI.CreateFixedObject(ArgSize, VA.getLocMemOffset(),
isImmutable);
// Get the actual size of the argument type
unsigned ObjSize = VA.getValVT().getStoreSize();
unsigned ArgOffset = VA.getLocMemOffset();
// Stack objects in PPC32 are right justified.
ArgOffset += ArgSize - ObjSize;
int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, isImmutable);
// Create load nodes to retrieve arguments from the stack.
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
@ -5468,10 +5473,15 @@ SDValue PPCTargetLowering::LowerCall_32SVR4(
Arg = PtrOff;
}
if (VA.isRegLoc()) {
if (Arg.getValueType() == MVT::i1)
Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg);
// When useCRBits() is true, there can be i1 arguments.
// It is because getRegisterType(MVT::i1) => MVT::i1,
// and for other integer types getRegisterType() => MVT::i32.
// Extend i1 and ensure callee will get i32.
if (Arg.getValueType() == MVT::i1)
Arg = DAG.getNode(Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
dl, MVT::i32, Arg);
if (VA.isRegLoc()) {
seenFloatArg |= VA.getLocVT().isFloatingPoint();
// Put argument in a physical register.
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));

View File

@ -0,0 +1,24 @@
; RUN: llc -verify-machineinstrs < %s -mcpu=ppc32 -mattr=+crbits | FileCheck %s
target triple = "powerpc-unknown-linux-gnu"
define void @check_callee(
i32, i32, i32, i32,
i32, i32, i32, i32,
i1 zeroext %s1
) {
call void @check_caller(
i32 9, i32 9, i32 9, i32 9,
i32 9, i32 9, i32 9, i32 9,
i1 zeroext %s1)
ret void
}
; CHECK-LABEL: @check_callee
; CHECK: lbz {{[0-9]+}}, 27(1)
; CHECK: stw {{[0-9]+}}, 8(1)
declare void @check_caller(
i32, i32, i32, i32,
i32, i32, i32, i32,
i1 zeroext
)