@@ -162,25 +162,11 @@ class YkControlPoint : public ModulePass {
162162 ->getType ();
163163
164164 // Create the new control point, which is of the form:
165- // bool new_control_point(YkMT*, YkLocation*, CtrlPointVars*,
166- // ReturnValue*)
167- // If the return type of the control point's caller is void (i.e. if a
168- // function f calls yk_control_point and f's return type is void), create
169- // an Int1 pointer as a dummy. We have to pass something as the yk_stopgap
170- // signature expects a pointer, even if its never used.
171- Type *ReturnTy = Caller->getReturnType ();
172- Type *ReturnPtrTy;
173- if (ReturnTy->isVoidTy ()) {
174- // Create dummy pointer which we pass in but which is never written to.
175- ReturnPtrTy = Type::getInt1Ty (Context);
176- } else {
177- ReturnPtrTy = ReturnTy;
178- }
179- FunctionType *FType =
180- FunctionType::get (Type::getInt1Ty (Context),
181- {YkMTTy, YkLocTy, CtrlPointVarsTy->getPointerTo (),
182- ReturnPtrTy->getPointerTo ()},
183- false );
165+ // void* new_control_point(YkMT*, YkLocation*, CtrlPointVars*, void*)
166+ PointerType *VoidPtr = PointerType::get (Context, 0 );
167+ FunctionType *FType = FunctionType::get (
168+ VoidPtr, {YkMTTy, YkLocTy, CtrlPointVarsTy->getPointerTo (), VoidPtr},
169+ false );
184170 Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
185171 YK_NEW_CONTROL_POINT, M);
186172
@@ -190,10 +176,6 @@ class YkControlPoint : public ModulePass {
190176 IRBuilder<> Builder (Caller->getEntryBlock ().getFirstNonPHI ());
191177 Value *InputStruct = Builder.CreateAlloca (CtrlPointVarsTy, 0 , " " );
192178
193- // Also at the top, generate storage for the interpreted return of the
194- // control points caller.
195- Value *ReturnPtr = Builder.CreateAlloca (ReturnPtrTy, 0 , " " );
196-
197179 Builder.SetInsertPoint (OldCtrlPointCall);
198180 unsigned LvIdx = 0 ;
199181 for (Value *LV : LiveVals) {
@@ -205,11 +187,17 @@ class YkControlPoint : public ModulePass {
205187 LvIdx++;
206188 }
207189
190+ // Create a call to the llvm.frameaddress intrinsic, which we pass into the
191+ // control point. This is later required for stack reconstruction.
192+ Function *FrameAddress =
193+ Intrinsic::getDeclaration (&M, Intrinsic::frameaddress, {VoidPtr});
194+ Value *FAddr = Builder.CreateCall (FrameAddress, {Builder.getInt32 (0 )});
195+
208196 // Insert call to the new control point.
209197 Instruction *NewCtrlPointCallInst = Builder.CreateCall (
210198 NF, {OldCtrlPointCall->getArgOperand (YK_CONTROL_POINT_ARG_MT_IDX),
211199 OldCtrlPointCall->getArgOperand (YK_CONTROL_POINT_ARG_LOC_IDX),
212- InputStruct, ReturnPtr });
200+ InputStruct, FAddr });
213201
214202 // Once the control point returns we need to extract the (potentially
215203 // mutated) values from the returned YkCtrlPointStruct and reassign them to
@@ -238,14 +226,14 @@ class YkControlPoint : public ModulePass {
238226 // Create the new exit block.
239227 BasicBlock *ExitBB = BasicBlock::Create (Context, " " , Caller);
240228 Builder.SetInsertPoint (ExitBB);
241- // YKFIXME: We need to return the value of interpreted return and the return
242- // type must be that of the control point's caller .
243- if (ReturnTy-> isVoidTy ()) {
244- Builder. CreateRetVoid ( );
245- } else {
246- Value *ReturnValue = Builder. CreateLoad (ReturnTy, ReturnPtr );
247- Builder.CreateRet (ReturnValue );
248- }
229+
230+ // Create call to frame reconstructor .
231+ FunctionType *YKFRType =
232+ FunctionType::get ( Type::getVoidTy (Context), {VoidPtr}, false );
233+ Function *YKFR = Function::Create (YKFRType, GlobalVariable::ExternalLinkage,
234+ YK_RECONSTRUCT_FRAMES, M );
235+ Builder.CreateCall (YKFR, {NewCtrlPointCallInst} );
236+ Builder. CreateUnreachable ();
249237
250238 // To do so we need to first split up the current block and then
251239 // insert a conditional branch that either continues or returns.
@@ -256,7 +244,13 @@ class YkControlPoint : public ModulePass {
256244 Instruction &OldBr = BB->back ();
257245 OldBr.eraseFromParent ();
258246 Builder.SetInsertPoint (BB);
259- Builder.CreateCondBr (NewCtrlPointCallInst, ExitBB, ContBB);
247+ // The return value of the control point tells us whether a guard has failed
248+ // or not (i.e. anything other than a nullptr means a guard has failed). If
249+ // it has jump to `ExitBB` which calls the code that copies over the new
250+ // stack from the given pointer.
251+ Value *HasGuardFailed = Builder.CreateICmpEQ (
252+ NewCtrlPointCallInst, ConstantPointerNull::get (VoidPtr));
253+ Builder.CreateCondBr (HasGuardFailed, ContBB, ExitBB);
260254
261255#ifndef NDEBUG
262256 // Our pass runs after LLVM normally does its verify pass. In debug builds
0 commit comments