1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

CodeGen: Add support for lowering byref attribute

This commit is contained in:
Matt Arsenault 2020-06-25 11:40:25 -04:00 committed by Matt Arsenault
parent 9d11825eb6
commit 80f5f4e026
3 changed files with 76 additions and 28 deletions

View File

@ -31,6 +31,7 @@ namespace ISD {
unsigned IsInReg : 1; ///< Passed in register
unsigned IsSRet : 1; ///< Hidden struct-ret ptr
unsigned IsByVal : 1; ///< Struct passed by value
unsigned IsByRef : 1; ///< Passed in memory
unsigned IsNest : 1; ///< Nested fn static chain
unsigned IsReturned : 1; ///< Always returned
unsigned IsSplit : 1;
@ -43,25 +44,31 @@ namespace ISD {
unsigned IsHva : 1; ///< HVA field for
unsigned IsHvaStart : 1; ///< HVA structure start
unsigned IsSecArgPass : 1; ///< Second argument
unsigned ByValAlign : 4; ///< Log 2 of byval alignment
unsigned ByValOrByRefAlign : 4; ///< Log 2 of byval/byref alignment
unsigned OrigAlign : 5; ///< Log 2 of original alignment
unsigned IsInConsecutiveRegsLast : 1;
unsigned IsInConsecutiveRegs : 1;
unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
unsigned IsPointer : 1;
unsigned ByValSize; ///< Byval struct size
unsigned ByValOrByRefSize; ///< Byval or byref struct size
unsigned PointerAddrSpace; ///< Address space of pointer argument
/// Set the alignment used by byref or byval parameters.
void setAlignImpl(Align A) {
ByValOrByRefAlign = encode(A);
assert(getNonZeroByValAlign() == A && "bitfield overflow");
}
public:
ArgFlagsTy()
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0),
IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0),
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0),
IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0),
IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0),
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0),
IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValOrByRefAlign(0),
OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0),
PointerAddrSpace(0) {
static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
}
@ -81,6 +88,9 @@ namespace ISD {
bool isByVal() const { return IsByVal; }
void setByVal() { IsByVal = 1; }
bool isByRef() const { return IsByRef; }
void setByRef() { IsByRef = 1; }
bool isInAlloca() const { return IsInAlloca; }
void setInAlloca() { IsInAlloca = 1; }
@ -131,17 +141,22 @@ namespace ISD {
LLVM_ATTRIBUTE_DEPRECATED(unsigned getByValAlign() const,
"Use getNonZeroByValAlign() instead") {
MaybeAlign A = decodeMaybeAlign(ByValAlign);
MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign);
return A ? A->value() : 0;
}
Align getNonZeroByValAlign() const {
MaybeAlign A = decodeMaybeAlign(ByValAlign);
MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign);
assert(A && "ByValAlign must be defined");
return *A;
}
void setByValAlign(Align A) {
ByValAlign = encode(A);
assert(getNonZeroByValAlign() == A && "bitfield overflow");
assert(isByVal() && !isByRef());
setAlignImpl(A);
}
void setByRefAlign(Align A) {
assert(!isByVal() && isByRef());
setAlignImpl(A);
}
LLVM_ATTRIBUTE_DEPRECATED(unsigned getOrigAlign() const,
@ -157,8 +172,23 @@ namespace ISD {
assert(getNonZeroOrigAlign() == A && "bitfield overflow");
}
unsigned getByValSize() const { return ByValSize; }
void setByValSize(unsigned S) { ByValSize = S; }
unsigned getByValSize() const {
assert(isByVal() && !isByRef());
return ByValOrByRefSize;
}
void setByValSize(unsigned S) {
assert(isByVal() && !isByRef());
ByValOrByRefSize = S;
}
unsigned getByRefSize() const {
assert(!isByVal() && isByRef());
return ByValOrByRefSize;
}
void setByRefSize(unsigned S) {
assert(!isByVal() && isByRef());
ByValOrByRefSize = S;
}
unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }

View File

@ -278,6 +278,7 @@ public:
bool IsSRet : 1;
bool IsNest : 1;
bool IsByVal : 1;
bool IsByRef : 1;
bool IsInAlloca : 1;
bool IsPreallocated : 1;
bool IsReturned : 1;
@ -290,7 +291,7 @@ public:
ArgListEntry()
: IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false),
IsNest(false), IsByVal(false), IsInAlloca(false),
IsNest(false), IsByVal(false), IsByRef(false), IsInAlloca(false),
IsPreallocated(false), IsReturned(false), IsSwiftSelf(false),
IsSwiftError(false), IsCFGuardTarget(false) {}

View File

@ -9119,6 +9119,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
Entry.IsSRet = true;
Entry.IsNest = false;
Entry.IsByVal = false;
Entry.IsByRef = false;
Entry.IsReturned = false;
Entry.IsSwiftSelf = false;
Entry.IsSwiftError = false;
@ -9239,6 +9240,8 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
Flags.setCFGuardTarget();
if (Args[i].IsByVal)
Flags.setByVal();
if (Args[i].IsByRef)
Flags.setByRef();
if (Args[i].IsPreallocated) {
Flags.setPreallocated();
// Set the byval flag for CCAssignFn callbacks that don't know about
@ -9752,6 +9755,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
Flags.setSwiftError();
if (Arg.hasAttribute(Attribute::ByVal))
Flags.setByVal();
if (Arg.hasAttribute(Attribute::ByRef))
Flags.setByRef();
if (Arg.hasAttribute(Attribute::InAlloca)) {
Flags.setInAlloca();
// Set the byval flag for CCAssignFn callbacks that don't know about
@ -9770,27 +9775,39 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
// preallocated handling in the various CC lowering callbacks.
Flags.setByVal();
}
Type *ArgMemTy = nullptr;
if (F.getCallingConv() == CallingConv::X86_INTR) {
// IA Interrupt passes frame (1st parameter) by value in the stack.
if (ArgNo == 0)
if (ArgNo == 0) {
Flags.setByVal();
// FIXME: Dependence on pointee element type. See bug 46672.
ArgMemTy = Arg.getType()->getPointerElementType();
}
}
if (Flags.isByVal() || Flags.isInAlloca() || Flags.isPreallocated()) {
Type *ElementTy = Arg.getParamByValType();
if (Flags.isByVal() || Flags.isInAlloca() || Flags.isPreallocated() ||
Flags.isByRef()) {
if (!ArgMemTy)
ArgMemTy = Arg.getPointeeInMemoryValueType();
// For ByVal, size and alignment should be passed from FE. BE will
// guess if this info is not there but there are cases it cannot get
// right.
unsigned FrameSize = DL.getTypeAllocSize(Arg.getParamByValType());
Flags.setByValSize(FrameSize);
uint64_t MemSize = DL.getTypeAllocSize(ArgMemTy);
unsigned FrameAlign;
if (Arg.getParamAlignment())
FrameAlign = Arg.getParamAlignment();
else
FrameAlign = TLI->getByValTypeAlignment(ElementTy, DL);
Flags.setByValAlign(Align(FrameAlign));
// For in-memory arguments, size and alignment should be passed from FE.
// BE will guess if this info is not there but there are cases it cannot
// get right.
MaybeAlign MemAlign = Arg.getParamAlign();
if (!MemAlign)
MemAlign = Align(TLI->getByValTypeAlignment(ArgMemTy, DL));
if (Flags.isByRef()) {
Flags.setByRefSize(MemSize);
Flags.setByRefAlign(*MemAlign);
} else {
Flags.setByValSize(MemSize);
Flags.setByValAlign(*MemAlign);
}
}
if (Arg.hasAttribute(Attribute::Nest))
Flags.setNest();
if (NeedsRegBlock)