@@ -169,14 +169,15 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
169169 (GlobalVariable *)nullptr );
170170
171171 // Create control point entry block. Checks if we are currently tracing.
172- Value *GVTracingVal = Builder.CreateLoad (GVTracing);
172+ Value *GVTracingVal = Builder.CreateLoad (Type::getInt8Ty (Context), GVTracing);
173173 Value *IsTracing =
174174 Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ, GVTracingVal, Int0);
175175 Builder.CreateCondBr (IsTracing, BBNotTracing, BBTracing);
176176
177177 // Create block for "not tracing" case. Checks if we already compiled a trace.
178178 Builder.SetInsertPoint (BBNotTracing);
179- Value *GVCompiledTraceVal = Builder.CreateLoad (GVCompiledTrace);
179+ Value *GVCompiledTraceVal =
180+ Builder.CreateLoad (Type::getInt8PtrTy (Context), GVCompiledTrace);
180181 Value *HasTrace = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
181182 GVCompiledTraceVal, PtNull);
182183 Builder.CreateCondBr (HasTrace, BBHasNoTrace, BBHasTrace);
@@ -193,7 +194,8 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
193194 // Create block that checks if we've reached the same location again so we
194195 // can execute a compiled trace.
195196 Builder.SetInsertPoint (BBHasTrace);
196- Value *ValStartLoc = Builder.CreateLoad (GVStartLoc);
197+ Value *ValStartLoc =
198+ Builder.CreateLoad (Type::getInt32Ty (Context), GVStartLoc);
197199 Value *ExecTraceCond = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
198200 ValStartLoc, F->getArg (0 ));
199201 Builder.CreateCondBr (ExecTraceCond, BBExecuteTrace, BBReturn);
@@ -216,7 +218,8 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
216218
217219 // Create block that decides when to stop tracing.
218220 Builder.SetInsertPoint (BBTracing);
219- Value *ValStartLoc2 = Builder.CreateLoad (GVStartLoc);
221+ Value *ValStartLoc2 =
222+ Builder.CreateLoad (Type::getInt32Ty (Context), GVStartLoc);
220223 Value *StopTracingCond = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
221224 ValStartLoc2, F->getArg (0 ));
222225 Builder.CreateCondBr (StopTracingCond, BBStopTracing, BBReturn);
@@ -264,102 +267,86 @@ std::vector<Value *> getLiveVars(DominatorTree &DT, CallInst *OldCtrlPoint) {
264267 return Vec;
265268}
266269
267- namespace {
268- struct YkControlPointPass : public ModulePass {
269- static char ID;
270+ YkControlPointPass::YkControlPointPass () {}
270271
271- YkControlPointPass () : ModulePass(ID) {}
272+ PreservedAnalyses YkControlPointPass::run (Module &M,
273+ ModuleAnalysisManager &AM) {
274+ LLVMContext &Context = M.getContext ();
272275
273- StringRef getPassName () const override {
274- return " Control Point Patching Pass" ;
276+ // Locate the "dummy" control point provided by the user.
277+ CallInst *OldCtrlPointCall = findControlPointCall (M);
278+ if (OldCtrlPointCall == nullptr ) {
279+ Context.emitError (" ykllvm couldn't find the call to `yk_control_point()`" );
280+ return PreservedAnalyses::all ();
275281 }
276282
277- bool runOnModule (Module &M) override {
278- LLVMContext &Context = M.getContext ();
279-
280- // Locate the "dummy" control point provided by the user.
281- CallInst *OldCtrlPointCall = findControlPointCall (M);
282- if (OldCtrlPointCall == nullptr ) {
283- Context.emitError (
284- " ykllvm couldn't find the call to `yk_control_point()`" );
285- return false ;
286- }
287-
288- // Replace old control point call.
289- IRBuilder<> Builder (OldCtrlPointCall);
290-
291- // Get function containing the control point.
292- Function *Caller = OldCtrlPointCall->getFunction ();
293-
294- // Find all live variables just before the call to the control point.
295- DominatorTree DT (*Caller);
296- std::vector<Value *> LiveVals = getLiveVars (DT, OldCtrlPointCall);
297- if (LiveVals.size () == 0 ) {
298- Context.emitError (
299- " The interpreter loop has no live variables!\n "
300- " ykllvm doesn't support this scenario, as such an interpreter would "
301- " make little sense." );
302- return false ;
303- }
304-
305- // Generate the YkCtrlPointVars struct. This struct is used to package up a
306- // copy of all LLVM variables that are live just before the call to the
307- // control point. These are passed in to the patched control point so that
308- // they can be used as inputs and outputs to JITted trace code. The control
309- // point returns a new YkCtrlPointVars whose members may have been mutated
310- // by JITted trace code (if a trace was executed).
311- std::vector<Type *> TypeParams;
312- for (Value *V : LiveVals) {
313- TypeParams.push_back (V->getType ());
314- }
315- StructType *CtrlPointReturnTy =
316- StructType::create (TypeParams, " YkCtrlPointVars" );
317-
318- // Create the new control point.
319- FunctionType *FType = FunctionType::get (
320- CtrlPointReturnTy, {Type::getInt32Ty (Context), CtrlPointReturnTy},
321- false );
322- Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
323- YK_NEW_CONTROL_POINT, M);
324-
325- // Instantiate the YkCtrlPointStruct to pass in to the control point.
326- Value *InputStruct = cast<Value>(Constant::getNullValue (CtrlPointReturnTy));
327- unsigned LvIdx = 0 ;
328- for (Value *LV : LiveVals) {
329- InputStruct = Builder.CreateInsertValue (InputStruct, LV, LvIdx);
330- assert (LvIdx != UINT_MAX);
331- LvIdx++;
332- }
283+ // Replace old control point call.
284+ IRBuilder<> Builder (OldCtrlPointCall);
285+
286+ // Get function containing the control point.
287+ Function *Caller = OldCtrlPointCall->getFunction ();
288+
289+ // Find all live variables just before the call to the control point.
290+ DominatorTree DT (*Caller);
291+ std::vector<Value *> LiveVals = getLiveVars (DT, OldCtrlPointCall);
292+ if (LiveVals.size () == 0 ) {
293+ Context.emitError (
294+ " The interpreter loop has no live variables!\n "
295+ " ykllvm doesn't support this scenario, as such an interpreter would "
296+ " make little sense." );
297+ return PreservedAnalyses::all ();
298+ }
333299
334- // Insert call to the new control point.
335- CallInst *CtrlPointRet = Builder.CreateCall (
336- NF, {OldCtrlPointCall->getArgOperand (0 ), InputStruct});
337-
338- // Once the control point returns we need to extract the (potentially
339- // mutated) values from the returned YkCtrlPointStruct and reassign them to
340- // their corresponding live variables. In LLVM IR we can do this by simply
341- // replacing all future references with the new values.
342- LvIdx = 0 ;
343- for (Value *LV : LiveVals) {
344- Value *New = Builder.CreateExtractValue (cast<Value>(CtrlPointRet), LvIdx);
345- LV->replaceUsesWithIf (
346- New, [&](Use &U) { return DT.dominates (CtrlPointRet, U); });
347- assert (LvIdx != UINT_MAX);
348- LvIdx++;
349- }
300+ // Generate the YkCtrlPointVars struct. This struct is used to package up a
301+ // copy of all LLVM variables that are live just before the call to the
302+ // control point. These are passed in to the patched control point so that
303+ // they can be used as inputs and outputs to JITted trace code. The control
304+ // point returns a new YkCtrlPointVars whose members may have been mutated
305+ // by JITted trace code (if a trace was executed).
306+ std::vector<Type *> TypeParams;
307+ for (Value *V : LiveVals) {
308+ TypeParams.push_back (V->getType ());
309+ }
310+ StructType *CtrlPointReturnTy =
311+ StructType::create (TypeParams, " YkCtrlPointVars" );
312+
313+ // Create the new control point.
314+ FunctionType *FType = FunctionType::get (
315+ CtrlPointReturnTy, {Type::getInt32Ty (Context), CtrlPointReturnTy}, false );
316+ Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
317+ YK_NEW_CONTROL_POINT, M);
318+
319+ // Instantiate the YkCtrlPointStruct to pass in to the control point.
320+ Value *InputStruct = cast<Value>(Constant::getNullValue (CtrlPointReturnTy));
321+ unsigned LvIdx = 0 ;
322+ for (Value *LV : LiveVals) {
323+ InputStruct = Builder.CreateInsertValue (InputStruct, LV, LvIdx);
324+ assert (LvIdx != UINT_MAX);
325+ LvIdx++;
326+ }
350327
351- // Replace the call to the dummy control point.
352- OldCtrlPointCall->eraseFromParent ();
328+ // Insert call to the new control point.
329+ CallInst *CtrlPointRet =
330+ Builder.CreateCall (NF, {OldCtrlPointCall->getArgOperand (0 ), InputStruct});
331+
332+ // Once the control point returns we need to extract the (potentially
333+ // mutated) values from the returned YkCtrlPointStruct and reassign them to
334+ // their corresponding live variables. In LLVM IR we can do this by simply
335+ // replacing all future references with the new values.
336+ LvIdx = 0 ;
337+ for (Value *LV : LiveVals) {
338+ Value *New = Builder.CreateExtractValue (cast<Value>(CtrlPointRet), LvIdx);
339+ LV->replaceUsesWithIf (
340+ New, [&](Use &U) { return DT.dominates (CtrlPointRet, U); });
341+ assert (LvIdx != UINT_MAX);
342+ LvIdx++;
343+ }
353344
354- // Generate new control point logic .
355- createControlPoint (M, NF, LiveVals, CtrlPointReturnTy );
345+ // Replace the call to the dummy control point.
346+ OldCtrlPointCall-> eraseFromParent ( );
356347
357- return true ;
358- }
359- };
360- char YkControlPointPass::ID = 0 ;
361- } // namespace
348+ // Generate new control point logic.
349+ createControlPoint (M, NF, LiveVals, CtrlPointReturnTy);
362350
363- namespace llvm {
364- ModulePass *createYkControlPointPass () { return new YkControlPointPass (); }
365- } // namespace llvm
351+ return PreservedAnalyses::none ();
352+ }
0 commit comments