@@ -283,6 +283,7 @@ static Function *jlvboundserror_func;
283
283
static Function *jlboundserrorv_func;
284
284
static Function *jlcheckassign_func;
285
285
static Function *jldeclareconst_func;
286
+ static Function *jlgetbinding_func;
286
287
static Function *jltopeval_func;
287
288
static Function *jlcopyast_func;
288
289
static Function *jltuple_func;
@@ -571,7 +572,7 @@ static int is_global(jl_sym_t *s, jl_codectx_t *ctx);
571
572
static Value *make_gcroot (Value *v, jl_codectx_t *ctx, jl_sym_t *var = NULL );
572
573
static Value *emit_boxed_rooted (jl_value_t *e, jl_codectx_t *ctx);
573
574
static Value *global_binding_pointer (jl_module_t *m, jl_sym_t *s,
574
- jl_binding_t **pbnd, bool assign);
575
+ jl_binding_t **pbnd, bool assign, jl_codectx_t *ctx );
575
576
static Value *emit_checked_var (Value *bp, jl_sym_t *name, jl_codectx_t *ctx, bool isvol=false );
576
577
static bool might_need_root (jl_value_t *ex);
577
578
static Value *emit_condition (jl_value_t *cond, const std::string &msg, jl_codectx_t *ctx);
@@ -1763,7 +1764,7 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx)
1763
1764
1764
1765
if (jl_is_module (expr)) {
1765
1766
Value *bp =
1766
- global_binding_pointer ((jl_module_t *)expr, name, NULL , false );
1767
+ global_binding_pointer ((jl_module_t *)expr, name, NULL , false , ctx );
1767
1768
// todo: use type info to avoid undef check
1768
1769
return emit_checked_var (bp, name, ctx);
1769
1770
}
@@ -2663,16 +2664,39 @@ static int is_global(jl_sym_t *s, jl_codectx_t *ctx)
2663
2664
return (it == ctx->vars .end ());
2664
2665
}
2665
2666
2667
+ static void undef_var_error_if_null (Value *v, jl_sym_t *name, jl_codectx_t *ctx)
2668
+ {
2669
+ Value *ok = builder.CreateICmpNE (v, V_null);
2670
+ BasicBlock *err = BasicBlock::Create (getGlobalContext (), " err" , ctx->f );
2671
+ BasicBlock *ifok = BasicBlock::Create (getGlobalContext (), " ok" );
2672
+ builder.CreateCondBr (ok, ifok, err);
2673
+ builder.SetInsertPoint (err);
2674
+ builder.CreateCall (prepare_call (jlundefvarerror_func), literal_pointer_val ((jl_value_t *)name));
2675
+ builder.CreateUnreachable ();
2676
+ ctx->f ->getBasicBlockList ().push_back (ifok);
2677
+ builder.SetInsertPoint (ifok);
2678
+ }
2679
+
2666
2680
static Value *global_binding_pointer (jl_module_t *m, jl_sym_t *s,
2667
- jl_binding_t **pbnd, bool assign)
2681
+ jl_binding_t **pbnd, bool assign, jl_codectx_t *ctx )
2668
2682
{
2669
2683
jl_binding_t *b=NULL ;
2670
- if (!assign)
2671
- b = jl_get_binding (m, s);
2672
- // if b is NULL, this might be a global that is not set yet but will be,
2673
- // so get a pointer for writing even when not assigning.
2674
- if (assign || b==NULL )
2684
+ if (assign) {
2675
2685
b = jl_get_binding_wr (m, s);
2686
+ assert (b != NULL );
2687
+ }
2688
+ else {
2689
+ b = jl_get_binding (m, s);
2690
+ if (b == NULL ) {
2691
+ // var not found. switch to delayed lookup.
2692
+ // TODO: examine performance of this
2693
+ Value *bval = builder.CreateCall2 (prepare_call (jlgetbinding_func),
2694
+ literal_pointer_val ((jl_value_t *)m),
2695
+ literal_pointer_val ((jl_value_t *)s));
2696
+ undef_var_error_if_null (bval, s, ctx);
2697
+ return julia_binding_gv (builder.CreateBitCast (bval,jl_ppvalue_llvmt));
2698
+ }
2699
+ }
2676
2700
if (pbnd) *pbnd = b;
2677
2701
return julia_binding_gv (b);
2678
2702
}
@@ -2693,7 +2717,7 @@ static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd,
2693
2717
s = jl_symbolnode_sym (s);
2694
2718
assert (jl_is_symbol (s));
2695
2719
if (is_global (s, ctx)) {
2696
- return global_binding_pointer (ctx->module , s, pbnd, assign);
2720
+ return global_binding_pointer (ctx->module , s, pbnd, assign, ctx );
2697
2721
}
2698
2722
jl_varinfo_t &vi = ctx->vars [s];
2699
2723
if (vi.closureidx != -1 ) {
@@ -2726,17 +2750,8 @@ static Value *emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx, boo
2726
2750
// in unreachable code, there might be a poorly-typed instance of a variable
2727
2751
// that has a concrete type everywhere it's actually used. tolerate this
2728
2752
// situation by just skipping the NULL check if it wouldn't be valid. (issue #7836)
2729
- if (v->getType () == jl_pvalue_llvmt) {
2730
- Value *ok = builder.CreateICmpNE (v, V_null);
2731
- BasicBlock *err = BasicBlock::Create (getGlobalContext (), " err" , ctx->f );
2732
- BasicBlock *ifok = BasicBlock::Create (getGlobalContext (), " ok" );
2733
- builder.CreateCondBr (ok, ifok, err);
2734
- builder.SetInsertPoint (err);
2735
- builder.CreateCall (prepare_call (jlundefvarerror_func), literal_pointer_val ((jl_value_t *)name));
2736
- builder.CreateUnreachable ();
2737
- ctx->f ->getBasicBlockList ().push_back (ifok);
2738
- builder.SetInsertPoint (ifok);
2739
- }
2753
+ if (v->getType () == jl_pvalue_llvmt)
2754
+ undef_var_error_if_null (v, name, ctx);
2740
2755
return v;
2741
2756
}
2742
2757
@@ -2761,8 +2776,7 @@ static Value *emit_var(jl_sym_t *sym, jl_value_t *ty, jl_codectx_t *ctx, bool is
2761
2776
Value *bp = var_binding_pointer (sym, &jbp, false , ctx);
2762
2777
if (bp == NULL )
2763
2778
return NULL ;
2764
- assert (jbp != NULL );
2765
- if (jbp->value != NULL ) {
2779
+ if (jbp && jbp->value != NULL ) {
2766
2780
if (jbp->constp ) {
2767
2781
if (!isboxed && jl_isbits (jl_typeof (jbp->value )))
2768
2782
return emit_unboxed (jbp->value , ctx);
@@ -5111,6 +5125,12 @@ static void init_julia_llvm_env(Module *m)
5111
5125
" jl_declare_constant" , m);
5112
5126
add_named_global (jldeclareconst_func, (void *)&jl_declare_constant);
5113
5127
5128
+ jlgetbinding_func =
5129
+ Function::Create (FunctionType::get (jl_pvalue_llvmt, args_2ptrs, false ),
5130
+ Function::ExternalLinkage,
5131
+ " jl_get_binding" , m);
5132
+ add_named_global (jlgetbinding_func, (void *)&jl_get_binding);
5133
+
5114
5134
builtin_func_map[jl_f_is] = jlcall_func_to_llvm (" jl_f_is" , (void *)&jl_f_is, m);
5115
5135
builtin_func_map[jl_f_typeof] = jlcall_func_to_llvm (" jl_f_typeof" , (void *)&jl_f_typeof, m);
5116
5136
builtin_func_map[jl_f_sizeof] = jlcall_func_to_llvm (" jl_f_sizeof" , (void *)&jl_f_sizeof, m);
0 commit comments