Mercurial > hg > CbC > CbC_llvm
comparison lib/CodeGen/ShadowStackGCLowering.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | 7d135dc70f03 |
children | 803732b1fca8 |
comparison
equal
deleted
inserted
replaced
101:34baf5011add | 120:1172e4bd9c6f |
---|---|
21 #include "llvm/CodeGen/GCStrategy.h" | 21 #include "llvm/CodeGen/GCStrategy.h" |
22 #include "llvm/IR/CallSite.h" | 22 #include "llvm/IR/CallSite.h" |
23 #include "llvm/IR/IRBuilder.h" | 23 #include "llvm/IR/IRBuilder.h" |
24 #include "llvm/IR/IntrinsicInst.h" | 24 #include "llvm/IR/IntrinsicInst.h" |
25 #include "llvm/IR/Module.h" | 25 #include "llvm/IR/Module.h" |
26 #include "llvm/Transforms/Utils/EscapeEnumerator.h" | |
26 | 27 |
27 using namespace llvm; | 28 using namespace llvm; |
28 | 29 |
29 #define DEBUG_TYPE "shadowstackgclowering" | 30 #define DEBUG_TYPE "shadowstackgclowering" |
30 | 31 |
78 ShadowStackGCLowering::ShadowStackGCLowering() | 79 ShadowStackGCLowering::ShadowStackGCLowering() |
79 : FunctionPass(ID), Head(nullptr), StackEntryTy(nullptr), | 80 : FunctionPass(ID), Head(nullptr), StackEntryTy(nullptr), |
80 FrameMapTy(nullptr) { | 81 FrameMapTy(nullptr) { |
81 initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry()); | 82 initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry()); |
82 } | 83 } |
83 | |
84 namespace { | |
85 /// EscapeEnumerator - This is a little algorithm to find all escape points | |
86 /// from a function so that "finally"-style code can be inserted. In addition | |
87 /// to finding the existing return and unwind instructions, it also (if | |
88 /// necessary) transforms any call instructions into invokes and sends them to | |
89 /// a landing pad. | |
90 /// | |
91 /// It's wrapped up in a state machine using the same transform C# uses for | |
92 /// 'yield return' enumerators, This transform allows it to be non-allocating. | |
93 class EscapeEnumerator { | |
94 Function &F; | |
95 const char *CleanupBBName; | |
96 | |
97 // State. | |
98 int State; | |
99 Function::iterator StateBB, StateE; | |
100 IRBuilder<> Builder; | |
101 | |
102 public: | |
103 EscapeEnumerator(Function &F, const char *N = "cleanup") | |
104 : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {} | |
105 | |
106 IRBuilder<> *Next() { | |
107 switch (State) { | |
108 default: | |
109 return nullptr; | |
110 | |
111 case 0: | |
112 StateBB = F.begin(); | |
113 StateE = F.end(); | |
114 State = 1; | |
115 | |
116 case 1: | |
117 // Find all 'return', 'resume', and 'unwind' instructions. | |
118 while (StateBB != StateE) { | |
119 BasicBlock *CurBB = &*StateBB++; | |
120 | |
121 // Branches and invokes do not escape, only unwind, resume, and return | |
122 // do. | |
123 TerminatorInst *TI = CurBB->getTerminator(); | |
124 if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI)) | |
125 continue; | |
126 | |
127 Builder.SetInsertPoint(TI); | |
128 return &Builder; | |
129 } | |
130 | |
131 State = 2; | |
132 | |
133 // Find all 'call' instructions. | |
134 SmallVector<Instruction *, 16> Calls; | |
135 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) | |
136 for (BasicBlock::iterator II = BB->begin(), EE = BB->end(); II != EE; | |
137 ++II) | |
138 if (CallInst *CI = dyn_cast<CallInst>(II)) | |
139 if (!CI->getCalledFunction() || | |
140 !CI->getCalledFunction()->getIntrinsicID()) | |
141 Calls.push_back(CI); | |
142 | |
143 if (Calls.empty()) | |
144 return nullptr; | |
145 | |
146 // Create a cleanup block. | |
147 LLVMContext &C = F.getContext(); | |
148 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F); | |
149 Type *ExnTy = | |
150 StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C), nullptr); | |
151 if (!F.hasPersonalityFn()) { | |
152 Constant *PersFn = F.getParent()->getOrInsertFunction( | |
153 "__gcc_personality_v0", | |
154 FunctionType::get(Type::getInt32Ty(C), true)); | |
155 F.setPersonalityFn(PersFn); | |
156 } | |
157 LandingPadInst *LPad = | |
158 LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB); | |
159 LPad->setCleanup(true); | |
160 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB); | |
161 | |
162 // Transform the 'call' instructions into 'invoke's branching to the | |
163 // cleanup block. Go in reverse order to make prettier BB names. | |
164 SmallVector<Value *, 16> Args; | |
165 for (unsigned I = Calls.size(); I != 0;) { | |
166 CallInst *CI = cast<CallInst>(Calls[--I]); | |
167 | |
168 // Split the basic block containing the function call. | |
169 BasicBlock *CallBB = CI->getParent(); | |
170 BasicBlock *NewBB = CallBB->splitBasicBlock( | |
171 CI->getIterator(), CallBB->getName() + ".cont"); | |
172 | |
173 // Remove the unconditional branch inserted at the end of CallBB. | |
174 CallBB->getInstList().pop_back(); | |
175 NewBB->getInstList().remove(CI); | |
176 | |
177 // Create a new invoke instruction. | |
178 Args.clear(); | |
179 CallSite CS(CI); | |
180 Args.append(CS.arg_begin(), CS.arg_end()); | |
181 | |
182 InvokeInst *II = | |
183 InvokeInst::Create(CI->getCalledValue(), NewBB, CleanupBB, Args, | |
184 CI->getName(), CallBB); | |
185 II->setCallingConv(CI->getCallingConv()); | |
186 II->setAttributes(CI->getAttributes()); | |
187 CI->replaceAllUsesWith(II); | |
188 delete CI; | |
189 } | |
190 | |
191 Builder.SetInsertPoint(RI); | |
192 return &Builder; | |
193 } | |
194 } | |
195 }; | |
196 } | |
197 | |
198 | 84 |
199 Constant *ShadowStackGCLowering::GetFrameMap(Function &F) { | 85 Constant *ShadowStackGCLowering::GetFrameMap(Function &F) { |
200 // doInitialization creates the abstract type of this value. | 86 // doInitialization creates the abstract type of this value. |
201 Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); | 87 Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); |
202 | 88 |