From 84b921f8053fa3f9cb15a91af03a51c9332bb3ce Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Wed, 28 Nov 2012 22:08:52 +0000 Subject: [PATCH] ABI: modify CreateCoercedLoad and CreateCoercedStore to not use load or store of the original parameter or return type. Since we do not accurately represent the data fields of a union, we should not directly load or store a union type. As an exmple, if we have i8,i8, i32, i32 as one field type and i32,i32 as another field type, the first field type will be chosen to represent the union. If we load with the union's type, the 3rd byte and the 4th byte will be skipped. rdar://12723368 llvm-svn: 168820 --- clang/lib/CodeGen/CGCall.cpp | 24 ++++++++++++------------ clang/test/CodeGen/x86_64-arguments.c | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c470918dde45..ab933c52b42d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -692,12 +692,12 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, // Otherwise do coercion through memory. This is stupid, but // simple. llvm::Value *Tmp = CGF.CreateTempAlloca(Ty); - llvm::Value *Casted = - CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(SrcTy)); - llvm::StoreInst *Store = - CGF.Builder.CreateStore(CGF.Builder.CreateLoad(SrcPtr), Casted); - // FIXME: Use better alignment / avoid requiring aligned store. - Store->setAlignment(1); + llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy(); + llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy); + llvm::Value *SrcCasted = CGF.Builder.CreateBitCast(SrcPtr, I8PtrTy); + CGF.Builder.CreateMemCpy(Casted, SrcCasted, + llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize), + 1, false); return CGF.Builder.CreateLoad(Tmp); } @@ -779,12 +779,12 @@ static void CreateCoercedStore(llvm::Value *Src, // to that information. llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy); CGF.Builder.CreateStore(Src, Tmp); - llvm::Value *Casted = - CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(DstTy)); - llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted); - // FIXME: Use better alignment / avoid requiring aligned load. - Load->setAlignment(1); - CGF.Builder.CreateStore(Load, DstPtr, DstIsVolatile); + llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy(); + llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy); + llvm::Value *DstCasted = CGF.Builder.CreateBitCast(DstPtr, I8PtrTy); + CGF.Builder.CreateMemCpy(DstCasted, Casted, + llvm::ConstantInt::get(CGF.IntPtrTy, DstSize), + 1, false); } } diff --git a/clang/test/CodeGen/x86_64-arguments.c b/clang/test/CodeGen/x86_64-arguments.c index f73e1f026a83..b39fa1d34910 100644 --- a/clang/test/CodeGen/x86_64-arguments.c +++ b/clang/test/CodeGen/x86_64-arguments.c @@ -354,3 +354,23 @@ void test46() { v46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); } struct s47 { unsigned a; }; void f47(int,int,int,int,int,int,struct s47); void test47(int a, struct s47 b) { f47(a, a, a, a, a, a, b); } + +// rdar://12723368 +// In the following example, there are holes in T4 at the 3rd byte and the 4th +// byte, however, T2 does not have those holes. T4 is chosen to be the +// representing type for union T1, but we can't use load or store of T4 since +// it will skip the 3rd byte and the 4th byte. +// In general, Since we don't accurately represent the data fields of a union, +// do not use load or store of the representing llvm type for the union. +typedef _Complex int T2; +typedef _Complex char T5; +typedef _Complex int T7; +typedef struct T4 { T5 field0; T7 field1; } T4; +typedef union T1 { T2 field0; T4 field1; } T1; +extern T1 T1_retval; +T1 test48(void) { +// CHECK: @test48 +// CHECK-NOT: load %struct.T4* %{{.*}} +// CHECK-NOT: store %struct.T4 %{{.*}}, %struct.T4* %{{.*}} + return T1_retval; +}