diff options
| -rw-r--r-- | README.txt | 4 | ||||
| -rw-r--r-- | evoke.e | 10 | ||||
| -rw-r--r-- | execution.e | 13 | ||||
| -rw-r--r-- | inscribe-evoke.e | 28 | ||||
| -rw-r--r-- | inscribe-hex.e | 26 | ||||
| -rw-r--r-- | transform.e | 74 |
6 files changed, 94 insertions, 61 deletions
diff --git a/README.txt b/README.txt index d07a5a4..34cdb5a 100644 --- a/README.txt +++ b/README.txt @@ -337,13 +337,13 @@ can be metacircular while you're metacircular.) To produce the hex-dump version of it, do: - $ (cat labels.e elf.e transform.e; echo 's" xyzzy" allocate-string dup 262144 read-to-buffer'; cat core.e linux.e output.e amd64.e execution-support.e log-load.e dynamic.e input.e interpret.e flow-control.e linux-dynamic.e labels.e elf.e hex.e; echo 'xyzzy s" hex-source" variable 1024 1024 * allocate s" hex-binary" variable 1024 1024 * allocate s" hex-metadata" variable hex-metadata hex-binary dup hex-source 5 roll hex-transform bye ' ) | ./evoke > hex.hex + $ cat labels.e elf.e transform.e inscribe-hex.e | ./evoke > hex.hex The program "hex" is written in Evocation-assembly, but the hex transform also works on Forth programs, including Evocation itself. To produce the hex-dump version of Evocation, do: - $ (cat labels.e elf.e transform.e; echo 's" xyzzy" allocate-string dup 1048576 read-to-buffer'; cat core.e linux.e output.e amd64.e execution-support.e log-load.e dynamic.e input.e interpret.e flow-control.e linux-dynamic.e labels.e elf.e transform.e execution.e evoke.e; echo 'xyzzy s" evoke-source" variable 1024 1024 4 * * allocate s" evoke-binary" variable 1024 1024 4 * * allocate s" evoke-metadata" variable evoke-metadata evoke-binary dup evoke-source 5 roll hex-transform bye ' ) | ./evoke > evoke.hex + $ cat labels.e elf.e transform.e inscribe-evoke.e | ./evoke > evoke.hex It should run to completion, producing output in evoke.hex. Passing evoke.hex through ./hex will give a binary that's byte-for-byte identical to diff --git a/evoke.e b/evoke.e index 9a12075..9a1e515 100644 --- a/evoke.e +++ b/evoke.e @@ -16,8 +16,7 @@ s" amd64.e" pack-file-contents s" execution-support.e" pack-file-contents s" log-load.e" pack-file-contents - s" pyrzqxgl" packstring - 0 pack8 8 packalign here ! + 8 packalign here ! s" source-to-precompile" variable here @ dup @@ -32,8 +31,7 @@ s" interpret.e" pack-file-contents s" flow-control.e" pack-file-contents s" linux-dynamic.e" pack-file-contents - s" pyrzqxgl" packstring - 0 pack8 8 packalign here ! + 8 packalign here ! s" source-to-copy-to-log" variable ; read-inputs @@ -60,8 +58,8 @@ read-inputs elf-program-header output-cold-start - source-to-copy-to-log s" pyrzqxgl" output-warm-start - source-to-precompile s" pyrzqxgl" label-transform + source-to-copy-to-log output-warm-start + source-to-precompile label-transform ~ If we wanted words in the log to be able to call statically-linked ~ words, we could set this to something nonzero. We don't, so we leave it diff --git a/execution.e b/execution.e index 8962578..81ec03b 100644 --- a/execution.e +++ b/execution.e @@ -418,7 +418,7 @@ ~ pointers. It was directly jumped to from cold-start. There's nowhere to ~ return to, so it needs to never return. ~ -~ (output buffer start, output point, input string pointer, delimiter pointer +~ (output buffer start, output point, input string pointer ~ -- output buffer start, output point) : output-warm-start ~ : blank-line @@ -452,11 +452,10 @@ ~ While it's not actually a requirement that codeword pointers be ~ word-aligned, it's highly likely that it helps performance. (Whether it ~ does is up to Intel's microcode.) - 4 unroll 3unroll + 3unroll 8 packalign current-offset L!' warm-start - ~ (delimiter pointer, input string pointer, - ~ output buffer start, output point) + ~ (input string pointer, output buffer start, output point) ~ Before handing off to us, cold-start pushed a single value onto the ~ stack, a pointer to the beginning of the log. Now, we load our entire @@ -553,10 +552,8 @@ ~ we can go ahead and dispatch to the log-load transform, and do the rest of ~ the code through that. - ~ (delimiter pointer, input string pointer, - ~ output buffer start, output point) - 3roll 4 roll - log-load-transform + ~ (input string pointer, output buffer start, output point) + 3roll log-load-transform ~ (output buffer start, output point) ~ : blank-line diff --git a/inscribe-evoke.e b/inscribe-evoke.e new file mode 100644 index 0000000..e757c0e --- /dev/null +++ b/inscribe-evoke.e @@ -0,0 +1,28 @@ +: prepare + here @ dup + s" core.e" pack-file-contents + s" linux.e" pack-file-contents + s" output.e" pack-file-contents + s" amd64.e" pack-file-contents + s" execution-support.e" pack-file-contents + s" log-load.e" pack-file-contents + s" dynamic.e" pack-file-contents + s" input.e" pack-file-contents + s" interpret.e" pack-file-contents + s" flow-control.e" pack-file-contents + s" linux-dynamic.e" pack-file-contents + s" labels.e" pack-file-contents + s" elf.e" pack-file-contents + s" transform.e" pack-file-contents + s" execution.e" pack-file-contents + s" evoke.e" pack-file-contents + 8 packalign here ! + s" evoke-source" variable + + 1024 1024 4 * * allocate s" evoke-binary" variable + 1024 1024 4 * * allocate s" evoke-metadata" variable ; + +prepare +evoke-metadata evoke-binary dup evoke-source hex-transform +bye + diff --git a/inscribe-hex.e b/inscribe-hex.e new file mode 100644 index 0000000..7d9aafa --- /dev/null +++ b/inscribe-hex.e @@ -0,0 +1,26 @@ +: prepare + here @ dup + s" core.e" pack-file-contents + s" linux.e" pack-file-contents + s" output.e" pack-file-contents + s" amd64.e" pack-file-contents + s" execution-support.e" pack-file-contents + s" log-load.e" pack-file-contents + s" dynamic.e" pack-file-contents + s" input.e" pack-file-contents + s" interpret.e" pack-file-contents + s" flow-control.e" pack-file-contents + s" linux-dynamic.e" pack-file-contents + s" labels.e" pack-file-contents + s" elf.e" pack-file-contents + s" hex.e" pack-file-contents + 8 packalign here ! + s" hex-source" variable + + 1024 1024 * allocate s" hex-binary" variable + 1024 1024 * allocate s" hex-metadata" variable ; + +prepare +hex-metadata hex-binary dup hex-source hex-transform +bye + diff --git a/transform.e b/transform.e index e184c7e..136b790 100644 --- a/transform.e +++ b/transform.e @@ -331,16 +331,14 @@ : transformation-state-output-buffer-start 2 8 * + ; : transformation-state-user-stack-depth 3 8 * + ; : transformation-state-label-scratch 4 8 * + ; -: transformation-state-delimiter 5 8 * + ; -: transformation-state-output-metadata 6 8 * + ; +: transformation-state-output-metadata 5 8 * + ; : allocate-transformation-state - 7 8 * allocate + 6 8 * allocate dup transformation-state-saved-here 0 swap ! dup transformation-state-saved-latest 0 swap ! dup transformation-state-output-buffer-start 0 swap ! dup transformation-state-user-stack-depth 0 swap ! dup transformation-state-label-scratch 0 swap ! - dup transformation-state-delimiter 0 swap ! dup transformation-state-output-metadata 0 swap ! ; allocate-transformation-state s" transformation-state" variable @@ -1349,18 +1347,14 @@ allocate-transformation-state s" transformation-state" variable : label-transform-one word - ~ If no word was returned, exit. - dup 0 = { drop 0 exit } if + ~ If no word was returned, end the transformation. + dup 0 = { drop 1 exit } if ~ The string is on the top of the stack, so to get a pointer to it we get ~ the stack address. ~ (string) value@ - ~ If it's the magic word, end the transformation. - dup transformation-state transformation-state-delimiter @ stringcmp 0 = - { drop dropstring 1 exit } if - ~ Check whether it's one of the words we have alternates for, and look up ~ the alternate if so. dup 0 swap @@ -1552,7 +1546,7 @@ allocate-transformation-state s" transformation-state" variable ~ input string. It is directly analogous to "quit", in interpet.e, but is far ~ more complex. ~ -~ (output buffer start, output point, input string pointer, delimiter pointer +~ (output buffer start, output point, input string pointer ~ -- output buffer start, output point) : label-transform ~ : blank-line @@ -1583,7 +1577,7 @@ allocate-transformation-state s" transformation-state" variable ~ : blank-line main-input-buffer dup push-input-buffer - 3roll attach-string-to-input-buffer + swap attach-string-to-input-buffer ~ Save the old values of "here" and "latest", and set the initial values ~ of the internal ones. These values need to persist across iterations, @@ -1592,25 +1586,25 @@ allocate-transformation-state s" transformation-state" variable ~ loop, and set it back when the loop ends. here @ transformation-state transformation-state-saved-here ! latest @ transformation-state transformation-state-saved-latest ! - 2 pick transformation-state transformation-state-output-buffer-start ! - swap here ! + swap transformation-state transformation-state-output-buffer-start ! + here ! 0 latest ! - transformation-state transformation-state-delimiter ! ~ Now the stack has nothing of ours on it, so client code can do its thing. ~ It's important that the stack has nothing of ours on it that persists ~ across iterations, so that client code can add and remove stuff there as ~ it sees fit. { label-transform-one - ~ (done) + ~ (..., done) ~ When the loop is done, get the real values of "here" and "latest" ~ back. The internal "here" is also the output point, and will become our ~ return value. The internal "latest" is discarded. - { here @ + { transformation-state transformation-state-output-buffer-start @ + here @ transformation-state transformation-state-saved-here @ here ! transformation-state transformation-state-saved-latest @ latest ! - ~ (output point) + ~ (output buffer start, output point) ~ Though we don't actually use transformation-state outside of this ~ invocation, for tidiness we zero it out. @@ -2561,18 +2555,14 @@ allocate-transformation-state s" transformation-state" variable : log-load-transform-one word - ~ If no word was returned, exit. - dup 0 = { drop 0 exit } if + ~ If no word was returned, end the transformation. + dup 0 = { drop 1 exit } if ~ The string is on the top of the stack, so to get a pointer to it we get ~ the stack address. ~ (string) value@ - ~ If it's the magic word, end the transformation. - dup transformation-state transformation-state-delimiter @ stringcmp 0 = - { drop dropstring 1 exit } if - ~ Check whether it's one of the words we have alternates for, and look up ~ the alternate if so. 0 swap @@ -2759,7 +2749,7 @@ allocate-transformation-state s" transformation-state" variable ~ an input string. It is directly analogous to "quit", in interpret.e, but is ~ far more complex. ~ -~ (output buffer start, output point, input string pointer, delimiter pointer +~ (output buffer start, output point, input string pointer ~ -- output buffer start, output point) : log-load-transform ~ : blank-line @@ -2788,7 +2778,7 @@ allocate-transformation-state s" transformation-state" variable ~ : blank-line main-input-buffer dup push-input-buffer - 3roll attach-string-to-input-buffer + swap attach-string-to-input-buffer ~ Save the old values of "here" and "latest", and set the initial values ~ of the internal ones. These values need to persist across iterations, @@ -2800,26 +2790,26 @@ allocate-transformation-state s" transformation-state" variable ~ user-stack-depth fields of transformation-state. here @ transformation-state transformation-state-saved-here ! latest @ transformation-state transformation-state-saved-latest ! - 2 pick transformation-state transformation-state-output-buffer-start ! + swap transformation-state transformation-state-output-buffer-start ! 0 transformation-state transformation-state-user-stack-depth ! - swap here ! + here ! 0 latest ! - transformation-state transformation-state-delimiter ! ~ Now the stack has nothing of ours on it, so client code can do its thing. ~ It's important that the stack has nothing of ours on it that persists ~ across iterations, so that client code can add and remove stuff there as ~ it sees fit. { log-load-transform-one - ~ (done) + ~ (..., done) ~ When the loop is done, get the real values of "here" and "latest" ~ back. The internal "here" is also the output point, and will become our ~ return value. The internal "latest" is discarded. - { here @ + { transformation-state transformation-state-output-buffer-start @ + here @ transformation-state transformation-state-saved-here @ here ! transformation-state transformation-state-saved-latest @ latest ! - ~ (output point) + ~ (output buffer start, output point) ~ Though we don't actually use transformation-state outside of this ~ invocation, for tidiness we zero it out. @@ -6327,18 +6317,14 @@ allocate-transformation-state s" transformation-state" variable hex-skip-space word - ~ If no word was returned, exit. - dup 0 = { drop 0 exit } if + ~ If no word was returned, end the transformation. + dup 0 = { drop 1 exit } if ~ The string is on the top of the stack, so to get a pointer to it we get ~ the stack address. ~ (string) value@ - ~ If it's the magic word, end the transformation. - dup transformation-state transformation-state-delimiter @ stringcmp 0 = - { drop dropstring 1 exit } if - ~ If it's anything but tilde, set the input state flag accordingly. dup s" ~" stringcmp 0 != { 1 has-non-space-this-input-line! } if @@ -6511,13 +6497,11 @@ allocate-transformation-state s" transformation-state" variable ~ more complex. ~ ~ (output metadata buffer start, output buffer start, output point, -~ input string pointer, delimiter pointer -~ -- output buffer start, output point) +~ input string pointer -- output buffer start, output point) : hex-transform main-input-buffer dup push-input-buffer - 3roll attach-string-to-input-buffer - ~ (output metadata buffer start, output buffer start, output point, - ~ delimiter pointer) + swap attach-string-to-input-buffer + ~ (output metadata buffer start, output buffer start, output point) ~ Save the old values of "here" and "latest", and set the initial values ~ of the internal ones. These values need to persist across iterations, @@ -6531,7 +6515,6 @@ allocate-transformation-state s" transformation-state" variable ~ most convenient order given how we received our parameters. here @ transformation-state transformation-state-saved-here ! latest @ transformation-state transformation-state-saved-latest ! - transformation-state transformation-state-delimiter ! here ! 0 latest ! transformation-state transformation-state-output-buffer-start ! @@ -6573,7 +6556,8 @@ allocate-transformation-state s" transformation-state" variable ~ When the loop is done, get the real values of "here" and "latest" ~ back. The internal "here" is also the output point, and will become our ~ return value. The internal "latest" is discarded. - { here @ + { transformation-state transformation-state-output-buffer-start @ + here @ transformation-state transformation-state-saved-here @ here ! transformation-state transformation-state-saved-latest @ latest ! ~ (output point) |