diff options
| author | Chris Lattner <sabre@nondot.org> | 2009-02-28 18:18:58 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2009-02-28 18:18:58 +0000 |
| commit | 3ef668c27ae05a20329f406e58bfe74af507ce4c (patch) | |
| tree | b60429c168afb5edc9470353cf0069d77199d2f7 | |
| parent | bb1fe8abddc3140ff8b7f8942d557a70c6cd8946 (diff) | |
| download | bcm5719-llvm-3ef668c27ae05a20329f406e58bfe74af507ce4c.tar.gz bcm5719-llvm-3ef668c27ae05a20329f406e58bfe74af507ce4c.zip | |
after going around in circles a few times, finally cave and emit structure
copies with memcpy instead of memmove. This matches what GCC does and if it
causes a problem with a particular libc we can always fix it with a target
hook.
llvm-svn: 65699
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 13 | ||||
| -rw-r--r-- | clang/test/CodeGen/struct-copy.c | 7 |
2 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index e2f5c79d994..b0596e2feeb 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -518,7 +518,16 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - // Aggregate assignment turns into llvm.memmove. + // Aggregate assignment turns into llvm.memset. This is almost valid per + // C99 6.5.16.1p3, which states "If the value being stored in an object is + // read from another object that overlaps in anyway the storage of the first + // object, then the overlap shall be exact and the two objects shall have + // qualified or unqualified versions of a compatible type." + // + // memset is not defined if the source and destination pointers are exactly + // equal, but other compilers do this optimization, and almost every memcpy + // implementation handles this case safely. If there is a libc that does not + // safely handle this, we can add a target hook. const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); @@ -531,7 +540,7 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // FIXME: Handle variable sized types. const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); - Builder.CreateCall4(CGM.getMemMoveFn(), + Builder.CreateCall4(CGM.getMemCpyFn(), DestPtr, SrcPtr, // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), diff --git a/clang/test/CodeGen/struct-copy.c b/clang/test/CodeGen/struct-copy.c new file mode 100644 index 00000000000..a45e37a30f4 --- /dev/null +++ b/clang/test/CodeGen/struct-copy.c @@ -0,0 +1,7 @@ +// RUN: clang -emit-llvm %s -o - | grep 'call.*llvm.memcpy' +struct x { int a[100]; }; + + +void foo(struct x *P, struct x *Q) { + *P = *Q; +} |

