@@ -490,6 +490,9 @@ struct jl_varinfo_t {
490
490
#else
491
491
DIVariable dinfo;
492
492
#endif
493
+ // if the variable might be used undefined and is not boxed
494
+ // this i1 flag is true when it is defined
495
+ Value *defFlag;
493
496
bool isSA;
494
497
bool isVolatile;
495
498
bool isArgument;
@@ -503,6 +506,7 @@ struct jl_varinfo_t {
503
506
#else
504
507
dinfo (DIVariable()),
505
508
#endif
509
+ defFlag (NULL ),
506
510
isSA(false ),
507
511
isVolatile(false ), isArgument(false ),
508
512
escapes(true ), usedUndef(false ), used(false )
@@ -727,7 +731,7 @@ static bool store_unboxed_p(int s, jl_codectx_t *ctx)
727
731
jl_varinfo_t &vi = ctx->slots [s];
728
732
// only store a variable unboxed if type inference has run, which
729
733
// checks that the variable is not referenced undefined.
730
- return (ctx->source ->inferred && !vi. usedUndef &&
734
+ return (ctx->source ->inferred &&
731
735
// don't unbox vararg tuples
732
736
s != ctx->vaSlot && store_unboxed_p (vi.value .typ ));
733
737
}
@@ -737,6 +741,22 @@ static jl_sym_t *slot_symbol(int s, jl_codectx_t *ctx)
737
741
return (jl_sym_t *)jl_array_ptr_ref (ctx->source ->slotnames , s);
738
742
}
739
743
744
+ static void store_def_flag (const jl_varinfo_t &vi, bool val)
745
+ {
746
+ assert (!vi.memloc ); // undefinedness is null pointer for boxed things
747
+ assert (vi.usedUndef && vi.defFlag );
748
+ builder.CreateStore (ConstantInt::get (T_int1, val), vi.defFlag );
749
+ }
750
+
751
+ static void alloc_def_flag (jl_varinfo_t & vi, jl_codectx_t * ctx)
752
+ {
753
+ assert (!vi.memloc ); // same as above, not used for pointers
754
+ if (vi.usedUndef ) {
755
+ vi.defFlag = emit_static_alloca (T_int1, ctx);
756
+ store_def_flag (vi, false );
757
+ }
758
+ }
759
+
740
760
static Value *alloc_local (int s, jl_codectx_t *ctx)
741
761
{
742
762
jl_varinfo_t &vi = ctx->slots [s];
@@ -753,6 +773,7 @@ static Value *alloc_local(int s, jl_codectx_t *ctx)
753
773
vi.value = mark_julia_slot (lv, jt, tbaa_stack);
754
774
// slot is not immutable if there are multiple assignments
755
775
vi.value .isimmutable &= (vi.isSA && s >= ctx->nargs );
776
+ alloc_def_flag (vi, ctx);
756
777
assert (vi.value .isboxed == false );
757
778
return lv;
758
779
}
@@ -2974,9 +2995,8 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx)
2974
2995
2975
2996
// --- accessing and assigning variables ---
2976
2997
2977
- static void undef_var_error_if_null (Value *v , jl_sym_t *name, jl_codectx_t *ctx)
2998
+ static void undef_var_error_ifnot (Value *ok , jl_sym_t *name, jl_codectx_t *ctx)
2978
2999
{
2979
- Value *ok = builder.CreateICmpNE (v, V_null);
2980
3000
BasicBlock *err = BasicBlock::Create (jl_LLVMContext, " err" , ctx->f );
2981
3001
BasicBlock *ifok = BasicBlock::Create (jl_LLVMContext, " ok" );
2982
3002
builder.CreateCondBr (ok, ifok, err);
@@ -3045,7 +3065,7 @@ static jl_cgval_t emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx,
3045
3065
Instruction *v = builder.CreateLoad (bp, isvol);
3046
3066
if (tbaa)
3047
3067
tbaa_decorate (tbaa, v);
3048
- undef_var_error_if_null (v , name, ctx);
3068
+ undef_var_error_ifnot (builder. CreateICmpNE (v, V_null) , name, ctx);
3049
3069
return mark_julia_type (v, true , jl_any_type, ctx);
3050
3070
}
3051
3071
@@ -3110,14 +3130,20 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx)
3110
3130
return v;
3111
3131
}
3112
3132
}
3113
- else if (!vi.isVolatile || vi.isArgument ) {
3114
- return vi.value ;
3115
- }
3116
3133
else {
3117
- // copy value to a non-mutable location
3118
- Type *T = julia_type_to_llvm (vi.value .typ )->getPointerTo ();
3119
- Value *v = data_pointer (vi.value , ctx, T);
3120
- return mark_julia_type (builder.CreateLoad (v, vi.isVolatile ), false , vi.value .typ , ctx);
3134
+ if (vi.usedUndef ) {
3135
+ assert (vi.defFlag );
3136
+ undef_var_error_ifnot (builder.CreateLoad (vi.defFlag ), sym, ctx);
3137
+ }
3138
+ if (!vi.isVolatile || vi.isArgument ) {
3139
+ return vi.value ;
3140
+ }
3141
+ else {
3142
+ // copy value to a non-mutable location
3143
+ Type *T = julia_type_to_llvm (vi.value .typ )->getPointerTo ();
3144
+ Value *v = data_pointer (vi.value , ctx, T);
3145
+ return mark_julia_type (builder.CreateLoad (v, vi.isVolatile ), false , vi.value .typ , ctx);
3146
+ }
3121
3147
}
3122
3148
}
3123
3149
@@ -3203,13 +3229,18 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
3203
3229
Value *rval = boxed (rval_info, ctx, false ); // no root needed on the temporary since it is about to be assigned to the variable slot
3204
3230
builder.CreateStore (rval, vi.memloc , vi.isVolatile );
3205
3231
}
3206
- else if (vi.value .constant ) {
3207
- // virtual store
3208
- }
3209
3232
else {
3210
- // store unboxed
3211
- assert (vi.value .ispointer ());
3212
- emit_unbox (julia_type_to_llvm (vi.value .typ ), rval_info, vi.value .typ , vi.value .V , vi.isVolatile );
3233
+ if (vi.usedUndef )
3234
+ store_def_flag (vi, true );
3235
+
3236
+ if (vi.value .constant ) {
3237
+ // virtual store
3238
+ }
3239
+ else {
3240
+ // store unboxed
3241
+ assert (vi.value .ispointer ());
3242
+ emit_unbox (julia_type_to_llvm (vi.value .typ ), rval_info, vi.value .typ , vi.value .V , vi.isVolatile );
3243
+ }
3213
3244
}
3214
3245
}
3215
3246
@@ -3254,10 +3285,12 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx)
3254
3285
assert (jl_is_slot (var));
3255
3286
jl_varinfo_t &vi = ctx->slots [jl_slot_number (var)-1 ];
3256
3287
Value *lv = vi.memloc ;
3257
- if (lv != NULL ) {
3288
+ if (vi. usedUndef ) {
3258
3289
// create a new uninitialized variable
3259
- if (vi. usedUndef )
3290
+ if (lv != NULL )
3260
3291
builder.CreateStore (V_null, lv);
3292
+ else
3293
+ store_def_flag (vi, false );
3261
3294
}
3262
3295
return ;
3263
3296
}
@@ -4448,32 +4481,32 @@ static std::unique_ptr<Module> emit_function(jl_method_instance_t *lam, jl_code_
4448
4481
if (s == unused_sym) continue ;
4449
4482
jl_varinfo_t &varinfo = ctx.slots [i];
4450
4483
assert (!varinfo.memloc ); // variables shouldn't have memory locs already
4451
- if (!varinfo.usedUndef ) {
4452
- if (varinfo.value .constant ) {
4453
- // no need to explicitly load/store a constant/ghost value
4454
- continue ;
4455
- }
4456
- else if (jl_is_type_type (varinfo.value .typ ) && jl_is_leaf_type (jl_tparam0 (varinfo.value .typ ))) {
4457
- // replace T::Type{T} with T
4458
- varinfo.value = mark_julia_const (jl_tparam0 (varinfo.value .typ ));
4459
- continue ;
4460
- }
4461
- else if (store_unboxed_p (i, &ctx)) {
4462
- if (!varinfo.isArgument ) { // otherwise, just leave it in the input register
4463
- Value *lv = alloc_local (i, &ctx); (void )lv;
4484
+ if (varinfo.value .constant ) {
4485
+ // no need to explicitly load/store a constant/ghost value
4486
+ alloc_def_flag (varinfo, &ctx);
4487
+ continue ;
4488
+ }
4489
+ else if (jl_is_type_type (varinfo.value .typ ) && jl_is_leaf_type (jl_tparam0 (varinfo.value .typ ))) {
4490
+ // replace T::Type{T} with T
4491
+ varinfo.value = mark_julia_const (jl_tparam0 (varinfo.value .typ ));
4492
+ alloc_def_flag (varinfo, &ctx);
4493
+ continue ;
4494
+ }
4495
+ else if (store_unboxed_p (i, &ctx)) {
4496
+ if (!varinfo.isArgument ) { // otherwise, just leave it in the input register
4497
+ Value *lv = alloc_local (i, &ctx); (void )lv;
4464
4498
#if JL_LLVM_VERSION >= 30600
4465
- if (ctx.debug_enabled && varinfo.dinfo ) {
4466
- assert ((Metadata*)varinfo.dinfo ->getType () != jl_pvalue_dillvmt);
4467
- dbuilder.insertDeclare (lv, varinfo.dinfo , dbuilder.createExpression (),
4499
+ if (ctx.debug_enabled && varinfo.dinfo ) {
4500
+ assert ((Metadata*)varinfo.dinfo ->getType () != jl_pvalue_dillvmt);
4501
+ dbuilder.insertDeclare (lv, varinfo.dinfo , dbuilder.createExpression (),
4468
4502
#if JL_LLVM_VERSION >= 30700
4469
- topdebugloc,
4470
- #endif
4471
- builder.GetInsertBlock ());
4472
- }
4503
+ topdebugloc,
4473
4504
#endif
4505
+ builder.GetInsertBlock ());
4474
4506
}
4475
- continue ;
4507
+ # endif
4476
4508
}
4509
+ continue ;
4477
4510
}
4478
4511
if (!varinfo.isArgument || // always need a slot if the variable is assigned
4479
4512
specsig || // for arguments, give them stack slots if they aren't in `argArray` (otherwise, will use that pointer)
0 commit comments