aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/ExpandVarArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/NaCl/ExpandVarArgs.cpp')
-rw-r--r--lib/Transforms/NaCl/ExpandVarArgs.cpp32
1 files changed, 24 insertions, 8 deletions
diff --git a/lib/Transforms/NaCl/ExpandVarArgs.cpp b/lib/Transforms/NaCl/ExpandVarArgs.cpp
index e1bd8f93a8..6998001754 100644
--- a/lib/Transforms/NaCl/ExpandVarArgs.cpp
+++ b/lib/Transforms/NaCl/ExpandVarArgs.cpp
@@ -168,13 +168,13 @@ static void LifetimeDecl(Intrinsic::ID id, Value *Ptr, Value *Size,
// CopyCall() uses argument overloading so that it can be used by the
// template ExpandVarArgCall().
-static Instruction *CopyCall(CallInst *Original, Value *Callee,
- ArrayRef<Value*> Args) {
+static CallInst *CopyCall(CallInst *Original, Value *Callee,
+ ArrayRef<Value*> Args) {
return CallInst::Create(Callee, Args, "", Original);
}
-static Instruction *CopyCall(InvokeInst *Original, Value *Callee,
- ArrayRef<Value*> Args) {
+static InvokeInst *CopyCall(InvokeInst *Original, Value *Callee,
+ ArrayRef<Value*> Args) {
return InvokeInst::Create(Callee, Original->getNormalDest(),
Original->getUnwindDest(), Args, "", Original);
}
@@ -190,16 +190,30 @@ static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) {
LLVMContext *Context = &Call->getContext();
+ SmallVector<AttributeSet, 8> Attrs;
+ Attrs.push_back(Call->getAttributes().getFnAttributes());
+ Attrs.push_back(Call->getAttributes().getRetAttributes());
+
// Split argument list into fixed and variable arguments.
SmallVector<Value *, 8> FixedArgs;
SmallVector<Value *, 8> VarArgs;
SmallVector<Type *, 8> VarArgsTypes;
- for (unsigned I = 0; I < FuncType->getNumParams(); ++I)
+ for (unsigned I = 0; I < FuncType->getNumParams(); ++I) {
FixedArgs.push_back(Call->getArgOperand(I));
+ // AttributeSets use 1-based indexing.
+ Attrs.push_back(Call->getAttributes().getParamAttributes(I + 1));
+ }
for (unsigned I = FuncType->getNumParams();
I < Call->getNumArgOperands(); ++I) {
- VarArgs.push_back(Call->getArgOperand(I));
- VarArgsTypes.push_back(Call->getArgOperand(I)->getType());
+ Value *ArgVal = Call->getArgOperand(I);
+ 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);
+ }
+ VarArgs.push_back(ArgVal);
+ VarArgsTypes.push_back(ArgVal->getType());
}
StructType *VarArgsTy;
@@ -262,7 +276,9 @@ static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) {
// Create the converted function call.
FixedArgs.push_back(ArgToAdd);
- Value *NewCall = CopyDebug(CopyCall(Call, CastFunc, FixedArgs), Call);
+ InstType *NewCall = CopyCall(Call, CastFunc, FixedArgs);
+ CopyDebug(NewCall, Call);
+ NewCall->setAttributes(AttributeSet::get(Call->getContext(), Attrs));
NewCall->takeName(Call);
if (BufPtr) {