Skip to content

A utility package for working with Julia's CodeInfo internal representation.

License

Notifications You must be signed in to change notification settings

JuliaCompilerPlugins/CodeInfoTools.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CodeInfoTools.jl

Build Status Coverage Documentation
] add CodeInfoTools

Note: A curated collection of tools for the discerning Core.CodeInfo connoisseur.

The architecture of this package is based closely on the Pipe construct in IRTools.jl. Many (if not all) of the same idioms apply.

Motivation

Working with Core.CodeInfo is often not fun. E.g. when examining the untyped lowered form of the Rosenbrock function

CodeInfo(
    @ /Users/mccoybecker/dev/CodeInfoTools.jl/examples/simple.jl:7 within `rosenbrock'
1 ─       a = 1.0
│         b = 100.0
│         result = 0.0
│   %4  = (length)(x)
│   %5  = (-)(%4, 1)
│   %6  = (Colon())(1, %5)
│         @_3 = (iterate)(%6)
│   %8  = (===)(@_3, nothing)
│   %9  = (Core.Intrinsics.not_int)(%8)
└──       goto #4 if not %9
2 ┄ %11 = @_3
│         i = (getfield)(%11, 1)
│   %13 = (getfield)(%11, 2)
│                .
│                .
│                .
│
│   %36 = (===)(@_3, nothing)
│   %37 = (Core.Intrinsics.not_int)(%36)
└──       goto #4 if not %37
3 ─       goto #2
4 ┄       return result
)

Do you ever wonder -- is there another (perhaps, any) way to work with this object? A Builder perhaps? Where I might load my CodeInfo into -- iterate, make local changes, and produce a new copy?

Contribution

CodeInfoTools.jl provides a Builder abstraction which allows you to safely iterate over and manipulate Core.CodeInfo. It also provides more advanced functionality for creating and evaluating Core.CodeInfo -- which is a bit on the experimental side.

How might you use this in practice?

using CodeInfoTools

function f(x, y)
    z = 10
    if z > 10
        n = 10
        return x + y
    else
        return x + y + z
    end
end

src = code_info(f, Int, Int)

function transform(src)
    b = CodeInfoTools.Builder(src)
    for (v, st) in b
        st isa Expr || continue
        st.head == :call || continue
        st.args[1] == Base.:(+) || continue
        b[v] = Expr(:call, Base.:(*), st.args[2:end]...)
    end
    return finish(b)
end

display(src)
display(transform(src))

Here, we've lowered a function directly to a Core.CodeInfo instance and created a Builder instance b. You can now safely iterate over this object, perform local changes, press finish and - (la di da!) - out comes a new Core.CodeInfo with your changes fresh.

# Before:
CodeInfo(
1 ─      Core.NewvarNode(:(n))
│        z = 10
│   %3 = z > 10
└──      goto #3 if not %3
2 ─      n = 10
│   %6 = x + y
└──      return %6
3 ─ %8 = x + y + z
└──      return %8
)

# After:
CodeInfo(
1 ─      Core.NewvarNode(:(n))
│        z = 10
│   %3 = (>)(z, 10)
└──      goto #3 if not %3
2 ─      n = 10
│   %6 = (*)(x, y)
└──      return %6
3 ─ %8 = (*)(x, y, z)
└──      return %8
)

About

A utility package for working with Julia's CodeInfo internal representation.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages