diff options
author | Arnold Schwaighofer <aschwaighofer@apple.com> | 2023-06-29 08:07:11 -0700 |
---|---|---|
committer | Arnold Schwaighofer <aschwaighofer@apple.com> | 2023-06-29 08:33:45 -0700 |
commit | 98eb8abff6ad5c2e2f95fd1189b35a24f2800b32 (patch) | |
tree | 3b129ee5f5dddd975a0138d911213ba6edb6cc6f /llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | |
parent | e12ffe6a93505e590158ddd8cc73a4f201bbf0aa (diff) | |
download | llvm-98eb8abff6ad5c2e2f95fd1189b35a24f2800b32.zip llvm-98eb8abff6ad5c2e2f95fd1189b35a24f2800b32.tar.gz llvm-98eb8abff6ad5c2e2f95fd1189b35a24f2800b32.tar.bz2 |
Add a type_checked_load_relative to support relative function pointer tables
This adds a type_checked_load_relative intrinsic whose semantics it is to
load a relative function pointer.
A relative function pointer is a pointer to a 32bit value that when
added to its address yields the address of the function.
Differential Revision: https://reviews.llvm.org/D143204
Diffstat (limited to 'llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 203846d..d332586 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -1006,7 +1006,7 @@ bool DevirtModule::tryFindVirtualCallTargets( return false; Constant *Ptr = getPointerAtOffset(TM.Bits->GV->getInitializer(), - TM.Offset + ByteOffset, M); + TM.Offset + ByteOffset, M, TM.Bits->GV); if (!Ptr) return false; @@ -2002,9 +2002,23 @@ void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) { // This helps avoid unnecessary spills. IRBuilder<> LoadB( (LoadedPtrs.size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI); - Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); - Value *GEPPtr = LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int8PtrTy)); - Value *LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEPPtr); + + Value *LoadedValue = nullptr; + if (TypeCheckedLoadFunc->getIntrinsicID() == + Intrinsic::type_checked_load_relative) { + Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); + Value *GEPPtr = LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int32Ty)); + LoadedValue = LoadB.CreateLoad(Int32Ty, GEPPtr); + LoadedValue = LoadB.CreateSExt(LoadedValue, IntPtrTy); + GEP = LoadB.CreatePtrToInt(GEP, IntPtrTy); + LoadedValue = LoadB.CreateAdd(GEP, LoadedValue); + LoadedValue = LoadB.CreateIntToPtr(LoadedValue, Int8PtrTy); + } else { + Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); + Value *GEPPtr = + LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int8PtrTy)); + LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEPPtr); + } for (Instruction *LoadedPtr : LoadedPtrs) { LoadedPtr->replaceAllUsesWith(LoadedValue); @@ -2185,6 +2199,8 @@ bool DevirtModule::run() { M.getFunction(Intrinsic::getName(Intrinsic::type_test)); Function *TypeCheckedLoadFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); + Function *TypeCheckedLoadRelativeFunc = + M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load_relative)); Function *AssumeFunc = M.getFunction(Intrinsic::getName(Intrinsic::assume)); // Normally if there are no users of the devirtualization intrinsics in the @@ -2193,7 +2209,9 @@ bool DevirtModule::run() { if (!ExportSummary && (!TypeTestFunc || TypeTestFunc->use_empty() || !AssumeFunc || AssumeFunc->use_empty()) && - (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty())) + (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) && + (!TypeCheckedLoadRelativeFunc || + TypeCheckedLoadRelativeFunc->use_empty())) return false; // Rebuild type metadata into a map for easy lookup. @@ -2207,6 +2225,9 @@ bool DevirtModule::run() { if (TypeCheckedLoadFunc) scanTypeCheckedLoadUsers(TypeCheckedLoadFunc); + if (TypeCheckedLoadRelativeFunc) + scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc); + if (ImportSummary) { for (auto &S : CallSlots) importResolution(S.first, S.second); |