diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 121 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 136 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 22 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 2 |
7 files changed, 250 insertions, 47 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index e84b68104bd..01648ae0747 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -27,24 +27,88 @@ using namespace clang; using namespace CodeGen; -/// Try to emit a definition as a global alias for another definition. -bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, - GlobalDecl TargetDecl) { +/// Determines whether the given function has a trivial body that does +/// not require any specific codegen. +static bool HasTrivialBody(const FunctionDecl *FD) { + Stmt *S = FD->getBody(); + if (!S) + return true; + if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty()) + return true; + return false; +} + +/// Try to emit a base destructor as an alias to its primary +/// base-class destructor. +bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { if (!getCodeGenOpts().CXXCtorDtorAliases) return true; - // Find the referrent. - llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl)); + // If the destructor doesn't have a trivial body, we have to emit it + // separately. + if (!HasTrivialBody(D)) + return true; - // Look for an existing entry. - const char *MangledName = getMangledName(AliasDecl); - llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; - if (Entry) { - assert(Entry->isDeclaration() && "definition already exists for alias"); - assert(Entry->getType() == Ref->getType() && - "declaration exists with different type"); + const CXXRecordDecl *Class = D->getParent(); + + // If we need to manipulate a VTT parameter, give up. + if (Class->getNumVBases()) { + // Extra Credit: passing extra parameters is perfectly safe + // in many calling conventions, so only bail out if the ctor's + // calling convention is nonstandard. + return true; } + // If any fields have a non-trivial destructor, we have to emit it + // separately. + for (CXXRecordDecl::field_iterator I = Class->field_begin(), + E = Class->field_end(); I != E; ++I) + if (const RecordType *RT = (*I)->getType()->getAs<RecordType>()) + if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor()) + return true; + + // Try to find a unique base class with a non-trivial destructor. + const CXXRecordDecl *UniqueBase = 0; + for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), + E = Class->bases_end(); I != E; ++I) { + + // We're in the base destructor, so skip virtual bases. + if (I->isVirtual()) continue; + + // Skip base classes with trivial destructors. + const CXXRecordDecl *Base + = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + if (Base->hasTrivialDestructor()) continue; + + // If we've already found a base class with a non-trivial + // destructor, give up. + if (UniqueBase) return true; + UniqueBase = Base; + } + + // If we didn't find any bases with a non-trivial destructor, then + // the base destructor is actually effectively trivial, which can + // happen if it was needlessly user-defined or if there are virtual + // bases with non-trivial destructors. + if (!UniqueBase) + return true; + + // If the base is at a non-zero offset, give up. + const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class); + if (ClassLayout.getBaseClassOffset(UniqueBase) != 0) + return true; + + const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(getContext()); + return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), + GlobalDecl(BaseD, Dtor_Base)); +} + +/// Try to emit a definition as a global alias for another definition. +bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, + GlobalDecl TargetDecl) { + if (!getCodeGenOpts().CXXCtorDtorAliases) + return true; + // The alias will use the linkage of the referrent. If we can't // support aliases with that linkage, fail. llvm::GlobalValue::LinkageTypes Linkage @@ -72,11 +136,32 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, return true; } + // Derive the type for the alias. + const llvm::PointerType *AliasType + = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); + + // Look for an existing entry. + const char *MangledName = getMangledName(AliasDecl); + llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; + if (Entry) { + assert(Entry->isDeclaration() && "definition already exists for alias"); + assert(Entry->getType() == AliasType && + "declaration exists with different type"); + } + + // Find the referrent. Some aliases might require a bitcast, in + // which case the caller is responsible for ensuring the soundness + // of these semantics. + llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl)); + llvm::Constant *Aliasee = Ref; + if (Ref->getType() != AliasType) + Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType); + // Create the alias with no name. llvm::GlobalAlias *Alias = - new llvm::GlobalAlias(Ref->getType(), Linkage, "", Ref, &getModule()); + new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule()); - // Switch any previous uses to the alias and continue. + // Switch any previous uses to the alias and kill the previous decl. if (Entry) { Entry->replaceAllUsesWith(Alias); Entry->eraseFromParent(); @@ -90,7 +175,6 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, return false; } - void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { // The constructor used for constructing this as a complete class; // constucts the virtual bases, then calls the base constructor. @@ -169,6 +253,13 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, GlobalDecl(D, Dtor_Base))) return; + // The base destructor is equivalent to the base destructor of its + // base class if there is exactly one non-virtual base class with a + // non-trivial destructor, there are no fields with a non-trivial + // destructor, and the body of the destructor is trivial. + if (Type == Dtor_Base && !TryEmitBaseDestructorAsAlias(D)) + return; + llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type)); CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b064c125ad0..1cd899318a9 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -416,6 +416,18 @@ bool CodeGenModule::ReturnTypeUsesSret(const CGFunctionInfo &FI) { return FI.getReturnInfo().isIndirect(); } +const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) { + const CGFunctionInfo &FI = getFunctionInfo(GD); + + // For definition purposes, don't consider a K&R function variadic. + bool Variadic = false; + if (const FunctionProtoType *FPT = + cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>()) + Variadic = FPT->isVariadic(); + + return GetFunctionType(FI, Variadic); +} + const llvm::FunctionType * CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) { std::vector<const llvm::Type*> ArgTys; diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index d30d2186870..99c6dfd7ebc 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -891,31 +891,80 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, } } +/// Checks whether the given constructor is a valid subject for the +/// complete-to-base constructor delegation optimization, i.e. +/// emitting the complete constructor as a simple call to the base +/// constructor. +static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) { + + // Currently we disable the optimization for classes with virtual + // bases because (1) the addresses of parameter variables need to be + // consistent across all initializers but (2) the delegate function + // call necessarily creates a second copy of the parameter variable. + // + // The limiting example (purely theoretical AFAIK): + // struct A { A(int &c) { c++; } }; + // struct B : virtual A { + // B(int count) : A(count) { printf("%d\n", count); } + // }; + // ...although even this example could in principle be emitted as a + // delegation since the address of the parameter doesn't escape. + if (Ctor->getParent()->getNumVBases()) { + // TODO: white-list trivial vbase initializers. This case wouldn't + // be subject to the restrictions below. + + // TODO: white-list cases where: + // - there are no non-reference parameters to the constructor + // - the initializers don't access any non-reference parameters + // - the initializers don't take the address of non-reference + // parameters + // - etc. + // If we ever add any of the above cases, remember that: + // - function-try-blocks will always blacklist this optimization + // - we need to perform the constructor prologue and cleanup in + // EmitConstructorBody. + + return false; + } + + // We also disable the optimization for variadic functions because + // it's impossible to "re-pass" varargs. + if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic()) + return false; + + return true; +} + /// EmitConstructorBody - Emits the body of the current constructor. void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl()); CXXCtorType CtorType = CurGD.getCtorType(); + // Before we go any further, try the complete->base constructor + // delegation optimization. + if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) { + EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args); + return; + } + Stmt *Body = Ctor->getBody(); - // Some of the optimizations we want to do can't be done with - // function try blocks. + // Enter the function-try-block before the constructor prologue if + // applicable. CXXTryStmtInfo TryInfo; - bool isTryBody = (Body && isa<CXXTryStmt>(Body)); - if (isTryBody) + bool IsTryBody = (Body && isa<CXXTryStmt>(Body)); + + if (IsTryBody) TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body)); unsigned CleanupStackSize = CleanupEntries.size(); - // Emit the constructor prologue, i.e. the base and member initializers. - - // TODO: for non-variadic complete-object constructors without a - // function try block for a body, we can get away with just emitting - // the vbase initializers, then calling the base constructor. + // Emit the constructor prologue, i.e. the base and member + // initializers. EmitCtorPrologue(Ctor, CtorType); // Emit the body of the statement. - if (isTryBody) + if (IsTryBody) EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); else if (Body) EmitStmt(Body); @@ -933,7 +982,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { // constructed. EmitCleanupBlocks(CleanupStackSize); - if (isTryBody) + if (IsTryBody) ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo); } @@ -1406,6 +1455,71 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd); } +void +CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, + CXXCtorType CtorType, + const FunctionArgList &Args) { + CallArgList DelegateArgs; + + FunctionArgList::const_iterator I = Args.begin(), E = Args.end(); + assert(I != E && "no parameters to constructor"); + + // this + DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()), + I->second)); + ++I; + + // vtt + if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType))) { + QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy); + DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP)); + + if (CGVtableInfo::needsVTTParameter(CurGD)) { + assert(I != E && "cannot skip vtt parameter, already done with args"); + assert(I->second == VoidPP && "skipping parameter not of vtt type"); + ++I; + } + } + + // 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)); + } + + DelegateArgs.push_back(std::make_pair(Arg, ArgType)); + } + + EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType), + CGM.GetAddrOfCXXConstructor(Ctor, CtorType), + ReturnValueSlot(), DelegateArgs, Ctor); +} + void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, llvm::Value *This) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 1c5cd67fa9d..c4f0a9fcfff 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -789,6 +789,9 @@ public: const CXXRecordDecl *BaseClassDecl, QualType Ty); + void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, + CXXCtorType CtorType, + const FunctionArgList &Args); void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 41575e41e53..f819382a936 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1195,28 +1195,8 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { - const llvm::FunctionType *Ty; const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); - - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - bool isVariadic = D->getType()->getAs<FunctionProtoType>()->isVariadic(); - - Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic); - } else { - Ty = cast<llvm::FunctionType>(getTypes().ConvertType(D->getType())); - - // As a special case, make sure that definitions of K&R function - // "type foo()" aren't declared as varargs (which forces the backend - // to do unnecessary work). - if (D->getType()->isFunctionNoProtoType()) { - assert(Ty->isVarArg() && "Didn't lower type as expected"); - // Due to stret, the lowered function could have arguments. - // Just create the same type as was lowered by ConvertType - // but strip off the varargs bit. - std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end()); - Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false); - } - } + const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index a5e1d9f12b3..ac8332647b7 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -485,6 +485,7 @@ private: // C++ related functions. bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); + bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); void EmitNamespace(const NamespaceDecl *D); void EmitLinkageSpec(const LinkageSpecDecl *D); diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index 87ba0bcfba1..7ce96f48f4e 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -168,6 +168,8 @@ public: const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info, bool IsVariadic); + const llvm::FunctionType *GetFunctionType(GlobalDecl GD); + /// GetFunctionTypeForVtable - Get the LLVM function type for use in a vtable, /// given a CXXMethodDecl. If the method to has an incomplete return type, |