├── .gitignore ├── CopyCollector2.pdf ├── CopyingCollector.pdf ├── Makefile ├── all.bib ├── book.tex ├── dataflow-notes.txt ├── defs.tex ├── figs ├── cheney.graffle ├── cheney.pdf ├── closures.graffle ├── closures.pdf ├── copy-collect-1.graffle ├── copy-collect-1.pdf ├── copy-collect-2.graffle ├── copy-collect-2.pdf ├── root-stack.graffle ├── root-stack.pdf ├── sudoku-graph.graffle ├── sudoku-graph.pdf ├── sudoku.graffle ├── sudoku.pdf ├── tuple-rep.graffle └── tuple-rep.pdf ├── s-expr-example.rkt ├── shadow-stack.pdf └── shell.nix /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /CopyCollector2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/CopyCollector2.pdf -------------------------------------------------------------------------------- /CopyingCollector.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/CopyingCollector.pdf -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all cont continuous clean publish 3 | 4 | LATEXMK= latexmk -outdir=./build -pdf 5 | 6 | all: 7 | $(LATEXMK) book.tex 8 | 9 | cont: continuous 10 | continuous: 11 | $(LATEXMK) -pvc book.tex 12 | 13 | clean: 14 | $(LATEXMK) -C book.tex 15 | 16 | # Build with a fixed snapshot of NixPkgs 17.03. Known-to-work. 17 | # For a very clean version, run git clean -fxd followed by this: 18 | # 19 | # This may take a long time and build a complete version of texlive. 20 | # Since it is fixed-in-time it may not have binary caches available and 21 | # may need to build from source. 22 | nix: 23 | NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/51a83266d164195698f04468d90d2c6238ed3491.tar.gz $(MAKE) nix-head 24 | 25 | # This is a compromise. Build faster by using a binary cache, but 26 | # still allow minor version patches by pointing at the head of a 27 | # (dynamic) channel. 28 | nix-fast: 29 | NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-17.03.tar.gz $(MAKE) nix-head 30 | 31 | # Build with whatever version of nixpkgs is in the users environment: 32 | nix-head: 33 | nix-shell --pure --run make 34 | 35 | 36 | # Specific to Fall16: 37 | publish: 38 | scp build/book.pdf tank.soic.indiana.edu:p523-web/book.pdf 39 | -------------------------------------------------------------------------------- /dataflow-notes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Liveness Analysis as a Dataflow Analysis 4 | ---------------------------------------- 5 | 6 | References: 7 | * Principles of Program Analysis by Nielson, Nielson, and Hankin 8 | * Ch. 9 of Compilers: Principles, Techniques, & Tools 9 | by Aho, Lam, Sethi, Ullman 10 | * Ch. 17 of Modern Compiler Implemenation in ML by Appel 11 | 12 | Running example: 13 | S* = 14 | [y := 1]^1 15 | while [x>0]^2 16 | [w := y]^3 17 | [x := x - 1]^4 18 | [z := w]^5 19 | 20 | We're going to work on the control flow graph of the program, 21 | where each superscript corresponds to a node in the graph 22 | and the edges represent control flow possibilities. 23 | 24 | Recall that a variable is *live* if it might get used later. 25 | Used for register allocation and dead code elimination. 26 | 27 | A backward analysis. 28 | 29 | gen([x:=e]) = FV(e) 30 | gen([skip]) = {} 31 | gen([e]) = FV(e) 32 | 33 | kill([x:=e]) = {x} 34 | kill([skip]) = {} 35 | kill([e]) = {} 36 | 37 | Let P[l] be the statement number l in program P. 38 | 39 | LV_before(l) = (LV_after(l) - kill(P[l])) U gen(P[l]) (1) 40 | LV_after(l) = Union{ LV_before(l') | l --> l' in CFG(P) } (2) 41 | 42 | We'd like to find a solution to these equations. 43 | It's useful to combine all these equations into a single 44 | equation by putting all the LV's into two vectors: 45 | 46 | LV_before = [LV_before(1), LV_before(2), ... ] 47 | LV_after = [LV_after(1), LV_after(2), ... ] 48 | 49 | And then encode the equations (1) and (2) for all the statements 50 | into two vector-valued functions F_before and F_after. 51 | 52 | F_before(l)(LV_after) = (LV_after[l] - kill(P[l])) U gen(P[l]) 53 | F_after(l)(LV_before) = Union{ LV_before[l'] | l --> l' in CFG(P) } 54 | 55 | We could even squish these two vectors (before/after) and two 56 | functions into a single vector LV and function F. Then a solution 57 | looks like: 58 | 59 | LV = F(LV) 60 | 61 | That is, we'd like to find a fixed point of F. 62 | 63 | There's a branch of mathematics that studies fixed points 64 | in the context of lattices. 65 | 66 | The sets of variables ordered by subseteq form a lattice, 67 | with {} as the bottom element and the set of all variables V 68 | as the top element. 69 | 70 | Vectors of sets ordered pointwise forms a lattice, with 71 | [{},{},{},...] as the bottom element and 72 | [V,V,V,...] as the top element. 73 | 74 | One of the classic fixpoint theorems is: 75 | 76 | Suppose F is an order-preserving function. If the set L 77 | has no infinitely ascending chains and a least element bot, 78 | then there is a fixed point of F. 79 | 80 | Proof. 81 | bot <= F(bot) because bot is the least element of L 82 | F(bot) <= F(F(bot)) because F is order preserving. 83 | and so on, so in general we have 84 | F^i(bot) <= F^i+1(bot) 85 | but this can't go on forever, so at some point 86 | F^n(bot) = F^n+1(bot) 87 | and therefore, F^n(bot) is a fixed point of F. 88 | 89 | But is our F for liveness order-preserving? (skip this) 90 | Suppose V <= V'. 91 | Let l be any statement number. 92 | If l is even: (LV_before) 93 | We have V[l] <= V'[l]. 94 | then V[l] - kill(P[l]) <= V[l]' - kill(P[l]) 95 | and (V[l] - kill(P[l])) U gen(P[l]) <= (V[l]' - kill(P[l])) U gen(P[l]). 96 | Therefore F_l(V) <= F_l(V'). 97 | If l is odd: (LV_after) 98 | We have V[i] <= V'[i] for any i. 99 | Thus, 100 | Union{ V[l'] | l --> l' in CFG(P) } 101 | <= Union{ V'[l'] | l --> l' in CFG(P) } 102 | Therefore F_l(V) <= F_l(V') 103 | So F(V) <= F(V). 104 | 105 | Do we have a least element? Yes: 106 | [{}, {}, ...] 107 | Are there infinite ascending chains? No, because there are 108 | a finite number of variables in the program. 109 | 110 | Worklist algorithm (applied to Liveness) 111 | 112 | W is a list of control-flow edges 113 | 114 | 1. Initialization 115 | W = [] 116 | for (l,l') in CFG 117 | W = [(l,l')] + W 118 | for l in CFG do 119 | Analysis[l] = {} 120 | 121 | 2. Iteration 122 | while W != []: 123 | (l,l') = W[0] 124 | W = W[1:] 125 | if F_l(Analysis[l]) not <= Analysis[l']: 126 | Analysis[l'] := Analysis[l'] |_| F_l(Analysis[l]) 127 | for l'' in in_edges(CFG, l'): 128 | W = [(l'',l')] + W 129 | 3. Recording the result 130 | LV_after(l) := Analysis[l] 131 | LV_before(l) := F_l(Analysis[l]) 132 | 133 | Example 134 | 135 | S* = 136 | [y := 1]^1 137 | while [x>0]^2 138 | [w := y]^3 139 | [x := x - 1]^4 140 | [z := w]^5 141 | 142 | flow^R(S*) = (2,1),(3,2),(4,3),(2,4),(5,2) 143 | 144 | F_before_1(X) = X - {y} 145 | F_before_2(X) = X U {x} 146 | F_before_3(X) = (X - {w}) U {y} 147 | F_before_4(X) = X U {x} 148 | F_before_5(X) = (X - {z}) U {w} 149 | 150 | Analysis W 151 | step 1 2 3 4 5 152 | 1 {} {} {} {} {} (2,1),(3,2),(4,3),(2,4),(5,2) 153 | 2 {x} {} {} {} {} (3,2),(4,3),(2,4),(5,2) 154 | 3 {x} {y} {} {} {} (2,1),(2,4),(4,3),(2,4),(5,2) 155 | 4 {x,y} {y} {} {} {} (2,4),(4,3),(2,4),(5,2) 156 | 5 {x,y} {y} {} {x,y} {} (4,3),(4,3),(2,4),(5,2) 157 | 6 {x,y} {y} {x,y} {x,y} {} (3,2),(4,3),(2,4),(5,2) 158 | 7 {x,y} {x,y} {x,y} {x,y} {} (2,1),(2,4),(4,3),(2,4),(5,2) 159 | 8 {x,y} {x,y} {x,y} {x,y} {} (2,4),(4,3),(2,4),(5,2) 160 | 9 {x,y} {x,y} {x,y} {x,y} {} (4,3),(2,4),(5,2) 161 | 10 {x,y} {x,y} {x,y} {x,y} {} (2,4),(5,2) 162 | 11 {x,y} {x,y} {x,y} {x,y} {} (5,2) 163 | 12 {x,y} {x,y,w} {x,y} {x,y} {} (2,1),(2,4) 164 | 13 {x,y,w} {x,y,w} {x,y} {x,y} {} (2,4) 165 | 14 {x,y,w} {x,y,w} {x,y} {x,y,w} {} (4,3) 166 | 15 {x,y,w} {x,y,w} {x,y,w} {x,y,w} {} (3,2) 167 | 16 {x,y,w} {x,y,w} {x,y,w} {x,y,w} {} 168 | 169 | Constant Propagation and Folding 170 | 171 | z = 3 172 | x = 1 173 | while x > 0: 174 | if x == 1: 175 | y = 7 176 | else: 177 | y = z + 4 178 | x = 3 179 | print y 180 | 181 | ===> 182 | 183 | z = 3 184 | x = 1 185 | while x > 0: 186 | if x == 1: 187 | y = 7 188 | else: 189 | y = 3 + 4 *** 190 | x = 3 191 | print y 192 | 193 | ===> 194 | 195 | z = 3 196 | x = 1 197 | while x > 0: 198 | if x == 1: 199 | y = 7 200 | else: 201 | y = 7 *** 202 | x = 3 203 | print y 204 | 205 | ===> 206 | 207 | z = 3 208 | x = 1 209 | while x > 0: 210 | if x == 1: 211 | y = 7 212 | else: 213 | y = 7 214 | x = 3 215 | print 7 *** 216 | 217 | Lattice for one program variable: 218 | 219 | NAC (not a constant) 220 | 221 | 1 2 3 4 ... (definitely a constant) 222 | 223 | UNDEF (don't know anything about the variable) 224 | 225 | The after/before's are mappings from variables to values 226 | in the above lattice. 227 | 228 | THE FOLLOWING NEEDS TO BE REVISED -Jeremy 229 | 230 | Constant propagation is a forward analysis 231 | 232 | kill([x:=e]^l) = {(x,c) | for any c} 233 | kill([skip]^l) = {} 234 | kill([e]^l) = {} 235 | 236 | gen([x:=e}^l) = { (x,eval(e,l)) } 237 | gen([skip]^l) = {} 238 | gen([e]^l) = {} 239 | 240 | eval(n,l) = n 241 | eval(x,l) = c if (x, c) in CP_before(l) 242 | eval(e1 + e2,l) = 243 | eval(e1,l) 244 | eval(e2,l) bot 1 2 ... uninit top 245 | bot bot bot bot bot bot 246 | 1 bot 2 3 bot top 247 | 2 bot 3 4 bot top 248 | ... 249 | uninit bot bot bot bot bot 250 | top bot top top top 251 | 252 | CP_before(l) = 253 | if l = init(S*) then 254 | {(x,uninit),(y,uninit),...} 255 | else 256 | |_| { CP_after(l') | (l',l) in flow(S*) } 257 | 258 | CP_after(l) = (CP_before(l) - kill(P[l])) |_| gen(P[l]) 259 | -------------------------------------------------------------------------------- /defs.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | 3 | \newcommand{\itm}[1]{\ensuremath{\mathit{#1}}} 4 | \newcommand{\Stmt}{\itm{stmt}} 5 | \newcommand{\Exp}{\itm{exp}} 6 | \newcommand{\Def}{\itm{def}} 7 | \newcommand{\Type}{\itm{type}} 8 | \newcommand{\FType}{\itm{ftype}} 9 | \newcommand{\Instr}{\itm{instr}} 10 | \newcommand{\Prog}{\itm{prog}} 11 | \newcommand{\Arg}{\itm{arg}} 12 | \newcommand{\Reg}{\itm{reg}} 13 | \newcommand{\Int}{\itm{int}} 14 | \newcommand{\Var}{\itm{var}} 15 | \newcommand{\Op}{\itm{op}} 16 | \newcommand{\key}[1]{\texttt{#1}} 17 | \newcommand{\code}[1]{\texttt{#1}} 18 | \newcommand{\READ}{(\key{read})} 19 | \newcommand{\UNIOP}[2]{(\key{#1}~#2)} 20 | \newcommand{\BINOP}[3]{(\key{#1}~#2~#3)} 21 | \newcommand{\LET}[3]{(\key{let}~([#1\;#2])~#3)} 22 | 23 | \newcommand{\ASSIGN}[2]{(\key{assign}~#1\;#2)} 24 | \newcommand{\RETURN}[1]{(\key{return}~#1)} 25 | 26 | \newcommand{\INT}[1]{(\key{int}\;#1)} 27 | \newcommand{\REG}[1]{(\key{reg}\;#1)} 28 | \newcommand{\VAR}[1]{(\key{var}\;#1)} 29 | \newcommand{\STACKLOC}[1]{(\key{stack}\;#1)} 30 | 31 | \newcommand{\IF}[3]{(\key{if}\,#1\;#2\;#3)} 32 | 33 | \newcommand{\TTKEY}[1]{{\normalfont\tt #1}} 34 | 35 | -------------------------------------------------------------------------------- /figs/cheney.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/cheney.graffle -------------------------------------------------------------------------------- /figs/cheney.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/cheney.pdf -------------------------------------------------------------------------------- /figs/closures.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/closures.graffle -------------------------------------------------------------------------------- /figs/closures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/closures.pdf -------------------------------------------------------------------------------- /figs/copy-collect-1.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/copy-collect-1.graffle -------------------------------------------------------------------------------- /figs/copy-collect-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/copy-collect-1.pdf -------------------------------------------------------------------------------- /figs/copy-collect-2.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/copy-collect-2.graffle -------------------------------------------------------------------------------- /figs/copy-collect-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/copy-collect-2.pdf -------------------------------------------------------------------------------- /figs/root-stack.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/root-stack.graffle -------------------------------------------------------------------------------- /figs/root-stack.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/root-stack.pdf -------------------------------------------------------------------------------- /figs/sudoku-graph.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/sudoku-graph.graffle -------------------------------------------------------------------------------- /figs/sudoku-graph.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/sudoku-graph.pdf -------------------------------------------------------------------------------- /figs/sudoku.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/sudoku.graffle -------------------------------------------------------------------------------- /figs/sudoku.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/sudoku.pdf -------------------------------------------------------------------------------- /figs/tuple-rep.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/tuple-rep.graffle -------------------------------------------------------------------------------- /figs/tuple-rep.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/figs/tuple-rep.pdf -------------------------------------------------------------------------------- /s-expr-example.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require racket/match) 3 | (require racket/fixnum) 4 | 5 | (define assert 6 | (lambda (msg b) 7 | (if (not b) 8 | (begin 9 | (display "ERROR: ") 10 | (display msg) 11 | (newline)) 12 | (void)))) 13 | 14 | (define ast1.4 `(- 8)) 15 | (define ast1.1 `(+ 50 ,ast1.4)) 16 | 17 | (match ast1.1 18 | [`(,op ,child1 ,child2) 19 | (print op) (newline) 20 | (print child1) (newline) 21 | (print child2)]) 22 | 23 | (define (arith-kind arith) 24 | (match arith 25 | [(? fixnum?) `int] 26 | [`(- ,c1) `neg] 27 | [`(+ ,c1 ,c2) `add])) 28 | 29 | (arith-kind `50) 30 | (arith-kind `(- 8)) 31 | (arith-kind `(+ 50 (- 8))) 32 | 33 | (define (arith? sexp) 34 | (match sexp 35 | [(? fixnum?) #t] 36 | [`(+ ,e1 ,e2) 37 | (and (arith? e1) (arith? e2))] 38 | [`(- ,e) (arith? e)] 39 | [else #f])) 40 | 41 | (arith? `(+ 50 (- 8))) 42 | (arith? `(- 50 (+ 8))) 43 | 44 | (define (interp-R0 e) 45 | (match e 46 | [(? fixnum?) e] 47 | [`(read) 48 | (let ([r (read)]) 49 | (cond [(fixnum? r) r] 50 | [else (error 'interp-R0 "input was not an integer" r)]))] 51 | [`(- ,(app interp-R0 v)) 52 | (fx- 0 v)] 53 | [`(+ ,(app interp-R0 v1) ,(app interp-R0 v2)) 54 | (fx+ v1 v2)] 55 | )) 56 | 57 | (interp-R0 ast1.1) 58 | ;(interp-R0 `(+ (read) (- 8))) 59 | 60 | (define (pe-neg r) 61 | (match r 62 | [(? fixnum?) (fx- 0 r)] 63 | [else `(- ,r)] 64 | )) 65 | 66 | (define (pe-add r1 r2) 67 | (match (list r1 r2) 68 | [`(,n1 ,n2) 69 | #:when (and (fixnum? n1) (fixnum? n2)) 70 | (fx+ r1 r2)] 71 | [else 72 | `(+ ,r1 ,r2)] 73 | )) 74 | 75 | (define (pe-arith e) 76 | (match e 77 | [(? fixnum?) e] 78 | [`(read) 79 | `(read)] 80 | [`(- ,e1) 81 | (pe-neg (pe-arith e1))] 82 | [`(+ ,e1 ,e2) 83 | (pe-add (pe-arith e1) (pe-arith e2))] 84 | )) 85 | 86 | ;; e ::= (read) | (- (read)) | (+ e e) 87 | ;; r ::= n | (+ n e) | e 88 | 89 | (define (pe-neg2 r) 90 | (match r 91 | [(? fixnum?) (fx- 0 r)] 92 | [`(+ ,n ,e2) 93 | #:when (fixnum? n) 94 | `(+ ,(fx- 0 n) ,(pe-neg2 e2))] 95 | [`(read) `(- (read))] 96 | [`(- ,e2) e2] 97 | [`(+ ,e1 ,e2) 98 | `(+ ,(pe-neg2 e1) ,(pe-neg2 e2))] 99 | )) 100 | 101 | (define (pe-add2 r1 r2) 102 | (match r1 103 | [(? fixnum?) 104 | (match r2 105 | [(? fixnum?) (fx+ r1 r2)] 106 | [`(+ ,n2 ,e2) #:when (fixnum? n2) 107 | `(+ ,(fx+ r1 n2) ,e2)] 108 | [else `(+ ,r1 ,r2)])] 109 | [`(+ ,n1 ,e1) 110 | (match r2 111 | [(? fixnum?) `(+ (fx+ n1 r2) ,e1)] 112 | [`(+ ,n2 ,e2) #:when (fixnum? n2) 113 | `(+ ,(fx+ n1 n2) (+ ,e1 ,e2))] 114 | [else `(+ ,r1 ,r2)])] 115 | [else 116 | (match r2 117 | [(? fixnum?) `(+ ,r2 ,r1)] 118 | [else `(+ ,r1 ,r2)])] 119 | )) 120 | 121 | (define (pe-arith2 e) 122 | (match e 123 | [(? fixnum?) e] 124 | [`(read) 125 | `(read)] 126 | [`(- ,e1) 127 | (pe-neg2 (pe-arith2 e1))] 128 | [`(+ ,e1 ,e2) 129 | (pe-add2 (pe-arith2 e1) (pe-arith2 e2))] 130 | )) 131 | 132 | 133 | (define (test-pe pe p) 134 | (assert "testing pe-arith" (equal? (interp-R0 p) 135 | (interp-R0 (pe p))))) 136 | (if #f 137 | (begin 138 | (test-pe pe-arith `(+ (read) (- (+ 5 3)))) 139 | (test-pe pe-arith `(+ 1 (+ (read) 1))) 140 | (test-pe pe-arith `(- (+ (read) (- 5)))) 141 | 142 | (test-pe pe-arith2 `(+ (read) (- (+ 5 3)))) 143 | (test-pe pe-arith2 `(+ 1 (+ (read) 1))) 144 | (test-pe pe-arith2 `(- (+ (read) (- 5)))) 145 | ) 146 | (void)) 147 | -------------------------------------------------------------------------------- /shadow-stack.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrnewton/Essentials-of-Compilation/c24bdded415d9e64b4209595f99e8060dbcd9e2e/shadow-stack.pdf -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | 2 | # By default (irreproducibly) use whatever nixpkgs is in path: 3 | with (import {}); 4 | 5 | # Probably a lower-footprint way of doing this: 6 | stdenv.mkDerivation { 7 | name = "docsEnv"; 8 | buildInputs = [ 9 | texlive.combined.scheme-full 10 | ]; 11 | } 12 | --------------------------------------------------------------------------------