diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-07-31 02:44:24 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-07-31 02:44:24 +0000 |
commit | b48280ba1790122cd3fa6e17c88ecd6a4571a4eb (patch) | |
tree | f9542b6b14db62a150a7af7d2cfb0b0d7d3b859f /lib/CodeGen/CGCall.cpp | |
parent | d72f56de7c79828928147389aed2c6c46f331031 (diff) |
Handle functions with struct arguments or return types and the regparm
attribute. It is a variation of the x86_64 ABI:
* A struct returned indirectly uses the first register argument to pass the
pointer.
* Floats, Doubles and structs containing only one of them are not passed in
registers.
* Other structs are split into registers if they fit on the remaining ones.
Otherwise they are passed in memory.
* When a struct doesn't fit it still consumes the registers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161022 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 9deec19bf8..7d2b9d355e 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -983,14 +983,18 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: break; - case ABIArgInfo::Indirect: - PAL.push_back(llvm::AttributeWithIndex::get(Index, - llvm::Attribute::StructRet)); + case ABIArgInfo::Indirect: { + llvm::Attributes SRETAttrs = llvm::Attribute::StructRet; + if (RetAI.getInReg()) + SRETAttrs |= llvm::Attribute::InReg; + PAL.push_back(llvm::AttributeWithIndex::get(Index, SRETAttrs)); + ++Index; // sret disables readnone and readonly FuncAttrs &= ~(llvm::Attribute::ReadOnly | llvm::Attribute::ReadNone); break; + } case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); @@ -999,14 +1003,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, if (RetAttrs) PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs)); - // FIXME: RegParm should be reduced in case of global register variable. - signed RegParm; - if (FI.getHasRegParm()) - RegParm = FI.getRegParm(); - else - RegParm = CodeGenOpts.NumRegisterParameters; - - unsigned PointerWidth = getContext().getTargetInfo().getPointerWidth(0); for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { QualType ParamType = it->type; @@ -1024,22 +1020,22 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, Attrs |= llvm::Attribute::ZExt; // FALL THROUGH case ABIArgInfo::Direct: - if (RegParm > 0 && - (ParamType->isIntegerType() || ParamType->isPointerType() || - ParamType->isReferenceType())) { - RegParm -= - (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth; - if (RegParm >= 0) + if (AI.getInReg()) Attrs |= llvm::Attribute::InReg; - } + // FIXME: handle sseregparm someday... // Increment Index if there is padding. Index += (AI.getPaddingType() != 0); if (llvm::StructType *STy = - dyn_cast<llvm::StructType>(AI.getCoerceToType())) - Index += STy->getNumElements()-1; // 1 will be added below. + dyn_cast<llvm::StructType>(AI.getCoerceToType())) { + unsigned Extra = STy->getNumElements()-1; // 1 will be added below. + if (Attrs != llvm::Attribute::None) + for (unsigned I = 0; I < Extra; ++I) + PAL.push_back(llvm::AttributeWithIndex::get(Index + I, Attrs)); + Index += Extra; + } break; case ABIArgInfo::Indirect: |