forked from OSchip/llvm-project
Refactor ABI argument lowering a little
Currently it tracks the number of free registers, but soon it will track stack offsets for inalloca lowering. No functional change. llvm-svn: 199532
This commit is contained in:
parent
0abb057715
commit
661f35b0c5
|
@ -526,6 +526,14 @@ static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
|
|||
// X86-32 ABI Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Similar to llvm::CCState, but for Clang.
|
||||
struct CCState {
|
||||
CCState(unsigned CC) : CC(CC), FreeRegs(0) {}
|
||||
|
||||
unsigned CC;
|
||||
unsigned FreeRegs;
|
||||
};
|
||||
|
||||
/// X86_32ABIInfo - The X86-32 ABI information.
|
||||
class X86_32ABIInfo : public ABIInfo {
|
||||
enum Class {
|
||||
|
@ -549,19 +557,17 @@ class X86_32ABIInfo : public ABIInfo {
|
|||
|
||||
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
|
||||
/// such that the argument will be passed in memory.
|
||||
ABIArgInfo getIndirectResult(QualType Ty, bool ByVal,
|
||||
unsigned &FreeRegs) const;
|
||||
ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const;
|
||||
|
||||
ABIArgInfo getIndirectReturnResult(CCState &State) const;
|
||||
|
||||
/// \brief Return the alignment to use for the given type on the stack.
|
||||
unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
|
||||
|
||||
Class classify(QualType Ty) const;
|
||||
ABIArgInfo classifyReturnType(QualType RetTy,
|
||||
unsigned callingConvention) const;
|
||||
ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &FreeRegs,
|
||||
bool IsFastCall) const;
|
||||
bool shouldUseInReg(QualType Ty, unsigned &FreeRegs,
|
||||
bool IsFastCall, bool &NeedsPadding) const;
|
||||
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
|
||||
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
|
||||
bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -677,8 +683,18 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
|
|||
return true;
|
||||
}
|
||||
|
||||
ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
||||
unsigned callingConvention) const {
|
||||
ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(CCState &State) const {
|
||||
// If the return value is indirect, then the hidden argument is consuming one
|
||||
// integer register.
|
||||
if (State.FreeRegs) {
|
||||
--State.FreeRegs;
|
||||
return ABIArgInfo::getIndirectInReg(/*Align=*/0, /*ByVal=*/false);
|
||||
}
|
||||
return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false);
|
||||
}
|
||||
|
||||
ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
||||
CCState &State) const {
|
||||
if (RetTy->isVoidType())
|
||||
return ABIArgInfo::getIgnore();
|
||||
|
||||
|
@ -701,7 +717,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
|||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
|
||||
Size));
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
return getIndirectReturnResult(State);
|
||||
}
|
||||
|
||||
return ABIArgInfo::getDirect();
|
||||
|
@ -710,21 +726,21 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
|||
if (isAggregateTypeForABI(RetTy)) {
|
||||
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
|
||||
if (isRecordReturnIndirect(RT, getCXXABI()))
|
||||
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
|
||||
return getIndirectReturnResult(State);
|
||||
|
||||
// Structures with flexible arrays are always indirect.
|
||||
if (RT->getDecl()->hasFlexibleArrayMember())
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
return getIndirectReturnResult(State);
|
||||
}
|
||||
|
||||
// If specified, structs and unions are always indirect.
|
||||
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
return getIndirectReturnResult(State);
|
||||
|
||||
// Small structures which are register sized are generally returned
|
||||
// in a register.
|
||||
if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(),
|
||||
callingConvention)) {
|
||||
if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(),
|
||||
State.CC)) {
|
||||
uint64_t Size = getContext().getTypeSize(RetTy);
|
||||
|
||||
// As a special-case, if the struct is a "single-element" struct, and
|
||||
|
@ -742,7 +758,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
|||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
|
||||
}
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
return getIndirectReturnResult(State);
|
||||
}
|
||||
|
||||
// Treat an enum type as its underlying type.
|
||||
|
@ -806,10 +822,10 @@ unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
|
|||
}
|
||||
|
||||
ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal,
|
||||
unsigned &FreeRegs) const {
|
||||
CCState &State) const {
|
||||
if (!ByVal) {
|
||||
if (FreeRegs) {
|
||||
--FreeRegs; // Non-byval indirects just use one pointer.
|
||||
if (State.FreeRegs) {
|
||||
--State.FreeRegs; // Non-byval indirects just use one pointer.
|
||||
return ABIArgInfo::getIndirectInReg(0, false);
|
||||
}
|
||||
return ABIArgInfo::getIndirect(0, false);
|
||||
|
@ -843,8 +859,8 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
|
|||
return Integer;
|
||||
}
|
||||
|
||||
bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
|
||||
bool IsFastCall, bool &NeedsPadding) const {
|
||||
bool X86_32ABIInfo::shouldUseInReg(QualType Ty, CCState &State,
|
||||
bool &NeedsPadding) const {
|
||||
NeedsPadding = false;
|
||||
Class C = classify(Ty);
|
||||
if (C == Float)
|
||||
|
@ -856,14 +872,14 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
|
|||
if (SizeInRegs == 0)
|
||||
return false;
|
||||
|
||||
if (SizeInRegs > FreeRegs) {
|
||||
FreeRegs = 0;
|
||||
if (SizeInRegs > State.FreeRegs) {
|
||||
State.FreeRegs = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeRegs -= SizeInRegs;
|
||||
State.FreeRegs -= SizeInRegs;
|
||||
|
||||
if (IsFastCall) {
|
||||
if (State.CC == llvm::CallingConv::X86_FastCall) {
|
||||
if (Size > 32)
|
||||
return false;
|
||||
|
||||
|
@ -876,7 +892,7 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
|
|||
if (Ty->isReferenceType())
|
||||
return true;
|
||||
|
||||
if (FreeRegs)
|
||||
if (State.FreeRegs)
|
||||
NeedsPadding = true;
|
||||
|
||||
return false;
|
||||
|
@ -885,21 +901,20 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
|
|||
return true;
|
||||
}
|
||||
|
||||
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
|
||||
unsigned &FreeRegs,
|
||||
bool IsFastCall) const {
|
||||
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State) const {
|
||||
// FIXME: Set alignment on indirect arguments.
|
||||
if (isAggregateTypeForABI(Ty)) {
|
||||
if (const RecordType *RT = Ty->getAs<RecordType>()) {
|
||||
if (IsWin32StructABI)
|
||||
return getIndirectResult(Ty, true, FreeRegs);
|
||||
return getIndirectResult(Ty, true, State);
|
||||
|
||||
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()))
|
||||
return getIndirectResult(Ty, RAA == CGCXXABI::RAA_DirectInMemory, FreeRegs);
|
||||
return getIndirectResult(Ty, RAA == CGCXXABI::RAA_DirectInMemory,
|
||||
State);
|
||||
|
||||
// Structures with flexible arrays are always indirect.
|
||||
if (RT->getDecl()->hasFlexibleArrayMember())
|
||||
return getIndirectResult(Ty, true, FreeRegs);
|
||||
return getIndirectResult(Ty, true, State);
|
||||
}
|
||||
|
||||
// Ignore empty structs/unions.
|
||||
|
@ -909,7 +924,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
|
|||
llvm::LLVMContext &LLVMContext = getVMContext();
|
||||
llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
|
||||
bool NeedsPadding;
|
||||
if (shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding)) {
|
||||
if (shouldUseInReg(Ty, State, NeedsPadding)) {
|
||||
unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
|
||||
SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
|
||||
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
|
||||
|
@ -923,9 +938,10 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
|
|||
// optimizations.
|
||||
if (getContext().getTypeSize(Ty) <= 4*32 &&
|
||||
canExpandIndirectArgument(Ty, getContext()))
|
||||
return ABIArgInfo::getExpandWithPadding(IsFastCall, PaddingType);
|
||||
return ABIArgInfo::getExpandWithPadding(
|
||||
State.CC == llvm::CallingConv::X86_FastCall, PaddingType);
|
||||
|
||||
return getIndirectResult(Ty, true, FreeRegs);
|
||||
return getIndirectResult(Ty, true, State);
|
||||
}
|
||||
|
||||
if (const VectorType *VT = Ty->getAs<VectorType>()) {
|
||||
|
@ -950,7 +966,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
|
|||
Ty = EnumTy->getDecl()->getIntegerType();
|
||||
|
||||
bool NeedsPadding;
|
||||
bool InReg = shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding);
|
||||
bool InReg = shouldUseInReg(Ty, State, NeedsPadding);
|
||||
|
||||
if (Ty->isPromotableIntegerType()) {
|
||||
if (InReg)
|
||||
|
@ -963,32 +979,19 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
|
|||
}
|
||||
|
||||
void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
|
||||
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(),
|
||||
FI.getCallingConvention());
|
||||
|
||||
unsigned CC = FI.getCallingConvention();
|
||||
bool IsFastCall = CC == llvm::CallingConv::X86_FastCall;
|
||||
unsigned FreeRegs;
|
||||
if (IsFastCall)
|
||||
FreeRegs = 2;
|
||||
CCState State(FI.getCallingConvention());
|
||||
if (State.CC == llvm::CallingConv::X86_FastCall)
|
||||
State.FreeRegs = 2;
|
||||
else if (FI.getHasRegParm())
|
||||
FreeRegs = FI.getRegParm();
|
||||
State.FreeRegs = FI.getRegParm();
|
||||
else
|
||||
FreeRegs = DefaultNumRegisterParameters;
|
||||
State.FreeRegs = DefaultNumRegisterParameters;
|
||||
|
||||
// If the return value is indirect, then the hidden argument is consuming one
|
||||
// integer register.
|
||||
if (FI.getReturnInfo().isIndirect() && FreeRegs) {
|
||||
--FreeRegs;
|
||||
ABIArgInfo &Old = FI.getReturnInfo();
|
||||
Old = ABIArgInfo::getIndirectInReg(Old.getIndirectAlign(),
|
||||
Old.getIndirectByVal(),
|
||||
Old.getIndirectRealign());
|
||||
}
|
||||
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
|
||||
|
||||
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
|
||||
it != ie; ++it)
|
||||
it->info = classifyArgumentType(it->type, FreeRegs, IsFastCall);
|
||||
it->info = classifyArgumentType(it->type, State);
|
||||
}
|
||||
|
||||
llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
||||
|
|
Loading…
Reference in New Issue