summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--transform.e59
1 files changed, 46 insertions, 13 deletions
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