vnmakarov / mir

A lightweight JIT compiler based on MIR (Medium Internal Representation) and C11 JIT compiler and interpreter based on MIR
MIT License
2.29k stars 145 forks source link

read/write modules into one file #281

Closed LambertWSJ closed 2 years ago

LambertWSJ commented 2 years ago

I'm working on simple RISC-V emulator rv32emu (branch: bug), and use MIR as JIT backend.

build and run ./rv32emu hello.elf then save all modules at finish emulator.

btw, each module is generated by c2mir_compile

#define DLIST_MODULE_FOREACH(ctx, module)                         \
    for (MIR_module_t module =                                    \
             DLIST_HEAD(MIR_module_t, *MIR_get_module_list(ctx)); \
         module; module = DLIST_NEXT(MIR_module_t, module))

// jit.c:  rv_jit_free
DLIST_MODULE_FOREACH (jit->ctx, module) {
    MIR_write_module(jit->ctx, jit->cache, module);
}

when run ./rv32emu hello.elf second time and load cache via MIR_read, I got error.

unfinished binary MIR

I also try MIR_write(ctx, jit->cache) but still got same error.

Did I miss something before or after write modules?

jserv commented 2 years ago

when run ./rv32emu hello.elf second time and load cache via MIR_read, I got error.

unfinished binary MIR

I also try MIR_write(ctx, jit->cache) but still got same error.

You shall provide a minimal reproducible example (MRE) instead of a complete project such as rv32emu. For the purpose, you might consider to modify cjit as MRE, so that people can help.

LambertWSJ commented 2 years ago

Sorry, I rewrite a simple program for reproduce problem. Gist

This program save 2 modules into one file. and get same problem when load MIR binary file.

int main(int argc, char **argv)
{
    generate_cache();
    puts("load MIR binary cache");
    MIR_context_t ctx = MIR_init();
    FILE *mirb = fopen(cache, "rb");
    MIR_read(ctx, mirb);
    fclose(mirb);

    MIR_module_t module;
    MIR_item_t func_item;

    DLIST_MODULE_FOREACH(ctx, module) {
        DLIST_ITEM_FOREACH(module, func_item) {
            arith_func arith = func_item->addr;
            const char *label = func_item->u.func->name;
            printf("%s(60, 10) = %d\n", label, arith(60, 10));
        }
    }

    return 0;
}

execute program.

> ./main
add(60, 10) = 70
sub(60, 10) = 50
save 2 modules
load MIR binary cache
unfinished binary MIR
LambertWSJ commented 2 years ago

I should use MIR_write instead of MIR_output_module for each module. then use MIR_read cache and re-generate machine code again.

The Gist has updated.

vnmakarov commented 2 years ago

Thank you for reporting your problem. Your feedback is important and I should improve the documentation at least.

You can not write more two or more modules separately into the same file. MIR_write or MIR_write_module write compressed MIR representation. When you use MIR_write module twice you will have several separately compressed MIR IRs. MIR_read accepts only one compressed MIR IR. I'll think what to do in order other people will not repeat this mistake again.