Hi timurrrr,
Unlike Itanium's VTTs, the "most derived" boolean or bitfield is the
last parameter, rather than the second. This affects structor calls and
structor decls in a variety of places.
http://llvm-reviews.chandlerc.com/D2405
Files:
lib/CodeGen/CGCXXABI.h
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/ItaniumCXXABI.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/microsoft-abi-structors.cpp
Index: lib/CodeGen/CGCXXABI.h
===================================================================
--- lib/CodeGen/CGCXXABI.h
+++ lib/CodeGen/CGCXXABI.h
@@ -67,9 +67,6 @@
return CGF.CXXStructorImplicitParamValue;
}
- /// Build a parameter variable suitable for 'this'.
- void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
-
/// Perform prolog initialization of the parameter variable suitable
/// for 'this' emitted by BuildThisParam.
void EmitThisParam(CodeGenFunction &CGF);
@@ -270,16 +267,17 @@
return This;
}
- /// Build the ABI-specific portion of the parameter list for a
- /// function. This generally involves a 'this' parameter and
- /// possibly some extra data for constructors and destructors.
+ /// Build a parameter variable suitable for 'this'.
+ void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
+
+ /// Insert any ABI-specific parameters into the parameter list for a function.
+ /// This generally involves extra data for constructors and destructors.
///
/// ABIs may also choose to override the return type, which has been
/// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or
/// the formal return type of the function otherwise.
- virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params) = 0;
+ virtual void AddImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
+ FunctionArgList &Params) = 0;
/// Perform ABI-specific "this" parameter adjustment in a virtual function
/// prologue.
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -202,16 +202,16 @@
CanQualType resultType =
TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
- TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
-
CanQual<FunctionProtoType> FTP = GetFormalType(D);
RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, argTypes.size());
// Add the formal parameters.
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
argTypes.push_back(FTP->getArgType(i));
+ TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
+
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required);
}
Index: lib/CodeGen/CGVTables.cpp
===================================================================
--- lib/CodeGen/CGVTables.cpp
+++ lib/CodeGen/CGVTables.cpp
@@ -253,14 +253,16 @@
FunctionArgList FunctionArgs;
// Create the implicit 'this' parameter declaration.
- CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
+ CGM.getCXXABI().BuildThisParam(*this, FunctionArgs);
// Add the rest of the parameters.
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
E = MD->param_end();
I != E; ++I)
FunctionArgs.push_back(*I);
+ CGM.getCXXABI().AddImplicitStructorParams(*this, ResultType, FunctionArgs);
+
// Start defining the function.
StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
SourceLocation());
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -694,16 +694,19 @@
QualType ResTy = FD->getResultType();
CurGD = GD;
- const CXXMethodDecl *MD;
+ const CXXMethodDecl *MD = 0;
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) {
if (CGM.getCXXABI().HasThisReturn(GD))
ResTy = MD->getThisType(getContext());
- CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
+ CGM.getCXXABI().BuildThisParam(*this, Args);
}
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
Args.push_back(FD->getParamDecl(i));
+ if (MD && MD->isInstance())
+ CGM.getCXXABI().AddImplicitStructorParams(*this, ResTy, Args);
+
SourceRange BodyRange;
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
CurEHLocation = BodyRange.getEnd();
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2492,6 +2492,7 @@
std::string &ConstraintStr,
SourceLocation Loc);
+public:
/// EmitCallArgs - Emit call arguments for a function.
template <typename T>
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
@@ -2565,6 +2566,7 @@
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd, bool ForceColumnInfo);
+private:
const TargetCodeGenInfo &getTargetHooks() const {
return CGM.getTargetCodeGenInfo();
}
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -136,9 +136,8 @@
void EmitCXXDestructors(const CXXDestructorDecl *D);
- void BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params);
+ void AddImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
+ FunctionArgList &Params);
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
@@ -801,18 +800,19 @@
/// The generic ABI passes 'this', plus a VTT if it's initializing a
/// base subobject.
-void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys) {
+void
+ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type, CanQualType &ResTy,
+ SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
- // 'this' parameter is already there, as well as 'this' return if
- // HasThisReturn(GlobalDecl(Ctor, Type)) is true
+ // All parameters are already in place except VTT, which goes after 'this'.
+ // These are Clang types, so we don't need to worry about sret yet.
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
- ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+ ArgTys.insert(ArgTys.begin() + 1,
+ Context.getPointerType(Context.VoidPtrTy));
}
void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
@@ -863,12 +863,9 @@
CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting));
}
-void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+void ItaniumCXXABI::AddImplicitStructorParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
- /// Create the 'this' variable.
- BuildThisParam(CGF, Params);
-
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
assert(MD->isInstance());
@@ -881,7 +878,7 @@
ImplicitParamDecl *VTTDecl
= ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
&Context.Idents.get("vtt"), T);
- Params.push_back(VTTDecl);
+ Params.insert(Params.begin() + 1, VTTDecl);
getStructorImplicitParamDecl(CGF) = VTTDecl;
}
}
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -140,9 +140,8 @@
GlobalDecl GD,
llvm::Value *This);
- void BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params);
+ void AddImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
+ FunctionArgList &Params);
llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This);
@@ -450,11 +449,12 @@
return isa<CXXConstructorDecl>(GD.getDecl());
}
-void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys) {
- // 'this' parameter and 'this' return are already in place
+void MicrosoftCXXABI::BuildConstructorSignature(
+ const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
+ SmallVectorImpl<CanQualType> &ArgTys) {
+
+ // All parameters are already in place except is_most_derived, which goes
+ // last.
const CXXRecordDecl *Class = Ctor->getParent();
if (Class->getNumVBases()) {
@@ -682,11 +682,9 @@
return false;
}
-void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params) {
- BuildThisParam(CGF, Params);
-
+void MicrosoftCXXABI::AddImplicitStructorParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
ASTContext &Context = getContext();
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
@@ -790,25 +788,41 @@
void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type,
- bool ForVirtualBase,
- bool Delegating,
- llvm::Value *This,
+ CXXCtorType Type, bool ForVirtualBase,
+ bool Delegating, llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
assert(Type == Ctor_Complete || Type == Ctor_Base);
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Ctor_Complete);
- llvm::Value *ImplicitParam = 0;
- QualType ImplicitParamTy;
+ // C++11 [class.mfct.non-static]p2:
+ // If a non-static member function of a class X is called for an object that
+ // is not of type X, or of a type derived from X, the behavior is undefined.
+ // FIXME: Provide a source location here.
+ CGF.EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(),
+ This, getContext().getRecordType(D->getParent()));
+
+ CallArgList Args;
+
+ // Push the this ptr.
+ unsigned ExtraArgs = 1;
+ Args.add(RValue::get(This), D->getThisType(getContext()));
+
+ // And the rest of the call args.
+ const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
+ CGF.EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
+
+ // Add the is_most_derived bitfield last.
if (D->getParent()->getNumVBases()) {
- ImplicitParam = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
- ImplicitParamTy = getContext().IntTy;
+ llvm::Value *MostDerived =
+ llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
+ Args.add(RValue::get(MostDerived), getContext().IntTy);
+ ++ExtraArgs;
}
- // FIXME: Provide a source location here.
- CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
- ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);
+ RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, ExtraArgs);
+ CGF.EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), Callee,
+ ReturnValueSlot(), Args, D);
}
void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
Index: test/CodeGenCXX/microsoft-abi-structors.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-structors.cpp
+++ test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -300,6 +300,23 @@
}
+namespace test1 {
+struct A { };
+struct B : virtual A {
+ B(void *a);
+};
+B::B(void *a) {}
+// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAX@Z"
+// CHECK: (%"struct.test1::B"* returned %this, i8* %a, i32 %is_most_derived)
+
+void construct_b() {
+ B b(0);
+}
+// CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"()
+// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAX@Z"
+// CHECK: (%"struct.test1::B"* {{.*}}, i8* null, i32 1)
+}
+
// Dtor thunks for classes in anonymous namespaces should be internal, not
// linkonce_odr.
namespace {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits