simon816 / Command-Block-Assembly

Compile high-level code into Minecraft commands
https://www.simon816.com/minecraft/assembler
MIT License
272 stars 29 forks source link

Linker bug involving subroutines included from external files #22

Closed sarahmence closed 4 years ago

sarahmence commented 4 years ago

I am working on the same project as the previous issue (#21), with this file structure:

In init.asm, I have this code:

#include_h ../util/regs.asm

init:
    [routine body omitted for brevity]

In main.asm, I have this code:

#include_h setup/init.asm

main:
    CALL init

Since you fixed #21, I am able to assemble this code into object files successfully, however when linking, I get this error:

Traceback (most recent call last):
  File "[redacted]/Command-Block-Assembly/mcc.py", line 4, in <module>
    start()
  File "[redacted]/Command-Block-Assembly/mcc/cli.py", line 353, in start
    run_with_args(args)
  File "[redacted]/Command-Block-Assembly/mcc/cli.py", line 360, in run_with_args
    main(args)
  File "[redacted]/Command-Block-Assembly/mcc/cli.py", line 290, in main
    top = link(tops, args)
  File "[redacted]/Command-Block-Assembly/mcc/cli.py", line 193, in link
    final_top = TopLevel.linker(*tops)
  File "[redacted]/Command-Block-Assembly/cmd_ir/core.py", line 470, in linker
    out.store(name, var)
  File "[redacted]/Command-Block-Assembly/cmd_ir/core.py", line 263, in store
    '%s: %s' % (name, self.scope[name])
AssertionError: sub_init: DynLink(sub_init)

Can you fix this? Thanks in advance!

simon816 commented 4 years ago

It looks like you're compiling multiple asm files at once, something like:

./mcc.py src/main.asm src/setup/init.asm

I can see what you're going for here - including the symbol table for things like init.asm to make it accessible in main.asm, then link the code together. The ability to compile and link multiple asm files together is relatively new, and was added much more recently than when include_h was added. As such, the semantics of include_h may need to be revised since it was made for dynamic linking only and not static linking.

My suggestion is to change include_h setup/init.asm to just include setup/init.asm in main.asm. Then just compile main.asm (./mcc.py src/main.asm). Essentially include all code into main.asm and just compile that one file.

If you want to be able to statically link multiple asm files and don't mind tweaking the compiler, I think this change should be sufficient:

In cmd_ir/core.py, function include_from change DynLinkFunction into ExternFunction:

https://github.com/simon816/Command-Block-Assembly/blob/a45874af3673bd55c60eb285e85ab28bcb5f8467/cmd_ir/core.py#L355-L356

                self.scope[name] = ExternFunction(var.global_name.name,
                                                   var.params, var.returns)

I won't make this change right away because I may add proper static/dynamic linking to the assembler to bring it in line with Command IR/CBL

sarahmence commented 4 years ago

That fixed it. Thanks!