diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp | 175 |
1 files changed, 70 insertions, 105 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp index f28d9b6..0df2c43 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp @@ -30,14 +30,7 @@ using namespace clang; using namespace CodeGen; CodeGenVTables::CodeGenVTables(CodeGenModule &CGM) - : CGM(CGM), ItaniumVTContext(CGM.getContext()) { - if (CGM.getTarget().getCXXABI().isMicrosoft()) { - // FIXME: Eventually, we should only have one of V*TContexts available. - // Today we use both in the Microsoft ABI as MicrosoftVFTableContext - // is not completely supported in CodeGen yet. - MicrosoftVTContext.reset(new MicrosoftVTableContext(CGM.getContext())); - } -} + : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {} llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk) { @@ -54,54 +47,13 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, Out.flush(); llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD); - return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true); + return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true, + /*DontDefer*/ true); } static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, const ThunkInfo &Thunk, llvm::Function *Fn) { CGM.setGlobalVisibility(Fn, MD); - - if (!CGM.getCodeGenOpts().HiddenWeakVTables) - return; - - // If the thunk has weak/linkonce linkage, but the function must be - // emitted in every translation unit that references it, then we can - // emit its thunks with hidden visibility, since its thunks must be - // emitted when the function is. - - // This follows CodeGenModule::setTypeVisibility; see the comments - // there for explanation. - - if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage && - Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) || - Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility) - return; - - if (MD->getExplicitVisibility(ValueDecl::VisibilityForValue)) - return; - - switch (MD->getTemplateSpecializationKind()) { - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitInstantiationDeclaration: - return; - - case TSK_Undeclared: - break; - - case TSK_ExplicitSpecialization: - case TSK_ImplicitInstantiation: - return; - break; - } - - // If there's an explicit definition, and that definition is - // out-of-line, then we can't assume that all users will have a - // definition to emit. - const FunctionDecl *Def = 0; - if (MD->hasBody(Def) && Def->isOutOfLine()) - return; - - Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); } #ifndef NDEBUG @@ -119,11 +71,11 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF, const ThunkInfo &Thunk) { // Emit the return adjustment. bool NullCheckValue = !ResultType->isReferenceType(); - - llvm::BasicBlock *AdjustNull = 0; - llvm::BasicBlock *AdjustNotNull = 0; - llvm::BasicBlock *AdjustEnd = 0; - + + llvm::BasicBlock *AdjustNull = nullptr; + llvm::BasicBlock *AdjustNotNull = nullptr; + llvm::BasicBlock *AdjustEnd = nullptr; + llvm::Value *ReturnValue = RV.getScalarVal(); if (NullCheckValue) { @@ -177,7 +129,7 @@ void CodeGenFunction::GenerateVarArgsThunk( GlobalDecl GD, const ThunkInfo &Thunk) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - QualType ResultType = FPT->getResultType(); + QualType ResultType = FPT->getReturnType(); // Get the original function assert(FnInfo.isVariadic()); @@ -207,7 +159,7 @@ void CodeGenFunction::GenerateVarArgsThunk( // with "this". llvm::Value *ThisPtr = &*AI; llvm::BasicBlock *EntryBB = Fn->begin(); - llvm::Instruction *ThisStore = 0; + llvm::Instruction *ThisStore = nullptr; for (llvm::BasicBlock::iterator I = EntryBB->begin(), E = EntryBB->end(); I != E; I++) { if (isa<llvm::StoreInst>(I) && I->getOperand(0) == ThisPtr) { @@ -248,11 +200,11 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, QualType ThisType = MD->getThisType(getContext()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType = - CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType(); + CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getReturnType(); 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(), @@ -260,9 +212,12 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, I != E; ++I) FunctionArgs.push_back(*I); + if (isa<CXXDestructorDecl>(MD)) + CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs); + // Start defining the function. StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, - SourceLocation()); + MD->getLocation(), SourceLocation()); // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. CGM.getCXXABI().EmitInstanceFunctionProlog(*this); @@ -316,7 +271,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(GlobalDecl GD, // Determine whether we have a return value slot to use. QualType ResultType = - CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType(); + CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getReturnType(); ReturnValueSlot Slot; if (!ResultType->isVoidType() && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && @@ -366,27 +321,30 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD); // FIXME: re-use FnInfo in this computation. - llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk); - + llvm::Constant *C = CGM.GetAddrOfThunk(GD, Thunk); + llvm::GlobalValue *Entry; + // Strip off a bitcast if we got one back. - if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(C)) { assert(CE->getOpcode() == llvm::Instruction::BitCast); - Entry = CE->getOperand(0); + Entry = cast<llvm::GlobalValue>(CE->getOperand(0)); + } else { + Entry = cast<llvm::GlobalValue>(C); } - + // There's already a declaration with the same name, check if it has the same // type or if we need to replace it. - if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != + if (Entry->getType()->getElementType() != CGM.getTypes().GetFunctionTypeForVTable(GD)) { - llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry); - + llvm::GlobalValue *OldThunkFn = Entry; + // If the types mismatch then we have to rewrite the definition. assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration"); // Remove the name from the old thunk function and get a new thunk. OldThunkFn->setName(StringRef()); - Entry = CGM.GetAddrOfThunk(GD, Thunk); + Entry = cast<llvm::GlobalValue>(CGM.GetAddrOfThunk(GD, Thunk)); // If needed, replace the old thunk with a bitcast. if (!OldThunkFn->use_empty()) { @@ -424,12 +382,14 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, // FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly. if (!UseAvailableExternallyLinkage) { CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable); + CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, + !Thunk.Return.isEmpty()); } } else { // Normal thunk body generation. CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable); + CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, + !Thunk.Return.isEmpty()); } } @@ -461,12 +421,8 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD) if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) return; - const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector; - if (MicrosoftVTContext.isValid()) { - ThunkInfoVector = MicrosoftVTContext->getThunkInfo(GD); - } else { - ThunkInfoVector = ItaniumVTContext.getThunkInfo(GD); - } + const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector = + VTContext->getThunkInfo(GD); if (!ThunkInfoVector) return; @@ -475,12 +431,10 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD) emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false); } -llvm::Constant * -CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, - const VTableComponent *Components, - unsigned NumComponents, - const VTableLayout::VTableThunkTy *VTableThunks, - unsigned NumVTableThunks) { +llvm::Constant *CodeGenVTables::CreateVTableInitializer( + const CXXRecordDecl *RD, const VTableComponent *Components, + unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks, + unsigned NumVTableThunks, llvm::Constant *RTTI) { SmallVector<llvm::Constant *, 64> Inits; llvm::Type *Int8PtrTy = CGM.Int8PtrTy; @@ -488,17 +442,14 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, llvm::Type *PtrDiffTy = CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); - QualType ClassType = CGM.getContext().getTagDeclType(RD); - llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType); - unsigned NextVTableThunkIndex = 0; - - llvm::Constant *PureVirtualFn = 0, *DeletedVirtualFn = 0; + + llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr; for (unsigned I = 0; I != NumComponents; ++I) { VTableComponent Component = Components[I]; - llvm::Constant *Init = 0; + llvm::Constant *Init = nullptr; switch (Component.getKind()) { case VTableComponent::CK_VCallOffset: @@ -603,8 +554,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) DI->completeClassData(Base.getBase()); - OwningPtr<VTableLayout> VTLayout( - ItaniumVTContext.createConstructionVTableLayout( + std::unique_ptr<VTableLayout> VTLayout( + getItaniumVTableContext().createConstructionVTableLayout( Base.getBase(), Base.getBaseOffset(), BaseIsVirtual, RD)); // Add the address points. @@ -633,18 +584,19 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage); - CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForConstructionVTable); + CGM.setGlobalVisibility(VTable, RD); // V-tables are always unnamed_addr. VTable->setUnnamedAddr(true); + llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor( + CGM.getContext().getTagDeclType(Base.getBase())); + // Create and set the initializer. - llvm::Constant *Init = - CreateVTableInitializer(Base.getBase(), - VTLayout->vtable_component_begin(), - VTLayout->getNumVTableComponents(), - VTLayout->vtable_thunk_begin(), - VTLayout->getNumVTableThunks()); + llvm::Constant *Init = CreateVTableInitializer( + Base.getBase(), VTLayout->vtable_component_begin(), + VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(), + VTLayout->getNumVTableThunks(), RTTI); VTable->setInitializer(Init); return VTable; @@ -663,7 +615,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { if (const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD)) { // If this class has a key function, use that to determine the // linkage of the vtable. - const FunctionDecl *def = 0; + const FunctionDecl *def = nullptr; if (keyFunction->hasBody(def)) keyFunction = cast<CXXMethodDecl>(def); @@ -697,18 +649,31 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { // internal linkage. if (Context.getLangOpts().AppleKext) return llvm::Function::InternalLinkage; - + + llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage = + llvm::GlobalValue::LinkOnceODRLinkage; + llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage = + llvm::GlobalValue::WeakODRLinkage; + if (RD->hasAttr<DLLExportAttr>()) { + // Cannot discard exported vtables. + DiscardableODRLinkage = NonDiscardableODRLinkage; + } else if (RD->hasAttr<DLLImportAttr>()) { + // Imported vtables are available externally. + DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; + NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; + } + switch (RD->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: case TSK_ImplicitInstantiation: - return llvm::GlobalVariable::LinkOnceODRLinkage; + return DiscardableODRLinkage; case TSK_ExplicitInstantiationDeclaration: llvm_unreachable("Should not have been asked to emit this"); case TSK_ExplicitInstantiationDefinition: - return llvm::GlobalVariable::WeakODRLinkage; + return NonDiscardableODRLinkage; } llvm_unreachable("Invalid TemplateSpecializationKind!"); @@ -752,7 +717,7 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { /// strongly elsewhere. Otherwise, we'd just like to avoid emitting /// v-tables when unnecessary. bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { - assert(RD->isDynamicClass() && "Non dynamic classes have no VTable."); + assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable."); // If we have an explicit instantiation declaration (and not a // definition), the v-table is defined elsewhere. |