@@ -548,7 +548,13 @@ static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const s
548
548
static void allocate_gc_frame (jl_codectx_t &ctx, BasicBlock *b0);
549
549
static void CreateTrap (IRBuilder<> &irbuilder);
550
550
static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
551
- jl_cgval_t *args, size_t nargs, CallingConv::ID cc);
551
+ jl_cgval_t *args, size_t nargs,
552
+ AttributeList Attrs, CallingConv::ID cc);
553
+ static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
554
+ jl_cgval_t *args, size_t nargs) {
555
+ AttributeList Attrs;
556
+ return emit_jlcall (ctx, theFptr, theF, args, nargs, Attrs, JLCALL_F_CC);
557
+ }
552
558
553
559
static Value *literal_pointer_val (jl_codectx_t &ctx, jl_value_t *p);
554
560
static GlobalVariable *prepare_global_in (Module *M, GlobalVariable *G);
@@ -2182,7 +2188,7 @@ static jl_cgval_t emit_getfield(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_s
2182
2188
strct,
2183
2189
mark_julia_const ((jl_value_t *)name)
2184
2190
};
2185
- Value *result = emit_jlcall (ctx, jlgetfield_func, maybe_decay_untracked (V_null), myargs_array, 2 , JLCALL_F_CC );
2191
+ Value *result = emit_jlcall (ctx, jlgetfield_func, maybe_decay_untracked (V_null), myargs_array, 2 );
2186
2192
return mark_julia_type (ctx, result, true , jl_any_type);
2187
2193
}
2188
2194
@@ -3022,7 +3028,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3022
3028
}
3023
3029
3024
3030
static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
3025
- jl_cgval_t *argv, size_t nargs, CallingConv::ID cc)
3031
+ jl_cgval_t *argv, size_t nargs,
3032
+ AttributeList Attrs, CallingConv::ID cc)
3026
3033
{
3027
3034
// emit arguments
3028
3035
SmallVector<Value*, 3 > theArgs;
@@ -3040,7 +3047,8 @@ static CallInst *emit_jlcall(jl_codectx_t &ctx, Value *theFptr, Value *theF,
3040
3047
CallInst *result = ctx.builder .CreateCall (FTy,
3041
3048
ctx.builder .CreateBitCast (prepare_call (theFptr), FTy->getPointerTo ()),
3042
3049
theArgs);
3043
- add_return_attr (result, Attribute::NonNull);
3050
+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::ReturnIndex, Attribute::NonNull);
3051
+ result->setAttributes (Attrs);
3044
3052
result->setCallingConv (cc);
3045
3053
return result;
3046
3054
}
@@ -3052,7 +3060,14 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
3052
3060
// emit specialized call site
3053
3061
jl_value_t *jlretty = codeinst->rettype ;
3054
3062
jl_returninfo_t returninfo = get_specsig_function (jl_Module, specFunctionObject, codeinst->def ->specTypes , jlretty);
3055
- FunctionType *cft = returninfo.decl ->getFunctionType ();
3063
+ Function *f = returninfo.decl ;
3064
+ FunctionType *cft = f->getFunctionType ();
3065
+ if (codeinst->def ->def .method ->pure ) {
3066
+ // pure marked functions don't have side-effects, nor observe them
3067
+ f->addFnAttr (Thunk);
3068
+ f->addFnAttr (Attribute::ReadNone);
3069
+ f->addFnAttr (Attribute::NoUnwind);
3070
+ }
3056
3071
3057
3072
size_t nfargs = cft->getNumParams ();
3058
3073
Value **argvals = (Value**)alloca (nfargs * sizeof (Value*));
@@ -3116,8 +3131,8 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
3116
3131
idx++;
3117
3132
}
3118
3133
assert (idx == nfargs);
3119
- CallInst *call = ctx.builder .CreateCall (returninfo. decl , ArrayRef<Value*>(&argvals[0 ], nfargs));
3120
- call->setAttributes (returninfo. decl ->getAttributes ());
3134
+ CallInst *call = ctx.builder .CreateCall (f , ArrayRef<Value*>(&argvals[0 ], nfargs));
3135
+ call->setAttributes (f ->getAttributes ());
3121
3136
3122
3137
jl_cgval_t retval;
3123
3138
switch (returninfo.cc ) {
@@ -3157,7 +3172,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
3157
3172
return retval;
3158
3173
}
3159
3174
3160
- static jl_cgval_t emit_call_specfun_boxed (jl_codectx_t &ctx, StringRef specFunctionObject,
3175
+ static jl_cgval_t emit_call_specfun_boxed (jl_codectx_t &ctx, jl_code_instance_t *codeinst, StringRef specFunctionObject,
3161
3176
jl_cgval_t *argv, size_t nargs, jl_value_t *inferred_retty)
3162
3177
{
3163
3178
auto theFptr = jl_Module->getOrInsertFunction (specFunctionObject, jl_func_sig)
@@ -3166,11 +3181,20 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, StringRef specFunct
3166
3181
#else
3167
3182
;
3168
3183
#endif
3169
- if (auto F = dyn_cast<Function>(theFptr->stripPointerCasts ())) {
3170
- add_return_attr (F, Attribute::NonNull);
3171
- F->addFnAttr (Thunk);
3172
- }
3173
- Value *ret = emit_jlcall (ctx, theFptr, nullptr , argv, nargs, JLCALL_F_CC);
3184
+ AttributeList Attrs;
3185
+ auto F = dyn_cast<Function>(theFptr->stripPointerCasts ());
3186
+ if (F)
3187
+ Attrs = F->getAttributes ();
3188
+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::ReturnIndex, Attribute::NonNull)
3189
+ .addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Thunk);
3190
+ if (codeinst->def ->def .method ->pure ) {
3191
+ // pure marked functions don't have side-effects, nor observe them
3192
+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Attribute::ReadNone)
3193
+ .addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Attribute::NoUnwind);
3194
+ }
3195
+ if (F)
3196
+ F->setAttributes (Attrs);
3197
+ Value *ret = emit_jlcall (ctx, theFptr, nullptr , argv, nargs, Attrs, JLCALL_F_CC);
3174
3198
return mark_julia_type (ctx, ret, true , inferred_retty);
3175
3199
}
3176
3200
@@ -3204,7 +3228,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
3204
3228
}
3205
3229
if (decls.functionObject ) {
3206
3230
if (!strcmp (decls.functionObject , " jl_fptr_args" )) {
3207
- result = emit_call_specfun_boxed (ctx, decls.specFunctionObject , argv, nargs, rt);
3231
+ result = emit_call_specfun_boxed (ctx, codeinst, decls.specFunctionObject , argv, nargs, rt);
3208
3232
handled = true ;
3209
3233
}
3210
3234
else if (!!strcmp (decls.functionObject , " jl_fptr_sparam" )) {
@@ -3216,7 +3240,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
3216
3240
}
3217
3241
}
3218
3242
if (!handled) {
3219
- Value *r = emit_jlcall (ctx, prepare_call (jlinvoke_func), boxed (ctx, lival), argv, nargs, JLCALL_F2_CC);
3243
+ Value *r = emit_jlcall (ctx, prepare_call (jlinvoke_func), boxed (ctx, lival), argv, nargs, jlinvoke_func-> getAttributes (), JLCALL_F2_CC);
3220
3244
result = mark_julia_type (ctx, r, true , rt);
3221
3245
}
3222
3246
if (result.typ == jl_bottom_type)
@@ -3257,13 +3281,13 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
3257
3281
std::map<jl_fptr_args_t , Function*>::iterator it = builtin_func_map.find (jl_get_builtin_fptr (f.constant ));
3258
3282
if (it != builtin_func_map.end ()) {
3259
3283
Value *theFptr = it->second ;
3260
- Value *ret = emit_jlcall (ctx, theFptr, maybe_decay_untracked (V_null), &argv[1 ], nargs - 1 , JLCALL_F_CC );
3284
+ Value *ret = emit_jlcall (ctx, theFptr, maybe_decay_untracked (V_null), &argv[1 ], nargs - 1 );
3261
3285
return mark_julia_type (ctx, ret, true , rt);
3262
3286
}
3263
3287
}
3264
3288
3265
3289
// emit function and arguments
3266
- Value *callval = emit_jlcall (ctx, jlapplygeneric_func, nullptr , argv, nargs, JLCALL_F_CC );
3290
+ Value *callval = emit_jlcall (ctx, jlapplygeneric_func, nullptr , argv, nargs);
3267
3291
return mark_julia_type (ctx, callval, true , rt);
3268
3292
}
3269
3293
@@ -4128,7 +4152,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
4128
4152
assert (nargs <= jl_datatype_nfields (jl_tparam0 (ty)) + 1 );
4129
4153
return emit_new_struct (ctx, jl_tparam0 (ty), nargs - 1 , &argv[1 ]);
4130
4154
}
4131
- Value *val = emit_jlcall (ctx, jlnew_func, nullptr , argv, nargs, JLCALL_F_CC );
4155
+ Value *val = emit_jlcall (ctx, jlnew_func, nullptr , argv, nargs);
4132
4156
// temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
4133
4157
// it to the inferred type.
4134
4158
return mark_julia_type (ctx, val, true , (jl_value_t *)jl_any_type);
@@ -4325,7 +4349,7 @@ static void emit_cfunc_invalidate(
4325
4349
}
4326
4350
}
4327
4351
assert (AI == gf_thunk->arg_end ());
4328
- Value *gf_ret = emit_jlcall (ctx, jlapplygeneric_func, nullptr , myargs, nargs, JLCALL_F_CC );
4352
+ Value *gf_ret = emit_jlcall (ctx, jlapplygeneric_func, nullptr , myargs, nargs);
4329
4353
jl_cgval_t gf_retbox = mark_julia_type (ctx, gf_ret, true , jl_any_type);
4330
4354
jl_value_t *astrt = codeinst->rettype ;
4331
4355
if (cc != jl_returninfo_t ::Boxed) {
@@ -4697,11 +4721,11 @@ static Function* gen_cfun_wrapper(
4697
4721
// for jlcall, we need to pass the function object even if it is a ghost.
4698
4722
Value *theF = boxed (ctx, inputargs[0 ]);
4699
4723
assert (theF);
4700
- ret_jlcall = emit_jlcall (ctx, theFptr, theF, &inputargs[1 ], nargs, JLCALL_F_CC );
4724
+ ret_jlcall = emit_jlcall (ctx, theFptr, theF, &inputargs[1 ], nargs);
4701
4725
ctx.builder .CreateBr (b_after);
4702
4726
ctx.builder .SetInsertPoint (b_generic);
4703
4727
}
4704
- Value *ret = emit_jlcall (ctx, prepare_call (jlapplygeneric_func), NULL , inputargs, nargs + 1 , JLCALL_F_CC );
4728
+ Value *ret = emit_jlcall (ctx, prepare_call (jlapplygeneric_func), NULL , inputargs, nargs + 1 );
4705
4729
if (age_ok) {
4706
4730
ctx.builder .CreateBr (b_after);
4707
4731
ctx.builder .SetInsertPoint (b_after);
@@ -5998,7 +6022,7 @@ static std::unique_ptr<Module> emit_function(
5998
6022
emit_varinfo_assign (ctx, vi, tuple);
5999
6023
} else {
6000
6024
Value *vtpl = emit_jlcall (ctx, prepare_call (jltuple_func), maybe_decay_untracked (V_null),
6001
- vargs, ctx.nvargs , JLCALL_F_CC );
6025
+ vargs, ctx.nvargs );
6002
6026
jl_cgval_t tuple = mark_julia_type (ctx, vtpl, true , vi.value .typ );
6003
6027
emit_varinfo_assign (ctx, vi, tuple);
6004
6028
}
0 commit comments