10b57cec5SDimitry Andric //===--- CGVTables.cpp - Emit LLVM Code for C++ vtables -------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This contains code dealing with C++ code generation of virtual tables. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "CGCXXABI.h" 140b57cec5SDimitry Andric #include "CodeGenFunction.h" 150b57cec5SDimitry Andric #include "CodeGenModule.h" 16480093f4SDimitry Andric #include "clang/AST/Attr.h" 170b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h" 180b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h" 190b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h" 200b57cec5SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h" 210b57cec5SDimitry Andric #include "clang/CodeGen/ConstantInitBuilder.h" 220b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 230b57cec5SDimitry Andric #include "llvm/Support/Format.h" 240b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 250b57cec5SDimitry Andric #include <algorithm> 260b57cec5SDimitry Andric #include <cstdio> 275f757f3fSDimitry Andric #include <utility> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace clang; 300b57cec5SDimitry Andric using namespace CodeGen; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric CodeGenVTables::CodeGenVTables(CodeGenModule &CGM) 330b57cec5SDimitry Andric : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {} 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric llvm::Constant *CodeGenModule::GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, 360b57cec5SDimitry Andric GlobalDecl GD) { 370b57cec5SDimitry Andric return GetOrCreateLLVMFunction(Name, FnTy, GD, /*ForVTable=*/true, 380b57cec5SDimitry Andric /*DontDefer=*/true, /*IsThunk=*/true); 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, 420b57cec5SDimitry Andric llvm::Function *ThunkFn, bool ForVTable, 430b57cec5SDimitry Andric GlobalDecl GD) { 440b57cec5SDimitry Andric CGM.setFunctionLinkage(GD, ThunkFn); 450b57cec5SDimitry Andric CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, 460b57cec5SDimitry Andric !Thunk.Return.isEmpty()); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric // Set the right visibility. 490b57cec5SDimitry Andric CGM.setGVProperties(ThunkFn, GD); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric if (!CGM.getCXXABI().exportThunk()) { 520b57cec5SDimitry Andric ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); 530b57cec5SDimitry Andric ThunkFn->setDSOLocal(true); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker()) 570b57cec5SDimitry Andric ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric #ifndef NDEBUG 610b57cec5SDimitry Andric static bool similar(const ABIArgInfo &infoL, CanQualType typeL, 620b57cec5SDimitry Andric const ABIArgInfo &infoR, CanQualType typeR) { 630b57cec5SDimitry Andric return (infoL.getKind() == infoR.getKind() && 640b57cec5SDimitry Andric (typeL == typeR || 650b57cec5SDimitry Andric (isa<PointerType>(typeL) && isa<PointerType>(typeR)) || 660b57cec5SDimitry Andric (isa<ReferenceType>(typeL) && isa<ReferenceType>(typeR)))); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric #endif 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric static RValue PerformReturnAdjustment(CodeGenFunction &CGF, 710b57cec5SDimitry Andric QualType ResultType, RValue RV, 720b57cec5SDimitry Andric const ThunkInfo &Thunk) { 730b57cec5SDimitry Andric // Emit the return adjustment. 740b57cec5SDimitry Andric bool NullCheckValue = !ResultType->isReferenceType(); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric llvm::BasicBlock *AdjustNull = nullptr; 770b57cec5SDimitry Andric llvm::BasicBlock *AdjustNotNull = nullptr; 780b57cec5SDimitry Andric llvm::BasicBlock *AdjustEnd = nullptr; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric llvm::Value *ReturnValue = RV.getScalarVal(); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric if (NullCheckValue) { 830b57cec5SDimitry Andric AdjustNull = CGF.createBasicBlock("adjust.null"); 840b57cec5SDimitry Andric AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); 850b57cec5SDimitry Andric AdjustEnd = CGF.createBasicBlock("adjust.end"); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); 880b57cec5SDimitry Andric CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); 890b57cec5SDimitry Andric CGF.EmitBlock(AdjustNotNull); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric auto ClassDecl = ResultType->getPointeeType()->getAsCXXRecordDecl(); 930b57cec5SDimitry Andric auto ClassAlign = CGF.CGM.getClassPointerAlignment(ClassDecl); 9481ad6265SDimitry Andric ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment( 9581ad6265SDimitry Andric CGF, 9681ad6265SDimitry Andric Address(ReturnValue, CGF.ConvertTypeForMem(ResultType->getPointeeType()), 9781ad6265SDimitry Andric ClassAlign), 980fca6ea1SDimitry Andric ClassDecl, Thunk.Return); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric if (NullCheckValue) { 1010b57cec5SDimitry Andric CGF.Builder.CreateBr(AdjustEnd); 1020b57cec5SDimitry Andric CGF.EmitBlock(AdjustNull); 1030b57cec5SDimitry Andric CGF.Builder.CreateBr(AdjustEnd); 1040b57cec5SDimitry Andric CGF.EmitBlock(AdjustEnd); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); 1070b57cec5SDimitry Andric PHI->addIncoming(ReturnValue, AdjustNotNull); 1080b57cec5SDimitry Andric PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), 1090b57cec5SDimitry Andric AdjustNull); 1100b57cec5SDimitry Andric ReturnValue = PHI; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric return RValue::get(ReturnValue); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric /// This function clones a function's DISubprogram node and enters it into 1170b57cec5SDimitry Andric /// a value map with the intent that the map can be utilized by the cloner 1180b57cec5SDimitry Andric /// to short-circuit Metadata node mapping. 1190b57cec5SDimitry Andric /// Furthermore, the function resolves any DILocalVariable nodes referenced 1200b57cec5SDimitry Andric /// by dbg.value intrinsics so they can be properly mapped during cloning. 1210b57cec5SDimitry Andric static void resolveTopLevelMetadata(llvm::Function *Fn, 1220b57cec5SDimitry Andric llvm::ValueToValueMapTy &VMap) { 1230b57cec5SDimitry Andric // Clone the DISubprogram node and put it into the Value map. 1240b57cec5SDimitry Andric auto *DIS = Fn->getSubprogram(); 1250b57cec5SDimitry Andric if (!DIS) 1260b57cec5SDimitry Andric return; 1270b57cec5SDimitry Andric auto *NewDIS = DIS->replaceWithDistinct(DIS->clone()); 1280b57cec5SDimitry Andric VMap.MD()[DIS].reset(NewDIS); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes 1310b57cec5SDimitry Andric // they are referencing. 132bdd1243dSDimitry Andric for (auto &BB : *Fn) { 1330b57cec5SDimitry Andric for (auto &I : BB) { 1340fca6ea1SDimitry Andric for (llvm::DbgVariableRecord &DVR : 1350fca6ea1SDimitry Andric llvm::filterDbgVars(I.getDbgRecordRange())) { 1360fca6ea1SDimitry Andric auto *DILocal = DVR.getVariable(); 1370fca6ea1SDimitry Andric if (!DILocal->isResolved()) 1380fca6ea1SDimitry Andric DILocal->resolve(); 1390fca6ea1SDimitry Andric } 1400b57cec5SDimitry Andric if (auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) { 1410b57cec5SDimitry Andric auto *DILocal = DII->getVariable(); 1420b57cec5SDimitry Andric if (!DILocal->isResolved()) 1430b57cec5SDimitry Andric DILocal->resolve(); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric // This function does roughly the same thing as GenerateThunk, but in a 1500b57cec5SDimitry Andric // very different way, so that va_start and va_end work correctly. 1510b57cec5SDimitry Andric // FIXME: This function assumes "this" is the first non-sret LLVM argument of 1520b57cec5SDimitry Andric // a function, and that there is an alloca built in the entry block 1530b57cec5SDimitry Andric // for all accesses to "this". 1540b57cec5SDimitry Andric // FIXME: This function assumes there is only one "ret" statement per function. 1550b57cec5SDimitry Andric // FIXME: Cloning isn't correct in the presence of indirect goto! 1560b57cec5SDimitry Andric // FIXME: This implementation of thunks bloats codesize by duplicating the 1570b57cec5SDimitry Andric // function definition. There are alternatives: 1580b57cec5SDimitry Andric // 1. Add some sort of stub support to LLVM for cases where we can 1590b57cec5SDimitry Andric // do a this adjustment, then a sibcall. 1600b57cec5SDimitry Andric // 2. We could transform the definition to take a va_list instead of an 1610b57cec5SDimitry Andric // actual variable argument list, then have the thunks (including a 1620b57cec5SDimitry Andric // no-op thunk for the regular definition) call va_start/va_end. 1630b57cec5SDimitry Andric // There's a bit of per-call overhead for this solution, but it's 1640b57cec5SDimitry Andric // better for codesize if the definition is long. 1650b57cec5SDimitry Andric llvm::Function * 1660b57cec5SDimitry Andric CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, 1670b57cec5SDimitry Andric const CGFunctionInfo &FnInfo, 1680b57cec5SDimitry Andric GlobalDecl GD, const ThunkInfo &Thunk) { 1690b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 170a7dea167SDimitry Andric const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 1710b57cec5SDimitry Andric QualType ResultType = FPT->getReturnType(); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // Get the original function 1740b57cec5SDimitry Andric assert(FnInfo.isVariadic()); 1750b57cec5SDimitry Andric llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo); 1760b57cec5SDimitry Andric llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); 1770b57cec5SDimitry Andric llvm::Function *BaseFn = cast<llvm::Function>(Callee); 1780b57cec5SDimitry Andric 179a7dea167SDimitry Andric // Cloning can't work if we don't have a definition. The Microsoft ABI may 180a7dea167SDimitry Andric // require thunks when a definition is not available. Emit an error in these 181a7dea167SDimitry Andric // cases. 182a7dea167SDimitry Andric if (!MD->isDefined()) { 183a7dea167SDimitry Andric CGM.ErrorUnsupported(MD, "return-adjusting thunk with variadic arguments"); 184a7dea167SDimitry Andric return Fn; 185a7dea167SDimitry Andric } 186a7dea167SDimitry Andric assert(!BaseFn->isDeclaration() && "cannot clone undefined variadic method"); 187a7dea167SDimitry Andric 1880b57cec5SDimitry Andric // Clone to thunk. 1890b57cec5SDimitry Andric llvm::ValueToValueMapTy VMap; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // We are cloning a function while some Metadata nodes are still unresolved. 1920b57cec5SDimitry Andric // Ensure that the value mapper does not encounter any of them. 1930b57cec5SDimitry Andric resolveTopLevelMetadata(BaseFn, VMap); 1940b57cec5SDimitry Andric llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap); 1950b57cec5SDimitry Andric Fn->replaceAllUsesWith(NewFn); 1960b57cec5SDimitry Andric NewFn->takeName(Fn); 1970b57cec5SDimitry Andric Fn->eraseFromParent(); 1980b57cec5SDimitry Andric Fn = NewFn; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric // "Initialize" CGF (minimally). 2010b57cec5SDimitry Andric CurFn = Fn; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // Get the "this" value 2040b57cec5SDimitry Andric llvm::Function::arg_iterator AI = Fn->arg_begin(); 2050b57cec5SDimitry Andric if (CGM.ReturnTypeUsesSRet(FnInfo)) 2060b57cec5SDimitry Andric ++AI; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Find the first store of "this", which will be to the alloca associated 2090b57cec5SDimitry Andric // with "this". 2100fca6ea1SDimitry Andric Address ThisPtr = makeNaturalAddressForPointer( 2110fca6ea1SDimitry Andric &*AI, MD->getFunctionObjectParameterType(), 21281ad6265SDimitry Andric CGM.getClassPointerAlignment(MD->getParent())); 2130b57cec5SDimitry Andric llvm::BasicBlock *EntryBB = &Fn->front(); 2140b57cec5SDimitry Andric llvm::BasicBlock::iterator ThisStore = 215349cc55cSDimitry Andric llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { 2160fca6ea1SDimitry Andric return isa<llvm::StoreInst>(I) && I.getOperand(0) == &*AI; 2170b57cec5SDimitry Andric }); 2180b57cec5SDimitry Andric assert(ThisStore != EntryBB->end() && 2190b57cec5SDimitry Andric "Store of this should be in entry block?"); 2200b57cec5SDimitry Andric // Adjust "this", if necessary. 2210b57cec5SDimitry Andric Builder.SetInsertPoint(&*ThisStore); 2220fca6ea1SDimitry Andric 2230fca6ea1SDimitry Andric const CXXRecordDecl *ThisValueClass = Thunk.ThisType->getPointeeCXXRecordDecl(); 2240fca6ea1SDimitry Andric llvm::Value *AdjustedThisPtr = CGM.getCXXABI().performThisAdjustment( 2250fca6ea1SDimitry Andric *this, ThisPtr, ThisValueClass, Thunk); 226a7dea167SDimitry Andric AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, 227a7dea167SDimitry Andric ThisStore->getOperand(0)->getType()); 2280b57cec5SDimitry Andric ThisStore->setOperand(0, AdjustedThisPtr); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric if (!Thunk.Return.isEmpty()) { 2310b57cec5SDimitry Andric // Fix up the returned value, if necessary. 2320b57cec5SDimitry Andric for (llvm::BasicBlock &BB : *Fn) { 2330b57cec5SDimitry Andric llvm::Instruction *T = BB.getTerminator(); 2340b57cec5SDimitry Andric if (isa<llvm::ReturnInst>(T)) { 2350b57cec5SDimitry Andric RValue RV = RValue::get(T->getOperand(0)); 2360b57cec5SDimitry Andric T->eraseFromParent(); 2370b57cec5SDimitry Andric Builder.SetInsertPoint(&BB); 2380b57cec5SDimitry Andric RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); 2390b57cec5SDimitry Andric Builder.CreateRet(RV.getScalarVal()); 2400b57cec5SDimitry Andric break; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric return Fn; 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, 2490b57cec5SDimitry Andric const CGFunctionInfo &FnInfo, 2500b57cec5SDimitry Andric bool IsUnprototyped) { 2510b57cec5SDimitry Andric assert(!CurGD.getDecl() && "CurGD was already set!"); 2520b57cec5SDimitry Andric CurGD = GD; 2530b57cec5SDimitry Andric CurFuncIsThunk = true; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // Build FunctionArgs. 2560b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 2570b57cec5SDimitry Andric QualType ThisType = MD->getThisType(); 2580b57cec5SDimitry Andric QualType ResultType; 2590b57cec5SDimitry Andric if (IsUnprototyped) 2600b57cec5SDimitry Andric ResultType = CGM.getContext().VoidTy; 2610b57cec5SDimitry Andric else if (CGM.getCXXABI().HasThisReturn(GD)) 2620b57cec5SDimitry Andric ResultType = ThisType; 2630b57cec5SDimitry Andric else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) 2640b57cec5SDimitry Andric ResultType = CGM.getContext().VoidPtrTy; 2650b57cec5SDimitry Andric else 266a7dea167SDimitry Andric ResultType = MD->getType()->castAs<FunctionProtoType>()->getReturnType(); 2670b57cec5SDimitry Andric FunctionArgList FunctionArgs; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // Create the implicit 'this' parameter declaration. 2700b57cec5SDimitry Andric CGM.getCXXABI().buildThisParam(*this, FunctionArgs); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric // Add the rest of the parameters, if we have a prototype to work with. 2730b57cec5SDimitry Andric if (!IsUnprototyped) { 2740b57cec5SDimitry Andric FunctionArgs.append(MD->param_begin(), MD->param_end()); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric if (isa<CXXDestructorDecl>(MD)) 2770b57cec5SDimitry Andric CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, 2780b57cec5SDimitry Andric FunctionArgs); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Start defining the function. 2820b57cec5SDimitry Andric auto NL = ApplyDebugLocation::CreateEmpty(*this); 2830b57cec5SDimitry Andric StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, 2840b57cec5SDimitry Andric MD->getLocation()); 2850b57cec5SDimitry Andric // Create a scope with an artificial location for the body of this function. 2860b57cec5SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. 2890b57cec5SDimitry Andric CGM.getCXXABI().EmitInstanceFunctionProlog(*this); 2900b57cec5SDimitry Andric CXXThisValue = CXXABIThisValue; 2910b57cec5SDimitry Andric CurCodeDecl = MD; 2920b57cec5SDimitry Andric CurFuncDecl = MD; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric void CodeGenFunction::FinishThunk() { 2960b57cec5SDimitry Andric // Clear these to restore the invariants expected by 2970b57cec5SDimitry Andric // StartFunction/FinishFunction. 2980b57cec5SDimitry Andric CurCodeDecl = nullptr; 2990b57cec5SDimitry Andric CurFuncDecl = nullptr; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric FinishFunction(); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee, 3050b57cec5SDimitry Andric const ThunkInfo *Thunk, 3060b57cec5SDimitry Andric bool IsUnprototyped) { 3070b57cec5SDimitry Andric assert(isa<CXXMethodDecl>(CurGD.getDecl()) && 3080b57cec5SDimitry Andric "Please use a new CGF for this thunk"); 3090b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl()); 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // Adjust the 'this' pointer if necessary 3120fca6ea1SDimitry Andric const CXXRecordDecl *ThisValueClass = 3130fca6ea1SDimitry Andric MD->getThisType()->getPointeeCXXRecordDecl(); 3140fca6ea1SDimitry Andric if (Thunk) 3150fca6ea1SDimitry Andric ThisValueClass = Thunk->ThisType->getPointeeCXXRecordDecl(); 3160fca6ea1SDimitry Andric 3170b57cec5SDimitry Andric llvm::Value *AdjustedThisPtr = 3180fca6ea1SDimitry Andric Thunk ? CGM.getCXXABI().performThisAdjustment(*this, LoadCXXThisAddress(), 3190fca6ea1SDimitry Andric ThisValueClass, *Thunk) 3200b57cec5SDimitry Andric : LoadCXXThis(); 3210b57cec5SDimitry Andric 322a7dea167SDimitry Andric // If perfect forwarding is required a variadic method, a method using 323a7dea167SDimitry Andric // inalloca, or an unprototyped thunk, use musttail. Emit an error if this 324a7dea167SDimitry Andric // thunk requires a return adjustment, since that is impossible with musttail. 325a7dea167SDimitry Andric if (CurFnInfo->usesInAlloca() || CurFnInfo->isVariadic() || IsUnprototyped) { 3260b57cec5SDimitry Andric if (Thunk && !Thunk->Return.isEmpty()) { 3270b57cec5SDimitry Andric if (IsUnprototyped) 3280b57cec5SDimitry Andric CGM.ErrorUnsupported( 3290b57cec5SDimitry Andric MD, "return-adjusting thunk with incomplete parameter type"); 330a7dea167SDimitry Andric else if (CurFnInfo->isVariadic()) 331a7dea167SDimitry Andric llvm_unreachable("shouldn't try to emit musttail return-adjusting " 332a7dea167SDimitry Andric "thunks for variadic functions"); 3330b57cec5SDimitry Andric else 3340b57cec5SDimitry Andric CGM.ErrorUnsupported( 3350b57cec5SDimitry Andric MD, "non-trivial argument copy for return-adjusting thunk"); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric EmitMustTailThunk(CurGD, AdjustedThisPtr, Callee); 3380b57cec5SDimitry Andric return; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // Start building CallArgs. 3420b57cec5SDimitry Andric CallArgList CallArgs; 3430b57cec5SDimitry Andric QualType ThisType = MD->getThisType(); 3440b57cec5SDimitry Andric CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric if (isa<CXXDestructorDecl>(MD)) 3470b57cec5SDimitry Andric CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs); 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric #ifndef NDEBUG 3500b57cec5SDimitry Andric unsigned PrefixArgs = CallArgs.size() - 1; 3510b57cec5SDimitry Andric #endif 3520b57cec5SDimitry Andric // Add the rest of the arguments. 3530b57cec5SDimitry Andric for (const ParmVarDecl *PD : MD->parameters()) 3540b57cec5SDimitry Andric EmitDelegateCallArg(CallArgs, PD, SourceLocation()); 3550b57cec5SDimitry Andric 356480093f4SDimitry Andric const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric #ifndef NDEBUG 3590b57cec5SDimitry Andric const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall( 3600b57cec5SDimitry Andric CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1), PrefixArgs); 3610b57cec5SDimitry Andric assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && 3620b57cec5SDimitry Andric CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && 3630b57cec5SDimitry Andric CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()); 3640b57cec5SDimitry Andric assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types 3650b57cec5SDimitry Andric similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), 3660b57cec5SDimitry Andric CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())); 3670b57cec5SDimitry Andric assert(CallFnInfo.arg_size() == CurFnInfo->arg_size()); 3680b57cec5SDimitry Andric for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i) 3690b57cec5SDimitry Andric assert(similar(CallFnInfo.arg_begin()[i].info, 3700b57cec5SDimitry Andric CallFnInfo.arg_begin()[i].type, 3710b57cec5SDimitry Andric CurFnInfo->arg_begin()[i].info, 3720b57cec5SDimitry Andric CurFnInfo->arg_begin()[i].type)); 3730b57cec5SDimitry Andric #endif 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // Determine whether we have a return value slot to use. 3760b57cec5SDimitry Andric QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) 3770b57cec5SDimitry Andric ? ThisType 3780b57cec5SDimitry Andric : CGM.getCXXABI().hasMostDerivedReturn(CurGD) 3790b57cec5SDimitry Andric ? CGM.getContext().VoidPtrTy 3800b57cec5SDimitry Andric : FPT->getReturnType(); 3810b57cec5SDimitry Andric ReturnValueSlot Slot; 3820b57cec5SDimitry Andric if (!ResultType->isVoidType() && 3835ffd83dbSDimitry Andric (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect || 3845ffd83dbSDimitry Andric hasAggregateEvaluationKind(ResultType))) 3855ffd83dbSDimitry Andric Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified(), 3865ffd83dbSDimitry Andric /*IsUnused=*/false, /*IsExternallyDestructed=*/true); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric // Now emit our call. 3890b57cec5SDimitry Andric llvm::CallBase *CallOrInvoke; 3900b57cec5SDimitry Andric RValue RV = EmitCall(*CurFnInfo, CGCallee::forDirect(Callee, CurGD), Slot, 3910b57cec5SDimitry Andric CallArgs, &CallOrInvoke); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // Consider return adjustment if we have ThunkInfo. 3940b57cec5SDimitry Andric if (Thunk && !Thunk->Return.isEmpty()) 3950b57cec5SDimitry Andric RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); 3960b57cec5SDimitry Andric else if (llvm::CallInst* Call = dyn_cast<llvm::CallInst>(CallOrInvoke)) 3970b57cec5SDimitry Andric Call->setTailCallKind(llvm::CallInst::TCK_Tail); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric // Emit return. 4000b57cec5SDimitry Andric if (!ResultType->isVoidType() && Slot.isNull()) 4010b57cec5SDimitry Andric CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric // Disable the final ARC autorelease. 4040b57cec5SDimitry Andric AutoreleaseResult = false; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric FinishThunk(); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD, 4100b57cec5SDimitry Andric llvm::Value *AdjustedThisPtr, 4110b57cec5SDimitry Andric llvm::FunctionCallee Callee) { 4120b57cec5SDimitry Andric // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery 4130b57cec5SDimitry Andric // to translate AST arguments into LLVM IR arguments. For thunks, we know 4140b57cec5SDimitry Andric // that the caller prototype more or less matches the callee prototype with 4150b57cec5SDimitry Andric // the exception of 'this'. 41681ad6265SDimitry Andric SmallVector<llvm::Value *, 8> Args(llvm::make_pointer_range(CurFn->args())); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric // Set the adjusted 'this' pointer. 4190b57cec5SDimitry Andric const ABIArgInfo &ThisAI = CurFnInfo->arg_begin()->info; 4200b57cec5SDimitry Andric if (ThisAI.isDirect()) { 4210b57cec5SDimitry Andric const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo(); 4220b57cec5SDimitry Andric int ThisArgNo = RetAI.isIndirect() && !RetAI.isSRetAfterThis() ? 1 : 0; 4230b57cec5SDimitry Andric llvm::Type *ThisType = Args[ThisArgNo]->getType(); 4240b57cec5SDimitry Andric if (ThisType != AdjustedThisPtr->getType()) 4250b57cec5SDimitry Andric AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); 4260b57cec5SDimitry Andric Args[ThisArgNo] = AdjustedThisPtr; 4270b57cec5SDimitry Andric } else { 4280b57cec5SDimitry Andric assert(ThisAI.isInAlloca() && "this is passed directly or inalloca"); 4290b57cec5SDimitry Andric Address ThisAddr = GetAddrOfLocalVar(CXXABIThisDecl); 4300b57cec5SDimitry Andric llvm::Type *ThisType = ThisAddr.getElementType(); 4310b57cec5SDimitry Andric if (ThisType != AdjustedThisPtr->getType()) 4320b57cec5SDimitry Andric AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); 4330b57cec5SDimitry Andric Builder.CreateStore(AdjustedThisPtr, ThisAddr); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric // Emit the musttail call manually. Even if the prologue pushed cleanups, we 4370b57cec5SDimitry Andric // don't actually want to run them. 4380b57cec5SDimitry Andric llvm::CallInst *Call = Builder.CreateCall(Callee, Args); 4390b57cec5SDimitry Andric Call->setTailCallKind(llvm::CallInst::TCK_MustTail); 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // Apply the standard set of call attributes. 4420b57cec5SDimitry Andric unsigned CallingConv; 4430b57cec5SDimitry Andric llvm::AttributeList Attrs; 4440b57cec5SDimitry Andric CGM.ConstructAttributeList(Callee.getCallee()->getName(), *CurFnInfo, GD, 445fe6060f1SDimitry Andric Attrs, CallingConv, /*AttrOnCallSite=*/true, 446fe6060f1SDimitry Andric /*IsThunk=*/false); 4470b57cec5SDimitry Andric Call->setAttributes(Attrs); 4480b57cec5SDimitry Andric Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric if (Call->getType()->isVoidTy()) 4510b57cec5SDimitry Andric Builder.CreateRetVoid(); 4520b57cec5SDimitry Andric else 4530b57cec5SDimitry Andric Builder.CreateRet(Call); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric // Finish the function to maintain CodeGenFunction invariants. 4560b57cec5SDimitry Andric // FIXME: Don't emit unreachable code. 4570b57cec5SDimitry Andric EmitBlock(createBasicBlock()); 4583788a439SDimitry Andric 4593788a439SDimitry Andric FinishThunk(); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric void CodeGenFunction::generateThunk(llvm::Function *Fn, 4630b57cec5SDimitry Andric const CGFunctionInfo &FnInfo, GlobalDecl GD, 4640b57cec5SDimitry Andric const ThunkInfo &Thunk, 4650b57cec5SDimitry Andric bool IsUnprototyped) { 4660b57cec5SDimitry Andric StartThunk(Fn, GD, FnInfo, IsUnprototyped); 4670b57cec5SDimitry Andric // Create a scope with an artificial location for the body of this function. 4680b57cec5SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric // Get our callee. Use a placeholder type if this method is unprototyped so 4710b57cec5SDimitry Andric // that CodeGenModule doesn't try to set attributes. 4720b57cec5SDimitry Andric llvm::Type *Ty; 4730b57cec5SDimitry Andric if (IsUnprototyped) 4740b57cec5SDimitry Andric Ty = llvm::StructType::get(getLLVMContext()); 4750b57cec5SDimitry Andric else 4760b57cec5SDimitry Andric Ty = CGM.getTypes().GetFunctionType(FnInfo); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric // Make the call and return the result. 4810b57cec5SDimitry Andric EmitCallAndReturnForThunk(llvm::FunctionCallee(Fn->getFunctionType(), Callee), 4820b57cec5SDimitry Andric &Thunk, IsUnprototyped); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD, 4860b57cec5SDimitry Andric bool IsUnprototyped, bool ForVTable) { 4870b57cec5SDimitry Andric // Always emit thunks in the MS C++ ABI. We cannot rely on other TUs to 4880b57cec5SDimitry Andric // provide thunks for us. 4890b57cec5SDimitry Andric if (CGM.getTarget().getCXXABI().isMicrosoft()) 4900b57cec5SDimitry Andric return true; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric // In the Itanium C++ ABI, vtable thunks are provided by TUs that provide 4930b57cec5SDimitry Andric // definitions of the main method. Therefore, emitting thunks with the vtable 4940b57cec5SDimitry Andric // is purely an optimization. Emit the thunk if optimizations are enabled and 4950b57cec5SDimitry Andric // all of the parameter types are complete. 4960b57cec5SDimitry Andric if (ForVTable) 4970b57cec5SDimitry Andric return CGM.getCodeGenOpts().OptimizationLevel && !IsUnprototyped; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // Always emit thunks along with the method definition. 5000b57cec5SDimitry Andric return true; 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD, 5040b57cec5SDimitry Andric const ThunkInfo &TI, 5050b57cec5SDimitry Andric bool ForVTable) { 5060b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // First, get a declaration. Compute the mangled name. Don't worry about 5090b57cec5SDimitry Andric // getting the function prototype right, since we may only need this 5100b57cec5SDimitry Andric // declaration to fill in a vtable slot. 5110b57cec5SDimitry Andric SmallString<256> Name; 5120b57cec5SDimitry Andric MangleContext &MCtx = CGM.getCXXABI().getMangleContext(); 5130b57cec5SDimitry Andric llvm::raw_svector_ostream Out(Name); 5140fca6ea1SDimitry Andric 5150fca6ea1SDimitry Andric if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { 5160fca6ea1SDimitry Andric MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI, 5170fca6ea1SDimitry Andric /* elideOverrideInfo */ false, Out); 5180fca6ea1SDimitry Andric } else 5190fca6ea1SDimitry Andric MCtx.mangleThunk(MD, TI, /* elideOverrideInfo */ false, Out); 5200fca6ea1SDimitry Andric 5210fca6ea1SDimitry Andric if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) { 5220fca6ea1SDimitry Andric Name = ""; 5230b57cec5SDimitry Andric if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) 5240fca6ea1SDimitry Andric MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI, 5250fca6ea1SDimitry Andric /* elideOverrideInfo */ true, Out); 5260b57cec5SDimitry Andric else 5270fca6ea1SDimitry Andric MCtx.mangleThunk(MD, TI, /* elideOverrideInfo */ true, Out); 5280fca6ea1SDimitry Andric } 5290fca6ea1SDimitry Andric 5300b57cec5SDimitry Andric llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD); 5310b57cec5SDimitry Andric llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD); 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // If we don't need to emit a definition, return this declaration as is. 5340b57cec5SDimitry Andric bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible( 5350b57cec5SDimitry Andric MD->getType()->castAs<FunctionType>()); 5360b57cec5SDimitry Andric if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable)) 5370b57cec5SDimitry Andric return Thunk; 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // Arrange a function prototype appropriate for a function definition. In some 5400b57cec5SDimitry Andric // cases in the MS ABI, we may need to build an unprototyped musttail thunk. 5410b57cec5SDimitry Andric const CGFunctionInfo &FnInfo = 5420b57cec5SDimitry Andric IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD) 5430b57cec5SDimitry Andric : CGM.getTypes().arrangeGlobalDeclaration(GD); 5440b57cec5SDimitry Andric llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo); 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric // If the type of the underlying GlobalValue is wrong, we'll have to replace 5470b57cec5SDimitry Andric // it. It should be a declaration. 5480b57cec5SDimitry Andric llvm::Function *ThunkFn = cast<llvm::Function>(Thunk->stripPointerCasts()); 5490b57cec5SDimitry Andric if (ThunkFn->getFunctionType() != ThunkFnTy) { 5500b57cec5SDimitry Andric llvm::GlobalValue *OldThunkFn = ThunkFn; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration"); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric // Remove the name from the old thunk function and get a new thunk. 5550b57cec5SDimitry Andric OldThunkFn->setName(StringRef()); 5560b57cec5SDimitry Andric ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage, 5570b57cec5SDimitry Andric Name.str(), &CGM.getModule()); 558fe6060f1SDimitry Andric CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/false); 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric if (!OldThunkFn->use_empty()) { 5615f757f3fSDimitry Andric OldThunkFn->replaceAllUsesWith(ThunkFn); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric // Remove the old thunk. 5650b57cec5SDimitry Andric OldThunkFn->eraseFromParent(); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions(); 5690b57cec5SDimitry Andric bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions; 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric if (!ThunkFn->isDeclaration()) { 5720b57cec5SDimitry Andric if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) { 5730b57cec5SDimitry Andric // There is already a thunk emitted for this function, do nothing. 5740b57cec5SDimitry Andric return ThunkFn; 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); 5780b57cec5SDimitry Andric return ThunkFn; 5790b57cec5SDimitry Andric } 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric // If this will be unprototyped, add the "thunk" attribute so that LLVM knows 5820b57cec5SDimitry Andric // that the return type is meaningless. These thunks can be used to call 5830b57cec5SDimitry Andric // functions with differing return types, and the caller is required to cast 5840b57cec5SDimitry Andric // the prototype appropriately to extract the correct value. 5850b57cec5SDimitry Andric if (IsUnprototyped) 5860b57cec5SDimitry Andric ThunkFn->addFnAttr("thunk"); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn); 5890b57cec5SDimitry Andric 590a7dea167SDimitry Andric // Thunks for variadic methods are special because in general variadic 5913788a439SDimitry Andric // arguments cannot be perfectly forwarded. In the general case, clang 592a7dea167SDimitry Andric // implements such thunks by cloning the original function body. However, for 593a7dea167SDimitry Andric // thunks with no return adjustment on targets that support musttail, we can 594a7dea167SDimitry Andric // use musttail to perfectly forward the variadic arguments. 595a7dea167SDimitry Andric bool ShouldCloneVarArgs = false; 5960b57cec5SDimitry Andric if (!IsUnprototyped && ThunkFn->isVarArg()) { 597a7dea167SDimitry Andric ShouldCloneVarArgs = true; 598a7dea167SDimitry Andric if (TI.Return.isEmpty()) { 599a7dea167SDimitry Andric switch (CGM.getTriple().getArch()) { 600a7dea167SDimitry Andric case llvm::Triple::x86_64: 601a7dea167SDimitry Andric case llvm::Triple::x86: 602a7dea167SDimitry Andric case llvm::Triple::aarch64: 603a7dea167SDimitry Andric ShouldCloneVarArgs = false; 604a7dea167SDimitry Andric break; 605a7dea167SDimitry Andric default: 606a7dea167SDimitry Andric break; 607a7dea167SDimitry Andric } 608a7dea167SDimitry Andric } 609a7dea167SDimitry Andric } 610a7dea167SDimitry Andric 611a7dea167SDimitry Andric if (ShouldCloneVarArgs) { 6120b57cec5SDimitry Andric if (UseAvailableExternallyLinkage) 6130b57cec5SDimitry Andric return ThunkFn; 614a7dea167SDimitry Andric ThunkFn = 615a7dea167SDimitry Andric CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI); 6160b57cec5SDimitry Andric } else { 6170b57cec5SDimitry Andric // Normal thunk body generation. 6180b57cec5SDimitry Andric CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); 6220b57cec5SDimitry Andric return ThunkFn; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric void CodeGenVTables::EmitThunks(GlobalDecl GD) { 6260b57cec5SDimitry Andric const CXXMethodDecl *MD = 6270b57cec5SDimitry Andric cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl(); 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric // We don't need to generate thunks for the base destructor. 6300b57cec5SDimitry Andric if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) 6310b57cec5SDimitry Andric return; 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector = 6340b57cec5SDimitry Andric VTContext->getThunkInfo(GD); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric if (!ThunkInfoVector) 6370b57cec5SDimitry Andric return; 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric for (const ThunkInfo& Thunk : *ThunkInfoVector) 6400b57cec5SDimitry Andric maybeEmitThunk(GD, Thunk, /*ForVTable=*/false); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6435ffd83dbSDimitry Andric void CodeGenVTables::addRelativeComponent(ConstantArrayBuilder &builder, 6445ffd83dbSDimitry Andric llvm::Constant *component, 6455ffd83dbSDimitry Andric unsigned vtableAddressPoint, 6465ffd83dbSDimitry Andric bool vtableHasLocalLinkage, 6475ffd83dbSDimitry Andric bool isCompleteDtor) const { 6485ffd83dbSDimitry Andric // No need to get the offset of a nullptr. 6495ffd83dbSDimitry Andric if (component->isNullValue()) 6505ffd83dbSDimitry Andric return builder.add(llvm::ConstantInt::get(CGM.Int32Ty, 0)); 6510b57cec5SDimitry Andric 6525ffd83dbSDimitry Andric auto *globalVal = 6535ffd83dbSDimitry Andric cast<llvm::GlobalValue>(component->stripPointerCastsAndAliases()); 6545ffd83dbSDimitry Andric llvm::Module &module = CGM.getModule(); 6555ffd83dbSDimitry Andric 6565ffd83dbSDimitry Andric // We don't want to copy the linkage of the vtable exactly because we still 6575ffd83dbSDimitry Andric // want the stub/proxy to be emitted for properly calculating the offset. 6585ffd83dbSDimitry Andric // Examples where there would be no symbol emitted are available_externally 6595ffd83dbSDimitry Andric // and private linkages. 6605f757f3fSDimitry Andric // 6615f757f3fSDimitry Andric // `internal` linkage results in STB_LOCAL Elf binding while still manifesting a 6625f757f3fSDimitry Andric // local symbol. 6635f757f3fSDimitry Andric // 6645f757f3fSDimitry Andric // `linkonce_odr` linkage results in a STB_DEFAULT Elf binding but also allows for 6655f757f3fSDimitry Andric // the rtti_proxy to be transparently replaced with a GOTPCREL reloc by a 6665f757f3fSDimitry Andric // target that supports this replacement. 6675f757f3fSDimitry Andric auto stubLinkage = vtableHasLocalLinkage 6685f757f3fSDimitry Andric ? llvm::GlobalValue::InternalLinkage 6695f757f3fSDimitry Andric : llvm::GlobalValue::LinkOnceODRLinkage; 6705ffd83dbSDimitry Andric 6715ffd83dbSDimitry Andric llvm::Constant *target; 6725ffd83dbSDimitry Andric if (auto *func = dyn_cast<llvm::Function>(globalVal)) { 673e8d8bef9SDimitry Andric target = llvm::DSOLocalEquivalent::get(func); 6745ffd83dbSDimitry Andric } else { 6755ffd83dbSDimitry Andric llvm::SmallString<16> rttiProxyName(globalVal->getName()); 6765ffd83dbSDimitry Andric rttiProxyName.append(".rtti_proxy"); 6775ffd83dbSDimitry Andric 6785ffd83dbSDimitry Andric // The RTTI component may not always be emitted in the same linkage unit as 6795ffd83dbSDimitry Andric // the vtable. As a general case, we can make a dso_local proxy to the RTTI 6805ffd83dbSDimitry Andric // that points to the actual RTTI struct somewhere. This will result in a 6815ffd83dbSDimitry Andric // GOTPCREL relocation when taking the relative offset to the proxy. 6825ffd83dbSDimitry Andric llvm::GlobalVariable *proxy = module.getNamedGlobal(rttiProxyName); 6835ffd83dbSDimitry Andric if (!proxy) { 6845ffd83dbSDimitry Andric proxy = new llvm::GlobalVariable(module, globalVal->getType(), 6855ffd83dbSDimitry Andric /*isConstant=*/true, stubLinkage, 6865ffd83dbSDimitry Andric globalVal, rttiProxyName); 6875ffd83dbSDimitry Andric proxy->setDSOLocal(true); 6885ffd83dbSDimitry Andric proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 6895ffd83dbSDimitry Andric if (!proxy->hasLocalLinkage()) { 6905ffd83dbSDimitry Andric proxy->setVisibility(llvm::GlobalValue::HiddenVisibility); 6915ffd83dbSDimitry Andric proxy->setComdat(module.getOrInsertComdat(rttiProxyName)); 6925ffd83dbSDimitry Andric } 693bdd1243dSDimitry Andric // Do not instrument the rtti proxies with hwasan to avoid a duplicate 694bdd1243dSDimitry Andric // symbol error. Aliases generated by hwasan will retain the same namebut 695bdd1243dSDimitry Andric // the addresses they are set to may have different tags from different 696bdd1243dSDimitry Andric // compilation units. We don't run into this without hwasan because the 697bdd1243dSDimitry Andric // proxies are in comdat groups, but those aren't propagated to the alias. 698bdd1243dSDimitry Andric RemoveHwasanMetadata(proxy); 6995ffd83dbSDimitry Andric } 7005ffd83dbSDimitry Andric target = proxy; 7015ffd83dbSDimitry Andric } 7025ffd83dbSDimitry Andric 7035ffd83dbSDimitry Andric builder.addRelativeOffsetToPosition(CGM.Int32Ty, target, 7045ffd83dbSDimitry Andric /*position=*/vtableAddressPoint); 7055ffd83dbSDimitry Andric } 7065ffd83dbSDimitry Andric 707bdd1243dSDimitry Andric static bool UseRelativeLayout(const CodeGenModule &CGM) { 7085ffd83dbSDimitry Andric return CGM.getTarget().getCXXABI().isItaniumFamily() && 7095ffd83dbSDimitry Andric CGM.getItaniumVTableContext().isRelativeLayout(); 7105ffd83dbSDimitry Andric } 7115ffd83dbSDimitry Andric 712bdd1243dSDimitry Andric bool CodeGenVTables::useRelativeLayout() const { 713bdd1243dSDimitry Andric return UseRelativeLayout(CGM); 714bdd1243dSDimitry Andric } 715bdd1243dSDimitry Andric 716bdd1243dSDimitry Andric llvm::Type *CodeGenModule::getVTableComponentType() const { 717bdd1243dSDimitry Andric if (UseRelativeLayout(*this)) 718bdd1243dSDimitry Andric return Int32Ty; 71906c3fb27SDimitry Andric return GlobalsInt8PtrTy; 720bdd1243dSDimitry Andric } 721bdd1243dSDimitry Andric 7225ffd83dbSDimitry Andric llvm::Type *CodeGenVTables::getVTableComponentType() const { 723bdd1243dSDimitry Andric return CGM.getVTableComponentType(); 7245ffd83dbSDimitry Andric } 7255ffd83dbSDimitry Andric 7265ffd83dbSDimitry Andric static void AddPointerLayoutOffset(const CodeGenModule &CGM, 7275ffd83dbSDimitry Andric ConstantArrayBuilder &builder, 7285ffd83dbSDimitry Andric CharUnits offset) { 7290b57cec5SDimitry Andric builder.add(llvm::ConstantExpr::getIntToPtr( 7300b57cec5SDimitry Andric llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()), 73106c3fb27SDimitry Andric CGM.GlobalsInt8PtrTy)); 7325ffd83dbSDimitry Andric } 7335ffd83dbSDimitry Andric 7345ffd83dbSDimitry Andric static void AddRelativeLayoutOffset(const CodeGenModule &CGM, 7355ffd83dbSDimitry Andric ConstantArrayBuilder &builder, 7365ffd83dbSDimitry Andric CharUnits offset) { 7375ffd83dbSDimitry Andric builder.add(llvm::ConstantInt::get(CGM.Int32Ty, offset.getQuantity())); 7385ffd83dbSDimitry Andric } 7395ffd83dbSDimitry Andric 7405ffd83dbSDimitry Andric void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, 7415ffd83dbSDimitry Andric const VTableLayout &layout, 7425ffd83dbSDimitry Andric unsigned componentIndex, 7435ffd83dbSDimitry Andric llvm::Constant *rtti, 7445ffd83dbSDimitry Andric unsigned &nextVTableThunkIndex, 7455ffd83dbSDimitry Andric unsigned vtableAddressPoint, 7465ffd83dbSDimitry Andric bool vtableHasLocalLinkage) { 7475ffd83dbSDimitry Andric auto &component = layout.vtable_components()[componentIndex]; 7485ffd83dbSDimitry Andric 7495ffd83dbSDimitry Andric auto addOffsetConstant = 7505ffd83dbSDimitry Andric useRelativeLayout() ? AddRelativeLayoutOffset : AddPointerLayoutOffset; 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric switch (component.getKind()) { 7530b57cec5SDimitry Andric case VTableComponent::CK_VCallOffset: 7545ffd83dbSDimitry Andric return addOffsetConstant(CGM, builder, component.getVCallOffset()); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric case VTableComponent::CK_VBaseOffset: 7575ffd83dbSDimitry Andric return addOffsetConstant(CGM, builder, component.getVBaseOffset()); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric case VTableComponent::CK_OffsetToTop: 7605ffd83dbSDimitry Andric return addOffsetConstant(CGM, builder, component.getOffsetToTop()); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric case VTableComponent::CK_RTTI: 7635ffd83dbSDimitry Andric if (useRelativeLayout()) 7645ffd83dbSDimitry Andric return addRelativeComponent(builder, rtti, vtableAddressPoint, 7655ffd83dbSDimitry Andric vtableHasLocalLinkage, 7665ffd83dbSDimitry Andric /*isCompleteDtor=*/false); 7675ffd83dbSDimitry Andric else 76806c3fb27SDimitry Andric return builder.add(rtti); 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric case VTableComponent::CK_FunctionPointer: 7710b57cec5SDimitry Andric case VTableComponent::CK_CompleteDtorPointer: 7720b57cec5SDimitry Andric case VTableComponent::CK_DeletingDtorPointer: { 773fe6060f1SDimitry Andric GlobalDecl GD = component.getGlobalDecl(); 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric if (CGM.getLangOpts().CUDA) { 7760b57cec5SDimitry Andric // Emit NULL for methods we can't codegen on this 7770b57cec5SDimitry Andric // side. Otherwise we'd end up with vtable with unresolved 7780b57cec5SDimitry Andric // references. 7790b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 7800b57cec5SDimitry Andric // OK on device side: functions w/ __device__ attribute 7810b57cec5SDimitry Andric // OK on host side: anything except __device__-only functions. 7820b57cec5SDimitry Andric bool CanEmitMethod = 7830b57cec5SDimitry Andric CGM.getLangOpts().CUDAIsDevice 7840b57cec5SDimitry Andric ? MD->hasAttr<CUDADeviceAttr>() 7850b57cec5SDimitry Andric : (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>()); 7860b57cec5SDimitry Andric if (!CanEmitMethod) 78706c3fb27SDimitry Andric return builder.add( 78806c3fb27SDimitry Andric llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy)); 7890b57cec5SDimitry Andric // Method is acceptable, continue processing as usual. 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 792480093f4SDimitry Andric auto getSpecialVirtualFn = [&](StringRef name) -> llvm::Constant * { 7935ffd83dbSDimitry Andric // FIXME(PR43094): When merging comdat groups, lld can select a local 7945ffd83dbSDimitry Andric // symbol as the signature symbol even though it cannot be accessed 7955ffd83dbSDimitry Andric // outside that symbol's TU. The relative vtables ABI would make 7965ffd83dbSDimitry Andric // __cxa_pure_virtual and __cxa_deleted_virtual local symbols, and 7975ffd83dbSDimitry Andric // depending on link order, the comdat groups could resolve to the one 7985ffd83dbSDimitry Andric // with the local symbol. As a temporary solution, fill these components 7995ffd83dbSDimitry Andric // with zero. We shouldn't be calling these in the first place anyway. 8005ffd83dbSDimitry Andric if (useRelativeLayout()) 80106c3fb27SDimitry Andric return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); 8025ffd83dbSDimitry Andric 803480093f4SDimitry Andric // For NVPTX devices in OpenMP emit special functon as null pointers, 804480093f4SDimitry Andric // otherwise linking ends up with unresolved references. 80506c3fb27SDimitry Andric if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice && 806480093f4SDimitry Andric CGM.getTriple().isNVPTX()) 80706c3fb27SDimitry Andric return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); 8080b57cec5SDimitry Andric llvm::FunctionType *fnTy = 8090b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); 8100b57cec5SDimitry Andric llvm::Constant *fn = cast<llvm::Constant>( 8110b57cec5SDimitry Andric CGM.CreateRuntimeFunction(fnTy, name).getCallee()); 8120b57cec5SDimitry Andric if (auto f = dyn_cast<llvm::Function>(fn)) 8130b57cec5SDimitry Andric f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 81406c3fb27SDimitry Andric return fn; 8150b57cec5SDimitry Andric }; 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric llvm::Constant *fnPtr; 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric // Pure virtual member functions. 8207a6dacacSDimitry Andric if (cast<CXXMethodDecl>(GD.getDecl())->isPureVirtual()) { 8210b57cec5SDimitry Andric if (!PureVirtualFn) 8220b57cec5SDimitry Andric PureVirtualFn = 8230b57cec5SDimitry Andric getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); 8240b57cec5SDimitry Andric fnPtr = PureVirtualFn; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // Deleted virtual member functions. 8270b57cec5SDimitry Andric } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) { 8280b57cec5SDimitry Andric if (!DeletedVirtualFn) 8290b57cec5SDimitry Andric DeletedVirtualFn = 8300b57cec5SDimitry Andric getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName()); 8310b57cec5SDimitry Andric fnPtr = DeletedVirtualFn; 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric // Thunks. 8340b57cec5SDimitry Andric } else if (nextVTableThunkIndex < layout.vtable_thunks().size() && 8355ffd83dbSDimitry Andric layout.vtable_thunks()[nextVTableThunkIndex].first == 8365ffd83dbSDimitry Andric componentIndex) { 8370b57cec5SDimitry Andric auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second; 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric nextVTableThunkIndex++; 8400b57cec5SDimitry Andric fnPtr = maybeEmitThunk(GD, thunkInfo, /*ForVTable=*/true); 8410fca6ea1SDimitry Andric if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) { 8420fca6ea1SDimitry Andric assert(thunkInfo.Method && "Method not set"); 8430fca6ea1SDimitry Andric GD = GD.getWithDecl(thunkInfo.Method); 8440fca6ea1SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // Otherwise we can use the method definition directly. 8470b57cec5SDimitry Andric } else { 8480b57cec5SDimitry Andric llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD); 8490b57cec5SDimitry Andric fnPtr = CGM.GetAddrOfFunction(GD, fnTy, /*ForVTable=*/true); 8500fca6ea1SDimitry Andric if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) 8510fca6ea1SDimitry Andric GD = getItaniumVTableContext().findOriginalMethod(GD); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8545ffd83dbSDimitry Andric if (useRelativeLayout()) { 8555ffd83dbSDimitry Andric return addRelativeComponent( 8565ffd83dbSDimitry Andric builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage, 8575ffd83dbSDimitry Andric component.getKind() == VTableComponent::CK_CompleteDtorPointer); 85806c3fb27SDimitry Andric } else { 85906c3fb27SDimitry Andric // TODO: this icky and only exists due to functions being in the generic 86006c3fb27SDimitry Andric // address space, rather than the global one, even though they are 86106c3fb27SDimitry Andric // globals; fixing said issue might be intrusive, and will be done 86206c3fb27SDimitry Andric // later. 86306c3fb27SDimitry Andric unsigned FnAS = fnPtr->getType()->getPointerAddressSpace(); 86406c3fb27SDimitry Andric unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace(); 86506c3fb27SDimitry Andric 86606c3fb27SDimitry Andric if (FnAS != GVAS) 86706c3fb27SDimitry Andric fnPtr = 86806c3fb27SDimitry Andric llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy); 8690fca6ea1SDimitry Andric if (const auto &Schema = 8700fca6ea1SDimitry Andric CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) 8710fca6ea1SDimitry Andric return builder.addSignedPointer(fnPtr, Schema, GD, QualType()); 87206c3fb27SDimitry Andric return builder.add(fnPtr); 87306c3fb27SDimitry Andric } 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric case VTableComponent::CK_UnusedFunctionPointer: 8775ffd83dbSDimitry Andric if (useRelativeLayout()) 8785ffd83dbSDimitry Andric return builder.add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty)); 8795ffd83dbSDimitry Andric else 88006c3fb27SDimitry Andric return builder.addNullPointer(CGM.GlobalsInt8PtrTy); 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric llvm_unreachable("Unexpected vtable component kind"); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) { 8870b57cec5SDimitry Andric SmallVector<llvm::Type *, 4> tys; 8885ffd83dbSDimitry Andric llvm::Type *componentType = getVTableComponentType(); 8895ffd83dbSDimitry Andric for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) 8905ffd83dbSDimitry Andric tys.push_back(llvm::ArrayType::get(componentType, layout.getVTableSize(i))); 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric return llvm::StructType::get(CGM.getLLVMContext(), tys); 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder, 8960b57cec5SDimitry Andric const VTableLayout &layout, 8975ffd83dbSDimitry Andric llvm::Constant *rtti, 8985ffd83dbSDimitry Andric bool vtableHasLocalLinkage) { 8995ffd83dbSDimitry Andric llvm::Type *componentType = getVTableComponentType(); 9005ffd83dbSDimitry Andric 9015ffd83dbSDimitry Andric const auto &addressPoints = layout.getAddressPointIndices(); 9020b57cec5SDimitry Andric unsigned nextVTableThunkIndex = 0; 9035ffd83dbSDimitry Andric for (unsigned vtableIndex = 0, endIndex = layout.getNumVTables(); 9045ffd83dbSDimitry Andric vtableIndex != endIndex; ++vtableIndex) { 9055ffd83dbSDimitry Andric auto vtableElem = builder.beginArray(componentType); 9065ffd83dbSDimitry Andric 9075ffd83dbSDimitry Andric size_t vtableStart = layout.getVTableOffset(vtableIndex); 9085ffd83dbSDimitry Andric size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex); 9095ffd83dbSDimitry Andric for (size_t componentIndex = vtableStart; componentIndex < vtableEnd; 9105ffd83dbSDimitry Andric ++componentIndex) { 9115ffd83dbSDimitry Andric addVTableComponent(vtableElem, layout, componentIndex, rtti, 9125ffd83dbSDimitry Andric nextVTableThunkIndex, addressPoints[vtableIndex], 9135ffd83dbSDimitry Andric vtableHasLocalLinkage); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric vtableElem.finishAndAddTo(builder); 9160b57cec5SDimitry Andric } 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric 9195ffd83dbSDimitry Andric llvm::GlobalVariable *CodeGenVTables::GenerateConstructionVTable( 9205ffd83dbSDimitry Andric const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, 9210b57cec5SDimitry Andric llvm::GlobalVariable::LinkageTypes Linkage, 9220b57cec5SDimitry Andric VTableAddressPointsMapTy &AddressPoints) { 9230b57cec5SDimitry Andric if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) 9240b57cec5SDimitry Andric DI->completeClassData(Base.getBase()); 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric std::unique_ptr<VTableLayout> VTLayout( 9270b57cec5SDimitry Andric getItaniumVTableContext().createConstructionVTableLayout( 9280b57cec5SDimitry Andric Base.getBase(), Base.getBaseOffset(), BaseIsVirtual, RD)); 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric // Add the address points. 9310b57cec5SDimitry Andric AddressPoints = VTLayout->getAddressPoints(); 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric // Get the mangled construction vtable name. 9340b57cec5SDimitry Andric SmallString<256> OutName; 9350b57cec5SDimitry Andric llvm::raw_svector_ostream Out(OutName); 9360b57cec5SDimitry Andric cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) 9370b57cec5SDimitry Andric .mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), 9380b57cec5SDimitry Andric Base.getBase(), Out); 9395ffd83dbSDimitry Andric SmallString<256> Name(OutName); 9405ffd83dbSDimitry Andric 9415ffd83dbSDimitry Andric bool UsingRelativeLayout = getItaniumVTableContext().isRelativeLayout(); 9425ffd83dbSDimitry Andric bool VTableAliasExists = 9435ffd83dbSDimitry Andric UsingRelativeLayout && CGM.getModule().getNamedAlias(Name); 9445ffd83dbSDimitry Andric if (VTableAliasExists) { 9455ffd83dbSDimitry Andric // We previously made the vtable hidden and changed its name. 9465ffd83dbSDimitry Andric Name.append(".local"); 9475ffd83dbSDimitry Andric } 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric llvm::Type *VTType = getVTableType(*VTLayout); 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric // Construction vtable symbols are not part of the Itanium ABI, so we cannot 9520b57cec5SDimitry Andric // guarantee that they actually will be available externally. Instead, when 9530b57cec5SDimitry Andric // emitting an available_externally VTT, we provide references to an internal 9540b57cec5SDimitry Andric // linkage construction vtable. The ABI only requires complete-object vtables 9550b57cec5SDimitry Andric // to be the same for all instances of a type, not construction vtables. 9560b57cec5SDimitry Andric if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) 9570b57cec5SDimitry Andric Linkage = llvm::GlobalVariable::InternalLinkage; 9580b57cec5SDimitry Andric 959bdd1243dSDimitry Andric llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType); 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric // Create the variable that will hold the construction vtable. 9620b57cec5SDimitry Andric llvm::GlobalVariable *VTable = 9630b57cec5SDimitry Andric CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align); 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric // V-tables are always unnamed_addr. 9660b57cec5SDimitry Andric VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor( 9690b57cec5SDimitry Andric CGM.getContext().getTagDeclType(Base.getBase())); 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric // Create and set the initializer. 9720b57cec5SDimitry Andric ConstantInitBuilder builder(CGM); 9730b57cec5SDimitry Andric auto components = builder.beginStruct(); 9745ffd83dbSDimitry Andric createVTableInitializer(components, *VTLayout, RTTI, 9755ffd83dbSDimitry Andric VTable->hasLocalLinkage()); 9760b57cec5SDimitry Andric components.finishAndSetAsInitializer(VTable); 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric // Set properties only after the initializer has been set to ensure that the 9790b57cec5SDimitry Andric // GV is treated as definition and not declaration. 9800b57cec5SDimitry Andric assert(!VTable->isDeclaration() && "Shouldn't set properties on declaration"); 9810b57cec5SDimitry Andric CGM.setGVProperties(VTable, RD); 9820b57cec5SDimitry Andric 983a7dea167SDimitry Andric CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout.get()); 9840b57cec5SDimitry Andric 985bdd1243dSDimitry Andric if (UsingRelativeLayout) { 986bdd1243dSDimitry Andric RemoveHwasanMetadata(VTable); 987bdd1243dSDimitry Andric if (!VTable->isDSOLocal()) 9885ffd83dbSDimitry Andric GenerateRelativeVTableAlias(VTable, OutName); 989bdd1243dSDimitry Andric } 9905ffd83dbSDimitry Andric 9910b57cec5SDimitry Andric return VTable; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 994bdd1243dSDimitry Andric // Ensure this vtable is not instrumented by hwasan. That is, a global alias is 995bdd1243dSDimitry Andric // not generated for it. This is mainly used by the relative-vtables ABI where 996bdd1243dSDimitry Andric // vtables instead contain 32-bit offsets between the vtable and function 997bdd1243dSDimitry Andric // pointers. Hwasan is disabled for these vtables for now because the tag in a 998bdd1243dSDimitry Andric // vtable pointer may fail the overflow check when resolving 32-bit PLT 999bdd1243dSDimitry Andric // relocations. A future alternative for this would be finding which usages of 1000bdd1243dSDimitry Andric // the vtable can continue to use the untagged hwasan value without any loss of 1001bdd1243dSDimitry Andric // value in hwasan. 1002bdd1243dSDimitry Andric void CodeGenVTables::RemoveHwasanMetadata(llvm::GlobalValue *GV) const { 1003bdd1243dSDimitry Andric if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) { 1004bdd1243dSDimitry Andric llvm::GlobalValue::SanitizerMetadata Meta; 1005bdd1243dSDimitry Andric if (GV->hasSanitizerMetadata()) 1006bdd1243dSDimitry Andric Meta = GV->getSanitizerMetadata(); 1007bdd1243dSDimitry Andric Meta.NoHWAddress = true; 1008bdd1243dSDimitry Andric GV->setSanitizerMetadata(Meta); 1009bdd1243dSDimitry Andric } 1010bdd1243dSDimitry Andric } 1011bdd1243dSDimitry Andric 10125ffd83dbSDimitry Andric // If the VTable is not dso_local, then we will not be able to indicate that 10135ffd83dbSDimitry Andric // the VTable does not need a relocation and move into rodata. A frequent 10145ffd83dbSDimitry Andric // time this can occur is for classes that should be made public from a DSO 10155ffd83dbSDimitry Andric // (like in libc++). For cases like these, we can make the vtable hidden or 10165ffd83dbSDimitry Andric // private and create a public alias with the same visibility and linkage as 10175ffd83dbSDimitry Andric // the original vtable type. 10185ffd83dbSDimitry Andric void CodeGenVTables::GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, 10195ffd83dbSDimitry Andric llvm::StringRef AliasNameRef) { 10205ffd83dbSDimitry Andric assert(getItaniumVTableContext().isRelativeLayout() && 10215ffd83dbSDimitry Andric "Can only use this if the relative vtable ABI is used"); 10225ffd83dbSDimitry Andric assert(!VTable->isDSOLocal() && "This should be called only if the vtable is " 10235ffd83dbSDimitry Andric "not guaranteed to be dso_local"); 10245ffd83dbSDimitry Andric 10255ffd83dbSDimitry Andric // If the vtable is available_externally, we shouldn't (or need to) generate 10265ffd83dbSDimitry Andric // an alias for it in the first place since the vtable won't actually by 10275ffd83dbSDimitry Andric // emitted in this compilation unit. 10285ffd83dbSDimitry Andric if (VTable->hasAvailableExternallyLinkage()) 10295ffd83dbSDimitry Andric return; 10305ffd83dbSDimitry Andric 10315ffd83dbSDimitry Andric // Create a new string in the event the alias is already the name of the 10325ffd83dbSDimitry Andric // vtable. Using the reference directly could lead to use of an inititialized 10335ffd83dbSDimitry Andric // value in the module's StringMap. 10345ffd83dbSDimitry Andric llvm::SmallString<256> AliasName(AliasNameRef); 10355ffd83dbSDimitry Andric VTable->setName(AliasName + ".local"); 10365ffd83dbSDimitry Andric 10375ffd83dbSDimitry Andric auto Linkage = VTable->getLinkage(); 10385ffd83dbSDimitry Andric assert(llvm::GlobalAlias::isValidLinkage(Linkage) && 10395ffd83dbSDimitry Andric "Invalid vtable alias linkage"); 10405ffd83dbSDimitry Andric 10415ffd83dbSDimitry Andric llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName); 10425ffd83dbSDimitry Andric if (!VTableAlias) { 10435ffd83dbSDimitry Andric VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(), 10445ffd83dbSDimitry Andric VTable->getAddressSpace(), Linkage, 10455ffd83dbSDimitry Andric AliasName, &CGM.getModule()); 10465ffd83dbSDimitry Andric } else { 10475ffd83dbSDimitry Andric assert(VTableAlias->getValueType() == VTable->getValueType()); 10485ffd83dbSDimitry Andric assert(VTableAlias->getLinkage() == Linkage); 10495ffd83dbSDimitry Andric } 10505ffd83dbSDimitry Andric VTableAlias->setVisibility(VTable->getVisibility()); 10515ffd83dbSDimitry Andric VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr()); 10525ffd83dbSDimitry Andric 10535ffd83dbSDimitry Andric // Both of these imply dso_local for the vtable. 10545ffd83dbSDimitry Andric if (!VTable->hasComdat()) { 10555ffd83dbSDimitry Andric // If this is in a comdat, then we shouldn't make the linkage private due to 10565ffd83dbSDimitry Andric // an issue in lld where private symbols can be used as the key symbol when 10575ffd83dbSDimitry Andric // choosing the prevelant group. This leads to "relocation refers to a 10585ffd83dbSDimitry Andric // symbol in a discarded section". 10595ffd83dbSDimitry Andric VTable->setLinkage(llvm::GlobalValue::PrivateLinkage); 10605ffd83dbSDimitry Andric } else { 10615ffd83dbSDimitry Andric // We should at least make this hidden since we don't want to expose it. 10625ffd83dbSDimitry Andric VTable->setVisibility(llvm::GlobalValue::HiddenVisibility); 10635ffd83dbSDimitry Andric } 10645ffd83dbSDimitry Andric 10655ffd83dbSDimitry Andric VTableAlias->setAliasee(VTable); 10665ffd83dbSDimitry Andric } 10675ffd83dbSDimitry Andric 10680b57cec5SDimitry Andric static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, 10690b57cec5SDimitry Andric const CXXRecordDecl *RD) { 10700b57cec5SDimitry Andric return CGM.getCodeGenOpts().OptimizationLevel > 0 && 10710b57cec5SDimitry Andric CGM.getCXXABI().canSpeculativelyEmitVTable(RD); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric /// Compute the required linkage of the vtable for the given class. 10750b57cec5SDimitry Andric /// 10760b57cec5SDimitry Andric /// Note that we only call this at the end of the translation unit. 10770b57cec5SDimitry Andric llvm::GlobalVariable::LinkageTypes 10780b57cec5SDimitry Andric CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { 10790b57cec5SDimitry Andric if (!RD->isExternallyVisible()) 10800b57cec5SDimitry Andric return llvm::GlobalVariable::InternalLinkage; 10810b57cec5SDimitry Andric 1082*62987288SDimitry Andric // In windows, the linkage of vtable is not related to modules. 1083*62987288SDimitry Andric bool IsInNamedModule = !getTarget().getCXXABI().isMicrosoft() && 1084*62987288SDimitry Andric RD->isInNamedModule(); 1085*62987288SDimitry Andric // If the CXXRecordDecl is not in a module unit, we need to get 1086*62987288SDimitry Andric // its key function. We're at the end of the translation unit, so the current 1087*62987288SDimitry Andric // key function is fully correct. 1088*62987288SDimitry Andric const CXXMethodDecl *keyFunction = 1089*62987288SDimitry Andric IsInNamedModule ? nullptr : Context.getCurrentKeyFunction(RD); 1090*62987288SDimitry Andric if (IsInNamedModule || (keyFunction && !RD->hasAttr<DLLImportAttr>())) { 10910b57cec5SDimitry Andric // If this class has a key function, use that to determine the 10920b57cec5SDimitry Andric // linkage of the vtable. 10930b57cec5SDimitry Andric const FunctionDecl *def = nullptr; 1094*62987288SDimitry Andric if (keyFunction && keyFunction->hasBody(def)) 10950b57cec5SDimitry Andric keyFunction = cast<CXXMethodDecl>(def); 10960b57cec5SDimitry Andric 1097*62987288SDimitry Andric bool IsExternalDefinition = 1098*62987288SDimitry Andric IsInNamedModule ? RD->shouldEmitInExternalSource() : !def; 1099*62987288SDimitry Andric 1100*62987288SDimitry Andric TemplateSpecializationKind Kind = 1101*62987288SDimitry Andric IsInNamedModule ? RD->getTemplateSpecializationKind() 1102*62987288SDimitry Andric : keyFunction->getTemplateSpecializationKind(); 1103*62987288SDimitry Andric 1104*62987288SDimitry Andric switch (Kind) { 11050b57cec5SDimitry Andric case TSK_Undeclared: 11060b57cec5SDimitry Andric case TSK_ExplicitSpecialization: 110706c3fb27SDimitry Andric assert( 1108*62987288SDimitry Andric (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 || 110906c3fb27SDimitry Andric CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) && 1110*62987288SDimitry Andric "Shouldn't query vtable linkage without the class in module units, " 1111*62987288SDimitry Andric "key function, optimizations, or debug info"); 1112*62987288SDimitry Andric if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0) 11130b57cec5SDimitry Andric return llvm::GlobalVariable::AvailableExternallyLinkage; 11140b57cec5SDimitry Andric 1115*62987288SDimitry Andric if (keyFunction && keyFunction->isInlined()) 111606c3fb27SDimitry Andric return !Context.getLangOpts().AppleKext 111706c3fb27SDimitry Andric ? llvm::GlobalVariable::LinkOnceODRLinkage 111806c3fb27SDimitry Andric : llvm::Function::InternalLinkage; 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric return llvm::GlobalVariable::ExternalLinkage; 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric case TSK_ImplicitInstantiation: 11230b57cec5SDimitry Andric return !Context.getLangOpts().AppleKext ? 11240b57cec5SDimitry Andric llvm::GlobalVariable::LinkOnceODRLinkage : 11250b57cec5SDimitry Andric llvm::Function::InternalLinkage; 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric case TSK_ExplicitInstantiationDefinition: 11280b57cec5SDimitry Andric return !Context.getLangOpts().AppleKext ? 11290b57cec5SDimitry Andric llvm::GlobalVariable::WeakODRLinkage : 11300b57cec5SDimitry Andric llvm::Function::InternalLinkage; 11310b57cec5SDimitry Andric 11320b57cec5SDimitry Andric case TSK_ExplicitInstantiationDeclaration: 11330b57cec5SDimitry Andric llvm_unreachable("Should not have been asked to emit this"); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric // -fapple-kext mode does not support weak linkage, so we must use 11380b57cec5SDimitry Andric // internal linkage. 11390b57cec5SDimitry Andric if (Context.getLangOpts().AppleKext) 11400b57cec5SDimitry Andric return llvm::Function::InternalLinkage; 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage = 11430b57cec5SDimitry Andric llvm::GlobalValue::LinkOnceODRLinkage; 11440b57cec5SDimitry Andric llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage = 11450b57cec5SDimitry Andric llvm::GlobalValue::WeakODRLinkage; 11460b57cec5SDimitry Andric if (RD->hasAttr<DLLExportAttr>()) { 11470b57cec5SDimitry Andric // Cannot discard exported vtables. 11480b57cec5SDimitry Andric DiscardableODRLinkage = NonDiscardableODRLinkage; 11490b57cec5SDimitry Andric } else if (RD->hasAttr<DLLImportAttr>()) { 11500b57cec5SDimitry Andric // Imported vtables are available externally. 11510b57cec5SDimitry Andric DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; 11520b57cec5SDimitry Andric NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric switch (RD->getTemplateSpecializationKind()) { 11560b57cec5SDimitry Andric case TSK_Undeclared: 11570b57cec5SDimitry Andric case TSK_ExplicitSpecialization: 11580b57cec5SDimitry Andric case TSK_ImplicitInstantiation: 11590b57cec5SDimitry Andric return DiscardableODRLinkage; 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric case TSK_ExplicitInstantiationDeclaration: 11620b57cec5SDimitry Andric // Explicit instantiations in MSVC do not provide vtables, so we must emit 11630b57cec5SDimitry Andric // our own. 11640b57cec5SDimitry Andric if (getTarget().getCXXABI().isMicrosoft()) 11650b57cec5SDimitry Andric return DiscardableODRLinkage; 11660b57cec5SDimitry Andric return shouldEmitAvailableExternallyVTable(*this, RD) 11670b57cec5SDimitry Andric ? llvm::GlobalVariable::AvailableExternallyLinkage 11680b57cec5SDimitry Andric : llvm::GlobalVariable::ExternalLinkage; 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric case TSK_ExplicitInstantiationDefinition: 11710b57cec5SDimitry Andric return NonDiscardableODRLinkage; 11720b57cec5SDimitry Andric } 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric llvm_unreachable("Invalid TemplateSpecializationKind!"); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric /// This is a callback from Sema to tell us that a particular vtable is 11780b57cec5SDimitry Andric /// required to be emitted in this translation unit. 11790b57cec5SDimitry Andric /// 11800b57cec5SDimitry Andric /// This is only called for vtables that _must_ be emitted (mainly due to key 11810b57cec5SDimitry Andric /// functions). For weak vtables, CodeGen tracks when they are needed and 11820b57cec5SDimitry Andric /// emits them as-needed. 11830b57cec5SDimitry Andric void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) { 11840b57cec5SDimitry Andric VTables.GenerateClassData(theClass); 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric void 11880b57cec5SDimitry Andric CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { 11890b57cec5SDimitry Andric if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) 11900b57cec5SDimitry Andric DI->completeClassData(RD); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric if (RD->getNumVBases()) 11930b57cec5SDimitry Andric CGM.getCXXABI().emitVirtualInheritanceTables(RD); 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric CGM.getCXXABI().emitVTableDefinitions(*this, RD); 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric /// At this point in the translation unit, does it appear that can we 11990b57cec5SDimitry Andric /// rely on the vtable being defined elsewhere in the program? 12000b57cec5SDimitry Andric /// 12010b57cec5SDimitry Andric /// The response is really only definitive when called at the end of 12020b57cec5SDimitry Andric /// the translation unit. 12030b57cec5SDimitry Andric /// 12040b57cec5SDimitry Andric /// The only semantic restriction here is that the object file should 12050b57cec5SDimitry Andric /// not contain a vtable definition when that vtable is defined 12060b57cec5SDimitry Andric /// strongly elsewhere. Otherwise, we'd just like to avoid emitting 12070b57cec5SDimitry Andric /// vtables when unnecessary. 12080b57cec5SDimitry Andric bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { 12090b57cec5SDimitry Andric assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable."); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't 12120b57cec5SDimitry Andric // emit them even if there is an explicit template instantiation. 12130b57cec5SDimitry Andric if (CGM.getTarget().getCXXABI().isMicrosoft()) 12140b57cec5SDimitry Andric return false; 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric // If we have an explicit instantiation declaration (and not a 12170b57cec5SDimitry Andric // definition), the vtable is defined elsewhere. 12180b57cec5SDimitry Andric TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); 12190b57cec5SDimitry Andric if (TSK == TSK_ExplicitInstantiationDeclaration) 12200b57cec5SDimitry Andric return true; 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric // Otherwise, if the class is an instantiated template, the 12230b57cec5SDimitry Andric // vtable must be defined here. 12240b57cec5SDimitry Andric if (TSK == TSK_ImplicitInstantiation || 12250b57cec5SDimitry Andric TSK == TSK_ExplicitInstantiationDefinition) 12260b57cec5SDimitry Andric return false; 12270b57cec5SDimitry Andric 1228*62987288SDimitry Andric // Otherwise, if the class is attached to a module, the tables are uniquely 1229*62987288SDimitry Andric // emitted in the object for the module unit in which it is defined. 1230*62987288SDimitry Andric if (RD->isInNamedModule()) 1231*62987288SDimitry Andric return RD->shouldEmitInExternalSource(); 1232*62987288SDimitry Andric 12330b57cec5SDimitry Andric // Otherwise, if the class doesn't have a key function (possibly 12340b57cec5SDimitry Andric // anymore), the vtable must be defined here. 12350b57cec5SDimitry Andric const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD); 12360b57cec5SDimitry Andric if (!keyFunction) 12370b57cec5SDimitry Andric return false; 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric // Otherwise, if we don't have a definition of the key function, the 12400b57cec5SDimitry Andric // vtable must be defined somewhere else. 1241*62987288SDimitry Andric return !keyFunction->hasBody(); 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric /// Given that we're currently at the end of the translation unit, and 12450b57cec5SDimitry Andric /// we've emitted a reference to the vtable for this class, should 12460b57cec5SDimitry Andric /// we define that vtable? 12470b57cec5SDimitry Andric static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, 12480b57cec5SDimitry Andric const CXXRecordDecl *RD) { 12490b57cec5SDimitry Andric // If vtable is internal then it has to be done. 12500b57cec5SDimitry Andric if (!CGM.getVTables().isVTableExternal(RD)) 12510b57cec5SDimitry Andric return true; 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric // If it's external then maybe we will need it as available_externally. 12540b57cec5SDimitry Andric return shouldEmitAvailableExternallyVTable(CGM, RD); 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andric /// Given that at some point we emitted a reference to one or more 12580b57cec5SDimitry Andric /// vtables, and that we are now at the end of the translation unit, 12590b57cec5SDimitry Andric /// decide whether we should emit them. 12600b57cec5SDimitry Andric void CodeGenModule::EmitDeferredVTables() { 12610b57cec5SDimitry Andric #ifndef NDEBUG 12620b57cec5SDimitry Andric // Remember the size of DeferredVTables, because we're going to assume 12630b57cec5SDimitry Andric // that this entire operation doesn't modify it. 12640b57cec5SDimitry Andric size_t savedSize = DeferredVTables.size(); 12650b57cec5SDimitry Andric #endif 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric for (const CXXRecordDecl *RD : DeferredVTables) 12680b57cec5SDimitry Andric if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD)) 12690b57cec5SDimitry Andric VTables.GenerateClassData(RD); 12700b57cec5SDimitry Andric else if (shouldOpportunisticallyEmitVTables()) 12710b57cec5SDimitry Andric OpportunisticVTables.push_back(RD); 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric assert(savedSize == DeferredVTables.size() && 12740b57cec5SDimitry Andric "deferred extra vtables during vtable emission?"); 12750b57cec5SDimitry Andric DeferredVTables.clear(); 12760b57cec5SDimitry Andric } 12770b57cec5SDimitry Andric 127881ad6265SDimitry Andric bool CodeGenModule::AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD) { 127906c3fb27SDimitry Andric if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>() || 128006c3fb27SDimitry Andric RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) 128181ad6265SDimitry Andric return true; 128281ad6265SDimitry Andric 12835ffd83dbSDimitry Andric if (!getCodeGenOpts().LTOVisibilityPublicStd) 12845ffd83dbSDimitry Andric return false; 12855ffd83dbSDimitry Andric 12865ffd83dbSDimitry Andric const DeclContext *DC = RD; 128704eeddc0SDimitry Andric while (true) { 12885ffd83dbSDimitry Andric auto *D = cast<Decl>(DC); 12895ffd83dbSDimitry Andric DC = DC->getParent(); 12905ffd83dbSDimitry Andric if (isa<TranslationUnitDecl>(DC->getRedeclContext())) { 12915ffd83dbSDimitry Andric if (auto *ND = dyn_cast<NamespaceDecl>(D)) 12925ffd83dbSDimitry Andric if (const IdentifierInfo *II = ND->getIdentifier()) 12935ffd83dbSDimitry Andric if (II->isStr("std") || II->isStr("stdext")) 12945ffd83dbSDimitry Andric return true; 12955ffd83dbSDimitry Andric break; 12965ffd83dbSDimitry Andric } 12975ffd83dbSDimitry Andric } 12985ffd83dbSDimitry Andric 12995ffd83dbSDimitry Andric return false; 13005ffd83dbSDimitry Andric } 13015ffd83dbSDimitry Andric 13020b57cec5SDimitry Andric bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) { 13030b57cec5SDimitry Andric LinkageInfo LV = RD->getLinkageAndVisibility(); 13040b57cec5SDimitry Andric if (!isExternallyVisible(LV.getLinkage())) 13050b57cec5SDimitry Andric return true; 13060b57cec5SDimitry Andric 130706c3fb27SDimitry Andric if (!getTriple().isOSBinFormatCOFF() && 130806c3fb27SDimitry Andric LV.getVisibility() != HiddenVisibility) 13090b57cec5SDimitry Andric return false; 13100b57cec5SDimitry Andric 131181ad6265SDimitry Andric return !AlwaysHasLTOVisibilityPublic(RD); 13120b57cec5SDimitry Andric } 13130b57cec5SDimitry Andric 1314e8d8bef9SDimitry Andric llvm::GlobalObject::VCallVisibility CodeGenModule::GetVCallVisibilityLevel( 1315e8d8bef9SDimitry Andric const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) { 1316e8d8bef9SDimitry Andric // If we have already visited this RD (which means this is a recursive call 1317e8d8bef9SDimitry Andric // since the initial call should have an empty Visited set), return the max 1318e8d8bef9SDimitry Andric // visibility. The recursive calls below compute the min between the result 1319e8d8bef9SDimitry Andric // of the recursive call and the current TypeVis, so returning the max here 1320e8d8bef9SDimitry Andric // ensures that it will have no effect on the current TypeVis. 1321e8d8bef9SDimitry Andric if (!Visited.insert(RD).second) 1322e8d8bef9SDimitry Andric return llvm::GlobalObject::VCallVisibilityTranslationUnit; 1323e8d8bef9SDimitry Andric 1324a7dea167SDimitry Andric LinkageInfo LV = RD->getLinkageAndVisibility(); 1325a7dea167SDimitry Andric llvm::GlobalObject::VCallVisibility TypeVis; 1326a7dea167SDimitry Andric if (!isExternallyVisible(LV.getLinkage())) 1327a7dea167SDimitry Andric TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit; 1328a7dea167SDimitry Andric else if (HasHiddenLTOVisibility(RD)) 1329a7dea167SDimitry Andric TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit; 1330a7dea167SDimitry Andric else 1331a7dea167SDimitry Andric TypeVis = llvm::GlobalObject::VCallVisibilityPublic; 1332a7dea167SDimitry Andric 133306c3fb27SDimitry Andric for (const auto &B : RD->bases()) 1334a7dea167SDimitry Andric if (B.getType()->getAsCXXRecordDecl()->isDynamicClass()) 1335e8d8bef9SDimitry Andric TypeVis = std::min( 1336e8d8bef9SDimitry Andric TypeVis, 1337e8d8bef9SDimitry Andric GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl(), Visited)); 1338a7dea167SDimitry Andric 133906c3fb27SDimitry Andric for (const auto &B : RD->vbases()) 1340a7dea167SDimitry Andric if (B.getType()->getAsCXXRecordDecl()->isDynamicClass()) 1341e8d8bef9SDimitry Andric TypeVis = std::min( 1342e8d8bef9SDimitry Andric TypeVis, 1343e8d8bef9SDimitry Andric GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl(), Visited)); 1344a7dea167SDimitry Andric 1345a7dea167SDimitry Andric return TypeVis; 1346a7dea167SDimitry Andric } 1347a7dea167SDimitry Andric 1348a7dea167SDimitry Andric void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, 1349a7dea167SDimitry Andric llvm::GlobalVariable *VTable, 13500b57cec5SDimitry Andric const VTableLayout &VTLayout) { 13515f757f3fSDimitry Andric // Emit type metadata on vtables with LTO or IR instrumentation. 13525f757f3fSDimitry Andric // In IR instrumentation, the type metadata is used to find out vtable 13535f757f3fSDimitry Andric // definitions (for type profiling) among all global variables. 13545f757f3fSDimitry Andric if (!getCodeGenOpts().LTOUnit && !getCodeGenOpts().hasProfileIRInstr()) 13550b57cec5SDimitry Andric return; 13560b57cec5SDimitry Andric 1357bdd1243dSDimitry Andric CharUnits ComponentWidth = GetTargetTypeStoreSize(getVTableComponentType()); 13580b57cec5SDimitry Andric 13595f757f3fSDimitry Andric struct AddressPoint { 13605f757f3fSDimitry Andric const CXXRecordDecl *Base; 13615f757f3fSDimitry Andric size_t Offset; 13625f757f3fSDimitry Andric std::string TypeName; 13635f757f3fSDimitry Andric bool operator<(const AddressPoint &RHS) const { 13645f757f3fSDimitry Andric int D = TypeName.compare(RHS.TypeName); 13655f757f3fSDimitry Andric return D < 0 || (D == 0 && Offset < RHS.Offset); 13665f757f3fSDimitry Andric } 13675f757f3fSDimitry Andric }; 13680b57cec5SDimitry Andric std::vector<AddressPoint> AddressPoints; 13695f757f3fSDimitry Andric for (auto &&AP : VTLayout.getAddressPoints()) { 13705f757f3fSDimitry Andric AddressPoint N{AP.first.getBase(), 13715f757f3fSDimitry Andric VTLayout.getVTableOffset(AP.second.VTableIndex) + 13725f757f3fSDimitry Andric AP.second.AddressPointIndex, 13735f757f3fSDimitry Andric {}}; 13745f757f3fSDimitry Andric llvm::raw_string_ostream Stream(N.TypeName); 13755f757f3fSDimitry Andric getCXXABI().getMangleContext().mangleCanonicalTypeName( 13765f757f3fSDimitry Andric QualType(N.Base->getTypeForDecl(), 0), Stream); 13775f757f3fSDimitry Andric AddressPoints.push_back(std::move(N)); 13785f757f3fSDimitry Andric } 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric // Sort the address points for determinism. 13815f757f3fSDimitry Andric llvm::sort(AddressPoints); 13820b57cec5SDimitry Andric 13830b57cec5SDimitry Andric ArrayRef<VTableComponent> Comps = VTLayout.vtable_components(); 13840b57cec5SDimitry Andric for (auto AP : AddressPoints) { 13850b57cec5SDimitry Andric // Create type metadata for the address point. 13865f757f3fSDimitry Andric AddVTableTypeMetadata(VTable, ComponentWidth * AP.Offset, AP.Base); 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric // The class associated with each address point could also potentially be 13890b57cec5SDimitry Andric // used for indirect calls via a member function pointer, so we need to 13900b57cec5SDimitry Andric // annotate the address of each function pointer with the appropriate member 13910b57cec5SDimitry Andric // function pointer type. 13920b57cec5SDimitry Andric for (unsigned I = 0; I != Comps.size(); ++I) { 13930b57cec5SDimitry Andric if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) 13940b57cec5SDimitry Andric continue; 13950b57cec5SDimitry Andric llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( 13960b57cec5SDimitry Andric Context.getMemberPointerType( 13970b57cec5SDimitry Andric Comps[I].getFunctionDecl()->getType(), 13985f757f3fSDimitry Andric Context.getRecordType(AP.Base).getTypePtr())); 1399bdd1243dSDimitry Andric VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric } 1402a7dea167SDimitry Andric 14035ffd83dbSDimitry Andric if (getCodeGenOpts().VirtualFunctionElimination || 14045ffd83dbSDimitry Andric getCodeGenOpts().WholeProgramVTables) { 1405e8d8bef9SDimitry Andric llvm::DenseSet<const CXXRecordDecl *> Visited; 1406e8d8bef9SDimitry Andric llvm::GlobalObject::VCallVisibility TypeVis = 1407e8d8bef9SDimitry Andric GetVCallVisibilityLevel(RD, Visited); 1408a7dea167SDimitry Andric if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic) 14095ffd83dbSDimitry Andric VTable->setVCallVisibilityMetadata(TypeVis); 1410a7dea167SDimitry Andric } 14110b57cec5SDimitry Andric } 1412