From 01ade0fbed8441e8525c384f73b2dd9ce7a2a364 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Wed, 9 Sep 2026 06:29:55 -0700 Subject: fix strings under the hex transform this is towards being able to run the hex transform on Forth compilations, rather than just assembly compilations like it does right now. it's been verified that it doesn't cause any regressions. the reasoning for why this fix is necessary is complex, but explained fully in comments I have to admit that I'm not totally clear why the unmodified, untransformed string words don't work for this scenario, but they don't, so... Force-Push: yes Change-Id: I93640c7ca965eba5dc28116bda0165ae1c941458 --- transform.e | 59 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'transform.e') diff --git a/transform.e b/transform.e index 30a9230..a75ea05 100644 --- a/transform.e +++ b/transform.e @@ -3469,27 +3469,60 @@ allocate-transformation-state s" transformation-state" variable : hex-self-codeword-alternate self-codeword ; : hex-string-alternate - ~ See label-string-alternate for detailed notes on how we wrap s". - ~ Essentially, we call the immediate version of it, in the outer context, - ~ which uses scratch space in the outer, "real" log. + ~ The technique we use to wrap s" is analogous to how we do it in the + ~ label transform, but with one critical decision different. + ~ + ~ In the label transform, the output buffer is going to be written + ~ directly into the final executable at some point, and we'd really rather + ~ not scribble temporary values into it, even if we expect to overwrite them + ~ later. Additionally, everything the label transform does runs inside the + ~ label loop, so the code it's transforming isn't expected to do any sort of + ~ miscellaneous setup things, just define a bunch of words. In that + ~ situation, making sure to use temporary space from the outer, "real" log + ~ is helpful. + ~ + ~ In the hex transform, most of that is different. The output buffer will + ~ include all sorts of things that don't become part of the final + ~ executable, though they're used in producing it. So, it's fine to use it + ~ for scratch space. Additionally, using the outer log for string literals + ~ gets us into trouble, since some of these temporary strings need to be + ~ made more durable by calling allocate-string on them. If we do that with + ~ a string pointer backed by the outer log, the inner "here" will wind up + ~ pointing to the end of the outer log, and all sorts of things will start + ~ scribbling atop each other. + ~ + ~ We do still benefit from using the interpreted version of s" rather than + ~ the compiled one; as with the label transform, it's convenient to handle + ~ the litstring dance ourselves. + ~ + ~ If we're in compile mode, we have reinvented a problem which the + ~ regular, non-transformed s" already deals with: The temporary space we're + ~ writing to is in the same place as the code we're compiling. We solve it + ~ the same way: Check beforehand and write out the call to litstring if we + ~ need it, so that we won't have to slide things around later. + interpreter-flags @ 0x01 & { + ~ We look up the inner version of litstring to reference here. This is + ~ similar to what the label transform does, except we don't use a label + ~ for it. + s" litstring" find entry-to-execution-token , + } if + + ~ Now, regardless of what mode we're actually in, call the interpreted + ~ version of s" to read the actual string and its null terminator. interpreter-flags @ ' s" entry-to-execution-token - swap-transform-variables [ ' [ entry-to-execution-token , ] execute - swap-transform-variables swap interpreter-flags ! ~ Now we have a string pointer on the stack at transform time. If we're in - ~ immediate mode, that's sufficient. If we're in compile mode, output a - ~ litstring invocation. Notice also that these are essentially the same - ~ responsibilities as we'd have in the label transform. + ~ immediate mode, that's sufficient. If we're in compile mode, we also + ~ already output a litstring invocation, and the string is in the right + ~ place, but "here" is pointing before it and needs to point after it, then + ~ we also still need to add alignment padding. Plus, we need to be sure to + ~ not leave the string pointer itself on the stack. interpreter-flags @ 0x01 & { - ~ We look up the inner version of litstring to reference here. This is - ~ similar to what the label transform does, except we don't use a label - ~ for it. - s" litstring" find entry-to-execution-token , - here @ swap packstring 8 packalign here ! + dup stringlen 1+ + 8 packalign here ! } if ; make-immediate -- cgit 1.4.1