1 | //===- TypeMetadataUtils.h - Utilities related to type metadata --*- C++ -*-==// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains functions that make it easier to manipulate type metadata |
10 | // for devirtualization. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_ANALYSIS_TYPEMETADATAUTILS_H |
15 | #define LLVM_ANALYSIS_TYPEMETADATAUTILS_H |
16 | |
17 | #include <cstdint> |
18 | #include <utility> |
19 | |
20 | namespace llvm { |
21 | |
22 | template <typename T> class SmallVectorImpl; |
23 | class CallBase; |
24 | class CallInst; |
25 | class Constant; |
26 | class Function; |
27 | class DominatorTree; |
28 | class GlobalVariable; |
29 | class Instruction; |
30 | class Module; |
31 | |
32 | /// The type of CFI jumptable needed for a function. |
33 | enum CfiFunctionLinkage { |
34 | CFL_Definition = 0, |
35 | CFL_Declaration = 1, |
36 | CFL_WeakDeclaration = 2 |
37 | }; |
38 | |
39 | /// A call site that could be devirtualized. |
40 | struct DevirtCallSite { |
41 | /// The offset from the address point to the virtual function. |
42 | uint64_t Offset; |
43 | /// The call site itself. |
44 | CallBase &CB; |
45 | }; |
46 | |
47 | /// Given a call to the intrinsic \@llvm.type.test, find all devirtualizable |
48 | /// call sites based on the call and return them in DevirtCalls. |
49 | void findDevirtualizableCallsForTypeTest( |
50 | SmallVectorImpl<DevirtCallSite> &DevirtCalls, |
51 | SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI, |
52 | DominatorTree &DT); |
53 | |
54 | /// Given a call to the intrinsic \@llvm.type.checked.load, find all |
55 | /// devirtualizable call sites based on the call and return them in DevirtCalls. |
56 | void findDevirtualizableCallsForTypeCheckedLoad( |
57 | SmallVectorImpl<DevirtCallSite> &DevirtCalls, |
58 | SmallVectorImpl<Instruction *> &LoadedPtrs, |
59 | SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses, |
60 | const CallInst *CI, DominatorTree &DT); |
61 | |
62 | /// Processes a Constant recursively looking into elements of arrays, structs |
63 | /// and expressions to find a trivial pointer element that is located at the |
64 | /// given offset (relative to the beginning of the whole outer Constant). |
65 | /// |
66 | /// Used for example from GlobalDCE to find an entry in a C++ vtable that |
67 | /// matches a vcall offset. |
68 | /// |
69 | /// To support Swift vtables, getPointerAtOffset can see through "relative |
70 | /// pointers", i.e. (sub-)expressions of the form of: |
71 | /// |
72 | /// @symbol = ... { |
73 | /// i32 trunc (i64 sub ( |
74 | /// i64 ptrtoint (<type> @target to i64), i64 ptrtoint (... @symbol to i64) |
75 | /// ) to i32) |
76 | /// } |
77 | /// |
78 | /// For such (sub-)expressions, getPointerAtOffset returns the @target pointer. |
79 | Constant *getPointerAtOffset(Constant *I, uint64_t Offset, Module &M, |
80 | Constant *TopLevelGlobal = nullptr); |
81 | |
82 | /// Given a vtable and a specified offset, returns the function and the trivial |
83 | /// pointer at the specified offset in pair iff the pointer at the specified |
84 | /// offset is a function or an alias to a function. Returns a pair of nullptr |
85 | /// otherwise. |
86 | std::pair<Function *, Constant *> |
87 | getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset, Module &M); |
88 | |
89 | /// Finds the same "relative pointer" pattern as described above, where the |
90 | /// target is `F`, and replaces the entire pattern with a constant zero. |
91 | void replaceRelativePointerUsersWithZero(Function *F); |
92 | |
93 | } // namespace llvm |
94 | |
95 | #endif |
96 | |