diff --git a/src/compiler/codegen/utils.jl b/src/compiler/codegen/utils.jl index 2676dd4..02405cc 100644 --- a/src/compiler/codegen/utils.jl +++ b/src/compiler/codegen/utils.jl @@ -102,16 +102,6 @@ Optionally stores a compile-time constant value. ghost_value(@nospecialize(jltype)) = CGVal(nothing, TypeId(-1), jltype, Int[], nothing, nothing, nothing) ghost_value(@nospecialize(jltype), constant) = CGVal(nothing, TypeId(-1), jltype, Int[], nothing, Some(constant), nothing) -""" - constant_value(jltype, type_id, constant) -> CGVal - -Deferred constant: has a Tile IR type but no bytecode value yet. -Materialized (ConstantOp emitted) on demand at SSA lookup time. -Parallel to Julia's non-ghost cgval from mark_julia_const. -""" -constant_value(@nospecialize(jltype), type_id::TypeId, constant) = - CGVal(nothing, type_id, jltype, Int[], nothing, Some(constant), nothing) - """ tuple_value(jltype, component_refs, component_constants) -> CGVal diff --git a/src/compiler/codegen/values.jl b/src/compiler/codegen/values.jl index 64c3c27..97d73a2 100644 --- a/src/compiler/codegen/values.jl +++ b/src/compiler/codegen/values.jl @@ -8,26 +8,7 @@ Emit/resolve a value reference to a CGVal using multiple dispatch. function emit_value!(ctx::CGCtx, ssa::SSAValue) tv = ctx[ssa] tv !== nothing || throw(IRError("SSAValue %$(ssa.id) not found in context")) - return maybe_materialize!(ctx, ssa, tv) -end - -""" - maybe_materialize!(ctx, ssa, tv) -> CGVal - -Materialize a deferred constant into bytecode on demand. -Only acts on CGVals with `type_id != TypeId(-1)` and no value yet (deferred constants). -""" -function maybe_materialize!(ctx::CGCtx, ssa::SSAValue, tv::CGVal) - tv.v !== nothing && return tv # already materialized - tv.type_id == TypeId(-1) && return tv # ghost — nothing to materialize - tv.constant === nothing && return tv # no constant to materialize - - val = something(tv.constant) - bytes = constant_to_bytes(val, CC.widenconst(tv.jltype)) - v = encode_ConstantOp!(ctx.cb, tv.type_id, bytes) - materialized = CGVal(v, tv.type_id, tv.jltype, Int[], nothing, tv.constant, nothing) - ctx[ssa] = materialized - return materialized + return tv end emit_value!(ctx::CGCtx, arg::Argument) = ctx[arg] emit_value!(ctx::CGCtx, slot::SlotNumber) = ctx[slot] @@ -81,13 +62,12 @@ end function emit_value!(ctx::CGCtx, ref::GlobalRef) val = getfield(ref.mod, ref.name) T = typeof(val) - # Ghost types have no materializable representation. - # Non-ghost types with a Tile IR type become deferred constants (materialized on demand). - # Everything else (functions, enums, etc.) is compile-time only → ghost. if !is_ghost_type(T) type_id = tile_type_for_julia!(ctx, T; throw_error=false) if type_id !== nothing - return constant_value(T, type_id, val) + bytes = constant_to_bytes(val, T) + v = encode_ConstantOp!(ctx.cb, type_id, bytes) + return CGVal(v, type_id, T, Int[], nothing, Some(val), nothing) end end ghost_value(T, val) diff --git a/test/codegen.jl b/test/codegen.jl index 58a056d..5616d1c 100644 --- a/test/codegen.jl +++ b/test/codegen.jl @@ -2174,6 +2174,45 @@ const _CODEGEN_TEST_FLOAT64 = 3.14159 end end end + + @testset "scalar arg multiplied by external constant" begin + # Regression test for issue #77: scalar × global constant failed + # because encode_MulFOp! received Nothing from the ghost-wrapped GlobalRef. + @test @filecheck begin + @check_label "entry" + code_tiled(Tuple{ct.TileArray{Float32,1,spec1d}, Float32}) do a, scale + pid = ct.bid(1) + tile = ct.load(a, pid, (16,)) + @check "constant