aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-07-29 18:13:09 +0000
committerChris Lattner <sabre@nondot.org>2010-07-29 18:13:09 +0000
commitf47c944b5710a545d564b4d4b641a2f8bac96af3 (patch)
tree691f9324792459ff697c086f34cf0fb737f913da /lib/CodeGen/TargetInfo.cpp
parentf6404774069a4759cab095b389ce007e74c9c9ee (diff)
fix rdar://8251384, another case where we could access beyond the
end of a struct. This improves the case when the struct being passed contains 3 floats, either due to a struct or array of 3 things. Before we'd generate this IR for the testcase: define float @bar(double %X.coerce0, double %X.coerce1) nounwind { entry: %X = alloca %struct.foof, align 8 ; <%struct.foof*> [#uses=2] %0 = bitcast %struct.foof* %X to %1* ; <%1*> [#uses=2] %1 = getelementptr %1* %0, i32 0, i32 0 ; <double*> [#uses=1] store double %X.coerce0, double* %1 %2 = getelementptr %1* %0, i32 0, i32 1 ; <double*> [#uses=1] store double %X.coerce1, double* %2 %tmp = getelementptr inbounds %struct.foof* %X, i32 0, i32 2 ; <float*> [#uses=1] %tmp1 = load float* %tmp ; <float> [#uses=1] ret float %tmp1 } which compiled (with optimization) to: _bar: ## @bar ## BB#0: ## %entry movd %xmm1, %rax movd %eax, %xmm0 ret Now we produce: define float @bar(double %X.coerce0, float %X.coerce1) nounwind { entry: %X = alloca %struct.foof, align 8 ; <%struct.foof*> [#uses=2] %0 = bitcast %struct.foof* %X to %0* ; <%0*> [#uses=2] %1 = getelementptr %0* %0, i32 0, i32 0 ; <double*> [#uses=1] store double %X.coerce0, double* %1 %2 = getelementptr %0* %0, i32 0, i32 1 ; <float*> [#uses=1] store float %X.coerce1, float* %2 %tmp = getelementptr inbounds %struct.foof* %X, i32 0, i32 2 ; <float*> [#uses=1] %tmp1 = load float* %tmp ; <float> [#uses=1] ret float %tmp1 } and: _bar: ## @bar ## BB#0: ## %entry movaps %xmm1, %xmm0 ret git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109776 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r--lib/CodeGen/TargetInfo.cpp49
1 files changed, 28 insertions, 21 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 1e66f046b0..ec52b93bdf 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -719,7 +719,8 @@ class X86_64ABIInfo : public ABIInfo {
const llvm::Type *Get16ByteVectorType(QualType Ty) const;
const llvm::Type *GetSSETypeAtOffset(const llvm::Type *IRType,
- unsigned IROffset) const;
+ unsigned IROffset, QualType SourceTy,
+ unsigned SourceOffset) const;
const llvm::Type *GetINTEGERTypeAtOffset(const llvm::Type *IRType,
unsigned IROffset, QualType SourceTy,
unsigned SourceOffset) const;
@@ -1211,21 +1212,6 @@ const llvm::Type *X86_64ABIInfo::Get16ByteVectorType(QualType Ty) const {
return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()), 2);
}
-
-/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the
-/// low 8 bytes of an XMM register, corresponding to the SSE class.
-const llvm::Type *X86_64ABIInfo::GetSSETypeAtOffset(const llvm::Type *IRType,
- unsigned IROffset) const {
- // The only two choices we have are either double or <2 x float>.
-
- // FIXME: <2 x float> doesn't pass as one XMM register yet. Don't enable this
- // code until it does.
-
- return llvm::Type::getDoubleTy(getVMContext());
-}
-
-
-
/// BitsContainNoUserData - Return true if the specified [start,end) bit range
/// is known to either be off the end of the specified type or being in
/// alignment padding. The user type specified is known to be at most 128 bits
@@ -1311,6 +1297,27 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit,
return false;
}
+
+/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the
+/// low 8 bytes of an XMM register, corresponding to the SSE class.
+const llvm::Type *X86_64ABIInfo::
+GetSSETypeAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ QualType SourceTy, unsigned SourceOffset) const {
+ // The only two choices we have are either double, <2 x float>, or float. We
+ // pass as float if the last 4 bytes is just padding. This happens for
+ // structs that contain 3 floats.
+ if (BitsContainNoUserData(SourceTy, SourceOffset*8+32,
+ SourceOffset*8+64, getContext()))
+ return llvm::Type::getFloatTy(getVMContext());
+
+ // FIXME: <2 x float> doesn't pass as one XMM register yet. Don't enable this
+ // code until it does.
+ //return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2);
+
+ return llvm::Type::getDoubleTy(getVMContext());
+}
+
+
/// GetINTEGERTypeAtOffset - 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
@@ -1420,7 +1427,7 @@ classifyReturnType(QualType RetTy) const {
// AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
// available SSE register of the sequence %xmm0, %xmm1 is used.
case SSE:
- ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0);
+ ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0, RetTy, 0);
break;
// AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is
@@ -1460,7 +1467,7 @@ classifyReturnType(QualType RetTy) const {
}
case SSE: {
const llvm::Type *HiType =
- GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8);
+ GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8);
ResType = llvm::StructType::get(getVMContext(), ResType, HiType,NULL);
break;
}
@@ -1483,7 +1490,7 @@ classifyReturnType(QualType RetTy) const {
// extra bits in an SSE reg.
if (Lo != X87) {
const llvm::Type *HiType =
- GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8);
+ GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8);
ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL);
}
break;
@@ -1539,7 +1546,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt,
// order from %xmm0 to %xmm7.
case SSE:
++neededSSE;
- ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 0);
+ ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 0, Ty, 0);
break;
}
@@ -1569,7 +1576,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt,
case X87Up:
case SSE: {
const llvm::Type *HiType =
- GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8);
+ GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8);
ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL);
++neededSSE;
break;