Skip to content

Commit

Permalink
Fix codegen not handling invoke exprs with Codeinstances iwith jl_fpt…
Browse files Browse the repository at this point in the history
…r_sparam_addr invoke types. (#56817)

fixes #56739
I didn't succeed in making a test for this. The sole trigger seems to be
```julia
using HMMGradients
T = Float32
A = T[0.0 1.0 0.0; 0.0 0.5 0.5; 1.0 0.0 0.0]
t2tr = Dict{Int,Vector{Int}}[Dict(1 => [2]),]
t2IJ= HMMGradients.t2tr2t2IJ(t2tr)

Nt = length(t2tr)+1
Ns = size(A,1)
y = rand(T,Nt,Ns)

c = rand(Float32, Nt)
beta = backward(Nt,A,c,t2IJ,y)
gamma = posterior(Nt,t2IJ,A,y)
```
in @oscardssmith memorynew PR

One other option is to have the builtin handle receiving a CI. That
might make the code cleaner and does handle the case where we receive a
dynamic CI (is that even a thing)
  • Loading branch information
gbaraldi authored Dec 13, 2024
1 parent 03a0247 commit ece1c70
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 49 deletions.
9 changes: 9 additions & 0 deletions Compiler/test/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1027,3 +1027,12 @@ for a in ((@noinline Ref{Int}(2)),
@test ex === a
end
end

# Make sure that code that has unbound sparams works
#https://github.com/JuliaLang/julia/issues/56739

f56739(a) where {T} = a

@test f56739(1) == 1
g56739(x) = @noinline f56739(x)
@test g56739(1) == 1
106 changes: 57 additions & 49 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5484,62 +5484,70 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, ArrayR
result = mark_julia_const(ctx, codeinst->rettype_const);
handled = true;
}
else if (invoke != jl_fptr_sparam_addr) {
else {
bool specsig, needsparams;
std::tie(specsig, needsparams) = uses_specsig(mi, codeinst->rettype, ctx.params->prefer_specsig);
std::string name;
StringRef protoname;
bool need_to_emit = true;
bool cache_valid = ctx.use_cache || ctx.external_linkage;
bool external = false;

// Check if we already queued this up
auto it = ctx.call_targets.find(codeinst);
if (need_to_emit && it != ctx.call_targets.end()) {
assert(it->second.specsig == specsig);
protoname = it->second.decl->getName();
need_to_emit = cache_valid = false;
}
if (needsparams) {
if (trim_may_error(ctx.params->trim))
push_frames(ctx, ctx.linfo, mi);
Value *r = emit_jlcall(ctx, jlinvoke_func, track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)mi)), argv, nargs, julia_call2);
result = mark_julia_type(ctx, r, true, rt);
handled = true;
} else {
std::string name;
StringRef protoname;
bool need_to_emit = true;
bool cache_valid = ctx.use_cache || ctx.external_linkage;
bool external = false;

// Check if we already queued this up
auto it = ctx.call_targets.find(codeinst);
if (need_to_emit && it != ctx.call_targets.end()) {
assert(it->second.specsig == specsig);
protoname = it->second.decl->getName();
need_to_emit = cache_valid = false;
}

// Check if it is already compiled (either JIT or externally)
if (need_to_emit && cache_valid) {
// optimization: emit the correct name immediately, if we know it
// TODO: use `emitted` map here too to try to consolidate names?
uint8_t specsigflags;
jl_callptr_t invoke;
void *fptr;
jl_read_codeinst_invoke(codeinst, &specsigflags, &invoke, &fptr, 0);
if (specsig ? specsigflags & 0b1 : invoke == jl_fptr_args_addr) {
protoname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)fptr, invoke, codeinst);
if (ctx.external_linkage) {
// TODO: Add !specsig support to aotcompile.cpp
// Check that the codeinst is containing native code
if (specsig && (specsigflags & 0b100)) {
external = true;
// Check if it is already compiled (either JIT or externally)
if (need_to_emit && cache_valid) {
// optimization: emit the correct name immediately, if we know it
// TODO: use `emitted` map here too to try to consolidate names?
uint8_t specsigflags;
jl_callptr_t invoke;
void *fptr;
jl_read_codeinst_invoke(codeinst, &specsigflags, &invoke, &fptr, 0);
if (specsig ? specsigflags & 0b1 : invoke == jl_fptr_args_addr) {
protoname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)fptr, invoke, codeinst);
if (ctx.external_linkage) {
// TODO: Add !specsig support to aotcompile.cpp
// Check that the codeinst is containing native code
if (specsig && (specsigflags & 0b100)) {
external = true;
need_to_emit = false;
}
}
else { // ctx.use_cache
need_to_emit = false;
}
}
else { // ctx.use_cache
need_to_emit = false;
}
}
}
if (need_to_emit) {
raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << jl_atomic_fetch_add_relaxed(&globalUniqueGeneratedNames, 1);
protoname = StringRef(name);
}
jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed;
unsigned return_roots = 0;
if (specsig)
result = emit_call_specfun_other(ctx, mi, codeinst->rettype, protoname, external ? codeinst : nullptr, argv, nargs, &cc, &return_roots, rt, age_ok);
else
result = emit_call_specfun_boxed(ctx, codeinst->rettype, protoname, external ? codeinst : nullptr, argv, nargs, rt, age_ok);
handled = true;
if (need_to_emit) {
Function *trampoline_decl = cast<Function>(jl_Module->getNamedValue(protoname));
ctx.call_targets[codeinst] = {cc, return_roots, trampoline_decl, nullptr, specsig};
if (trim_may_error(ctx.params->trim))
push_frames(ctx, ctx.linfo, mi);
if (need_to_emit) {
raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << jl_atomic_fetch_add_relaxed(&globalUniqueGeneratedNames, 1);
protoname = StringRef(name);
}
jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed;
unsigned return_roots = 0;
if (specsig)
result = emit_call_specfun_other(ctx, mi, codeinst->rettype, protoname, external ? codeinst : nullptr, argv, nargs, &cc, &return_roots, rt, age_ok);
else
result = emit_call_specfun_boxed(ctx, codeinst->rettype, protoname, external ? codeinst : nullptr, argv, nargs, rt, age_ok);
handled = true;
if (need_to_emit) {
Function *trampoline_decl = cast<Function>(jl_Module->getNamedValue(protoname));
ctx.call_targets[codeinst] = {cc, return_roots, trampoline_decl, nullptr, specsig};
if (trim_may_error(ctx.params->trim))
push_frames(ctx, ctx.linfo, mi);
}
}
}
}
Expand Down

0 comments on commit ece1c70

Please sign in to comment.