Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/CodeGen/ItaniumCXXABI.cpp
Show First 20 Lines • Show All 664 Lines • ▼ Show 20 Lines | CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( | ||||
// Check the address of the function pointer if CFI on member function | // Check the address of the function pointer if CFI on member function | ||||
// pointers is enabled. | // pointers is enabled. | ||||
llvm::Constant *CheckSourceLocation; | llvm::Constant *CheckSourceLocation; | ||||
llvm::Constant *CheckTypeDesc; | llvm::Constant *CheckTypeDesc; | ||||
bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) && | bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) && | ||||
CGM.HasHiddenLTOVisibility(RD); | CGM.HasHiddenLTOVisibility(RD); | ||||
bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination && | bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination && | ||||
CGM.HasHiddenLTOVisibility(RD); | CGM.HasHiddenLTOVisibility(RD); | ||||
bool ShouldEmitWPDInfo = | |||||
CGM.getCodeGenOpts().WholeProgramVTables && | |||||
// Don't insert type tests if we are forcing public std visibility. | |||||
!CGM.HasLTOVisibilityPublicStd(RD); | |||||
llvm::Value *VirtualFn = nullptr; | llvm::Value *VirtualFn = nullptr; | ||||
{ | { | ||||
CodeGenFunction::SanitizerScope SanScope(&CGF); | CodeGenFunction::SanitizerScope SanScope(&CGF); | ||||
llvm::Value *TypeId = nullptr; | llvm::Value *TypeId = nullptr; | ||||
llvm::Value *CheckResult = nullptr; | llvm::Value *CheckResult = nullptr; | ||||
if (ShouldEmitCFICheck || ShouldEmitVFEInfo) { | if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) { | ||||
// If doing CFI or VFE, we will need the metadata node to check against. | // If doing CFI, VFE or WPD, we will need the metadata node to check | ||||
// against. | |||||
llvm::Metadata *MD = | llvm::Metadata *MD = | ||||
CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0)); | CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0)); | ||||
TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); | TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); | ||||
} | } | ||||
llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); | llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); | ||||
if (ShouldEmitVFEInfo) { | if (ShouldEmitVFEInfo) { | ||||
// If doing VFE, load from the vtable with a type.checked.load intrinsic | // If doing VFE, load from the vtable with a type.checked.load intrinsic | ||||
// call. Note that we use the GEP to calculate the address to load from | // call. Note that we use the GEP to calculate the address to load from | ||||
// and pass 0 as the offset to the intrinsic. This is because every | // and pass 0 as the offset to the intrinsic. This is because every | ||||
// vtable slot of the correct type is marked with matching metadata, and | // vtable slot of the correct type is marked with matching metadata, and | ||||
// we know that the load must be from one of these slots. | // we know that the load must be from one of these slots. | ||||
llvm::Value *CheckedLoad = Builder.CreateCall( | llvm::Value *CheckedLoad = Builder.CreateCall( | ||||
CGM.getIntrinsic(llvm::Intrinsic::type_checked_load), | CGM.getIntrinsic(llvm::Intrinsic::type_checked_load), | ||||
{VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId}); | {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId}); | ||||
CheckResult = Builder.CreateExtractValue(CheckedLoad, 1); | CheckResult = Builder.CreateExtractValue(CheckedLoad, 1); | ||||
VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0); | VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0); | ||||
VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(), | VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(), | ||||
"memptr.virtualfn"); | "memptr.virtualfn"); | ||||
} else { | } else { | ||||
// When not doing VFE, emit a normal load, as it allows more | // When not doing VFE, emit a normal load, as it allows more | ||||
// optimisations than type.checked.load. | // optimisations than type.checked.load. | ||||
if (ShouldEmitCFICheck) { | if (ShouldEmitCFICheck || ShouldEmitWPDInfo) { | ||||
CheckResult = Builder.CreateCall( | CheckResult = Builder.CreateCall( | ||||
CGM.getIntrinsic(llvm::Intrinsic::type_test), | CGM.getIntrinsic(llvm::Intrinsic::type_test), | ||||
{Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId}); | {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId}); | ||||
} | } | ||||
VFPAddr = | VFPAddr = | ||||
Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); | Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); | ||||
VirtualFn = Builder.CreateAlignedLoad(VFPAddr, CGF.getPointerAlign(), | VirtualFn = Builder.CreateAlignedLoad(VFPAddr, CGF.getPointerAlign(), | ||||
"memptr.virtualfn"); | "memptr.virtualfn"); | ||||
} | } | ||||
assert(VirtualFn && "Virtual fuction pointer not created!"); | assert(VirtualFn && "Virtual fuction pointer not created!"); | ||||
assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) && | assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo || | ||||
CheckResult) && | |||||
"Check result required but not created!"); | "Check result required but not created!"); | ||||
if (ShouldEmitCFICheck) { | if (ShouldEmitCFICheck) { | ||||
// If doing CFI, emit the check. | // If doing CFI, emit the check. | ||||
CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc()); | CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc()); | ||||
CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0)); | CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0)); | ||||
llvm::Constant *StaticData[] = { | llvm::Constant *StaticData[] = { | ||||
llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall), | llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall), | ||||
▲ Show 20 Lines • Show All 3,679 Lines • Show Last 20 Lines |