Stream: cranelift

Topic: visualizing cranelift output


view this post on Zulip chc4 (Aug 05 2021 at 01:58):

Hi, I'm writing a project that uses Cranelift as a JIT backend for dynamic recompilation. Is there any way to get a GraphViz printout of the basic blocks + instructions from Cranelift for ease of debugging? Or any other debugging outputs I could use, other than just disassembling the JIT output?

view this post on Zulip Afonso Bordado (Aug 05 2021 at 08:47):

Hey, You should be able to get an output in the form of Cranelift IR by calling display on a FunctionBuilder or Function and get a string with the Cranelift IR Module. (Here's a more complete example)

This gets you an output a bit higher level than disassembly. I don't know if we have a GraphViz formatter.

view this post on Zulip Afonso Bordado (Aug 05 2021 at 08:55):

Oops, it looks like you don't get a String directly, but a formattable object, which you can pass into println! like: println!("{}", func.display(None));

view this post on Zulip Till Schneidereit (Aug 05 2021 at 08:56):

Or into format! :smile:

view this post on Zulip chc4 (Aug 05 2021 at 13:40):

Great, thank you!

view this post on Zulip bjorn3 (Aug 05 2021 at 15:22):

Is there any way to get a GraphViz printout of the basic blocks + instructions from Cranelift for ease of debugging?

Yes, clif-util has the print_cfg subcommand. You can also use cranelift_codegen::cfg_printer::CFGPrinter.

view this post on Zulip Ivan Chinenov (Nov 11 2021 at 19:11):

Afonso Bordado said:

Hey, You should be able to get an output in the form of Cranelift IR by calling display on a FunctionBuilder or Function and get a string with the Cranelift IR Module. (Here's a more complete example)

This gets you an output a bit higher level than disassembly. I don't know if we have a GraphViz formatter.

Is there a way to do this currently? display method seems to have been removed since you've commented

view this post on Zulip Chris Fallin (Nov 11 2021 at 19:22):

The Function has a display method in the latest version (though indeed it seems the analogous one on FunctionBuilder went away as part of some recent cleanups (?)): docs here

view this post on Zulip Ivan Chinenov (Nov 11 2021 at 19:27):

Chris Fallin said:

The Function has a display method in the latest version (though indeed it seems the analogous one on FunctionBuilder went away as part of some recent cleanups (?)): docs here

Thanks. How do I acquire a Function? I'm following along with the JIT demo and all I have access to is a FunctionBuilder.

view this post on Zulip Ivan Chinenov (Nov 11 2021 at 19:28):

Oh, I see, it's func on FunctionBuilder

view this post on Zulip Chase Wilson (Mar 15 2022 at 17:02):

Somewhat related to this, I've been trying to figure out how to associate user-generated ExternalNames to strings or to otherwise make cranelift output use actual names for functions and stuff instead of numbers, is that possible?

view this post on Zulip Chris Fallin (Mar 15 2022 at 17:40):

Currently this is handled outside of the core Cranelift IR types -- the idea is that the embedding, if it has a concept of symbol names or whatnot, would carry a mapping

view this post on Zulip Chris Fallin (Mar 15 2022 at 17:41):

there's some overlap between this design choice and the "function-local compilation" choice: keeping a symtab within CLIF would mean duplicating symbols in each function that refers to them, unless we add some module-level context

view this post on Zulip Chris Fallin (Mar 15 2022 at 17:42):

but, plugging in some custom mapping for symbols to text names during pretty-printing is not a bad idea -- I'm open to something like that at least!

view this post on Zulip bjorn3 (Mar 15 2022 at 19:15):

See also https://github.com/bjorn3/rustc_codegen_cranelift/blob/master/src/pretty_clif.rs

Cranelift based backend for rustc. Contribute to bjorn3/rustc_codegen_cranelift development by creating an account on GitHub.

view this post on Zulip Joseph Kanichai (Jun 13 2024 at 12:48):

Hi, I'm trying to print out some cranelift IR with display, but I keep getting the below panic, and it happens only if the function i'm printing has a call in it. Anyone have an idea?

Panic:

thread '<unnamed>' panicked at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/ir/extname.rs:191:58:
index out of bounds: the len is 0 but the index is 0
stack backtrace:
   0: rust_begin_unwind
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
   1: core::panicking::panic_fmt
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
   2: core::panicking::panic_bounds_check
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:180:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/slice/index.rs:261:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/slice/index.rs:18:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/alloc/src/vec/mod.rs:2728:9
   6: <cranelift_entity::primary::PrimaryMap<K,V> as core::ops::index::Index<K>>::index
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-entity-0.91.1/src/primary.rs:202:20
   7: <cranelift_codegen::ir::extname::DisplayableExternalName as core::fmt::Display>::fmt
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/ir/extname.rs:191:58
   8: core::fmt::rt::Argument::fmt
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/fmt/rt.rs:138:9
   9: core::fmt::write
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/fmt/mod.rs:1114:21
  10: <cranelift_codegen::ir::extfunc::DisplayableExtFuncData as core::fmt::Display>::fmt
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/ir/extfunc.rs:363:9
  11: core::fmt::rt::Argument::fmt
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/fmt/rt.rs:138:9
  12: core::fmt::write
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/fmt/mod.rs:1114:21
  13: cranelift_codegen::write::FuncWriter::super_entity_definition
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:131:9
  14: cranelift_codegen::write::FuncWriter::write_entity_definition
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:119:9
  15: cranelift_codegen::write::FuncWriter::super_preamble
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:84:17
  16: cranelift_codegen::write::FuncWriter::write_preamble
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:38:9
  17: cranelift_codegen::write::decorate_function
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:191:19
  18: cranelift_codegen::write::write_function
             at /home/joefe/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/write.rs:164:5

Wasm throwing the error:

(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (type (;1;) (func (param i32) (result i32)))
  (func (;0;) (type 0) (param i32 i32) (result i32)
    (local i32)
    local.get 0
    local.get 1
    i32.add
    local.set 2
    local.get 2
    return)
  (func (;1;) (type 1) (param i32) (result i32)
    (local i32 i32 i32 i32)
    i32.const 2
    local.set 1
    local.get 0
    local.get 1
    call 0
    local.set 2
    i32.const 5
    local.set 3
    local.get 2
    local.get 3
    i32.add
    local.set 4
    local.get 4
    return)
  (table (;0;) 1 1 funcref)
  (memory (;0;) 16)
  (global (;0;) (mut i32) (i32.const 1048576))
  (global (;1;) i32 (i32.const 1048576))
  (global (;2;) i32 (i32.const 1048576))
  (export "memory" (memory 0))
  (export "add" (func 0))
  (export "add_two" (func 1))
  (export "__data_end" (global 1))
  (export "__heap_base" (global 2)))

view this post on Zulip fitzgen (he/him) (Jun 13 2024 at 15:18):

Hi @Joseph Kanichai -- can you clarify exactly the method you are using to construct the CLIF?

For example, I don't get a panic from this:

$ wasmtime compile --emit-clif clif input.wat

and fwiw, that yields the following clif files:

clif/wasm_func_0.clif:

function u0:0(i64 vmctx, i64, i32, i32) -> i32 tail {
    gv0 = vmctx
    gv1 = load.i64 notrap aligned readonly gv0+8
    gv2 = load.i64 notrap aligned gv1
    stack_limit = gv2

                                block0(v0: i64, v1: i64, v2: i32, v3: i32):
@007e                               v5 = iconst.i32 0
@0084                               v6 = iadd v2, v3
@0089                               return v6
}

clif/wasm_func_1.clif:

function u0:1(i64 vmctx, i64, i32) -> i32 tail {
    gv0 = vmctx
    gv1 = load.i64 notrap aligned readonly gv0+8
    gv2 = load.i64 notrap aligned gv1
    sig0 = (i64 vmctx, i64, i32, i32) -> i32 tail
    fn0 = colocated u0:0 sig0
    stack_limit = gv2

                                block0(v0: i64, v1: i64, v2: i32):
@008d                               v4 = iconst.i32 0
@008f                               v5 = iconst.i32 2
@0097                               v6 = call fn0(v0, v0, v2, v5)  ; v5 = 2
@009b                               v7 = iconst.i32 5
@00a3                               v8 = iadd v6, v7  ; v7 = 5
@00a8                               return v8
}

view this post on Zulip fitzgen (he/him) (Jun 13 2024 at 15:19):

can you clarify exactly the method you are using to construct the CLIF?

to add a little more color here, I ask because it looks like you are indexing into some kind of PrimaryMap with a key that doesn't exist in that map, which indicates a bug somewhere in that general viscinity

view this post on Zulip Joseph Kanichai (Jun 13 2024 at 15:23):

fitzgen (he/him) said:

can you clarify exactly the method you are using to construct the CLIF?

to add a little more color here, I ask because it looks like you are indexing into some kind of PrimaryMap with a key that doesn't exist in that map, which indicates a bug somewhere in that general viscinity

I'm calling .display on cranelift_codegen::ir::function

view this post on Zulip fitzgen (he/him) (Jun 13 2024 at 15:30):

how did you get the ir::Function?

view this post on Zulip fitzgen (he/him) (Jun 13 2024 at 15:30):

and did you modify it yourself at all?

view this post on Zulip Joseph Kanichai (Jun 13 2024 at 15:34):

fitzgen (he/him) said:

and did you modify it yourself at all?

I have not performed any modifications, and It's inside a compile function inside wasmer, here.

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten - wasmerio/wasmer

view this post on Zulip fitzgen (he/him) (Jun 13 2024 at 15:37):

wasmer is not associated with the bytecode alliance, uses a very outdated version of cranelift, and we don't provide support for it here. if you would like to try out wasmtime, we can help you out with that, but otherwise you're on your own with wasmer issues. good luck!

view this post on Zulip Joseph Kanichai (Jun 13 2024 at 15:54):

fitzgen (he/him) Yep looks like wasmer's old cranelift version has issues. Just tried it in wasmtime's repo and it's running fine.


Last updated: Nov 22 2024 at 17:03 UTC