about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--amd64.e4
-rw-r--r--transform.e75
2 files changed, 63 insertions, 16 deletions
diff --git a/amd64.e b/amd64.e
index a6503f0..ea0d5b2 100644
--- a/amd64.e
+++ b/amd64.e
@@ -745,7 +745,9 @@ s" :cc-greater" keyword
 : mov-disp8-reg64-reg64
   ~ : 1 # # # mov-disp8-reg64-reg64
   4 roll rex-w 0x89 pack8 4 unroll
-  3roll reg64 3unroll addressing-disp8-reg64 ;
+  3roll reg64 3unroll addressing-disp8-reg64
+  ~ : 3 roll-subitems
+  ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg64-indirect-reg64
diff --git a/transform.e b/transform.e
index 52fa24f..e23453b 100644
--- a/transform.e
+++ b/transform.e
@@ -3027,14 +3027,22 @@ allocate-transformation-state s" transformation-state" variable
 ~ you are at risk of falling into the abyss[1].
 ~
 ~   Postprocessing re-organizes entries, without changing their meaning, but
-~ in a way that will make them easier to format. There are two things it does,
-~ and they happen simultaneously: The whole array is bubble-sorted by the
-~ address it's attached to; and every suffix comment entry with a length
-~ that's not zero is is split apart into a fresh-line entry at the start of
-~ the span it attaches to, and a zero-length suffix comment entry at the end
-~ of the span. The bubble sort is a stable sort; any entries that are already
-~ attached to the same address will stay in whatever order they're in to begin
-~ with.
+~ in a way that will make them easier to format. There are two things it
+~ does, and they happen simultaneously: The whole array is bubble-sorted;
+~ and some suffix comment entries are split apart.
+~
+~   The bubble sort resolves ordering first by the address each entry is
+~ attached to, low-to-high. As a tiebreaker when two entries have the same
+~ address, a comment entry is sorted after a stack-manipulation entry. The
+~ tiebreaker rule means that stack-manipulation commands can come after the
+~ last byte that's within the comment's span; otherwise they would always have
+~ to be before it. If neither criterion applies, the entries will stay in
+~ whatever order they were in to begin with; that is, it's a stable sort.
+~
+~   The comment splitting applies only to suffix comments, and only when their
+~ length is not zero. They become a fresh-line entry at the start of the span
+~ the comment originally attached to, and a zero-length suffix comment entry
+~ at the end of the span.
 ~
 ~   Please notice that adjust-length commands happen when magic comments are
 ~ executed, which was long, long ago by now. By the time the postprocessing
@@ -3147,6 +3155,13 @@ allocate-transformation-state s" transformation-state" variable
 ~ -entry-type-roll-subitems, which rolls them, or unrolls them with a negative
 ~ parameter.
 ~
+~   In using these commands that manipulate the subitem stack, it's important
+~ to remember that, when formatting happens, the left-to-right output of
+~ subitems in the final output comment is top-to-bottom on the subitem stack,
+~ because they're popped in order. This is the opposite of the usual visual
+~ representation of stacks, and can easily be confusing.
+~ TODO this seems worth a semantic change once the output vetting is done
+~
 ~   One more thing: The order in which provide-* commands execute will most
 ~ likely match the order in which the corresponding bytes are output. This may
 ~ not always match the order in which the comment template wants to
@@ -3698,10 +3713,10 @@ allocate-transformation-state s" transformation-state" variable
       over hex-output-metadata-entry-data-length @ 0 != && {
         ~   Split it into two entries so as not to rely on data length for
         ~ formatting.
-        ~ (did anything, entry pointer)
-
         dup dup-metadata-entry
-        ~ (..., entry pointer)
+        ~ (did anything, entry pointer)
+        ~   Now we have the original entry at the original location, and a copy
+        ~ of it at the next location.
 
         ~   We have a feature which lets a suffix comment be created with a
         ~ negative length, which means it covers bytes before the current output
@@ -3712,9 +3727,8 @@ allocate-transformation-state s" transformation-state" variable
         2dup min 3unroll max
         ~ (..., entry pointer, low end of data, high end of data)
 
-        ~   Now we have the original entry at the original location, and a copy
-        ~ of it at the next location. We modify the original one in-place to
-        ~ turn it into a fresh-line entry at the low end of the data...
+        ~   Now we modify the original in-place to turn it into a fresh-line
+        ~ entry at the low end of the data...
         2 pick hex-output-metadata-entry-type
         hex-output-metadata-entry-type-fresh-line swap !
         ~ (..., entry pointer, low end of data, high end of data)
@@ -3738,7 +3752,8 @@ allocate-transformation-state s" transformation-state" variable
         ~ a different type, and it won't fire on the modified suffix-comment
         ~ entry because its data length is zero.
         ~
-        ~   It's possible the bubble-sort rule will fire on either of them.
+        ~   It's possible that one or the other of the bubble-sort rules will
+        ~ fire on either of them.
 
         ~ (did anything, entry pointer)
         swap drop 1 swap
@@ -3767,6 +3782,36 @@ allocate-transformation-state s" transformation-state" variable
       } if
       ~ (did anything, entry pointer)
 
+      ~   Do this entry and the next entry both exist, and they have the same
+      ~ data start, and this one is a comment entry, and the next one is a
+      ~ stack-manipulation entry with zero length?
+      dup is-comment-entry over hex-output-metadata-next-entry @ &&
+        { ~ (did anything, entry pointer)
+          dup hex-output-metadata-next-entry
+          over hex-output-metadata-entry-data-start @
+          over hex-output-metadata-entry-data-start @ =
+          swap dup hex-output-metadata-entry-data-length @ 0 = 3roll && swap
+          is-subitem-stack-manipulation-entry && }
+        { 0 } if-else
+      {
+        ~   Swap the order of the two entries. Since this whole thing is in a
+        ~ loop, this functions as a bubble sort.
+        dup swap-metadata-entries
+        swap drop 1 swap
+
+        ~   This rule can't fire in the same iteration as the previous swap,
+        ~ because that one doesn't fire when the starts are equal. It also
+        ~ won't fire again on the same pair of entries, again because now
+        ~ they're in the correct order. If it fires again in the next
+        ~ iteration that'll only be in the usual way it does for a bubble
+        ~ sort.
+        ~
+        ~   As with the other swap rule, this rule also does nothing to alter
+        ~ whether the suffix-comment rule will fire on either entry it
+        ~ touches, so it won't loop through that one.
+      } if
+      ~ (did anything, entry pointer)
+
       hex-output-metadata-next-entry
     } while drop
   } while ;