aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r--lib/CodeGen/TargetInfo.cpp123
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,