From: John McCall Date: Tue, 6 Feb 2018 18:52:44 +0000 (+0000) Subject: Pass around function pointers as CGCallees, not bare llvm::Value*s. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5203555364188d5c92fc0c0bf51a5e37f3719d87;p=clang Pass around function pointers as CGCallees, not bare llvm::Value*s. The intention here is to make it easy to write frontend-assisted CFI systems by propagating extra information in the CGCallee. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324377 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 56adcbc575..2262360d86 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -413,10 +413,10 @@ public: CharUnits VPtrOffset) = 0; /// Build a virtual function pointer in the ABI-specific way. - virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, Address This, - llvm::Type *Ty, - SourceLocation Loc) = 0; + virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, Address This, + llvm::Type *Ty, + SourceLocation Loc) = 0; /// Emit the ABI-specific virtual destructor call. virtual llvm::Value * diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 0f222ae21a..de42d159fa 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -4052,14 +4052,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } - llvm::Value *CalleePtr; - if (Callee.isVirtual()) { - const CallExpr *CE = Callee.getVirtualCallExpr(); - CalleePtr = CGM.getCXXABI().getVirtualFunctionPointer( - *this, Callee.getVirtualMethodDecl(), Callee.getThisAddress(), - Callee.getFunctionType(), CE ? CE->getLocStart() : SourceLocation()); - } else - CalleePtr = Callee.getFunctionPointer(); + const CGCallee &ConcreteCallee = Callee.prepareConcreteCallee(*this); + llvm::Value *CalleePtr = ConcreteCallee.getFunctionPointer(); // If we're using inalloca, set up that argument. if (ArgMemory.isValid()) { @@ -4412,6 +4406,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return Ret; } +CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const { + if (isVirtual()) { + const CallExpr *CE = getVirtualCallExpr(); + return CGF.CGM.getCXXABI().getVirtualFunctionPointer( + CGF, getVirtualMethodDecl(), getThisAddress(), + getFunctionType(), CE ? CE->getLocStart() : SourceLocation()); + } + + return *this; +} + /* VarArg handling */ Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) { diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h index 6b23a81fa9..495baf0f9a 100644 --- a/lib/CodeGen/CGCall.h +++ b/lib/CodeGen/CGCall.h @@ -206,6 +206,10 @@ public: return cast( getFunctionPointer()->getType()->getPointerElementType()); } + + /// If this is a delayed callee computation of some sort, prepare + /// a concrete callee. + CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const; }; struct CallArg { diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 2792636c7f..dc60b1d2ed 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -280,9 +280,9 @@ public: llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; - llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, - Address This, llvm::Type *Ty, - SourceLocation Loc) override; + CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, + Address This, llvm::Type *Ty, + SourceLocation Loc) override; llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, @@ -1651,42 +1651,47 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, return VTable; } -llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, - Address This, - llvm::Type *Ty, - SourceLocation Loc) { +CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, + Address This, + llvm::Type *Ty, + SourceLocation Loc) { GD = GD.getCanonicalDecl(); Ty = Ty->getPointerTo()->getPointerTo(); auto *MethodDecl = cast(GD.getDecl()); llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent()); uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); - if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) - return CGF.EmitVTableTypeCheckedLoad( + llvm::Value *VFunc; + if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { + VFunc = CGF.EmitVTableTypeCheckedLoad( MethodDecl->getParent(), VTable, VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); - - CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc); - - llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); - auto *VFuncLoad = - CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); - - // Add !invariant.load md to virtual function load to indicate that - // function didn't change inside vtable. - // It's safe to add it without -fstrict-vtable-pointers, but it would not - // help in devirtualization because it will only matter if we will have 2 - // the same virtual function loads from the same vtable load, which won't - // happen without enabled devirtualization with -fstrict-vtable-pointers. - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCodeGenOpts().StrictVTablePointers) - VFuncLoad->setMetadata( - llvm::LLVMContext::MD_invariant_load, - llvm::MDNode::get(CGM.getLLVMContext(), - llvm::ArrayRef())); - return VFuncLoad; + } else { + CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc); + + llvm::Value *VFuncPtr = + CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); + auto *VFuncLoad = + CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); + + // Add !invariant.load md to virtual function load to indicate that + // function didn't change inside vtable. + // It's safe to add it without -fstrict-vtable-pointers, but it would not + // help in devirtualization because it will only matter if we will have 2 + // the same virtual function loads from the same vtable load, which won't + // happen without enabled devirtualization with -fstrict-vtable-pointers. + if (CGM.getCodeGenOpts().OptimizationLevel > 0 && + CGM.getCodeGenOpts().StrictVTablePointers) + VFuncLoad->setMetadata( + llvm::LLVMContext::MD_invariant_load, + llvm::MDNode::get(CGM.getLLVMContext(), + llvm::ArrayRef())); + VFunc = VFuncLoad; + } + + CGCallee Callee(MethodDecl, VFunc); + return Callee; } llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 046acd76ce..16bb598fae 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -285,9 +285,9 @@ public: llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; - llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, - Address This, llvm::Type *Ty, - SourceLocation Loc) override; + CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, + Address This, llvm::Type *Ty, + SourceLocation Loc) override; llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, @@ -1827,11 +1827,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, return VTable; } -llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, - Address This, - llvm::Type *Ty, - SourceLocation Loc) { +CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, + Address This, + llvm::Type *Ty, + SourceLocation Loc) { GD = GD.getCanonicalDecl(); CGBuilderTy &Builder = CGF.Builder; @@ -1858,17 +1858,22 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, ->ObjectWithVPtr; }; - if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) - return CGF.EmitVTableTypeCheckedLoad( + llvm::Value *VFunc; + if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { + VFunc = CGF.EmitVTableTypeCheckedLoad( getObjectWithVPtr(), VTable, ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); + } else { + if (CGM.getCodeGenOpts().PrepareForLTO) + CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc); - if (CGM.getCodeGenOpts().PrepareForLTO) - CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc); + llvm::Value *VFuncPtr = + Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); + VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); + } - llvm::Value *VFuncPtr = - Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); - return Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); + CGCallee Callee(MethodDecl, VFunc); + return Callee; } llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(