Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux target produces incorrect assembly for function calls with 5> parameters. #37

Open
Goubermouche opened this issue Feb 2, 2024 · 0 comments

Comments

@Goubermouche
Copy link

Hi, I believe I've discovered a bug in the Linux target, specifically, there seems to be an issue with how function calls with more than 5 parameters behave. I've attached a minimal reproducible example below:

#include "tb/include/tb.h"
#define CUIK_USE_TB

int main() {
    TB_FeatureSet features = { 0 };
    TB_Module* module = tb_module_create(TB_ARCH_X86_64, TB_SYSTEM_LINUX,  &features, false);
    TB_ModuleSectionHandle text = tb_module_get_text(module);

    TB_PrototypeParam printf_ret = { TB_TYPE_I32 };
    TB_PrototypeParam printf_param = { TB_TYPE_PTR };

    // printf
    TB_External* printf_external = tb_extern_create(module, 7, "printf", TB_EXTERNAL_SO_LOCAL);
    TB_FunctionPrototype* printf_proto = tb_prototype_create(module, TB_STDCALL, 1, &printf_param, 1, &printf_ret, true);

    // main
    TB_PrototypeParam main_ret = { TB_TYPE_I32 };

    // main
    TB_Function* main_f = tb_function_create(module, 5, "main", TB_LINKAGE_PUBLIC);
    TB_FunctionPrototype* main_prototype = tb_prototype_create(module, TB_STDCALL, 0, NULL, 1, &main_ret, false);
    tb_function_set_prototype(main_f, text, main_prototype, NULL);

    TB_Node* params[8] = {
        tb_inst_string(main_f, 22, "%d %d %d %d %d %d %d\n"),
        tb_inst_sint(main_f, TB_TYPE_I32, 1),
        tb_inst_sint(main_f, TB_TYPE_I32, 2),
        tb_inst_sint(main_f, TB_TYPE_I32, 3),
        tb_inst_sint(main_f, TB_TYPE_I32, 4),
        tb_inst_sint(main_f, TB_TYPE_I32, 5),
        tb_inst_sint(main_f, TB_TYPE_I32, 6),
        tb_inst_sint(main_f, TB_TYPE_I32, 7)
    };

    tb_inst_call(main_f, printf_proto, tb_inst_get_symbol_address(main_f, (TB_Symbol*)printf_external), 8, params);

    TB_Node* ret_value = tb_inst_sint(main_f, TB_TYPE_I32, 0);
    tb_inst_ret(main_f, 1, &ret_value);
        
    TB_Passes* p_main = tb_pass_enter(main_f, tb_function_get_arena(main_f));
    tb_pass_exit(p_main);

    TB_ExportBuffer buffer = tb_module_object_export(module, TB_DEBUGFMT_NONE);

    // copy into file
    if (!tb_export_buffer_to_file(buffer, "./a.o")) {
        printf("err\n");
    }

    return 0;
}

When we link the generated object file for TB_SYSTEM_LINUX using clang like so:

$ clang a.o -o test

The program partially prints gibberish:

1 2 3 4 5 1776 1872767257

If we were to compile the same IR with TB_SYSTEM_WINDOWS, and with the same command, we'd get the following, correct result:

1 2 3 4 5 6 7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant