diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-01-18 01:12:41 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-01-18 01:12:41 +0000 |
commit | 661f35b0c54c79805e6b17944b155c111bc39ec3 (patch) | |
tree | 43809b5fd564daad88bcace6fb3d9ac25569d46d /clang/lib/CodeGen | |
parent | 0abb05771500eee8c6e39f4f4646a8de8403c491 (diff) | |
download | bcm5719-llvm-661f35b0c54c79805e6b17944b155c111bc39ec3.tar.gz bcm5719-llvm-661f35b0c54c79805e6b17944b155c111bc39ec3.zip |
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
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 117 |
1 files changed, 60 insertions, 57 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 2fbbda503fe..ba8b483052b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -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, |