I would like to highjack all calls to a particular function.
I've tried cassette, but this runs into the llvmcall issue. I've tried cassetteoverlay, but that breaks julia entirely (argextype called on Expr with head :call which is not valid for IR in argument-position.) I've also looked at irtools/dynamo, but run into an issue where irtools breaks on certain broadcast expressions.
I realise that I'm trying to do something that is highly discouraged and hacky, but do there nevertheless exist other solutions that I haven't explored yet? It seems that Cassette work has somewhat stalled with the promise that some work in base (abstractinterpreter) will allow for a more robust cassette like implementation. Does that exist somewhere?
A low-tech option is to create an own type and just implement methods for it until you are able to hit the function you want to overwrite.
That'd be a lot of work that I would ideally avoid. One workaround for me may be to hack on top of JuliaInterpreter.
They have a global dictionary that links methods with their frames, so all I'd need to do is manually insert the calls that I want to detour there...
Nevermind, juliainterpreter is too slow
you'll probably want to watch this talk that just ended https://pretalx.com/juliacon2024/talk/D88XFU/
the recording will be up on youtube at some point
the live stream is https://www.youtube.com/watch?v=OQnHyHgs0Qo, you should be able to scroll back ~30 minutes (at time of writing)
I doubt a bit though whether this is less work :sweat_smile:
watching it now :)
I may also take some inspiration from infiltrator.jl
I think both Cassette.jl and Infiltrator.jl are going to be completely subsumed by that talk
oh, right before that talk was another ~half hour talk explaining the basic compiler/optimization pipeline which might be useful if you're not already familiar with it
If that talk gets merged, it'd be perfect !
What doesn't work for you with cassetteoverlay?
something deep within julia's abstracteval errors. The code partially runs after spitting out an enormous stacktrace. I don't have a real "minimal" working example, but I did open an issue https://github.com/JuliaDebug/CassetteOverlay.jl/issues/57
https://gist.github.com/maartenvd/e9e3afbefe2577a0c504bdb217508ea8 for an example part of the stacktrace
Interestingly on master I get an entirely different error, but an error nevertheless
I think I found the problem with IRtools dynamo...
I forgot that I can simply re-use some of the amazing work in Revise/CodeTracking!
using Revise, CodeTracking
function hello(a::String)
println(a)
end
function detourhack(::typeof(hello),a::String)
println("detoured "*a)
end
detourtable = Any[]
for detour in methods(Main.detourhack)
orig = which(Tuple{detour.sig.parameters[2:end]...})
orig_expr = definition(orig)
push!(detourtable,(detour,orig,orig_expr))
end
function enable_highjack()
tsymb = GlobalRef(Main,:detourhack)
for (detour,orig,orig_expr) in detourtable
orsigparams = orig.sig.parameters
pars = [gensym() for v in orsigparams]
fdeff = Expr(:call,[Expr(:(::),a,b) for (a,b) in zip(pars,orsigparams)]...)
body = Expr(:call,tsymb,pars...)
orig.module.eval(Expr(:function,fdeff,body))
end
end
function disable_highjack()
for (detour,orig,orig_expr) in detourtable
orig.module.eval(orig_expr)
end
end
julia> hello("world")
world
julia>enable_highjack()
julia>hello("world")
detoured world
I don't know how to make this work with kwargs though
Last updated: Nov 22 2024 at 04:41 UTC