forked from OSchip/llvm-project
[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:
parent
a3937b231d
commit
c68f78d5d8
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
)
|
Loading…
Reference in New Issue