;;;; (filled b) and (dead-beef), the two byte fills, read back as bytes. ;;;; ;;;; The whole point of this program is that every row is a *byte* and not a ;;;; value: the pattern fill's contract is "a hex dump reads the pattern left ;;;; to right", which is a claim about which byte lands at which address, and ;;;; only reading the bytes back in address order can check it. The u32 rows ;;;; are the same claim from the other side — a little-endian load of ;;;; DE AD BE EF is 0xEFBEADDE, which is 4022250974, so a backend that wrote ;;;; the word the other way round would print 3735928559 here and be caught. ;;;; ;;;; The lengths are chosen for the tail. 8 is a whole number of patterns, 9 ;;;; ends on DE, 6 ends on DE AD, and 7 ends on DE AD BE — the three truncated ;;;; endings and the one that is not truncated at all. ;;;; ;;;; The rows that matter most are the last group: a pattern that is *not* a ;;;; literal, over a length that is not a multiple of four. That is the case a ;;;; constant-only implementation would pass by accident — the word reaches ;;;; the loop in a register and the tail bytes have to be shifted out of it ;;;; rather than folded, on both backends. (defstruct Words [a u32 b u32]) ;;;; A computed global initialiser: a fill is never a constant the linker can ;;;; write, so this one goes through the startup function on both backends. (defonce gfill [4 u8] (filled 0x41)) (defonce gsent [5 u8]) (defn bytes4 [b [4 u8]] () (dotimes [i 4] (print (at b i)) (print " "))) ;;;; A u32 that no literal rule can see through: (u32 0xBAADF00D) will not do, ;;;; because the cast checks its operand as an i32 first and 0xBAADF00D is not ;;;; one. A parameter's declared type is what makes the literal a u32, and it ;;;; is also what stops the checker folding it at the fill. (defn u32of [x u32] u32 x) ;;;; The pattern crosses a call boundary, so nothing can fold it at the fill. (defn beef7 [pat u32] () (let [a (array 7 u8)] (set a (dead-beef pat)) (dotimes [i 7] (print (at a i)) (print " ")) (println ""))) (defn main [] i32 ;; One byte, repeated. 0xFF is the -1 fill a debug allocator wants. (let [a (array 4 u8)] (set a (filled 0xFF)) (bytes4 a) (println "")) ; 255 255 255 255 ;; The byte is an expression, not a literal: this is a memset with the ;; operand in a register, and the register path is the one a constant would ;; otherwise hide. (let [v (u8 7) a (array 4 u8)] (set a (filled v)) (bytes4 a) (println "")) ; 7 7 7 7 ;; (filled 0) is (zeroed), byte for byte, and saying so here is what keeps ;; the two from drifting. (let [a (array 4 u8)] (set a (filled 0)) (bytes4 a) (println "")) ; 0 0 0 0 ;; Four bytes, ascending, with nothing truncated. (let [a (array 8 u8)] (set a (dead-beef)) (dotimes [i 8] (print (at a i)) (print " ")) (println "")) ; 222 173 190 239 x2 ;; The bare form is the spelled-out default, and this is the row that says ;; so: the same eight bytes from (dead-beef 0xDEADBEEF). (let [a (array 8 u8)] (set a (dead-beef 0xDEADBEEF)) (dotimes [i 8] (print (at a i)) (print " ")) (println "")) ; identical to the row above ;; The three truncated tails. (let [a (array 9 u8)] (set a (dead-beef)) (dotimes [i 9] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 (let [a (array 6 u8)] (set a (dead-beef)) (dotimes [i 6] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 173 (let [a (array 7 u8)] (set a (dead-beef)) (dotimes [i 7] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 173 190 ;; A pattern of the program's own choosing, laid down left to right the same ;; way: 0xBAADF00D is BA AD F0 0D, which is 186 173 240 13. (let [a (array 6 u8)] (set a (dead-beef 0xBAADF00D)) (dotimes [i 6] (print (at a i)) (print " ")) (println "")) ; 186 173 240 13 186 173 ;; The same pattern read as words rather than as bytes, which is what says ;; which end the DE is at. (let [w (Words {})] (set w (dead-beef)) (print (.a w)) (print " ") (print (.b w)) (println "")) (let [w (Words {})] (set w (dead-beef 0xBAADF00D)) (print (.a w)) (print " ") (print (.b w)) (println "")) ;; A nested aggregate: a fixed array of structs is plain data all the way ;; down, so the fill reaches every byte of it. (let [g (array 2 Words)] (set g (filled 0xFF)) (print (.a (at g 0))) (print " ") (print (.b (at g 1))) (println "")) ;; The globals. [gfill] was filled before main ran; [gsent] is filled here. (dotimes [i 4] (print (at gfill i)) (print " ")) (println "") ; 65 65 65 65 (set gsent (dead-beef)) (dotimes [i 5] (print (at gsent i)) (print " ")) (println "") ; 222 173 190 239 222 ;; A fill in value position rather than as the value of a [set]: the same ;; bytes, reached through a temporary instead of through the place. (bytes4 (filled 0xFF)) (println "") ; 255 255 255 255 ;; ── The computed pattern ────────────────────────────────────────── ;; None of these can be folded: the pattern is a parameter, or arithmetic ;; the checker does not evaluate. Seven bytes is one whole pattern and a ;; three-byte tail, so the tail bytes have to come out of the register the ;; word is in rather than out of a constant. (beef7 0xDEADBEEF) ; 222 173 190 239 222 173 190 (beef7 0xBAADF00D) ; 186 173 240 13 186 173 240 (let [p (u32of 0xBAADF00D) a (array 6 u8)] (set a (dead-beef p)) (dotimes [i 6] (print (at a i)) (print " ")) (println "")) ; 186 173 240 13 186 173 ;; A pattern that is genuinely computed, not merely held in a slot, and read ;; back as a word so the byte order of the runtime path is pinned too. (let [p (u32of 0xBAAD0000) w (Words {})] (set w (dead-beef (bit-or p (u32of 0xF00D)))) (print (.a w)) (print " ") (print (.b w)) (println "")) 0)