Commit graph

467 commits

Author SHA1 Message Date
Brian Carroll
1b97675f1f Refactor the optimisation for immediately-returned Let statements
The original intention was to avoid creating a local when we define
and immediately return a primitive value. But now our default path
does avoids unnecessary locals anyway!

For StackMemory values we do need an optimised path but it's nicer
to just pass a flag to Storage::allocate.
2021-10-18 13:18:10 +02:00
Brian Carroll
2daefc8b32 Name a constant 2021-10-18 13:11:05 +02:00
Brian Carroll
99468b0aac Clarify a comment 2021-10-17 11:24:25 +02:00
Brian Carroll
6206418b67 Fix clippy warnings 2021-10-14 00:13:47 +02:00
Brian Carroll
e6245c41f5 README updates 2021-10-14 00:04:17 +02:00
Brian Carroll
5c42455ca7 Rename some values & improve comments 2021-10-13 10:52:51 +02:00
Brian Carroll
472943a068 Refactoring: extract Storage out of WasmBackend 2021-10-12 10:22:38 +01:00
Brian Carroll
d2e01bd10a rename SymbolStorage -> StoredValue 2021-10-12 10:20:17 +01:00
Brian Carroll
85ca33ddd6 tweak test script 2021-10-11 08:20:33 +01:00
Brian Carroll
f6685349b3 Batch local declarations to save a few bytes and make some code a little nicer 2021-10-10 22:21:13 +01:00
Brian Carroll
58549bdf07 CodeBuilder doc comments 2021-10-10 20:56:49 +01:00
Brian Carroll
041e26e807 rename CodeBuilder methods 2021-10-10 20:56:39 +01:00
Brian Carroll
c5ee41af25 rename code_builder 2021-10-10 20:56:32 +01:00
Brian Carroll
8164a14dfa rename module_builder 2021-10-10 20:56:20 +01:00
Brian Carroll
c9997f2115 Turn off output file generation & delete duplicate test 2021-10-10 20:55:53 +01:00
Brian Carroll
9dcc6f2bc5 size comparison tweaks 2021-10-10 12:52:53 +01:00
Brian Carroll
14f7f0f3b4 Improved test setup for size comparison 2021-10-10 10:42:02 +01:00
Brian Carroll
47f93bddea Fix & refactor create_storage 2021-10-10 10:36:23 +01:00
Brian Carroll
32b9f4fb07 Generate a .wasm file for every test, for size benchmarking 2021-10-09 18:47:37 +01:00
Brian Carroll
d166f65a31 Fix bug: Forgot to generate a local for the stack frame pointer 2021-10-09 18:16:24 +01:00
Brian Carroll
476c1664ec Add debug logging to CodeBuilder and fix a minor bug 2021-10-09 17:24:37 +01:00
Brian Carroll
3aaafdefe1 Get Join/Jump working with VM storage 2021-10-09 16:46:59 +01:00
Brian Carroll
d81999045a Get Switch statements working with VM storage 2021-10-07 09:14:35 +01:00
Brian Carroll
af823fe5a8 Get rid of unneeded local.set/get in common cases 2021-10-06 20:07:20 +01:00
Brian Carroll
d6bba482ee Treat the Virtual Machine stack as a form of SymbolStorage
Simulate the behaviour of the stack machine, mark where Symbol values
are created, and track where they are in the stack as we emit instructions.

This will allow us to be smarter with setting and getting locals.
However that's not actually implemented yet! At the moment,
we're still generating the same code as before but in a fancier way.

What's happening:

Let's say we have a function call that takes two arguments [A,B]
and that we are lucky and just happen to have a VM stack of [A,B]
That's great, we _should_ not have to do anything, just emit 'Call'

BUT what we are doing is "load A to the top" and then "load B to the top".
This sounds good but it's actually stupid
We are saying we want A at the top of the stack when we don't!!
We want it right where it is, just beneath the top!

So we are emitting code to bring it from 2nd position to the top.
How do we do that? By inserting a local.set instruction to save it,
and a local.get instruction to load it to the top!

What should be happening:

Check the entire VM stack at once for all the symbols we are trying to load.
If they happen to be there (which is likely given the IR structure) do nothing.
If it's not quite perfect... then emit lots of local.set and local.get. Whatever.

What would be the way to solve this properly?

Build the Wasm instructions as a tree, then serialise it depth-first.
The tree encodes all of the information about what needs to be on the
stack at what point in the program. If a tree node has two children,
it consumes two items from the stack. If you do it this way, all
of the instructions get executed just at the right time.
2021-10-05 21:39:19 +01:00
Brian Carroll
d796bbcc68 add a couple of assertions 2021-10-05 21:19:08 +01:00
Brian Carroll
32f79b5ee2 Create CodeBuilder to track Wasm VM stack as we accumulate instructions 2021-10-03 22:50:11 +01:00
Brian Carroll
cc6f83f284 Clearer variant names for StackMemoryLocation 2021-10-03 21:53:18 +01:00
Brian Carroll
2756425eb9 Assert storage matches when copying 2021-10-03 21:52:27 +01:00
Brian Carroll
79a4f2bbf7 Refactor SymbolStorage local_id code, and copy_memory
SymbolStorage had some rather ad-hoc methods for extracting pieces of data.
This change makes that more intentional and organised.

Also cleaned up the API for the related function copy_memory,
as it had lots of positional arguments with the same types.
Created a struct for this just to name them and make the code clearer.
2021-10-02 22:31:48 +01:00
Brian Carroll
6aed70978d Refactor SymbolStorage into two enums instead of one 2021-10-02 16:15:06 +01:00
Brian Carroll
ffa6ff0a62 gen_wasm: Get rid of individual locals for values in stack memory
All values in stack memory can share the stack frame pointer,
with different offsets.

This avoids having to generate initialisation code for individual
pointers we used to have. It should also make things more efficient
when the runtime compiles Wasm to machine code. It can just assign
the stack frame pointer to a single CPU register and leave it there.

The original idea was to make params and local variables work the same.
(A struct param will be passed as a pointer to caller stack memory.)
But now I don't think that's worth it. Some match expressions get more
awkward this way but we might be able to refactor that to be nicer.
2021-10-02 15:12:25 +01:00
Brian Carroll
4aa2452e01 gen_wasm: Change some compiler bugs error handling from Result to panic
Result makes sense where I have something meaningful to say to the user like
"X is not implemented yet". And also for public functions that may interface
with other parts of the project like Backend.

But for private functions internal to gen_wasm, it's just unhelpful to get a stack trace
to where the Result is unwrapped! I want a stack trace to the root cause.
I always end up temporarily rewriting Err("oops") to panic!("oops") and then waiting
for it to recompile.

This feels like a more balanced approach, using each technique where it makes sense.
2021-10-02 13:40:44 +01:00
Brian Carroll
304e9c904f Formatting 2021-09-30 17:28:02 +01:00
Brian Carroll
92085a0fcb README notes on reducing gets and sets 2021-09-30 17:27:56 +01:00
Brian Carroll
7ac7e16f60 Ensure stack frame is always popped when procedure returns from inside a branch 2021-09-30 17:04:16 +01:00
Brian Carroll
79ac2f04b8 Improve stack allocation code 2021-09-30 17:04:16 +01:00
Brian Carroll
f1b14c14e3 Refactor SymbolStorage to emphasise stack/non-stack params
We don't have much (any) code that cares about the difference between
heap pointers and other primitives, but we have a _lot_ of code that cares
if it's stack memory. So let's encode it that way.
2021-09-30 17:04:16 +01:00
Brian Carroll
7ea59ad9d4 PR tidy-ups 2021-09-29 06:15:58 +01:00
Brian Carroll
45c9dc8617 update gen_wasm README 2021-09-28 19:06:47 +01:00
Brian Carroll
02bb9028ef Returning records on the stack from Wasm dev backend! 2021-09-28 08:06:59 +01:00
Brian Carroll
39fda3e675 Add more information to SymbolStorage
SymbolStorage is function-specific, whereas WasmLayout is function-independent.

SymbolStorage used to be a single-variant enum with a LocalId and a WasmLayout,
but now we need more variants, so we can handle stack memory allocation..

- For values in stack memory, the storage needs to include an offset within the
  stack frame, but we don't need that for primitive values.

- For function parameters, the allocated stack memory is in the caller's frame
  rather than the current frame, so we don't want size or offset.

We could have kept a WasmLayout inside of SymbolStorage but that would have made
possible a lot of invalid combinations. It seemed better to copy the fields we need.
2021-09-26 20:52:17 +01:00
Brian Carroll
ecece45a83 Add a helper method local_id_from_symbol 2021-09-26 20:52:17 +01:00
Brian Carroll
ae6cfe1992 Moree implementations for Wasm32TestResult 2021-09-26 20:52:16 +01:00
Brian Carroll
286ca680e0 Tidy up load_literal 2021-09-26 20:52:16 +01:00
Brian Carroll
ab4f28fd69 Comment out a test that isn't working 2021-09-26 20:52:16 +01:00
Brian Carroll
92b1d73bd6 Refactor build_proc into smaller helpers 2021-09-26 20:52:10 +01:00
Brian Carroll
65446ce1e8 Remove unnecessary Option 2021-09-18 14:46:09 +01:00
Brian Carroll
c3b5ac6c82 Allocate stack memory to local variables 2021-09-18 13:39:38 +01:00
Brian Carroll
52a56bfa27 Optimise away a memory copy for returned structs in simple cases 2021-09-17 21:50:00 +01:00