forked from OSchip/llvm-project
CodeGen: Add support for lowering byref attribute
This commit is contained in:
parent
7ce32f87f9
commit
f659c44016
|
@ -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; }
|
||||
|
|
|
@ -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) {}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue