aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-11-18 02:12:09 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-11-18 02:12:09 +0000
commit7b1fb81a512def2a20e2834b4598a7b3a740dc7f (patch)
tree276a52d287050a636616cde00756e0cca9a7a803
parent506d4e375a6a36a49eb70578983dc4acaf2f15ae (diff)
A bunch of fixes to argument passing and va_arg on Darwin x86-32 for structures containing an SSE vector.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144963 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/TargetInfo.cpp24
-rw-r--r--test/CodeGen/x86_32-arguments-darwin.c24
2 files changed, 45 insertions, 3 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 5be38978f2..88f8579b9a 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -620,7 +620,7 @@ static bool isRecordWithSSEVectorType(ASTContext &Context, QualType Ty) {
i != e; ++i) {
QualType FT = i->getType();
- if (FT->getAs<VectorType>() && Context.getTypeSize(Ty) == 128)
+ if (FT->getAs<VectorType>() && Context.getTypeSize(FT) == 128)
return true;
if (isRecordWithSSEVectorType(Context, FT))
@@ -644,7 +644,7 @@ unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
}
// Otherwise, if the type contains an SSE vector type, the alignment is 16.
- if (isRecordWithSSEVectorType(getContext(), Ty))
+ if (Align >= 16 && isRecordWithSSEVectorType(getContext(), Ty))
return 16;
return MinABIStackAlignInBytes;
@@ -739,12 +739,30 @@ llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
"ap");
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+
+ // Compute if the address needs to be aligned
+ unsigned Align = CGF.getContext().getTypeAlignInChars(Ty).getQuantity();
+ Align = getTypeStackAlignInBytes(Ty, Align);
+ Align = std::max(Align, 4U);
+ if (Align > 4) {
+ // addr = (addr + align - 1) & -align;
+ llvm::Value *Offset =
+ llvm::ConstantInt::get(CGF.Int32Ty, Align - 1);
+ Addr = CGF.Builder.CreateGEP(Addr, Offset);
+ llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(Addr,
+ CGF.Int32Ty);
+ llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -Align);
+ Addr = CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
+ Addr->getType(),
+ "ap.cur.aligned");
+ }
+
llvm::Type *PTy =
llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, Align);
llvm::Value *NextAddr =
Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
"ap.next");
diff --git a/test/CodeGen/x86_32-arguments-darwin.c b/test/CodeGen/x86_32-arguments-darwin.c
index cc203d2add..31802ab8a3 100644
--- a/test/CodeGen/x86_32-arguments-darwin.c
+++ b/test/CodeGen/x86_32-arguments-darwin.c
@@ -292,3 +292,27 @@ struct s59 f59() { while (1) {} }
// CHECK: define void @f60(%struct.s60* byval align 4, i32 %y)
struct s60 { int x __attribute((aligned(8))); };
void f60(struct s60 x, int y) {}
+
+// CHECK: define void @f61(i32 %x, %struct.s61* byval align 16 %y)
+typedef int T61 __attribute((vector_size(16)));
+struct s61 { T61 x; int y; };
+void f61(int x, struct s61 y) {}
+
+// CHECK: define void @f62(i32 %x, %struct.s62* byval align 4)
+typedef int T62 __attribute((vector_size(16)));
+struct s62 { T62 x; int y; } __attribute((packed, aligned(8)));
+void f62(int x, struct s62 y) {}
+
+// CHECK: define i32 @f63
+// CHECK: ptrtoint
+// CHECK: and {{.*}}, -16
+// CHECK: inttoptr
+typedef int T63 __attribute((vector_size(16)));
+struct s63 { T63 x; int y; };
+int f63(int i, ...) {
+ __builtin_va_list ap;
+ __builtin_va_start(ap, i);
+ struct s63 s = __builtin_va_arg(ap, struct s63);
+ __builtin_va_end(ap);
+ return s.y;
+}