about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-11-27 22:44:23 -0800
committerKartik Agaram <vc@akkartik.com>2020-11-27 22:44:23 -0800
commitbbcf033aff4dd3aad3aa0307e1c3843d5a81c184 (patch)
tree5861f95f95c555d260f780edadac1eacb84bd165
parentbcd2adfbf333987e03846b99204d3fd5031ddd93 (diff)
downloadmu-bbcf033aff4dd3aad3aa0307e1c3843d5a81c184.tar.gz
7292 - mu.subx: loosen copy-byte checks a bit
Without this there's no way to convert an int to a byte. And that feels
too restrictive, and gives up a lot of safe things one might want to do
with bytes. (Such as divide a number by 10 and emit the remainder as a
byte.)
-rwxr-xr-xapps/mubin594903 -> 593602 bytes
-rw-r--r--apps/mu.subx156
-rw-r--r--mu.md6
3 files changed, 34 insertions, 128 deletions
diff --git a/apps/mu b/apps/mu
index 4f739a67..a608bd3f 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 5dc5cb13..b71756c7 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -8607,7 +8607,7 @@ test-copy-byte-with-invalid-output-type:
     5d/pop-to-ebp
     c3/return
 
-test-copy-byte-from-invalid-type:
+test-copy-byte-from-non-scalar-inout:
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -8625,52 +8625,8 @@ test-copy-byte-from-invalid-type:
     (tailor-exit-descriptor %edx 0x10)
     #
     (write _test-input-stream "fn foo {\n")
-    (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
-    (write _test-input-stream "  var y/eax: int <- copy-byte x\n")
-    (write _test-input-stream "}\n")
-    # convert
-    (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
-    # registers except esp clobbered at this point
-    # restore ed
-    89/<- %edx 4/r32/esp
-    (flush _test-output-buffered-file)
-    (flush _test-error-buffered-file)
-#?     # dump _test-error-stream {{{
-#?     (write 2 "^")
-#?     (write-stream 2 _test-error-stream)
-#?     (write 2 "$\n")
-#?     (rewind-stream _test-error-stream)
-#?     # }}}
-    # check output
-    (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-invalid-type: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: inout must have type byte"  "F - test-copy-byte-from-invalid-type: error message")
-    # check that stop(1) was called
-    (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-invalid-type: exit status")
-    # don't restore from ebp
-    81 0/subop/add %esp 8/imm32
-    # . epilogue
-    5d/pop-to-ebp
-    c3/return
-
-test-copy-byte-with-literal-inout:
-    # . prologue
-    55/push-ebp
-    89/<- %ebp 4/r32/esp
-    # setup
-    (clear-stream _test-input-stream)
-    (clear-stream $_test-input-buffered-file->buffer)
-    (clear-stream _test-output-stream)
-    (clear-stream $_test-output-buffered-file->buffer)
-    (clear-stream _test-error-stream)
-    (clear-stream $_test-error-buffered-file->buffer)
-    # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
-    68/push 0/imm32
-    68/push 0/imm32
-    89/<- %edx 4/r32/esp
-    (tailor-exit-descriptor %edx 0x10)
-    #
-    (write _test-input-stream "fn foo {\n")
-    (write _test-input-stream "  var x/eax: byte <- copy-byte 0\n")
+    (write _test-input-stream "  var x: (handle int)\n")
+    (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
     (write _test-input-stream "}\n")
     # convert
     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
@@ -8686,10 +8642,10 @@ test-copy-byte-with-literal-inout:
 #?     (rewind-stream _test-error-stream)
 #?     # }}}
     # check output
-    (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-literal-inout: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: inout must have type byte"  "F - test-copy-byte-with-literal-inout: error message")
+    (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
+    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
     # check that stop(1) was called
-    (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-literal-inout: exit status")
+    (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
     # don't restore from ebp
     81 0/subop/add %esp 8/imm32
     # . epilogue
@@ -8967,52 +8923,6 @@ test-copy-byte-to-with-literal-inout:
     5d/pop-to-ebp
     c3/return
 
-test-copy-byte-to-from-invalid-type:
-    # . prologue
-    55/push-ebp
-    89/<- %ebp 4/r32/esp
-    # setup
-    (clear-stream _test-input-stream)
-    (clear-stream $_test-input-buffered-file->buffer)
-    (clear-stream _test-output-stream)
-    (clear-stream $_test-output-buffered-file->buffer)
-    (clear-stream _test-error-stream)
-    (clear-stream $_test-error-buffered-file->buffer)
-    # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
-    68/push 0/imm32
-    68/push 0/imm32
-    89/<- %edx 4/r32/esp
-    (tailor-exit-descriptor %edx 0x10)
-    #
-    (write _test-input-stream "fn foo {\n")
-    (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
-    (write _test-input-stream "  var y: int\n")
-    (write _test-input-stream "  copy-byte-to y, x\n")
-    (write _test-input-stream "}\n")
-    # convert
-    (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
-    # registers except esp clobbered at this point
-    # restore ed
-    89/<- %edx 4/r32/esp
-    (flush _test-output-buffered-file)
-    (flush _test-error-buffered-file)
-#?     # dump _test-error-stream {{{
-#?     (write 2 "^")
-#?     (write-stream 2 _test-error-stream)
-#?     (write 2 "$\n")
-#?     (rewind-stream _test-error-stream)
-#?     # }}}
-    # check output
-    (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-invalid-type: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must have type byte"  "F - test-copy-byte-to-from-invalid-type: error message")
-    # check that stop(1) was called
-    (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-invalid-type: exit status")
-    # don't restore from ebp
-    81 0/subop/add %esp 8/imm32
-    # . epilogue
-    5d/pop-to-ebp
-    c3/return
-
 test-copy-byte-to-deref-address:
     # . prologue
     55/push-ebp
@@ -9031,14 +8941,7 @@ test-copy-byte-to-deref-address:
     # convert
     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     (flush _test-output-buffered-file)
-#?     # dump _test-error-stream {{{
-#?     (write 2 "^")
-#?     (write-stream 2 _test-error-stream)
-#?     (write 2 "$\n")
-#?     (rewind-stream _test-error-stream)
-#?     # }}}
-    # not bothering checking output
-    (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-to-deref-address: error message")
+    # no errors
     # . epilogue
     5d/pop-to-ebp
     c3/return
@@ -9062,8 +8965,8 @@ test-copy-byte-to-from-non-scalar-inout:
     #
     (write _test-input-stream "fn foo {\n")
     (write _test-input-stream "  var x: (handle int)\n")
-    (write _test-input-stream "  var y: int\n")
-    (write _test-input-stream "  copy-byte-to y, x\n")
+    (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
+    (write _test-input-stream "  copy-byte-to *y, x\n")
     (write _test-input-stream "}\n")
     # convert
     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
@@ -9080,8 +8983,7 @@ test-copy-byte-to-from-non-scalar-inout:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
-#?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
-    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
     # don't restore from ebp
@@ -22255,6 +22157,11 @@ $check-mu-copy-byte-stmt:get-inout:
     3d/compare-eax-and 0/imm32
     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
 $check-mu-copy-byte-stmt:types:
+    # if inout is not a scalar, abort
+    (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
+    (size-of %eax)  # => eax
+    3d/compare-eax-and 4/imm32
+    0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
     # var inout-type/ecx: (addr type-tree) = inout->value->type
     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
@@ -22276,10 +22183,6 @@ $check-mu-copy-byte-stmt:inout-is-deref2:
       }
       89/<- %ecx 0/r32/eax
     }
-    # if inout is not of type byte, abort
-    (is-simple-mu-type? %ecx 8)  # byte => eax
-    3d/compare-eax-and 0/imm32
-    0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-inout-type/disp32
     # if output not in register, abort
     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
@@ -22370,12 +22273,16 @@ $check-mu-copy-byte-stmt:error-invalid-output-type:
     (stop *(ebp+0x14) 1)
     # never gets here
 
-$check-mu-copy-byte-stmt:error-invalid-inout-type:
+$check-mu-copy-byte-stmt:error-inout-too-large:
     (write-buffered *(ebp+0x10) "fn ")
     8b/-> *(ebp+0xc) 0/r32/eax
     (lookup *eax *(eax+4))  # Function-name Function-name => eax
     (write-buffered *(ebp+0x10) %eax)
-    (write-buffered *(ebp+0x10) ": stmt copy-byte: inout must have type byte\n")
+    (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
+    (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0x10) %eax)
+    (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
     (flush *(ebp+0x10))
     (stop *(ebp+0x14) 1)
     # never gets here
@@ -22386,7 +22293,6 @@ check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (add
     89/<- %ebp 4/r32/esp
     # . save registers
     50/push-eax
-    51/push-ecx
     52/push-edx
     53/push-ebx
     56/push-esi
@@ -22423,10 +22329,11 @@ $check-mu-copy-byte-to-stmt:get-src:
     3d/compare-eax-and 0/imm32
     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
 $check-mu-copy-byte-to-stmt:types:
-    # var src-type/ecx: (addr type-tree) = src->value->type
+    # if src is not a scalar, abort
     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
-    (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
-    89/<- %ecx 0/r32/eax
+    (size-of %eax)  # => eax
+    3d/compare-eax-and 4/imm32
+    0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
     # if src not in register, abort
     {
       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
@@ -22435,10 +22342,6 @@ $check-mu-copy-byte-to-stmt:types:
       75/jump-if-!= break/disp8
       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
     }
-    # if src is not a byte, abort
-    (is-simple-mu-type? %ecx 8)  # byte => eax
-    3d/compare-eax-and 0/imm32/false
-    0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-src-type/disp32
     # var dest-type/ebx: (addr type-tree) = dest->value->type
     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
@@ -22472,7 +22375,6 @@ $check-mu-copy-byte-to-stmt:end:
     5e/pop-to-esi
     5b/pop-to-ebx
     5a/pop-to-edx
-    59/pop-to-ecx
     58/pop-to-eax
     # . epilogue
     89/<- %esp 5/r32/ebp
@@ -22523,12 +22425,16 @@ $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
     (stop *(ebp+0x14) 1)
     # never gets here
 
-$check-mu-copy-byte-to-stmt:error-invalid-src-type:
+$check-mu-copy-byte-to-stmt:error-src-too-large:
     (write-buffered *(ebp+0x10) "fn ")
     8b/-> *(ebp+0xc) 0/r32/eax
     (lookup *eax *(eax+4))  # Function-name Function-name => eax
     (write-buffered *(ebp+0x10) %eax)
-    (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must have type byte\n")
+    (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
+    (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0x10) %eax)
+    (write-buffered *(ebp+0x10) "' is too large to copy\n")
     (flush *(ebp+0x10))
     (stop *(ebp+0x14) 1)
     # never gets here
diff --git a/mu.md b/mu.md
index a990bc0c..0bc63d2b 100644
--- a/mu.md
+++ b/mu.md
@@ -335,9 +335,9 @@ variables of type 'byte' are only allowed in registers, not on the stack. Here
 are the possible statements for reading bytes to/from memory:
 
 ```
-var/reg <- copy-byte var2/reg2      # var: byte, var2: byte
-var/reg <- copy-byte *var2/reg2     # var: byte, var2: (addr byte)
-copy-byte-to *var1/reg1, var2/reg2  # var1: (addr byte), var2: byte
+var/reg <- copy-byte var2/reg2      # var: byte
+var/reg <- copy-byte *var2/reg2     # var: byte
+copy-byte-to *var1/reg1, var2/reg2  # var1: (addr byte)
 ```
 
 In addition, variables of type 'byte' are restricted to (the lowest bytes of)
t&id=4d1f6bd73041c11a58287816a6b645df32b4dff1'>4d1f6bd7 ^
845a989f ^
a27dfba3 ^



845a989f ^



bee53b4b ^
a27dfba3 ^

















4d1f6bd7 ^
5b698455 ^
7d2c2d55 ^

a03b8aea ^

93d5dce6 ^
7d2c2d55 ^


98e6a592 ^


3f29fba8 ^
98e6a592 ^
a27dfba3 ^

a03b8aea ^
a27dfba3 ^








4d1f6bd7 ^
5b698455 ^
93d5dce6 ^
7d2c2d55 ^


a27dfba3 ^













10c5eed0 ^
a27dfba3 ^

bee53b4b ^
a27dfba3 ^

4d1f6bd7 ^
5b698455 ^
93d5dce6 ^
a27dfba3 ^


a03b8aea ^

ce3518f3 ^
d1c12218 ^
ce3518f3 ^



ce3518f3 ^
ce3518f3 ^

e605597d ^

e605597d ^
e605597d ^


445a1494 ^
ce3518f3 ^


16a83577 ^
d1c12218 ^
f7a26719 ^








a1f2f613 ^
93d5dce6 ^
4d1f6bd7 ^
83a43e63 ^
09e2e533 ^

8ab4b12c ^
7d2c2d55 ^

5249b0ff ^
0d2c3387 ^
d2db5af7 ^
0d2c3387 ^
7d2c2d55 ^
0d2c3387 ^
7d2c2d55 ^
0d2c3387 ^
7d2c2d55 ^
09e2e533 ^
bee53b4b ^
7d2c2d55 ^



4ca73eb6 ^
bee53b4b ^
98e6a592 ^
5249b0ff ^


16a83577 ^




954dd99d ^
308e1146 ^
445a1494 ^
308e1146 ^
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