зеркало из https://github.com/microsoft/clang-1.git
Correctly pass aggregates by reference when emitting thunks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104778 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
12e131385e
Коммит
2736071ea3
|
@ -862,6 +862,36 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
|
|||
}
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
|
||||
// StartFunction converted the ABI-lowered parameter(s) into a
|
||||
// local alloca. We need to turn that into an r-value suitable
|
||||
// for EmitCall.
|
||||
llvm::Value *Local = GetAddrOfLocalVar(Param);
|
||||
|
||||
QualType ArgType = Param->getType();
|
||||
|
||||
// For the most part, we just need to load the alloca, except:
|
||||
// 1) aggregate r-values are actually pointers to temporaries, and
|
||||
// 2) references to aggregates are pointers directly to the aggregate.
|
||||
// I don't know why references to non-aggregates are different here.
|
||||
if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) {
|
||||
if (hasAggregateLLVMType(RefType->getPointeeType()))
|
||||
return RValue::getAggregate(Local);
|
||||
|
||||
// Locals which are references to scalars are represented
|
||||
// with allocas holding the pointer.
|
||||
return RValue::get(Builder.CreateLoad(Local));
|
||||
}
|
||||
|
||||
if (ArgType->isAnyComplexType())
|
||||
return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false));
|
||||
|
||||
if (hasAggregateLLVMType(ArgType))
|
||||
return RValue::getAggregate(Local);
|
||||
|
||||
return RValue::get(EmitLoadOfScalar(Local, false, ArgType));
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
|
||||
if (ArgType->isReferenceType())
|
||||
return EmitReferenceBindingToExpr(E);
|
||||
|
|
|
@ -1137,34 +1137,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
|
|||
|
||||
// Explicit arguments.
|
||||
for (; I != E; ++I) {
|
||||
|
||||
const VarDecl *Param = I->first;
|
||||
QualType ArgType = Param->getType(); // because we're passing it to itself
|
||||
|
||||
// StartFunction converted the ABI-lowered parameter(s) into a
|
||||
// local alloca. We need to turn that into an r-value suitable
|
||||
// for EmitCall.
|
||||
llvm::Value *Local = GetAddrOfLocalVar(Param);
|
||||
RValue Arg;
|
||||
|
||||
// For the most part, we just need to load the alloca, except:
|
||||
// 1) aggregate r-values are actually pointers to temporaries, and
|
||||
// 2) references to aggregates are pointers directly to the aggregate.
|
||||
// I don't know why references to non-aggregates are different here.
|
||||
if (ArgType->isReferenceType()) {
|
||||
const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
|
||||
if (hasAggregateLLVMType(RefType->getPointeeType()))
|
||||
Arg = RValue::getAggregate(Local);
|
||||
else
|
||||
// Locals which are references to scalars are represented
|
||||
// with allocas holding the pointer.
|
||||
Arg = RValue::get(Builder.CreateLoad(Local));
|
||||
} else {
|
||||
if (hasAggregateLLVMType(ArgType))
|
||||
Arg = RValue::getAggregate(Local);
|
||||
else
|
||||
Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
|
||||
}
|
||||
RValue Arg = EmitDelegateCallArg(Param);
|
||||
|
||||
DelegateArgs.push_back(std::make_pair(Arg, ArgType));
|
||||
}
|
||||
|
|
|
@ -2641,14 +2641,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
|
|||
E = MD->param_end(); I != E; ++I) {
|
||||
ParmVarDecl *Param = *I;
|
||||
QualType ArgType = Param->getType();
|
||||
|
||||
// Load the argument corresponding to this parameter.
|
||||
RValue Arg;
|
||||
if (ArgType->isReferenceType() ||
|
||||
(hasAggregateLLVMType(ArgType) && !ArgType->isAnyComplexType()))
|
||||
Arg = RValue::get(Builder.CreateLoad(LocalDeclMap[Param]));
|
||||
else
|
||||
Arg = RValue::get(EmitLoadOfScalar(LocalDeclMap[Param], false, ArgType));
|
||||
RValue Arg = EmitDelegateCallArg(Param);
|
||||
|
||||
CallArgs.push_back(std::make_pair(Arg, ArgType));
|
||||
}
|
||||
|
|
|
@ -1302,6 +1302,11 @@ public:
|
|||
/// EmitCallArg - Emit a single call argument.
|
||||
RValue EmitCallArg(const Expr *E, QualType ArgType);
|
||||
|
||||
/// EmitDelegateCallArg - We are performing a delegate call; that
|
||||
/// is, the current function is delegating to another one. Produce
|
||||
/// a r-value suitable for passing the given parameter.
|
||||
RValue EmitDelegateCallArg(const VarDecl *Param);
|
||||
|
||||
private:
|
||||
|
||||
void EmitReturnOfRValue(RValue RV, QualType Ty);
|
||||
|
|
|
@ -218,6 +218,24 @@ namespace Test7 {
|
|||
void testD() { D d; }
|
||||
}
|
||||
|
||||
namespace Test8 {
|
||||
struct NonPOD { ~NonPOD(); int x, y, z; };
|
||||
struct A { virtual void foo(); };
|
||||
struct B { virtual void bar(NonPOD); };
|
||||
struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
|
||||
|
||||
// CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
|
||||
void C::helper(NonPOD var) {}
|
||||
|
||||
// CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
|
||||
// CHECK-NOT: load [[NONPODTYPE]]*
|
||||
// CHECK-NOT: memcpy
|
||||
// CHECK: ret void
|
||||
void C::bar(NonPOD var) {}
|
||||
}
|
||||
|
||||
/**** The following has to go at the end of the file ****/
|
||||
|
||||
// This is from Test5:
|
||||
// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
|
||||
// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(
|
||||
|
|
Загрузка…
Ссылка в новой задаче