Skip to content

Commit

Permalink
Clean up for maybe_decay_tracked
Browse files Browse the repository at this point in the history
* Document returned LLVM type for a few functions
* Require and assert `Vboxed` to be of type `T_prjlvalue`
* Remove unused branch/specialization of `maybe_decay_tracked`
* Add function to cast known-untracked value.
  • Loading branch information
yuyichao committed Aug 4, 2020
1 parent e3a4916 commit 964fc9f
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 53 deletions.
6 changes: 4 additions & 2 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ static Value *llvm_type_rewrite(

// --- argument passing and scratch space utilities ---

// Returns T_prjlvalue
static Value *runtime_apply_type_env(jl_codectx_t &ctx, jl_value_t *ty)
{
// box if concrete type was not statically known
Expand Down Expand Up @@ -441,7 +442,7 @@ static Value *julia_to_native(
// We're passing Any
if (toboxed) {
assert(!byRef); // don't expect any ABI to pass pointers by pointer
return maybe_decay_untracked(ctx, boxed(ctx, jvinfo));
return boxed(ctx, jvinfo);
}
assert(jl_is_datatype(jlto) && julia_struct_has_layout((jl_datatype_t*)jlto, jlto_env));

Expand Down Expand Up @@ -1028,6 +1029,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar

// --- code generator for ccall itself ---

// Returns T_prjlvalue
static Value *box_ccall_result(jl_codectx_t &ctx, Value *result, Value *runtime_dt, jl_value_t *rt)
{
// XXX: need to handle parameterized zero-byte types (singleton)
Expand Down Expand Up @@ -1278,7 +1280,7 @@ static bool verify_ref_type(jl_codectx_t &ctx, jl_value_t* ref, jl_unionall_t *u
else {
Value *notany = ctx.builder.CreateICmpNE(
boxed(ctx, runtime_sp),
maybe_decay_untracked(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_any_type)));
track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_any_type)));
error_unless(ctx, notany, make_errmsg(fname, n, rt_err_msg_notany));
always_error = false;
}
Expand Down
72 changes: 36 additions & 36 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,21 @@ static Instruction *tbaa_decorate(MDNode *md, Instruction *load_or_store)
return load_or_store;
}

static Value *track_pjlvalue(jl_codectx_t &ctx, Value *V)
{
assert(V->getType() == T_pjlvalue);
return ctx.builder.CreateAddrSpaceCast(V, T_prjlvalue);
}

// Take an arbitrary untracked value and make it gc-tracked
static Value *maybe_decay_untracked(jl_codectx_t &ctx, Value *V)
{
if (V->getType() == T_pjlvalue)
return ctx.builder.CreateAddrSpaceCast(V, T_prjlvalue);
else if (V->getType() == T_ppjlvalue)
return ctx.builder.CreateBitCast(V, T_pprjlvalue);
assert(V->getType() == T_prjlvalue);
return V;
}

// Take an untracked value and make it tracked (specialized on Constant)
JL_UNUSED static Constant *maybe_decay_untracked(jl_codectx_t&, Constant *C)
{
if (C->getType() == T_pjlvalue)
return ConstantExpr::getAddrSpaceCast(C, T_prjlvalue);
else if (C->getType() == T_ppjlvalue)
return ConstantExpr::getBitCast(C, T_pprjlvalue);
return C;
}

// Take any value and mark that it may be derived from a rooted value
static Value *decay_derived(jl_codectx_t &ctx, Value *V)
{
Expand Down Expand Up @@ -384,6 +379,7 @@ static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool
return maybe_mark_load_dereferenceable(LI, can_be_null, size, alignment);
}

// Returns T_pjlvalue
static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p)
{
if (p == NULL)
Expand All @@ -396,6 +392,7 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p)
false, jl_typeof(p)));
}

// Returns T_pjlvalue
static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p)
{
// emit a pointer to any jl_value_t which will be valid across reloading code
Expand Down Expand Up @@ -817,6 +814,7 @@ static Value *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, ssize_t n, MDNode

static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &v);

// Returns T_prjlvalue
static Value *emit_typeof(jl_codectx_t &ctx, Value *tt)
{
assert(tt != NULL && !isa<AllocaInst>(tt) && "expected a conditionally boxed value");
Expand Down Expand Up @@ -856,15 +854,15 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
ptr = literal_pointer_val_slot(ctx, (jl_value_t*)jt);
}
else {
ptr = maybe_decay_untracked(ctx, literal_pointer_val(ctx, (jl_value_t*)jt));
ptr = track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jt));
}
datatype_or_p = ctx.builder.CreateSelect(cmp, ptr, datatype_or_p);
},
p.typ,
counter);
auto emit_unboxty = [&] () -> Value* {
if (imaging_mode)
return maybe_decay_untracked(
return track_pjlvalue(
ctx, tbaa_decorate(tbaa_const, ctx.builder.CreateAlignedLoad(T_pjlvalue, datatype_or_p, sizeof(void*))));
return datatype_or_p;
};
Expand Down Expand Up @@ -897,6 +895,7 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p)
return mark_julia_const(p.typ);
}

// Returns T_prjlvalue
static Value *emit_typeof_boxed(jl_codectx_t &ctx, const jl_cgval_t &p)
{
return boxed(ctx, emit_typeof(ctx, p));
Expand Down Expand Up @@ -1113,8 +1112,8 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,

// intersection with Type needs to be handled specially
if (jl_has_intersect_type_not_kind(type) || jl_has_intersect_type_not_kind(intersected_type)) {
Value *vx = maybe_decay_untracked(ctx, boxed(ctx, x));
Value *vtyp = maybe_decay_untracked(ctx, literal_pointer_val(ctx, type));
Value *vx = boxed(ctx, x);
Value *vtyp = track_pjlvalue(ctx, literal_pointer_val(ctx, type));
if (msg && *msg == "typeassert") {
ctx.builder.CreateCall(prepare_call(jltypeassert_func), { vx, vtyp });
return std::make_pair(ConstantInt::get(T_int1, 1), true);
Expand All @@ -1141,7 +1140,7 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
ctx.builder.CreateCondBr(isboxed, isaBB, postBB);
ctx.builder.SetInsertPoint(isaBB);
Value *istype_boxed = ctx.builder.CreateICmpEQ(emit_typeof(ctx, x.Vboxed),
maybe_decay_untracked(ctx, literal_pointer_val(ctx, intersected_type)));
track_pjlvalue(ctx, literal_pointer_val(ctx, intersected_type)));
ctx.builder.CreateBr(postBB);
isaBB = ctx.builder.GetInsertBlock(); // could have changed
ctx.builder.SetInsertPoint(postBB);
Expand All @@ -1155,7 +1154,7 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
}
}
return std::make_pair(ctx.builder.CreateICmpEQ(emit_typeof_boxed(ctx, x),
maybe_decay_untracked(ctx, literal_pointer_val(ctx, intersected_type))), false);
track_pjlvalue(ctx, literal_pointer_val(ctx, intersected_type))), false);
}
jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(intersected_type);
if (jl_is_datatype(dt) && !dt->abstract && jl_subtype(dt->name->wrapper, type)) {
Expand All @@ -1170,8 +1169,8 @@ static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
// everything else can be handled via subtype tests
return std::make_pair(ctx.builder.CreateICmpNE(
ctx.builder.CreateCall(prepare_call(jlsubtype_func),
{ maybe_decay_untracked(ctx, emit_typeof_boxed(ctx, x)),
maybe_decay_untracked(ctx, literal_pointer_val(ctx, type)) }),
{ emit_typeof_boxed(ctx, x),
track_pjlvalue(ctx, literal_pointer_val(ctx, type)) }),
ConstantInt::get(T_int32, 0)), false);
}

Expand Down Expand Up @@ -1371,7 +1370,7 @@ static void typed_store(jl_codectx_t &ctx,
if (!isboxed)
r = emit_unbox(ctx, elty, rhs, jltype);
else
r = maybe_decay_untracked(ctx, boxed(ctx, rhs));
r = boxed(ctx, rhs);
Type *ptrty = PointerType::get(elty, ptr->getType()->getPointerAddressSpace());
if (ptr->getType() != ptrty)
ptr = ctx.builder.CreateBitCast(ptr, ptrty);
Expand All @@ -1398,6 +1397,7 @@ static void typed_store(jl_codectx_t &ctx,

// --- convert boolean value to julia ---

// Returns T_pjlvalue
static Value *julia_bool(jl_codectx_t &ctx, Value *cond)
{
return ctx.builder.CreateSelect(cond, literal_pointer_val(ctx, jl_true),
Expand Down Expand Up @@ -2187,20 +2187,21 @@ static Value *as_value(jl_codectx_t &ctx, Type *to, const jl_cgval_t &v)
}

// some types have special boxing functions with small-value caches
// Returns T_prjlvalue
static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t)
{
jl_value_t *jt = vinfo.typ;
if (jt == (jl_value_t*)jl_bool_type)
return julia_bool(ctx, ctx.builder.CreateTrunc(as_value(ctx, t, vinfo), T_int1));
return track_pjlvalue(ctx, julia_bool(ctx, ctx.builder.CreateTrunc(as_value(ctx, t, vinfo), T_int1)));
if (t == T_int1)
return julia_bool(ctx, as_value(ctx, t, vinfo));
return track_pjlvalue(ctx, julia_bool(ctx, as_value(ctx, t, vinfo)));

if (ctx.linfo && jl_is_method(ctx.linfo->def.method) && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel
if (Constant *c = dyn_cast<Constant>(vinfo.V)) {
jl_value_t *s = static_constant_instance(c, jt);
if (s) {
jl_add_method_root(ctx, s);
return literal_pointer_val(ctx, s);
return track_pjlvalue(ctx, literal_pointer_val(ctx, s));
}
}
}
Expand All @@ -2209,7 +2210,7 @@ static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t
assert(jl_is_datatype(jb));
Value *box = NULL;
if (jb == jl_int8_type)
box = call_with_attrs(ctx, box_int8_func, as_value(ctx, t, vinfo));
box = track_pjlvalue(ctx, call_with_attrs(ctx, box_int8_func, as_value(ctx, t, vinfo)));
else if (jb == jl_int16_type)
box = call_with_attrs(ctx, box_int16_func, as_value(ctx, t, vinfo));
else if (jb == jl_int32_type)
Expand All @@ -2222,7 +2223,7 @@ static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t
// box = ctx.builder.CreateCall(box_float64_func, as_value(ctx, t, vinfo);
// for Float64, fall through to generic case below, to inline alloc & init of Float64 box. cheap, I know.
else if (jb == jl_uint8_type)
box = call_with_attrs(ctx, box_uint8_func, as_value(ctx, t, vinfo));
box = track_pjlvalue(ctx, call_with_attrs(ctx, box_uint8_func, as_value(ctx, t, vinfo)));
else if (jb == jl_uint16_type)
box = call_with_attrs(ctx, box_uint16_func, as_value(ctx, t, vinfo));
else if (jb == jl_uint32_type)
Expand All @@ -2241,7 +2242,7 @@ static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t
else if (!jb->abstract && jl_datatype_nbits(jb) == 0) {
// singleton
assert(jb->instance != NULL);
return literal_pointer_val(ctx, jb->instance);
return track_pjlvalue(ctx, literal_pointer_val(ctx, jb->instance));
}
return box;
}
Expand All @@ -2253,7 +2254,7 @@ static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype, jl_value_t
for_each_uniontype_small(
[&](unsigned idx, jl_datatype_t *jt) {
if (jl_subtype((jl_value_t*)jt, supertype)) {
Value *cmp = ctx.builder.CreateICmpEQ(maybe_decay_untracked(ctx, literal_pointer_val(ctx, (jl_value_t*)jt)), datatype);
Value *cmp = ctx.builder.CreateICmpEQ(track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jt)), datatype);
tindex = ctx.builder.CreateSelect(cmp, ConstantInt::get(T_int8, idx), tindex);
}
},
Expand Down Expand Up @@ -2325,6 +2326,7 @@ static AllocaInst *try_emit_union_alloca(jl_codectx_t &ctx, jl_uniontype_t *ut,
* case, the calling code must separately deal with the case where
* `vinfo` is already an unknown boxed union (union tag 0x80).
*/
// Returns T_prjlvalue
static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallBitVector &skip)
{
// given vinfo::Union{T, S}, emit IR of the form:
Expand Down Expand Up @@ -2359,7 +2361,7 @@ static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallB
switchInst->addCase(ConstantInt::get(T_int8, idx), tempBB);
Value *box;
if (type_is_ghost(t)) {
box = literal_pointer_val(ctx, jt->instance);
box = track_pjlvalue(ctx, literal_pointer_val(ctx, jt->instance));
}
else {
jl_cgval_t vinfo_r = jl_cgval_t(vinfo, (jl_value_t*)jt, NULL);
Expand All @@ -2369,7 +2371,6 @@ static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallB
init_bits_cgval(ctx, box, vinfo_r, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut);
}
}
box = maybe_decay_untracked(ctx, box);
tempBB = ctx.builder.GetInsertBlock(); // could have changed
box_merge->addIncoming(box, tempBB);
ctx.builder.CreateBr(postBB);
Expand Down Expand Up @@ -2400,19 +2401,21 @@ static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallB
// this is used to wrap values for generic contexts, where a
// dynamically-typed value is required (e.g. argument to unknown function).
// if it's already a pointer it's left alone.
// Returns T_prjlvalue
static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo)
{
jl_value_t *jt = vinfo.typ;
if (jt == jl_bottom_type || jt == NULL)
// We have an undef value on a (hopefully) dead branch
return UndefValue::get(T_prjlvalue);
if (vinfo.constant)
return maybe_decay_untracked(ctx, literal_pointer_val(ctx, vinfo.constant));
return track_pjlvalue(ctx, literal_pointer_val(ctx, vinfo.constant));
// This can happen in early bootstrap for `gc_preserve_begin` return value.
if (jt == (jl_value_t*)jl_nothing_type)
return maybe_decay_untracked(ctx, literal_pointer_val(ctx, jl_nothing));
return track_pjlvalue(ctx, literal_pointer_val(ctx, jl_nothing));
if (vinfo.isboxed) {
assert(vinfo.V == vinfo.Vboxed);
assert(vinfo.V->getType() == T_prjlvalue);
return vinfo.V;
}

Expand All @@ -2431,9 +2434,6 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo)
box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val(ctx, (jl_value_t*)jt));
init_bits_cgval(ctx, box, vinfo, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut);
}
else {
box = maybe_decay_untracked(ctx, box);
}
}
return box;
}
Expand Down Expand Up @@ -2607,7 +2607,7 @@ static void emit_setfield(jl_codectx_t &ctx,
}
jl_value_t *jfty = jl_svecref(sty->types, idx0);
if (jl_field_isptr(sty, idx0)) {
Value *r = maybe_decay_untracked(ctx, boxed(ctx, rhs)); // don't need a temporary gcroot since it'll be rooted by strct
Value *r = boxed(ctx, rhs); // don't need a temporary gcroot since it'll be rooted by strct
cast<StoreInst>(tbaa_decorate(strct.tbaa, ctx.builder.CreateAlignedStore(r,
emit_bitcast(ctx, addr, T_pprjlvalue),
sizeof(jl_value_t*))))
Expand Down
Loading

0 comments on commit 964fc9f

Please sign in to comment.