diff options
Diffstat (limited to 'clang/lib/CodeGen/CGVTables.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 82 |
1 files changed, 39 insertions, 43 deletions
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 91dd7a8e046b..27a2cab4f753 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -24,6 +24,7 @@ #include "llvm/Transforms/Utils/Cloning.h" #include <algorithm> #include <cstdio> +#include <utility> using namespace clang; using namespace CodeGen; @@ -201,7 +202,7 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getThisType()->getPointeeType()), + Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = @@ -464,10 +465,6 @@ void CodeGenFunction::generateThunk(llvm::Function *Fn, llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); - // Fix up the function type for an unprototyped musttail call. - if (IsUnprototyped) - Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType()); - // Make the call and return the result. EmitCallAndReturnForThunk(llvm::FunctionCallee(Fn->getFunctionType(), Callee), &Thunk, IsUnprototyped); @@ -536,11 +533,8 @@ llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD, Name.str(), &CGM.getModule()); CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/false); - // If needed, replace the old thunk with a bitcast. if (!OldThunkFn->use_empty()) { - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(ThunkFn, OldThunkFn->getType()); - OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl); + OldThunkFn->replaceAllUsesWith(ThunkFn); } // Remove the old thunk. @@ -639,8 +633,16 @@ void CodeGenVTables::addRelativeComponent(ConstantArrayBuilder &builder, // want the stub/proxy to be emitted for properly calculating the offset. // Examples where there would be no symbol emitted are available_externally // and private linkages. - auto stubLinkage = vtableHasLocalLinkage ? llvm::GlobalValue::InternalLinkage - : llvm::GlobalValue::ExternalLinkage; + // + // `internal` linkage results in STB_LOCAL Elf binding while still manifesting a + // local symbol. + // + // `linkonce_odr` linkage results in a STB_DEFAULT Elf binding but also allows for + // the rtti_proxy to be transparently replaced with a GOTPCREL reloc by a + // target that supports this replacement. + auto stubLinkage = vtableHasLocalLinkage + ? llvm::GlobalValue::InternalLinkage + : llvm::GlobalValue::LinkOnceODRLinkage; llvm::Constant *target; if (auto *func = dyn_cast<llvm::Function>(globalVal)) { @@ -1303,48 +1305,42 @@ llvm::GlobalObject::VCallVisibility CodeGenModule::GetVCallVisibilityLevel( void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { - if (!getCodeGenOpts().LTOUnit) + // Emit type metadata on vtables with LTO or IR instrumentation. + // In IR instrumentation, the type metadata is used to find out vtable + // definitions (for type profiling) among all global variables. + if (!getCodeGenOpts().LTOUnit && !getCodeGenOpts().hasProfileIRInstr()) return; CharUnits ComponentWidth = GetTargetTypeStoreSize(getVTableComponentType()); - typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint; + struct AddressPoint { + const CXXRecordDecl *Base; + size_t Offset; + std::string TypeName; + bool operator<(const AddressPoint &RHS) const { + int D = TypeName.compare(RHS.TypeName); + return D < 0 || (D == 0 && Offset < RHS.Offset); + } + }; std::vector<AddressPoint> AddressPoints; - for (auto &&AP : VTLayout.getAddressPoints()) - AddressPoints.push_back(std::make_pair( - AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + - AP.second.AddressPointIndex)); + for (auto &&AP : VTLayout.getAddressPoints()) { + AddressPoint N{AP.first.getBase(), + VTLayout.getVTableOffset(AP.second.VTableIndex) + + AP.second.AddressPointIndex, + {}}; + llvm::raw_string_ostream Stream(N.TypeName); + getCXXABI().getMangleContext().mangleCanonicalTypeName( + QualType(N.Base->getTypeForDecl(), 0), Stream); + AddressPoints.push_back(std::move(N)); + } // Sort the address points for determinism. - llvm::sort(AddressPoints, [this](const AddressPoint &AP1, - const AddressPoint &AP2) { - if (&AP1 == &AP2) - return false; - - std::string S1; - llvm::raw_string_ostream O1(S1); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP1.first->getTypeForDecl(), 0), O1); - O1.flush(); - - std::string S2; - llvm::raw_string_ostream O2(S2); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP2.first->getTypeForDecl(), 0), O2); - O2.flush(); - - if (S1 < S2) - return true; - if (S1 != S2) - return false; - - return AP1.second < AP2.second; - }); + llvm::sort(AddressPoints); ArrayRef<VTableComponent> Comps = VTLayout.vtable_components(); for (auto AP : AddressPoints) { // Create type metadata for the address point. - AddVTableTypeMetadata(VTable, ComponentWidth * AP.second, AP.first); + AddVTableTypeMetadata(VTable, ComponentWidth * AP.Offset, AP.Base); // The class associated with each address point could also potentially be // used for indirect calls via a member function pointer, so we need to @@ -1356,7 +1352,7 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( Context.getMemberPointerType( Comps[I].getFunctionDecl()->getType(), - Context.getRecordType(AP.first).getTypePtr())); + Context.getRecordType(AP.Base).getTypePtr())); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } } |
