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 | 06b2b4a7c940a299473e5fece3fa31fe58233aff (patch) | |
tree | a2ebac330e79b10b410b7a7d4134913348f3e7be /clang/lib/CodeGen/CGCall.cpp | |
parent | 3865c6e670a9d8054050ac9af733e8a2a5906554 (diff) | |
download | bcm5719-llvm-06b2b4a7c940a299473e5fece3fa31fe58233aff.tar.gz bcm5719-llvm-06b2b4a7c940a299473e5fece3fa31fe58233aff.zip |
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.
llvm-svn: 161022
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 9deec19bf80..7d2b9d355ec 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/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: |