@@ -739,6 +739,13 @@ static const auto jlundefvarerror_func = new JuliaFunction<>{
739
739
{PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted)}, false ); },
740
740
get_attrs_noreturn,
741
741
};
742
+ static const auto jlhasnofield_func = new JuliaFunction<>{
743
+ XSTR (jl_has_no_field_error),
744
+ [](LLVMContext &C) { return FunctionType::get (getVoidTy (C),
745
+ {PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted),
746
+ PointerType::get (JuliaType::get_jlvalue_ty (C), AddressSpace::CalleeRooted)}, false ); },
747
+ get_attrs_noreturn,
748
+ };
742
749
static const auto jlboundserrorv_func = new JuliaFunction<TypeFnContextAndSizeT>{
743
750
XSTR (jl_bounds_error_ints),
744
751
[](LLVMContext &C, Type *T_size) { return FunctionType::get (getVoidTy (C),
@@ -3318,6 +3325,8 @@ static jl_llvm_functions_t
3318
3325
jl_value_t *jlrettype,
3319
3326
jl_codegen_params_t ¶ms);
3320
3327
3328
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name);
3329
+
3321
3330
static bool emit_builtin_call (jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3322
3331
const jl_cgval_t *argv, size_t nargs, jl_value_t *rt,
3323
3332
jl_expr_t *ex, bool is_promotable)
@@ -3819,6 +3828,19 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3819
3828
return true ;
3820
3829
}
3821
3830
}
3831
+ else if (fld.typ == (jl_value_t *)jl_symbol_type) {
3832
+ if (jl_is_datatype (utt) && !jl_is_namedtuple_type (utt)) { // TODO: Look into this for NamedTuple
3833
+ if (jl_struct_try_layout (utt) && (jl_datatype_nfields (utt) == 1 )) {
3834
+ jl_svec_t *fn = jl_field_names (utt);
3835
+ assert (jl_svec_len (fn) == 1 );
3836
+ Value *typ_sym = literal_pointer_val (ctx, jl_svecref (fn, 0 ));
3837
+ Value *cond = ctx.builder .CreateICmpEQ (mark_callee_rooted (ctx, typ_sym), mark_callee_rooted (ctx, boxed (ctx, fld)));
3838
+ emit_hasnofield_error_ifnot (ctx, cond, utt->name ->name , fld);
3839
+ *ret = emit_getfield_knownidx (ctx, obj, 0 , utt, order);
3840
+ return true ;
3841
+ }
3842
+ }
3843
+ }
3822
3844
// TODO: generic getfield func with more efficient calling convention
3823
3845
return false ;
3824
3846
}
@@ -4612,6 +4634,22 @@ static void undef_var_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *name)
4612
4634
ctx.builder .SetInsertPoint (ifok);
4613
4635
}
4614
4636
4637
+ static void emit_hasnofield_error_ifnot (jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name)
4638
+ {
4639
+ ++EmittedUndefVarErrors;
4640
+ assert (name.typ == (jl_value_t *)jl_symbol_type);
4641
+ BasicBlock *err = BasicBlock::Create (ctx.builder .getContext (), " err" , ctx.f );
4642
+ BasicBlock *ifok = BasicBlock::Create (ctx.builder .getContext (), " ok" );
4643
+ ctx.builder .CreateCondBr (ok, ifok, err);
4644
+ ctx.builder .SetInsertPoint (err);
4645
+ ctx.builder .CreateCall (prepare_call (jlhasnofield_func),
4646
+ {mark_callee_rooted (ctx, literal_pointer_val (ctx, (jl_value_t *)type)),
4647
+ mark_callee_rooted (ctx, boxed (ctx, name))});
4648
+ ctx.builder .CreateUnreachable ();
4649
+ ctx.f ->getBasicBlockList ().push_back (ifok);
4650
+ ctx.builder .SetInsertPoint (ifok);
4651
+ }
4652
+
4615
4653
// returns a jl_ppvalue_t location for the global variable m.s
4616
4654
// if the reference currently bound or assign == true,
4617
4655
// pbnd will also be assigned with the binding address
@@ -9011,6 +9049,7 @@ static void init_jit_functions(void)
9011
9049
add_named_global (jlatomicerror_func, &jl_atomic_error);
9012
9050
add_named_global (jlthrow_func, &jl_throw);
9013
9051
add_named_global (jlundefvarerror_func, &jl_undefined_var_error);
9052
+ add_named_global (jlhasnofield_func, &jl_has_no_field_error);
9014
9053
add_named_global (jlboundserrorv_func, &jl_bounds_error_ints);
9015
9054
add_named_global (jlboundserror_func, &jl_bounds_error_int);
9016
9055
add_named_global (jlvboundserror_func, &jl_bounds_error_tuple_int);
0 commit comments