;;;; (filled b) and (sentinel-filled) — 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 sentinel's contract is "a hex dump reads DEADBEEF", 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. (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. (defvar gfill [4 u8] (filled 0x41)) (defvar gsent [5 u8]) (defn bytes4 [b [4 u8]] () (dotimes [i 4] (print (at b i)) (print " "))) (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 (sentinel-filled)) (dotimes [i 8] (print (at a i)) (print " ")) (println "")) ; 222 173 190 239 x2 ;; The three truncated tails. (let [a (array 9 u8)] (set a (sentinel-filled)) (dotimes [i 9] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 (let [a (array 6 u8)] (set a (sentinel-filled)) (dotimes [i 6] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 173 (let [a (array 7 u8)] (set a (sentinel-filled)) (dotimes [i 7] (print (at a i)) (print " ")) (println "")) ; ... ends on 222 173 190 ;; 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 (sentinel-filled)) (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 (sentinel-filled)) (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 0)