These changes enable a Hello World example. However, all implemented
codegen is not yet feature-complete.
- asm only supports 'svc #0' at the moment
- call only supports leaf functions at the moment
- setReg uses a naive method at the moment
* move SPU code from std to self hosted compiler
* change std lib comments to be descriptive rather than prescriptive
* avoid usingnamespace
* fix case style of error codes
* remove duplication of producer_string
* generalize handling of less than 64 bit arch pointers
* clean up SPU II related test harness code
I forgot to do -Denable-qemu -Denable-wasmtime when testing yesterday,
sorry about that.
In reuseOperand, the code assumed a re-used register would be tracked in
the register table but that is not always the case.
See #6113 for an alternate way of doing this that we didn't end up
following.
Closes#6079.
I also took the opportunity here to extract C.zig and Elf.zig from
link.zig.
According to the Mach-O file format reference, the first
load command should be a `__PAGEZERO` segment command. The
segment is located at virtual memory location 0, has no protection
rights, and causes acccesses to NULL to immediately crash.
Signed-off-by: Jakub Konka <kubkon@jakubkonka.com>
`is_pub` added to `Fn` would cost us an additional 8
bytes of memory per function, which is a real bummer
since it's only 1 bit of information.
If we wanted to really remove this, I suspect we could
make this a function isPub() which looks at the AST of
the corresponding Decl and finds if the FnProto AST node
has the pub token. However I saw an easier approach -
The data of whether something is pub or not is actually
a property of a Decl anyway, not a function, so we can
look at moving the field into Decl. Indeed, doing this,
we see that Decl already has deletion_flag: bool which
is hiding in the padding bytes between the enum (1 byte)
and the following u32 field (generation). So if we put
the is_pub bool there, it actually will take up no
additional space, with 1 byte of padding remaining.
This was an easy reworking of the code since any
func.is_pub could be changed simply to func.owner_decl.is_pub.
I also modified `Var` to make the init value non-optional
and moved the optional bit to a has_init: bool field. This is worse from
the perspective of control flow and safety, however it makes
`@sizeOf(Var)` go from 32 bytes to 24 bytes. The more code we can fit
into memory at once, the more justified we are in using the compiler as
a long-running process that does incremental updates.
During codegen we do not yet know the indexes that will be used for
called functions. Therefore, we store the offset into the in-memory
code where the index is needed with a pointer to the Decl and use this
data to insert the proper indexes while writing the binary in the flush
function.
Before this commit the wasm backend worked similarly to elf. As
functions were generated they were written directly to the output file
and existing code was shifted around in the file as necessary. This
approach had several disadvantages:
- Large amounts of padding in the output were necessary to avoid
expensive copying of data within the file.
- Function/type/global/etc indexes were required to be known at the time
of preforming codegen, which severely limited the flexibility of where
code could be placed in the binary
- Significant complexity to track the state of the output file through
incremental updates
This commit takes things in a different direction. Code is incrementally
compiled into in-memory buffers and the entire binary is rewritten using
these buffers on flush. This has several advantages:
- Significantly smaller resulting binaries
- More performant resulting binaries due to lack of indirection
- Significantly simpler compiler code
- Indexes no longer need to be known before codegen. We can track where
Decls must be referenced by index insert the proper indexes while
writing the code in the flush() function. This is not yet implemented
but is planned for the next commit.
The main disadvantage is of course increased memory usage in order to
store these buffers of generated code.