From ed397411d4e32d618cf48119d218713d016c3f5d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 11 Dec 2018 11:00:03 -0500 Subject: [PATCH] codegen: disable Bool optimization for maybe-undef fields We don't have a way to mark that the slot may contain invalid data, so just eagerly load it so we can sanitize the value immediately in case it is garbage. fix #30344 --- base/boot.jl | 4 ++-- src/cgutils.cpp | 8 ++++---- src/runtime_intrinsics.c | 2 -- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 0f0d0b6d0851e..63c7f4b5b4821 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -624,7 +624,7 @@ toInt8(x::UInt16) = checked_trunc_sint(Int8, check_top_bit(x)) toInt8(x::UInt32) = checked_trunc_sint(Int8, check_top_bit(x)) toInt8(x::UInt64) = checked_trunc_sint(Int8, check_top_bit(x)) toInt8(x::UInt128) = checked_trunc_sint(Int8, check_top_bit(x)) -toInt8(x::Bool) = and_int(zext_int(Int8, x), Int8(1)) +toInt8(x::Bool) = and_int(bitcast(Int8, x), Int8(1)) toInt16(x::Int8) = sext_int(Int16, x) toInt16(x::Int16) = x toInt16(x::Int32) = checked_trunc_sint(Int16, x) @@ -679,7 +679,7 @@ toUInt8(x::UInt16) = checked_trunc_uint(UInt8, x) toUInt8(x::UInt32) = checked_trunc_uint(UInt8, x) toUInt8(x::UInt64) = checked_trunc_uint(UInt8, x) toUInt8(x::UInt128) = checked_trunc_uint(UInt8, x) -toUInt8(x::Bool) = and_int(zext_int(UInt8, x), UInt8(1)) +toUInt8(x::Bool) = and_int(bitcast(UInt8, x), UInt8(1)) toUInt16(x::Int8) = sext_int(UInt16, check_top_bit(x)) toUInt16(x::Int16) = bitcast(UInt16, check_top_bit(x)) toUInt16(x::Int32) = checked_trunc_uint(UInt16, x) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 946065c7e6273..33373416d7ebc 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1425,10 +1425,10 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, Value *idx, jl_datatype_t *stt, jl_value_t *inbounds) { size_t nfields = jl_datatype_nfields(stt); + bool maybe_null = (unsigned)stt->ninitialized != nfields; if (strct.ispointer()) { // boxed or stack if (is_datatype_all_pointers(stt)) { idx = emit_bounds_check(ctx, strct, (jl_value_t*)stt, idx, ConstantInt::get(T_size, nfields), inbounds); - bool maybe_null = (unsigned)stt->ninitialized != nfields; size_t minimum_field_size = std::numeric_limits::max(); size_t minimum_align = JL_HEAP_ALIGNMENT; for (size_t i = 0; i < nfields; ++i) { @@ -1458,7 +1458,7 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, jl_value_t *jt = jl_field_type(stt, 0); idx = emit_bounds_check(ctx, strct, (jl_value_t*)stt, idx, ConstantInt::get(T_size, nfields), inbounds); Value *ptr = maybe_decay_tracked(data_pointer(ctx, strct)); - if (!stt->mutabl) { + if (!stt->mutabl && !(maybe_null && jt == (jl_value_t*)jl_bool_type)) { // just compute the pointer and let user load it when necessary Type *fty = julia_type_to_llvm(jt); Value *addr = ctx.builder.CreateInBoundsGEP(fty, emit_bitcast(ctx, ptr, PointerType::get(fty, 0)), idx); @@ -1512,6 +1512,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st if (type_is_ghost(elty)) return ghostValue(jfty); Value *fldv = NULL; + bool maybe_null = idx >= (unsigned)jt->ninitialized; if (strct.ispointer()) { Value *staddr = maybe_decay_tracked(data_pointer(ctx, strct)); bool isboxed; @@ -1553,7 +1554,6 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st } unsigned align = jl_field_align(jt, idx); if (jl_field_isptr(jt, idx)) { - bool maybe_null = idx >= (unsigned)jt->ninitialized; Instruction *Load = maybe_mark_load_dereferenceable( ctx.builder.CreateLoad(T_prjlvalue, emit_bitcast(ctx, addr, T_pprjlvalue)), maybe_null, jl_field_type(jt, idx)); @@ -1586,7 +1586,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st } return mark_julia_slot(addr, jfty, tindex, strct.tbaa); } - else if (!jt->mutabl) { + else if (!jt->mutabl && !(maybe_null && jfty == (jl_value_t*)jl_bool_type)) { // just compute the pointer and let user load it when necessary return mark_julia_slot(addr, jfty, NULL, strct.tbaa); } diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 22f8866f143a5..d43ae3d5ff9af 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -400,8 +400,6 @@ static inline jl_value_t *jl_intrinsic_cvt(jl_value_t *ty, jl_value_t *a, const void *pr = alloca(osize); unsigned isize_bits = isize * host_char_bit; unsigned osize_bits = osize * host_char_bit; - if (aty == (jl_value_t*)jl_bool_type) - isize_bits = 1; op(isize_bits, pa, osize_bits, pr); return jl_new_bits(ty, pr); }