Skip to content

Function dependencies not respected with --disable-main #1727

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

Closed
Tracked by #1600
certik opened this issue Apr 21, 2023 · 3 comments · Fixed by #1732
Closed
Tracked by #1600

Function dependencies not respected with --disable-main #1727

certik opened this issue Apr 21, 2023 · 3 comments · Fixed by #1732
Assignees

Comments

@certik
Copy link
Contributor

certik commented Apr 21, 2023

import_order_01.py:

from import_order_01b import f

@ccallback
def main1():
    a: i32 = f()
    print(a)

import_order_01b.py:

from lpython import i32

def f() -> i32:
    return 42

Compile using:

$ lpython -I. --show-c --disable-main import_order_01.py
...

// Implementations
void main1()
{
    int32_t a;
    a = f();
    printf("%d\n", a);
}

int32_t f()
{
    int32_t _lpython_return_variable;
    _lpython_return_variable = 42;
    return _lpython_return_variable;
}

This then fails to compile due to:

$ clang x.c                
x.c:41:9: error: implicit declaration of function 'f' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    a = f();
        ^
1 error generated.

The issue is that main1 depends on f, but f gets generated below the function. It only happens when --disable-main is used, but we need to use it.

@certik certik mentioned this issue Apr 21, 2023
38 tasks
@certik
Copy link
Contributor Author

certik commented Apr 21, 2023

I am not sure how to best test this in integration tests, due to the --disable-main. The @ccallback is needed, otherwise the function gets treated as unused.

@czgdp1807 czgdp1807 self-assigned this Apr 21, 2023
@czgdp1807
Copy link
Collaborator

The --disable-main doesn't matter. Even without it, f() goes below main1,

...

// Implementations
void main1()
{
    int32_t a;
    a = f();
    printf("%d\n", a);
}

int32_t f()
{
    int32_t _lpython_return_variable;
    _lpython_return_variable = 42;
    return _lpython_return_variable;
}

int main(int argc, char* argv[])
{
    return 0;
}

@czgdp1807
Copy link
Collaborator

Its a problem with pass_wrap_global_stmts_into_program. It only shifts user defined functions into _global_symbols (generated module) only when they are called. In your case main1 is never called so it stays in the global scope. Now C backend first visits all the functions in global scope and since main1 lies in global scope so C code of it is generated first. Then f is generated when the modules are visited. If main1 is shifted to _global_symbols then it depends on import_order_01 and hence f will always be generated before main1 (which is correct).

End moral - So, IMO global scope should only contain intrinsic functions generated by libasr in intrinsic_function_registry.h. All user defined functions should be shifted to _global_symbols modules irrespective of the fact whether they are called by the user or not.

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

Successfully merging a pull request may close this issue.

2 participants