Inspect intermediate representations of code

The Erlang compiler supports a few flags

+to_pp
+to_exp
+to_core
+to_kernel
+to_asm

which output intermediate representations of your code in its way down to final BEAM bytecode. Works as expected with erlc, but seems to have no effect if set using ERL_COMPILER_OPTIONS:

~/tmp % cat foo.ex
defmodule Foo do
  @x 25
  def f(x) when x < @x - 1, do: :ok
end

~/tmp % ERL_COMPILER_OPTIONS=to_asm elixirc foo.ex

== Compilation error in file foo.ex ==
** (CompileError) foo.ex: could not compile module Foo. We expected the compiler to return a .beam binary but got something else. This usually happens because ERL_COMPILER_OPTIONS or @compile was set to change the compilation outcome in a way that is incompatible with Elixir
    (elixir 1.10.3) src/elixir_erl_compiler.erl:12: anonymous fn/3 in :elixir_erl_compiler.spawn/2
    (elixir 1.10.3) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

Do you know how to do that?

Motivation is to see with my own eyes that the guard in f/1 is constant folded (if it is, I guess so), but the solution that explains how to get those intermediate representations is interesting in itself.

1 Like

Check this project out: https://github.com/michalmuskala/decompile

5 Likes

Confirm, it is eventually constant folded.