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:
John McCall 2010-05-26 22:34:26 +00:00
Родитель 12e131385e
Коммит 2736071ea3
5 изменённых файлов: 55 добавлений и 34 удалений

Просмотреть файл

@ -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(