@@ -162,25 +162,11 @@ class YkControlPoint : public ModulePass {
162
162
->getType ();
163
163
164
164
// 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 );
184
170
Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
185
171
YK_NEW_CONTROL_POINT, M);
186
172
@@ -190,10 +176,6 @@ class YkControlPoint : public ModulePass {
190
176
IRBuilder<> Builder (Caller->getEntryBlock ().getFirstNonPHI ());
191
177
Value *InputStruct = Builder.CreateAlloca (CtrlPointVarsTy, 0 , " " );
192
178
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
-
197
179
Builder.SetInsertPoint (OldCtrlPointCall);
198
180
unsigned LvIdx = 0 ;
199
181
for (Value *LV : LiveVals) {
@@ -205,11 +187,17 @@ class YkControlPoint : public ModulePass {
205
187
LvIdx++;
206
188
}
207
189
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
+
208
196
// Insert call to the new control point.
209
197
Instruction *NewCtrlPointCallInst = Builder.CreateCall (
210
198
NF, {OldCtrlPointCall->getArgOperand (YK_CONTROL_POINT_ARG_MT_IDX),
211
199
OldCtrlPointCall->getArgOperand (YK_CONTROL_POINT_ARG_LOC_IDX),
212
- InputStruct, ReturnPtr });
200
+ InputStruct, FAddr });
213
201
214
202
// Once the control point returns we need to extract the (potentially
215
203
// mutated) values from the returned YkCtrlPointStruct and reassign them to
@@ -238,14 +226,14 @@ class YkControlPoint : public ModulePass {
238
226
// Create the new exit block.
239
227
BasicBlock *ExitBB = BasicBlock::Create (Context, " " , Caller);
240
228
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 ();
249
237
250
238
// To do so we need to first split up the current block and then
251
239
// insert a conditional branch that either continues or returns.
@@ -256,7 +244,13 @@ class YkControlPoint : public ModulePass {
256
244
Instruction &OldBr = BB->back ();
257
245
OldBr.eraseFromParent ();
258
246
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);
260
254
261
255
#ifndef NDEBUG
262
256
// Our pass runs after LLVM normally does its verify pass. In debug builds
0 commit comments