-
Notifications
You must be signed in to change notification settings - Fork 1
/
machine.scm
267 lines (212 loc) · 7.05 KB
/
machine.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
(declare (unit machine)
(uses nodes arch))
(use matchable)
(use srfi-1)
(include "struct-syntax")
;; aggregate structures
(define-struct mc-module (contexts))
(define-struct mc-context (name args start vregs))
(define-struct mc-block (name head tail succ cxt))
;; instructions
(define-struct mc-spec (name fmt fmt-indices verifiers reads writes))
(define-struct mc-instr (spec ops next prev implicit-uses index block data))
;; operands
(define-struct mc-vreg (name hreg pref users data))
(define-struct mc-imm (size value))
(define-struct mc-disp (value))
;; Constructors
(define (mc-make-module)
(make-mc-module '()))
(define (mc-make-context name params mod)
(arch-make-context name params mod))
(define (mc-make-block cxt name)
(make-mc-block name '() '() '() cxt))
(define (mc-make-instr blk spec implicit-uses operands)
(let ((instr (make-mc-instr spec operands '() '() implicit-uses #f blk '())))
(for-each (lambda (op)
(cond
((mc-vreg? op)
(mc-vreg-add-user op instr))))
operands)
(and blk (mc-block-append blk instr))
instr))
(define mc-make-vreg
(lambda operands
(match operands
((name)
(make-mc-vreg name #f #f '() '()))
((name hreg pref)
(make-mc-vreg name hreg pref '() '()))
(else (assert-not-reached)))))
;; Operand Protocol
(define (mc-operand-equal? o1 o2)
(or (mc-vreg-equal? o1 o2)
(mc-imm-equal? o1 o2)
(mc-disp-equal? o1 o2)))
(define (mc-operand-format op)
(arch-operand-format op))
;; Vreg Protocol
(define (mc-vreg-equal? v1 v2)
(and (mc-vreg? v1) (mc-vreg? v2) (eq? v1 v2)))
(define (mc-vreg-add-user vreg instr)
(mc-vreg-users-set! vreg (cons instr (mc-vreg-users vreg))))
(define (mc-vreg-remove-user vreg instr)
(mc-vreg-users-set! vreg
(lset-difference mc-vreg-equal? (mc-vreg-users vreg) (list instr))))
(define (mc-vreg-param? v)
(mc-vreg-attribs v))
;; Imm Protocol
(define (mc-imm-equal? i1 i2)
(and (mc-imm? i1) (mc-imm? i2) (eq? i1 i2)))
;; Disp Protocol
(define (mc-disp-equal? d1 d2)
(and (mc-disp? d1) (mc-disp? d2) (eq? d1 d2)))
;; Instruction Protocol
;; Get all vregs that are read
(define (mc-instr-vregs-read instr)
(arch-vregs-read instr))
;; Get all vregs that are written
(define (mc-instr-vregs-written instr)
(arch-vregs-written instr))
(define (mc-instr-is-read? instr vreg)
(and (find (lambda (x)
(mc-vreg-equal? x vreg))
(mc-instr-vregs-read instr))
#t))
(define (mc-instr-is-written? instr vreg)
(and (find (lambda (x)
(mc-vreg-equal? x vreg))
(mc-instr-vregs-written instr))
#t))
;; Replace a vreg
(define (mc-instr-replace-vreg instr vreg x)
(define (replace ops)
(reverse
(fold (lambda (op ops)
(cond
((mc-operand-equal? op vreg)
(mc-vreg-remove-user op instr)
(mc-vreg-add-user x instr)
(cons x ops))
(else
(cons op ops))))
'()
ops)))
(mc-instr-ops-set! instr (replace (mc-instr-ops instr))))
;; Context Protocol
(define mc-context-allocate-vreg
(lambda operands
(match operands
((cxt name rest* ...)
(let ((vregs (mc-context-vregs cxt)))
(cond
((find (lambda (vreg)
(eq? (mc-vreg-name vreg) name))
vregs)
=> (lambda (vreg) vreg))
(else
(let ((vreg (apply mc-make-vreg (cons name rest*))))
(mc-context-vregs-set! cxt (cons vreg vregs))
vreg)))))
(else (assert-not-reached)))))
;; Printing
(define (mc-module-print mod port)
(fprintf port "section .text\n\n")
(fprintf port " global __scheme_exec\n\n")
(mc-context-for-each
(lambda (context)
(mc-context-print context port))
mod))
(define (mc-context-print context port)
(struct-case context
((mc-context name args entry)
(fprintf port " # context: name=~s args=~s\n" name (map (lambda (arg) (mc-vreg-name arg)) args))
(mc-block-for-each
(lambda (block)
(mc-block-print block port))
context))))
(define (mc-block-print block port)
(struct-case block
((mc-block name head tail succ)
;; print label
(fprintf port " ~a:\n" name)
;; print code
(mc-instr-for-each
(lambda (instr)
(mc-instr-print instr port))
block)
(fprintf port "\n"))))
(define (mc-instr-print instr port)
(let* ((fmt (mc-spec-fmt (mc-instr-spec instr)))
(fmt-indices (mc-spec-fmt-indices (mc-instr-spec instr)))
(ops-vect (list->vector (mc-instr-ops instr)))
(ops-sorted (reverse (fold (lambda (i x)
(cons (vector-ref ops-vect (- i 1)) x))
'()
fmt-indices))))
;; (fprintf port " # live = ~s\n" (map (lambda (vreg) (mc-vreg-name vreg)) (mc-instr-data instr)))
(fprintf port " ")
(fprintf port
(apply format
(cons
fmt
(map mc-operand-format ops-sorted))))
(fprintf port "\n")))
(define (mc-block-append blk instr)
(cond
((and (null? (mc-block-head blk))
(null? (mc-block-tail blk)))
(mc-block-head-set! blk instr)
(mc-block-tail-set! blk instr))
(else
(let ((tail (mc-block-tail blk)))
(mc-instr-prev-set! instr tail)
(mc-instr-next-set! tail instr)
(mc-block-tail-set! blk instr))))
blk)
(define (mc-block-insert-after blk instr x)
(let ((next (mc-instr-next instr))
(prev (mc-instr-prev instr)))
(cond
((and (null? next))
(mc-instr-prev-set! x instr)
(mc-instr-next-set! x '())
(mc-instr-next-set! instr x)
(mc-block-tail-set! blk x))
(else
(mc-instr-prev-set! x instr)
(mc-instr-next-set! x next)
(mc-instr-next-set! instr x)
(mc-instr-prev-set! next x)))))
(define (mc-block-insert-before blk instr x)
(let ((next (mc-instr-next instr))
(prev (mc-instr-prev instr)))
(cond
((and (null? prev))
(mc-instr-next-set! x instr)
(mc-instr-prev-set! x '())
(mc-instr-prev-set! instr x)
(mc-block-head-set! blk x))
(else
(mc-instr-prev-set! x prev)
(mc-instr-next-set! x instr)
(mc-instr-prev-set! instr x)
(mc-instr-next-set! prev x)))))
;; iteration
(define (mc-context-for-each f mod)
(for-each f (mc-module-contexts mod)))
(define (mc-block-for-each f context)
(define (visit-block block f)
(let ((succ (mc-block-succ block)))
(f block)
(for-each (lambda (succ)
(visit-block succ f))
succ)))
(visit-block (mc-context-start context) f))
(define (mc-instr-for-each f block)
(let ((head (mc-block-head block)))
(let walk ((x head))
(cond
((not (null? x))
(f x)
(walk (mc-instr-next x)))))))