Bugfix ten: type error in `convert`. I was calling `rewind-stream` on a
`buffered-file`.
examples/ex1 is now just one nibble off the canonical.
I *have* found one missing feature in the self-hosted translator,
though: dquotes doesn't support newlines in strings, even though the C++
version does. dquotes parses them right, but the value initialized in
the data segment is wrong.
Bugfix eight: incorrect segment count in ELF header.
The generated examples/ex1 is still not right. But it has the second
segment now. Or almost all of it. Final byte is missing for some reason.
The result isn't an identical binary to before, and it segfaults when
run. But it's bugfix seven.
A couple of places where we make .subx files a little more strict:
a) All .subx files must define a data segment. Even if they have no
data.
b) All .subx files must define an `Entry` label for the binary to start
at. Earlier we used to default to the start of the code label. That's
not too hard to add; we'd just need to:
i) rename `get` to `get-or-abort`
ii) clone a third variant of `get-or-insert` called `get` that returns
null if the key is not found.
iii) use `get` rather than `get-or-abort` when looking up the `Entry`
label.
map of how far we've gotten by now (functions with '*' independently tested):
✓ compute-offsets*
✓ compute-addresses*
✓ emit-output
✓ emit-headers
✓ emit-elf-header
✓ emit-hex-array*
✓ first emit-elf-program-header-entry
✓ emit-hex-array*
? second emit-elf-program-header-entry
emit-hex-array*
emit-segments*
I carefully logged the segment a label is declared in but forgot to
actually save it in the table. This has been a theoretic concern for
some time, but I've never seen it actually happen until now. SubX is
just too low level.
Now I get past the first two phases but code generation fails to find
the 'Entry' label.
Snapshot at a random moment, showing a new debugging trick: hacking on
the C++ level to dump memory contents on specific labels.
For some reason label 'x' doesn't have a segment assigned by the time we
get to compute-addresses.
'curr-segment-name' is now a string, and it's stored in a register
rather than a global.
Paradoxically, this leaks *less* than before. Before, every call to
`get-or-insert-slice` leaked memory. Now we leak one string for every
new segment. Which is trivial.
I changed the test a little to make it obvious.
Basically there's no way we can compute the segment offset correctly
without knowing the segment name in the previous assertion.
The pseudocode was a mess here :/ I was saving the segment-offset but
tracing the file-offset.
Segments need file offsets (to tweak their starting address).
Labels need segment offsets (to add to segment starting address).