diff options
| author | Chris Lattner <sabre@nondot.org> | 2010-07-28 22:15:08 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2010-07-28 22:15:08 +0000 |
| commit | 4c1e484f39490d1fcb96369ecfb242e0ce17787d (patch) | |
| tree | 019db5fd73e1c2e34df02e7938d32dbaf7488a3d /clang/lib | |
| parent | a5fd522992d64a2d1ff12537f6b9b81c4557abb6 (diff) | |
| download | bcm5719-llvm-4c1e484f39490d1fcb96369ecfb242e0ce17787d.tar.gz bcm5719-llvm-4c1e484f39490d1fcb96369ecfb242e0ce17787d.zip | |
fix PR7714 by not referencing off the end of a struct when passed by value in
x86-64 abi. This also improves codegen as well. Some refactoring is needed of
this code.
llvm-svn: 109681
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index c65f2037155..b315e851c28 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1112,7 +1112,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, const llvm::Type *CoerceTo) const { - if (CoerceTo->isIntegerTy(64) || isa<llvm::PointerType>(CoerceTo)) { + // If this is a pointer passed as a pointer, just pass it directly. + if ((isa<llvm::PointerType>(CoerceTo) || CoerceTo->isIntegerTy(64)) && + Ty->hasPointerRepresentation()) + return ABIArgInfo::getExtend(); + + if (isa<llvm::IntegerType>(CoerceTo)) { // Integer and pointer types will end up in a general purpose // register. @@ -1120,10 +1125,12 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, if (const EnumType *EnumTy = Ty->getAs<EnumType>()) Ty = EnumTy->getDecl()->getIntegerType(); - if (Ty->isIntegralOrEnumerationType() || Ty->hasPointerRepresentation()) + if (Ty->isIntegralOrEnumerationType()) return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + // FIXME: Zap this. + // If this is a 8/16/32-bit structure that is passed as an int64, then it // will be passed in the low 8/16/32-bits of a 64-bit GPR, which is the same // as how an i8/i16/i32 is passed. Coerce to a i8/i16/i32 instead of a i64. @@ -1320,6 +1327,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, X86_64ABIInfo::Class Lo, Hi; classify(Ty, 0, Lo, Hi); + uint64_t TySizeInBytes = Context.getTypeSizeInChars(Ty).getQuantity(); + // Check some invariants. // FIXME: Enforce these by construction. assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); @@ -1351,8 +1360,6 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 // and %r9 is used. case Integer: - // It is always safe to classify this as an i64 argument. - ResType = llvm::Type::getInt64Ty(VMContext); ++neededInt; // If we can choose a better 8-byte type based on the preferred type, and if @@ -1361,6 +1368,19 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, if (isa<llvm::IntegerType>(PrefTypeLo) || isa<llvm::PointerType>(PrefTypeLo)) ResType = PrefTypeLo; + + if (ResType == 0) { + // It is always safe to classify this as an integer type up to i64 that + // isn't larger than the structure. + if (TySizeInBytes == 1) + ResType = llvm::Type::getInt8Ty(VMContext); + else if (TySizeInBytes == 2) + ResType = llvm::Type::getInt16Ty(VMContext); + else if (TySizeInBytes <= 4) + ResType = llvm::Type::getInt32Ty(VMContext); + else + ResType = llvm::Type::getInt64Ty(VMContext); + } break; // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next @@ -1385,8 +1405,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, case NoClass: break; case Integer: { - // It is always safe to classify this as an i64 argument. - const llvm::Type *HiType = llvm::Type::getInt64Ty(VMContext); + const llvm::Type *HiType = 0; ++neededInt; // If we can choose a better 8-byte type based on the preferred type, and if @@ -1395,7 +1414,20 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, if (isa<llvm::IntegerType>(PrefTypeHi) || isa<llvm::PointerType>(PrefTypeHi)) HiType = PrefTypeHi; - + + if (HiType == 0) { + // It is always safe to classify this as an integer type up to i64 that + // isn't larger than the structure. + if (TySizeInBytes == 9) + HiType = llvm::Type::getInt8Ty(VMContext); + else if (TySizeInBytes == 10) + HiType = llvm::Type::getInt16Ty(VMContext); + else if (TySizeInBytes <= 12) + HiType = llvm::Type::getInt32Ty(VMContext); + else + HiType = llvm::Type::getInt64Ty(VMContext); + } + ResType = llvm::StructType::get(VMContext, ResType, HiType, NULL); break; } |

