diff options
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 123 |
1 files changed, 63 insertions, 60 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 0df657070f..4bc37775b8 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1198,6 +1198,62 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty) const { return ABIArgInfo::getIndirect(0); } +/// Get8ByteTypeAtOffset - The ABI specifies that a value should be passed in an +/// 8-byte GPR. This means that we either have a scalar or we are talking about +/// the high or low part of an up-to-16-byte struct. This routine picks the +/// best LLVM IR type to represent this, which may be i64 or may be anything +/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*, +/// etc). +/// +/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for +/// the source type. IROffset is an offset in bytes into the LLVM IR type that +/// the 8-byte value references. PrefType may be null. +/// +/// SourceTy is the source level type for the entire argument. SourceOffset is +/// an offset into this that we're processing (which is always either 0 or 8). +/// +static const llvm::Type *Get8ByteTypeAtOffset(const llvm::Type *PrefType, + unsigned IROffset, + QualType SourceTy, + unsigned SourceOffset, + const llvm::TargetData &TD, + llvm::LLVMContext &VMContext, + ASTContext &Context) { + // Pointers are always 8-bytes at offset 0. + if (IROffset == 0 && PrefType && isa<llvm::PointerType>(PrefType)) + return PrefType; + + // TODO: 1/2/4/8 byte integers are also interesting, but we have to know that + // the "hole" is not used in the containing struct (just undef padding). + + if (const llvm::StructType *STy = + dyn_cast_or_null<llvm::StructType>(PrefType)) { + // If this is a struct, recurse into the field at the specified offset. + const llvm::StructLayout *SL = TD.getStructLayout(STy); + if (IROffset < SL->getSizeInBytes()) { + unsigned FieldIdx = SL->getElementContainingOffset(IROffset); + IROffset -= SL->getElementOffset(FieldIdx); + + return Get8ByteTypeAtOffset(STy->getElementType(FieldIdx), IROffset, + SourceTy, SourceOffset, TD,VMContext,Context); + } + } + + // Okay, we don't have any better idea of what to pass, so we pass this in an + // integer register that isn't too big to fit the rest of the struct. + uint64_t TySizeInBytes = Context.getTypeSizeInChars(SourceTy).getQuantity(); + + // It is always safe to classify this as an integer type up to i64 that + // isn't larger than the structure. + switch (unsigned(TySizeInBytes-SourceOffset)) { + case 1: return llvm::Type::getInt8Ty(VMContext); + case 2: return llvm::Type::getInt16Ty(VMContext); + case 3: + case 4: return llvm::Type::getInt32Ty(VMContext); + default: return llvm::Type::getInt64Ty(VMContext); + } +} + ABIArgInfo X86_64ABIInfo:: classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const { // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the @@ -1227,7 +1283,8 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const { // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next // available register of the sequence %rax, %rdx is used. case Integer: - ResType = llvm::Type::getInt64Ty(VMContext); break; + ResType = Get8ByteTypeAtOffset(0, 0, RetTy, 0, TD, VMContext, Context); + break; // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next // available SSE register of the sequence %xmm0, %xmm1 is used. @@ -1261,10 +1318,12 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const { case ComplexX87: // Previously handled. case NoClass: break; - case Integer: - ResType = llvm::StructType::get(VMContext, ResType, - llvm::Type::getInt64Ty(VMContext), NULL); + case Integer: { + const llvm::Type *HiType = + Get8ByteTypeAtOffset(0, 8, RetTy, 8, TD, VMContext, Context); + ResType = llvm::StructType::get(VMContext, ResType, HiType, NULL); break; + } case SSE: ResType = llvm::StructType::get(VMContext, ResType, llvm::Type::getDoubleTy(VMContext), NULL); @@ -1295,62 +1354,6 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const { return getCoerceResult(RetTy, ResType); } -/// Get8ByteTypeAtOffset - The ABI specifies that a value should be passed in an -/// 8-byte GPR. This means that we either have a scalar or we are talking about -/// the high or low part of an up-to-16-byte struct. This routine picks the -/// best LLVM IR type to represent this, which may be i64 or may be anything -/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*, -/// etc). -/// -/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for -/// the source type. IROffset is an offset in bytes into the LLVM IR type that -/// the 8-byte value references. PrefType may be null. -/// -/// SourceTy is the source level type for the entire argument. SourceOffset is -/// an offset into this that we're processing (which is always either 0 or 8). -/// -static const llvm::Type *Get8ByteTypeAtOffset(const llvm::Type *PrefType, - unsigned IROffset, - QualType SourceTy, - unsigned SourceOffset, - const llvm::TargetData &TD, - llvm::LLVMContext &VMContext, - ASTContext &Context) { - // Pointers are always 8-bytes at offset 0. - if (IROffset == 0 && PrefType && isa<llvm::PointerType>(PrefType)) - return PrefType; - - // TODO: 1/2/4/8 byte integers are also interesting, but we have to know that - // the "hole" is not used in the containing struct (just undef padding). - - if (const llvm::StructType *STy = - dyn_cast_or_null<llvm::StructType>(PrefType)) { - // If this is a struct, recurse into the field at the specified offset. - const llvm::StructLayout *SL = TD.getStructLayout(STy); - if (IROffset < SL->getSizeInBytes()) { - unsigned FieldIdx = SL->getElementContainingOffset(IROffset); - IROffset -= SL->getElementOffset(FieldIdx); - - return Get8ByteTypeAtOffset(STy->getElementType(FieldIdx), IROffset, - SourceTy, SourceOffset, TD,VMContext,Context); - } - } - - // Okay, we don't have any better idea of what to pass, so we pass this in an - // integer register that isn't too big to fit the rest of the struct. - uint64_t TySizeInBytes = Context.getTypeSizeInChars(SourceTy).getQuantity(); - - // It is always safe to classify this as an integer type up to i64 that - // isn't larger than the structure. - switch (unsigned(TySizeInBytes-SourceOffset)) { - case 1: return llvm::Type::getInt8Ty(VMContext); - case 2: return llvm::Type::getInt16Ty(VMContext); - case 3: - case 4: return llvm::Type::getInt32Ty(VMContext); - default: return llvm::Type::getInt64Ty(VMContext); - } -} - ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, llvm::LLVMContext &VMContext, unsigned &neededInt, |