diff options
-rw-r--r-- | lib/Transforms/NaCl/ExpandVarArgs.cpp | 23 | ||||
-rw-r--r-- | test/Transforms/NaCl/expand-varargs-struct.ll | 5 |
2 files changed, 19 insertions, 9 deletions
diff --git a/lib/Transforms/NaCl/ExpandVarArgs.cpp b/lib/Transforms/NaCl/ExpandVarArgs.cpp index 36f58416e2..0fd1a3cb44 100644 --- a/lib/Transforms/NaCl/ExpandVarArgs.cpp +++ b/lib/Transforms/NaCl/ExpandVarArgs.cpp @@ -38,6 +38,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" @@ -196,14 +197,13 @@ static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) { for (unsigned I = FuncType->getNumParams(); I < Call->getNumArgOperands(); ++I) { Value *ArgVal = Call->getArgOperand(I); + VarArgs.push_back(ArgVal); if (Call->getAttributes().hasAttribute(I + 1, Attribute::ByVal)) { - // For "byval" arguments we must dereference the pointer and - // make a copy of the struct being passed by value. - ArgVal = CopyDebug(new LoadInst(ArgVal, "vararg_struct_copy", Call), - Call); + // For "byval" arguments we must dereference the pointer. + VarArgsTypes.push_back(ArgVal->getType()->getPointerElementType()); + } else { + VarArgsTypes.push_back(ArgVal->getType()); } - VarArgs.push_back(ArgVal); - VarArgsTypes.push_back(ArgVal->getType()); } if (VarArgsTypes.size() == 0) { // Some buggy code (e.g. 176.gcc in Spec2k) uses va_arg on an @@ -249,7 +249,16 @@ static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) { Indexes.push_back(ConstantInt::get(*Context, APInt(32, Index))); Value *Ptr = CopyDebug(GetElementPtrInst::Create( Buf, Indexes, "vararg_ptr", Call), Call); - CopyDebug(new StoreInst(*Iter, Ptr, Call), Call); + if (Call->getAttributes().hasAttribute( + FuncType->getNumParams() + Index + 1, Attribute::ByVal)) { + IRBuilder<> Builder(Call); + Builder.CreateMemCpy( + Ptr, *Iter, + DL->getTypeAllocSize((*Iter)->getType()->getPointerElementType()), + /* Align= */ 1); + } else { + CopyDebug(new StoreInst(*Iter, Ptr, Call), Call); + } } // Cast function to new type to add our extra pointer argument. diff --git a/test/Transforms/NaCl/expand-varargs-struct.ll b/test/Transforms/NaCl/expand-varargs-struct.ll index 7bb310fd40..b96b41875c 100644 --- a/test/Transforms/NaCl/expand-varargs-struct.ll +++ b/test/Transforms/NaCl/expand-varargs-struct.ll @@ -11,6 +11,7 @@ define i32 @varargs_call_struct(%MyStruct* %ptr) { ret i32 %result } ; CHECK: define i32 @varargs_call_struct(%MyStruct* %ptr) { -; CHECK: %vararg_struct_copy = load %MyStruct* %ptr ; CHECK: %vararg_ptr1 = getelementptr <{ i64, %MyStruct }>* %vararg_buffer, i32 0, i32 1 -; CHECK: store %MyStruct %vararg_struct_copy, %MyStruct* %vararg_ptr1 +; CHECK: %1 = bitcast %MyStruct* %vararg_ptr1 to i8* +; CHECK: %2 = bitcast %MyStruct* %ptr to i8* +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 16, i32 1, i1 false) |