@@ -4160,10 +4160,10 @@ static void emit_cfunc_invalidate(
4160
4160
#if JL_LLVM_VERSION >= 50000
4161
4161
0 ,
4162
4162
#endif
4163
- ConstantInt::get (T_int32, nargs + 1 ), " jlcall" , ctx.ptlsStates );
4163
+ ConstantInt::get (T_int32, nargs), " jlcall" , ctx.ptlsStates );
4164
4164
if (cc == jl_returninfo_t ::SRet || cc == jl_returninfo_t ::Union)
4165
4165
++AI;
4166
- for (size_t i = 0 ; i < nargs + 1 ; i++) {
4166
+ for (size_t i = 0 ; i < nargs; i++) {
4167
4167
jl_value_t *jt = jl_nth_slot_type (lam->specTypes , i);
4168
4168
bool isboxed;
4169
4169
Type *et = julia_type_to_llvm (jt, &isboxed);
@@ -4193,7 +4193,7 @@ static void emit_cfunc_invalidate(
4193
4193
ctx.builder .CreateStore (maybe_decay_untracked (arg_box), argn);
4194
4194
}
4195
4195
assert (AI == gf_thunk->arg_end ());
4196
- Value *nargs_v = ConstantInt::get (T_int32, nargs + 1 );
4196
+ Value *nargs_v = ConstantInt::get (T_int32, nargs);
4197
4197
Value *gf_ret = ctx.builder .CreateCall (prepare_call (jlapplygeneric_func), { myargs, nargs_v });
4198
4198
jl_cgval_t gf_retbox = mark_julia_type (ctx, gf_ret, true , jl_any_type, /* needsroot*/ false );
4199
4199
jl_value_t *astrt = lam->rettype ;
@@ -4343,73 +4343,16 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
4343
4343
sf->func .value = jl_box_voidpointer ((void *)cw_proto);
4344
4344
jl_gc_wb (sf, sf->func .value );
4345
4345
4346
- // See whether this function is specsig or jlcall or generic (unknown)
4347
- bool specsig, jlfunc_sret;
4348
- jl_returninfo_t ::CallingConv cc = jl_returninfo_t ::Boxed;
4349
- Function *theFptr;
4350
- Value *result;
4351
- Value *myargs;
4352
- size_t FParamIndex = 0 ;
4353
- std::vector<Value*> args;
4346
+ // first emit code to record the arguments
4354
4347
Function::arg_iterator AI = cw->arg_begin ();
4355
4348
Value *sretPtr = sig.sret ? &*AI++ : NULL ;
4356
- if (lam && lam->jlcall_api == 2 ) {
4357
- nargs = 0 ; // arguments not needed
4358
- specsig = true ;
4359
- jlfunc_sret = false ;
4360
- myargs = NULL ;
4361
- theFptr = NULL ;
4362
- }
4363
- else if (lam && lam->functionObjectsDecls .specFunctionObject != NULL ) {
4364
- const char *protoname = lam->functionObjectsDecls .specFunctionObject ;
4365
- jl_returninfo_t returninfo = get_specsig_function (M, protoname, lam->specTypes , lam->rettype );
4366
- FunctionType *cft = returninfo.decl ->getFunctionType ();
4367
- theFptr = returninfo.decl ;
4368
- specsig = true ;
4369
- cc = returninfo.cc ;
4370
- jlfunc_sret = cc == jl_returninfo_t ::SRet;
4371
- if (jlfunc_sret || cc == jl_returninfo_t ::Union) {
4372
- // fuse the two sret together, or emit an alloca to hold it
4373
- if (sig.sret && jlfunc_sret)
4374
- result = emit_bitcast (ctx, sretPtr, cft->getParamType (0 ));
4375
- else
4376
- result = decay_derived (ctx.builder .CreateAlloca (cft->getParamType (0 )->getContainedType (0 )));
4377
- args.push_back (result);
4378
- FParamIndex++;
4379
- }
4380
- myargs = NULL ;
4381
- }
4382
- else {
4383
- theFptr = NULL ;
4384
- if (lam) {
4385
- const char *fname = lam->functionObjectsDecls .functionObject ;
4386
- if (fname) {
4387
- theFptr = cast_or_null<Function>(jl_Module->getNamedValue (fname));
4388
- if (!theFptr) {
4389
- theFptr = Function::Create (jl_func_sig, GlobalVariable::ExternalLinkage,
4390
- fname, jl_Module);
4391
- }
4392
- else {
4393
- assert (theFptr->getFunctionType () == jl_func_sig);
4394
- }
4395
- }
4396
- }
4397
- specsig = false ;
4398
- jlfunc_sret = false ;
4399
- myargs = new AllocaInst (T_prjlvalue,
4400
- #if JL_LLVM_VERSION >= 50000
4401
- 0 ,
4402
- #endif
4403
- ConstantInt::get (T_int32, nargs + 1 ), " jlcall" , /* InsertBefore*/ ctx.ptlsStates );
4404
- FParamIndex++; // leave room for writing the ff object at the beginning
4405
- }
4406
-
4407
- // first emit the arguments
4408
- for (size_t i = 0 ; i < nargs; i++) {
4409
- Value *val = &*AI++;
4349
+ jl_cgval_t *inputargs = (jl_cgval_t *)alloca (sizeof (jl_cgval_t ) * (nargs + 1 ));
4350
+ inputargs[0 ] = mark_julia_const (ff); // we need to pass the function object even if (even though) it is a ghost
4351
+ for (size_t i = 0 ; i < nargs; ++i, ++AI) {
4352
+ Value *val = &*AI;
4410
4353
jl_value_t *jargty = jl_nth_slot_type ((jl_value_t *)argt, i);
4411
4354
// figure out how to unpack this type
4412
- jl_cgval_t inputarg;
4355
+ jl_cgval_t & inputarg = inputargs[i + 1 ] ;
4413
4356
if (jl_is_abstract_ref_type (jargty)) {
4414
4357
// a pointer to a value
4415
4358
jargty = jl_tparam0 (jargty);
@@ -4473,18 +4416,39 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
4473
4416
}
4474
4417
}
4475
4418
}
4419
+ }
4420
+ assert (AI == cw->arg_end ());
4476
4421
4477
- // figure out how to repack this type
4478
- if (!specsig) {
4479
- Value *arg = boxed (ctx, inputarg, false ); // don't want a gcroot, since it's about to be put into the jlcall frame anyways
4480
- GetElementPtrInst *slot = GetElementPtrInst::Create (T_prjlvalue, myargs,
4481
- ArrayRef<Value*>(ConstantInt::get (T_int32, FParamIndex)));
4482
- slot->insertAfter (ctx.ptlsStates );
4483
- ctx.builder .CreateStore (arg, slot);
4422
+ // Create the call
4423
+ bool jlfunc_sret;
4424
+ jl_cgval_t retval;
4425
+ if (lam && lam->jlcall_api == 2 ) {
4426
+ nargs = 0 ; // arguments not needed -- TODO: not really true, should emit an age_ok test and jlcall
4427
+ jlfunc_sret = false ;
4428
+ retval = mark_julia_const (lam->inferred_const );
4429
+ }
4430
+ else if (lam && lam->functionObjectsDecls .specFunctionObject != NULL ) {
4431
+ // emit a specsig call
4432
+ const char *protoname = lam->functionObjectsDecls .specFunctionObject ;
4433
+ jl_returninfo_t returninfo = get_specsig_function (M, protoname, lam->specTypes , lam->rettype );
4434
+ FunctionType *cft = returninfo.decl ->getFunctionType ();
4435
+ jlfunc_sret = (returninfo.cc == jl_returninfo_t ::SRet);
4436
+
4437
+ std::vector<Value*> args;
4438
+ Value *result;
4439
+ if (jlfunc_sret || returninfo.cc == jl_returninfo_t ::Union) {
4440
+ // fuse the two sret together, or emit an alloca to hold it
4441
+ if (sig.sret && jlfunc_sret)
4442
+ result = emit_bitcast (ctx, sretPtr, cft->getParamType (0 ));
4443
+ else
4444
+ result = decay_derived (emit_static_alloca (ctx, cft->getParamType (0 )->getContainedType (0 )));
4445
+ args.push_back (result);
4484
4446
}
4485
- else {
4447
+ for (size_t i = 0 ; i < nargs + 1 ; i++) {
4448
+ // figure out how to repack the arguments
4449
+ const jl_cgval_t &inputarg = inputargs[i];
4486
4450
Value *arg;
4487
- jl_value_t *spect = jl_nth_slot_type (lam->specTypes , i + 1 ); // +1 because argt excludes function
4451
+ jl_value_t *spect = jl_nth_slot_type (lam->specTypes , i);
4488
4452
bool isboxed;
4489
4453
Type *T = julia_type_to_llvm (spect, &isboxed);
4490
4454
if (isboxed) {
@@ -4505,63 +4469,62 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
4505
4469
// add to argument list
4506
4470
args.push_back (arg);
4507
4471
}
4508
- FParamIndex++;
4509
- }
4510
-
4511
- // Create the call
4512
- jl_cgval_t retval;
4513
- Function *gf_thunk = NULL ;
4514
- if (specsig) {
4515
- if (lam->jlcall_api == 2 ) {
4516
- retval = mark_julia_const (lam->inferred_const );
4517
- }
4518
- else {
4519
- assert (theFptr);
4520
- Value *call_v = prepare_call (theFptr);
4521
- if (age_ok) {
4522
- funcName << " _gfthunk" ;
4523
- gf_thunk = Function::Create (theFptr->getFunctionType (),
4524
- GlobalVariable::InternalLinkage,
4525
- funcName.str (), M);
4526
- jl_init_function (gf_thunk);
4527
- gf_thunk->setAttributes (theFptr->getAttributes ());
4528
- gf_thunk->addFnAttr (" no-frame-pointer-elim" , " true" );
4529
- call_v = ctx.builder .CreateSelect (age_ok, call_v, gf_thunk);
4530
- }
4531
- CallInst *call = ctx.builder .CreateCall (call_v, ArrayRef<Value*>(args));
4532
- call->setAttributes (theFptr->getAttributes ());
4533
- switch (cc) {
4534
- case jl_returninfo_t ::Boxed:
4535
- retval = mark_julia_type (ctx, call, true , astrt);
4536
- break ;
4537
- case jl_returninfo_t ::Register:
4538
- retval = mark_julia_type (ctx, call, false , astrt);
4539
- break ;
4540
- case jl_returninfo_t ::SRet:
4541
- retval = mark_julia_slot (result, astrt, NULL , tbaa_stack);
4542
- break ;
4543
- case jl_returninfo_t ::Union:
4544
- retval = mark_julia_slot (ctx.builder .CreateExtractValue (call, 0 ),
4545
- astrt,
4546
- ctx.builder .CreateExtractValue (call, 1 ),
4547
- tbaa_stack);
4548
- // note that the value may not be rooted here (on the return path)
4549
- break ;
4550
- case jl_returninfo_t ::Ghosts:
4551
- retval = mark_julia_slot (NULL , astrt, call, tbaa_stack);
4552
- break ;
4553
- }
4472
+ Value *theFptr = returninfo.decl ;
4473
+ assert (theFptr);
4474
+ if (age_ok) {
4475
+ funcName << " _gfthunk" ;
4476
+ Function *gf_thunk = Function::Create (returninfo.decl ->getFunctionType (),
4477
+ GlobalVariable::InternalLinkage, funcName.str (), M);
4478
+ jl_init_function (gf_thunk);
4479
+ gf_thunk->setAttributes (returninfo.decl ->getAttributes ());
4480
+ gf_thunk->addFnAttr (" no-frame-pointer-elim" , " true" );
4481
+ // build a specsig -> jl_apply_generic converter thunk
4482
+ // this builds a method that calls jl_apply_generic (as a closure over a singleton function pointer),
4483
+ // but which has the signature of a specsig
4484
+ emit_cfunc_invalidate (gf_thunk, returninfo.cc , lam, nargs + 1 , world);
4485
+ theFptr = ctx.builder .CreateSelect (age_ok, theFptr, gf_thunk);
4486
+ }
4487
+ CallInst *call = ctx.builder .CreateCall (theFptr, ArrayRef<Value*>(args));
4488
+ call->setAttributes (returninfo.decl ->getAttributes ());
4489
+ switch (returninfo.cc ) {
4490
+ case jl_returninfo_t ::Boxed:
4491
+ retval = mark_julia_type (ctx, call, true , astrt);
4492
+ break ;
4493
+ case jl_returninfo_t ::Register:
4494
+ retval = mark_julia_type (ctx, call, false , astrt);
4495
+ break ;
4496
+ case jl_returninfo_t ::SRet:
4497
+ retval = mark_julia_slot (result, astrt, NULL , tbaa_stack);
4498
+ break ;
4499
+ case jl_returninfo_t ::Union:
4500
+ retval = mark_julia_slot (ctx.builder .CreateExtractValue (call, 0 ),
4501
+ astrt,
4502
+ ctx.builder .CreateExtractValue (call, 1 ),
4503
+ tbaa_stack);
4504
+ // note that the value may not be rooted here (on the return path)
4505
+ break ;
4506
+ case jl_returninfo_t ::Ghosts:
4507
+ retval = mark_julia_slot (NULL , astrt, call, tbaa_stack);
4508
+ break ;
4554
4509
}
4555
4510
}
4556
4511
else {
4557
- // for jlcall, we need to pass the function object even if it is a ghost.
4558
- // here we reconstruct the function instance from its type (first elt of argt)
4559
- Value *theF = literal_pointer_val (ctx, (jl_value_t *)ff);
4560
- GetElementPtrInst *slot = GetElementPtrInst::Create (T_prjlvalue, myargs,
4561
- ArrayRef<Value*>(ConstantInt::get (T_int32, 0 )));
4562
- slot->insertAfter (ctx.ptlsStates );
4563
- ctx.builder .CreateStore (theF, slot);
4564
-
4512
+ // emit a jlcall
4513
+ jlfunc_sret = false ;
4514
+ Function *theFptr = NULL ;
4515
+ if (lam) {
4516
+ const char *fname = lam->functionObjectsDecls .functionObject ;
4517
+ if (fname) {
4518
+ theFptr = cast_or_null<Function>(jl_Module->getNamedValue (fname));
4519
+ if (!theFptr) {
4520
+ theFptr = Function::Create (jl_func_sig, GlobalVariable::ExternalLinkage,
4521
+ fname, jl_Module);
4522
+ }
4523
+ else {
4524
+ assert (theFptr->getFunctionType () == jl_func_sig);
4525
+ }
4526
+ }
4527
+ }
4565
4528
BasicBlock *b_generic, *b_jlcall, *b_after;
4566
4529
Value *ret_jlcall;
4567
4530
if (age_ok) {
@@ -4571,19 +4534,18 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
4571
4534
b_after = BasicBlock::Create (jl_LLVMContext, " after" , cw);
4572
4535
ctx.builder .CreateCondBr (age_ok, b_jlcall, b_generic);
4573
4536
ctx.builder .SetInsertPoint (b_jlcall);
4574
- Value *nargs_v = ConstantInt::get (T_int32, nargs);
4575
- Value *myargs1 = ctx.builder .CreateConstInBoundsGEP1_32 (T_prjlvalue, myargs, 1 );
4576
- ret_jlcall = ctx.builder .CreateCall (prepare_call (theFptr), {theF, myargs1, nargs_v});
4537
+ // for jlcall, we need to pass the function object even if it is a ghost.
4538
+ Value *theF = boxed (ctx, inputargs[0 ]);
4539
+ assert (theF);
4540
+ ret_jlcall = emit_jlcall (ctx, theFptr, theF, &inputargs[1 ], nargs);
4577
4541
ctx.builder .CreateBr (b_after);
4578
4542
ctx.builder .SetInsertPoint (b_generic);
4579
4543
}
4580
-
4581
- Value *nargs_v = ConstantInt::get (T_int32, nargs + 1 );
4582
- Value *ret = ctx.builder .CreateCall (prepare_call (jlapplygeneric_func), {myargs, nargs_v});
4544
+ Value *ret = emit_jlcall (ctx, prepare_call (jlapplygeneric_func), NULL , inputargs, nargs + 1 );
4583
4545
if (age_ok) {
4584
4546
ctx.builder .CreateBr (b_after);
4585
4547
ctx.builder .SetInsertPoint (b_after);
4586
- PHINode *retphi = ctx.builder .CreatePHI (T_pjlvalue , 2 );
4548
+ PHINode *retphi = ctx.builder .CreatePHI (T_prjlvalue , 2 );
4587
4549
retphi->addIncoming (ret_jlcall, b_jlcall);
4588
4550
retphi->addIncoming (ret, b_generic);
4589
4551
ret = retphi;
@@ -4627,14 +4589,6 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
4627
4589
ctx.builder .CreateStore (last_age, ctx.world_age_field );
4628
4590
ctx.builder .CreateRet (r);
4629
4591
4630
- // also need to finish emission of our specsig -> jl_apply_generic converter thunk
4631
- // this builds a method that calls jl_apply_generic (as a closure over a singleton function pointer),
4632
- // but which has the signature of a specsig
4633
- if (gf_thunk) {
4634
- assert (lam && specsig);
4635
- emit_cfunc_invalidate (gf_thunk, cc, lam, nargs, world);
4636
- }
4637
-
4638
4592
ctx.builder .SetCurrentDebugLocation (noDbg);
4639
4593
ctx.builder .ClearInsertionPoint ();
4640
4594
0 commit comments