xref: /llvm-project/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h (revision 5f36042508c1ba765df503a493beafb20bf9ddd0)
1 //===- MemoryTaggingSupport.h - helpers for memory tagging implementations ===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file declares common infrastructure for HWAddressSanitizer and
9 // Aarch64StackTagging.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H
13 #define LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H
14 
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/ADT/STLFunctionalExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Analysis/LoopInfo.h"
19 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
20 #include "llvm/Analysis/StackSafetyAnalysis.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/Support/Alignment.h"
23 
24 namespace llvm {
25 class DominatorTree;
26 class DbgVariableIntrinsic;
27 class IntrinsicInst;
28 class PostDominatorTree;
29 class AllocaInst;
30 class Instruction;
31 namespace memtag {
32 // For an alloca valid between lifetime markers Start and Ends, call the
33 // Callback for all possible exits out of the lifetime in the containing
34 // function, which can return from the instructions in RetVec.
35 //
36 // Returns whether Ends covered all possible exits. If they did not,
37 // the caller should remove Ends to ensure that work done at the other
38 // exits does not happen outside of the lifetime.
39 bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT,
40                           const LoopInfo &LI, const Instruction *Start,
41                           const SmallVectorImpl<IntrinsicInst *> &Ends,
42                           const SmallVectorImpl<Instruction *> &RetVec,
43                           llvm::function_ref<void(Instruction *)> Callback);
44 
45 bool isStandardLifetime(const SmallVectorImpl<IntrinsicInst *> &LifetimeStart,
46                         const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd,
47                         const DominatorTree *DT, const LoopInfo *LI,
48                         size_t MaxLifetimes);
49 
50 Instruction *getUntagLocationIfFunctionExit(Instruction &Inst);
51 
52 struct AllocaInfo {
53   AllocaInst *AI;
54   SmallVector<IntrinsicInst *, 2> LifetimeStart;
55   SmallVector<IntrinsicInst *, 2> LifetimeEnd;
56   SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics;
57   // Non-intrinsic records of variable locations.
58   SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
59 };
60 
61 struct StackInfo {
62   MapVector<AllocaInst *, AllocaInfo> AllocasToInstrument;
63   SmallVector<Instruction *, 4> UnrecognizedLifetimes;
64   SmallVector<Instruction *, 8> RetVec;
65   bool CallsReturnTwice = false;
66 };
67 
68 enum class AllocaInterestingness {
69   // Uninteresting because of the nature of the alloca.
70   kUninteresting,
71   // Uninteresting because proven safe.
72   kSafe,
73   // Interesting.
74   kInteresting
75 };
76 
77 class StackInfoBuilder {
78 public:
79   StackInfoBuilder(const StackSafetyGlobalInfo *SSI, const char *DebugType)
80       : SSI(SSI), DebugType(DebugType) {}
81 
82   void visit(OptimizationRemarkEmitter &ORE, Instruction &Inst);
83   AllocaInterestingness getAllocaInterestingness(const AllocaInst &AI);
84   StackInfo &get() { return Info; };
85 
86 private:
87   StackInfo Info;
88   const StackSafetyGlobalInfo *SSI;
89   const char *DebugType;
90 };
91 
92 uint64_t getAllocaSizeInBytes(const AllocaInst &AI);
93 void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align);
94 bool isLifetimeIntrinsic(Value *V);
95 
96 Value *readRegister(IRBuilder<> &IRB, StringRef Name);
97 Value *getFP(IRBuilder<> &IRB);
98 Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB);
99 Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot);
100 
101 void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag);
102 Value *incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong,
103                            unsigned int Inc);
104 
105 } // namespace memtag
106 } // namespace llvm
107 
108 #endif
109