From 85a964616d7ee85f87cb6d0c1e9d0e3fb088e602 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 14 Mar 2020 14:48:05 -0700 Subject: 6146 --- html/apps/mu.subx.html | 18019 ++++++++++++++++++++++++----------------------- 1 file changed, 9044 insertions(+), 8975 deletions(-) (limited to 'html/apps') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 583026b8..ae00ba3e 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -536,15 +536,15 @@ if ('onhashchange' in window) { 474 55/push-ebp 475 89/<- %ebp 4/r32/esp 476 # initialize global data structures - 477 c7 0/subop/copy *Next-block-index 1/imm32 + 477 c7 0/subop/copy *Next-block-index 1/imm32 478 c7 0/subop/copy *Type-id 0x1c/imm32 # stream-write 479 c7 0/subop/copy *_Program-functions 0/imm32 480 c7 0/subop/copy *_Program-types 0/imm32 481 # - 482 (parse-mu *(ebp+8)) - 483 (populate-mu-type-sizes) - 484 (check-mu-types) - 485 (emit-subx *(ebp+0xc)) + 482 (parse-mu *(ebp+8)) + 483 (populate-mu-type-sizes) + 484 (check-mu-types) + 485 (emit-subx *(ebp+0xc)) 486 $convert-mu:end: 487 # . epilogue 488 89/<- %esp 5/r32/ebp @@ -867,7 +867,7 @@ if ('onhashchange' in window) { 845 (clear-stream _test-output-stream) 846 (clear-stream $_test-output-buffered-file->buffer) 847 # - 848 (write _test-input-stream "fn main -> result/ebx: int {\n") + 848 (write _test-input-stream "fn main -> result/ebx: int {\n") 849 (write _test-input-stream " result <- do-add 3 4\n") 850 (write _test-input-stream "}\n") 851 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") @@ -2145,7 +2145,7 @@ if ('onhashchange' in window) { 2258 5d/pop-to-ebp 2259 c3/return 2260 - 2261 test-convert-length-of-array: + 2261 test-convert-address: 2262 # . prologue 2263 55/push-ebp 2264 89/<- %ebp 4/r32/esp @@ -2155,165 +2155,165 @@ if ('onhashchange' in window) { 2268 (clear-stream _test-output-stream) 2269 (clear-stream $_test-output-buffered-file->buffer) 2270 # - 2271 (write _test-input-stream "fn foo a: (addr array int) {\n") - 2272 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") - 2273 (write _test-input-stream " var c/eax: int <- length b\n") + 2271 (write _test-input-stream "fn foo {\n") + 2272 (write _test-input-stream " var a: int\n") + 2273 (write _test-input-stream " var b/eax: (addr int) <- address a\n") 2274 (write _test-input-stream "}\n") 2275 # convert 2276 (convert-mu _test-input-buffered-file _test-output-buffered-file) 2277 (flush _test-output-buffered-file) 2278 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 2284 # check output - 2285 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") - 2286 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") - 2287 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") - 2288 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") - 2289 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") - 2290 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") - 2291 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") - 2292 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") - 2293 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") - 2294 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") - 2295 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") - 2296 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") - 2297 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") - 2298 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") - 2299 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") - 2300 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") - 2301 # . epilogue - 2302 89/<- %esp 5/r32/ebp - 2303 5d/pop-to-ebp - 2304 c3/return - 2305 - 2306 test-convert-length-of-array-on-stack: - 2307 # . prologue - 2308 55/push-ebp - 2309 89/<- %ebp 4/r32/esp - 2310 # setup - 2311 (clear-stream _test-input-stream) - 2312 (clear-stream $_test-input-buffered-file->buffer) - 2313 (clear-stream _test-output-stream) - 2314 (clear-stream $_test-output-buffered-file->buffer) - 2315 # - 2316 (write _test-input-stream "fn foo {\n") - 2317 (write _test-input-stream " var a: (array int 3)\n") - 2318 (write _test-input-stream " var b/eax: int <- length a\n") - 2319 (write _test-input-stream "}\n") - 2320 # convert - 2321 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2322 (flush _test-output-buffered-file) - 2323 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2329 # check output - 2330 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-on-stack/0") - 2331 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-on-stack/1") - 2332 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-on-stack/2") - 2333 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-on-stack/3") - 2334 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-on-stack/4") - 2335 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-on-stack/5") - 2336 # define x - 2337 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-length-of-array-on-stack/6") - 2338 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7") - 2339 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8") - 2340 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9") - 2341 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/10") - 2342 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/11") - 2343 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/12") - 2344 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/13") - 2345 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/14") - 2346 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/15") - 2347 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/16") - 2348 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/17") - 2349 # . epilogue - 2350 89/<- %esp 5/r32/ebp - 2351 5d/pop-to-ebp - 2352 c3/return - 2353 - 2354 test-convert-index-into-array: - 2355 # . prologue - 2356 55/push-ebp - 2357 89/<- %ebp 4/r32/esp - 2358 # setup - 2359 (clear-stream _test-input-stream) - 2360 (clear-stream $_test-input-buffered-file->buffer) - 2361 (clear-stream _test-output-stream) - 2362 (clear-stream $_test-output-buffered-file->buffer) - 2363 # - 2364 (write _test-input-stream "fn foo {\n") - 2365 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2366 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2367 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2368 (write _test-input-stream "}\n") - 2369 # convert - 2370 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2371 (flush _test-output-buffered-file) - 2372 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2378 # check output - 2379 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array/0") - 2380 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array/1") - 2381 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array/2") - 2382 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array/3") - 2383 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array/4") - 2384 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array/5") - 2385 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array/6") - 2386 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array/7") - 2387 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8") - 2388 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9") - 2389 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11") - 2390 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/13") - 2391 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/14") - 2392 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/15") - 2393 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/16") - 2394 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/17") - 2395 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/18") - 2396 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/19") - 2397 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/20") - 2398 # . epilogue - 2399 89/<- %esp 5/r32/ebp - 2400 5d/pop-to-ebp - 2401 c3/return - 2402 - 2403 test-convert-index-into-array-with-literal: - 2404 # . prologue - 2405 55/push-ebp - 2406 89/<- %ebp 4/r32/esp - 2407 # setup - 2408 (clear-stream _test-input-stream) - 2409 (clear-stream $_test-input-buffered-file->buffer) - 2410 (clear-stream _test-output-stream) - 2411 (clear-stream $_test-output-buffered-file->buffer) - 2412 # - 2413 (write _test-input-stream "fn foo {\n") - 2414 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2415 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 2416 (write _test-input-stream "}\n") - 2417 # convert - 2418 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2419 (flush _test-output-buffered-file) - 2420 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2426 # check output - 2427 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") - 2428 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") - 2429 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") - 2430 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") - 2431 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") - 2432 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") - 2433 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") - 2434 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") - 2435 # 2 * 4 bytes/elem + 4 bytes for length = offset 12 - 2436 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8") - 2437 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9") - 2438 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10") - 2439 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/11") - 2440 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/12") - 2441 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/13") - 2442 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/14") - 2443 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/15") + 2285 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-address/0") + 2286 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-address/1") + 2287 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-address/2") + 2288 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-address/3") + 2289 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-address/4") + 2290 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-address/5") + 2291 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-address/6") + 2292 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-address/7") + 2293 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-address/8") + 2294 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-address/9") + 2295 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-address/10") + 2296 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-address/11") + 2297 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-address/12") + 2298 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-address/13") + 2299 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-address/14") + 2300 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-address/15") + 2301 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-address/16") + 2302 # . epilogue + 2303 89/<- %esp 5/r32/ebp + 2304 5d/pop-to-ebp + 2305 c3/return + 2306 + 2307 test-convert-length-of-array: + 2308 # . prologue + 2309 55/push-ebp + 2310 89/<- %ebp 4/r32/esp + 2311 # setup + 2312 (clear-stream _test-input-stream) + 2313 (clear-stream $_test-input-buffered-file->buffer) + 2314 (clear-stream _test-output-stream) + 2315 (clear-stream $_test-output-buffered-file->buffer) + 2316 # + 2317 (write _test-input-stream "fn foo a: (addr array int) {\n") + 2318 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") + 2319 (write _test-input-stream " var c/eax: int <- length b\n") + 2320 (write _test-input-stream "}\n") + 2321 # convert + 2322 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2323 (flush _test-output-buffered-file) + 2324 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2330 # check output + 2331 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") + 2332 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") + 2333 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") + 2334 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") + 2335 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") + 2336 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") + 2337 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") + 2338 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") + 2339 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") + 2340 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") + 2341 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") + 2342 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") + 2343 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") + 2344 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") + 2345 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") + 2346 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") + 2347 # . epilogue + 2348 89/<- %esp 5/r32/ebp + 2349 5d/pop-to-ebp + 2350 c3/return + 2351 + 2352 test-convert-length-of-array-on-stack: + 2353 # . prologue + 2354 55/push-ebp + 2355 89/<- %ebp 4/r32/esp + 2356 # setup + 2357 (clear-stream _test-input-stream) + 2358 (clear-stream $_test-input-buffered-file->buffer) + 2359 (clear-stream _test-output-stream) + 2360 (clear-stream $_test-output-buffered-file->buffer) + 2361 # + 2362 (write _test-input-stream "fn foo {\n") + 2363 (write _test-input-stream " var a: (array int 3)\n") + 2364 (write _test-input-stream " var b/eax: int <- length a\n") + 2365 (write _test-input-stream "}\n") + 2366 # convert + 2367 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2368 (flush _test-output-buffered-file) + 2369 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2375 # check output + 2376 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-on-stack/0") + 2377 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-on-stack/1") + 2378 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-on-stack/2") + 2379 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-on-stack/3") + 2380 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-on-stack/4") + 2381 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-on-stack/5") + 2382 # define x + 2383 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-length-of-array-on-stack/6") + 2384 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7") + 2385 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8") + 2386 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9") + 2387 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/10") + 2388 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/11") + 2389 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/12") + 2390 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/13") + 2391 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/14") + 2392 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/15") + 2393 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/16") + 2394 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/17") + 2395 # . epilogue + 2396 89/<- %esp 5/r32/ebp + 2397 5d/pop-to-ebp + 2398 c3/return + 2399 + 2400 test-convert-index-into-array: + 2401 # . prologue + 2402 55/push-ebp + 2403 89/<- %ebp 4/r32/esp + 2404 # setup + 2405 (clear-stream _test-input-stream) + 2406 (clear-stream $_test-input-buffered-file->buffer) + 2407 (clear-stream _test-output-stream) + 2408 (clear-stream $_test-output-buffered-file->buffer) + 2409 # + 2410 (write _test-input-stream "fn foo {\n") + 2411 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2412 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 2413 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 2414 (write _test-input-stream "}\n") + 2415 # convert + 2416 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2417 (flush _test-output-buffered-file) + 2418 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2424 # check output + 2425 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array/0") + 2426 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array/1") + 2427 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array/2") + 2428 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array/3") + 2429 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array/4") + 2430 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array/5") + 2431 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array/6") + 2432 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array/7") + 2433 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8") + 2434 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9") + 2435 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11") + 2436 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/13") + 2437 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/14") + 2438 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/15") + 2439 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/16") + 2440 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/17") + 2441 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/18") + 2442 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/19") + 2443 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/20") 2444 # . epilogue 2445 89/<- %esp 5/r32/ebp 2446 5d/pop-to-ebp 2447 c3/return 2448 - 2449 test-convert-index-into-array-on-stack: + 2449 test-convert-index-into-array-with-literal: 2450 # . prologue 2451 55/push-ebp 2452 89/<- %ebp 4/r32/esp @@ -2324,8901 +2324,8970 @@ if ('onhashchange' in window) { 2457 (clear-stream $_test-output-buffered-file->buffer) 2458 # 2459 (write _test-input-stream "fn foo {\n") - 2460 (write _test-input-stream " var arr: (array int 3)\n") - 2461 (write _test-input-stream " var idx/eax: int <- copy 2\n") - 2462 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2463 (write _test-input-stream "}\n") - 2464 # convert - 2465 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2466 (flush _test-output-buffered-file) - 2467 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2473 # check output - 2474 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") - 2475 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") - 2476 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") - 2477 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") - 2478 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") - 2479 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") - 2480 # var arr - 2481 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") - 2482 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") - 2483 # var idx - 2484 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") - 2485 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") - 2486 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc - 2487 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/10") - 2488 # reclaim idx - 2489 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/11") - 2490 # reclaim arr - 2491 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/12") - 2492 # - 2493 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/13") - 2494 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/14") - 2495 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/15") - 2496 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/16") - 2497 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/17") - 2498 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/18") - 2499 # . epilogue - 2500 89/<- %esp 5/r32/ebp - 2501 5d/pop-to-ebp - 2502 c3/return - 2503 - 2504 test-convert-index-into-array-on-stack-with-literal: - 2505 # . prologue - 2506 55/push-ebp - 2507 89/<- %ebp 4/r32/esp - 2508 # setup - 2509 (clear-stream _test-input-stream) - 2510 (clear-stream $_test-input-buffered-file->buffer) - 2511 (clear-stream _test-output-stream) - 2512 (clear-stream $_test-output-buffered-file->buffer) - 2513 # - 2514 (write _test-input-stream "fn foo {\n") - 2515 (write _test-input-stream " var arr: (array int 3)\n") - 2516 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 2517 (write _test-input-stream "}\n") - 2518 # convert - 2519 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2520 (flush _test-output-buffered-file) - 2521 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2527 # check output - 2528 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") - 2529 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") - 2530 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") - 2531 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") - 2532 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") - 2533 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") - 2534 # var arr - 2535 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") - 2536 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") - 2537 # var x - 2538 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") - 2539 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 - 2540 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/9") - 2541 # reclaim x - 2542 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/10") - 2543 # reclaim arr - 2544 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/11") - 2545 # - 2546 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/12") - 2547 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/13") - 2548 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/14") - 2549 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/15") - 2550 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") - 2551 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/17") - 2552 # . epilogue - 2553 89/<- %esp 5/r32/ebp - 2554 5d/pop-to-ebp - 2555 c3/return - 2556 - 2557 test-convert-index-into-array-using-offset: - 2558 # . prologue - 2559 55/push-ebp - 2560 89/<- %ebp 4/r32/esp - 2561 # setup - 2562 (clear-stream _test-input-stream) - 2563 (clear-stream $_test-input-buffered-file->buffer) - 2564 (clear-stream _test-output-stream) - 2565 (clear-stream $_test-output-buffered-file->buffer) - 2566 # - 2567 (write _test-input-stream "fn foo {\n") - 2568 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2569 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2570 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 2571 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 2572 (write _test-input-stream "}\n") - 2573 # convert - 2574 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2575 (flush _test-output-buffered-file) - 2576 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2582 # check output - 2583 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") - 2584 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") - 2585 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") - 2586 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") - 2587 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") - 2588 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") - 2589 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") - 2590 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") - 2591 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") - 2592 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") - 2593 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 %ecx 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") - 2594 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/11") - 2595 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/12") - 2596 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/13") - 2597 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/14") - 2598 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/15") - 2599 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/16") - 2600 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/17") - 2601 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/18") - 2602 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/19") - 2603 # . epilogue - 2604 89/<- %esp 5/r32/ebp - 2605 5d/pop-to-ebp - 2606 c3/return - 2607 - 2608 test-convert-index-into-array-using-offset-on-stack: - 2609 # . prologue - 2610 55/push-ebp - 2611 89/<- %ebp 4/r32/esp - 2612 # setup - 2613 (clear-stream _test-input-stream) - 2614 (clear-stream $_test-input-buffered-file->buffer) - 2615 (clear-stream _test-output-stream) - 2616 (clear-stream $_test-output-buffered-file->buffer) - 2617 # - 2618 (write _test-input-stream "fn foo {\n") - 2619 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 2620 (write _test-input-stream " var idx: int\n") - 2621 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 2622 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 2623 (write _test-input-stream "}\n") - 2624 # convert - 2625 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2626 (flush _test-output-buffered-file) - 2627 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2633 # check output - 2634 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") - 2635 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") - 2636 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") - 2637 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") - 2638 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") - 2639 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") - 2640 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") - 2641 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") - 2642 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") - 2643 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") - 2644 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 *(ebp+0xfffffff8) 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") - 2645 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/11") - 2646 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/12") - 2647 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/13") - 2648 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/14") - 2649 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/15") - 2650 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/16") - 2651 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/17") - 2652 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/18") - 2653 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/19") - 2654 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/20") - 2655 # . epilogue - 2656 89/<- %esp 5/r32/ebp - 2657 5d/pop-to-ebp - 2658 c3/return - 2659 - 2660 test-convert-function-and-type-definition: - 2661 # . prologue - 2662 55/push-ebp - 2663 89/<- %ebp 4/r32/esp - 2664 # setup - 2665 (clear-stream _test-input-stream) - 2666 (clear-stream $_test-input-buffered-file->buffer) - 2667 (clear-stream _test-output-stream) - 2668 (clear-stream $_test-output-buffered-file->buffer) - 2669 # - 2670 (write _test-input-stream "fn foo a: (addr t) {\n") - 2671 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") - 2672 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") - 2673 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") - 2674 (write _test-input-stream "}\n") - 2675 (write _test-input-stream "type t {\n") - 2676 (write _test-input-stream " x: int\n") - 2677 (write _test-input-stream " y: int\n") - 2678 (write _test-input-stream "}\n") - 2679 # convert - 2680 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2681 (flush _test-output-buffered-file) - 2682 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2688 # check output - 2689 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") - 2690 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") - 2691 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") - 2692 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") - 2693 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") - 2694 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") - 2695 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") - 2696 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") - 2697 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") - 2698 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") - 2699 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") - 2700 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") - 2701 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") - 2702 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") - 2703 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") - 2704 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") - 2705 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") - 2706 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") - 2707 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") - 2708 # . epilogue - 2709 89/<- %esp 5/r32/ebp - 2710 5d/pop-to-ebp - 2711 c3/return - 2712 - 2713 test-convert-function-with-local-var-with-user-defined-type: - 2714 # . prologue - 2715 55/push-ebp - 2716 89/<- %ebp 4/r32/esp - 2717 # setup - 2718 (clear-stream _test-input-stream) - 2719 (clear-stream $_test-input-buffered-file->buffer) - 2720 (clear-stream _test-output-stream) - 2721 (clear-stream $_test-output-buffered-file->buffer) - 2722 # - 2723 (write _test-input-stream "fn foo {\n") - 2724 (write _test-input-stream " var a: t\n") - 2725 (write _test-input-stream "}\n") - 2726 (write _test-input-stream "type t {\n") - 2727 (write _test-input-stream " x: int\n") - 2728 (write _test-input-stream " y: int\n") - 2729 (write _test-input-stream "}\n") - 2730 # convert - 2731 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2732 (flush _test-output-buffered-file) - 2733 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2739 # check output - 2740 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") - 2741 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") - 2742 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") - 2743 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") - 2744 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") - 2745 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") - 2746 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") - 2747 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") - 2748 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") - 2749 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") - 2750 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") - 2751 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") - 2752 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") - 2753 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") - 2754 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") - 2755 # . epilogue - 2756 89/<- %esp 5/r32/ebp - 2757 5d/pop-to-ebp - 2758 c3/return - 2759 - 2760 test-convert-get-of-type-on-stack: - 2761 # . prologue - 2762 55/push-ebp - 2763 89/<- %ebp 4/r32/esp - 2764 # setup - 2765 (clear-stream _test-input-stream) - 2766 (clear-stream $_test-input-buffered-file->buffer) - 2767 (clear-stream _test-output-stream) - 2768 (clear-stream $_test-output-buffered-file->buffer) - 2769 # - 2770 (write _test-input-stream "fn foo {\n") - 2771 (write _test-input-stream " var a: t\n") - 2772 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 2773 (write _test-input-stream "}\n") - 2774 (write _test-input-stream "type t {\n") - 2775 (write _test-input-stream " x: int\n") - 2776 (write _test-input-stream " y: int\n") - 2777 (write _test-input-stream "}\n") - 2778 # convert - 2779 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2780 (flush _test-output-buffered-file) - 2781 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2787 # check output - 2788 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-of-type-on-stack/0") - 2789 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-of-type-on-stack/1") - 2790 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-of-type-on-stack/2") - 2791 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-of-type-on-stack/3") - 2792 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-of-type-on-stack/4") - 2793 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-of-type-on-stack/5") - 2794 # var a - 2795 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/6") - 2796 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/7") - 2797 # var c - 2798 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-of-type-on-stack/8") - 2799 # get - 2800 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-of-type-on-stack/9") - 2801 # reclaim c - 2802 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-of-type-on-stack/10") - 2803 # reclaim a - 2804 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-of-type-on-stack/11") - 2805 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-of-type-on-stack/12") - 2806 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-of-type-on-stack/13") - 2807 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-of-type-on-stack/14") - 2808 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-of-type-on-stack/15") - 2809 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-of-type-on-stack/16") - 2810 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-of-type-on-stack/17") - 2811 # . epilogue - 2812 89/<- %esp 5/r32/ebp - 2813 5d/pop-to-ebp - 2814 c3/return - 2815 - 2816 test-convert-array-of-user-defined-types: - 2817 # . prologue - 2818 55/push-ebp - 2819 89/<- %ebp 4/r32/esp - 2820 # setup - 2821 (clear-stream _test-input-stream) - 2822 (clear-stream $_test-input-buffered-file->buffer) - 2823 (clear-stream _test-output-stream) - 2824 (clear-stream $_test-output-buffered-file->buffer) - 2825 # - 2826 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 - 2827 (write _test-input-stream " x: int\n") - 2828 (write _test-input-stream " y: int\n") - 2829 (write _test-input-stream "}\n") - 2830 (write _test-input-stream "fn foo {\n") - 2831 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") - 2832 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 2833 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 2834 (write _test-input-stream "}\n") - 2835 # convert - 2836 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 2837 (flush _test-output-buffered-file) - 2838 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 2844 # check output - 2845 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") - 2846 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") - 2847 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") - 2848 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") - 2849 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") - 2850 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") - 2851 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") - 2852 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") - 2853 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") - 2854 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") - 2855 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11") - 2856 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/13") - 2857 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/14") - 2858 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/15") - 2859 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/16") - 2860 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/17") - 2861 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/18") - 2862 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/19") - 2863 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/20") - 2864 # . epilogue - 2865 89/<- %esp 5/r32/ebp - 2866 5d/pop-to-ebp - 2867 c3/return - 2868 - 2869 ####################################################### - 2870 # Parsing - 2871 ####################################################### - 2872 - 2873 parse-mu: # in: (addr buffered-file) - 2874 # pseudocode - 2875 # var curr-function: (addr (handle function)) = Program->functions - 2876 # var curr-type: (addr (handle typeinfo)) = Program->types - 2877 # var line: (stream byte 512) - 2878 # var word-slice: slice - 2879 # while true # line loop - 2880 # clear-stream(line) - 2881 # read-line-buffered(in, line) - 2882 # if (line->write == 0) break # end of file - 2883 # word-slice = next-mu-token(line) - 2884 # if slice-empty?(word-slice) # end of line - 2885 # continue - 2886 # else if slice-starts-with?(word-slice, "#") # comment - 2887 # continue # end of line - 2888 # else if slice-equal?(word-slice, "fn") - 2889 # var new-function: (handle function) = allocate(function) - 2890 # var vars: (stack (addr var) 256) - 2891 # populate-mu-function-header(in, new-function, vars) - 2892 # populate-mu-function-body(in, new-function, vars) - 2893 # assert(vars->top == 0) - 2894 # *curr-function = new-function - 2895 # curr-function = &new-function->next - 2896 # else if slice-equal?(word-slice, "type") - 2897 # word-slice = next-mu-token(line) - 2898 # type-id = pos-or-insert-slice(Type-id, word-slice) - 2899 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) - 2900 # assert(next-word(line) == "{") - 2901 # populate-mu-type(in, new-type) - 2902 # else - 2903 # abort() - 2904 # - 2905 # . prologue - 2906 55/push-ebp - 2907 89/<- %ebp 4/r32/esp - 2908 # . save registers - 2909 50/push-eax - 2910 51/push-ecx - 2911 52/push-edx - 2912 53/push-ebx - 2913 56/push-esi - 2914 57/push-edi - 2915 # var line/ecx: (stream byte 512) - 2916 81 5/subop/subtract %esp 0x200/imm32 - 2917 68/push 0x200/imm32/length - 2918 68/push 0/imm32/read - 2919 68/push 0/imm32/write - 2920 89/<- %ecx 4/r32/esp - 2921 # var word-slice/edx: slice - 2922 68/push 0/imm32/end - 2923 68/push 0/imm32/start - 2924 89/<- %edx 4/r32/esp - 2925 # var curr-function/edi: (addr (handle function)) - 2926 bf/copy-to-edi _Program-functions/imm32 - 2927 # var curr-type/esi: (addr (handle typeinfo)) - 2928 be/copy-to-esi _Program-types/imm32 - 2929 # var vars/ebx: (stack (addr var) 256) - 2930 81 5/subop/subtract %esp 0x400/imm32 - 2931 68/push 0x400/imm32/length - 2932 68/push 0/imm32/top - 2933 89/<- %ebx 4/r32/esp - 2934 { - 2935 $parse-mu:line-loop: - 2936 (clear-stream %ecx) - 2937 (read-line-buffered *(ebp+8) %ecx) - 2938 # if (line->write == 0) break - 2939 81 7/subop/compare *ecx 0/imm32 - 2940 0f 84/jump-if-= break/disp32 - 2941 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ - 2947 (next-mu-token %ecx %edx) - 2948 # if slice-empty?(word-slice) continue - 2949 (slice-empty? %edx) - 2950 3d/compare-eax-and 0/imm32/false - 2951 0f 85/jump-if-!= loop/disp32 - 2952 # if (*word-slice->start == "#") continue - 2953 # . eax = *word-slice->start - 2954 8b/-> *edx 0/r32/eax - 2955 8a/copy-byte *eax 0/r32/AL - 2956 81 4/subop/and %eax 0xff/imm32 - 2957 # . if (eax == '#') continue - 2958 3d/compare-eax-and 0x23/imm32/hash - 2959 0f 84/jump-if-= loop/disp32 - 2960 # if (slice-equal?(word-slice, "fn")) parse a function - 2961 { - 2962 $parse-mu:fn: - 2963 (slice-equal? %edx "fn") - 2964 3d/compare-eax-and 0/imm32/false - 2965 0f 84/jump-if-= break/disp32 - 2966 # var new-function/eax: (handle function) = populate-mu-function(line, in, vars) - 2967 (allocate Heap *Function-size) # => eax - 2968 (zero-out %eax *Function-size) - 2969 (clear-stack %ebx) - 2970 (populate-mu-function-header %ecx %eax %ebx) - 2971 (populate-mu-function-body *(ebp+8) %eax %ebx) - 2972 # *curr-function = new-function - 2973 89/<- *edi 0/r32/eax - 2974 # curr-function = &new-function->next - 2975 8d/address-> *(eax+0x14) 7/r32/edi # Function-next - 2976 e9/jump $parse-mu:line-loop/disp32 - 2977 } - 2978 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition - 2979 { - 2980 $parse-mu:type: - 2981 (slice-equal? %edx "type") - 2982 3d/compare-eax-and 0/imm32 - 2983 0f 84/jump-if-= break/disp32 - 2984 (next-mu-token %ecx %edx) - 2985 # var type-id/eax: int - 2986 (pos-or-insert-slice Type-id %edx) # => eax - 2987 # var new-type/eax: (handle typeinfo) - 2988 (find-or-create-typeinfo %eax) # => eax - 2989 # TODO: ensure that 'line' has nothing else but '{' - 2990 (populate-mu-type *(ebp+8) %eax) # => eax - 2991 e9/jump $parse-mu:line-loop/disp32 - 2992 } - 2993 # otherwise abort - 2994 e9/jump $parse-mu:error1/disp32 - 2995 } # end line loop - 2996 $parse-mu:end: - 2997 # . reclaim locals - 2998 81 0/subop/add %esp 0x630/imm32 - 2999 # . restore registers - 3000 5f/pop-to-edi - 3001 5e/pop-to-esi - 3002 5b/pop-to-ebx - 3003 5a/pop-to-edx - 3004 59/pop-to-ecx - 3005 58/pop-to-eax - 3006 # . epilogue - 3007 89/<- %esp 5/r32/ebp - 3008 5d/pop-to-ebp - 3009 c3/return - 3010 - 3011 $parse-mu:error1: - 3012 # error("unexpected top-level command: " word-slice "\n") - 3013 (write-buffered Stderr "unexpected top-level command: ") - 3014 (write-slice-buffered Stderr %edx) - 3015 (write-buffered Stderr "\n") - 3016 (flush Stderr) - 3017 # . syscall(exit, 1) - 3018 bb/copy-to-ebx 1/imm32 - 3019 b8/copy-to-eax 1/imm32/exit - 3020 cd/syscall 0x80/imm8 - 3021 # never gets here - 3022 - 3023 $parse-mu:error2: - 3024 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") - 3025 (print-int32-buffered Stderr *ebx) - 3026 (write-buffered Stderr " vars not reclaimed after fn '") - 3027 (write-slice-buffered Stderr *eax) # Function-name - 3028 (write-buffered Stderr "'\n") - 3029 (flush Stderr) - 3030 # . syscall(exit, 1) - 3031 bb/copy-to-ebx 1/imm32 - 3032 b8/copy-to-eax 1/imm32/exit - 3033 cd/syscall 0x80/imm8 - 3034 # never gets here - 3035 - 3036 # scenarios considered: - 3037 # ✗ fn foo # no block - 3038 # ✓ fn foo { - 3039 # ✗ fn foo { { - 3040 # ✗ fn foo { } - 3041 # ✗ fn foo { } { - 3042 # ✗ fn foo x { - 3043 # ✗ fn foo x: { - 3044 # ✓ fn foo x: int { - 3045 # ✓ fn foo x: int { - 3046 # ✓ fn foo x: int -> y/eax: int { - 3047 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) - 3048 # pseudocode: - 3049 # var name: slice - 3050 # next-mu-token(first-line, name) - 3051 # assert(name not in '{' '}' '->') - 3052 # out->name = slice-to-string(name) - 3053 # ## inouts - 3054 # while true - 3055 # ## name - 3056 # name = next-mu-token(first-line) - 3057 # if (name == '{') goto done - 3058 # if (name == '->') break - 3059 # assert(name != '}') - 3060 # var v: (handle var) = parse-var-with-type(name, first-line) - 3061 # assert(v->register == null) - 3062 # # v->block-depth is implicitly 0 - 3063 # out->inouts = append(out->inouts, v) - 3064 # push(vars, v) - 3065 # ## outputs - 3066 # while true - 3067 # ## name - 3068 # name = next-mu-token(first-line) - 3069 # assert(name not in '{' '}' '->') - 3070 # var v: (handle var) = parse-var-with-type(name, first-line) - 3071 # assert(v->register != null) - 3072 # out->outputs = append(out->outputs, v) - 3073 # done: - 3074 # - 3075 # . prologue - 3076 55/push-ebp - 3077 89/<- %ebp 4/r32/esp - 3078 # . save registers - 3079 50/push-eax - 3080 51/push-ecx - 3081 52/push-edx - 3082 53/push-ebx - 3083 57/push-edi - 3084 # edi = out - 3085 8b/-> *(ebp+0xc) 7/r32/edi - 3086 # var word-slice/ecx: slice - 3087 68/push 0/imm32/end - 3088 68/push 0/imm32/start - 3089 89/<- %ecx 4/r32/esp - 3090 # read function name - 3091 (next-mu-token *(ebp+8) %ecx) - 3092 # error checking - 3093 # TODO: error if name starts with 'break' or 'loop' - 3094 # if (word-slice == '{') abort - 3095 (slice-equal? %ecx "{") # => eax - 3096 3d/compare-eax-and 0/imm32/false - 3097 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3098 # if (word-slice == '->') abort - 3099 (slice-equal? %ecx "->") # => eax - 3100 3d/compare-eax-and 0/imm32/false - 3101 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3102 # if (word-slice == '}') abort - 3103 (slice-equal? %ecx "}") # => eax - 3104 3d/compare-eax-and 0/imm32/false - 3105 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3106 # save function name - 3107 (slice-to-string Heap %ecx) # => eax - 3108 89/<- *edi 0/r32/eax # Function-name - 3109 # initialize default subx-name as well - 3110 89/<- *(edi+4) 0/r32/eax # Function-subx-name - 3111 # save function inouts - 3112 { - 3113 $populate-mu-function-header:check-for-inout: - 3114 (next-mu-token *(ebp+8) %ecx) - 3115 # if (word-slice == '{') goto done - 3116 (slice-equal? %ecx "{") # => eax - 3117 3d/compare-eax-and 0/imm32/false - 3118 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 - 3119 # if (word-slice == '->') break - 3120 (slice-equal? %ecx "->") # => eax - 3121 3d/compare-eax-and 0/imm32/false - 3122 0f 85/jump-if-!= break/disp32 - 3123 # if (word-slice == '}') abort - 3124 (slice-equal? %ecx "}") # => eax - 3125 3d/compare-eax-and 0/imm32/false - 3126 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3127 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) - 3128 (parse-var-with-type %ecx *(ebp+8)) # => eax - 3129 89/<- %ebx 0/r32/eax - 3130 # assert(v->register == null) - 3131 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 3132 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 - 3133 # v->block-depth is implicitly 0 - 3134 # - 3135 # out->inouts = append(out->inouts, v) - 3136 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax - 3137 89/<- *(edi+8) 0/r32/eax # Function-inouts - 3138 # push(vars, v) - 3139 (push *(ebp+0x10) %ebx) - 3140 # - 3141 e9/jump loop/disp32 - 3142 } - 3143 # save function outputs - 3144 { - 3145 $populate-mu-function-header:check-for-out: - 3146 (next-mu-token *(ebp+8) %ecx) - 3147 # if (word-slice == '{') break - 3148 (slice-equal? %ecx "{") # => eax - 3149 3d/compare-eax-and 0/imm32/false - 3150 0f 85/jump-if-!= break/disp32 - 3151 # if (word-slice == '->') abort - 3152 (slice-equal? %ecx "->") # => eax - 3153 3d/compare-eax-and 0/imm32/false - 3154 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3155 # if (word-slice == '}') abort - 3156 (slice-equal? %ecx "}") # => eax - 3157 3d/compare-eax-and 0/imm32/false - 3158 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 - 3159 # - 3160 (parse-var-with-type %ecx *(ebp+8)) # => eax - 3161 89/<- %ebx 0/r32/eax - 3162 # assert(var->register != null) - 3163 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 3164 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 - 3165 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax - 3166 89/<- *(edi+0xc) 0/r32/eax # Function-outputs - 3167 e9/jump loop/disp32 - 3168 } - 3169 $populate-mu-function-header:done: - 3170 (check-no-tokens-left *(ebp+8)) - 3171 $populate-mu-function-header:end: - 3172 # . reclaim locals - 3173 81 0/subop/add %esp 8/imm32 - 3174 # . restore registers - 3175 5f/pop-to-edi - 3176 5b/pop-to-ebx - 3177 5a/pop-to-edx - 3178 59/pop-to-ecx - 3179 58/pop-to-eax - 3180 # . epilogue - 3181 89/<- %esp 5/r32/ebp - 3182 5d/pop-to-ebp - 3183 c3/return - 3184 - 3185 $populate-mu-function-header:error1: - 3186 # error("function header not in form 'fn <name> {'") - 3187 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") - 3188 (flush Stderr) - 3189 (rewind-stream *(ebp+8)) - 3190 (write-stream 2 *(ebp+8)) - 3191 (write-buffered Stderr "'\n") - 3192 (flush Stderr) - 3193 # . syscall(exit, 1) - 3194 bb/copy-to-ebx 1/imm32 - 3195 b8/copy-to-eax 1/imm32/exit - 3196 cd/syscall 0x80/imm8 - 3197 # never gets here - 3198 - 3199 $populate-mu-function-header:error2: - 3200 # error("function input '" var "' cannot be in a register") - 3201 (write-buffered Stderr "function input '") - 3202 (write-buffered Stderr *ebx) # Var-name - 3203 (write-buffered Stderr "' cannot be in a register") - 3204 (flush Stderr) - 3205 # . syscall(exit, 1) - 3206 bb/copy-to-ebx 1/imm32 - 3207 b8/copy-to-eax 1/imm32/exit - 3208 cd/syscall 0x80/imm8 - 3209 # never gets here - 3210 - 3211 $populate-mu-function-header:error3: - 3212 # error("function input '" var "' must be in a register") - 3213 (write-buffered Stderr "function input '") - 3214 (write-buffered Stderr *eax) # Var-name - 3215 (write-buffered Stderr " must be in a register'") - 3216 (flush Stderr) - 3217 (rewind-stream *(ebp+8)) - 3218 (write-stream 2 *(ebp+8)) - 3219 (write-buffered Stderr "'\n") - 3220 (flush Stderr) - 3221 # . syscall(exit, 1) - 3222 bb/copy-to-ebx 1/imm32 - 3223 b8/copy-to-eax 1/imm32/exit - 3224 cd/syscall 0x80/imm8 - 3225 # never gets here - 3226 - 3227 test-function-header-with-arg: - 3228 # . prologue - 3229 55/push-ebp - 3230 89/<- %ebp 4/r32/esp - 3231 # setup - 3232 (clear-stream _test-input-stream) - 3233 (write _test-input-stream "foo n: int {\n") - 3234 # var result/ecx: function - 3235 2b/subtract-> *Function-size 4/r32/esp - 3236 89/<- %ecx 4/r32/esp - 3237 (zero-out %ecx *Function-size) - 3238 # var vars/ebx: (stack (addr var) 16) - 3239 81 5/subop/subtract %esp 0x10/imm32 - 3240 68/push 0x10/imm32/length - 3241 68/push 0/imm32/top - 3242 89/<- %ebx 4/r32/esp - 3243 # convert - 3244 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3245 # check result - 3246 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name - 3247 # edx: (handle list var) = result->inouts - 3248 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3249 # ebx: (handle var) = result->inouts->value - 3250 8b/-> *edx 3/r32/ebx # List-value - 3251 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name - 3252 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3253 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left - 3254 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right - 3255 # . epilogue - 3256 89/<- %esp 5/r32/ebp - 3257 5d/pop-to-ebp - 3258 c3/return - 3259 - 3260 test-function-header-with-multiple-args: - 3261 # . prologue - 3262 55/push-ebp - 3263 89/<- %ebp 4/r32/esp - 3264 # setup - 3265 (clear-stream _test-input-stream) - 3266 (write _test-input-stream "foo a: int, b: int c: int {\n") - 3267 # result/ecx: (handle function) - 3268 2b/subtract-> *Function-size 4/r32/esp - 3269 89/<- %ecx 4/r32/esp - 3270 (zero-out %ecx *Function-size) - 3271 # var vars/ebx: (stack (addr var) 16) - 3272 81 5/subop/subtract %esp 0x10/imm32 - 3273 68/push 0x10/imm32/length - 3274 68/push 0/imm32/top - 3275 89/<- %ebx 4/r32/esp - 3276 # convert - 3277 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3278 # check result - 3279 (check-strings-equal *ecx "foo") # Function-name - 3280 # edx: (handle list var) = result->inouts - 3281 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3282 $test-function-header-with-multiple-args:inout0: - 3283 # ebx: (handle var) = result->inouts->value - 3284 8b/-> *edx 3/r32/ebx # List-value - 3285 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name - 3286 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3287 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left - 3288 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right - 3289 # edx = result->inouts->next - 3290 8b/-> *(edx+4) 2/r32/edx # List-next - 3291 $test-function-header-with-multiple-args:inout1: - 3292 # ebx = result->inouts->next->value - 3293 8b/-> *edx 3/r32/ebx # List-value - 3294 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name - 3295 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3296 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left - 3297 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right - 3298 # edx = result->inouts->next->next - 3299 8b/-> *(edx+4) 2/r32/edx # List-next - 3300 $test-function-header-with-multiple-args:inout2: - 3301 # ebx = result->inouts->next->next->value - 3302 8b/-> *edx 3/r32/ebx # List-value - 3303 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name - 3304 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3305 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left - 3306 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right - 3307 # . epilogue - 3308 89/<- %esp 5/r32/ebp - 3309 5d/pop-to-ebp - 3310 c3/return - 3311 - 3312 test-function-with-multiple-args-and-outputs: - 3313 # . prologue - 3314 55/push-ebp - 3315 89/<- %ebp 4/r32/esp - 3316 # setup - 3317 (clear-stream _test-input-stream) - 3318 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") - 3319 # result/ecx: (handle function) - 3320 2b/subtract-> *Function-size 4/r32/esp - 3321 89/<- %ecx 4/r32/esp - 3322 (zero-out %ecx *Function-size) - 3323 # var vars/ebx: (stack (addr var) 16) - 3324 81 5/subop/subtract %esp 0x10/imm32 - 3325 68/push 0x10/imm32/length - 3326 68/push 0/imm32/top - 3327 89/<- %ebx 4/r32/esp - 3328 # convert - 3329 (populate-mu-function-header _test-input-stream %ecx %ebx) - 3330 # check result - 3331 (check-strings-equal *ecx "foo") # Function-name - 3332 # edx: (handle list var) = result->inouts - 3333 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - 3334 # ebx: (handle var) = result->inouts->value - 3335 8b/-> *edx 3/r32/ebx # List-value - 3336 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name - 3337 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3338 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left - 3339 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right - 3340 # edx = result->inouts->next - 3341 8b/-> *(edx+4) 2/r32/edx # List-next - 3342 # ebx = result->inouts->next->value - 3343 8b/-> *edx 3/r32/ebx # List-value - 3344 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name - 3345 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3346 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left - 3347 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right - 3348 # edx = result->inouts->next->next - 3349 8b/-> *(edx+4) 2/r32/edx # List-next - 3350 # ebx = result->inouts->next->next->value - 3351 8b/-> *edx 3/r32/ebx # List-value - 3352 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name - 3353 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3354 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left - 3355 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right - 3356 # edx: (handle list var) = result->outputs - 3357 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs - 3358 # ebx: (handle var) = result->outputs->value - 3359 8b/-> *edx 3/r32/ebx # List-value - 3360 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name - 3361 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register - 3362 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3363 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left - 3364 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right - 3365 # edx = result->outputs->next - 3366 8b/-> *(edx+4) 2/r32/edx # List-next - 3367 # ebx = result->outputs->next->value - 3368 8b/-> *edx 3/r32/ebx # List-value - 3369 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name - 3370 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register - 3371 8b/-> *(ebx+4) 3/r32/ebx # Var-type - 3372 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left - 3373 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right - 3374 # . epilogue - 3375 89/<- %esp 5/r32/ebp - 3376 5d/pop-to-ebp - 3377 c3/return - 3378 - 3379 # format for variables with types - 3380 # x: int - 3381 # x: int, - 3382 # x/eax: int - 3383 # x/eax: int, - 3384 # ignores at most one trailing comma - 3385 # WARNING: modifies name - 3386 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) - 3387 # pseudocode: - 3388 # var s: slice - 3389 # if (!slice-ends-with(name, ":")) - 3390 # abort - 3391 # --name->end to skip ':' - 3392 # next-token-from-slice(name->start, name->end, '/', s) - 3393 # result = new-var-from-slice(s) - 3394 # ## register - 3395 # next-token-from-slice(s->end, name->end, '/', s) - 3396 # if (!slice-empty?(s)) - 3397 # v->register = slice-to-string(s) - 3398 # ## type - 3399 # var type: (handle tree type-id) = parse-type(first-line) - 3400 # v->type = type - 3401 # return v - 3402 # - 3403 # . prologue - 3404 55/push-ebp - 3405 89/<- %ebp 4/r32/esp - 3406 # . save registers - 3407 51/push-ecx - 3408 52/push-edx - 3409 53/push-ebx - 3410 56/push-esi - 3411 57/push-edi - 3412 # esi = name - 3413 8b/-> *(ebp+8) 6/r32/esi - 3414 # if (!slice-ends-with?(name, ":")) abort - 3415 8b/-> *(esi+4) 1/r32/ecx # Slice-end - 3416 49/decrement-ecx - 3417 8a/copy-byte *ecx 1/r32/CL - 3418 81 4/subop/and %ecx 0xff/imm32 - 3419 81 7/subop/compare %ecx 0x3a/imm32/colon - 3420 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 - 3421 # --name->end to skip ':' - 3422 ff 1/subop/decrement *(esi+4) - 3423 # var s/ecx: slice - 3424 68/push 0/imm32/end - 3425 68/push 0/imm32/start - 3426 89/<- %ecx 4/r32/esp - 3427 $parse-var-with-type:parse-name: - 3428 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' - 3429 $parse-var-with-type:create-var: - 3430 # edi = new-var-from-slice(s) - 3431 (new-var-from-slice Heap %ecx) # => eax - 3432 89/<- %edi 0/r32/eax - 3433 # save v->register - 3434 $parse-var-with-type:save-register: - 3435 # s = next-token(...) - 3436 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' - 3437 # if (!slice-empty?(s)) v->register = slice-to-string(s) - 3438 { - 3439 $parse-var-with-type:write-register: - 3440 (slice-empty? %ecx) # => eax - 3441 3d/compare-eax-and 0/imm32/false - 3442 75/jump-if-!= break/disp8 - 3443 (slice-to-string Heap %ecx) - 3444 89/<- *(edi+0x10) 0/r32/eax # Var-register - 3445 } - 3446 $parse-var-with-type:save-type: - 3447 (parse-type Heap *(ebp+0xc)) # => eax - 3448 #? (write-buffered Stderr "saving to var ") - 3449 #? (print-int32-buffered Stderr %edi) - 3450 #? (write-buffered Stderr Newline) - 3451 #? (flush Stderr) - 3452 89/<- *(edi+4) 0/r32/eax # Var-type - 3453 $parse-var-with-type:end: - 3454 # return result - 3455 89/<- %eax 7/r32/edi - 3456 # . reclaim locals - 3457 81 0/subop/add %esp 8/imm32 - 3458 # . restore registers - 3459 5f/pop-to-edi - 3460 5e/pop-to-esi - 3461 5b/pop-to-ebx - 3462 5a/pop-to-edx - 3463 59/pop-to-ecx - 3464 # . epilogue - 3465 89/<- %esp 5/r32/ebp - 3466 5d/pop-to-ebp - 3467 c3/return - 3468 - 3469 $parse-var-with-type:abort: - 3470 # error("var should have form 'name: type' in '" line "'\n") - 3471 (write-buffered Stderr "var should have form 'name: type' in '") - 3472 (flush Stderr) - 3473 (rewind-stream *(ebp+0xc)) - 3474 (write-stream 2 *(ebp+0xc)) - 3475 (write-buffered Stderr "'\n") - 3476 (flush Stderr) - 3477 # . syscall(exit, 1) - 3478 bb/copy-to-ebx 1/imm32 - 3479 b8/copy-to-eax 1/imm32/exit - 3480 cd/syscall 0x80/imm8 - 3481 # never gets here - 3482 - 3483 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) - 3484 # pseudocode: - 3485 # var s: slice = next-mu-token(in) - 3486 # assert s != "" - 3487 # assert s != "->" - 3488 # assert s != "{" - 3489 # assert s != "}" - 3490 # if s == ")" - 3491 # return 0 - 3492 # result = allocate(Tree) - 3493 # zero-out(result, *Tree-size) - 3494 # if s != "(" - 3495 # result->left = pos-or-insert-slice(Type-id, s) - 3496 # return - 3497 # result->left = parse-type(ad, in) - 3498 # result->right = parse-type-tree(ad, in) - 3499 # - 3500 # . prologue - 3501 55/push-ebp - 3502 89/<- %ebp 4/r32/esp - 3503 # . save registers - 3504 51/push-ecx - 3505 52/push-edx - 3506 # var s/ecx: slice - 3507 68/push 0/imm32 - 3508 68/push 0/imm32 - 3509 89/<- %ecx 4/r32/esp - 3510 # s = next-mu-token(in) - 3511 (next-mu-token *(ebp+0xc) %ecx) - 3512 #? (write-buffered Stderr "tok: ") - 3513 #? (write-slice-buffered Stderr %ecx) - 3514 #? (write-buffered Stderr "$\n") - 3515 #? (flush Stderr) - 3516 # assert s != "" - 3517 (slice-equal? %ecx "") - 3518 3d/compare-eax-and 0/imm32/false - 3519 0f 85/jump-if-!= $parse-type:abort/disp32 - 3520 # assert s != "{" - 3521 (slice-equal? %ecx "{") - 3522 3d/compare-eax-and 0/imm32/false - 3523 0f 85/jump-if-!= $parse-type:abort/disp32 - 3524 # assert s != "}" - 3525 (slice-equal? %ecx "}") - 3526 3d/compare-eax-and 0/imm32/false - 3527 0f 85/jump-if-!= $parse-type:abort/disp32 - 3528 # assert s != "->" - 3529 (slice-equal? %ecx "->") - 3530 3d/compare-eax-and 0/imm32/false - 3531 0f 85/jump-if-!= $parse-type:abort/disp32 - 3532 # if (s == ")") return 0 - 3533 (slice-equal? %ecx ")") - 3534 3d/compare-eax-and 0/imm32/false - 3535 b8/copy-to-eax 0/imm32 - 3536 0f 85/jump-if-!= $parse-type:end/disp32 - 3537 # var result/edx: (handle tree type-id) - 3538 (allocate *(ebp+8) *Tree-size) # => eax - 3539 (zero-out %eax *Tree-size) - 3540 89/<- %edx 0/r32/eax - 3541 { - 3542 # if (s != "(") break - 3543 (slice-equal? %ecx "(") - 3544 3d/compare-eax-and 0/imm32/false - 3545 75/jump-if-!= break/disp8 - 3546 # EGREGIOUS HACK for static array sizes: if s is a number, parse it - 3547 { - 3548 (is-hex-int? %ecx) # => eax - 3549 3d/compare-eax-and 0/imm32/false - 3550 74/jump-if-= break/disp8 - 3551 (parse-hex-int-from-slice %ecx) # => eax - 3552 89/<- *edx 0/r32/eax # Tree-left - 3553 e9/jump $parse-type:return-edx/disp32 - 3554 } - 3555 # result->left = pos-or-insert-slice(Type-id, s) - 3556 (pos-or-insert-slice Type-id %ecx) # => eax - 3557 #? (write-buffered Stderr "=> {") - 3558 #? (print-int32-buffered Stderr %eax) - 3559 #? (write-buffered Stderr ", 0}\n") - 3560 #? (flush Stderr) - 3561 89/<- *edx 0/r32/eax # Tree-left - 3562 e9/jump $parse-type:return-edx/disp32 - 3563 } - 3564 # otherwise s == "(" - 3565 # result->left = parse-type(ad, in) - 3566 (parse-type *(ebp+8) *(ebp+0xc)) - 3567 #? (write-buffered Stderr "=> {") - 3568 #? (print-int32-buffered Stderr %eax) - 3569 89/<- *edx 0/r32/eax # Tree-left - 3570 # result->right = parse-type-tree(ad, in) - 3571 (parse-type-tree *(ebp+8) *(ebp+0xc)) - 3572 #? (write-buffered Stderr Space) - 3573 #? (print-int32-buffered Stderr %eax) - 3574 #? (write-buffered Stderr "}\n") - 3575 #? (flush Stderr) - 3576 89/<- *(edx+4) 0/r32/eax # Tree-right - 3577 $parse-type:return-edx: - 3578 89/<- %eax 2/r32/edx - 3579 $parse-type:end: - 3580 # . reclaim locals - 3581 81 0/subop/add %esp 8/imm32 - 3582 # . restore registers - 3583 5a/pop-to-edx - 3584 59/pop-to-ecx - 3585 # . epilogue - 3586 89/<- %esp 5/r32/ebp - 3587 5d/pop-to-ebp - 3588 c3/return - 3589 - 3590 $parse-type:abort: - 3591 # error("unexpected token when parsing type: '" s "'\n") - 3592 (write-buffered Stderr "unexpected token when parsing type: '") - 3593 (write-slice-buffered Stderr %ecx) - 3594 (write-buffered Stderr "'\n") - 3595 (flush Stderr) - 3596 # . syscall(exit, 1) - 3597 bb/copy-to-ebx 1/imm32 - 3598 b8/copy-to-eax 1/imm32/exit - 3599 cd/syscall 0x80/imm8 - 3600 # never gets here - 3601 - 3602 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) - 3603 # pseudocode: - 3604 # var tmp: (handle tree type-id) = parse-type(ad, in) - 3605 # if tmp == 0 - 3606 # return 0 - 3607 # result = allocate(Tree) - 3608 # zero-out(result, *Tree-size) - 3609 # result->left = tmp - 3610 # result->right = parse-type-tree(ad, in) - 3611 # - 3612 # . prologue - 3613 55/push-ebp - 3614 89/<- %ebp 4/r32/esp - 3615 # . save registers - 3616 51/push-ecx - 3617 52/push-edx - 3618 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) - 3619 (parse-type *(ebp+8) *(ebp+0xc)) - 3620 # if (tmp == 0) return tmp - 3621 3d/compare-eax-and 0/imm32 - 3622 74/jump-if-= $parse-type-tree:end/disp8 - 3623 # var tmp2/ecx = tmp - 3624 89/<- %ecx 0/r32/eax - 3625 # var result/edx: (handle tree type-id) - 3626 (allocate *(ebp+8) *Tree-size) # => eax - 3627 (zero-out %eax *Tree-size) - 3628 89/<- %edx 0/r32/eax - 3629 # result->left = tmp2 - 3630 89/<- *edx 1/r32/ecx # Tree-left - 3631 # result->right = parse-type-tree(ad, in) - 3632 (parse-type-tree *(ebp+8) *(ebp+0xc)) - 3633 89/<- *(edx+4) 0/r32/eax # Tree-right - 3634 $parse-type-tree:return-edx: - 3635 89/<- %eax 2/r32/edx - 3636 $parse-type-tree:end: - 3637 # . restore registers - 3638 5a/pop-to-edx - 3639 59/pop-to-ecx - 3640 # . epilogue - 3641 89/<- %esp 5/r32/ebp - 3642 5d/pop-to-ebp - 3643 c3/return - 3644 - 3645 next-mu-token: # in: (addr stream byte), out: (addr slice) - 3646 # pseudocode: - 3647 # start: - 3648 # skip-chars-matching-whitespace(in) - 3649 # if in->read >= in->write # end of in - 3650 # out = {0, 0} - 3651 # return - 3652 # out->start = &in->data[in->read] - 3653 # var curr-byte/eax: byte = in->data[in->read] - 3654 # if curr->byte == ',' # comment token - 3655 # ++in->read - 3656 # goto start - 3657 # if curr-byte == '#' # comment - 3658 # goto done # treat as eof - 3659 # if curr-byte == '"' # string literal - 3660 # skip-string(in) - 3661 # goto done # no metadata - 3662 # if curr-byte == '(' - 3663 # ++in->read - 3664 # goto done - 3665 # if curr-byte == ')' - 3666 # ++in->read - 3667 # goto done - 3668 # # read a word - 3669 # while true - 3670 # if in->read >= in->write - 3671 # break - 3672 # curr-byte = in->data[in->read] - 3673 # if curr-byte == ' ' - 3674 # break - 3675 # if curr-byte == '\r' - 3676 # break - 3677 # if curr-byte == '\n' - 3678 # break - 3679 # if curr-byte == '(' - 3680 # break - 3681 # if curr-byte == ')' - 3682 # break - 3683 # if curr-byte == ',' - 3684 # break - 3685 # ++in->read - 3686 # done: - 3687 # out->end = &in->data[in->read] - 3688 # - 3689 # . prologue - 3690 55/push-ebp - 3691 89/<- %ebp 4/r32/esp - 3692 # . save registers - 3693 50/push-eax - 3694 51/push-ecx - 3695 56/push-esi - 3696 57/push-edi - 3697 # esi = in - 3698 8b/-> *(ebp+8) 6/r32/esi - 3699 # edi = out - 3700 8b/-> *(ebp+0xc) 7/r32/edi - 3701 $next-mu-token:start: - 3702 (skip-chars-matching-whitespace %esi) - 3703 $next-mu-token:check0: - 3704 # if (in->read >= in->write) return out = {0, 0} - 3705 # . ecx = in->read - 3706 8b/-> *(esi+4) 1/r32/ecx - 3707 # . if (ecx >= in->write) return out = {0, 0} - 3708 3b/compare 1/r32/ecx *esi - 3709 c7 0/subop/copy *edi 0/imm32 - 3710 c7 0/subop/copy *(edi+4) 0/imm32 - 3711 0f 8d/jump-if->= $next-mu-token:end/disp32 - 3712 # out->start = &in->data[in->read] - 3713 8d/copy-address *(esi+ecx+0xc) 0/r32/eax - 3714 89/<- *edi 0/r32/eax - 3715 # var curr-byte/eax: byte = in->data[in->read] - 3716 31/xor %eax 0/r32/eax - 3717 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL - 3718 { - 3719 $next-mu-token:check-for-comma: - 3720 # if (curr-byte != ',') break - 3721 3d/compare-eax-and 0x2c/imm32/comma - 3722 75/jump-if-!= break/disp8 - 3723 # ++in->read - 3724 ff 0/subop/increment *(esi+4) - 3725 # restart - 3726 e9/jump $next-mu-token:start/disp32 - 3727 } - 3728 { - 3729 $next-mu-token:check-for-comment: - 3730 # if (curr-byte != '#') break - 3731 3d/compare-eax-and 0x23/imm32/pound - 3732 75/jump-if-!= break/disp8 - 3733 # return eof - 3734 e9/jump $next-mu-token:done/disp32 - 3735 } - 3736 { - 3737 $next-mu-token:check-for-string-literal: - 3738 # if (curr-byte != '"') break - 3739 3d/compare-eax-and 0x22/imm32/dquote - 3740 75/jump-if-!= break/disp8 - 3741 (skip-string %esi) - 3742 # return - 3743 e9/jump $next-mu-token:done/disp32 - 3744 } - 3745 { - 3746 $next-mu-token:check-for-open-paren: - 3747 # if (curr-byte != '(') break - 3748 3d/compare-eax-and 0x28/imm32/open-paren - 3749 75/jump-if-!= break/disp8 - 3750 # ++in->read - 3751 ff 0/subop/increment *(esi+4) - 3752 # return - 3753 e9/jump $next-mu-token:done/disp32 - 3754 } - 3755 { - 3756 $next-mu-token:check-for-close-paren: - 3757 # if (curr-byte != ')') break - 3758 3d/compare-eax-and 0x29/imm32/close-paren - 3759 75/jump-if-!= break/disp8 - 3760 # ++in->read - 3761 ff 0/subop/increment *(esi+4) - 3762 # return - 3763 e9/jump $next-mu-token:done/disp32 - 3764 } - 3765 { - 3766 $next-mu-token:regular-word-without-metadata: - 3767 # if (in->read >= in->write) break - 3768 # . ecx = in->read - 3769 8b/-> *(esi+4) 1/r32/ecx - 3770 # . if (ecx >= in->write) break - 3771 3b/compare *esi 1/r32/ecx - 3772 7d/jump-if->= break/disp8 - 3773 # var c/eax: byte = in->data[in->read] - 3774 31/xor %eax 0/r32/eax - 3775 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL - 3776 # if (c == ' ') break - 3777 3d/compare-eax-and 0x20/imm32/space - 3778 74/jump-if-= break/disp8 - 3779 # if (c == '\r') break - 3780 3d/compare-eax-and 0xd/imm32/carriage-return - 3781 74/jump-if-= break/disp8 - 3782 # if (c == '\n') break - 3783 3d/compare-eax-and 0xa/imm32/newline - 3784 74/jump-if-= break/disp8 - 3785 # if (c == '(') break - 3786 3d/compare-eax-and 0x28/imm32/open-paren - 3787 0f 84/jump-if-= break/disp32 - 3788 # if (c == ')') break - 3789 3d/compare-eax-and 0x29/imm32/close-paren - 3790 0f 84/jump-if-= break/disp32 - 3791 # if (c == ',') break - 3792 3d/compare-eax-and 0x2c/imm32/comma - 3793 0f 84/jump-if-= break/disp32 - 3794 # ++in->read - 3795 ff 0/subop/increment *(esi+4) - 3796 # - 3797 e9/jump loop/disp32 - 3798 } - 3799 $next-mu-token:done: - 3800 # out->end = &in->data[in->read] - 3801 8b/-> *(esi+4) 1/r32/ecx - 3802 8d/copy-address *(esi+ecx+0xc) 0/r32/eax - 3803 89/<- *(edi+4) 0/r32/eax - 3804 $next-mu-token:end: - 3805 # . restore registers - 3806 5f/pop-to-edi - 3807 5e/pop-to-esi - 3808 59/pop-to-ecx - 3809 58/pop-to-eax - 3810 # . epilogue - 3811 89/<- %esp 5/r32/ebp - 3812 5d/pop-to-ebp - 3813 c3/return - 3814 - 3815 pos-or-insert-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int - 3816 # . prologue - 3817 55/push-ebp - 3818 89/<- %ebp 4/r32/esp - 3819 # if (pos-slice(arr, s) != -1) return it - 3820 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax - 3821 3d/compare-eax-and -1/imm32 - 3822 75/jump-if-!= $pos-or-insert-slice:end/disp8 - 3823 $pos-or-insert-slice:insert: - 3824 (slice-to-string Heap *(ebp+0xc)) # => eax - 3825 (write-int *(ebp+8) %eax) - 3826 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax - 3827 $pos-or-insert-slice:end: - 3828 # . epilogue - 3829 89/<- %esp 5/r32/ebp - 3830 5d/pop-to-ebp - 3831 c3/return - 3832 - 3833 # return the index in an array of strings matching 's', -1 if not found - 3834 # index is denominated in elements, not bytes - 3835 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int - 3836 # . prologue - 3837 55/push-ebp - 3838 89/<- %ebp 4/r32/esp - 3839 # . save registers - 3840 51/push-ecx - 3841 52/push-edx - 3842 53/push-ebx - 3843 56/push-esi - 3844 #? (write-buffered Stderr "pos-slice: ") - 3845 #? (write-slice-buffered Stderr *(ebp+0xc)) - 3846 #? (write-buffered Stderr "\n") - 3847 #? (flush Stderr) - 3848 # esi = arr - 3849 8b/-> *(ebp+8) 6/r32/esi - 3850 # var index/ecx: int = 0 - 3851 b9/copy-to-ecx 0/imm32 - 3852 # var curr/edx: (addr (addr array byte)) = arr->data - 3853 8d/copy-address *(esi+0xc) 2/r32/edx - 3854 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] - 3855 8b/-> *esi 3/r32/ebx - 3856 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx - 3857 { - 3858 #? (write-buffered Stderr " ") - 3859 #? (print-int32-buffered Stderr %ecx) - 3860 #? (write-buffered Stderr "\n") - 3861 #? (flush Stderr) - 3862 # if (curr >= max) return -1 - 3863 39/compare %edx 3/r32/ebx - 3864 b8/copy-to-eax -1/imm32 - 3865 73/jump-if-addr>= $pos-slice:end/disp8 - 3866 # if (slice-equal?(s, *curr)) break - 3867 (slice-equal? *(ebp+0xc) *edx) # => eax - 3868 3d/compare-eax-and 0/imm32/false - 3869 75/jump-if-!= break/disp8 - 3870 # ++index - 3871 41/increment-ecx - 3872 # curr += 4 - 3873 81 0/subop/add %edx 4/imm32 - 3874 # - 3875 eb/jump loop/disp8 - 3876 } - 3877 # return index - 3878 89/<- %eax 1/r32/ecx - 3879 $pos-slice:end: - 3880 #? (write-buffered Stderr "=> ") - 3881 #? (print-int32-buffered Stderr %eax) - 3882 #? (write-buffered Stderr "\n") - 3883 # . restore registers - 3884 5e/pop-to-esi - 3885 5b/pop-to-ebx - 3886 5a/pop-to-edx - 3887 59/pop-to-ecx - 3888 # . epilogue - 3889 89/<- %esp 5/r32/ebp - 3890 5d/pop-to-ebp - 3891 c3/return - 3892 - 3893 test-parse-var-with-type: - 3894 # . prologue - 3895 55/push-ebp - 3896 89/<- %ebp 4/r32/esp - 3897 # (eax..ecx) = "x:" - 3898 b8/copy-to-eax "x:"/imm32 - 3899 8b/-> *eax 1/r32/ecx - 3900 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3901 05/add-to-eax 4/imm32 - 3902 # var slice/ecx: slice = {eax, ecx} - 3903 51/push-ecx - 3904 50/push-eax - 3905 89/<- %ecx 4/r32/esp - 3906 # _test-input-stream contains "int" - 3907 (clear-stream _test-input-stream) - 3908 (write _test-input-stream "int") - 3909 # - 3910 (parse-var-with-type %ecx _test-input-stream) - 3911 8b/-> *eax 2/r32/edx # Var-name - 3912 (check-strings-equal %edx "x" "F - test-var-with-type/name") - 3913 8b/-> *(eax+4) 2/r32/edx # Var-type - 3914 (check-ints-equal *edx 1 "F - test-var-with-type/type") - 3915 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") - 3916 # . epilogue - 3917 89/<- %esp 5/r32/ebp - 3918 5d/pop-to-ebp - 3919 c3/return - 3920 - 3921 test-parse-var-with-type-and-register: - 3922 # . prologue - 3923 55/push-ebp - 3924 89/<- %ebp 4/r32/esp - 3925 # (eax..ecx) = "x/eax:" - 3926 b8/copy-to-eax "x/eax:"/imm32 - 3927 8b/-> *eax 1/r32/ecx - 3928 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3929 05/add-to-eax 4/imm32 - 3930 # var slice/ecx: slice = {eax, ecx} - 3931 51/push-ecx - 3932 50/push-eax - 3933 89/<- %ecx 4/r32/esp - 3934 # _test-input-stream contains "int" - 3935 (clear-stream _test-input-stream) - 3936 (write _test-input-stream "int") - 3937 # - 3938 (parse-var-with-type %ecx _test-input-stream) - 3939 8b/-> *eax 2/r32/edx # Var-name - 3940 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") - 3941 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 3942 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") - 3943 8b/-> *(eax+4) 2/r32/edx # Var-type - 3944 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") - 3945 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") - 3946 # . epilogue - 3947 89/<- %esp 5/r32/ebp - 3948 5d/pop-to-ebp - 3949 c3/return - 3950 - 3951 test-parse-var-with-trailing-characters: - 3952 # . prologue - 3953 55/push-ebp - 3954 89/<- %ebp 4/r32/esp - 3955 # (eax..ecx) = "x:" - 3956 b8/copy-to-eax "x:"/imm32 - 3957 8b/-> *eax 1/r32/ecx - 3958 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3959 05/add-to-eax 4/imm32 - 3960 # var slice/ecx: slice = {eax, ecx} - 3961 51/push-ecx - 3962 50/push-eax - 3963 89/<- %ecx 4/r32/esp - 3964 # _test-input-stream contains "int," - 3965 (clear-stream _test-input-stream) - 3966 (write _test-input-stream "int,") - 3967 # - 3968 (parse-var-with-type %ecx _test-input-stream) - 3969 8b/-> *eax 2/r32/edx # Var-name - 3970 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") - 3971 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 3972 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") - 3973 8b/-> *(eax+4) 2/r32/edx # Var-type - 3974 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") - 3975 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") - 3976 # . epilogue - 3977 89/<- %esp 5/r32/ebp - 3978 5d/pop-to-ebp - 3979 c3/return - 3980 - 3981 test-parse-var-with-register-and-trailing-characters: - 3982 # . prologue - 3983 55/push-ebp - 3984 89/<- %ebp 4/r32/esp - 3985 # (eax..ecx) = "x/eax:" - 3986 b8/copy-to-eax "x/eax:"/imm32 - 3987 8b/-> *eax 1/r32/ecx - 3988 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 3989 05/add-to-eax 4/imm32 - 3990 # var slice/ecx: slice = {eax, ecx} - 3991 51/push-ecx - 3992 50/push-eax - 3993 89/<- %ecx 4/r32/esp - 3994 # _test-input-stream contains "int," - 3995 (clear-stream _test-input-stream) - 3996 (write _test-input-stream "int,") - 3997 # - 3998 (parse-var-with-type %ecx _test-input-stream) - 3999 8b/-> *eax 2/r32/edx # Var-name - 4000 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") - 4001 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 4002 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") - 4003 8b/-> *(eax+4) 2/r32/edx # Var-type - 4004 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") - 4005 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") - 4006 # . epilogue - 4007 89/<- %esp 5/r32/ebp - 4008 5d/pop-to-ebp - 4009 c3/return - 4010 - 4011 test-parse-var-with-compound-type: - 4012 # . prologue - 4013 55/push-ebp - 4014 89/<- %ebp 4/r32/esp - 4015 # (eax..ecx) = "x:" - 4016 b8/copy-to-eax "x:"/imm32 - 4017 8b/-> *eax 1/r32/ecx - 4018 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4019 05/add-to-eax 4/imm32 - 4020 # var slice/ecx: slice = {eax, ecx} - 4021 51/push-ecx - 4022 50/push-eax - 4023 89/<- %ecx 4/r32/esp - 4024 # _test-input-stream contains "(addr int)" - 4025 (clear-stream _test-input-stream) - 4026 (write _test-input-stream "(addr int)") - 4027 # - 4028 (parse-var-with-type %ecx _test-input-stream) - 4029 8b/-> *eax 2/r32/edx # Var-name - 4030 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") - 4031 8b/-> *(eax+0x10) 2/r32/edx # Var-register - 4032 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") - 4033 # var type/edx: (handle tree type-id) = var->type - 4034 8b/-> *(eax+4) 2/r32/edx # Var-type - 4035 # type->left == atom(addr) - 4036 8b/-> *edx 0/r32/eax # Atom-value - 4037 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left - 4038 # type->right->left == atom(int) - 4039 8b/-> *(edx+4) 2/r32/edx # Tree-right - 4040 8b/-> *edx 0/r32/eax # Tree-left - 4041 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value - 4042 # type->right->right == null - 4043 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right - 4044 # . epilogue - 4045 89/<- %esp 5/r32/ebp - 4046 5d/pop-to-ebp - 4047 c3/return - 4048 - 4049 # identifier starts with a letter or '$' or '_' - 4050 # no constraints at the moment on later letters - 4051 # all we really want to do so far is exclude '{', '}' and '->' - 4052 is-identifier?: # in: (addr slice) -> result/eax: boolean - 4053 # . prologue - 4054 55/push-ebp - 4055 89/<- %ebp 4/r32/esp - 4056 # if (slice-empty?(in)) return false - 4057 (slice-empty? *(ebp+8)) # => eax - 4058 3d/compare-eax-and 0/imm32/false - 4059 75/jump-if-!= $is-identifier?:false/disp8 - 4060 # var c/eax: byte = *in->start - 4061 8b/-> *(ebp+8) 0/r32/eax - 4062 8b/-> *eax 0/r32/eax - 4063 8a/copy-byte *eax 0/r32/AL - 4064 81 4/subop/and %eax 0xff/imm32 - 4065 # if (c == '$') return true - 4066 3d/compare-eax-and 0x24/imm32/$ - 4067 74/jump-if-= $is-identifier?:true/disp8 - 4068 # if (c == '_') return true - 4069 3d/compare-eax-and 0x5f/imm32/_ - 4070 74/jump-if-= $is-identifier?:true/disp8 - 4071 # drop case - 4072 25/and-eax-with 0x5f/imm32 - 4073 # if (c < 'A') return false - 4074 3d/compare-eax-and 0x41/imm32/A - 4075 7c/jump-if-< $is-identifier?:false/disp8 - 4076 # if (c > 'Z') return false - 4077 3d/compare-eax-and 0x5a/imm32/Z - 4078 7f/jump-if-> $is-identifier?:false/disp8 - 4079 # otherwise return true - 4080 $is-identifier?:true: - 4081 b8/copy-to-eax 1/imm32/true - 4082 eb/jump $is-identifier?:end/disp8 - 4083 $is-identifier?:false: - 4084 b8/copy-to-eax 0/imm32/false - 4085 $is-identifier?:end: - 4086 # . epilogue - 4087 89/<- %esp 5/r32/ebp - 4088 5d/pop-to-ebp - 4089 c3/return - 4090 - 4091 test-is-identifier-dollar: - 4092 # . prologue - 4093 55/push-ebp - 4094 89/<- %ebp 4/r32/esp - 4095 # (eax..ecx) = "$a" - 4096 b8/copy-to-eax "$a"/imm32 - 4097 8b/-> *eax 1/r32/ecx - 4098 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4099 05/add-to-eax 4/imm32 - 4100 # var slice/ecx: slice = {eax, ecx} - 4101 51/push-ecx - 4102 50/push-eax - 4103 89/<- %ecx 4/r32/esp - 4104 # - 4105 (is-identifier? %ecx) - 4106 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") - 4107 # . epilogue - 4108 89/<- %esp 5/r32/ebp - 4109 5d/pop-to-ebp - 4110 c3/return - 4111 - 4112 test-is-identifier-underscore: - 4113 # . prologue - 4114 55/push-ebp - 4115 89/<- %ebp 4/r32/esp - 4116 # (eax..ecx) = "_a" - 4117 b8/copy-to-eax "_a"/imm32 - 4118 8b/-> *eax 1/r32/ecx - 4119 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4120 05/add-to-eax 4/imm32 - 4121 # var slice/ecx: slice = {eax, ecx} - 4122 51/push-ecx - 4123 50/push-eax - 4124 89/<- %ecx 4/r32/esp - 4125 # - 4126 (is-identifier? %ecx) - 4127 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") - 4128 # . epilogue - 4129 89/<- %esp 5/r32/ebp - 4130 5d/pop-to-ebp - 4131 c3/return - 4132 - 4133 test-is-identifier-a: - 4134 # . prologue - 4135 55/push-ebp - 4136 89/<- %ebp 4/r32/esp - 4137 # (eax..ecx) = "a$" - 4138 b8/copy-to-eax "a$"/imm32 - 4139 8b/-> *eax 1/r32/ecx - 4140 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4141 05/add-to-eax 4/imm32 - 4142 # var slice/ecx: slice = {eax, ecx} - 4143 51/push-ecx - 4144 50/push-eax - 4145 89/<- %ecx 4/r32/esp - 4146 # - 4147 (is-identifier? %ecx) - 4148 (check-ints-equal %eax 1 "F - test-is-identifier-a") - 4149 # . epilogue - 4150 89/<- %esp 5/r32/ebp - 4151 5d/pop-to-ebp - 4152 c3/return - 4153 - 4154 test-is-identifier-z: - 4155 # . prologue - 4156 55/push-ebp - 4157 89/<- %ebp 4/r32/esp - 4158 # (eax..ecx) = "z$" - 4159 b8/copy-to-eax "z$"/imm32 - 4160 8b/-> *eax 1/r32/ecx - 4161 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4162 05/add-to-eax 4/imm32 - 4163 # var slice/ecx: slice = {eax, ecx} - 4164 51/push-ecx - 4165 50/push-eax - 4166 89/<- %ecx 4/r32/esp - 4167 # - 4168 (is-identifier? %ecx) - 4169 (check-ints-equal %eax 1 "F - test-is-identifier-z") - 4170 # . epilogue - 4171 89/<- %esp 5/r32/ebp - 4172 5d/pop-to-ebp - 4173 c3/return - 4174 - 4175 test-is-identifier-A: - 4176 # . prologue - 4177 55/push-ebp - 4178 89/<- %ebp 4/r32/esp - 4179 # (eax..ecx) = "A$" - 4180 b8/copy-to-eax "A$"/imm32 - 4181 8b/-> *eax 1/r32/ecx - 4182 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4183 05/add-to-eax 4/imm32 - 4184 # var slice/ecx: slice = {eax, ecx} - 4185 51/push-ecx - 4186 50/push-eax - 4187 89/<- %ecx 4/r32/esp - 4188 # - 4189 (is-identifier? %ecx) - 4190 (check-ints-equal %eax 1 "F - test-is-identifier-A") - 4191 # . epilogue - 4192 89/<- %esp 5/r32/ebp - 4193 5d/pop-to-ebp - 4194 c3/return - 4195 - 4196 test-is-identifier-Z: - 4197 # . prologue - 4198 55/push-ebp - 4199 89/<- %ebp 4/r32/esp - 4200 # (eax..ecx) = "Z$" - 4201 b8/copy-to-eax "Z$"/imm32 - 4202 8b/-> *eax 1/r32/ecx - 4203 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4204 05/add-to-eax 4/imm32 - 4205 # var slice/ecx: slice = {eax, ecx} - 4206 51/push-ecx - 4207 50/push-eax - 4208 89/<- %ecx 4/r32/esp - 4209 # - 4210 (is-identifier? %ecx) - 4211 (check-ints-equal %eax 1 "F - test-is-identifier-Z") - 4212 # . epilogue - 4213 89/<- %esp 5/r32/ebp - 4214 5d/pop-to-ebp - 4215 c3/return - 4216 - 4217 test-is-identifier-@: - 4218 # character before 'A' is invalid - 4219 # . prologue - 4220 55/push-ebp - 4221 89/<- %ebp 4/r32/esp - 4222 # (eax..ecx) = "@a" - 4223 b8/copy-to-eax "@a"/imm32 - 4224 8b/-> *eax 1/r32/ecx - 4225 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4226 05/add-to-eax 4/imm32 - 4227 # var slice/ecx: slice = {eax, ecx} - 4228 51/push-ecx - 4229 50/push-eax - 4230 89/<- %ecx 4/r32/esp - 4231 # - 4232 (is-identifier? %ecx) - 4233 (check-ints-equal %eax 0 "F - test-is-identifier-@") - 4234 # . epilogue - 4235 89/<- %esp 5/r32/ebp - 4236 5d/pop-to-ebp - 4237 c3/return - 4238 - 4239 test-is-identifier-square-bracket: - 4240 # character after 'Z' is invalid - 4241 # . prologue - 4242 55/push-ebp - 4243 89/<- %ebp 4/r32/esp - 4244 # (eax..ecx) = "[a" - 4245 b8/copy-to-eax "[a"/imm32 - 4246 8b/-> *eax 1/r32/ecx - 4247 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4248 05/add-to-eax 4/imm32 - 4249 # var slice/ecx: slice = {eax, ecx} - 4250 51/push-ecx - 4251 50/push-eax - 4252 89/<- %ecx 4/r32/esp - 4253 # - 4254 (is-identifier? %ecx) - 4255 (check-ints-equal %eax 0 "F - test-is-identifier-@") - 4256 # . epilogue - 4257 89/<- %esp 5/r32/ebp - 4258 5d/pop-to-ebp - 4259 c3/return - 4260 - 4261 test-is-identifier-backtick: - 4262 # character before 'a' is invalid - 4263 # . prologue - 4264 55/push-ebp - 4265 89/<- %ebp 4/r32/esp - 4266 # (eax..ecx) = "`a" - 4267 b8/copy-to-eax "`a"/imm32 - 4268 8b/-> *eax 1/r32/ecx - 4269 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4270 05/add-to-eax 4/imm32 - 4271 # var slice/ecx: slice = {eax, ecx} - 4272 51/push-ecx - 4273 50/push-eax - 4274 89/<- %ecx 4/r32/esp - 4275 # - 4276 (is-identifier? %ecx) - 4277 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") - 4278 # . epilogue - 4279 89/<- %esp 5/r32/ebp - 4280 5d/pop-to-ebp - 4281 c3/return - 4282 - 4283 test-is-identifier-curly-brace-open: - 4284 # character after 'z' is invalid; also used for blocks - 4285 # . prologue - 4286 55/push-ebp - 4287 89/<- %ebp 4/r32/esp - 4288 # (eax..ecx) = "{a" - 4289 b8/copy-to-eax "{a"/imm32 - 4290 8b/-> *eax 1/r32/ecx - 4291 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4292 05/add-to-eax 4/imm32 - 4293 # var slice/ecx: slice = {eax, ecx} - 4294 51/push-ecx - 4295 50/push-eax - 4296 89/<- %ecx 4/r32/esp - 4297 # - 4298 (is-identifier? %ecx) - 4299 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") - 4300 # . epilogue - 4301 89/<- %esp 5/r32/ebp - 4302 5d/pop-to-ebp - 4303 c3/return - 4304 - 4305 test-is-identifier-curly-brace-close: - 4306 # . prologue - 4307 55/push-ebp - 4308 89/<- %ebp 4/r32/esp - 4309 # (eax..ecx) = "}a" - 4310 b8/copy-to-eax "}a"/imm32 - 4311 8b/-> *eax 1/r32/ecx - 4312 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4313 05/add-to-eax 4/imm32 - 4314 # var slice/ecx: slice = {eax, ecx} - 4315 51/push-ecx - 4316 50/push-eax - 4317 89/<- %ecx 4/r32/esp - 4318 # - 4319 (is-identifier? %ecx) - 4320 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") - 4321 # . epilogue - 4322 89/<- %esp 5/r32/ebp - 4323 5d/pop-to-ebp - 4324 c3/return - 4325 - 4326 test-is-identifier-hyphen: - 4327 # disallow leading '-' since '->' has special meaning - 4328 # . prologue - 4329 55/push-ebp - 4330 89/<- %ebp 4/r32/esp - 4331 # (eax..ecx) = "-a" - 4332 b8/copy-to-eax "-a"/imm32 - 4333 8b/-> *eax 1/r32/ecx - 4334 8d/copy-address *(eax+ecx+4) 1/r32/ecx - 4335 05/add-to-eax 4/imm32 - 4336 # var slice/ecx: slice = {eax, ecx} - 4337 51/push-ecx - 4338 50/push-eax - 4339 89/<- %ecx 4/r32/esp - 4340 # - 4341 (is-identifier? %ecx) - 4342 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") - 4343 # . epilogue - 4344 89/<- %esp 5/r32/ebp - 4345 5d/pop-to-ebp - 4346 c3/return - 4347 - 4348 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) - 4349 # . prologue - 4350 55/push-ebp - 4351 89/<- %ebp 4/r32/esp - 4352 # . save registers - 4353 50/push-eax - 4354 56/push-esi - 4355 57/push-edi - 4356 # esi = in - 4357 8b/-> *(ebp+8) 6/r32/esi - 4358 # edi = out - 4359 8b/-> *(ebp+0xc) 7/r32/edi - 4360 # var eax: (handle block) = parse-mu-block(in, vars, fn) - 4361 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax - 4362 # out->body = eax - 4363 89/<- *(edi+0x10) 0/r32/eax # Function-body - 4364 $populate-mu-function-body:end: - 4365 # . restore registers - 4366 5f/pop-to-edi - 4367 5e/pop-to-esi - 4368 58/pop-to-eax - 4369 # . epilogue - 4370 89/<- %esp 5/r32/ebp - 4371 5d/pop-to-ebp - 4372 c3/return - 4373 - 4374 # parses a block, assuming that the leading '{' has already been read by the caller - 4375 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) - 4376 # pseudocode: - 4377 # var line: (stream byte 512) - 4378 # var word-slice: slice - 4379 # result/eax = allocate(Heap, Stmt-size) - 4380 # result->tag = 0/block - 4381 # result->name = some unique name - 4382 # while true # line loop - 4383 # clear-stream(line) - 4384 # read-line-buffered(in, line) - 4385 # if (line->write == 0) break # end of file - 4386 # word-slice = next-mu-token(line) - 4387 # if slice-empty?(word-slice) # end of line - 4388 # continue - 4389 # else if slice-starts-with?(word-slice, "#") - 4390 # continue - 4391 # else if slice-equal?(word-slice, "{") - 4392 # assert(no-tokens-in(line)) - 4393 # block = parse-mu-block(in, vars, fn) - 4394 # append-to-block(result, block) - 4395 # else if slice-equal?(word-slice, "}") - 4396 # break - 4397 # else if slice-ends-with?(word-slice, ":") - 4398 # # TODO: error-check the rest of 'line' - 4399 # --word-slice->end to skip ':' - 4400 # named-block = parse-mu-named-block(word-slice, in, vars, fn) - 4401 # append-to-block(result, named-block) - 4402 # else if slice-equal?(word-slice, "var") - 4403 # var-def = parse-mu-var-def(line, vars) - 4404 # append-to-block(result, var-def) - 4405 # else - 4406 # stmt = parse-mu-stmt(line, vars, fn) - 4407 # append-to-block(result, stmt) - 4408 # return result - 4409 # - 4410 # . prologue - 4411 55/push-ebp - 4412 89/<- %ebp 4/r32/esp - 4413 # . save registers - 4414 51/push-ecx - 4415 52/push-edx - 4416 53/push-ebx - 4417 57/push-edi - 4418 # var line/ecx: (stream byte 512) - 4419 81 5/subop/subtract %esp 0x200/imm32 - 4420 68/push 0x200/imm32/length - 4421 68/push 0/imm32/read - 4422 68/push 0/imm32/write - 4423 89/<- %ecx 4/r32/esp - 4424 # var word-slice/edx: slice - 4425 68/push 0/imm32/end - 4426 68/push 0/imm32/start - 4427 89/<- %edx 4/r32/esp - 4428 # edi = result - 4429 (allocate Heap *Stmt-size) # => eax - 4430 (zero-out %eax *Stmt-size) - 4431 89/<- %edi 0/r32/eax - 4432 # set result->tag - 4433 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag - 4434 # set result->var - 4435 (new-block-name *(ebp+0x10)) # => eax - 4436 89/<- *(edi+8) 0/r32/eax # Block-var - 4437 # push result->var to vars - 4438 (push *(ebp+0xc) %eax) - 4439 { - 4440 $parse-mu-block:line-loop: - 4441 # line = read-line-buffered(in) - 4442 (clear-stream %ecx) - 4443 (read-line-buffered *(ebp+8) %ecx) - 4444 #? (write-buffered Stderr "line: ") - 4445 #? (write-stream-data Stderr %ecx) - 4446 #? (write-buffered Stderr Newline) - 4447 #? (flush Stderr) - 4448 # if (line->write == 0) break - 4449 81 7/subop/compare *ecx 0/imm32 - 4450 0f 84/jump-if-= break/disp32 - 4451 # word-slice = next-mu-token(line) - 4452 (next-mu-token %ecx %edx) - 4453 #? (write-buffered Stderr "word: ") - 4454 #? (write-slice-buffered Stderr %edx) - 4455 #? (write-buffered Stderr Newline) - 4456 #? (flush Stderr) - 4457 # if slice-empty?(word-slice) continue - 4458 (slice-empty? %edx) - 4459 3d/compare-eax-and 0/imm32/false - 4460 0f 85/jump-if-!= loop/disp32 - 4461 # if (slice-starts-with?(word-slice, '#') continue - 4462 # . eax = *word-slice->start - 4463 8b/-> *edx 0/r32/eax - 4464 8a/copy-byte *eax 0/r32/AL - 4465 81 4/subop/and %eax 0xff/imm32 - 4466 # . if (eax == '#') continue - 4467 3d/compare-eax-and 0x23/imm32/hash - 4468 0f 84/jump-if-= loop/disp32 - 4469 # if slice-equal?(word-slice, "{") - 4470 { - 4471 $parse-mu-block:check-for-block: - 4472 (slice-equal? %edx "{") - 4473 3d/compare-eax-and 0/imm32/false - 4474 74/jump-if-= break/disp8 - 4475 (check-no-tokens-left %ecx) - 4476 # parse new block and append - 4477 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax - 4478 (append-to-block Heap %edi %eax) - 4479 e9/jump $parse-mu-block:line-loop/disp32 - 4480 } - 4481 # if slice-equal?(word-slice, "}") break - 4482 $parse-mu-block:check-for-end: - 4483 (slice-equal? %edx "}") - 4484 3d/compare-eax-and 0/imm32/false - 4485 0f 85/jump-if-!= break/disp32 - 4486 # if slice-ends-with?(word-slice, ":") parse named block and append - 4487 { - 4488 $parse-mu-block:check-for-named-block: - 4489 # . eax = *(word-slice->end-1) - 4490 8b/-> *(edx+4) 0/r32/eax - 4491 48/decrement-eax - 4492 8a/copy-byte *eax 0/r32/AL - 4493 81 4/subop/and %eax 0xff/imm32 - 4494 # . if (eax != ':') break - 4495 3d/compare-eax-and 0x3a/imm32/colon - 4496 0f 85/jump-if-!= break/disp32 - 4497 # TODO: error-check the rest of 'line' - 4498 # - 4499 # skip ':' - 4500 ff 1/subop/decrement *(edx+4) # Slice-end - 4501 # - 4502 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax - 4503 (append-to-block Heap %edi %eax) - 4504 e9/jump $parse-mu-block:line-loop/disp32 - 4505 } - 4506 # if slice-equal?(word-slice, "var") - 4507 { - 4508 $parse-mu-block:check-for-var: - 4509 (slice-equal? %edx "var") - 4510 3d/compare-eax-and 0/imm32/false - 4511 74/jump-if-= break/disp8 - 4512 # - 4513 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax - 4514 (append-to-block Heap %edi %eax) - 4515 e9/jump $parse-mu-block:line-loop/disp32 - 4516 } - 4517 $parse-mu-block:regular-stmt: - 4518 # otherwise - 4519 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax - 4520 (append-to-block Heap %edi %eax) - 4521 e9/jump loop/disp32 - 4522 } # end line loop - 4523 # - 4524 (pop *(ebp+0xc)) # => eax - 4525 # return result - 4526 89/<- %eax 7/r32/edi - 4527 $parse-mu-block:end: - 4528 # . reclaim locals - 4529 81 0/subop/add %esp 0x214/imm32 - 4530 # . restore registers - 4531 5f/pop-to-edi - 4532 5b/pop-to-ebx - 4533 5a/pop-to-edx - 4534 59/pop-to-ecx - 4535 # . epilogue - 4536 89/<- %esp 5/r32/ebp - 4537 5d/pop-to-ebp - 4538 c3/return - 4539 - 4540 $parse-mu-block:abort: - 4541 # error("'{' or '}' should be on its own line, but got '") - 4542 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") - 4543 (rewind-stream %ecx) - 4544 (write-stream 2 %ecx) - 4545 (write-buffered Stderr "'\n") - 4546 (flush Stderr) - 4547 # . syscall(exit, 1) - 4548 bb/copy-to-ebx 1/imm32 - 4549 b8/copy-to-eax 1/imm32/exit - 4550 cd/syscall 0x80/imm8 - 4551 # never gets here - 4552 - 4553 new-block-name: # fn: (handle function) -> result/eax: (handle var) - 4554 # . prologue - 4555 55/push-ebp - 4556 89/<- %ebp 4/r32/esp - 4557 # . save registers - 4558 51/push-ecx - 4559 52/push-edx - 4560 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' - 4561 8b/-> *(ebp+8) 0/r32/eax - 4562 8b/-> *eax 0/r32/eax # Function-name - 4563 8b/-> *eax 0/r32/eax # String-length - 4564 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' - 4565 89/<- %ecx 0/r32/eax - 4566 # var name/edx: (stream byte n) - 4567 29/subtract %esp 1/r32/ecx - 4568 ff 6/subop/push %ecx - 4569 68/push 0/imm32/read - 4570 68/push 0/imm32/write - 4571 89/<- %edx 4/r32/esp - 4572 (clear-stream %edx) - 4573 # eax = fn->name - 4574 8b/-> *(ebp+8) 0/r32/eax - 4575 8b/-> *eax 0/r32/eax # Function-name - 4576 # construct result using Next-block-index (and increment it) - 4577 (write %edx "$") - 4578 (write %edx %eax) - 4579 (write %edx ":") - 4580 (print-int32 %edx *Next-block-index) - 4581 ff 0/subop/increment *Next-block-index - 4582 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) - 4583 # . eax = name->write - 4584 8b/-> *edx 0/r32/eax - 4585 # . edx = name->data - 4586 8d/copy-address *(edx+0xc) 2/r32/edx - 4587 # . eax = name->write + name->data - 4588 01/add %eax 2/r32/edx - 4589 # . push {edx, eax} - 4590 ff 6/subop/push %eax - 4591 ff 6/subop/push %edx - 4592 89/<- %eax 4/r32/esp - 4593 # result->var = new literal(s) - 4594 (new-literal Heap %eax) # => eax - 4595 $new-block-name:end: - 4596 # . reclaim locals - 4597 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} - 4598 81 0/subop/add %ecx 8/imm32 # slice - 4599 01/add %esp 1/r32/ecx - 4600 # . restore registers - 4601 5a/pop-to-edx - 4602 59/pop-to-ecx - 4603 # . epilogue - 4604 89/<- %esp 5/r32/ebp - 4605 5d/pop-to-ebp - 4606 c3/return - 4607 - 4608 == data - 4609 - 4610 # Global state added to each var record when parsing a function - 4611 Next-block-index: # (addr int) - 4612 1/imm32 - 4613 - 4614 == code - 4615 - 4616 check-no-tokens-left: # line: (addr stream byte) - 4617 # . prologue - 4618 55/push-ebp - 4619 89/<- %ebp 4/r32/esp - 4620 # . save registers - 4621 50/push-eax - 4622 51/push-ecx - 4623 # var s/ecx: slice - 4624 68/push 0/imm32/end - 4625 68/push 0/imm32/start - 4626 89/<- %ecx 4/r32/esp - 4627 # - 4628 (next-mu-token *(ebp+8) %ecx) - 4629 # if slice-empty?(s) return - 4630 (slice-empty? %ecx) - 4631 3d/compare-eax-and 0/imm32/false - 4632 75/jump-if-!= $check-no-tokens-left:end/disp8 - 4633 # if (slice-starts-with?(s, '#') return - 4634 # . eax = *s->start - 4635 8b/-> *edx 0/r32/eax - 4636 8a/copy-byte *eax 0/r32/AL - 4637 81 4/subop/and %eax 0xff/imm32 - 4638 # . if (eax == '#') continue - 4639 3d/compare-eax-and 0x23/imm32/hash - 4640 74/jump-if-= $check-no-tokens-left:end/disp8 - 4641 # abort - 4642 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") - 4643 (rewind-stream %ecx) - 4644 (write-stream 2 %ecx) - 4645 (write-buffered Stderr "'\n") - 4646 (flush Stderr) - 4647 # . syscall(exit, 1) - 4648 bb/copy-to-ebx 1/imm32 - 4649 b8/copy-to-eax 1/imm32/exit - 4650 cd/syscall 0x80/imm8 - 4651 # never gets here - 4652 $check-no-tokens-left:end: - 4653 # . reclaim locals - 4654 81 0/subop/add %esp 8/imm32 - 4655 # . restore registers - 4656 59/pop-to-ecx - 4657 58/pop-to-eax - 4658 # . epilogue - 4659 89/<- %esp 5/r32/ebp - 4660 5d/pop-to-ebp - 4661 c3/return - 4662 - 4663 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) - 4664 # pseudocode: - 4665 # var v: (handle var) = new-literal(name) - 4666 # push(vars, v) - 4667 # result = parse-mu-block(in, vars, fn) - 4668 # pop(vars) - 4669 # result->name = s - 4670 # return result - 4671 # - 4672 # . prologue - 4673 55/push-ebp - 4674 89/<- %ebp 4/r32/esp - 4675 # . save registers - 4676 51/push-ecx - 4677 # var v/ecx: (handle var) - 4678 (new-literal Heap *(ebp+8)) # => eax - 4679 89/<- %ecx 0/r32/eax - 4680 # push(vars, v) - 4681 (push *(ebp+0x10) %ecx) - 4682 # eax = result - 4683 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax - 4684 # pop the var - 4685 50/push-eax - 4686 (pop *(ebp+0x10)) # => eax - 4687 58/pop-to-eax - 4688 # result->tag = named-block - 4689 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag - 4690 # result->var = v - 4691 89/<- *(eax+8) 1/r32/ecx # Block-var - 4692 $parse-mu-named-block:end: - 4693 # . restore registers - 4694 59/pop-to-ecx - 4695 # . epilogue - 4696 89/<- %esp 5/r32/ebp - 4697 5d/pop-to-ebp - 4698 c3/return - 4699 - 4700 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) - 4701 # . prologue - 4702 55/push-ebp - 4703 89/<- %ebp 4/r32/esp - 4704 # . save registers - 4705 51/push-ecx - 4706 52/push-edx - 4707 # var word-slice/ecx: slice - 4708 68/push 0/imm32/end - 4709 68/push 0/imm32/start - 4710 89/<- %ecx 4/r32/esp - 4711 # var v/edx: (handle var) = parse-var-with-type(line) - 4712 (next-mu-token *(ebp+8) %ecx) - 4713 (parse-var-with-type %ecx *(ebp+8)) # => eax - 4714 89/<- %edx 0/r32/eax - 4715 # - 4716 (push *(ebp+0xc) %edx) - 4717 # either v has no register and there's no more to this line - 4718 8b/-> *(edx+0x10) 0/r32/eax # Var-register - 4719 3d/compare-eax-and 0/imm32 - 4720 { - 4721 75/jump-if-!= break/disp8 - 4722 # TODO: ensure that there's nothing else on this line - 4723 (new-var-def Heap %edx) # => eax - 4724 eb/jump $parse-mu-var-def:end/disp8 - 4725 } - 4726 # or v has a register and there's more to this line - 4727 { - 4728 74/jump-if-= break/disp8 - 4729 # ensure that the next word is '<-' - 4730 (next-mu-token *(ebp+8) %ecx) - 4731 (slice-equal? %ecx "<-") # => eax - 4732 3d/compare-eax-and 0/imm32/false - 4733 74/jump-if-= $parse-mu-var-def:abort/disp8 - 4734 # - 4735 (new-reg-var-def Heap %edx) # => eax - 4736 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) - 4737 } - 4738 $parse-mu-var-def:end: - 4739 # . reclaim locals - 4740 81 0/subop/add %esp 8/imm32 - 4741 # . restore registers - 4742 5a/pop-to-edx - 4743 59/pop-to-ecx - 4744 # . epilogue - 4745 89/<- %esp 5/r32/ebp - 4746 5d/pop-to-ebp - 4747 c3/return - 4748 - 4749 $parse-mu-var-def:abort: - 4750 (rewind-stream *(ebp+8)) - 4751 # error("register variable requires a valid instruction to initialize but got '" line "'\n") - 4752 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") - 4753 (flush Stderr) - 4754 (write-stream 2 *(ebp+8)) - 4755 (write-buffered Stderr "'\n") - 4756 (flush Stderr) - 4757 # . syscall(exit, 1) - 4758 bb/copy-to-ebx 1/imm32 - 4759 b8/copy-to-eax 1/imm32/exit - 4760 cd/syscall 0x80/imm8 - 4761 # never gets here - 4762 - 4763 test-parse-mu-var-def: - 4764 # 'var n: int' - 4765 # . prologue - 4766 55/push-ebp - 4767 89/<- %ebp 4/r32/esp - 4768 # setup - 4769 (clear-stream _test-input-stream) - 4770 (write _test-input-stream "n: int\n") # caller has consumed the 'var' - 4771 # var vars/ecx: (stack (addr var) 4) - 4772 81 5/subop/subtract %esp 0x10/imm32 - 4773 68/push 0x10/imm32/length - 4774 68/push 0/imm32/top - 4775 89/<- %ecx 4/r32/esp - 4776 (clear-stack %ecx) - 4777 # convert - 4778 (parse-mu-var-def _test-input-stream %ecx) # => eax - 4779 # check result - 4780 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def - 4781 8b/-> *(eax+4) 0/r32/eax # Vardef-var - 4782 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name - 4783 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register - 4784 # ensure type is int - 4785 8b/-> *(eax+4) 0/r32/eax # Var-type - 4786 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left - 4787 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right - 4788 # . epilogue - 4789 89/<- %esp 5/r32/ebp - 4790 5d/pop-to-ebp - 4791 c3/return - 4792 - 4793 test-parse-mu-reg-var-def: - 4794 # 'var n/eax: int <- copy 0' - 4795 # . prologue - 4796 55/push-ebp - 4797 89/<- %ebp 4/r32/esp - 4798 # setup - 4799 (clear-stream _test-input-stream) - 4800 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' - 4801 # var vars/ecx: (stack (addr var) 4) - 4802 81 5/subop/subtract %esp 0x10/imm32 - 4803 68/push 0x10/imm32/length - 4804 68/push 0/imm32/top - 4805 89/<- %ecx 4/r32/esp - 4806 (clear-stack %ecx) - 4807 # convert - 4808 (parse-mu-var-def _test-input-stream %ecx) # => eax - 4809 # check result - 4810 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def - 4811 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs - 4812 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next - 4813 8b/-> *eax 0/r32/eax # Stmt-var-value - 4814 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name - 4815 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register - 4816 # ensure type is int - 4817 8b/-> *(eax+4) 0/r32/eax # Var-type - 4818 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left - 4819 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right - 4820 # . epilogue - 4821 89/<- %esp 5/r32/ebp - 4822 5d/pop-to-ebp - 4823 c3/return - 4824 - 4825 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) - 4826 # pseudocode: - 4827 # var name: slice - 4828 # result = allocate(Heap, Stmt-size) - 4829 # if stmt-has-outputs?(line) - 4830 # while true - 4831 # name = next-mu-token(line) - 4832 # if (name == '<-') break - 4833 # assert(is-identifier?(name)) - 4834 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs - 4835 # result->outputs = append(result->outputs, v) - 4836 # add-operation-and-inputs-to-stmt(result, line, vars) - 4837 # - 4838 # . prologue - 4839 55/push-ebp - 4840 89/<- %ebp 4/r32/esp - 4841 # . save registers - 4842 51/push-ecx - 4843 52/push-edx - 4844 57/push-edi - 4845 # var name/ecx: slice - 4846 68/push 0/imm32/end - 4847 68/push 0/imm32/start - 4848 89/<- %ecx 4/r32/esp - 4849 # var is-deref?/edx: boolean = false - 4850 ba/copy-to-edx 0/imm32/false - 4851 # result/edi: (handle stmt) - 4852 (allocate Heap *Stmt-size) # => eax - 4853 (zero-out %eax *Stmt-size) - 4854 89/<- %edi 0/r32/eax - 4855 # result->tag = 1/stmt - 4856 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag - 4857 { - 4858 (stmt-has-outputs? *(ebp+8)) - 4859 3d/compare-eax-and 0/imm32/false - 4860 0f 84/jump-if-= break/disp32 - 4861 { - 4862 $parse-mu-stmt:read-outputs: - 4863 # name = next-mu-token(line) - 4864 (next-mu-token *(ebp+8) %ecx) - 4865 # if slice-empty?(word-slice) break - 4866 (slice-empty? %ecx) # => eax - 4867 3d/compare-eax-and 0/imm32/false - 4868 0f 85/jump-if-!= break/disp32 - 4869 # if (name == "<-") break - 4870 (slice-equal? %ecx "<-") # => eax - 4871 3d/compare-eax-and 0/imm32/false - 4872 0f 85/jump-if-!= break/disp32 - 4873 # is-deref? = false - 4874 ba/copy-to-edx 0/imm32/false - 4875 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? - 4876 8b/-> *ecx 0/r32/eax # Slice-start - 4877 8a/copy-byte *eax 0/r32/AL - 4878 81 4/subop/and %eax 0xff/imm32 - 4879 3d/compare-eax-and 0x2a/imm32/asterisk - 4880 { - 4881 75/jump-if-!= break/disp8 - 4882 ff 0/subop/increment *ecx - 4883 ba/copy-to-edx 1/imm32/true - 4884 } - 4885 # assert(is-identifier?(name)) - 4886 (is-identifier? %ecx) # => eax - 4887 3d/compare-eax-and 0/imm32/false - 4888 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 - 4889 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) - 4890 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax - 4891 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax - 4892 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs - 4893 e9/jump loop/disp32 - 4894 } - 4895 } - 4896 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) - 4897 $parse-mu-stmt:end: - 4898 # return result - 4899 89/<- %eax 7/r32/edi - 4900 # . reclaim locals - 4901 81 0/subop/add %esp 8/imm32 - 4902 # . restore registers - 4903 5f/pop-to-edi - 4904 5a/pop-to-edx - 4905 59/pop-to-ecx - 4906 # . epilogue - 4907 89/<- %esp 5/r32/ebp - 4908 5d/pop-to-ebp - 4909 c3/return - 4910 - 4911 $parse-mu-stmt:abort: - 4912 # error("invalid identifier '" name "'\n") - 4913 (write-buffered Stderr "invalid identifier '") - 4914 (write-slice-buffered Stderr %ecx) - 4915 (write-buffered Stderr "'\n") - 4916 (flush Stderr) - 4917 # . syscall(exit, 1) - 4918 bb/copy-to-ebx 1/imm32 - 4919 b8/copy-to-eax 1/imm32/exit - 4920 cd/syscall 0x80/imm8 - 4921 # never gets here - 4922 - 4923 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) - 4924 # pseudocode: - 4925 # stmt->name = slice-to-string(next-mu-token(line)) - 4926 # while true - 4927 # name = next-mu-token(line) - 4928 # v = lookup-var-or-literal(name) - 4929 # stmt->inouts = append(stmt->inouts, v) - 4930 # - 4931 # . prologue - 4932 55/push-ebp - 4933 89/<- %ebp 4/r32/esp - 4934 # . save registers - 4935 50/push-eax - 4936 51/push-ecx - 4937 52/push-edx - 4938 53/push-ebx - 4939 57/push-edi - 4940 # edi = stmt - 4941 8b/-> *(ebp+8) 7/r32/edi - 4942 # var name/ecx: slice - 4943 68/push 0/imm32/end - 4944 68/push 0/imm32/start - 4945 89/<- %ecx 4/r32/esp - 4946 # var is-deref?/edx: boolean = false - 4947 ba/copy-to-edx 0/imm32/false - 4948 $add-operation-and-inputs-to-stmt:read-operation: - 4949 (next-mu-token *(ebp+0xc) %ecx) - 4950 (slice-to-string Heap %ecx) # => eax - 4951 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation - 4952 # var is-get?/ebx: boolean = (name == "get") - 4953 (slice-equal? %ecx "get") # => eax - 4954 89/<- %ebx 0/r32/eax - 4955 { - 4956 $add-operation-and-inputs-to-stmt:read-inouts: - 4957 # name = next-mu-token(line) - 4958 (next-mu-token *(ebp+0xc) %ecx) - 4959 # if slice-empty?(word-slice) break - 4960 (slice-empty? %ecx) # => eax - 4961 3d/compare-eax-and 0/imm32/false - 4962 0f 85/jump-if-!= break/disp32 - 4963 # if (name == "<-") abort - 4964 (slice-equal? %ecx "<-") - 4965 3d/compare-eax-and 0/imm32/false - 4966 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 - 4967 # if (is-get? && second operand) lookup or create offset - 4968 { - 4969 81 7/subop/compare %ebx 0/imm32/false - 4970 74/jump-if-= break/disp8 - 4971 81 7/subop/compare *(edi+8) 0/imm32 # Stmt1-inouts or Regvardef-inouts - 4972 74/jump-if-= break/disp8 - 4973 (lookup-or-create-constant *(edi+8) %ecx) # Stmt1-inouts => eax - 4974 #? (write-buffered Stderr "creating new output var ") - 4975 #? (print-int32-buffered Stderr %eax) - 4976 #? (write-buffered Stderr " for field called ") - 4977 #? (write-slice-buffered Stderr %ecx) - 4978 #? (write-buffered Stderr Newline) - 4979 #? (flush Stderr) - 4980 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 - 4981 } - 4982 # is-deref? = false - 4983 ba/copy-to-edx 0/imm32/false - 4984 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? - 4985 8b/-> *ecx 0/r32/eax # Slice-start - 4986 8a/copy-byte *eax 0/r32/AL - 4987 81 4/subop/and %eax 0xff/imm32 - 4988 3d/compare-eax-and 0x2a/imm32/asterisk - 4989 { - 4990 75/jump-if-!= break/disp8 - 4991 $add-operation-and-inputs-to-stmt:inout-is-deref: - 4992 ff 0/subop/increment *ecx - 4993 ba/copy-to-edx 1/imm32/true - 4994 } - 4995 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax - 4996 $add-operation-and-inputs-to-stmt:save-var: - 4997 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax - 4998 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 4999 e9/jump loop/disp32 - 5000 } - 5001 $add-operation-and-inputs-to-stmt:end: - 5002 # . reclaim locals - 5003 81 0/subop/add %esp 8/imm32 - 5004 # . restore registers - 5005 5f/pop-to-edi - 5006 5b/pop-to-ebx - 5007 5a/pop-to-edx - 5008 59/pop-to-ecx - 5009 58/pop-to-eax - 5010 # . epilogue - 5011 89/<- %esp 5/r32/ebp - 5012 5d/pop-to-ebp - 5013 c3/return - 5014 - 5015 $add-operation-and-inputs-to-stmt:abort: - 5016 # error("invalid statement '" line "'\n") - 5017 (rewind-stream *(ebp+8)) - 5018 (write-buffered Stderr "invalid identifier '") - 5019 (flush Stderr) - 5020 (write-stream 2 *(ebp+8)) - 5021 (write-buffered Stderr "'\n") - 5022 (flush Stderr) - 5023 # . syscall(exit, 1) - 5024 bb/copy-to-ebx 1/imm32 - 5025 b8/copy-to-eax 1/imm32/exit - 5026 cd/syscall 0x80/imm8 - 5027 # never gets here - 5028 - 5029 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean - 5030 # . prologue - 5031 55/push-ebp - 5032 89/<- %ebp 4/r32/esp - 5033 # . save registers - 5034 51/push-ecx - 5035 # var word-slice/ecx: slice - 5036 68/push 0/imm32/end - 5037 68/push 0/imm32/start - 5038 89/<- %ecx 4/r32/esp - 5039 # result = false - 5040 b8/copy-to-eax 0/imm32/false - 5041 (rewind-stream *(ebp+8)) - 5042 { - 5043 (next-mu-token *(ebp+8) %ecx) - 5044 # if slice-empty?(word-slice) break - 5045 (slice-empty? %ecx) - 5046 3d/compare-eax-and 0/imm32/false - 5047 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) - 5048 0f 85/jump-if-!= break/disp32 - 5049 # if slice-starts-with?(word-slice, '#') break - 5050 # . eax = *word-slice->start - 5051 8b/-> *ecx 0/r32/eax - 5052 8a/copy-byte *eax 0/r32/AL - 5053 81 4/subop/and %eax 0xff/imm32 - 5054 # . if (eax == '#') break - 5055 3d/compare-eax-and 0x23/imm32/hash - 5056 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) - 5057 0f 84/jump-if-= break/disp32 - 5058 # if slice-equal?(word-slice, '<-') return true - 5059 (slice-equal? %ecx "<-") - 5060 3d/compare-eax-and 0/imm32/false - 5061 74/jump-if-= loop/disp8 - 5062 b8/copy-to-eax 1/imm32/true - 5063 } - 5064 $stmt-has-outputs:end: - 5065 (rewind-stream *(ebp+8)) - 5066 # . reclaim locals - 5067 81 0/subop/add %esp 8/imm32 - 5068 # . restore registers - 5069 59/pop-to-ecx - 5070 # . epilogue - 5071 89/<- %esp 5/r32/ebp - 5072 5d/pop-to-ebp - 5073 c3/return + 2460 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2461 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 2462 (write _test-input-stream "}\n") + 2463 # convert + 2464 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2465 (flush _test-output-buffered-file) + 2466 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2472 # check output + 2473 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") + 2474 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") + 2475 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") + 2476 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") + 2477 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") + 2478 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") + 2479 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") + 2480 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") + 2481 # 2 * 4 bytes/elem + 4 bytes for length = offset 12 + 2482 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8") + 2483 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9") + 2484 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10") + 2485 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/11") + 2486 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/12") + 2487 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/13") + 2488 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/14") + 2489 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/15") + 2490 # . epilogue + 2491 89/<- %esp 5/r32/ebp + 2492 5d/pop-to-ebp + 2493 c3/return + 2494 + 2495 test-convert-index-into-array-on-stack: + 2496 # . prologue + 2497 55/push-ebp + 2498 89/<- %ebp 4/r32/esp + 2499 # setup + 2500 (clear-stream _test-input-stream) + 2501 (clear-stream $_test-input-buffered-file->buffer) + 2502 (clear-stream _test-output-stream) + 2503 (clear-stream $_test-output-buffered-file->buffer) + 2504 # + 2505 (write _test-input-stream "fn foo {\n") + 2506 (write _test-input-stream " var arr: (array int 3)\n") + 2507 (write _test-input-stream " var idx/eax: int <- copy 2\n") + 2508 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 2509 (write _test-input-stream "}\n") + 2510 # convert + 2511 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2512 (flush _test-output-buffered-file) + 2513 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2519 # check output + 2520 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") + 2521 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") + 2522 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") + 2523 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") + 2524 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") + 2525 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") + 2526 # var arr + 2527 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") + 2528 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") + 2529 # var idx + 2530 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") + 2531 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") + 2532 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc + 2533 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/10") + 2534 # reclaim idx + 2535 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/11") + 2536 # reclaim arr + 2537 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/12") + 2538 # + 2539 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/13") + 2540 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/14") + 2541 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/15") + 2542 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/16") + 2543 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/17") + 2544 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/18") + 2545 # . epilogue + 2546 89/<- %esp 5/r32/ebp + 2547 5d/pop-to-ebp + 2548 c3/return + 2549 + 2550 test-convert-index-into-array-on-stack-with-literal: + 2551 # . prologue + 2552 55/push-ebp + 2553 89/<- %ebp 4/r32/esp + 2554 # setup + 2555 (clear-stream _test-input-stream) + 2556 (clear-stream $_test-input-buffered-file->buffer) + 2557 (clear-stream _test-output-stream) + 2558 (clear-stream $_test-output-buffered-file->buffer) + 2559 # + 2560 (write _test-input-stream "fn foo {\n") + 2561 (write _test-input-stream " var arr: (array int 3)\n") + 2562 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 2563 (write _test-input-stream "}\n") + 2564 # convert + 2565 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2566 (flush _test-output-buffered-file) + 2567 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2573 # check output + 2574 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") + 2575 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") + 2576 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") + 2577 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") + 2578 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") + 2579 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") + 2580 # var arr + 2581 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") + 2582 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") + 2583 # var x + 2584 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") + 2585 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 + 2586 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/9") + 2587 # reclaim x + 2588 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/10") + 2589 # reclaim arr + 2590 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/11") + 2591 # + 2592 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/12") + 2593 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/13") + 2594 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/14") + 2595 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/15") + 2596 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") + 2597 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/17") + 2598 # . epilogue + 2599 89/<- %esp 5/r32/ebp + 2600 5d/pop-to-ebp + 2601 c3/return + 2602 + 2603 test-convert-index-into-array-using-offset: + 2604 # . prologue + 2605 55/push-ebp + 2606 89/<- %ebp 4/r32/esp + 2607 # setup + 2608 (clear-stream _test-input-stream) + 2609 (clear-stream $_test-input-buffered-file->buffer) + 2610 (clear-stream _test-output-stream) + 2611 (clear-stream $_test-output-buffered-file->buffer) + 2612 # + 2613 (write _test-input-stream "fn foo {\n") + 2614 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2615 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 2616 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 2617 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 2618 (write _test-input-stream "}\n") + 2619 # convert + 2620 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2621 (flush _test-output-buffered-file) + 2622 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2628 # check output + 2629 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") + 2630 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") + 2631 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") + 2632 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") + 2633 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") + 2634 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") + 2635 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") + 2636 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") + 2637 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") + 2638 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") + 2639 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 %ecx 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") + 2640 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/11") + 2641 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/12") + 2642 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/13") + 2643 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/14") + 2644 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/15") + 2645 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/16") + 2646 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/17") + 2647 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/18") + 2648 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/19") + 2649 # . epilogue + 2650 89/<- %esp 5/r32/ebp + 2651 5d/pop-to-ebp + 2652 c3/return + 2653 + 2654 test-convert-index-into-array-using-offset-on-stack: + 2655 # . prologue + 2656 55/push-ebp + 2657 89/<- %ebp 4/r32/esp + 2658 # setup + 2659 (clear-stream _test-input-stream) + 2660 (clear-stream $_test-input-buffered-file->buffer) + 2661 (clear-stream _test-output-stream) + 2662 (clear-stream $_test-output-buffered-file->buffer) + 2663 # + 2664 (write _test-input-stream "fn foo {\n") + 2665 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 2666 (write _test-input-stream " var idx: int\n") + 2667 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 2668 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 2669 (write _test-input-stream "}\n") + 2670 # convert + 2671 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2672 (flush _test-output-buffered-file) + 2673 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2679 # check output + 2680 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") + 2681 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") + 2682 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") + 2683 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") + 2684 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") + 2685 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") + 2686 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") + 2687 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") + 2688 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") + 2689 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") + 2690 (check-next-stream-line-equal _test-output-stream " 69/multiply 0x00000004/imm32 *(ebp+0xfffffff8) 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") + 2691 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/11") + 2692 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/12") + 2693 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/13") + 2694 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/14") + 2695 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/15") + 2696 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/16") + 2697 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/17") + 2698 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/18") + 2699 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/19") + 2700 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/20") + 2701 # . epilogue + 2702 89/<- %esp 5/r32/ebp + 2703 5d/pop-to-ebp + 2704 c3/return + 2705 + 2706 test-convert-function-and-type-definition: + 2707 # . prologue + 2708 55/push-ebp + 2709 89/<- %ebp 4/r32/esp + 2710 # setup + 2711 (clear-stream _test-input-stream) + 2712 (clear-stream $_test-input-buffered-file->buffer) + 2713 (clear-stream _test-output-stream) + 2714 (clear-stream $_test-output-buffered-file->buffer) + 2715 # + 2716 (write _test-input-stream "fn foo a: (addr t) {\n") + 2717 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") + 2718 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") + 2719 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") + 2720 (write _test-input-stream "}\n") + 2721 (write _test-input-stream "type t {\n") + 2722 (write _test-input-stream " x: int\n") + 2723 (write _test-input-stream " y: int\n") + 2724 (write _test-input-stream "}\n") + 2725 # convert + 2726 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2727 (flush _test-output-buffered-file) + 2728 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2734 # check output + 2735 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") + 2736 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") + 2737 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") + 2738 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") + 2739 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") + 2740 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") + 2741 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") + 2742 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") + 2743 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") + 2744 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") + 2745 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") + 2746 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") + 2747 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") + 2748 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") + 2749 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") + 2750 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") + 2751 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") + 2752 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") + 2753 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") + 2754 # . epilogue + 2755 89/<- %esp 5/r32/ebp + 2756 5d/pop-to-ebp + 2757 c3/return + 2758 + 2759 test-convert-function-with-local-var-with-user-defined-type: + 2760 # . prologue + 2761 55/push-ebp + 2762 89/<- %ebp 4/r32/esp + 2763 # setup + 2764 (clear-stream _test-input-stream) + 2765 (clear-stream $_test-input-buffered-file->buffer) + 2766 (clear-stream _test-output-stream) + 2767 (clear-stream $_test-output-buffered-file->buffer) + 2768 # + 2769 (write _test-input-stream "fn foo {\n") + 2770 (write _test-input-stream " var a: t\n") + 2771 (write _test-input-stream "}\n") + 2772 (write _test-input-stream "type t {\n") + 2773 (write _test-input-stream " x: int\n") + 2774 (write _test-input-stream " y: int\n") + 2775 (write _test-input-stream "}\n") + 2776 # convert + 2777 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2778 (flush _test-output-buffered-file) + 2779 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2785 # check output + 2786 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") + 2787 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") + 2788 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") + 2789 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") + 2790 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") + 2791 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") + 2792 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") + 2793 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") + 2794 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") + 2795 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") + 2796 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") + 2797 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") + 2798 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") + 2799 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") + 2800 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") + 2801 # . epilogue + 2802 89/<- %esp 5/r32/ebp + 2803 5d/pop-to-ebp + 2804 c3/return + 2805 + 2806 test-convert-get-of-type-on-stack: + 2807 # . prologue + 2808 55/push-ebp + 2809 89/<- %ebp 4/r32/esp + 2810 # setup + 2811 (clear-stream _test-input-stream) + 2812 (clear-stream $_test-input-buffered-file->buffer) + 2813 (clear-stream _test-output-stream) + 2814 (clear-stream $_test-output-buffered-file->buffer) + 2815 # + 2816 (write _test-input-stream "fn foo {\n") + 2817 (write _test-input-stream " var a: t\n") + 2818 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") + 2819 (write _test-input-stream "}\n") + 2820 (write _test-input-stream "type t {\n") + 2821 (write _test-input-stream " x: int\n") + 2822 (write _test-input-stream " y: int\n") + 2823 (write _test-input-stream "}\n") + 2824 # convert + 2825 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2826 (flush _test-output-buffered-file) + 2827 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2833 # check output + 2834 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-of-type-on-stack/0") + 2835 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-of-type-on-stack/1") + 2836 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-of-type-on-stack/2") + 2837 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-of-type-on-stack/3") + 2838 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-of-type-on-stack/4") + 2839 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-of-type-on-stack/5") + 2840 # var a + 2841 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/6") + 2842 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-of-type-on-stack/7") + 2843 # var c + 2844 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-of-type-on-stack/8") + 2845 # get + 2846 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-of-type-on-stack/9") + 2847 # reclaim c + 2848 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-of-type-on-stack/10") + 2849 # reclaim a + 2850 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-of-type-on-stack/11") + 2851 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-of-type-on-stack/12") + 2852 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-of-type-on-stack/13") + 2853 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-of-type-on-stack/14") + 2854 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-of-type-on-stack/15") + 2855 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-of-type-on-stack/16") + 2856 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-of-type-on-stack/17") + 2857 # . epilogue + 2858 89/<- %esp 5/r32/ebp + 2859 5d/pop-to-ebp + 2860 c3/return + 2861 + 2862 test-convert-array-of-user-defined-types: + 2863 # . prologue + 2864 55/push-ebp + 2865 89/<- %ebp 4/r32/esp + 2866 # setup + 2867 (clear-stream _test-input-stream) + 2868 (clear-stream $_test-input-buffered-file->buffer) + 2869 (clear-stream _test-output-stream) + 2870 (clear-stream $_test-output-buffered-file->buffer) + 2871 # + 2872 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 + 2873 (write _test-input-stream " x: int\n") + 2874 (write _test-input-stream " y: int\n") + 2875 (write _test-input-stream "}\n") + 2876 (write _test-input-stream "fn foo {\n") + 2877 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") + 2878 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 2879 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 2880 (write _test-input-stream "}\n") + 2881 # convert + 2882 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 2883 (flush _test-output-buffered-file) + 2884 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 2890 # check output + 2891 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") + 2892 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") + 2893 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") + 2894 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") + 2895 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") + 2896 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") + 2897 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") + 2898 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") + 2899 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") + 2900 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") + 2901 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11") + 2902 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/13") + 2903 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/14") + 2904 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/15") + 2905 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/16") + 2906 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/17") + 2907 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/18") + 2908 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/19") + 2909 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/20") + 2910 # . epilogue + 2911 89/<- %esp 5/r32/ebp + 2912 5d/pop-to-ebp + 2913 c3/return + 2914 + 2915 ####################################################### + 2916 # Parsing + 2917 ####################################################### + 2918 + 2919 parse-mu: # in: (addr buffered-file) + 2920 # pseudocode + 2921 # var curr-function: (addr (handle function)) = Program->functions + 2922 # var curr-type: (addr (handle typeinfo)) = Program->types + 2923 # var line: (stream byte 512) + 2924 # var word-slice: slice + 2925 # while true # line loop + 2926 # clear-stream(line) + 2927 # read-line-buffered(in, line) + 2928 # if (line->write == 0) break # end of file + 2929 # word-slice = next-mu-token(line) + 2930 # if slice-empty?(word-slice) # end of line + 2931 # continue + 2932 # else if slice-starts-with?(word-slice, "#") # comment + 2933 # continue # end of line + 2934 # else if slice-equal?(word-slice, "fn") + 2935 # var new-function: (handle function) = allocate(function) + 2936 # var vars: (stack (addr var) 256) + 2937 # populate-mu-function-header(in, new-function, vars) + 2938 # populate-mu-function-body(in, new-function, vars) + 2939 # assert(vars->top == 0) + 2940 # *curr-function = new-function + 2941 # curr-function = &new-function->next + 2942 # else if slice-equal?(word-slice, "type") + 2943 # word-slice = next-mu-token(line) + 2944 # type-id = pos-or-insert-slice(Type-id, word-slice) + 2945 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) + 2946 # assert(next-word(line) == "{") + 2947 # populate-mu-type(in, new-type) + 2948 # else + 2949 # abort() + 2950 # + 2951 # . prologue + 2952 55/push-ebp + 2953 89/<- %ebp 4/r32/esp + 2954 # . save registers + 2955 50/push-eax + 2956 51/push-ecx + 2957 52/push-edx + 2958 53/push-ebx + 2959 56/push-esi + 2960 57/push-edi + 2961 # var line/ecx: (stream byte 512) + 2962 81 5/subop/subtract %esp 0x200/imm32 + 2963 68/push 0x200/imm32/length + 2964 68/push 0/imm32/read + 2965 68/push 0/imm32/write + 2966 89/<- %ecx 4/r32/esp + 2967 # var word-slice/edx: slice + 2968 68/push 0/imm32/end + 2969 68/push 0/imm32/start + 2970 89/<- %edx 4/r32/esp + 2971 # var curr-function/edi: (addr (handle function)) + 2972 bf/copy-to-edi _Program-functions/imm32 + 2973 # var curr-type/esi: (addr (handle typeinfo)) + 2974 be/copy-to-esi _Program-types/imm32 + 2975 # var vars/ebx: (stack (addr var) 256) + 2976 81 5/subop/subtract %esp 0x400/imm32 + 2977 68/push 0x400/imm32/length + 2978 68/push 0/imm32/top + 2979 89/<- %ebx 4/r32/esp + 2980 { + 2981 $parse-mu:line-loop: + 2982 (clear-stream %ecx) + 2983 (read-line-buffered *(ebp+8) %ecx) + 2984 # if (line->write == 0) break + 2985 81 7/subop/compare *ecx 0/imm32 + 2986 0f 84/jump-if-= break/disp32 + 2987 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ + 2993 (next-mu-token %ecx %edx) + 2994 # if slice-empty?(word-slice) continue + 2995 (slice-empty? %edx) + 2996 3d/compare-eax-and 0/imm32/false + 2997 0f 85/jump-if-!= loop/disp32 + 2998 # if (*word-slice->start == "#") continue + 2999 # . eax = *word-slice->start + 3000 8b/-> *edx 0/r32/eax + 3001 8a/copy-byte *eax 0/r32/AL + 3002 81 4/subop/and %eax 0xff/imm32 + 3003 # . if (eax == '#') continue + 3004 3d/compare-eax-and 0x23/imm32/hash + 3005 0f 84/jump-if-= loop/disp32 + 3006 # if (slice-equal?(word-slice, "fn")) parse a function + 3007 { + 3008 $parse-mu:fn: + 3009 (slice-equal? %edx "fn") + 3010 3d/compare-eax-and 0/imm32/false + 3011 0f 84/jump-if-= break/disp32 + 3012 # var new-function/eax: (handle function) = populate-mu-function(line, in, vars) + 3013 (allocate Heap *Function-size) # => eax + 3014 (zero-out %eax *Function-size) + 3015 (clear-stack %ebx) + 3016 (populate-mu-function-header %ecx %eax %ebx) + 3017 (populate-mu-function-body *(ebp+8) %eax %ebx) + 3018 # *curr-function = new-function + 3019 89/<- *edi 0/r32/eax + 3020 # curr-function = &new-function->next + 3021 8d/address-> *(eax+0x14) 7/r32/edi # Function-next + 3022 e9/jump $parse-mu:line-loop/disp32 + 3023 } + 3024 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition + 3025 { + 3026 $parse-mu:type: + 3027 (slice-equal? %edx "type") + 3028 3d/compare-eax-and 0/imm32 + 3029 0f 84/jump-if-= break/disp32 + 3030 (next-mu-token %ecx %edx) + 3031 # var type-id/eax: int + 3032 (pos-or-insert-slice Type-id %edx) # => eax + 3033 # var new-type/eax: (handle typeinfo) + 3034 (find-or-create-typeinfo %eax) # => eax + 3035 # TODO: ensure that 'line' has nothing else but '{' + 3036 (populate-mu-type *(ebp+8) %eax) # => eax + 3037 e9/jump $parse-mu:line-loop/disp32 + 3038 } + 3039 # otherwise abort + 3040 e9/jump $parse-mu:error1/disp32 + 3041 } # end line loop + 3042 $parse-mu:end: + 3043 # . reclaim locals + 3044 81 0/subop/add %esp 0x630/imm32 + 3045 # . restore registers + 3046 5f/pop-to-edi + 3047 5e/pop-to-esi + 3048 5b/pop-to-ebx + 3049 5a/pop-to-edx + 3050 59/pop-to-ecx + 3051 58/pop-to-eax + 3052 # . epilogue + 3053 89/<- %esp 5/r32/ebp + 3054 5d/pop-to-ebp + 3055 c3/return + 3056 + 3057 $parse-mu:error1: + 3058 # error("unexpected top-level command: " word-slice "\n") + 3059 (write-buffered Stderr "unexpected top-level command: ") + 3060 (write-slice-buffered Stderr %edx) + 3061 (write-buffered Stderr "\n") + 3062 (flush Stderr) + 3063 # . syscall(exit, 1) + 3064 bb/copy-to-ebx 1/imm32 + 3065 b8/copy-to-eax 1/imm32/exit + 3066 cd/syscall 0x80/imm8 + 3067 # never gets here + 3068 + 3069 $parse-mu:error2: + 3070 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") + 3071 (print-int32-buffered Stderr *ebx) + 3072 (write-buffered Stderr " vars not reclaimed after fn '") + 3073 (write-slice-buffered Stderr *eax) # Function-name + 3074 (write-buffered Stderr "'\n") + 3075 (flush Stderr) + 3076 # . syscall(exit, 1) + 3077 bb/copy-to-ebx 1/imm32 + 3078 b8/copy-to-eax 1/imm32/exit + 3079 cd/syscall 0x80/imm8 + 3080 # never gets here + 3081 + 3082 # scenarios considered: + 3083 # ✗ fn foo # no block + 3084 # ✓ fn foo { + 3085 # ✗ fn foo { { + 3086 # ✗ fn foo { } + 3087 # ✗ fn foo { } { + 3088 # ✗ fn foo x { + 3089 # ✗ fn foo x: { + 3090 # ✓ fn foo x: int { + 3091 # ✓ fn foo x: int { + 3092 # ✓ fn foo x: int -> y/eax: int { + 3093 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) + 3094 # pseudocode: + 3095 # var name: slice + 3096 # next-mu-token(first-line, name) + 3097 # assert(name not in '{' '}' '->') + 3098 # out->name = slice-to-string(name) + 3099 # ## inouts + 3100 # while true + 3101 # ## name + 3102 # name = next-mu-token(first-line) + 3103 # if (name == '{') goto done + 3104 # if (name == '->') break + 3105 # assert(name != '}') + 3106 # var v: (handle var) = parse-var-with-type(name, first-line) + 3107 # assert(v->register == null) + 3108 # # v->block-depth is implicitly 0 + 3109 # out->inouts = append(out->inouts, v) + 3110 # push(vars, v) + 3111 # ## outputs + 3112 # while true + 3113 # ## name + 3114 # name = next-mu-token(first-line) + 3115 # assert(name not in '{' '}' '->') + 3116 # var v: (handle var) = parse-var-with-type(name, first-line) + 3117 # assert(v->register != null) + 3118 # out->outputs = append(out->outputs, v) + 3119 # done: + 3120 # + 3121 # . prologue + 3122 55/push-ebp + 3123 89/<- %ebp 4/r32/esp + 3124 # . save registers + 3125 50/push-eax + 3126 51/push-ecx + 3127 52/push-edx + 3128 53/push-ebx + 3129 57/push-edi + 3130 # edi = out + 3131 8b/-> *(ebp+0xc) 7/r32/edi + 3132 # var word-slice/ecx: slice + 3133 68/push 0/imm32/end + 3134 68/push 0/imm32/start + 3135 89/<- %ecx 4/r32/esp + 3136 # read function name + 3137 (next-mu-token *(ebp+8) %ecx) + 3138 # error checking + 3139 # TODO: error if name starts with 'break' or 'loop' + 3140 # if (word-slice == '{') abort + 3141 (slice-equal? %ecx "{") # => eax + 3142 3d/compare-eax-and 0/imm32/false + 3143 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3144 # if (word-slice == '->') abort + 3145 (slice-equal? %ecx "->") # => eax + 3146 3d/compare-eax-and 0/imm32/false + 3147 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3148 # if (word-slice == '}') abort + 3149 (slice-equal? %ecx "}") # => eax + 3150 3d/compare-eax-and 0/imm32/false + 3151 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3152 # save function name + 3153 (slice-to-string Heap %ecx) # => eax + 3154 89/<- *edi 0/r32/eax # Function-name + 3155 # initialize default subx-name as well + 3156 89/<- *(edi+4) 0/r32/eax # Function-subx-name + 3157 # save function inouts + 3158 { + 3159 $populate-mu-function-header:check-for-inout: + 3160 (next-mu-token *(ebp+8) %ecx) + 3161 # if (word-slice == '{') goto done + 3162 (slice-equal? %ecx "{") # => eax + 3163 3d/compare-eax-and 0/imm32/false + 3164 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 + 3165 # if (word-slice == '->') break + 3166 (slice-equal? %ecx "->") # => eax + 3167 3d/compare-eax-and 0/imm32/false + 3168 0f 85/jump-if-!= break/disp32 + 3169 # if (word-slice == '}') abort + 3170 (slice-equal? %ecx "}") # => eax + 3171 3d/compare-eax-and 0/imm32/false + 3172 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3173 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) + 3174 (parse-var-with-type %ecx *(ebp+8)) # => eax + 3175 89/<- %ebx 0/r32/eax + 3176 # assert(v->register == null) + 3177 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 3178 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 + 3179 # v->block-depth is implicitly 0 + 3180 # + 3181 # out->inouts = append(out->inouts, v) + 3182 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax + 3183 89/<- *(edi+8) 0/r32/eax # Function-inouts + 3184 # push(vars, v) + 3185 (push *(ebp+0x10) %ebx) + 3186 # + 3187 e9/jump loop/disp32 + 3188 } + 3189 # save function outputs + 3190 { + 3191 $populate-mu-function-header:check-for-out: + 3192 (next-mu-token *(ebp+8) %ecx) + 3193 # if (word-slice == '{') break + 3194 (slice-equal? %ecx "{") # => eax + 3195 3d/compare-eax-and 0/imm32/false + 3196 0f 85/jump-if-!= break/disp32 + 3197 # if (word-slice == '->') abort + 3198 (slice-equal? %ecx "->") # => eax + 3199 3d/compare-eax-and 0/imm32/false + 3200 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3201 # if (word-slice == '}') abort + 3202 (slice-equal? %ecx "}") # => eax + 3203 3d/compare-eax-and 0/imm32/false + 3204 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + 3205 # + 3206 (parse-var-with-type %ecx *(ebp+8)) # => eax + 3207 89/<- %ebx 0/r32/eax + 3208 # assert(var->register != null) + 3209 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 3210 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 + 3211 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax + 3212 89/<- *(edi+0xc) 0/r32/eax # Function-outputs + 3213 e9/jump loop/disp32 + 3214 } + 3215 $populate-mu-function-header:done: + 3216 (check-no-tokens-left *(ebp+8)) + 3217 $populate-mu-function-header:end: + 3218 # . reclaim locals + 3219 81 0/subop/add %esp 8/imm32 + 3220 # . restore registers + 3221 5f/pop-to-edi + 3222 5b/pop-to-ebx + 3223 5a/pop-to-edx + 3224 59/pop-to-ecx + 3225 58/pop-to-eax + 3226 # . epilogue + 3227 89/<- %esp 5/r32/ebp + 3228 5d/pop-to-ebp + 3229 c3/return + 3230 + 3231 $populate-mu-function-header:error1: + 3232 # error("function header not in form 'fn <name> {'") + 3233 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") + 3234 (flush Stderr) + 3235 (rewind-stream *(ebp+8)) + 3236 (write-stream 2 *(ebp+8)) + 3237 (write-buffered Stderr "'\n") + 3238 (flush Stderr) + 3239 # . syscall(exit, 1) + 3240 bb/copy-to-ebx 1/imm32 + 3241 b8/copy-to-eax 1/imm32/exit + 3242 cd/syscall 0x80/imm8 + 3243 # never gets here + 3244 + 3245 $populate-mu-function-header:error2: + 3246 # error("function input '" var "' cannot be in a register") + 3247 (write-buffered Stderr "function input '") + 3248 (write-buffered Stderr *ebx) # Var-name + 3249 (write-buffered Stderr "' cannot be in a register") + 3250 (flush Stderr) + 3251 # . syscall(exit, 1) + 3252 bb/copy-to-ebx 1/imm32 + 3253 b8/copy-to-eax 1/imm32/exit + 3254 cd/syscall 0x80/imm8 + 3255 # never gets here + 3256 + 3257 $populate-mu-function-header:error3: + 3258 # error("function input '" var "' must be in a register") + 3259 (write-buffered Stderr "function input '") + 3260 (write-buffered Stderr *eax) # Var-name + 3261 (write-buffered Stderr " must be in a register'") + 3262 (flush Stderr) + 3263 (rewind-stream *(ebp+8)) + 3264 (write-stream 2 *(ebp+8)) + 3265 (write-buffered Stderr "'\n") + 3266 (flush Stderr) + 3267 # . syscall(exit, 1) + 3268 bb/copy-to-ebx 1/imm32 + 3269 b8/copy-to-eax 1/imm32/exit + 3270 cd/syscall 0x80/imm8 + 3271 # never gets here + 3272 + 3273 test-function-header-with-arg: + 3274 # . prologue + 3275 55/push-ebp + 3276 89/<- %ebp 4/r32/esp + 3277 # setup + 3278 (clear-stream _test-input-stream) + 3279 (write _test-input-stream "foo n: int {\n") + 3280 # var result/ecx: function + 3281 2b/subtract-> *Function-size 4/r32/esp + 3282 89/<- %ecx 4/r32/esp + 3283 (zero-out %ecx *Function-size) + 3284 # var vars/ebx: (stack (addr var) 16) + 3285 81 5/subop/subtract %esp 0x10/imm32 + 3286 68/push 0x10/imm32/length + 3287 68/push 0/imm32/top + 3288 89/<- %ebx 4/r32/esp + 3289 # convert + 3290 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3291 # check result + 3292 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name + 3293 # edx: (handle list var) = result->inouts + 3294 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3295 # ebx: (handle var) = result->inouts->value + 3296 8b/-> *edx 3/r32/ebx # List-value + 3297 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name + 3298 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3299 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left + 3300 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right + 3301 # . epilogue + 3302 89/<- %esp 5/r32/ebp + 3303 5d/pop-to-ebp + 3304 c3/return + 3305 + 3306 test-function-header-with-multiple-args: + 3307 # . prologue + 3308 55/push-ebp + 3309 89/<- %ebp 4/r32/esp + 3310 # setup + 3311 (clear-stream _test-input-stream) + 3312 (write _test-input-stream "foo a: int, b: int c: int {\n") + 3313 # result/ecx: (handle function) + 3314 2b/subtract-> *Function-size 4/r32/esp + 3315 89/<- %ecx 4/r32/esp + 3316 (zero-out %ecx *Function-size) + 3317 # var vars/ebx: (stack (addr var) 16) + 3318 81 5/subop/subtract %esp 0x10/imm32 + 3319 68/push 0x10/imm32/length + 3320 68/push 0/imm32/top + 3321 89/<- %ebx 4/r32/esp + 3322 # convert + 3323 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3324 # check result + 3325 (check-strings-equal *ecx "foo") # Function-name + 3326 # edx: (handle list var) = result->inouts + 3327 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3328 $test-function-header-with-multiple-args:inout0: + 3329 # ebx: (handle var) = result->inouts->value + 3330 8b/-> *edx 3/r32/ebx # List-value + 3331 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name + 3332 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3333 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left + 3334 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right + 3335 # edx = result->inouts->next + 3336 8b/-> *(edx+4) 2/r32/edx # List-next + 3337 $test-function-header-with-multiple-args:inout1: + 3338 # ebx = result->inouts->next->value + 3339 8b/-> *edx 3/r32/ebx # List-value + 3340 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name + 3341 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3342 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left + 3343 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right + 3344 # edx = result->inouts->next->next + 3345 8b/-> *(edx+4) 2/r32/edx # List-next + 3346 $test-function-header-with-multiple-args:inout2: + 3347 # ebx = result->inouts->next->next->value + 3348 8b/-> *edx 3/r32/ebx # List-value + 3349 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name + 3350 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3351 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left + 3352 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right + 3353 # . epilogue + 3354 89/<- %esp 5/r32/ebp + 3355 5d/pop-to-ebp + 3356 c3/return + 3357 + 3358 test-function-with-multiple-args-and-outputs: + 3359 # . prologue + 3360 55/push-ebp + 3361 89/<- %ebp 4/r32/esp + 3362 # setup + 3363 (clear-stream _test-input-stream) + 3364 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") + 3365 # result/ecx: (handle function) + 3366 2b/subtract-> *Function-size 4/r32/esp + 3367 89/<- %ecx 4/r32/esp + 3368 (zero-out %ecx *Function-size) + 3369 # var vars/ebx: (stack (addr var) 16) + 3370 81 5/subop/subtract %esp 0x10/imm32 + 3371 68/push 0x10/imm32/length + 3372 68/push 0/imm32/top + 3373 89/<- %ebx 4/r32/esp + 3374 # convert + 3375 (populate-mu-function-header _test-input-stream %ecx %ebx) + 3376 # check result + 3377 (check-strings-equal *ecx "foo") # Function-name + 3378 # edx: (handle list var) = result->inouts + 3379 8b/-> *(ecx+8) 2/r32/edx # Function-inouts + 3380 # ebx: (handle var) = result->inouts->value + 3381 8b/-> *edx 3/r32/ebx # List-value + 3382 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name + 3383 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3384 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left + 3385 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right + 3386 # edx = result->inouts->next + 3387 8b/-> *(edx+4) 2/r32/edx # List-next + 3388 # ebx = result->inouts->next->value + 3389 8b/-> *edx 3/r32/ebx # List-value + 3390 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name + 3391 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3392 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left + 3393 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right + 3394 # edx = result->inouts->next->next + 3395 8b/-> *(edx+4) 2/r32/edx # List-next + 3396 # ebx = result->inouts->next->next->value + 3397 8b/-> *edx 3/r32/ebx # List-value + 3398 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name + 3399 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3400 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left + 3401 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right + 3402 # edx: (handle list var) = result->outputs + 3403 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs + 3404 # ebx: (handle var) = result->outputs->value + 3405 8b/-> *edx 3/r32/ebx # List-value + 3406 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name + 3407 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register + 3408 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3409 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left + 3410 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right + 3411 # edx = result->outputs->next + 3412 8b/-> *(edx+4) 2/r32/edx # List-next + 3413 # ebx = result->outputs->next->value + 3414 8b/-> *edx 3/r32/ebx # List-value + 3415 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name + 3416 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register + 3417 8b/-> *(ebx+4) 3/r32/ebx # Var-type + 3418 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left + 3419 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right + 3420 # . epilogue + 3421 89/<- %esp 5/r32/ebp + 3422 5d/pop-to-ebp + 3423 c3/return + 3424 + 3425 # format for variables with types + 3426 # x: int + 3427 # x: int, + 3428 # x/eax: int + 3429 # x/eax: int, + 3430 # ignores at most one trailing comma + 3431 # WARNING: modifies name + 3432 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) + 3433 # pseudocode: + 3434 # var s: slice + 3435 # if (!slice-ends-with(name, ":")) + 3436 # abort + 3437 # --name->end to skip ':' + 3438 # next-token-from-slice(name->start, name->end, '/', s) + 3439 # result = new-var-from-slice(s) + 3440 # ## register + 3441 # next-token-from-slice(s->end, name->end, '/', s) + 3442 # if (!slice-empty?(s)) + 3443 # v->register = slice-to-string(s) + 3444 # ## type + 3445 # var type: (handle tree type-id) = parse-type(first-line) + 3446 # v->type = type + 3447 # return v + 3448 # + 3449 # . prologue + 3450 55/push-ebp + 3451 89/<- %ebp 4/r32/esp + 3452 # . save registers + 3453 51/push-ecx + 3454 52/push-edx + 3455 53/push-ebx + 3456 56/push-esi + 3457 57/push-edi + 3458 # esi = name + 3459 8b/-> *(ebp+8) 6/r32/esi + 3460 # if (!slice-ends-with?(name, ":")) abort + 3461 8b/-> *(esi+4) 1/r32/ecx # Slice-end + 3462 49/decrement-ecx + 3463 8a/copy-byte *ecx 1/r32/CL + 3464 81 4/subop/and %ecx 0xff/imm32 + 3465 81 7/subop/compare %ecx 0x3a/imm32/colon + 3466 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 + 3467 # --name->end to skip ':' + 3468 ff 1/subop/decrement *(esi+4) + 3469 # var s/ecx: slice + 3470 68/push 0/imm32/end + 3471 68/push 0/imm32/start + 3472 89/<- %ecx 4/r32/esp + 3473 $parse-var-with-type:parse-name: + 3474 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' + 3475 $parse-var-with-type:create-var: + 3476 # edi = new-var-from-slice(s) + 3477 (new-var-from-slice Heap %ecx) # => eax + 3478 89/<- %edi 0/r32/eax + 3479 # save v->register + 3480 $parse-var-with-type:save-register: + 3481 # s = next-token(...) + 3482 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' + 3483 # if (!slice-empty?(s)) v->register = slice-to-string(s) + 3484 { + 3485 $parse-var-with-type:write-register: + 3486 (slice-empty? %ecx) # => eax + 3487 3d/compare-eax-and 0/imm32/false + 3488 75/jump-if-!= break/disp8 + 3489 (slice-to-string Heap %ecx) + 3490 89/<- *(edi+0x10) 0/r32/eax # Var-register + 3491 } + 3492 $parse-var-with-type:save-type: + 3493 (parse-type Heap *(ebp+0xc)) # => eax + 3494 #? (write-buffered Stderr "saving to var ") + 3495 #? (print-int32-buffered Stderr %edi) + 3496 #? (write-buffered Stderr Newline) + 3497 #? (flush Stderr) + 3498 89/<- *(edi+4) 0/r32/eax # Var-type + 3499 $parse-var-with-type:end: + 3500 # return result + 3501 89/<- %eax 7/r32/edi + 3502 # . reclaim locals + 3503 81 0/subop/add %esp 8/imm32 + 3504 # . restore registers + 3505 5f/pop-to-edi + 3506 5e/pop-to-esi + 3507 5b/pop-to-ebx + 3508 5a/pop-to-edx + 3509 59/pop-to-ecx + 3510 # . epilogue + 3511 89/<- %esp 5/r32/ebp + 3512 5d/pop-to-ebp + 3513 c3/return + 3514 + 3515 $parse-var-with-type:abort: + 3516 # error("var should have form 'name: type' in '" line "'\n") + 3517 (write-buffered Stderr "var should have form 'name: type' in '") + 3518 (flush Stderr) + 3519 (rewind-stream *(ebp+0xc)) + 3520 (write-stream 2 *(ebp+0xc)) + 3521 (write-buffered Stderr "'\n") + 3522 (flush Stderr) + 3523 # . syscall(exit, 1) + 3524 bb/copy-to-ebx 1/imm32 + 3525 b8/copy-to-eax 1/imm32/exit + 3526 cd/syscall 0x80/imm8 + 3527 # never gets here + 3528 + 3529 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) + 3530 # pseudocode: + 3531 # var s: slice = next-mu-token(in) + 3532 # assert s != "" + 3533 # assert s != "->" + 3534 # assert s != "{" + 3535 # assert s != "}" + 3536 # if s == ")" + 3537 # return 0 + 3538 # result = allocate(Tree) + 3539 # zero-out(result, *Tree-size) + 3540 # if s != "(" + 3541 # result->left = pos-or-insert-slice(Type-id, s) + 3542 # return + 3543 # result->left = parse-type(ad, in) + 3544 # result->right = parse-type-tree(ad, in) + 3545 # + 3546 # . prologue + 3547 55/push-ebp + 3548 89/<- %ebp 4/r32/esp + 3549 # . save registers + 3550 51/push-ecx + 3551 52/push-edx + 3552 # var s/ecx: slice + 3553 68/push 0/imm32 + 3554 68/push 0/imm32 + 3555 89/<- %ecx 4/r32/esp + 3556 # s = next-mu-token(in) + 3557 (next-mu-token *(ebp+0xc) %ecx) + 3558 #? (write-buffered Stderr "tok: ") + 3559 #? (write-slice-buffered Stderr %ecx) + 3560 #? (write-buffered Stderr "$\n") + 3561 #? (flush Stderr) + 3562 # assert s != "" + 3563 (slice-equal? %ecx "") + 3564 3d/compare-eax-and 0/imm32/false + 3565 0f 85/jump-if-!= $parse-type:abort/disp32 + 3566 # assert s != "{" + 3567 (slice-equal? %ecx "{") + 3568 3d/compare-eax-and 0/imm32/false + 3569 0f 85/jump-if-!= $parse-type:abort/disp32 + 3570 # assert s != "}" + 3571 (slice-equal? %ecx "}") + 3572 3d/compare-eax-and 0/imm32/false + 3573 0f 85/jump-if-!= $parse-type:abort/disp32 + 3574 # assert s != "->" + 3575 (slice-equal? %ecx "->") + 3576 3d/compare-eax-and 0/imm32/false + 3577 0f 85/jump-if-!= $parse-type:abort/disp32 + 3578 # if (s == ")") return 0 + 3579 (slice-equal? %ecx ")") + 3580 3d/compare-eax-and 0/imm32/false + 3581 b8/copy-to-eax 0/imm32 + 3582 0f 85/jump-if-!= $parse-type:end/disp32 + 3583 # var result/edx: (handle tree type-id) + 3584 (allocate *(ebp+8) *Tree-size) # => eax + 3585 (zero-out %eax *Tree-size) + 3586 89/<- %edx 0/r32/eax + 3587 { + 3588 # if (s != "(") break + 3589 (slice-equal? %ecx "(") + 3590 3d/compare-eax-and 0/imm32/false + 3591 75/jump-if-!= break/disp8 + 3592 # EGREGIOUS HACK for static array sizes: if s is a number, parse it + 3593 { + 3594 (is-hex-int? %ecx) # => eax + 3595 3d/compare-eax-and 0/imm32/false + 3596 74/jump-if-= break/disp8 + 3597 (parse-hex-int-from-slice %ecx) # => eax + 3598 89/<- *edx 0/r32/eax # Tree-left + 3599 e9/jump $parse-type:return-edx/disp32 + 3600 } + 3601 # result->left = pos-or-insert-slice(Type-id, s) + 3602 (pos-or-insert-slice Type-id %ecx) # => eax + 3603 #? (write-buffered Stderr "=> {") + 3604 #? (print-int32-buffered Stderr %eax) + 3605 #? (write-buffered Stderr ", 0}\n") + 3606 #? (flush Stderr) + 3607 89/<- *edx 0/r32/eax # Tree-left + 3608 e9/jump $parse-type:return-edx/disp32 + 3609 } + 3610 # otherwise s == "(" + 3611 # result->left = parse-type(ad, in) + 3612 (parse-type *(ebp+8) *(ebp+0xc)) + 3613 #? (write-buffered Stderr "=> {") + 3614 #? (print-int32-buffered Stderr %eax) + 3615 89/<- *edx 0/r32/eax # Tree-left + 3616 # result->right = parse-type-tree(ad, in) + 3617 (parse-type-tree *(ebp+8) *(ebp+0xc)) + 3618 #? (write-buffered Stderr Space) + 3619 #? (print-int32-buffered Stderr %eax) + 3620 #? (write-buffered Stderr "}\n") + 3621 #? (flush Stderr) + 3622 89/<- *(edx+4) 0/r32/eax # Tree-right + 3623 $parse-type:return-edx: + 3624 89/<- %eax 2/r32/edx + 3625 $parse-type:end: + 3626 # . reclaim locals + 3627 81 0/subop/add %esp 8/imm32 + 3628 # . restore registers + 3629 5a/pop-to-edx + 3630 59/pop-to-ecx + 3631 # . epilogue + 3632 89/<- %esp 5/r32/ebp + 3633 5d/pop-to-ebp + 3634 c3/return + 3635 + 3636 $parse-type:abort: + 3637 # error("unexpected token when parsing type: '" s "'\n") + 3638 (write-buffered Stderr "unexpected token when parsing type: '") + 3639 (write-slice-buffered Stderr %ecx) + 3640 (write-buffered Stderr "'\n") + 3641 (flush Stderr) + 3642 # . syscall(exit, 1) + 3643 bb/copy-to-ebx 1/imm32 + 3644 b8/copy-to-eax 1/imm32/exit + 3645 cd/syscall 0x80/imm8 + 3646 # never gets here + 3647 + 3648 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) + 3649 # pseudocode: + 3650 # var tmp: (handle tree type-id) = parse-type(ad, in) + 3651 # if tmp == 0 + 3652 # return 0 + 3653 # result = allocate(Tree) + 3654 # zero-out(result, *Tree-size) + 3655 # result->left = tmp + 3656 # result->right = parse-type-tree(ad, in) + 3657 # + 3658 # . prologue + 3659 55/push-ebp + 3660 89/<- %ebp 4/r32/esp + 3661 # . save registers + 3662 51/push-ecx + 3663 52/push-edx + 3664 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) + 3665 (parse-type *(ebp+8) *(ebp+0xc)) + 3666 # if (tmp == 0) return tmp + 3667 3d/compare-eax-and 0/imm32 + 3668 74/jump-if-= $parse-type-tree:end/disp8 + 3669 # var tmp2/ecx = tmp + 3670 89/<- %ecx 0/r32/eax + 3671 # var result/edx: (handle tree type-id) + 3672 (allocate *(ebp+8) *Tree-size) # => eax + 3673 (zero-out %eax *Tree-size) + 3674 89/<- %edx 0/r32/eax + 3675 # result->left = tmp2 + 3676 89/<- *edx 1/r32/ecx # Tree-left + 3677 # result->right = parse-type-tree(ad, in) + 3678 (parse-type-tree *(ebp+8) *(ebp+0xc)) + 3679 89/<- *(edx+4) 0/r32/eax # Tree-right + 3680 $parse-type-tree:return-edx: + 3681 89/<- %eax 2/r32/edx + 3682 $parse-type-tree:end: + 3683 # . restore registers + 3684 5a/pop-to-edx + 3685 59/pop-to-ecx + 3686 # . epilogue + 3687 89/<- %esp 5/r32/ebp + 3688 5d/pop-to-ebp + 3689 c3/return + 3690 + 3691 next-mu-token: # in: (addr stream byte), out: (addr slice) + 3692 # pseudocode: + 3693 # start: + 3694 # skip-chars-matching-whitespace(in) + 3695 # if in->read >= in->write # end of in + 3696 # out = {0, 0} + 3697 # return + 3698 # out->start = &in->data[in->read] + 3699 # var curr-byte/eax: byte = in->data[in->read] + 3700 # if curr->byte == ',' # comment token + 3701 # ++in->read + 3702 # goto start + 3703 # if curr-byte == '#' # comment + 3704 # goto done # treat as eof + 3705 # if curr-byte == '"' # string literal + 3706 # skip-string(in) + 3707 # goto done # no metadata + 3708 # if curr-byte == '(' + 3709 # ++in->read + 3710 # goto done + 3711 # if curr-byte == ')' + 3712 # ++in->read + 3713 # goto done + 3714 # # read a word + 3715 # while true + 3716 # if in->read >= in->write + 3717 # break + 3718 # curr-byte = in->data[in->read] + 3719 # if curr-byte == ' ' + 3720 # break + 3721 # if curr-byte == '\r' + 3722 # break + 3723 # if curr-byte == '\n' + 3724 # break + 3725 # if curr-byte == '(' + 3726 # break + 3727 # if curr-byte == ')' + 3728 # break + 3729 # if curr-byte == ',' + 3730 # break + 3731 # ++in->read + 3732 # done: + 3733 # out->end = &in->data[in->read] + 3734 # + 3735 # . prologue + 3736 55/push-ebp + 3737 89/<- %ebp 4/r32/esp + 3738 # . save registers + 3739 50/push-eax + 3740 51/push-ecx + 3741 56/push-esi + 3742 57/push-edi + 3743 # esi = in + 3744 8b/-> *(ebp+8) 6/r32/esi + 3745 # edi = out + 3746 8b/-> *(ebp+0xc) 7/r32/edi + 3747 $next-mu-token:start: + 3748 (skip-chars-matching-whitespace %esi) + 3749 $next-mu-token:check0: + 3750 # if (in->read >= in->write) return out = {0, 0} + 3751 # . ecx = in->read + 3752 8b/-> *(esi+4) 1/r32/ecx + 3753 # . if (ecx >= in->write) return out = {0, 0} + 3754 3b/compare 1/r32/ecx *esi + 3755 c7 0/subop/copy *edi 0/imm32 + 3756 c7 0/subop/copy *(edi+4) 0/imm32 + 3757 0f 8d/jump-if->= $next-mu-token:end/disp32 + 3758 # out->start = &in->data[in->read] + 3759 8d/copy-address *(esi+ecx+0xc) 0/r32/eax + 3760 89/<- *edi 0/r32/eax + 3761 # var curr-byte/eax: byte = in->data[in->read] + 3762 31/xor %eax 0/r32/eax + 3763 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL + 3764 { + 3765 $next-mu-token:check-for-comma: + 3766 # if (curr-byte != ',') break + 3767 3d/compare-eax-and 0x2c/imm32/comma + 3768 75/jump-if-!= break/disp8 + 3769 # ++in->read + 3770 ff 0/subop/increment *(esi+4) + 3771 # restart + 3772 e9/jump $next-mu-token:start/disp32 + 3773 } + 3774 { + 3775 $next-mu-token:check-for-comment: + 3776 # if (curr-byte != '#') break + 3777 3d/compare-eax-and 0x23/imm32/pound + 3778 75/jump-if-!= break/disp8 + 3779 # return eof + 3780 e9/jump $next-mu-token:done/disp32 + 3781 } + 3782 { + 3783 $next-mu-token:check-for-string-literal: + 3784 # if (curr-byte != '"') break + 3785 3d/compare-eax-and 0x22/imm32/dquote + 3786 75/jump-if-!= break/disp8 + 3787 (skip-string %esi) + 3788 # return + 3789 e9/jump $next-mu-token:done/disp32 + 3790 } + 3791 { + 3792 $next-mu-token:check-for-open-paren: + 3793 # if (curr-byte != '(') break + 3794 3d/compare-eax-and 0x28/imm32/open-paren + 3795 75/jump-if-!= break/disp8 + 3796 # ++in->read + 3797 ff 0/subop/increment *(esi+4) + 3798 # return + 3799 e9/jump $next-mu-token:done/disp32 + 3800 } + 3801 { + 3802 $next-mu-token:check-for-close-paren: + 3803 # if (curr-byte != ')') break + 3804 3d/compare-eax-and 0x29/imm32/close-paren + 3805 75/jump-if-!= break/disp8 + 3806 # ++in->read + 3807 ff 0/subop/increment *(esi+4) + 3808 # return + 3809 e9/jump $next-mu-token:done/disp32 + 3810 } + 3811 { + 3812 $next-mu-token:regular-word-without-metadata: + 3813 # if (in->read >= in->write) break + 3814 # . ecx = in->read + 3815 8b/-> *(esi+4) 1/r32/ecx + 3816 # . if (ecx >= in->write) break + 3817 3b/compare *esi 1/r32/ecx + 3818 7d/jump-if->= break/disp8 + 3819 # var c/eax: byte = in->data[in->read] + 3820 31/xor %eax 0/r32/eax + 3821 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL + 3822 # if (c == ' ') break + 3823 3d/compare-eax-and 0x20/imm32/space + 3824 74/jump-if-= break/disp8 + 3825 # if (c == '\r') break + 3826 3d/compare-eax-and 0xd/imm32/carriage-return + 3827 74/jump-if-= break/disp8 + 3828 # if (c == '\n') break + 3829 3d/compare-eax-and 0xa/imm32/newline + 3830 74/jump-if-= break/disp8 + 3831 # if (c == '(') break + 3832 3d/compare-eax-and 0x28/imm32/open-paren + 3833 0f 84/jump-if-= break/disp32 + 3834 # if (c == ')') break + 3835 3d/compare-eax-and 0x29/imm32/close-paren + 3836 0f 84/jump-if-= break/disp32 + 3837 # if (c == ',') break + 3838 3d/compare-eax-and 0x2c/imm32/comma + 3839 0f 84/jump-if-= break/disp32 + 3840 # ++in->read + 3841 ff 0/subop/increment *(esi+4) + 3842 # + 3843 e9/jump loop/disp32 + 3844 } + 3845 $next-mu-token:done: + 3846 # out->end = &in->data[in->read] + 3847 8b/-> *(esi+4) 1/r32/ecx + 3848 8d/copy-address *(esi+ecx+0xc) 0/r32/eax + 3849 89/<- *(edi+4) 0/r32/eax + 3850 $next-mu-token:end: + 3851 # . restore registers + 3852 5f/pop-to-edi + 3853 5e/pop-to-esi + 3854 59/pop-to-ecx + 3855 58/pop-to-eax + 3856 # . epilogue + 3857 89/<- %esp 5/r32/ebp + 3858 5d/pop-to-ebp + 3859 c3/return + 3860 + 3861 pos-or-insert-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int + 3862 # . prologue + 3863 55/push-ebp + 3864 89/<- %ebp 4/r32/esp + 3865 # if (pos-slice(arr, s) != -1) return it + 3866 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax + 3867 3d/compare-eax-and -1/imm32 + 3868 75/jump-if-!= $pos-or-insert-slice:end/disp8 + 3869 $pos-or-insert-slice:insert: + 3870 (slice-to-string Heap *(ebp+0xc)) # => eax + 3871 (write-int *(ebp+8) %eax) + 3872 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax + 3873 $pos-or-insert-slice:end: + 3874 # . epilogue + 3875 89/<- %esp 5/r32/ebp + 3876 5d/pop-to-ebp + 3877 c3/return + 3878 + 3879 # return the index in an array of strings matching 's', -1 if not found + 3880 # index is denominated in elements, not bytes + 3881 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int + 3882 # . prologue + 3883 55/push-ebp + 3884 89/<- %ebp 4/r32/esp + 3885 # . save registers + 3886 51/push-ecx + 3887 52/push-edx + 3888 53/push-ebx + 3889 56/push-esi + 3890 #? (write-buffered Stderr "pos-slice: ") + 3891 #? (write-slice-buffered Stderr *(ebp+0xc)) + 3892 #? (write-buffered Stderr "\n") + 3893 #? (flush Stderr) + 3894 # esi = arr + 3895 8b/-> *(ebp+8) 6/r32/esi + 3896 # var index/ecx: int = 0 + 3897 b9/copy-to-ecx 0/imm32 + 3898 # var curr/edx: (addr (addr array byte)) = arr->data + 3899 8d/copy-address *(esi+0xc) 2/r32/edx + 3900 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] + 3901 8b/-> *esi 3/r32/ebx + 3902 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx + 3903 { + 3904 #? (write-buffered Stderr " ") + 3905 #? (print-int32-buffered Stderr %ecx) + 3906 #? (write-buffered Stderr "\n") + 3907 #? (flush Stderr) + 3908 # if (curr >= max) return -1 + 3909 39/compare %edx 3/r32/ebx + 3910 b8/copy-to-eax -1/imm32 + 3911 73/jump-if-addr>= $pos-slice:end/disp8 + 3912 # if (slice-equal?(s, *curr)) break + 3913 (slice-equal? *(ebp+0xc) *edx) # => eax + 3914 3d/compare-eax-and 0/imm32/false + 3915 75/jump-if-!= break/disp8 + 3916 # ++index + 3917 41/increment-ecx + 3918 # curr += 4 + 3919 81 0/subop/add %edx 4/imm32 + 3920 # + 3921 eb/jump loop/disp8 + 3922 } + 3923 # return index + 3924 89/<- %eax 1/r32/ecx + 3925 $pos-slice:end: + 3926 #? (write-buffered Stderr "=> ") + 3927 #? (print-int32-buffered Stderr %eax) + 3928 #? (write-buffered Stderr "\n") + 3929 # . restore registers + 3930 5e/pop-to-esi + 3931 5b/pop-to-ebx + 3932 5a/pop-to-edx + 3933 59/pop-to-ecx + 3934 # . epilogue + 3935 89/<- %esp 5/r32/ebp + 3936 5d/pop-to-ebp + 3937 c3/return + 3938 + 3939 test-parse-var-with-type: + 3940 # . prologue + 3941 55/push-ebp + 3942 89/<- %ebp 4/r32/esp + 3943 # (eax..ecx) = "x:" + 3944 b8/copy-to-eax "x:"/imm32 + 3945 8b/-> *eax 1/r32/ecx + 3946 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 3947 05/add-to-eax 4/imm32 + 3948 # var slice/ecx: slice = {eax, ecx} + 3949 51/push-ecx + 3950 50/push-eax + 3951 89/<- %ecx 4/r32/esp + 3952 # _test-input-stream contains "int" + 3953 (clear-stream _test-input-stream) + 3954 (write _test-input-stream "int") + 3955 # + 3956 (parse-var-with-type %ecx _test-input-stream) + 3957 8b/-> *eax 2/r32/edx # Var-name + 3958 (check-strings-equal %edx "x" "F - test-var-with-type/name") + 3959 8b/-> *(eax+4) 2/r32/edx # Var-type + 3960 (check-ints-equal *edx 1 "F - test-var-with-type/type") + 3961 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") + 3962 # . epilogue + 3963 89/<- %esp 5/r32/ebp + 3964 5d/pop-to-ebp + 3965 c3/return + 3966 + 3967 test-parse-var-with-type-and-register: + 3968 # . prologue + 3969 55/push-ebp + 3970 89/<- %ebp 4/r32/esp + 3971 # (eax..ecx) = "x/eax:" + 3972 b8/copy-to-eax "x/eax:"/imm32 + 3973 8b/-> *eax 1/r32/ecx + 3974 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 3975 05/add-to-eax 4/imm32 + 3976 # var slice/ecx: slice = {eax, ecx} + 3977 51/push-ecx + 3978 50/push-eax + 3979 89/<- %ecx 4/r32/esp + 3980 # _test-input-stream contains "int" + 3981 (clear-stream _test-input-stream) + 3982 (write _test-input-stream "int") + 3983 # + 3984 (parse-var-with-type %ecx _test-input-stream) + 3985 8b/-> *eax 2/r32/edx # Var-name + 3986 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") + 3987 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 3988 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") + 3989 8b/-> *(eax+4) 2/r32/edx # Var-type + 3990 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") + 3991 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") + 3992 # . epilogue + 3993 89/<- %esp 5/r32/ebp + 3994 5d/pop-to-ebp + 3995 c3/return + 3996 + 3997 test-parse-var-with-trailing-characters: + 3998 # . prologue + 3999 55/push-ebp + 4000 89/<- %ebp 4/r32/esp + 4001 # (eax..ecx) = "x:" + 4002 b8/copy-to-eax "x:"/imm32 + 4003 8b/-> *eax 1/r32/ecx + 4004 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4005 05/add-to-eax 4/imm32 + 4006 # var slice/ecx: slice = {eax, ecx} + 4007 51/push-ecx + 4008 50/push-eax + 4009 89/<- %ecx 4/r32/esp + 4010 # _test-input-stream contains "int," + 4011 (clear-stream _test-input-stream) + 4012 (write _test-input-stream "int,") + 4013 # + 4014 (parse-var-with-type %ecx _test-input-stream) + 4015 8b/-> *eax 2/r32/edx # Var-name + 4016 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") + 4017 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4018 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") + 4019 8b/-> *(eax+4) 2/r32/edx # Var-type + 4020 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") + 4021 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") + 4022 # . epilogue + 4023 89/<- %esp 5/r32/ebp + 4024 5d/pop-to-ebp + 4025 c3/return + 4026 + 4027 test-parse-var-with-register-and-trailing-characters: + 4028 # . prologue + 4029 55/push-ebp + 4030 89/<- %ebp 4/r32/esp + 4031 # (eax..ecx) = "x/eax:" + 4032 b8/copy-to-eax "x/eax:"/imm32 + 4033 8b/-> *eax 1/r32/ecx + 4034 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4035 05/add-to-eax 4/imm32 + 4036 # var slice/ecx: slice = {eax, ecx} + 4037 51/push-ecx + 4038 50/push-eax + 4039 89/<- %ecx 4/r32/esp + 4040 # _test-input-stream contains "int," + 4041 (clear-stream _test-input-stream) + 4042 (write _test-input-stream "int,") + 4043 # + 4044 (parse-var-with-type %ecx _test-input-stream) + 4045 8b/-> *eax 2/r32/edx # Var-name + 4046 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") + 4047 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4048 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") + 4049 8b/-> *(eax+4) 2/r32/edx # Var-type + 4050 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") + 4051 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") + 4052 # . epilogue + 4053 89/<- %esp 5/r32/ebp + 4054 5d/pop-to-ebp + 4055 c3/return + 4056 + 4057 test-parse-var-with-compound-type: + 4058 # . prologue + 4059 55/push-ebp + 4060 89/<- %ebp 4/r32/esp + 4061 # (eax..ecx) = "x:" + 4062 b8/copy-to-eax "x:"/imm32 + 4063 8b/-> *eax 1/r32/ecx + 4064 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4065 05/add-to-eax 4/imm32 + 4066 # var slice/ecx: slice = {eax, ecx} + 4067 51/push-ecx + 4068 50/push-eax + 4069 89/<- %ecx 4/r32/esp + 4070 # _test-input-stream contains "(addr int)" + 4071 (clear-stream _test-input-stream) + 4072 (write _test-input-stream "(addr int)") + 4073 # + 4074 (parse-var-with-type %ecx _test-input-stream) + 4075 8b/-> *eax 2/r32/edx # Var-name + 4076 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") + 4077 8b/-> *(eax+0x10) 2/r32/edx # Var-register + 4078 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") + 4079 # var type/edx: (handle tree type-id) = var->type + 4080 8b/-> *(eax+4) 2/r32/edx # Var-type + 4081 # type->left == atom(addr) + 4082 8b/-> *edx 0/r32/eax # Atom-value + 4083 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left + 4084 # type->right->left == atom(int) + 4085 8b/-> *(edx+4) 2/r32/edx # Tree-right + 4086 8b/-> *edx 0/r32/eax # Tree-left + 4087 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value + 4088 # type->right->right == null + 4089 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right + 4090 # . epilogue + 4091 89/<- %esp 5/r32/ebp + 4092 5d/pop-to-ebp + 4093 c3/return + 4094 + 4095 # identifier starts with a letter or '$' or '_' + 4096 # no constraints at the moment on later letters + 4097 # all we really want to do so far is exclude '{', '}' and '->' + 4098 is-identifier?: # in: (addr slice) -> result/eax: boolean + 4099 # . prologue + 4100 55/push-ebp + 4101 89/<- %ebp 4/r32/esp + 4102 # if (slice-empty?(in)) return false + 4103 (slice-empty? *(ebp+8)) # => eax + 4104 3d/compare-eax-and 0/imm32/false + 4105 75/jump-if-!= $is-identifier?:false/disp8 + 4106 # var c/eax: byte = *in->start + 4107 8b/-> *(ebp+8) 0/r32/eax + 4108 8b/-> *eax 0/r32/eax + 4109 8a/copy-byte *eax 0/r32/AL + 4110 81 4/subop/and %eax 0xff/imm32 + 4111 # if (c == '$') return true + 4112 3d/compare-eax-and 0x24/imm32/$ + 4113 74/jump-if-= $is-identifier?:true/disp8 + 4114 # if (c == '_') return true + 4115 3d/compare-eax-and 0x5f/imm32/_ + 4116 74/jump-if-= $is-identifier?:true/disp8 + 4117 # drop case + 4118 25/and-eax-with 0x5f/imm32 + 4119 # if (c < 'A') return false + 4120 3d/compare-eax-and 0x41/imm32/A + 4121 7c/jump-if-< $is-identifier?:false/disp8 + 4122 # if (c > 'Z') return false + 4123 3d/compare-eax-and 0x5a/imm32/Z + 4124 7f/jump-if-> $is-identifier?:false/disp8 + 4125 # otherwise return true + 4126 $is-identifier?:true: + 4127 b8/copy-to-eax 1/imm32/true + 4128 eb/jump $is-identifier?:end/disp8 + 4129 $is-identifier?:false: + 4130 b8/copy-to-eax 0/imm32/false + 4131 $is-identifier?:end: + 4132 # . epilogue + 4133 89/<- %esp 5/r32/ebp + 4134 5d/pop-to-ebp + 4135 c3/return + 4136 + 4137 test-is-identifier-dollar: + 4138 # . prologue + 4139 55/push-ebp + 4140 89/<- %ebp 4/r32/esp + 4141 # (eax..ecx) = "$a" + 4142 b8/copy-to-eax "$a"/imm32 + 4143 8b/-> *eax 1/r32/ecx + 4144 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4145 05/add-to-eax 4/imm32 + 4146 # var slice/ecx: slice = {eax, ecx} + 4147 51/push-ecx + 4148 50/push-eax + 4149 89/<- %ecx 4/r32/esp + 4150 # + 4151 (is-identifier? %ecx) + 4152 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") + 4153 # . epilogue + 4154 89/<- %esp 5/r32/ebp + 4155 5d/pop-to-ebp + 4156 c3/return + 4157 + 4158 test-is-identifier-underscore: + 4159 # . prologue + 4160 55/push-ebp + 4161 89/<- %ebp 4/r32/esp + 4162 # (eax..ecx) = "_a" + 4163 b8/copy-to-eax "_a"/imm32 + 4164 8b/-> *eax 1/r32/ecx + 4165 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4166 05/add-to-eax 4/imm32 + 4167 # var slice/ecx: slice = {eax, ecx} + 4168 51/push-ecx + 4169 50/push-eax + 4170 89/<- %ecx 4/r32/esp + 4171 # + 4172 (is-identifier? %ecx) + 4173 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") + 4174 # . epilogue + 4175 89/<- %esp 5/r32/ebp + 4176 5d/pop-to-ebp + 4177 c3/return + 4178 + 4179 test-is-identifier-a: + 4180 # . prologue + 4181 55/push-ebp + 4182 89/<- %ebp 4/r32/esp + 4183 # (eax..ecx) = "a$" + 4184 b8/copy-to-eax "a$"/imm32 + 4185 8b/-> *eax 1/r32/ecx + 4186 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4187 05/add-to-eax 4/imm32 + 4188 # var slice/ecx: slice = {eax, ecx} + 4189 51/push-ecx + 4190 50/push-eax + 4191 89/<- %ecx 4/r32/esp + 4192 # + 4193 (is-identifier? %ecx) + 4194 (check-ints-equal %eax 1 "F - test-is-identifier-a") + 4195 # . epilogue + 4196 89/<- %esp 5/r32/ebp + 4197 5d/pop-to-ebp + 4198 c3/return + 4199 + 4200 test-is-identifier-z: + 4201 # . prologue + 4202 55/push-ebp + 4203 89/<- %ebp 4/r32/esp + 4204 # (eax..ecx) = "z$" + 4205 b8/copy-to-eax "z$"/imm32 + 4206 8b/-> *eax 1/r32/ecx + 4207 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4208 05/add-to-eax 4/imm32 + 4209 # var slice/ecx: slice = {eax, ecx} + 4210 51/push-ecx + 4211 50/push-eax + 4212 89/<- %ecx 4/r32/esp + 4213 # + 4214 (is-identifier? %ecx) + 4215 (check-ints-equal %eax 1 "F - test-is-identifier-z") + 4216 # . epilogue + 4217 89/<- %esp 5/r32/ebp + 4218 5d/pop-to-ebp + 4219 c3/return + 4220 + 4221 test-is-identifier-A: + 4222 # . prologue + 4223 55/push-ebp + 4224 89/<- %ebp 4/r32/esp + 4225 # (eax..ecx) = "A$" + 4226 b8/copy-to-eax "A$"/imm32 + 4227 8b/-> *eax 1/r32/ecx + 4228 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4229 05/add-to-eax 4/imm32 + 4230 # var slice/ecx: slice = {eax, ecx} + 4231 51/push-ecx + 4232 50/push-eax + 4233 89/<- %ecx 4/r32/esp + 4234 # + 4235 (is-identifier? %ecx) + 4236 (check-ints-equal %eax 1 "F - test-is-identifier-A") + 4237 # . epilogue + 4238 89/<- %esp 5/r32/ebp + 4239 5d/pop-to-ebp + 4240 c3/return + 4241 + 4242 test-is-identifier-Z: + 4243 # . prologue + 4244 55/push-ebp + 4245 89/<- %ebp 4/r32/esp + 4246 # (eax..ecx) = "Z$" + 4247 b8/copy-to-eax "Z$"/imm32 + 4248 8b/-> *eax 1/r32/ecx + 4249 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4250 05/add-to-eax 4/imm32 + 4251 # var slice/ecx: slice = {eax, ecx} + 4252 51/push-ecx + 4253 50/push-eax + 4254 89/<- %ecx 4/r32/esp + 4255 # + 4256 (is-identifier? %ecx) + 4257 (check-ints-equal %eax 1 "F - test-is-identifier-Z") + 4258 # . epilogue + 4259 89/<- %esp 5/r32/ebp + 4260 5d/pop-to-ebp + 4261 c3/return + 4262 + 4263 test-is-identifier-@: + 4264 # character before 'A' is invalid + 4265 # . prologue + 4266 55/push-ebp + 4267 89/<- %ebp 4/r32/esp + 4268 # (eax..ecx) = "@a" + 4269 b8/copy-to-eax "@a"/imm32 + 4270 8b/-> *eax 1/r32/ecx + 4271 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4272 05/add-to-eax 4/imm32 + 4273 # var slice/ecx: slice = {eax, ecx} + 4274 51/push-ecx + 4275 50/push-eax + 4276 89/<- %ecx 4/r32/esp + 4277 # + 4278 (is-identifier? %ecx) + 4279 (check-ints-equal %eax 0 "F - test-is-identifier-@") + 4280 # . epilogue + 4281 89/<- %esp 5/r32/ebp + 4282 5d/pop-to-ebp + 4283 c3/return + 4284 + 4285 test-is-identifier-square-bracket: + 4286 # character after 'Z' is invalid + 4287 # . prologue + 4288 55/push-ebp + 4289 89/<- %ebp 4/r32/esp + 4290 # (eax..ecx) = "[a" + 4291 b8/copy-to-eax "[a"/imm32 + 4292 8b/-> *eax 1/r32/ecx + 4293 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4294 05/add-to-eax 4/imm32 + 4295 # var slice/ecx: slice = {eax, ecx} + 4296 51/push-ecx + 4297 50/push-eax + 4298 89/<- %ecx 4/r32/esp + 4299 # + 4300 (is-identifier? %ecx) + 4301 (check-ints-equal %eax 0 "F - test-is-identifier-@") + 4302 # . epilogue + 4303 89/<- %esp 5/r32/ebp + 4304 5d/pop-to-ebp + 4305 c3/return + 4306 + 4307 test-is-identifier-backtick: + 4308 # character before 'a' is invalid + 4309 # . prologue + 4310 55/push-ebp + 4311 89/<- %ebp 4/r32/esp + 4312 # (eax..ecx) = "`a" + 4313 b8/copy-to-eax "`a"/imm32 + 4314 8b/-> *eax 1/r32/ecx + 4315 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4316 05/add-to-eax 4/imm32 + 4317 # var slice/ecx: slice = {eax, ecx} + 4318 51/push-ecx + 4319 50/push-eax + 4320 89/<- %ecx 4/r32/esp + 4321 # + 4322 (is-identifier? %ecx) + 4323 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") + 4324 # . epilogue + 4325 89/<- %esp 5/r32/ebp + 4326 5d/pop-to-ebp + 4327 c3/return + 4328 + 4329 test-is-identifier-curly-brace-open: + 4330 # character after 'z' is invalid; also used for blocks + 4331 # . prologue + 4332 55/push-ebp + 4333 89/<- %ebp 4/r32/esp + 4334 # (eax..ecx) = "{a" + 4335 b8/copy-to-eax "{a"/imm32 + 4336 8b/-> *eax 1/r32/ecx + 4337 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4338 05/add-to-eax 4/imm32 + 4339 # var slice/ecx: slice = {eax, ecx} + 4340 51/push-ecx + 4341 50/push-eax + 4342 89/<- %ecx 4/r32/esp + 4343 # + 4344 (is-identifier? %ecx) + 4345 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") + 4346 # . epilogue + 4347 89/<- %esp 5/r32/ebp + 4348 5d/pop-to-ebp + 4349 c3/return + 4350 + 4351 test-is-identifier-curly-brace-close: + 4352 # . prologue + 4353 55/push-ebp + 4354 89/<- %ebp 4/r32/esp + 4355 # (eax..ecx) = "}a" + 4356 b8/copy-to-eax "}a"/imm32 + 4357 8b/-> *eax 1/r32/ecx + 4358 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4359 05/add-to-eax 4/imm32 + 4360 # var slice/ecx: slice = {eax, ecx} + 4361 51/push-ecx + 4362 50/push-eax + 4363 89/<- %ecx 4/r32/esp + 4364 # + 4365 (is-identifier? %ecx) + 4366 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") + 4367 # . epilogue + 4368 89/<- %esp 5/r32/ebp + 4369 5d/pop-to-ebp + 4370 c3/return + 4371 + 4372 test-is-identifier-hyphen: + 4373 # disallow leading '-' since '->' has special meaning + 4374 # . prologue + 4375 55/push-ebp + 4376 89/<- %ebp 4/r32/esp + 4377 # (eax..ecx) = "-a" + 4378 b8/copy-to-eax "-a"/imm32 + 4379 8b/-> *eax 1/r32/ecx + 4380 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 4381 05/add-to-eax 4/imm32 + 4382 # var slice/ecx: slice = {eax, ecx} + 4383 51/push-ecx + 4384 50/push-eax + 4385 89/<- %ecx 4/r32/esp + 4386 # + 4387 (is-identifier? %ecx) + 4388 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") + 4389 # . epilogue + 4390 89/<- %esp 5/r32/ebp + 4391 5d/pop-to-ebp + 4392 c3/return + 4393 + 4394 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) + 4395 # . prologue + 4396 55/push-ebp + 4397 89/<- %ebp 4/r32/esp + 4398 # . save registers + 4399 50/push-eax + 4400 56/push-esi + 4401 57/push-edi + 4402 # esi = in + 4403 8b/-> *(ebp+8) 6/r32/esi + 4404 # edi = out + 4405 8b/-> *(ebp+0xc) 7/r32/edi + 4406 # var eax: (handle block) = parse-mu-block(in, vars, fn) + 4407 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax + 4408 # out->body = eax + 4409 89/<- *(edi+0x10) 0/r32/eax # Function-body + 4410 $populate-mu-function-body:end: + 4411 # . restore registers + 4412 5f/pop-to-edi + 4413 5e/pop-to-esi + 4414 58/pop-to-eax + 4415 # . epilogue + 4416 89/<- %esp 5/r32/ebp + 4417 5d/pop-to-ebp + 4418 c3/return + 4419 + 4420 # parses a block, assuming that the leading '{' has already been read by the caller + 4421 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) + 4422 # pseudocode: + 4423 # var line: (stream byte 512) + 4424 # var word-slice: slice + 4425 # result/eax = allocate(Heap, Stmt-size) + 4426 # result->tag = 0/block + 4427 # result->name = some unique name + 4428 # while true # line loop + 4429 # clear-stream(line) + 4430 # read-line-buffered(in, line) + 4431 # if (line->write == 0) break # end of file + 4432 # word-slice = next-mu-token(line) + 4433 # if slice-empty?(word-slice) # end of line + 4434 # continue + 4435 # else if slice-starts-with?(word-slice, "#") + 4436 # continue + 4437 # else if slice-equal?(word-slice, "{") + 4438 # assert(no-tokens-in(line)) + 4439 # block = parse-mu-block(in, vars, fn) + 4440 # append-to-block(result, block) + 4441 # else if slice-equal?(word-slice, "}") + 4442 # break + 4443 # else if slice-ends-with?(word-slice, ":") + 4444 # # TODO: error-check the rest of 'line' + 4445 # --word-slice->end to skip ':' + 4446 # named-block = parse-mu-named-block(word-slice, in, vars, fn) + 4447 # append-to-block(result, named-block) + 4448 # else if slice-equal?(word-slice, "var") + 4449 # var-def = parse-mu-var-def(line, vars) + 4450 # append-to-block(result, var-def) + 4451 # else + 4452 # stmt = parse-mu-stmt(line, vars, fn) + 4453 # append-to-block(result, stmt) + 4454 # return result + 4455 # + 4456 # . prologue + 4457 55/push-ebp + 4458 89/<- %ebp 4/r32/esp + 4459 # . save registers + 4460 51/push-ecx + 4461 52/push-edx + 4462 53/push-ebx + 4463 57/push-edi + 4464 # var line/ecx: (stream byte 512) + 4465 81 5/subop/subtract %esp 0x200/imm32 + 4466 68/push 0x200/imm32/length + 4467 68/push 0/imm32/read + 4468 68/push 0/imm32/write + 4469 89/<- %ecx 4/r32/esp + 4470 # var word-slice/edx: slice + 4471 68/push 0/imm32/end + 4472 68/push 0/imm32/start + 4473 89/<- %edx 4/r32/esp + 4474 # edi = result + 4475 (allocate Heap *Stmt-size) # => eax + 4476 (zero-out %eax *Stmt-size) + 4477 89/<- %edi 0/r32/eax + 4478 # set result->tag + 4479 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag + 4480 # set result->var + 4481 (new-block-name *(ebp+0x10)) # => eax + 4482 89/<- *(edi+8) 0/r32/eax # Block-var + 4483 # push result->var to vars + 4484 (push *(ebp+0xc) %eax) + 4485 { + 4486 $parse-mu-block:line-loop: + 4487 # line = read-line-buffered(in) + 4488 (clear-stream %ecx) + 4489 (read-line-buffered *(ebp+8) %ecx) + 4490 #? (write-buffered Stderr "line: ") + 4491 #? (write-stream-data Stderr %ecx) + 4492 #? (write-buffered Stderr Newline) + 4493 #? (flush Stderr) + 4494 # if (line->write == 0) break + 4495 81 7/subop/compare *ecx 0/imm32 + 4496 0f 84/jump-if-= break/disp32 + 4497 # word-slice = next-mu-token(line) + 4498 (next-mu-token %ecx %edx) + 4499 #? (write-buffered Stderr "word: ") + 4500 #? (write-slice-buffered Stderr %edx) + 4501 #? (write-buffered Stderr Newline) + 4502 #? (flush Stderr) + 4503 # if slice-empty?(word-slice) continue + 4504 (slice-empty? %edx) + 4505 3d/compare-eax-and 0/imm32/false + 4506 0f 85/jump-if-!= loop/disp32 + 4507 # if (slice-starts-with?(word-slice, '#') continue + 4508 # . eax = *word-slice->start + 4509 8b/-> *edx 0/r32/eax + 4510 8a/copy-byte *eax 0/r32/AL + 4511 81 4/subop/and %eax 0xff/imm32 + 4512 # . if (eax == '#') continue + 4513 3d/compare-eax-and 0x23/imm32/hash + 4514 0f 84/jump-if-= loop/disp32 + 4515 # if slice-equal?(word-slice, "{") + 4516 { + 4517 $parse-mu-block:check-for-block: + 4518 (slice-equal? %edx "{") + 4519 3d/compare-eax-and 0/imm32/false + 4520 74/jump-if-= break/disp8 + 4521 (check-no-tokens-left %ecx) + 4522 # parse new block and append + 4523 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax + 4524 (append-to-block Heap %edi %eax) + 4525 e9/jump $parse-mu-block:line-loop/disp32 + 4526 } + 4527 # if slice-equal?(word-slice, "}") break + 4528 $parse-mu-block:check-for-end: + 4529 (slice-equal? %edx "}") + 4530 3d/compare-eax-and 0/imm32/false + 4531 0f 85/jump-if-!= break/disp32 + 4532 # if slice-ends-with?(word-slice, ":") parse named block and append + 4533 { + 4534 $parse-mu-block:check-for-named-block: + 4535 # . eax = *(word-slice->end-1) + 4536 8b/-> *(edx+4) 0/r32/eax + 4537 48/decrement-eax + 4538 8a/copy-byte *eax 0/r32/AL + 4539 81 4/subop/and %eax 0xff/imm32 + 4540 # . if (eax != ':') break + 4541 3d/compare-eax-and 0x3a/imm32/colon + 4542 0f 85/jump-if-!= break/disp32 + 4543 # TODO: error-check the rest of 'line' + 4544 # + 4545 # skip ':' + 4546 ff 1/subop/decrement *(edx+4) # Slice-end + 4547 # + 4548 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax + 4549 (append-to-block Heap %edi %eax) + 4550 e9/jump $parse-mu-block:line-loop/disp32 + 4551 } + 4552 # if slice-equal?(word-slice, "var") + 4553 { + 4554 $parse-mu-block:check-for-var: + 4555 (slice-equal? %edx "var") + 4556 3d/compare-eax-and 0/imm32/false + 4557 74/jump-if-= break/disp8 + 4558 # + 4559 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax + 4560 (append-to-block Heap %edi %eax) + 4561 e9/jump $parse-mu-block:line-loop/disp32 + 4562 } + 4563 $parse-mu-block:regular-stmt: + 4564 # otherwise + 4565 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax + 4566 (append-to-block Heap %edi %eax) + 4567 e9/jump loop/disp32 + 4568 } # end line loop + 4569 # + 4570 (pop *(ebp+0xc)) # => eax + 4571 # return result + 4572 89/<- %eax 7/r32/edi + 4573 $parse-mu-block:end: + 4574 # . reclaim locals + 4575 81 0/subop/add %esp 0x214/imm32 + 4576 # . restore registers + 4577 5f/pop-to-edi + 4578 5b/pop-to-ebx + 4579 5a/pop-to-edx + 4580 59/pop-to-ecx + 4581 # . epilogue + 4582 89/<- %esp 5/r32/ebp + 4583 5d/pop-to-ebp + 4584 c3/return + 4585 + 4586 $parse-mu-block:abort: + 4587 # error("'{' or '}' should be on its own line, but got '") + 4588 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") + 4589 (rewind-stream %ecx) + 4590 (write-stream 2 %ecx) + 4591 (write-buffered Stderr "'\n") + 4592 (flush Stderr) + 4593 # . syscall(exit, 1) + 4594 bb/copy-to-ebx 1/imm32 + 4595 b8/copy-to-eax 1/imm32/exit + 4596 cd/syscall 0x80/imm8 + 4597 # never gets here + 4598 + 4599 new-block-name: # fn: (handle function) -> result/eax: (handle var) + 4600 # . prologue + 4601 55/push-ebp + 4602 89/<- %ebp 4/r32/esp + 4603 # . save registers + 4604 51/push-ecx + 4605 52/push-edx + 4606 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' + 4607 8b/-> *(ebp+8) 0/r32/eax + 4608 8b/-> *eax 0/r32/eax # Function-name + 4609 8b/-> *eax 0/r32/eax # String-length + 4610 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' + 4611 89/<- %ecx 0/r32/eax + 4612 # var name/edx: (stream byte n) + 4613 29/subtract %esp 1/r32/ecx + 4614 ff 6/subop/push %ecx + 4615 68/push 0/imm32/read + 4616 68/push 0/imm32/write + 4617 89/<- %edx 4/r32/esp + 4618 (clear-stream %edx) + 4619 # eax = fn->name + 4620 8b/-> *(ebp+8) 0/r32/eax + 4621 8b/-> *eax 0/r32/eax # Function-name + 4622 # construct result using Next-block-index (and increment it) + 4623 (write %edx "$") + 4624 (write %edx %eax) + 4625 (write %edx ":") + 4626 (print-int32 %edx *Next-block-index) + 4627 ff 0/subop/increment *Next-block-index + 4628 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) + 4629 # . eax = name->write + 4630 8b/-> *edx 0/r32/eax + 4631 # . edx = name->data + 4632 8d/copy-address *(edx+0xc) 2/r32/edx + 4633 # . eax = name->write + name->data + 4634 01/add %eax 2/r32/edx + 4635 # . push {edx, eax} + 4636 ff 6/subop/push %eax + 4637 ff 6/subop/push %edx + 4638 89/<- %eax 4/r32/esp + 4639 # result->var = new literal(s) + 4640 (new-literal Heap %eax) # => eax + 4641 $new-block-name:end: + 4642 # . reclaim locals + 4643 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} + 4644 81 0/subop/add %ecx 8/imm32 # slice + 4645 01/add %esp 1/r32/ecx + 4646 # . restore registers + 4647 5a/pop-to-edx + 4648 59/pop-to-ecx + 4649 # . epilogue + 4650 89/<- %esp 5/r32/ebp + 4651 5d/pop-to-ebp + 4652 c3/return + 4653 + 4654 == data + 4655 + 4656 # Global state added to each var record when parsing a function + 4657 Next-block-index: # (addr int) + 4658 1/imm32 + 4659 + 4660 == code + 4661 + 4662 check-no-tokens-left: # line: (addr stream byte) + 4663 # . prologue + 4664 55/push-ebp + 4665 89/<- %ebp 4/r32/esp + 4666 # . save registers + 4667 50/push-eax + 4668 51/push-ecx + 4669 # var s/ecx: slice + 4670 68/push 0/imm32/end + 4671 68/push 0/imm32/start + 4672 89/<- %ecx 4/r32/esp + 4673 # + 4674 (next-mu-token *(ebp+8) %ecx) + 4675 # if slice-empty?(s) return + 4676 (slice-empty? %ecx) + 4677 3d/compare-eax-and 0/imm32/false + 4678 75/jump-if-!= $check-no-tokens-left:end/disp8 + 4679 # if (slice-starts-with?(s, '#') return + 4680 # . eax = *s->start + 4681 8b/-> *edx 0/r32/eax + 4682 8a/copy-byte *eax 0/r32/AL + 4683 81 4/subop/and %eax 0xff/imm32 + 4684 # . if (eax == '#') continue + 4685 3d/compare-eax-and 0x23/imm32/hash + 4686 74/jump-if-= $check-no-tokens-left:end/disp8 + 4687 # abort + 4688 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") + 4689 (rewind-stream %ecx) + 4690 (write-stream 2 %ecx) + 4691 (write-buffered Stderr "'\n") + 4692 (flush Stderr) + 4693 # . syscall(exit, 1) + 4694 bb/copy-to-ebx 1/imm32 + 4695 b8/copy-to-eax 1/imm32/exit + 4696 cd/syscall 0x80/imm8 + 4697 # never gets here + 4698 $check-no-tokens-left:end: + 4699 # . reclaim locals + 4700 81 0/subop/add %esp 8/imm32 + 4701 # . restore registers + 4702 59/pop-to-ecx + 4703 58/pop-to-eax + 4704 # . epilogue + 4705 89/<- %esp 5/r32/ebp + 4706 5d/pop-to-ebp + 4707 c3/return + 4708 + 4709 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) + 4710 # pseudocode: + 4711 # var v: (handle var) = new-literal(name) + 4712 # push(vars, v) + 4713 # result = parse-mu-block(in, vars, fn) + 4714 # pop(vars) + 4715 # result->name = s + 4716 # return result + 4717 # + 4718 # . prologue + 4719 55/push-ebp + 4720 89/<- %ebp 4/r32/esp + 4721 # . save registers + 4722 51/push-ecx + 4723 # var v/ecx: (handle var) + 4724 (new-literal Heap *(ebp+8)) # => eax + 4725 89/<- %ecx 0/r32/eax + 4726 # push(vars, v) + 4727 (push *(ebp+0x10) %ecx) + 4728 # eax = result + 4729 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax + 4730 # pop the var + 4731 50/push-eax + 4732 (pop *(ebp+0x10)) # => eax + 4733 58/pop-to-eax + 4734 # result->tag = named-block + 4735 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag + 4736 # result->var = v + 4737 89/<- *(eax+8) 1/r32/ecx # Block-var + 4738 $parse-mu-named-block:end: + 4739 # . restore registers + 4740 59/pop-to-ecx + 4741 # . epilogue + 4742 89/<- %esp 5/r32/ebp + 4743 5d/pop-to-ebp + 4744 c3/return + 4745 + 4746 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) + 4747 # . prologue + 4748 55/push-ebp + 4749 89/<- %ebp 4/r32/esp + 4750 # . save registers + 4751 51/push-ecx + 4752 52/push-edx + 4753 # var word-slice/ecx: slice + 4754 68/push 0/imm32/end + 4755 68/push 0/imm32/start + 4756 89/<- %ecx 4/r32/esp + 4757 # var v/edx: (handle var) = parse-var-with-type(line) + 4758 (next-mu-token *(ebp+8) %ecx) + 4759 (parse-var-with-type %ecx *(ebp+8)) # => eax + 4760 89/<- %edx 0/r32/eax + 4761 # + 4762 (push *(ebp+0xc) %edx) + 4763 # either v has no register and there's no more to this line + 4764 8b/-> *(edx+0x10) 0/r32/eax # Var-register + 4765 3d/compare-eax-and 0/imm32 + 4766 { + 4767 75/jump-if-!= break/disp8 + 4768 # TODO: ensure that there's nothing else on this line + 4769 (new-var-def Heap %edx) # => eax + 4770 eb/jump $parse-mu-var-def:end/disp8 + 4771 } + 4772 # or v has a register and there's more to this line + 4773 { + 4774 74/jump-if-= break/disp8 + 4775 # ensure that the next word is '<-' + 4776 (next-mu-token *(ebp+8) %ecx) + 4777 (slice-equal? %ecx "<-") # => eax + 4778 3d/compare-eax-and 0/imm32/false + 4779 74/jump-if-= $parse-mu-var-def:abort/disp8 + 4780 # + 4781 (new-reg-var-def Heap %edx) # => eax + 4782 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) + 4783 } + 4784 $parse-mu-var-def:end: + 4785 # . reclaim locals + 4786 81 0/subop/add %esp 8/imm32 + 4787 # . restore registers + 4788 5a/pop-to-edx + 4789 59/pop-to-ecx + 4790 # . epilogue + 4791 89/<- %esp 5/r32/ebp + 4792 5d/pop-to-ebp + 4793 c3/return + 4794 + 4795 $parse-mu-var-def:abort: + 4796 (rewind-stream *(ebp+8)) + 4797 # error("register variable requires a valid instruction to initialize but got '" line "'\n") + 4798 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") + 4799 (flush Stderr) + 4800 (write-stream 2 *(ebp+8)) + 4801 (write-buffered Stderr "'\n") + 4802 (flush Stderr) + 4803 # . syscall(exit, 1) + 4804 bb/copy-to-ebx 1/imm32 + 4805 b8/copy-to-eax 1/imm32/exit + 4806 cd/syscall 0x80/imm8 + 4807 # never gets here + 4808 + 4809 test-parse-mu-var-def: + 4810 # 'var n: int' + 4811 # . prologue + 4812 55/push-ebp + 4813 89/<- %ebp 4/r32/esp + 4814 # setup + 4815 (clear-stream _test-input-stream) + 4816 (write _test-input-stream "n: int\n") # caller has consumed the 'var' + 4817 # var vars/ecx: (stack (addr var) 4) + 4818 81 5/subop/subtract %esp 0x10/imm32 + 4819 68/push 0x10/imm32/length + 4820 68/push 0/imm32/top + 4821 89/<- %ecx 4/r32/esp + 4822 (clear-stack %ecx) + 4823 # convert + 4824 (parse-mu-var-def _test-input-stream %ecx) # => eax + 4825 # check result + 4826 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def + 4827 8b/-> *(eax+4) 0/r32/eax # Vardef-var + 4828 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name + 4829 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register + 4830 # ensure type is int + 4831 8b/-> *(eax+4) 0/r32/eax # Var-type + 4832 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left + 4833 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right + 4834 # . epilogue + 4835 89/<- %esp 5/r32/ebp + 4836 5d/pop-to-ebp + 4837 c3/return + 4838 + 4839 test-parse-mu-reg-var-def: + 4840 # 'var n/eax: int <- copy 0' + 4841 # . prologue + 4842 55/push-ebp + 4843 89/<- %ebp 4/r32/esp + 4844 # setup + 4845 (clear-stream _test-input-stream) + 4846 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' + 4847 # var vars/ecx: (stack (addr var) 4) + 4848 81 5/subop/subtract %esp 0x10/imm32 + 4849 68/push 0x10/imm32/length + 4850 68/push 0/imm32/top + 4851 89/<- %ecx 4/r32/esp + 4852 (clear-stack %ecx) + 4853 # convert + 4854 (parse-mu-var-def _test-input-stream %ecx) # => eax + 4855 # check result + 4856 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def + 4857 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs + 4858 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next + 4859 8b/-> *eax 0/r32/eax # Stmt-var-value + 4860 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name + 4861 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register + 4862 # ensure type is int + 4863 8b/-> *(eax+4) 0/r32/eax # Var-type + 4864 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left + 4865 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right + 4866 # . epilogue + 4867 89/<- %esp 5/r32/ebp + 4868 5d/pop-to-ebp + 4869 c3/return + 4870 + 4871 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) + 4872 # pseudocode: + 4873 # var name: slice + 4874 # result = allocate(Heap, Stmt-size) + 4875 # if stmt-has-outputs?(line) + 4876 # while true + 4877 # name = next-mu-token(line) + 4878 # if (name == '<-') break + 4879 # assert(is-identifier?(name)) + 4880 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs + 4881 # result->outputs = append(result->outputs, v) + 4882 # add-operation-and-inputs-to-stmt(result, line, vars) + 4883 # + 4884 # . prologue + 4885 55/push-ebp + 4886 89/<- %ebp 4/r32/esp + 4887 # . save registers + 4888 51/push-ecx + 4889 52/push-edx + 4890 57/push-edi + 4891 # var name/ecx: slice + 4892 68/push 0/imm32/end + 4893 68/push 0/imm32/start + 4894 89/<- %ecx 4/r32/esp + 4895 # var is-deref?/edx: boolean = false + 4896 ba/copy-to-edx 0/imm32/false + 4897 # result/edi: (handle stmt) + 4898 (allocate Heap *Stmt-size) # => eax + 4899 (zero-out %eax *Stmt-size) + 4900 89/<- %edi 0/r32/eax + 4901 # result->tag = 1/stmt + 4902 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag + 4903 { + 4904 (stmt-has-outputs? *(ebp+8)) + 4905 3d/compare-eax-and 0/imm32/false + 4906 0f 84/jump-if-= break/disp32 + 4907 { + 4908 $parse-mu-stmt:read-outputs: + 4909 # name = next-mu-token(line) + 4910 (next-mu-token *(ebp+8) %ecx) + 4911 # if slice-empty?(word-slice) break + 4912 (slice-empty? %ecx) # => eax + 4913 3d/compare-eax-and 0/imm32/false + 4914 0f 85/jump-if-!= break/disp32 + 4915 # if (name == "<-") break + 4916 (slice-equal? %ecx "<-") # => eax + 4917 3d/compare-eax-and 0/imm32/false + 4918 0f 85/jump-if-!= break/disp32 + 4919 # is-deref? = false + 4920 ba/copy-to-edx 0/imm32/false + 4921 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? + 4922 8b/-> *ecx 0/r32/eax # Slice-start + 4923 8a/copy-byte *eax 0/r32/AL + 4924 81 4/subop/and %eax 0xff/imm32 + 4925 3d/compare-eax-and 0x2a/imm32/asterisk + 4926 { + 4927 75/jump-if-!= break/disp8 + 4928 ff 0/subop/increment *ecx + 4929 ba/copy-to-edx 1/imm32/true + 4930 } + 4931 # assert(is-identifier?(name)) + 4932 (is-identifier? %ecx) # => eax + 4933 3d/compare-eax-and 0/imm32/false + 4934 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 + 4935 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) + 4936 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax + 4937 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax + 4938 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs + 4939 e9/jump loop/disp32 + 4940 } + 4941 } + 4942 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) + 4943 $parse-mu-stmt:end: + 4944 # return result + 4945 89/<- %eax 7/r32/edi + 4946 # . reclaim locals + 4947 81 0/subop/add %esp 8/imm32 + 4948 # . restore registers + 4949 5f/pop-to-edi + 4950 5a/pop-to-edx + 4951 59/pop-to-ecx + 4952 # . epilogue + 4953 89/<- %esp 5/r32/ebp + 4954 5d/pop-to-ebp + 4955 c3/return + 4956 + 4957 $parse-mu-stmt:abort: + 4958 # error("invalid identifier '" name "'\n") + 4959 (write-buffered Stderr "invalid identifier '") + 4960 (write-slice-buffered Stderr %ecx) + 4961 (write-buffered Stderr "'\n") + 4962 (flush Stderr) + 4963 # . syscall(exit, 1) + 4964 bb/copy-to-ebx 1/imm32 + 4965 b8/copy-to-eax 1/imm32/exit + 4966 cd/syscall 0x80/imm8 + 4967 # never gets here + 4968 + 4969 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) + 4970 # pseudocode: + 4971 # stmt->name = slice-to-string(next-mu-token(line)) + 4972 # while true + 4973 # name = next-mu-token(line) + 4974 # v = lookup-var-or-literal(name) + 4975 # stmt->inouts = append(stmt->inouts, v) + 4976 # + 4977 # . prologue + 4978 55/push-ebp + 4979 89/<- %ebp 4/r32/esp + 4980 # . save registers + 4981 50/push-eax + 4982 51/push-ecx + 4983 52/push-edx + 4984 53/push-ebx + 4985 57/push-edi + 4986 # edi = stmt + 4987 8b/-> *(ebp+8) 7/r32/edi + 4988 # var name/ecx: slice + 4989 68/push 0/imm32/end + 4990 68/push 0/imm32/start + 4991 89/<- %ecx 4/r32/esp + 4992 # var is-deref?/edx: boolean = false + 4993 ba/copy-to-edx 0/imm32/false + 4994 $add-operation-and-inputs-to-stmt:read-operation: + 4995 (next-mu-token *(ebp+0xc) %ecx) + 4996 (slice-to-string Heap %ecx) # => eax + 4997 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation + 4998 # var is-get?/ebx: boolean = (name == "get") + 4999 (slice-equal? %ecx "get") # => eax + 5000 89/<- %ebx 0/r32/eax + 5001 { + 5002 $add-operation-and-inputs-to-stmt:read-inouts: + 5003 # name = next-mu-token(line) + 5004 (next-mu-token *(ebp+0xc) %ecx) + 5005 # if slice-empty?(word-slice) break + 5006 (slice-empty? %ecx) # => eax + 5007 3d/compare-eax-and 0/imm32/false + 5008 0f 85/jump-if-!= break/disp32 + 5009 # if (name == "<-") abort + 5010 (slice-equal? %ecx "<-") + 5011 3d/compare-eax-and 0/imm32/false + 5012 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 + 5013 # if (is-get? && second operand) lookup or create offset + 5014 { + 5015 81 7/subop/compare %ebx 0/imm32/false + 5016 74/jump-if-= break/disp8 + 5017 81 7/subop/compare *(edi+8) 0/imm32 # Stmt1-inouts or Regvardef-inouts + 5018 74/jump-if-= break/disp8 + 5019 (lookup-or-create-constant *(edi+8) %ecx) # Stmt1-inouts => eax + 5020 #? (write-buffered Stderr "creating new output var ") + 5021 #? (print-int32-buffered Stderr %eax) + 5022 #? (write-buffered Stderr " for field called ") + 5023 #? (write-slice-buffered Stderr %ecx) + 5024 #? (write-buffered Stderr Newline) + 5025 #? (flush Stderr) + 5026 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 + 5027 } + 5028 # is-deref? = false + 5029 ba/copy-to-edx 0/imm32/false + 5030 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? + 5031 8b/-> *ecx 0/r32/eax # Slice-start + 5032 8a/copy-byte *eax 0/r32/AL + 5033 81 4/subop/and %eax 0xff/imm32 + 5034 3d/compare-eax-and 0x2a/imm32/asterisk + 5035 { + 5036 75/jump-if-!= break/disp8 + 5037 $add-operation-and-inputs-to-stmt:inout-is-deref: + 5038 ff 0/subop/increment *ecx + 5039 ba/copy-to-edx 1/imm32/true + 5040 } + 5041 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax + 5042 $add-operation-and-inputs-to-stmt:save-var: + 5043 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax + 5044 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 5045 e9/jump loop/disp32 + 5046 } + 5047 $add-operation-and-inputs-to-stmt:end: + 5048 # . reclaim locals + 5049 81 0/subop/add %esp 8/imm32 + 5050 # . restore registers + 5051 5f/pop-to-edi + 5052 5b/pop-to-ebx + 5053 5a/pop-to-edx + 5054 59/pop-to-ecx + 5055 58/pop-to-eax + 5056 # . epilogue + 5057 89/<- %esp 5/r32/ebp + 5058 5d/pop-to-ebp + 5059 c3/return + 5060 + 5061 $add-operation-and-inputs-to-stmt:abort: + 5062 # error("invalid statement '" line "'\n") + 5063 (rewind-stream *(ebp+8)) + 5064 (write-buffered Stderr "invalid identifier '") + 5065 (flush Stderr) + 5066 (write-stream 2 *(ebp+8)) + 5067 (write-buffered Stderr "'\n") + 5068 (flush Stderr) + 5069 # . syscall(exit, 1) + 5070 bb/copy-to-ebx 1/imm32 + 5071 b8/copy-to-eax 1/imm32/exit + 5072 cd/syscall 0x80/imm8 + 5073 # never gets here 5074 - 5075 # if 'name' starts with a digit, create a new literal var for it - 5076 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found - 5077 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5078 # . prologue - 5079 55/push-ebp - 5080 89/<- %ebp 4/r32/esp - 5081 # . save registers - 5082 51/push-ecx - 5083 56/push-esi - 5084 # esi = name - 5085 8b/-> *(ebp+8) 6/r32/esi - 5086 # if slice-empty?(name) abort - 5087 (slice-empty? %esi) # => eax - 5088 3d/compare-eax-and 0/imm32/false - 5089 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 - 5090 # var c/ecx: byte = *name->start - 5091 8b/-> *esi 1/r32/ecx - 5092 8a/copy-byte *ecx 1/r32/CL - 5093 81 4/subop/and %ecx 0xff/imm32 - 5094 # if is-decimal-digit?(c) return new var(name) - 5095 { - 5096 (is-decimal-digit? %ecx) # => eax - 5097 3d/compare-eax-and 0/imm32/false - 5098 74/jump-if-= break/disp8 - 5099 (new-literal-integer Heap %esi) # => eax - 5100 eb/jump $lookup-var-or-literal:end/disp8 - 5101 } - 5102 # else if (c == '"') return new var(name) - 5103 { - 5104 81 7/subop/compare %ecx 0x22/imm32/dquote - 5105 75/jump-if-!= break/disp8 - 5106 (new-literal Heap %esi) # => eax - 5107 eb/jump $lookup-var-or-literal:end/disp8 - 5108 } - 5109 # otherwise return lookup-var(name, vars) - 5110 { - 5111 (lookup-var %esi *(ebp+0xc)) # => eax - 5112 } - 5113 $lookup-var-or-literal:end: + 5075 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean + 5076 # . prologue + 5077 55/push-ebp + 5078 89/<- %ebp 4/r32/esp + 5079 # . save registers + 5080 51/push-ecx + 5081 # var word-slice/ecx: slice + 5082 68/push 0/imm32/end + 5083 68/push 0/imm32/start + 5084 89/<- %ecx 4/r32/esp + 5085 # result = false + 5086 b8/copy-to-eax 0/imm32/false + 5087 (rewind-stream *(ebp+8)) + 5088 { + 5089 (next-mu-token *(ebp+8) %ecx) + 5090 # if slice-empty?(word-slice) break + 5091 (slice-empty? %ecx) + 5092 3d/compare-eax-and 0/imm32/false + 5093 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) + 5094 0f 85/jump-if-!= break/disp32 + 5095 # if slice-starts-with?(word-slice, '#') break + 5096 # . eax = *word-slice->start + 5097 8b/-> *ecx 0/r32/eax + 5098 8a/copy-byte *eax 0/r32/AL + 5099 81 4/subop/and %eax 0xff/imm32 + 5100 # . if (eax == '#') break + 5101 3d/compare-eax-and 0x23/imm32/hash + 5102 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) + 5103 0f 84/jump-if-= break/disp32 + 5104 # if slice-equal?(word-slice, '<-') return true + 5105 (slice-equal? %ecx "<-") + 5106 3d/compare-eax-and 0/imm32/false + 5107 74/jump-if-= loop/disp8 + 5108 b8/copy-to-eax 1/imm32/true + 5109 } + 5110 $stmt-has-outputs:end: + 5111 (rewind-stream *(ebp+8)) + 5112 # . reclaim locals + 5113 81 0/subop/add %esp 8/imm32 5114 # . restore registers - 5115 5e/pop-to-esi - 5116 59/pop-to-ecx - 5117 # . epilogue - 5118 89/<- %esp 5/r32/ebp - 5119 5d/pop-to-ebp - 5120 c3/return - 5121 - 5122 $lookup-var-or-literal:abort: - 5123 (write-buffered Stderr "empty variable!") - 5124 (flush Stderr) - 5125 # . syscall(exit, 1) - 5126 bb/copy-to-ebx 1/imm32 - 5127 b8/copy-to-eax 1/imm32/exit - 5128 cd/syscall 0x80/imm8 - 5129 # never gets here - 5130 - 5131 # return first 'name' from the top (back) of 'vars' and abort if not found - 5132 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5133 # . prologue - 5134 55/push-ebp - 5135 89/<- %ebp 4/r32/esp - 5136 # var target/eax: (handle array byte) = slice-to-string(name) - 5137 (slice-to-string Heap *(ebp+8)) # => eax - 5138 # - 5139 (lookup-var-helper %eax *(ebp+0xc)) # => eax - 5140 # if (result == 0) abort - 5141 3d/compare-eax-and 0/imm32 - 5142 74/jump-if-= $lookup-var:abort/disp8 - 5143 $lookup-var:end: - 5144 # . epilogue - 5145 89/<- %esp 5/r32/ebp - 5146 5d/pop-to-ebp - 5147 c3/return - 5148 - 5149 $lookup-var:abort: - 5150 (write-buffered Stderr "unknown variable '") - 5151 (write-slice-buffered Stderr *(ebp+8)) - 5152 (write-buffered Stderr "'\n") - 5153 (flush Stderr) - 5154 # . syscall(exit, 1) - 5155 bb/copy-to-ebx 1/imm32 - 5156 b8/copy-to-eax 1/imm32/exit - 5157 cd/syscall 0x80/imm8 - 5158 # never gets here - 5159 - 5160 # return first 'name' from the top (back) of 'vars', and 0/null if not found - 5161 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) - 5162 # pseudocode: - 5163 # var curr: (addr handle var) = &vars->data[vars->top - 4] - 5164 # var min = vars->data - 5165 # while curr >= min - 5166 # var v: (handle var) = *curr - 5167 # if v->name == name - 5168 # return v - 5169 # return 0 - 5170 # - 5171 # . prologue - 5172 55/push-ebp - 5173 89/<- %ebp 4/r32/esp - 5174 # . save registers - 5175 52/push-edx - 5176 53/push-ebx - 5177 56/push-esi - 5178 # esi = vars - 5179 8b/-> *(ebp+0xc) 6/r32/esi - 5180 # ebx = vars->top - 5181 8b/-> *esi 3/r32/ebx - 5182 # if (vars->top > vars->length) abort - 5183 3b/compare 0/r32/eax *(esi+4) - 5184 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 - 5185 # var min/edx: (addr handle var) = vars->data - 5186 8d/copy-address *(esi+8) 2/r32/edx - 5187 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] - 5188 81 5/subop/subtract %ebx 4/imm32 - 5189 8d/copy-address *(esi+ebx+8) 3/r32/ebx - 5190 { - 5191 # if (curr < min) return 0 - 5192 39/compare %ebx 2/r32/edx - 5193 b8/copy-to-eax 0/imm32 - 5194 0f 82/jump-if-addr< break/disp32 - 5195 # var v/eax: (handle var) = *curr - 5196 8b/-> *ebx 0/r32/eax - 5197 # if (v->name == name) return v - 5198 (string-equal? *eax *(ebp+8)) # Var-name - 5199 3d/compare-eax-and 0/imm32/false - 5200 8b/-> *ebx 0/r32/eax - 5201 75/jump-if-!= break/disp8 - 5202 # curr -= 4 - 5203 81 5/subop/subtract %ebx 4/imm32 - 5204 e9/jump loop/disp32 - 5205 } - 5206 $lookup-var-helper:end: - 5207 # . restore registers - 5208 5e/pop-to-esi - 5209 5b/pop-to-ebx - 5210 5a/pop-to-edx - 5211 # . epilogue - 5212 89/<- %esp 5/r32/ebp - 5213 5d/pop-to-ebp - 5214 c3/return - 5215 - 5216 $lookup-var-helper:error1: - 5217 (write-buffered Stderr "malformed stack when looking up '") - 5218 (write-slice-buffered Stderr *(ebp+8)) - 5219 (write-buffered Stderr "'\n") - 5220 (flush Stderr) - 5221 # . syscall(exit, 1) - 5222 bb/copy-to-ebx 1/imm32 - 5223 b8/copy-to-eax 1/imm32/exit - 5224 cd/syscall 0x80/imm8 - 5225 # never gets here - 5226 - 5227 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found - 5228 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) - 5229 # . prologue - 5230 55/push-ebp - 5231 89/<- %ebp 4/r32/esp - 5232 # . save registers - 5233 51/push-ecx - 5234 # var target/ecx: (handle array byte) = slice-to-string(name) - 5235 (slice-to-string Heap *(ebp+8)) # => eax - 5236 89/<- %ecx 0/r32/eax - 5237 # - 5238 (lookup-var-helper %ecx *(ebp+0xc)) # => eax - 5239 { - 5240 # if (result != 0) return - 5241 3d/compare-eax-and 0/imm32 - 5242 75/jump-if-!= break/disp8 - 5243 # if name is one of fn's outputs, return it - 5244 { - 5245 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax - 5246 3d/compare-eax-and 0/imm32 - 5247 # otherwise abort - 5248 0f 84/jump-if-!= $lookup-var:abort/disp32 - 5249 } - 5250 } - 5251 $lookup-or-define-var:end: - 5252 # . restore registers - 5253 59/pop-to-ecx - 5254 # . epilogue - 5255 89/<- %esp 5/r32/ebp - 5256 5d/pop-to-ebp - 5257 c3/return - 5258 - 5259 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) - 5260 # . prologue - 5261 55/push-ebp - 5262 89/<- %ebp 4/r32/esp - 5263 # . save registers - 5264 51/push-ecx - 5265 # var curr/ecx: (handle list var) = fn->outputs - 5266 8b/-> *(ebp+8) 1/r32/ecx - 5267 8b/-> *(ecx+0xc) 1/r32/ecx - 5268 # while curr != null - 5269 { - 5270 81 7/subop/compare %ecx 0/imm32 - 5271 74/jump-if-= break/disp8 - 5272 # var v: (handle var) = *curr - 5273 8b/-> *ecx 0/r32/eax # List-value - 5274 # if (curr->name == name) return curr - 5275 50/push-eax - 5276 (string-equal? *eax *(ebp+0xc)) - 5277 3d/compare-eax-and 0/imm32/false - 5278 58/pop-to-eax - 5279 75/jump-if-!= $find-in-function-outputs:end/disp8 - 5280 # curr = curr->next - 5281 8b/-> *(ecx+4) 1/r32/ecx # List-next - 5282 eb/jump loop/disp8 - 5283 } - 5284 b8/copy-to-eax 0/imm32 - 5285 $find-in-function-outputs:end: - 5286 # . restore registers - 5287 59/pop-to-ecx - 5288 # . epilogue - 5289 89/<- %esp 5/r32/ebp - 5290 5d/pop-to-ebp - 5291 c3/return - 5292 - 5293 test-parse-mu-stmt: - 5294 # . prologue - 5295 55/push-ebp - 5296 89/<- %ebp 4/r32/esp - 5297 # setup - 5298 (clear-stream _test-input-stream) - 5299 (write _test-input-stream "increment n\n") - 5300 # var vars/ecx: (stack (addr var) 4) - 5301 81 5/subop/subtract %esp 0x10/imm32 - 5302 68/push 0x10/imm32/length - 5303 68/push 0/imm32/top - 5304 89/<- %ecx 4/r32/esp - 5305 (clear-stack %ecx) - 5306 # var v/edx: var - 5307 81 5/subop/subtract %esp 0x14/imm32 # Var-size - 5308 89/<- %edx 4/r32/esp - 5309 (zero-out %edx 0x14) # Var-size - 5310 # v->name = "n" - 5311 c7 0/subop/copy *edx "n"/imm32 # Var-name - 5312 # - 5313 (push %ecx %edx) - 5314 # convert - 5315 (parse-mu-stmt _test-input-stream %ecx) # => eax - 5316 # check result - 5317 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 - 5318 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation - 5319 # edx: (handle list var) = result->inouts - 5320 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts - 5321 # ebx: (handle var) = result->inouts->value - 5322 8b/-> *edx 3/r32/ebx # Stmt-var-value - 5323 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name - 5324 # . epilogue - 5325 89/<- %esp 5/r32/ebp - 5326 5d/pop-to-ebp - 5327 c3/return - 5328 - 5329 test-parse-mu-stmt-with-comma: - 5330 # . prologue - 5331 55/push-ebp - 5332 89/<- %ebp 4/r32/esp - 5333 # setup - 5334 (clear-stream _test-input-stream) - 5335 (write _test-input-stream "copy-to n, 3\n") - 5336 # var vars/ecx: (stack (addr var) 4) - 5337 81 5/subop/subtract %esp 0x10/imm32 - 5338 68/push 0x10/imm32/length - 5339 68/push 0/imm32/top - 5340 89/<- %ecx 4/r32/esp - 5341 (clear-stack %ecx) - 5342 # var v/edx: var - 5343 81 5/subop/subtract %esp 0x14/imm32 # Var-size - 5344 89/<- %edx 4/r32/esp - 5345 (zero-out %edx 0x14) # Var-size - 5346 # v->name = "n" - 5347 c7 0/subop/copy *edx "n"/imm32 # Var-name - 5348 # - 5349 (push %ecx %edx) - 5350 # convert - 5351 (parse-mu-stmt _test-input-stream %ecx) # => eax - 5352 # check result - 5353 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 - 5354 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation - 5355 # edx: (handle list var) = result->inouts - 5356 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts - 5357 # ebx: (handle var) = result->inouts->value - 5358 8b/-> *edx 3/r32/ebx # Stmt-var-value - 5359 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name - 5360 # . epilogue - 5361 89/<- %esp 5/r32/ebp - 5362 5d/pop-to-ebp - 5363 c3/return - 5364 - 5365 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) - 5366 # . prologue - 5367 55/push-ebp - 5368 89/<- %ebp 4/r32/esp - 5369 # . save registers - 5370 51/push-ecx - 5371 # - 5372 (allocate *(ebp+8) *Function-size) # => eax - 5373 8b/-> *(ebp+0xc) 1/r32/ecx - 5374 89/<- *eax 1/r32/ecx # Function-name - 5375 8b/-> *(ebp+0x10) 1/r32/ecx - 5376 89/<- *(eax+4) 1/r32/ecx # Function-subx-name - 5377 8b/-> *(ebp+0x14) 1/r32/ecx - 5378 89/<- *(eax+8) 1/r32/ecx # Function-inouts - 5379 8b/-> *(ebp+0x18) 1/r32/ecx - 5380 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs - 5381 8b/-> *(ebp+0x1c) 1/r32/ecx - 5382 89/<- *(eax+0x10) 1/r32/ecx # Function-body - 5383 8b/-> *(ebp+0x20) 1/r32/ecx - 5384 89/<- *(eax+0x14) 1/r32/ecx # Function-next - 5385 $new-function:end: - 5386 # . restore registers - 5387 59/pop-to-ecx - 5388 # . epilogue - 5389 89/<- %esp 5/r32/ebp - 5390 5d/pop-to-ebp - 5391 c3/return - 5392 - 5393 new-var: # ad: (addr allocation-descriptor), name: (addr array byte) -> result/eax: (handle var) - 5394 # . prologue - 5395 55/push-ebp - 5396 89/<- %ebp 4/r32/esp - 5397 # . save registers - 5398 51/push-ecx - 5399 # - 5400 (allocate *(ebp+8) *Var-size) # => eax - 5401 (zero-out %eax *Var-size) - 5402 8b/-> *(ebp+0xc) 1/r32/ecx - 5403 89/<- *eax 1/r32/ecx # Var-name - 5404 $new-var:end: - 5405 # . restore registers - 5406 59/pop-to-ecx - 5407 # . epilogue - 5408 89/<- %esp 5/r32/ebp - 5409 5d/pop-to-ebp - 5410 c3/return - 5411 - 5412 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5413 # . prologue - 5414 55/push-ebp - 5415 89/<- %ebp 4/r32/esp - 5416 # . save registers - 5417 51/push-ecx - 5418 # if (!is-hex-int?(name)) abort - 5419 (is-hex-int? *(ebp+0xc)) # => eax - 5420 3d/compare-eax-and 0/imm32/false - 5421 0f 84/jump-if-= $new-literal-integer:abort/disp32 - 5422 # var type/ecx: (handle tree type-id) = new type() - 5423 (allocate *(ebp+8) *Tree-size) # => eax - 5424 (zero-out %eax *Tree-size) # default type is 'literal' - 5425 89/<- %ecx 0/r32/eax - 5426 # result = new var(s) - 5427 (new-var-from-slice *(ebp+8) *(ebp+0xc)) # => eax - 5428 89/<- *(eax+4) 1/r32/ecx - 5429 $new-literal-integer:end: - 5430 # . restore registers - 5431 59/pop-to-ecx - 5432 # . epilogue - 5433 89/<- %esp 5/r32/ebp - 5434 5d/pop-to-ebp - 5435 c3/return - 5436 - 5437 $new-literal-integer:abort: - 5438 (write-buffered Stderr "variable cannot begin with a digit '") - 5439 (write-slice-buffered Stderr *(ebp+0xc)) - 5440 (write-buffered Stderr "'\n") - 5441 (flush Stderr) - 5442 # . syscall(exit, 1) - 5443 bb/copy-to-ebx 1/imm32 - 5444 b8/copy-to-eax 1/imm32/exit - 5445 cd/syscall 0x80/imm8 - 5446 # never gets here - 5447 - 5448 new-literal: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5449 # . prologue - 5450 55/push-ebp - 5451 89/<- %ebp 4/r32/esp - 5452 # . save registers - 5453 51/push-ecx - 5454 52/push-edx - 5455 # var s/ecx: (addr array byte) - 5456 (slice-to-string Heap *(ebp+0xc)) # => eax - 5457 89/<- %ecx 0/r32/eax - 5458 # type = new type() - 5459 (allocate *(ebp+8) *Tree-size) # => eax - 5460 (zero-out %eax *Tree-size) # default type is 'literal' - 5461 89/<- %edx 0/r32/eax - 5462 # eax = result - 5463 (new-var *(ebp+8) %ecx) # => eax - 5464 # result->type = type - 5465 89/<- *(eax+4) 2/r32/edx # Var-type - 5466 $new-literal:end: - 5467 # . restore registers - 5468 5a/pop-to-edx - 5469 59/pop-to-ecx - 5470 # . epilogue - 5471 89/<- %esp 5/r32/ebp - 5472 5d/pop-to-ebp - 5473 c3/return - 5474 - 5475 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) - 5476 # . prologue - 5477 55/push-ebp - 5478 89/<- %ebp 4/r32/esp - 5479 # . save registers - 5480 51/push-ecx - 5481 # result = new-var(slice-to-string(name)) - 5482 (slice-to-string Heap *(ebp+0xc)) # => eax - 5483 (new-var *(ebp+8) %eax) - 5484 $new-var-from-slice:end: - 5485 # . restore registers - 5486 59/pop-to-ecx - 5487 # . epilogue - 5488 89/<- %esp 5/r32/ebp - 5489 5d/pop-to-ebp - 5490 c3/return - 5491 - 5492 new-block: # ad: (addr allocation-descriptor), data: (handle list stmt) -> result/eax: (handle stmt) - 5493 # . prologue - 5494 55/push-ebp - 5495 89/<- %ebp 4/r32/esp - 5496 # . save registers - 5497 51/push-ecx - 5498 # - 5499 (allocate *(ebp+8) *Stmt-size) # => eax - 5500 (zero-out %eax *Stmt-size) - 5501 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag - 5502 8b/-> *(ebp+0xc) 1/r32/ecx - 5503 89/<- *(eax+4) 1/r32/ecx # Block-stmts - 5504 $new-block:end: - 5505 # . restore registers - 5506 59/pop-to-ecx - 5507 # . epilogue - 5508 89/<- %esp 5/r32/ebp - 5509 5d/pop-to-ebp - 5510 c3/return - 5511 - 5512 new-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) - 5513 # . prologue - 5514 55/push-ebp - 5515 89/<- %ebp 4/r32/esp - 5516 # . save registers - 5517 51/push-ecx - 5518 # - 5519 (allocate *(ebp+8) *Stmt-size) # => eax - 5520 (zero-out %eax *Stmt-size) - 5521 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag - 5522 # result->var = var - 5523 8b/-> *(ebp+0xc) 1/r32/ecx - 5524 89/<- *(eax+4) 1/r32/ecx # Vardef-var - 5525 $new-var-def:end: - 5526 # . restore registers - 5527 59/pop-to-ecx - 5528 # . epilogue - 5529 89/<- %esp 5/r32/ebp - 5530 5d/pop-to-ebp - 5531 c3/return - 5532 - 5533 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) - 5534 # . prologue - 5535 55/push-ebp - 5536 89/<- %ebp 4/r32/esp - 5537 # . save registers - 5538 51/push-ecx - 5539 57/push-edi - 5540 # ecx = var - 5541 8b/-> *(ebp+0xc) 1/r32/ecx - 5542 # edi = result - 5543 (allocate *(ebp+8) *Stmt-size) # => eax - 5544 89/<- %edi 0/r32/eax - 5545 (zero-out %edi *Stmt-size) - 5546 # set tag - 5547 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag - 5548 # set output - 5549 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax - 5550 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs - 5551 $new-reg-var-def:end: - 5552 89/<- %eax 7/r32/edi - 5553 # . restore registers - 5554 5f/pop-to-edi - 5555 59/pop-to-ecx - 5556 # . epilogue - 5557 89/<- %esp 5/r32/ebp - 5558 5d/pop-to-ebp - 5559 c3/return - 5560 - 5561 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) - 5562 # . prologue - 5563 55/push-ebp - 5564 89/<- %ebp 4/r32/esp - 5565 # . save registers - 5566 51/push-ecx - 5567 # - 5568 (allocate *(ebp+8) *List-size) # => eax - 5569 (zero-out %eax *List-size) - 5570 8b/-> *(ebp+0xc) 1/r32/ecx - 5571 89/<- *eax 1/r32/ecx # List-value - 5572 # if (list == null) return result - 5573 81 7/subop/compare *(ebp+0x10) 0/imm32 - 5574 74/jump-if-= $append-list:end/disp8 - 5575 # otherwise append - 5576 # var curr/ecx = list - 5577 8b/-> *(ebp+0x10) 1/r32/ecx - 5578 # while (curr->next != null) curr = curr->next - 5579 { - 5580 81 7/subop/compare *(ecx+4) 0/imm32 # List-next - 5581 74/jump-if-= break/disp8 - 5582 # curr = curr->next - 5583 8b/-> *(ecx+4) 1/r32/ecx - 5584 eb/jump loop/disp8 - 5585 } - 5586 # curr->next = result - 5587 89/<- *(ecx+4) 0/r32/eax - 5588 # return list - 5589 8b/-> *(ebp+0x10) 0/r32/eax - 5590 $append-list:end: - 5591 # . restore registers - 5592 59/pop-to-ecx - 5593 # . epilogue - 5594 89/<- %esp 5/r32/ebp - 5595 5d/pop-to-ebp - 5596 c3/return - 5597 - 5598 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) - 5599 # . prologue - 5600 55/push-ebp - 5601 89/<- %ebp 4/r32/esp - 5602 # . save registers - 5603 51/push-ecx - 5604 # - 5605 (allocate *(ebp+8) *Stmt-var-size) # => eax - 5606 (zero-out %eax *Stmt-var-size) - 5607 8b/-> *(ebp+0xc) 1/r32/ecx - 5608 89/<- *eax 1/r32/ecx # Stmt-var-value - 5609 8b/-> *(ebp+0x14) 1/r32/ecx - 5610 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref - 5611 # if (list == null) return result - 5612 81 7/subop/compare *(ebp+0x10) 0/imm32 - 5613 74/jump-if-= $append-stmt-var:end/disp8 - 5614 # otherwise append - 5615 # var curr/ecx: (handle stmt-var) = vars - 5616 8b/-> *(ebp+0x10) 1/r32/ecx - 5617 # while (curr->next != null) curr = curr->next - 5618 { - 5619 81 7/subop/compare *(ecx+4) 0/imm32 # List-next - 5620 74/jump-if-= break/disp8 - 5621 # curr = curr->next - 5622 8b/-> *(ecx+4) 1/r32/ecx - 5623 eb/jump loop/disp8 - 5624 } - 5625 # curr->next = result - 5626 89/<- *(ecx+4) 0/r32/eax - 5627 # return vars - 5628 8b/-> *(ebp+0x10) 0/r32/eax - 5629 $append-stmt-var:end: - 5630 # . restore registers - 5631 59/pop-to-ecx - 5632 # . epilogue - 5633 89/<- %esp 5/r32/ebp - 5634 5d/pop-to-ebp - 5635 c3/return - 5636 - 5637 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) - 5638 # . prologue - 5639 55/push-ebp - 5640 89/<- %ebp 4/r32/esp - 5641 # . save registers - 5642 56/push-esi - 5643 # esi = block - 5644 8b/-> *(ebp+0xc) 6/r32/esi - 5645 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-stmts - 5646 89/<- *(esi+4) 0/r32/eax # Block-stmts - 5647 $append-to-block:end: - 5648 # . restore registers - 5649 5e/pop-to-esi - 5650 # . epilogue - 5651 89/<- %esp 5/r32/ebp - 5652 5d/pop-to-ebp - 5653 c3/return - 5654 - 5655 ## Parsing types - 5656 # We need to create metadata on user-defined types, and we need to use this - 5657 # metadata as we parse instructions. - 5658 # However, we also want to allow types to be used before their definitions. - 5659 # This means we can't ever assume any type data structures exist. - 5660 - 5661 lookup-or-create-constant: # container: (handle stmt-var), field-name: (addr slice) -> result/eax: (handle var) - 5662 # . prologue - 5663 55/push-ebp - 5664 89/<- %ebp 4/r32/esp - 5665 # . save registers - 5666 56/push-esi - 5667 # var container-type/esi: type-id - 5668 (container-type *(ebp+8)) # => eax - 5669 #? (write-buffered Stderr "lookup-or-create-constant: container type-id: ") - 5670 #? (print-int32-buffered Stderr %eax) - 5671 #? (write-buffered Stderr Newline) - 5672 #? (flush Stderr) - 5673 89/<- %esi 0/r32/eax - 5674 # var typeinfo/eax: (addr typeinfo) - 5675 (find-or-create-typeinfo %esi) # => eax - 5676 #? (write-buffered Stderr "lookup-or-create-constant: typeinfo: ") - 5677 #? (print-int32-buffered Stderr %eax) - 5678 #? (write-buffered Stderr Newline) - 5679 #? (flush Stderr) - 5680 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) - 5681 (find-or-create-typeinfo-output-var %eax *(ebp+0xc)) # => eax - 5682 $lookup-or-create-constant:end: - 5683 # . restore registers - 5684 5e/pop-to-esi - 5685 # . epilogue - 5686 89/<- %esp 5/r32/ebp - 5687 5d/pop-to-ebp - 5688 c3/return - 5689 - 5690 # if addr var: - 5691 # container->var->type->right->left->value - 5692 # otherwise - 5693 # container->var->type->value - 5694 container-type: # container: (handle stmt-var) -> result/eax: type-id - 5695 # . prologue - 5696 55/push-ebp - 5697 89/<- %ebp 4/r32/esp - 5698 # - 5699 8b/-> *(ebp+8) 0/r32/eax - 5700 8b/-> *eax 0/r32/eax # Stmt-var-value - 5701 8b/-> *(eax+4) 0/r32/eax # Var-type - 5702 { - 5703 81 7/subop/compare *(eax+4) 0/imm32 - 5704 74/jump-if-= break/disp8 - 5705 8b/-> *(eax+4) 0/r32/eax # Tree-right - 5706 8b/-> *eax 0/r32/eax # Tree-left - 5707 } - 5708 8b/-> *eax 0/r32/eax # Atom-value - 5709 $container-type:end: - 5710 # . epilogue - 5711 89/<- %esp 5/r32/ebp - 5712 5d/pop-to-ebp - 5713 c3/return - 5714 - 5715 find-or-create-typeinfo: # t: type-id -> result/eax: (handle typeinfo) - 5716 # . prologue - 5717 55/push-ebp - 5718 89/<- %ebp 4/r32/esp - 5719 # . save registers - 5720 51/push-ecx - 5721 # eax = find-typeinfo(t) - 5722 (find-typeinfo *(ebp+8)) # => eax - 5723 { - 5724 # if (curr != 0) break - 5725 3d/compare-eax-and 0/imm32 - 5726 75/jump-if-!= break/disp8 - 5727 $find-or-create-typeinfo:create: - 5728 (allocate Heap *Typeinfo-size) # => eax - 5729 (zero-out %eax *Typeinfo-size) - 5730 # result->id = t - 5731 8b/-> *(ebp+8) 1/r32/ecx - 5732 89/<- *eax 1/r32/ecx # Typeinfo-id - 5733 # result->fields = new table - 5734 # . ecx = new table - 5735 50/push-eax - 5736 (new-stream Heap 0x40 *Typeinfo-fields-row-size) # => eax - 5737 89/<- %ecx 0/r32/eax - 5738 58/pop-to-eax - 5739 # . result->fields = ecx - 5740 89/<- *(eax+4) 1/r32/ecx # Typeinfo-fields - 5741 # result->next = Program->types - 5742 8b/-> *_Program-types 1/r32/ecx - 5743 89/<- *(eax+0xc) 1/r32/ecx # Typeinfo-next - 5744 # Program->types = result - 5745 89/<- *_Program-types 0/r32/eax - 5746 } - 5747 $find-or-create-typeinfo:end: - 5748 # . restore registers - 5749 59/pop-to-ecx - 5750 # . epilogue - 5751 89/<- %esp 5/r32/ebp - 5752 5d/pop-to-ebp - 5753 c3/return - 5754 - 5755 find-typeinfo: # t: type-id -> result/eax: (handle typeinfo) - 5756 # . prologue - 5757 55/push-ebp - 5758 89/<- %ebp 4/r32/esp - 5759 # . save registers - 5760 51/push-ecx - 5761 # ecx = t - 5762 8b/-> *(ebp+8) 1/r32/ecx - 5763 # var curr/eax: (handle typeinfo) = Program->types - 5764 8b/-> *_Program-types 0/r32/eax - 5765 { - 5766 # if (curr == 0) break - 5767 3d/compare-eax-and 0/imm32 - 5768 74/jump-if-= break/disp8 - 5769 # if (curr->id == t) return curr - 5770 39/compare *eax 1/r32/ecx # Typeinfo-id - 5771 0f 84/jump-if-= $find-or-create-typeinfo:end/disp32 - 5772 # curr = curr->next - 5773 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-next - 5774 # - 5775 eb/jump loop/disp8 - 5776 } - 5777 $find-typeinfo:end: - 5778 # . restore registers - 5779 59/pop-to-ecx - 5780 # . epilogue - 5781 89/<- %esp 5/r32/ebp - 5782 5d/pop-to-ebp - 5783 c3/return - 5784 - 5785 find-or-create-typeinfo-output-var: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle var) - 5786 # . prologue - 5787 55/push-ebp - 5788 89/<- %ebp 4/r32/esp - 5789 # . save registers - 5790 51/push-ecx - 5791 56/push-esi - 5792 # esi = find-or-create-typeinfo-fields(T, f) - 5793 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc)) # => eax - 5794 89/<- %esi 0/r32/eax - 5795 # if output var doesn't exist, create it - 5796 { - 5797 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-entry-output-var - 5798 75/jump-if-!= break/disp8 - 5799 # var type/eax: (handle tree type-id) = new var("dummy name", constant type, -1 offset) - 5800 (allocate Heap *Tree-size) # => eax - 5801 c7 0/subop/copy *eax 6/imm32/constant # Atom-value - 5802 c7 0/subop/copy *(eax+4) 0/imm32 # Tree-right - 5803 89/<- %ecx 0/r32/eax - 5804 # eax = result - 5805 (new-var Heap "field") # => eax - 5806 # result->type = type - 5807 89/<- *(eax+4) 1/r32/ecx # Var-type - 5808 # result->offset isn't filled out yet - 5809 c7 0/subop/copy *(eax+0xc) -1/imm32/uninitialized # Var-offset - 5810 # save result as output var - 5811 89/<- *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 5812 } - 5813 # return the output var - 5814 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 5815 $find-or-create-typeinfo-output-var:end: - 5816 # . restore registers - 5817 5e/pop-to-esi - 5818 59/pop-to-ecx - 5819 # . epilogue - 5820 89/<- %esp 5/r32/ebp - 5821 5d/pop-to-ebp - 5822 c3/return - 5823 - 5824 find-or-create-typeinfo-fields: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle typeinfo-entry) - 5825 # . prologue - 5826 55/push-ebp - 5827 89/<- %ebp 4/r32/esp - 5828 # . save registers - 5829 56/push-esi - 5830 # esi = T->fields - 5831 8b/-> *(ebp+8) 6/r32/esi - 5832 8b/-> *(esi+4) 6/r32/esi # Typeinfo-fields - 5833 # esi = get-or-insert(T->fields, f) - 5834 (leaky-get-or-insert-slice %esi *(ebp+0xc) *Typeinfo-fields-row-size) # => eax - 5835 89/<- %esi 0/r32/eax - 5836 # if typeinfo-entry doesn't exist, allocate it - 5837 { - 5838 81 7/subop/compare *esi 0/imm32 # output var - 5839 75/jump-if-!= break/disp8 - 5840 (allocate Heap *Typeinfo-entry-size) # => eax - 5841 (zero-out %eax *Typeinfo-entry-size) - 5842 89/<- *esi 0/r32/eax - 5843 } - 5844 # eax = T->fields[f]->entry - 5845 8b/-> *esi 0/r32/eax - 5846 $find-or-create-typeinfo-fields:end: - 5847 # . restore registers - 5848 5e/pop-to-esi - 5849 # . epilogue - 5850 89/<- %esp 5/r32/ebp - 5851 5d/pop-to-ebp - 5852 c3/return - 5853 - 5854 populate-mu-type: # in: (addr stream byte), t: (handle typeinfo) - 5855 # pseudocode: - 5856 # var line: (stream byte 512) - 5857 # curr-index = 0 - 5858 # while true - 5859 # clear-stream(line) - 5860 # read-line-buffered(in, line) - 5861 # if line->write == 0 - 5862 # abort - 5863 # word-slice = next-mu-token(line) - 5864 # if slice-empty?(word-slice) # end of line - 5865 # continue - 5866 # if slice-equal?(word-slice, "}") - 5867 # break - 5868 # var v: (handle var) = parse-var-with-type(word-slice, line) - 5869 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) - 5870 # TODO: ensure that r->first is null - 5871 # r->index = curr-index - 5872 # curr-index++ - 5873 # r->input-var = v - 5874 # if r->output-var == 0 - 5875 # r->output-var = new literal - 5876 # TODO: ensure nothing else in line - 5877 # t->total-size-in-bytes = -2 (not yet initialized) - 5878 # - 5879 # . prologue - 5880 55/push-ebp - 5881 89/<- %ebp 4/r32/esp - 5882 # var curr-index: int at *(ebp-4) - 5883 68/push 0/imm32 - 5884 # . save registers - 5885 50/push-eax - 5886 51/push-ecx - 5887 52/push-edx - 5888 53/push-ebx - 5889 56/push-esi - 5890 57/push-edi - 5891 # edi = t - 5892 8b/-> *(ebp+0xc) 7/r32/edi - 5893 # var line/ecx: (stream byte 512) - 5894 81 5/subop/subtract %esp 0x200/imm32 - 5895 68/push 0x200/imm32/length - 5896 68/push 0/imm32/read - 5897 68/push 0/imm32/write - 5898 89/<- %ecx 4/r32/esp - 5899 # var word-slice/edx: slice - 5900 68/push 0/imm32/end - 5901 68/push 0/imm32/start - 5902 89/<- %edx 4/r32/esp - 5903 { - 5904 $populate-mu-type:line-loop: - 5905 (clear-stream %ecx) - 5906 (read-line-buffered *(ebp+8) %ecx) - 5907 # if (line->write == 0) abort - 5908 81 7/subop/compare *ecx 0/imm32 - 5909 0f 84/jump-if-= $populate-mu-type:abort/disp32 - 5910 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ - 5916 (next-mu-token %ecx %edx) - 5917 # if slice-empty?(word-slice) continue - 5918 (slice-empty? %edx) # => eax - 5919 3d/compare-eax-and 0/imm32 - 5920 0f 85/jump-if-!= loop/disp32 - 5921 # if slice-equal?(word-slice, "}") break - 5922 (slice-equal? %edx "}") - 5923 3d/compare-eax-and 0/imm32 - 5924 0f 85/jump-if-!= break/disp32 - 5925 $populate-mu-type:parse-element: - 5926 # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line) - 5927 (parse-var-with-type %edx %ecx) # => eax - 5928 89/<- %esi 0/r32/eax - 5929 $populate-mu-type:create-typeinfo-fields: - 5930 # var r/ebx: (handle typeinfo-entry) - 5931 (find-or-create-typeinfo-fields %edi %edx) # => eax - 5932 89/<- %ebx 0/r32/eax - 5933 #? (write-buffered Stderr "var ") - 5934 #? (write-buffered Stderr *esi) # Var-name - 5935 #? (write-buffered Stderr " is at index ") - 5936 #? (print-int32-buffered Stderr *(ebp-4)) - 5937 #? (write-buffered Stderr Newline) - 5938 #? (flush Stderr) - 5939 # r->index = curr-index - 5940 8b/-> *(ebp-4) 0/r32/eax - 5941 89/<- *(ebx+4) 0/r32/eax # Typeinfo-entry-index - 5942 # ++curr-index - 5943 ff 0/subop/increment *(ebp-4) - 5944 $populate-mu-type:set-input-type: - 5945 # r->input-var = v - 5946 89/<- *ebx 6/r32/esi # Typeinfo-entry-input-var - 5947 { - 5948 $populate-mu-type:create-output-type: - 5949 # if (r->output-var == 0) create a new var with some placeholder data - 5950 81 7/subop/compare *(ebx+8) 0/imm32 # Typeinfo-entry-output-var - 5951 75/jump-if-!= break/disp8 - 5952 (new-literal Heap %edx) # => eax - 5953 89/<- *(ebx+8) 0/r32/eax # Typeinfo-entry-output-var - 5954 } - 5955 e9/jump loop/disp32 - 5956 } - 5957 $populate-mu-type:invalidate-total-size-in-bytes: - 5958 # Offsets and total size may not be accurate here since we may not yet - 5959 # have encountered the element types. - 5960 # We'll recompute them separately after parsing the entire program. - 5961 c7 0/subop/copy *(edi+8) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes - 5962 $populate-mu-type:end: - 5963 # . reclaim locals - 5964 81 0/subop/add %esp 0x214/imm32 - 5965 # . restore registers - 5966 5f/pop-to-edi - 5967 5e/pop-to-esi - 5968 5b/pop-to-ebx - 5969 5a/pop-to-edx - 5970 59/pop-to-ecx - 5971 58/pop-to-eax - 5972 # reclaim curr-index - 5973 81 0/subop/add %esp 4/imm32 - 5974 # . epilogue - 5975 89/<- %esp 5/r32/ebp - 5976 5d/pop-to-ebp - 5977 c3/return - 5978 - 5979 $populate-mu-type:abort: - 5980 # error("unexpected top-level command: " word-slice "\n") - 5981 (write-buffered Stderr "incomplete type definition '") - 5982 (type-name *edi) # Typeinfo-id => eax - 5983 (write-buffered Stderr %eax) - 5984 (write-buffered Stderr "\n") - 5985 (flush Stderr) - 5986 # . syscall(exit, 1) - 5987 bb/copy-to-ebx 1/imm32 - 5988 b8/copy-to-eax 1/imm32/exit - 5989 cd/syscall 0x80/imm8 - 5990 # never gets here - 5991 - 5992 type-name: # index: int -> result/eax: (addr array byte) - 5993 # . prologue - 5994 55/push-ebp - 5995 89/<- %ebp 4/r32/esp - 5996 # - 5997 (index Type-id *(ebp+8)) - 5998 $type-name:end: - 5999 # . epilogue - 6000 89/<- %esp 5/r32/ebp - 6001 5d/pop-to-ebp - 6002 c3/return - 6003 - 6004 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) - 6005 # . prologue - 6006 55/push-ebp - 6007 89/<- %ebp 4/r32/esp - 6008 # . save registers - 6009 56/push-esi - 6010 # TODO: bounds-check index - 6011 # esi = arr - 6012 8b/-> *(ebp+8) 6/r32/esi - 6013 # eax = index - 6014 8b/-> *(ebp+0xc) 0/r32/eax - 6015 # eax = *(arr + 12 + index) - 6016 8b/-> *(esi+eax+0xc) 0/r32/eax - 6017 $index:end: - 6018 # . restore registers - 6019 5e/pop-to-esi + 5115 59/pop-to-ecx + 5116 # . epilogue + 5117 89/<- %esp 5/r32/ebp + 5118 5d/pop-to-ebp + 5119 c3/return + 5120 + 5121 # if 'name' starts with a digit, create a new literal var for it + 5122 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found + 5123 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5124 # . prologue + 5125 55/push-ebp + 5126 89/<- %ebp 4/r32/esp + 5127 # . save registers + 5128 51/push-ecx + 5129 56/push-esi + 5130 # esi = name + 5131 8b/-> *(ebp+8) 6/r32/esi + 5132 # if slice-empty?(name) abort + 5133 (slice-empty? %esi) # => eax + 5134 3d/compare-eax-and 0/imm32/false + 5135 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 + 5136 # var c/ecx: byte = *name->start + 5137 8b/-> *esi 1/r32/ecx + 5138 8a/copy-byte *ecx 1/r32/CL + 5139 81 4/subop/and %ecx 0xff/imm32 + 5140 # if is-decimal-digit?(c) return new var(name) + 5141 { + 5142 (is-decimal-digit? %ecx) # => eax + 5143 3d/compare-eax-and 0/imm32/false + 5144 74/jump-if-= break/disp8 + 5145 (new-literal-integer Heap %esi) # => eax + 5146 eb/jump $lookup-var-or-literal:end/disp8 + 5147 } + 5148 # else if (c == '"') return new var(name) + 5149 { + 5150 81 7/subop/compare %ecx 0x22/imm32/dquote + 5151 75/jump-if-!= break/disp8 + 5152 (new-literal Heap %esi) # => eax + 5153 eb/jump $lookup-var-or-literal:end/disp8 + 5154 } + 5155 # otherwise return lookup-var(name, vars) + 5156 { + 5157 (lookup-var %esi *(ebp+0xc)) # => eax + 5158 } + 5159 $lookup-var-or-literal:end: + 5160 # . restore registers + 5161 5e/pop-to-esi + 5162 59/pop-to-ecx + 5163 # . epilogue + 5164 89/<- %esp 5/r32/ebp + 5165 5d/pop-to-ebp + 5166 c3/return + 5167 + 5168 $lookup-var-or-literal:abort: + 5169 (write-buffered Stderr "empty variable!") + 5170 (flush Stderr) + 5171 # . syscall(exit, 1) + 5172 bb/copy-to-ebx 1/imm32 + 5173 b8/copy-to-eax 1/imm32/exit + 5174 cd/syscall 0x80/imm8 + 5175 # never gets here + 5176 + 5177 # return first 'name' from the top (back) of 'vars' and abort if not found + 5178 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5179 # . prologue + 5180 55/push-ebp + 5181 89/<- %ebp 4/r32/esp + 5182 # var target/eax: (handle array byte) = slice-to-string(name) + 5183 (slice-to-string Heap *(ebp+8)) # => eax + 5184 # + 5185 (lookup-var-helper %eax *(ebp+0xc)) # => eax + 5186 # if (result == 0) abort + 5187 3d/compare-eax-and 0/imm32 + 5188 74/jump-if-= $lookup-var:abort/disp8 + 5189 $lookup-var:end: + 5190 # . epilogue + 5191 89/<- %esp 5/r32/ebp + 5192 5d/pop-to-ebp + 5193 c3/return + 5194 + 5195 $lookup-var:abort: + 5196 (write-buffered Stderr "unknown variable '") + 5197 (write-slice-buffered Stderr *(ebp+8)) + 5198 (write-buffered Stderr "'\n") + 5199 (flush Stderr) + 5200 # . syscall(exit, 1) + 5201 bb/copy-to-ebx 1/imm32 + 5202 b8/copy-to-eax 1/imm32/exit + 5203 cd/syscall 0x80/imm8 + 5204 # never gets here + 5205 + 5206 # return first 'name' from the top (back) of 'vars', and 0/null if not found + 5207 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) + 5208 # pseudocode: + 5209 # var curr: (addr handle var) = &vars->data[vars->top - 4] + 5210 # var min = vars->data + 5211 # while curr >= min + 5212 # var v: (handle var) = *curr + 5213 # if v->name == name + 5214 # return v + 5215 # return 0 + 5216 # + 5217 # . prologue + 5218 55/push-ebp + 5219 89/<- %ebp 4/r32/esp + 5220 # . save registers + 5221 52/push-edx + 5222 53/push-ebx + 5223 56/push-esi + 5224 # esi = vars + 5225 8b/-> *(ebp+0xc) 6/r32/esi + 5226 # ebx = vars->top + 5227 8b/-> *esi 3/r32/ebx + 5228 # if (vars->top > vars->length) abort + 5229 3b/compare 0/r32/eax *(esi+4) + 5230 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 + 5231 # var min/edx: (addr handle var) = vars->data + 5232 8d/copy-address *(esi+8) 2/r32/edx + 5233 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] + 5234 81 5/subop/subtract %ebx 4/imm32 + 5235 8d/copy-address *(esi+ebx+8) 3/r32/ebx + 5236 { + 5237 # if (curr < min) return 0 + 5238 39/compare %ebx 2/r32/edx + 5239 b8/copy-to-eax 0/imm32 + 5240 0f 82/jump-if-addr< break/disp32 + 5241 # var v/eax: (handle var) = *curr + 5242 8b/-> *ebx 0/r32/eax + 5243 # if (v->name == name) return v + 5244 (string-equal? *eax *(ebp+8)) # Var-name + 5245 3d/compare-eax-and 0/imm32/false + 5246 8b/-> *ebx 0/r32/eax + 5247 75/jump-if-!= break/disp8 + 5248 # curr -= 4 + 5249 81 5/subop/subtract %ebx 4/imm32 + 5250 e9/jump loop/disp32 + 5251 } + 5252 $lookup-var-helper:end: + 5253 # . restore registers + 5254 5e/pop-to-esi + 5255 5b/pop-to-ebx + 5256 5a/pop-to-edx + 5257 # . epilogue + 5258 89/<- %esp 5/r32/ebp + 5259 5d/pop-to-ebp + 5260 c3/return + 5261 + 5262 $lookup-var-helper:error1: + 5263 (write-buffered Stderr "malformed stack when looking up '") + 5264 (write-slice-buffered Stderr *(ebp+8)) + 5265 (write-buffered Stderr "'\n") + 5266 (flush Stderr) + 5267 # . syscall(exit, 1) + 5268 bb/copy-to-ebx 1/imm32 + 5269 b8/copy-to-eax 1/imm32/exit + 5270 cd/syscall 0x80/imm8 + 5271 # never gets here + 5272 + 5273 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found + 5274 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) + 5275 # . prologue + 5276 55/push-ebp + 5277 89/<- %ebp 4/r32/esp + 5278 # . save registers + 5279 51/push-ecx + 5280 # var target/ecx: (handle array byte) = slice-to-string(name) + 5281 (slice-to-string Heap *(ebp+8)) # => eax + 5282 89/<- %ecx 0/r32/eax + 5283 # + 5284 (lookup-var-helper %ecx *(ebp+0xc)) # => eax + 5285 { + 5286 # if (result != 0) return + 5287 3d/compare-eax-and 0/imm32 + 5288 75/jump-if-!= break/disp8 + 5289 # if name is one of fn's outputs, return it + 5290 { + 5291 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax + 5292 3d/compare-eax-and 0/imm32 + 5293 # otherwise abort + 5294 0f 84/jump-if-!= $lookup-var:abort/disp32 + 5295 } + 5296 } + 5297 $lookup-or-define-var:end: + 5298 # . restore registers + 5299 59/pop-to-ecx + 5300 # . epilogue + 5301 89/<- %esp 5/r32/ebp + 5302 5d/pop-to-ebp + 5303 c3/return + 5304 + 5305 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) + 5306 # . prologue + 5307 55/push-ebp + 5308 89/<- %ebp 4/r32/esp + 5309 # . save registers + 5310 51/push-ecx + 5311 # var curr/ecx: (handle list var) = fn->outputs + 5312 8b/-> *(ebp+8) 1/r32/ecx + 5313 8b/-> *(ecx+0xc) 1/r32/ecx + 5314 # while curr != null + 5315 { + 5316 81 7/subop/compare %ecx 0/imm32 + 5317 74/jump-if-= break/disp8 + 5318 # var v: (handle var) = *curr + 5319 8b/-> *ecx 0/r32/eax # List-value + 5320 # if (curr->name == name) return curr + 5321 50/push-eax + 5322 (string-equal? *eax *(ebp+0xc)) + 5323 3d/compare-eax-and 0/imm32/false + 5324 58/pop-to-eax + 5325 75/jump-if-!= $find-in-function-outputs:end/disp8 + 5326 # curr = curr->next + 5327 8b/-> *(ecx+4) 1/r32/ecx # List-next + 5328 eb/jump loop/disp8 + 5329 } + 5330 b8/copy-to-eax 0/imm32 + 5331 $find-in-function-outputs:end: + 5332 # . restore registers + 5333 59/pop-to-ecx + 5334 # . epilogue + 5335 89/<- %esp 5/r32/ebp + 5336 5d/pop-to-ebp + 5337 c3/return + 5338 + 5339 test-parse-mu-stmt: + 5340 # . prologue + 5341 55/push-ebp + 5342 89/<- %ebp 4/r32/esp + 5343 # setup + 5344 (clear-stream _test-input-stream) + 5345 (write _test-input-stream "increment n\n") + 5346 # var vars/ecx: (stack (addr var) 4) + 5347 81 5/subop/subtract %esp 0x10/imm32 + 5348 68/push 0x10/imm32/length + 5349 68/push 0/imm32/top + 5350 89/<- %ecx 4/r32/esp + 5351 (clear-stack %ecx) + 5352 # var v/edx: var + 5353 81 5/subop/subtract %esp 0x14/imm32 # Var-size + 5354 89/<- %edx 4/r32/esp + 5355 (zero-out %edx 0x14) # Var-size + 5356 # v->name = "n" + 5357 c7 0/subop/copy *edx "n"/imm32 # Var-name + 5358 # + 5359 (push %ecx %edx) + 5360 # convert + 5361 (parse-mu-stmt _test-input-stream %ecx) # => eax + 5362 # check result + 5363 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 + 5364 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation + 5365 # edx: (handle list var) = result->inouts + 5366 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts + 5367 # ebx: (handle var) = result->inouts->value + 5368 8b/-> *edx 3/r32/ebx # Stmt-var-value + 5369 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name + 5370 # . epilogue + 5371 89/<- %esp 5/r32/ebp + 5372 5d/pop-to-ebp + 5373 c3/return + 5374 + 5375 test-parse-mu-stmt-with-comma: + 5376 # . prologue + 5377 55/push-ebp + 5378 89/<- %ebp 4/r32/esp + 5379 # setup + 5380 (clear-stream _test-input-stream) + 5381 (write _test-input-stream "copy-to n, 3\n") + 5382 # var vars/ecx: (stack (addr var) 4) + 5383 81 5/subop/subtract %esp 0x10/imm32 + 5384 68/push 0x10/imm32/length + 5385 68/push 0/imm32/top + 5386 89/<- %ecx 4/r32/esp + 5387 (clear-stack %ecx) + 5388 # var v/edx: var + 5389 81 5/subop/subtract %esp 0x14/imm32 # Var-size + 5390 89/<- %edx 4/r32/esp + 5391 (zero-out %edx 0x14) # Var-size + 5392 # v->name = "n" + 5393 c7 0/subop/copy *edx "n"/imm32 # Var-name + 5394 # + 5395 (push %ecx %edx) + 5396 # convert + 5397 (parse-mu-stmt _test-input-stream %ecx) # => eax + 5398 # check result + 5399 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 + 5400 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation + 5401 # edx: (handle list var) = result->inouts + 5402 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts + 5403 # ebx: (handle var) = result->inouts->value + 5404 8b/-> *edx 3/r32/ebx # Stmt-var-value + 5405 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name + 5406 # . epilogue + 5407 89/<- %esp 5/r32/ebp + 5408 5d/pop-to-ebp + 5409 c3/return + 5410 + 5411 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) + 5412 # . prologue + 5413 55/push-ebp + 5414 89/<- %ebp 4/r32/esp + 5415 # . save registers + 5416 51/push-ecx + 5417 # + 5418 (allocate *(ebp+8) *Function-size) # => eax + 5419 8b/-> *(ebp+0xc) 1/r32/ecx + 5420 89/<- *eax 1/r32/ecx # Function-name + 5421 8b/-> *(ebp+0x10) 1/r32/ecx + 5422 89/<- *(eax+4) 1/r32/ecx # Function-subx-name + 5423 8b/-> *(ebp+0x14) 1/r32/ecx + 5424 89/<- *(eax+8) 1/r32/ecx # Function-inouts + 5425 8b/-> *(ebp+0x18) 1/r32/ecx + 5426 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs + 5427 8b/-> *(ebp+0x1c) 1/r32/ecx + 5428 89/<- *(eax+0x10) 1/r32/ecx # Function-body + 5429 8b/-> *(ebp+0x20) 1/r32/ecx + 5430 89/<- *(eax+0x14) 1/r32/ecx # Function-next + 5431 $new-function:end: + 5432 # . restore registers + 5433 59/pop-to-ecx + 5434 # . epilogue + 5435 89/<- %esp 5/r32/ebp + 5436 5d/pop-to-ebp + 5437 c3/return + 5438 + 5439 new-var: # ad: (addr allocation-descriptor), name: (addr array byte) -> result/eax: (handle var) + 5440 # . prologue + 5441 55/push-ebp + 5442 89/<- %ebp 4/r32/esp + 5443 # . save registers + 5444 51/push-ecx + 5445 # + 5446 (allocate *(ebp+8) *Var-size) # => eax + 5447 (zero-out %eax *Var-size) + 5448 8b/-> *(ebp+0xc) 1/r32/ecx + 5449 89/<- *eax 1/r32/ecx # Var-name + 5450 $new-var:end: + 5451 # . restore registers + 5452 59/pop-to-ecx + 5453 # . epilogue + 5454 89/<- %esp 5/r32/ebp + 5455 5d/pop-to-ebp + 5456 c3/return + 5457 + 5458 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5459 # . prologue + 5460 55/push-ebp + 5461 89/<- %ebp 4/r32/esp + 5462 # . save registers + 5463 51/push-ecx + 5464 # if (!is-hex-int?(name)) abort + 5465 (is-hex-int? *(ebp+0xc)) # => eax + 5466 3d/compare-eax-and 0/imm32/false + 5467 0f 84/jump-if-= $new-literal-integer:abort/disp32 + 5468 # var type/ecx: (handle tree type-id) = new type() + 5469 (allocate *(ebp+8) *Tree-size) # => eax + 5470 (zero-out %eax *Tree-size) # default type is 'literal' + 5471 89/<- %ecx 0/r32/eax + 5472 # result = new var(s) + 5473 (new-var-from-slice *(ebp+8) *(ebp+0xc)) # => eax + 5474 89/<- *(eax+4) 1/r32/ecx + 5475 $new-literal-integer:end: + 5476 # . restore registers + 5477 59/pop-to-ecx + 5478 # . epilogue + 5479 89/<- %esp 5/r32/ebp + 5480 5d/pop-to-ebp + 5481 c3/return + 5482 + 5483 $new-literal-integer:abort: + 5484 (write-buffered Stderr "variable cannot begin with a digit '") + 5485 (write-slice-buffered Stderr *(ebp+0xc)) + 5486 (write-buffered Stderr "'\n") + 5487 (flush Stderr) + 5488 # . syscall(exit, 1) + 5489 bb/copy-to-ebx 1/imm32 + 5490 b8/copy-to-eax 1/imm32/exit + 5491 cd/syscall 0x80/imm8 + 5492 # never gets here + 5493 + 5494 new-literal: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5495 # . prologue + 5496 55/push-ebp + 5497 89/<- %ebp 4/r32/esp + 5498 # . save registers + 5499 51/push-ecx + 5500 52/push-edx + 5501 # var s/ecx: (addr array byte) + 5502 (slice-to-string Heap *(ebp+0xc)) # => eax + 5503 89/<- %ecx 0/r32/eax + 5504 # type = new type() + 5505 (allocate *(ebp+8) *Tree-size) # => eax + 5506 (zero-out %eax *Tree-size) # default type is 'literal' + 5507 89/<- %edx 0/r32/eax + 5508 # eax = result + 5509 (new-var *(ebp+8) %ecx) # => eax + 5510 # result->type = type + 5511 89/<- *(eax+4) 2/r32/edx # Var-type + 5512 $new-literal:end: + 5513 # . restore registers + 5514 5a/pop-to-edx + 5515 59/pop-to-ecx + 5516 # . epilogue + 5517 89/<- %esp 5/r32/ebp + 5518 5d/pop-to-ebp + 5519 c3/return + 5520 + 5521 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) + 5522 # . prologue + 5523 55/push-ebp + 5524 89/<- %ebp 4/r32/esp + 5525 # . save registers + 5526 51/push-ecx + 5527 # result = new-var(slice-to-string(name)) + 5528 (slice-to-string Heap *(ebp+0xc)) # => eax + 5529 (new-var *(ebp+8) %eax) + 5530 $new-var-from-slice:end: + 5531 # . restore registers + 5532 59/pop-to-ecx + 5533 # . epilogue + 5534 89/<- %esp 5/r32/ebp + 5535 5d/pop-to-ebp + 5536 c3/return + 5537 + 5538 new-block: # ad: (addr allocation-descriptor), data: (handle list stmt) -> result/eax: (handle stmt) + 5539 # . prologue + 5540 55/push-ebp + 5541 89/<- %ebp 4/r32/esp + 5542 # . save registers + 5543 51/push-ecx + 5544 # + 5545 (allocate *(ebp+8) *Stmt-size) # => eax + 5546 (zero-out %eax *Stmt-size) + 5547 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag + 5548 8b/-> *(ebp+0xc) 1/r32/ecx + 5549 89/<- *(eax+4) 1/r32/ecx # Block-stmts + 5550 $new-block:end: + 5551 # . restore registers + 5552 59/pop-to-ecx + 5553 # . epilogue + 5554 89/<- %esp 5/r32/ebp + 5555 5d/pop-to-ebp + 5556 c3/return + 5557 + 5558 new-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) + 5559 # . prologue + 5560 55/push-ebp + 5561 89/<- %ebp 4/r32/esp + 5562 # . save registers + 5563 51/push-ecx + 5564 # + 5565 (allocate *(ebp+8) *Stmt-size) # => eax + 5566 (zero-out %eax *Stmt-size) + 5567 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag + 5568 # result->var = var + 5569 8b/-> *(ebp+0xc) 1/r32/ecx + 5570 89/<- *(eax+4) 1/r32/ecx # Vardef-var + 5571 $new-var-def:end: + 5572 # . restore registers + 5573 59/pop-to-ecx + 5574 # . epilogue + 5575 89/<- %esp 5/r32/ebp + 5576 5d/pop-to-ebp + 5577 c3/return + 5578 + 5579 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle stmt) + 5580 # . prologue + 5581 55/push-ebp + 5582 89/<- %ebp 4/r32/esp + 5583 # . save registers + 5584 51/push-ecx + 5585 57/push-edi + 5586 # ecx = var + 5587 8b/-> *(ebp+0xc) 1/r32/ecx + 5588 # edi = result + 5589 (allocate *(ebp+8) *Stmt-size) # => eax + 5590 89/<- %edi 0/r32/eax + 5591 (zero-out %edi *Stmt-size) + 5592 # set tag + 5593 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag + 5594 # set output + 5595 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax + 5596 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs + 5597 $new-reg-var-def:end: + 5598 89/<- %eax 7/r32/edi + 5599 # . restore registers + 5600 5f/pop-to-edi + 5601 59/pop-to-ecx + 5602 # . epilogue + 5603 89/<- %esp 5/r32/ebp + 5604 5d/pop-to-ebp + 5605 c3/return + 5606 + 5607 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) + 5608 # . prologue + 5609 55/push-ebp + 5610 89/<- %ebp 4/r32/esp + 5611 # . save registers + 5612 51/push-ecx + 5613 # + 5614 (allocate *(ebp+8) *List-size) # => eax + 5615 (zero-out %eax *List-size) + 5616 8b/-> *(ebp+0xc) 1/r32/ecx + 5617 89/<- *eax 1/r32/ecx # List-value + 5618 # if (list == null) return result + 5619 81 7/subop/compare *(ebp+0x10) 0/imm32 + 5620 74/jump-if-= $append-list:end/disp8 + 5621 # otherwise append + 5622 # var curr/ecx = list + 5623 8b/-> *(ebp+0x10) 1/r32/ecx + 5624 # while (curr->next != null) curr = curr->next + 5625 { + 5626 81 7/subop/compare *(ecx+4) 0/imm32 # List-next + 5627 74/jump-if-= break/disp8 + 5628 # curr = curr->next + 5629 8b/-> *(ecx+4) 1/r32/ecx + 5630 eb/jump loop/disp8 + 5631 } + 5632 # curr->next = result + 5633 89/<- *(ecx+4) 0/r32/eax + 5634 # return list + 5635 8b/-> *(ebp+0x10) 0/r32/eax + 5636 $append-list:end: + 5637 # . restore registers + 5638 59/pop-to-ecx + 5639 # . epilogue + 5640 89/<- %esp 5/r32/ebp + 5641 5d/pop-to-ebp + 5642 c3/return + 5643 + 5644 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) + 5645 # . prologue + 5646 55/push-ebp + 5647 89/<- %ebp 4/r32/esp + 5648 # . save registers + 5649 51/push-ecx + 5650 # + 5651 (allocate *(ebp+8) *Stmt-var-size) # => eax + 5652 (zero-out %eax *Stmt-var-size) + 5653 8b/-> *(ebp+0xc) 1/r32/ecx + 5654 89/<- *eax 1/r32/ecx # Stmt-var-value + 5655 8b/-> *(ebp+0x14) 1/r32/ecx + 5656 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref + 5657 # if (list == null) return result + 5658 81 7/subop/compare *(ebp+0x10) 0/imm32 + 5659 74/jump-if-= $append-stmt-var:end/disp8 + 5660 # otherwise append + 5661 # var curr/ecx: (handle stmt-var) = vars + 5662 8b/-> *(ebp+0x10) 1/r32/ecx + 5663 # while (curr->next != null) curr = curr->next + 5664 { + 5665 81 7/subop/compare *(ecx+4) 0/imm32 # List-next + 5666 74/jump-if-= break/disp8 + 5667 # curr = curr->next + 5668 8b/-> *(ecx+4) 1/r32/ecx + 5669 eb/jump loop/disp8 + 5670 } + 5671 # curr->next = result + 5672 89/<- *(ecx+4) 0/r32/eax + 5673 # return vars + 5674 8b/-> *(ebp+0x10) 0/r32/eax + 5675 $append-stmt-var:end: + 5676 # . restore registers + 5677 59/pop-to-ecx + 5678 # . epilogue + 5679 89/<- %esp 5/r32/ebp + 5680 5d/pop-to-ebp + 5681 c3/return + 5682 + 5683 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) + 5684 # . prologue + 5685 55/push-ebp + 5686 89/<- %ebp 4/r32/esp + 5687 # . save registers + 5688 56/push-esi + 5689 # esi = block + 5690 8b/-> *(ebp+0xc) 6/r32/esi + 5691 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-stmts + 5692 89/<- *(esi+4) 0/r32/eax # Block-stmts + 5693 $append-to-block:end: + 5694 # . restore registers + 5695 5e/pop-to-esi + 5696 # . epilogue + 5697 89/<- %esp 5/r32/ebp + 5698 5d/pop-to-ebp + 5699 c3/return + 5700 + 5701 ## Parsing types + 5702 # We need to create metadata on user-defined types, and we need to use this + 5703 # metadata as we parse instructions. + 5704 # However, we also want to allow types to be used before their definitions. + 5705 # This means we can't ever assume any type data structures exist. + 5706 + 5707 lookup-or-create-constant: # container: (handle stmt-var), field-name: (addr slice) -> result/eax: (handle var) + 5708 # . prologue + 5709 55/push-ebp + 5710 89/<- %ebp 4/r32/esp + 5711 # . save registers + 5712 56/push-esi + 5713 # var container-type/esi: type-id + 5714 (container-type *(ebp+8)) # => eax + 5715 #? (write-buffered Stderr "lookup-or-create-constant: container type-id: ") + 5716 #? (print-int32-buffered Stderr %eax) + 5717 #? (write-buffered Stderr Newline) + 5718 #? (flush Stderr) + 5719 89/<- %esi 0/r32/eax + 5720 # var typeinfo/eax: (addr typeinfo) + 5721 (find-or-create-typeinfo %esi) # => eax + 5722 #? (write-buffered Stderr "lookup-or-create-constant: typeinfo: ") + 5723 #? (print-int32-buffered Stderr %eax) + 5724 #? (write-buffered Stderr Newline) + 5725 #? (flush Stderr) + 5726 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) + 5727 (find-or-create-typeinfo-output-var %eax *(ebp+0xc)) # => eax + 5728 $lookup-or-create-constant:end: + 5729 # . restore registers + 5730 5e/pop-to-esi + 5731 # . epilogue + 5732 89/<- %esp 5/r32/ebp + 5733 5d/pop-to-ebp + 5734 c3/return + 5735 + 5736 # if addr var: + 5737 # container->var->type->right->left->value + 5738 # otherwise + 5739 # container->var->type->value + 5740 container-type: # container: (handle stmt-var) -> result/eax: type-id + 5741 # . prologue + 5742 55/push-ebp + 5743 89/<- %ebp 4/r32/esp + 5744 # + 5745 8b/-> *(ebp+8) 0/r32/eax + 5746 8b/-> *eax 0/r32/eax # Stmt-var-value + 5747 8b/-> *(eax+4) 0/r32/eax # Var-type + 5748 { + 5749 81 7/subop/compare *(eax+4) 0/imm32 + 5750 74/jump-if-= break/disp8 + 5751 8b/-> *(eax+4) 0/r32/eax # Tree-right + 5752 8b/-> *eax 0/r32/eax # Tree-left + 5753 } + 5754 8b/-> *eax 0/r32/eax # Atom-value + 5755 $container-type:end: + 5756 # . epilogue + 5757 89/<- %esp 5/r32/ebp + 5758 5d/pop-to-ebp + 5759 c3/return + 5760 + 5761 find-or-create-typeinfo: # t: type-id -> result/eax: (handle typeinfo) + 5762 # . prologue + 5763 55/push-ebp + 5764 89/<- %ebp 4/r32/esp + 5765 # . save registers + 5766 51/push-ecx + 5767 # eax = find-typeinfo(t) + 5768 (find-typeinfo *(ebp+8)) # => eax + 5769 { + 5770 # if (curr != 0) break + 5771 3d/compare-eax-and 0/imm32 + 5772 75/jump-if-!= break/disp8 + 5773 $find-or-create-typeinfo:create: + 5774 (allocate Heap *Typeinfo-size) # => eax + 5775 (zero-out %eax *Typeinfo-size) + 5776 # result->id = t + 5777 8b/-> *(ebp+8) 1/r32/ecx + 5778 89/<- *eax 1/r32/ecx # Typeinfo-id + 5779 # result->fields = new table + 5780 # . ecx = new table + 5781 50/push-eax + 5782 (new-stream Heap 0x40 *Typeinfo-fields-row-size) # => eax + 5783 89/<- %ecx 0/r32/eax + 5784 58/pop-to-eax + 5785 # . result->fields = ecx + 5786 89/<- *(eax+4) 1/r32/ecx # Typeinfo-fields + 5787 # result->next = Program->types + 5788 8b/-> *_Program-types 1/r32/ecx + 5789 89/<- *(eax+0xc) 1/r32/ecx # Typeinfo-next + 5790 # Program->types = result + 5791 89/<- *_Program-types 0/r32/eax + 5792 } + 5793 $find-or-create-typeinfo:end: + 5794 # . restore registers + 5795 59/pop-to-ecx + 5796 # . epilogue + 5797 89/<- %esp 5/r32/ebp + 5798 5d/pop-to-ebp + 5799 c3/return + 5800 + 5801 find-typeinfo: # t: type-id -> result/eax: (handle typeinfo) + 5802 # . prologue + 5803 55/push-ebp + 5804 89/<- %ebp 4/r32/esp + 5805 # . save registers + 5806 51/push-ecx + 5807 # ecx = t + 5808 8b/-> *(ebp+8) 1/r32/ecx + 5809 # var curr/eax: (handle typeinfo) = Program->types + 5810 8b/-> *_Program-types 0/r32/eax + 5811 { + 5812 # if (curr == 0) break + 5813 3d/compare-eax-and 0/imm32 + 5814 74/jump-if-= break/disp8 + 5815 # if (curr->id == t) return curr + 5816 39/compare *eax 1/r32/ecx # Typeinfo-id + 5817 0f 84/jump-if-= $find-or-create-typeinfo:end/disp32 + 5818 # curr = curr->next + 5819 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-next + 5820 # + 5821 eb/jump loop/disp8 + 5822 } + 5823 $find-typeinfo:end: + 5824 # . restore registers + 5825 59/pop-to-ecx + 5826 # . epilogue + 5827 89/<- %esp 5/r32/ebp + 5828 5d/pop-to-ebp + 5829 c3/return + 5830 + 5831 find-or-create-typeinfo-output-var: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle var) + 5832 # . prologue + 5833 55/push-ebp + 5834 89/<- %ebp 4/r32/esp + 5835 # . save registers + 5836 51/push-ecx + 5837 56/push-esi + 5838 # esi = find-or-create-typeinfo-fields(T, f) + 5839 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc)) # => eax + 5840 89/<- %esi 0/r32/eax + 5841 # if output var doesn't exist, create it + 5842 { + 5843 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-entry-output-var + 5844 75/jump-if-!= break/disp8 + 5845 # var type/eax: (handle tree type-id) = new var("dummy name", constant type, -1 offset) + 5846 (allocate Heap *Tree-size) # => eax + 5847 c7 0/subop/copy *eax 6/imm32/constant # Atom-value + 5848 c7 0/subop/copy *(eax+4) 0/imm32 # Tree-right + 5849 89/<- %ecx 0/r32/eax + 5850 # eax = result + 5851 (new-var Heap "field") # => eax + 5852 # result->type = type + 5853 89/<- *(eax+4) 1/r32/ecx # Var-type + 5854 # result->offset isn't filled out yet + 5855 c7 0/subop/copy *(eax+0xc) -1/imm32/uninitialized # Var-offset + 5856 # save result as output var + 5857 89/<- *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 5858 } + 5859 # return the output var + 5860 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 5861 $find-or-create-typeinfo-output-var:end: + 5862 # . restore registers + 5863 5e/pop-to-esi + 5864 59/pop-to-ecx + 5865 # . epilogue + 5866 89/<- %esp 5/r32/ebp + 5867 5d/pop-to-ebp + 5868 c3/return + 5869 + 5870 find-or-create-typeinfo-fields: # T: (handle typeinfo), f: (addr slice) -> result/eax: (handle typeinfo-entry) + 5871 # . prologue + 5872 55/push-ebp + 5873 89/<- %ebp 4/r32/esp + 5874 # . save registers + 5875 56/push-esi + 5876 # esi = T->fields + 5877 8b/-> *(ebp+8) 6/r32/esi + 5878 8b/-> *(esi+4) 6/r32/esi # Typeinfo-fields + 5879 # esi = get-or-insert(T->fields, f) + 5880 (leaky-get-or-insert-slice %esi *(ebp+0xc) *Typeinfo-fields-row-size) # => eax + 5881 89/<- %esi 0/r32/eax + 5882 # if typeinfo-entry doesn't exist, allocate it + 5883 { + 5884 81 7/subop/compare *esi 0/imm32 # output var + 5885 75/jump-if-!= break/disp8 + 5886 (allocate Heap *Typeinfo-entry-size) # => eax + 5887 (zero-out %eax *Typeinfo-entry-size) + 5888 89/<- *esi 0/r32/eax + 5889 } + 5890 # eax = T->fields[f]->entry + 5891 8b/-> *esi 0/r32/eax + 5892 $find-or-create-typeinfo-fields:end: + 5893 # . restore registers + 5894 5e/pop-to-esi + 5895 # . epilogue + 5896 89/<- %esp 5/r32/ebp + 5897 5d/pop-to-ebp + 5898 c3/return + 5899 + 5900 populate-mu-type: # in: (addr stream byte), t: (handle typeinfo) + 5901 # pseudocode: + 5902 # var line: (stream byte 512) + 5903 # curr-index = 0 + 5904 # while true + 5905 # clear-stream(line) + 5906 # read-line-buffered(in, line) + 5907 # if line->write == 0 + 5908 # abort + 5909 # word-slice = next-mu-token(line) + 5910 # if slice-empty?(word-slice) # end of line + 5911 # continue + 5912 # if slice-equal?(word-slice, "}") + 5913 # break + 5914 # var v: (handle var) = parse-var-with-type(word-slice, line) + 5915 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) + 5916 # TODO: ensure that r->first is null + 5917 # r->index = curr-index + 5918 # curr-index++ + 5919 # r->input-var = v + 5920 # if r->output-var == 0 + 5921 # r->output-var = new literal + 5922 # TODO: ensure nothing else in line + 5923 # t->total-size-in-bytes = -2 (not yet initialized) + 5924 # + 5925 # . prologue + 5926 55/push-ebp + 5927 89/<- %ebp 4/r32/esp + 5928 # var curr-index: int at *(ebp-4) + 5929 68/push 0/imm32 + 5930 # . save registers + 5931 50/push-eax + 5932 51/push-ecx + 5933 52/push-edx + 5934 53/push-ebx + 5935 56/push-esi + 5936 57/push-edi + 5937 # edi = t + 5938 8b/-> *(ebp+0xc) 7/r32/edi + 5939 # var line/ecx: (stream byte 512) + 5940 81 5/subop/subtract %esp 0x200/imm32 + 5941 68/push 0x200/imm32/length + 5942 68/push 0/imm32/read + 5943 68/push 0/imm32/write + 5944 89/<- %ecx 4/r32/esp + 5945 # var word-slice/edx: slice + 5946 68/push 0/imm32/end + 5947 68/push 0/imm32/start + 5948 89/<- %edx 4/r32/esp + 5949 { + 5950 $populate-mu-type:line-loop: + 5951 (clear-stream %ecx) + 5952 (read-line-buffered *(ebp+8) %ecx) + 5953 # if (line->write == 0) abort + 5954 81 7/subop/compare *ecx 0/imm32 + 5955 0f 84/jump-if-= $populate-mu-type:abort/disp32 + 5956 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ + 5962 (next-mu-token %ecx %edx) + 5963 # if slice-empty?(word-slice) continue + 5964 (slice-empty? %edx) # => eax + 5965 3d/compare-eax-and 0/imm32 + 5966 0f 85/jump-if-!= loop/disp32 + 5967 # if slice-equal?(word-slice, "}") break + 5968 (slice-equal? %edx "}") + 5969 3d/compare-eax-and 0/imm32 + 5970 0f 85/jump-if-!= break/disp32 + 5971 $populate-mu-type:parse-element: + 5972 # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line) + 5973 (parse-var-with-type %edx %ecx) # => eax + 5974 89/<- %esi 0/r32/eax + 5975 $populate-mu-type:create-typeinfo-fields: + 5976 # var r/ebx: (handle typeinfo-entry) + 5977 (find-or-create-typeinfo-fields %edi %edx) # => eax + 5978 89/<- %ebx 0/r32/eax + 5979 #? (write-buffered Stderr "var ") + 5980 #? (write-buffered Stderr *esi) # Var-name + 5981 #? (write-buffered Stderr " is at index ") + 5982 #? (print-int32-buffered Stderr *(ebp-4)) + 5983 #? (write-buffered Stderr Newline) + 5984 #? (flush Stderr) + 5985 # r->index = curr-index + 5986 8b/-> *(ebp-4) 0/r32/eax + 5987 89/<- *(ebx+4) 0/r32/eax # Typeinfo-entry-index + 5988 # ++curr-index + 5989 ff 0/subop/increment *(ebp-4) + 5990 $populate-mu-type:set-input-type: + 5991 # r->input-var = v + 5992 89/<- *ebx 6/r32/esi # Typeinfo-entry-input-var + 5993 { + 5994 $populate-mu-type:create-output-type: + 5995 # if (r->output-var == 0) create a new var with some placeholder data + 5996 81 7/subop/compare *(ebx+8) 0/imm32 # Typeinfo-entry-output-var + 5997 75/jump-if-!= break/disp8 + 5998 (new-literal Heap %edx) # => eax + 5999 89/<- *(ebx+8) 0/r32/eax # Typeinfo-entry-output-var + 6000 } + 6001 e9/jump loop/disp32 + 6002 } + 6003 $populate-mu-type:invalidate-total-size-in-bytes: + 6004 # Offsets and total size may not be accurate here since we may not yet + 6005 # have encountered the element types. + 6006 # We'll recompute them separately after parsing the entire program. + 6007 c7 0/subop/copy *(edi+8) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes + 6008 $populate-mu-type:end: + 6009 # . reclaim locals + 6010 81 0/subop/add %esp 0x214/imm32 + 6011 # . restore registers + 6012 5f/pop-to-edi + 6013 5e/pop-to-esi + 6014 5b/pop-to-ebx + 6015 5a/pop-to-edx + 6016 59/pop-to-ecx + 6017 58/pop-to-eax + 6018 # reclaim curr-index + 6019 81 0/subop/add %esp 4/imm32 6020 # . epilogue 6021 89/<- %esp 5/r32/ebp 6022 5d/pop-to-ebp 6023 c3/return 6024 - 6025 ####################################################### - 6026 # Compute type sizes - 6027 ####################################################### - 6028 - 6029 # Compute the sizes of all user-defined types. - 6030 # We'll need the sizes of their elements, which may be other user-defined - 6031 # types, which we will compute as needed. - 6032 - 6033 # Initially, all user-defined types have their sizes set to -2 (invalid) - 6034 populate-mu-type-sizes: - 6035 # . prologue - 6036 55/push-ebp - 6037 89/<- %ebp 4/r32/esp - 6038 # . save registers - 6039 51/push-ecx - 6040 $populate-mu-type-sizes:total-sizes: - 6041 # var curr/ecx: (handle typeinfo) = *Program->types - 6042 8b/-> *_Program-types 1/r32/ecx - 6043 { - 6044 # if (curr == null) break - 6045 81 7/subop/compare %ecx 0/imm32 - 6046 74/jump-if-= break/disp8 - 6047 (populate-mu-type-sizes-in-type %ecx) - 6048 # curr = curr->next - 6049 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next - 6050 eb/jump loop/disp8 - 6051 } - 6052 $populate-mu-type-sizes:offsets: - 6053 # var curr/ecx: (handle typeinfo) = *Program->types - 6054 8b/-> *_Program-types 1/r32/ecx - 6055 { - 6056 # if (curr == null) break - 6057 81 7/subop/compare %ecx 0/imm32 - 6058 74/jump-if-= break/disp8 - 6059 (populate-mu-type-offsets %ecx) - 6060 # curr = curr->next - 6061 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next - 6062 eb/jump loop/disp8 - 6063 } - 6064 $populate-mu-type-sizes:end: - 6065 # . restore registers - 6066 59/pop-to-ecx - 6067 # . epilogue - 6068 89/<- %esp 5/r32/ebp - 6069 5d/pop-to-ebp - 6070 c3/return - 6071 - 6072 # compute sizes of all fields, recursing as necessary - 6073 # sum up all their sizes to arrive at total size - 6074 # fields may be out of order, but that doesn't affect the answer - 6075 populate-mu-type-sizes-in-type: # T: (handle typeinfo) - 6076 # . prologue - 6077 55/push-ebp - 6078 89/<- %ebp 4/r32/esp - 6079 # . save registers - 6080 50/push-eax - 6081 51/push-ecx - 6082 52/push-edx - 6083 56/push-esi - 6084 57/push-edi - 6085 # esi = T - 6086 8b/-> *(ebp+8) 6/r32/esi - 6087 # if T is already computed, return - 6088 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-total-size-in-bytes - 6089 7d/jump-if->= $populate-mu-type-sizes-in-type:end/disp8 - 6090 # if T is being computed, abort - 6091 81 7/subop/compare *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes - 6092 74/jump-if-= $populate-mu-type-sizes-in-type:abort/disp8 - 6093 # tag T (-2 to -1) to avoid infinite recursion - 6094 c7 0/subop/copy *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes - 6095 # var total-size/edi: int = 0 - 6096 bf/copy-to-edi 0/imm32 - 6097 # - for every field, if it's a user-defined type, compute its size - 6098 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields - 6099 8b/-> *(esi+4) 1/r32/ecx # Typeinfo-fields - 6100 # var table-size/edx: int = table->write - 6101 8b/-> *ecx 2/r32/edx # stream-write - 6102 # var curr/ecx: (addr table_row) = table->data - 6103 8d/copy-address *(ecx+0xc) 1/r32/ecx - 6104 # var max/edx: (addr table_row) = table->data + table->write - 6105 8d/copy-address *(ecx+edx) 2/r32/edx - 6106 { - 6107 $populate-mu-type-sizes-in-type:loop: - 6108 # if (curr >= max) break - 6109 39/compare %ecx 2/r32/edx - 6110 73/jump-if-addr>= break/disp8 - 6111 # var t/eax: (handle typeinfo-entry) = curr->value - 6112 8b/-> *(ecx+4) 0/r32/eax - 6113 # compute size of t - 6114 (compute-size-of-var *eax) # Typeinfo-entry-input-var => eax - 6115 # result += eax - 6116 01/add-to %edi 0/r32/eax - 6117 # curr += row-size - 6118 81 0/subop/add %ecx 8/imm32 - 6119 # - 6120 eb/jump loop/disp8 - 6121 } - 6122 # - save result - 6123 89/<- *(esi+8) 7/r32/edi # Typeinfo-total-size-in-bytes - 6124 $populate-mu-type-sizes-in-type:end: - 6125 # . restore registers - 6126 5f/pop-to-edi - 6127 5e/pop-to-esi - 6128 5a/pop-to-edx - 6129 59/pop-to-ecx - 6130 58/pop-to-eax - 6131 # . epilogue - 6132 89/<- %esp 5/r32/ebp - 6133 5d/pop-to-ebp - 6134 c3/return - 6135 - 6136 $populate-mu-type-sizes-in-type:abort: - 6137 (write-buffered Stderr "cycle in type definitions\n") - 6138 (flush Stderr) - 6139 # . syscall(exit, 1) - 6140 bb/copy-to-ebx 1/imm32 - 6141 b8/copy-to-eax 1/imm32/exit - 6142 cd/syscall 0x80/imm8 - 6143 # never gets here - 6144 - 6145 # Analogous to size-of, except we need to compute what size-of can just read - 6146 # off the right data structures. - 6147 compute-size-of-var: # in: (handle var) -> result/eax: int - 6148 # . prologue - 6149 55/push-ebp - 6150 89/<- %ebp 4/r32/esp - 6151 # . push registers - 6152 51/push-ecx - 6153 # var t/ecx: (handle tree type-id) = v->type - 6154 8b/-> *(ebp+8) 1/r32/ecx - 6155 8b/-> *(ecx+4) 1/r32/ecx # Var-type - 6156 # if (t->left >= *Max-type-id) t = t->left - 6157 { - 6158 8b/-> *Max-type-id 0/r32/eax - 6159 39/compare *ecx 0/r32/eax # Tree-left - 6160 72/jump-if-addr< break/disp8 - 6161 8b/-> *ecx 1/r32/ecx # Tree-left - 6162 } - 6163 (compute-size-of-type-id *ecx) # Atom-left => eax - 6164 $compute-size-of-var:end: - 6165 # . restore registers - 6166 59/pop-to-ecx - 6167 # . epilogue - 6168 89/<- %esp 5/r32/ebp - 6169 5d/pop-to-ebp - 6170 c3/return - 6171 - 6172 compute-size-of-type-id: # t: type-id -> result/eax: int - 6173 # . prologue - 6174 55/push-ebp - 6175 89/<- %ebp 4/r32/esp - 6176 # - 6177 8b/-> *(ebp+8) 0/r32/eax - 6178 # if v is a literal, return 0 - 6179 3d/compare-eax-and 0/imm32 - 6180 74/jump-if-= $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int - 6181 # if v has a user-defined type, compute its size - 6182 # TODO: support non-atom type - 6183 (find-typeinfo %eax) # => eax - 6184 { - 6185 3d/compare-eax-and 0/imm32 - 6186 74/jump-if-= break/disp8 - 6187 $compute-size-of-type-id:user-defined: - 6188 (populate-mu-type-sizes %eax) - 6189 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes - 6190 eb/jump $compute-size-of-type-id:end/disp8 - 6191 } - 6192 # otherwise return the word size - 6193 b8/copy-to-eax 4/imm32 - 6194 $compute-size-of-type-id:end: - 6195 # . epilogue - 6196 89/<- %esp 5/r32/ebp - 6197 5d/pop-to-ebp - 6198 c3/return - 6199 - 6200 # at this point we have total sizes for all user-defined types - 6201 # compute offsets for each element - 6202 # complication: fields may be out of order - 6203 populate-mu-type-offsets: # in: (handle typeinfo) - 6204 # . prologue - 6205 55/push-ebp - 6206 89/<- %ebp 4/r32/esp - 6207 # . save registers - 6208 50/push-eax - 6209 51/push-ecx - 6210 52/push-edx - 6211 53/push-ebx - 6212 56/push-esi - 6213 57/push-edi - 6214 # var curr-offset/edi: int = 0 - 6215 bf/copy-to-edi 0/imm32 - 6216 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields - 6217 8b/-> *(ebp+8) 1/r32/ecx - 6218 8b/-> *(ecx+4) 1/r32/ecx # Typeinfo-fields - 6219 # var num-elems/edx: int = table->write / 8 - 6220 8b/-> *ecx 2/r32/edx # stream-write - 6221 c1 5/subop/shift-right-logical %edx 3/imm8 - 6222 # var i/ebx: int = 0 - 6223 bb/copy-to-ebx 0/imm32 - 6224 { - 6225 $populate-mu-type-offsets:loop: - 6226 39/compare %ebx 2/r32/edx - 6227 7d/jump-if->= break/disp8 - 6228 # var v/esi: (handle typeinfo-entry) - 6229 (locate-typeinfo-entry-with-index %ecx %ebx) # => eax - 6230 89/<- %esi 0/r32/eax - 6231 # v->output-var->offset = curr-offset - 6232 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var - 6233 89/<- *(eax+0xc) 7/r32/edi # Var-offset - 6234 # curr-offset += size-of(v->input-var) - 6235 8b/-> *esi 0/r32/eax # Typeinfo-entry-input-var - 6236 (size-of %eax) # => eax - 6237 01/add-to %edi 0/r32/eax - 6238 # ++i - 6239 43/increment-ebx - 6240 eb/jump loop/disp8 - 6241 } - 6242 $populate-mu-type-offsets:end: - 6243 # . restore registers - 6244 5f/pop-to-edi - 6245 5e/pop-to-esi - 6246 5b/pop-to-ebx - 6247 5a/pop-to-edx - 6248 59/pop-to-ecx - 6249 58/pop-to-eax - 6250 # . epilogue - 6251 89/<- %esp 5/r32/ebp - 6252 5d/pop-to-ebp - 6253 c3/return - 6254 - 6255 locate-typeinfo-entry-with-index: # table: (handle table string_key (handle typeinfo-entry)), idx: int -> result/eax: (handle typeinfo-entry) - 6256 # . prologue - 6257 55/push-ebp - 6258 89/<- %ebp 4/r32/esp - 6259 # . save registers - 6260 51/push-ecx - 6261 52/push-edx - 6262 53/push-ebx - 6263 56/push-esi - 6264 57/push-edi - 6265 # esi = table - 6266 8b/-> *(ebp+8) 6/r32/esi - 6267 # var curr/ecx: (addr string_key) = table->data - 6268 8d/copy-address *(esi+0xc) 1/r32/ecx - 6269 # var max/edx: (addr byte) = &table->data[table->write] - 6270 8b/-> *esi 2/r32/edx - 6271 8d/copy-address *(ecx+edx) 2/r32/edx - 6272 { - 6273 $locate-typeinfo-entry-with-index:loop: - 6274 39/compare %ecx 2/r32/edx - 6275 73/jump-if-addr>= $locate-typeinfo-entry-with-index:abort/disp8 - 6276 # var v/ebx: (handle typeinfo-entry) - 6277 8b/-> *(ecx+4) 3/r32/ebx - 6278 # if (v->index == idx) return v - 6279 8b/-> *(ebx+4) 0/r32/eax # Typeinfo-entry-index - 6280 39/compare *(ebp+0xc) 0/r32/eax - 6281 89/<- %eax 3/r32/ebx - 6282 74/jump-if-= break/disp8 - 6283 # curr += 8 - 6284 81 0/subop/add %ecx 8/imm32 - 6285 eb/jump loop/disp8 - 6286 } - 6287 $locate-typeinfo-entry-with-index:end: - 6288 # . restore registers - 6289 5f/pop-to-edi - 6290 5e/pop-to-esi - 6291 5b/pop-to-ebx - 6292 5a/pop-to-edx - 6293 59/pop-to-ecx - 6294 # . epilogue - 6295 89/<- %esp 5/r32/ebp - 6296 5d/pop-to-ebp - 6297 c3/return - 6298 - 6299 $locate-typeinfo-entry-with-index:abort: - 6300 (write-buffered Stderr "overflowing typeinfo-entry->index ") - 6301 (print-int32-buffered Stderr %ecx) - 6302 (write-buffered Stderr "\n") - 6303 (flush Stderr) - 6304 # . syscall(exit, 1) - 6305 bb/copy-to-ebx 1/imm32 - 6306 b8/copy-to-eax 1/imm32/exit - 6307 cd/syscall 0x80/imm8 - 6308 # never gets here - 6309 - 6310 ####################################################### - 6311 # Type-checking - 6312 ####################################################### - 6313 - 6314 check-mu-types: - 6315 # . prologue - 6316 55/push-ebp - 6317 89/<- %ebp 4/r32/esp - 6318 # - 6319 $check-mu-types:end: - 6320 # . epilogue - 6321 89/<- %esp 5/r32/ebp - 6322 5d/pop-to-ebp - 6323 c3/return - 6324 - 6325 size-of: # v: (handle var) -> result/eax: int - 6326 # . prologue - 6327 55/push-ebp - 6328 89/<- %ebp 4/r32/esp - 6329 # . save registers - 6330 51/push-ecx - 6331 # var t/ecx: (handle tree type-id) = v->type - 6332 8b/-> *(ebp+8) 1/r32/ecx - 6333 8b/-> *(ecx+4) 1/r32/ecx # Var-type - 6334 # if is-mu-array?(t) return size-of-array(t) - 6335 { - 6336 (is-mu-array? %ecx) # => eax - 6337 3d/compare-eax-and 0/imm32/false - 6338 74/jump-if-= break/disp8 - 6339 (size-of-array %ecx) # => eax - 6340 eb/jump $size-of:end/disp8 - 6341 } - 6342 # if (t->left >= *Max-type-id) t = t->left - 6343 { - 6344 8b/-> *Max-type-id 0/r32/eax - 6345 39/compare *ecx 0/r32/eax # Tree-left - 6346 72/jump-if-addr< break/disp8 - 6347 8b/-> *ecx 1/r32/ecx # Tree-left - 6348 } - 6349 (size-of-type-id *ecx) # Atom-left => eax - 6350 $size-of:end: - 6351 # . restore registers - 6352 59/pop-to-ecx - 6353 # . epilogue - 6354 89/<- %esp 5/r32/ebp - 6355 5d/pop-to-ebp - 6356 c3/return - 6357 - 6358 is-mu-array?: # t: (handle tree type-id) -> result/eax: boolean - 6359 # . prologue - 6360 55/push-ebp - 6361 89/<- %ebp 4/r32/esp - 6362 # . save registers - 6363 51/push-ecx - 6364 # ecx = t->left - 6365 8b/-> *(ebp+8) 1/r32/ecx - 6366 8b/-> *ecx 1/r32/ecx # Tree-left - 6367 # if t is an atomic type, return false - 6368 3b/compare 1/r32/ecx *Max-type-id - 6369 b8/copy-to-eax 0/imm32/false - 6370 72/jump-if-addr< $is-mu-array?:end/disp8 - 6371 # return ecx->value == array - 6372 81 7/subop/compare *ecx 3/imm32/array-type-id # Atom-value - 6373 0f 94/set-if-= %al - 6374 81 4/subop/and %eax 0xff/imm32 - 6375 $is-mu-array?:end: - 6376 # . restore registers - 6377 59/pop-to-ecx - 6378 # . epilogue - 6379 89/<- %esp 5/r32/ebp - 6380 5d/pop-to-ebp - 6381 c3/return - 6382 - 6383 size-of-array: # a: (handle tree type-id) -> result/eax: int - 6384 # . prologue - 6385 55/push-ebp - 6386 89/<- %ebp 4/r32/esp - 6387 # . save registers - 6388 51/push-ecx - 6389 52/push-edx - 6390 # - 6391 8b/-> *(ebp+8) 1/r32/ecx - 6392 # TODO: assert that a->left is 'array' - 6393 8b/-> *(ecx+4) 1/r32/ecx # Tree-right - 6394 # var elem-type/edx: type-id = a->right->value - 6395 8b/-> *ecx 2/r32/edx # Atom-value - 6396 8b/-> *edx 2/r32/edx # Atom-value - 6397 # var array-size/ecx: int = a->right->right->left->value - 6398 8b/-> *(ecx+4) 1/r32/ecx # Tree-right - 6399 8b/-> *ecx 1/r32/ecx # Tree-left - 6400 8b/-> *ecx 1/r32/ecx # Atom-value - 6401 # return array-size * size-of(elem-type) - 6402 (size-of-type-id %edx) # => eax - 6403 f7 4/subop/multiply-into-eax %ecx - 6404 05/add-to-eax 4/imm32 # for array length - 6405 $size-of-array:end: - 6406 # . restore registers - 6407 5a/pop-to-edx - 6408 59/pop-to-ecx - 6409 # . epilogue - 6410 89/<- %esp 5/r32/ebp - 6411 5d/pop-to-ebp - 6412 c3/return - 6413 - 6414 size-of-type-id: # t: type-id -> result/eax: int - 6415 # . prologue - 6416 55/push-ebp - 6417 89/<- %ebp 4/r32/esp - 6418 # - 6419 8b/-> *(ebp+8) 0/r32/eax - 6420 # if v is a literal, return 0 - 6421 3d/compare-eax-and 0/imm32 - 6422 74/jump-if-= $size-of-type-id:end/disp8 # eax changes type from type-id to int - 6423 # if v has a user-defined type, return its size - 6424 # TODO: support non-atom type - 6425 (find-typeinfo %eax) # => eax - 6426 { - 6427 3d/compare-eax-and 0/imm32 - 6428 74/jump-if-= break/disp8 - 6429 $size-of-type-id:user-defined: - 6430 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes - 6431 eb/jump $size-of-type-id:end/disp8 - 6432 } - 6433 # otherwise return the word size - 6434 b8/copy-to-eax 4/imm32 - 6435 $size-of-type-id:end: - 6436 # . epilogue - 6437 89/<- %esp 5/r32/ebp - 6438 5d/pop-to-ebp - 6439 c3/return - 6440 - 6441 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean - 6442 # . prologue - 6443 55/push-ebp - 6444 89/<- %ebp 4/r32/esp - 6445 # . save registers - 6446 51/push-ecx - 6447 52/push-edx - 6448 # ecx = a - 6449 8b/-> *(ebp+8) 1/r32/ecx - 6450 # edx = b - 6451 8b/-> *(ebp+0xc) 2/r32/edx - 6452 # if (a == b) return true - 6453 8b/-> %ecx 0/r32/eax # Var-type - 6454 39/compare %edx 0/r32/eax # Var-type - 6455 b8/copy-to-eax 1/imm32/true - 6456 74/jump-if-= $type-equal?:end/disp8 - 6457 # if (a < MAX_TYPE_ID) return false - 6458 81 7/subop/compare %ecx 0x10000/imm32 - 6459 b8/copy-to-eax 0/imm32/false - 6460 72/jump-if-addr< $type-equal?:end/disp8 - 6461 # if (b < MAX_TYPE_ID) return false - 6462 81 7/subop/compare %edx 0x10000/imm32 - 6463 b8/copy-to-eax 0/imm32/false - 6464 72/jump-if-addr< $type-equal?:end/disp8 - 6465 # if (!type-equal?(a->left, b->left)) return false - 6466 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax - 6467 3d/compare-eax-and 0/imm32/false - 6468 74/jump-if-= $type-equal?:end/disp8 - 6469 # return type-equal?(a->right, b->right) - 6470 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax - 6471 $type-equal?:end: - 6472 # . restore registers - 6473 5a/pop-to-edx - 6474 59/pop-to-ecx - 6475 # . epilogue - 6476 89/<- %esp 5/r32/ebp - 6477 5d/pop-to-ebp - 6478 c3/return - 6479 - 6480 ####################################################### - 6481 # Code-generation - 6482 ####################################################### - 6483 - 6484 == data - 6485 - 6486 Curr-block-depth: # (addr int) - 6487 0/imm32 - 6488 Curr-local-stack-offset: # (addr int) - 6489 0/imm32 - 6490 - 6491 == code - 6492 - 6493 emit-subx: # out: (addr buffered-file) - 6494 # . prologue - 6495 55/push-ebp - 6496 89/<- %ebp 4/r32/esp - 6497 # . save registers - 6498 50/push-eax - 6499 51/push-ecx - 6500 57/push-edi - 6501 # edi = out - 6502 8b/-> *(ebp+8) 7/r32/edi - 6503 # var curr/ecx: (handle function) = *Program->functions - 6504 8b/-> *_Program-functions 1/r32/ecx - 6505 { - 6506 # if (curr == null) break - 6507 81 7/subop/compare %ecx 0/imm32 - 6508 0f 84/jump-if-= break/disp32 - 6509 (emit-subx-function %edi %ecx) - 6510 # curr = curr->next - 6511 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next - 6512 e9/jump loop/disp32 - 6513 } - 6514 $emit-subx:end: - 6515 # . restore registers - 6516 5f/pop-to-edi - 6517 59/pop-to-ecx - 6518 58/pop-to-eax - 6519 # . epilogue - 6520 89/<- %esp 5/r32/ebp - 6521 5d/pop-to-ebp - 6522 c3/return - 6523 - 6524 emit-subx-function: # out: (addr buffered-file), f: (handle function) - 6525 # . prologue - 6526 55/push-ebp - 6527 89/<- %ebp 4/r32/esp - 6528 # some preprocessing - 6529 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) - 6530 # . save registers - 6531 50/push-eax - 6532 51/push-ecx - 6533 52/push-edx - 6534 57/push-edi - 6535 # edi = out - 6536 8b/-> *(ebp+8) 7/r32/edi - 6537 # ecx = f - 6538 8b/-> *(ebp+0xc) 1/r32/ecx - 6539 # var vars/edx: (stack (addr var) 256) - 6540 81 5/subop/subtract %esp 0x400/imm32 - 6541 68/push 0x400/imm32/length - 6542 68/push 0/imm32/top - 6543 89/<- %edx 4/r32/esp - 6544 # - 6545 (write-buffered %edi *ecx) - 6546 (write-buffered %edi ":\n") - 6547 # initialize some global state - 6548 c7 0/subop/copy *Curr-block-depth 1/imm32 - 6549 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 - 6550 # - 6551 (emit-subx-prologue %edi) - 6552 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body - 6553 (emit-subx-epilogue %edi) - 6554 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have - 6555 # been cleaned up - 6556 $emit-subx-function:end: - 6557 # . reclaim locals - 6558 81 0/subop/add %esp 408/imm32 - 6559 # . restore registers - 6560 5f/pop-to-edi - 6561 5a/pop-to-edx - 6562 59/pop-to-ecx - 6563 58/pop-to-eax - 6564 # . epilogue - 6565 89/<- %esp 5/r32/ebp - 6566 5d/pop-to-ebp - 6567 c3/return - 6568 - 6569 populate-mu-type-offsets-in-inouts: # f: (handle function) - 6570 # . prologue - 6571 55/push-ebp - 6572 89/<- %ebp 4/r32/esp - 6573 # . save registers - 6574 50/push-eax - 6575 51/push-ecx - 6576 52/push-edx - 6577 53/push-ebx - 6578 57/push-edi - 6579 # var next-offset/edx: int = 8 - 6580 ba/copy-to-edx 8/imm32 - 6581 # var curr/ecx: (handle list var) = f->inouts - 6582 8b/-> *(ebp+8) 1/r32/ecx - 6583 8b/-> *(ecx+8) 1/r32/ecx # Function-inouts - 6584 { - 6585 $populate-mu-type-offsets-in-inouts:loop: - 6586 81 7/subop/compare %ecx 0/imm32 - 6587 74/jump-if-= break/disp8 - 6588 # var v/ebx: (handle var) = curr->value - 6589 8b/-> *ecx 3/r32/ebx # List-value - 6590 # v->offset = next-offset - 6591 89/<- *(ebx+0xc) 2/r32/edx # Var-offset - 6592 # next-offset += size-of(v) - 6593 (size-of %ebx) # => eax - 6594 01/add %edx 0/r32/eax - 6595 # curr = curr->next - 6596 8b/-> *(ecx+4) 1/r32/ecx # List-next - 6597 eb/jump loop/disp8 - 6598 } - 6599 $populate-mu-type-offsets-in-inouts:end: - 6600 # . restore registers - 6601 5f/pop-to-edi - 6602 5b/pop-to-ebx - 6603 5a/pop-to-edx - 6604 59/pop-to-ecx - 6605 58/pop-to-eax - 6606 # . epilogue - 6607 89/<- %esp 5/r32/ebp - 6608 5d/pop-to-ebp - 6609 c3/return - 6610 - 6611 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) - 6612 # . prologue - 6613 55/push-ebp - 6614 89/<- %ebp 4/r32/esp - 6615 # . save registers - 6616 50/push-eax - 6617 51/push-ecx - 6618 52/push-edx - 6619 53/push-ebx - 6620 56/push-esi - 6621 # esi = stmts - 6622 8b/-> *(ebp+0xc) 6/r32/esi - 6623 # var var-seen?/edx: boolean <- copy false - 6624 ba/copy-to-edx 0/imm32/false - 6625 # - 6626 { - 6627 $emit-subx-stmt-list:loop: - 6628 81 7/subop/compare %esi 0/imm32 - 6629 0f 84/jump-if-= break/disp32 - 6630 # var curr-stmt/ecx = stmts->value - 6631 8b/-> *esi 1/r32/ecx # List-value - 6632 { - 6633 $emit-subx-stmt-list:check-for-block: - 6634 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag - 6635 75/jump-if-!= break/disp8 - 6636 $emit-subx-stmt-list:block: - 6637 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) - 6638 } - 6639 { - 6640 $emit-subx-stmt-list:check-for-stmt: - 6641 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag - 6642 0f 85/jump-if-!= break/disp32 - 6643 $emit-subx-stmt-list:stmt1: - 6644 { - 6645 (is-mu-branch? %ecx) # => eax - 6646 3d/compare-eax-and 0/imm32/false - 6647 0f 84/jump-if-= break/disp32 - 6648 $emit-subx-stmt-list:branch-stmt: - 6649 # if !var-seen? break - 6650 81 7/subop/compare %edx 0/imm32/false - 6651 0f 84/jump-if-= break/disp32 - 6652 $emit-subx-stmt-list:branch-stmt-and-var-seen: - 6653 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- - 6679 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- - 6694 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- - 6731 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- - 6750 } - 6751 $emit-subx-stmt-list:1-to-1: - 6752 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) - 6753 } - 6754 { - 6755 $emit-subx-stmt-list:check-for-var-def: - 6756 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag - 6757 75/jump-if-!= break/disp8 - 6758 $emit-subx-stmt-list:var-def: - 6759 (emit-subx-var-def *(ebp+8) %ecx) - 6760 (push *(ebp+0x10) *(ecx+4)) # Vardef-var - 6761 # var-seen? = true - 6762 ba/copy-to-edx 1/imm32/true - 6763 } - 6764 { - 6765 $emit-subx-stmt-list:check-for-reg-var-def: - 6766 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag - 6767 0f 85/jump-if-!= break/disp32 - 6768 $emit-subx-stmt-list:reg-var-def: - 6769 # TODO: ensure that there's exactly one output - 6770 (compute-reg-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) - 6771 # register variable definition - 6772 (push *(ebp+0x10) %eax) - 6773 # emit the instruction as usual - 6774 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) - 6775 # var-seen? = true - 6776 ba/copy-to-edx 1/imm32/true - 6777 } - 6778 $emit-subx-stmt-list:continue: - 6779 # TODO: raise an error on unrecognized Stmt-tag - 6780 8b/-> *(esi+4) 6/r32/esi # List-next - 6781 e9/jump loop/disp32 - 6782 } - 6783 $emit-subx-stmt-list:emit-cleanup: - 6784 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) - 6785 $emit-subx-stmt-list:cleanup: - 6786 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) - 6787 $emit-subx-stmt-list:end: - 6788 # . restore registers - 6789 5e/pop-to-esi - 6790 5b/pop-to-ebx - 6791 5a/pop-to-edx - 6792 59/pop-to-ecx - 6793 58/pop-to-eax - 6794 # . epilogue - 6795 89/<- %esp 5/r32/ebp - 6796 5d/pop-to-ebp - 6797 c3/return - 6798 - 6799 compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (handle reg-var-def), vars: (addr stack (handle var)) -> result/eax: (handle var) - 6800 # . prologue - 6801 55/push-ebp - 6802 89/<- %ebp 4/r32/esp - 6803 # . save registers - 6804 51/push-ecx - 6805 # ecx = stmt - 6806 8b/-> *(ebp+0xc) 1/r32/ecx - 6807 # var output/ecx: (handle var) = curr-stmt->outputs->value - 6808 8b/-> *(ecx+0xc) 1/r32/ecx # Regvardef-inouts - 6809 8b/-> *ecx 1/r32/ecx # List-value - 6810 # v->block-depth = *Curr-block-depth - 6811 8b/-> *Curr-block-depth 0/r32/eax - 6812 89/<- *(ecx+8) 0/r32/eax # Var-block-depth - 6813 # var reg/eax: (handle array byte) = output->register - 6814 8b/-> *(ecx+0x10) 0/r32/eax # Var-register - 6815 # ensure that output is in a register - 6816 3d/compare-eax-and 0/imm32 - 6817 0f 84/jump-if-= $compute-reg-and-maybe-emit-spill:abort/disp32 - 6818 # if already-spilled-this-block?(reg, vars) return - 6819 (already-spilled-this-block? %ecx *(ebp+0x10)) # => eax - 6820 3d/compare-eax-and 0/imm32/false - 6821 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 - 6822 # TODO: assert(size-of(output) == 4) - 6823 # *Curr-local-stack-offset -= 4 - 6824 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 - 6825 # emit spill - 6826 (emit-indent *(ebp+8) *Curr-block-depth) - 6827 (write-buffered *(ebp+8) "ff 6/subop/push %") - 6828 (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register - 6829 (write-buffered *(ebp+8) Newline) - 6830 $compute-reg-and-maybe-emit-spill:end: - 6831 # return output - 6832 89/<- %eax 1/r32/ecx - 6833 # . restore registers - 6834 59/pop-to-ecx - 6835 # . epilogue - 6836 89/<- %esp 5/r32/ebp - 6837 5d/pop-to-ebp - 6838 c3/return - 6839 - 6840 $compute-reg-and-maybe-emit-spill:abort: - 6841 # error("var '" var->name "' initialized from an instruction must live in a register\n") - 6842 (write-buffered Stderr "var '") - 6843 (write-buffered Stderr *eax) # Var-name - 6844 (write-buffered Stderr "' initialized from an instruction must live in a register\n") - 6845 (flush Stderr) - 6846 # . syscall(exit, 1) - 6847 bb/copy-to-ebx 1/imm32 - 6848 b8/copy-to-eax 1/imm32/exit - 6849 cd/syscall 0x80/imm8 - 6850 # never gets here - 6851 - 6852 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) - 6853 # . prologue - 6854 55/push-ebp - 6855 89/<- %ebp 4/r32/esp - 6856 # . save registers - 6857 50/push-eax - 6858 51/push-ecx - 6859 52/push-edx - 6860 # ecx = stmt - 6861 8b/-> *(ebp+0xc) 1/r32/ecx - 6862 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name - 6863 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 6864 8b/-> *edx 2/r32/edx # Stmt-var-value - 6865 8b/-> *edx 2/r32/edx # Var-name - 6866 # clean up until target block - 6867 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) - 6868 # emit jump to target block - 6869 (emit-indent *(ebp+8) *Curr-block-depth) - 6870 (write-buffered *(ebp+8) "e9/jump ") - 6871 (write-buffered *(ebp+8) %edx) - 6872 (string-starts-with? *(ecx+4) "break") - 6873 3d/compare-eax-and 0/imm32/false - 6874 { - 6875 74/jump-if-= break/disp8 - 6876 (write-buffered *(ebp+8) ":break/disp32\n") - 6877 } - 6878 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags - 6879 { - 6880 75/jump-if-!= break/disp8 - 6881 (write-buffered *(ebp+8) ":loop/disp32\n") - 6882 } - 6883 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: - 6884 # . restore registers - 6885 5a/pop-to-edx - 6886 59/pop-to-ecx - 6887 58/pop-to-eax - 6888 # . epilogue - 6889 89/<- %esp 5/r32/ebp - 6890 5d/pop-to-ebp - 6891 c3/return - 6892 - 6893 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean - 6894 # . prologue - 6895 55/push-ebp - 6896 89/<- %ebp 4/r32/esp - 6897 # . save registers - 6898 51/push-ecx - 6899 # ecx = stmt - 6900 8b/-> *(ebp+8) 1/r32/ecx - 6901 # if (stmt->operation starts with "loop") return true - 6902 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax - 6903 3d/compare-eax-and 0/imm32/false - 6904 75/jump-if-not-equal $is-mu-branch?:end/disp8 - 6905 # otherwise return (stmt->operation starts with "break") - 6906 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax - 6907 $is-mu-branch?:end: - 6908 # . restore registers - 6909 59/pop-to-ecx - 6910 # . epilogue - 6911 89/<- %esp 5/r32/ebp - 6912 5d/pop-to-ebp - 6913 c3/return - 6914 - 6915 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) - 6916 # . prologue - 6917 55/push-ebp - 6918 89/<- %ebp 4/r32/esp - 6919 # . save registers - 6920 50/push-eax - 6921 # eax = stmt - 6922 8b/-> *(ebp+0xc) 0/r32/eax - 6923 # - 6924 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) - 6925 (emit-indent *(ebp+8) *Curr-block-depth) - 6926 (write-buffered *(ebp+8) *eax) - 6927 (write-buffered *(ebp+8) " break/disp32\n") - 6928 $emit-reverse-break:end: - 6929 # . restore registers - 6930 58/pop-to-eax - 6931 # . epilogue - 6932 89/<- %esp 5/r32/ebp - 6933 5d/pop-to-ebp - 6934 c3/return - 6935 - 6936 == data - 6937 - 6938 Reverse-branch: # (table string string) - 6939 # a table is a stream - 6940 0xa0/imm32/write - 6941 0/imm32/read - 6942 0xa0/imm32/length - 6943 # data - 6944 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 - 6945 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 - 6946 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 - 6947 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 - 6948 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 - 6949 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 - 6950 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 - 6951 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 - 6952 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 - 6953 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 - 6954 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 - 6955 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 - 6956 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 - 6957 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 - 6958 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 - 6959 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 - 6960 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 - 6961 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 - 6962 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 - 6963 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 - 6964 - 6965 == code - 6966 - 6967 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) - 6968 # . prologue - 6969 55/push-ebp - 6970 89/<- %ebp 4/r32/esp - 6971 # . save registers - 6972 50/push-eax - 6973 51/push-ecx - 6974 52/push-edx - 6975 53/push-ebx - 6976 # ecx = vars - 6977 8b/-> *(ebp+0xc) 1/r32/ecx - 6978 # var eax: int = vars->top - 6979 8b/-> *ecx 0/r32/eax - 6980 # var min/ecx: (address (handle var)) = vars->data - 6981 81 0/subop/add %ecx 8/imm32 - 6982 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] - 6983 81 5/subop/subtract %eax 4/imm32 - 6984 8d/copy-address *(ecx+eax) 0/r32/eax - 6985 # edx = depth - 6986 8b/-> *(ebp+0x10) 2/r32/edx - 6987 { - 6988 $emit-unconditional-jump-to-depth:loop: - 6989 # if (curr < min) break - 6990 39/compare %eax 1/r32/ecx - 6991 0f 82/jump-if-addr< break/disp32 - 6992 # var v/ebx: (handle var) = *curr - 6993 8b/-> *eax 3/r32/ebx - 6994 # if (v->block-depth < until-block-depth) break - 6995 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 6996 0f 8c/jump-if-< break/disp32 - 6997 { - 6998 $emit-unconditional-jump-to-depth:check: - 6999 # if v->block-depth != until-block-depth, continue - 7000 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 7001 0f 85/jump-if-!= break/disp32 - 7002 $emit-unconditional-jump-to-depth:depth-found: - 7003 # if v is not a literal, continue - 7004 # . var eax: int = size-of(v) - 7005 50/push-eax - 7006 (size-of %ebx) # => eax - 7007 # . if (eax != 0) continue - 7008 3d/compare-eax-and 0/imm32 - 7009 58/pop-to-eax - 7010 # - 7011 0f 85/jump-if-!= break/disp32 - 7012 $emit-unconditional-jump-to-depth:label-found: - 7013 # emit unconditional jump, then return - 7014 (emit-indent *(ebp+8) *Curr-block-depth) - 7015 (write-buffered *(ebp+8) "e9/jump ") - 7016 (write-buffered *(ebp+8) *ebx) # Var-name - 7017 (write-buffered *(ebp+8) ":") - 7018 (write-buffered *(ebp+8) *(ebp+0x14)) - 7019 (write-buffered *(ebp+8) "/disp32\n") - 7020 eb/jump $emit-unconditional-jump-to-depth:end/disp8 - 7021 } - 7022 # curr -= 4 - 7023 2d/subtract-from-eax 4/imm32 - 7024 e9/jump loop/disp32 - 7025 } - 7026 # TODO: error if no label at 'depth' was found - 7027 $emit-unconditional-jump-to-depth:end: - 7028 # . restore registers - 7029 5b/pop-to-ebx - 7030 5a/pop-to-edx - 7031 59/pop-to-ecx - 7032 58/pop-to-eax - 7033 # . epilogue - 7034 89/<- %esp 5/r32/ebp - 7035 5d/pop-to-ebp - 7036 c3/return - 7037 - 7038 # emit clean-up code for 'vars' until some block depth - 7039 # doesn't actually modify 'vars' so we need traverse manually inside the stack - 7040 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int - 7041 # . prologue - 7042 55/push-ebp - 7043 89/<- %ebp 4/r32/esp - 7044 # . save registers - 7045 50/push-eax - 7046 51/push-ecx - 7047 52/push-edx - 7048 53/push-ebx - 7049 # ecx = vars - 7050 8b/-> *(ebp+0xc) 1/r32/ecx - 7051 # var eax: int = vars->top - 7052 8b/-> *ecx 0/r32/eax - 7053 # var min/ecx: (address (handle var)) = vars->data - 7054 81 0/subop/add %ecx 8/imm32 - 7055 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] - 7056 81 5/subop/subtract %eax 4/imm32 - 7057 8d/copy-address *(ecx+eax) 0/r32/eax - 7058 # edx = until-block-depth - 7059 8b/-> *(ebp+0x10) 2/r32/edx - 7060 { - 7061 $emit-cleanup-code-until-depth:loop: - 7062 # if (curr < min) break - 7063 39/compare %eax 1/r32/ecx - 7064 0f 82/jump-if-addr< break/disp32 - 7065 # var v/ebx: (handle var) = *curr - 7066 8b/-> *eax 3/r32/ebx - 7067 # if (v->block-depth < until-block-depth) break - 7068 39/compare *(ebx+8) 2/r32/edx # Var-block-depth - 7069 0f 8c/jump-if-< break/disp32 - 7070 # if v is in a register - 7071 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 7072 { - 7073 0f 84/jump-if-= break/disp32 - 7074 50/push-eax - 7075 { - 7076 $emit-cleanup-code-until-depth:check-for-previous-spill: - 7077 (same-register-spilled-before? %ebx *(ebp+0xc) %eax) # => eax - 7078 3d/compare-eax-and 0/imm32/false - 7079 0f 85/jump-if-!= break/disp32 - 7080 $emit-cleanup-code-until-depth:reclaim-var-in-register: - 7081 (emit-indent *(ebp+8) *Curr-block-depth) - 7082 (write-buffered *(ebp+8) "8f 0/subop/pop %") - 7083 (write-buffered *(ebp+8) *(ebx+0x10)) - 7084 (write-buffered *(ebp+8) Newline) - 7085 } - 7086 58/pop-to-eax - 7087 eb/jump $emit-cleanup-code-until-depth:continue/disp8 - 7088 } - 7089 # otherwise v is on the stack - 7090 { - 7091 75/jump-if-!= break/disp8 - 7092 $emit-cleanup-code-until-depth:reclaim-var-on-stack: - 7093 50/push-eax - 7094 (size-of %ebx) # => eax - 7095 # don't emit code for labels - 7096 3d/compare-eax-and 0/imm32 - 7097 74/jump-if-= break/disp8 - 7098 # - 7099 (emit-indent *(ebp+8) *Curr-block-depth) - 7100 (write-buffered *(ebp+8) "81 0/subop/add %esp ") - 7101 (print-int32-buffered *(ebp+8) %eax) - 7102 (write-buffered *(ebp+8) "/imm32\n") - 7103 58/pop-to-eax - 7104 } - 7105 $emit-cleanup-code-until-depth:continue: - 7106 # curr -= 4 - 7107 2d/subtract-from-eax 4/imm32 - 7108 e9/jump loop/disp32 - 7109 } - 7110 $emit-cleanup-code-until-depth:end: - 7111 # . restore registers - 7112 5b/pop-to-ebx - 7113 5a/pop-to-edx - 7114 59/pop-to-ecx - 7115 58/pop-to-eax - 7116 # . epilogue - 7117 89/<- %esp 5/r32/ebp - 7118 5d/pop-to-ebp - 7119 c3/return - 7120 - 7121 # emit clean-up code for 'vars' until a given label is encountered - 7122 # doesn't actually modify 'vars' so we need traverse manually inside the stack - 7123 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) - 7124 # . prologue - 7125 55/push-ebp - 7126 89/<- %ebp 4/r32/esp - 7127 # . save registers - 7128 50/push-eax - 7129 51/push-ecx - 7130 52/push-edx - 7131 53/push-ebx - 7132 # ecx = vars - 7133 8b/-> *(ebp+0xc) 1/r32/ecx - 7134 # var eax: int = vars->top - 7135 8b/-> *ecx 0/r32/eax - 7136 # var min/ecx: (address (handle var)) = vars->data - 7137 81 0/subop/add %ecx 8/imm32 - 7138 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] - 7139 81 5/subop/subtract %eax 4/imm32 - 7140 8d/copy-address *(ecx+eax) 2/r32/edx - 7141 { - 7142 $emit-cleanup-code-until-target:loop: - 7143 # if (curr < min) break - 7144 39/compare %edx 1/r32/ecx - 7145 0f 82/jump-if-addr< break/disp32 - 7146 # var v/ebx: (handle var) = *curr - 7147 8b/-> *edx 3/r32/ebx - 7148 # if (v->name == until-block-label) break - 7149 (string-equal? *ebx *(ebp+0x10)) # => eax - 7150 3d/compare-eax-and 0/imm32/false - 7151 0f 85/jump-if-!= break/disp32 - 7152 # if v is in a register - 7153 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register - 7154 { - 7155 74/jump-if-= break/disp8 - 7156 50/push-eax - 7157 { - 7158 $emit-cleanup-code-until-target:check-for-previous-spill: - 7159 (same-register-spilled-before? %ebx *(ebp+0xc) %edx) # => eax - 7160 3d/compare-eax-and 0/imm32/false - 7161 75/jump-if-!= break/disp8 - 7162 $emit-cleanup-code-until-target:reclaim-var-in-register: - 7163 (emit-indent *(ebp+8) *Curr-block-depth) - 7164 (write-buffered *(ebp+8) "8f 0/subop/pop %") - 7165 (write-buffered *(ebp+8) *(ebx+0x10)) - 7166 (write-buffered *(ebp+8) Newline) - 7167 } - 7168 58/pop-to-eax - 7169 eb/jump $emit-cleanup-code-until-target:continue/disp8 - 7170 } - 7171 # otherwise v is on the stack - 7172 { - 7173 75/jump-if-!= break/disp8 - 7174 $emit-cleanup-code-until-target:reclaim-var-on-stack: - 7175 (size-of %ebx) # => eax - 7176 # don't emit code for labels - 7177 3d/compare-eax-and 0/imm32 - 7178 74/jump-if-= break/disp8 - 7179 # - 7180 (emit-indent *(ebp+8) *Curr-block-depth) - 7181 (write-buffered *(ebp+8) "81 0/subop/add %esp ") - 7182 (print-int32-buffered *(ebp+8) %eax) - 7183 (write-buffered *(ebp+8) "/imm32\n") - 7184 } - 7185 $emit-cleanup-code-until-target:continue: - 7186 # curr -= 4 - 7187 81 5/subop/subtract %edx 4/imm32 - 7188 e9/jump loop/disp32 - 7189 } - 7190 $emit-cleanup-code-until-target:end: - 7191 # . restore registers - 7192 5b/pop-to-ebx - 7193 5a/pop-to-edx - 7194 59/pop-to-ecx - 7195 58/pop-to-eax - 7196 # . epilogue - 7197 89/<- %esp 5/r32/ebp - 7198 5d/pop-to-ebp - 7199 c3/return - 7200 - 7201 # is there already a var with the same block-depth and register as 'v' on the 'vars' stack? - 7202 # v is guaranteed not to be within vars - 7203 already-spilled-this-block?: # v: (handle var), vars: (addr stack (handle var)) -> result/eax: boolean - 7204 # . prologue - 7205 55/push-ebp - 7206 89/<- %ebp 4/r32/esp - 7207 # . save registers - 7208 51/push-ecx - 7209 52/push-edx - 7210 53/push-ebx - 7211 56/push-esi - 7212 57/push-edi - 7213 # ecx = vars - 7214 8b/-> *(ebp+0xc) 1/r32/ecx - 7215 # var eax: int = vars->top - 7216 8b/-> *ecx 0/r32/eax - 7217 # var min/ecx: (address (handle var)) = vars->data - 7218 81 0/subop/add %ecx 8/imm32 - 7219 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] - 7220 81 5/subop/subtract %eax 4/imm32 - 7221 8d/copy-address *(ecx+eax) 2/r32/edx - 7222 # var depth/ebx: int = v->block-depth - 7223 8b/-> *(ebp+8) 3/r32/ebx - 7224 8b/-> *(ebx+8) 3/r32/ebx # Var-block-depth - 7225 # var needle/esi: (handle array byte) = v->register - 7226 8b/-> *(ebp+8) 6/r32/esi - 7227 8b/-> *(esi+0x10) 6/r32/esi # Var-register - 7228 { - 7229 $already-spilled-this-block?:loop: - 7230 # if (curr < min) break - 7231 39/compare %edx 1/r32/ecx - 7232 0f 82/jump-if-addr< break/disp32 - 7233 # var cand/edi: (handle var) = *curr - 7234 8b/-> *edx 7/r32/edi - 7235 # if (cand->block-depth < depth) break - 7236 39/compare *(edi+8) 3/r32/ebx # Var-block-depth - 7237 0f 8c/jump-if-< break/disp32 - 7238 # var cand-reg/edi: (handle array byte) = cand->reg - 7239 8b/-> *(edi+0x10) 7/r32/edi - 7240 # if (cand-reg == null) continue - 7241 { - 7242 $already-spilled-this-block?:check-reg: - 7243 81 7/subop/compare %edi 0/imm32 - 7244 74/jump-if-= break/disp8 - 7245 # if (cand-reg == needle) return true - 7246 (string-equal? %esi %edi) # => eax - 7247 3d/compare-eax-and 0/imm32/false - 7248 74/jump-if-= break/disp8 - 7249 b8/copy-to-eax 1/imm32/true - 7250 eb/jump $already-spilled-this-block?:end/disp8 - 7251 } - 7252 $already-spilled-this-block?:continue: - 7253 # curr -= 4 - 7254 81 5/subop/subtract %edx 4/imm32 - 7255 e9/jump loop/disp32 - 7256 } - 7257 # return false - 7258 b8/copy-to-eax 0/imm32/false - 7259 $already-spilled-this-block?:end: - 7260 # . restore registers - 7261 5f/pop-to-edi - 7262 5e/pop-to-esi - 7263 5b/pop-to-ebx - 7264 5a/pop-to-edx - 7265 59/pop-to-ecx - 7266 # . epilogue - 7267 89/<- %esp 5/r32/ebp - 7268 5d/pop-to-ebp - 7269 c3/return - 7270 - 7271 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? - 7272 # v is guaranteed to be within vars - 7273 # 'start' is provided as an optimization, a pointer within vars - 7274 # *start == v - 7275 same-register-spilled-before?: # v: (handle var), vars: (addr stack (handle var)), start: (addr (handle var)) -> result/eax: boolean - 7276 # . prologue - 7277 55/push-ebp - 7278 89/<- %ebp 4/r32/esp - 7279 # . save registers - 7280 51/push-ecx - 7281 52/push-edx - 7282 53/push-ebx - 7283 56/push-esi - 7284 57/push-edi - 7285 # ecx = v - 7286 8b/-> *(ebp+8) 1/r32/ecx - 7287 # var reg/edx: (handle array byte) = v->register - 7288 8b/-> *(ecx+0x10) 2/r32/edx # Var-register - 7289 # var depth/ebx: int = v->block-depth - 7290 8b/-> *(ecx+8) 3/r32/ebx # Var-block-depth - 7291 # var min/ecx: (address (handle var)) = vars->data - 7292 8b/-> *(ebp+0xc) 1/r32/ecx - 7293 81 0/subop/add %ecx 8/imm32 - 7294 # TODO: check that start >= min and start < &vars->data[top] - 7295 # TODO: check that *start == v - 7296 # var curr/esi: (address (handle var)) = start - 7297 8b/-> *(ebp+0x10) 6/r32/esi - 7298 # curr -= 4 - 7299 81 5/subop/subtract %esi 4/imm32 - 7300 { - 7301 $same-register-spilled-before?:loop: - 7302 # if (curr < min) break - 7303 39/compare %esi 1/r32/ecx - 7304 0f 82/jump-if-addr< break/disp32 - 7305 # var x/eax: (handle var) = *curr - 7306 8b/-> *esi 0/r32/eax - 7307 # if (x->block-depth < depth) break - 7308 39/compare *(eax+8) 3/r32/ebx # Var-block-depth - 7309 0f 8c/jump-if-< break/disp32 - 7310 # if (x->register == 0) continue - 7311 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register - 7312 74/jump-if-= $same-register-spilled-before?:continue/disp8 - 7313 # if (x->register == reg) return true - 7314 (string-equal? *(eax+0x10) %edx) # Var-register => eax - 7315 3d/compare-eax-and 0/imm32/false - 7316 75/jump-if-!= $same-register-spilled-before?:end/disp8 - 7317 $same-register-spilled-before?:continue: - 7318 # curr -= 4 - 7319 81 5/subop/subtract %esi 4/imm32 - 7320 e9/jump loop/disp32 - 7321 } - 7322 $same-register-spilled-before?:false: - 7323 b8/copy-to-eax 0/imm32/false - 7324 $same-register-spilled-before?:end: - 7325 # . restore registers - 7326 5f/pop-to-edi - 7327 5e/pop-to-esi - 7328 5b/pop-to-ebx - 7329 5a/pop-to-edx - 7330 59/pop-to-ecx - 7331 # . epilogue - 7332 89/<- %esp 5/r32/ebp - 7333 5d/pop-to-ebp - 7334 c3/return - 7335 - 7336 # clean up global state for 'vars' until some block depth - 7337 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int - 7338 # . prologue - 7339 55/push-ebp - 7340 89/<- %ebp 4/r32/esp - 7341 # . save registers - 7342 50/push-eax - 7343 51/push-ecx - 7344 56/push-esi - 7345 # esi = vars - 7346 8b/-> *(ebp+8) 6/r32/esi - 7347 # ecx = until-block-depth - 7348 8b/-> *(ebp+0xc) 1/r32/ecx - 7349 { - 7350 $clean-up-blocks:reclaim-loop: - 7351 # if (vars->top <= 0) break - 7352 81 7/subop/compare *esi 0/imm32 # Stack-top - 7353 7e/jump-if-<= break/disp8 - 7354 # var v/eax: (handle var) = top(vars) - 7355 (top %esi) # => eax - 7356 # if (v->block-depth < until-block-depth) break - 7357 39/compare *(eax+8) 1/r32/ecx # Var-block-depth - 7358 7c/jump-if-< break/disp8 - 7359 # if v is on the stack, update Curr-local-stack-offset - 7360 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register - 7361 { - 7362 75/jump-if-!= break/disp8 - 7363 $clean-up-blocks:reclaim-var-on-stack: - 7364 (size-of %eax) # => eax - 7365 01/add *Curr-local-stack-offset 0/r32/eax - 7366 } - 7367 (pop %esi) - 7368 e9/jump loop/disp32 - 7369 } - 7370 $clean-up-blocks:end: + 6025 $populate-mu-type:abort: + 6026 # error("unexpected top-level command: " word-slice "\n") + 6027 (write-buffered Stderr "incomplete type definition '") + 6028 (type-name *edi) # Typeinfo-id => eax + 6029 (write-buffered Stderr %eax) + 6030 (write-buffered Stderr "\n") + 6031 (flush Stderr) + 6032 # . syscall(exit, 1) + 6033 bb/copy-to-ebx 1/imm32 + 6034 b8/copy-to-eax 1/imm32/exit + 6035 cd/syscall 0x80/imm8 + 6036 # never gets here + 6037 + 6038 type-name: # index: int -> result/eax: (addr array byte) + 6039 # . prologue + 6040 55/push-ebp + 6041 89/<- %ebp 4/r32/esp + 6042 # + 6043 (index Type-id *(ebp+8)) + 6044 $type-name:end: + 6045 # . epilogue + 6046 89/<- %esp 5/r32/ebp + 6047 5d/pop-to-ebp + 6048 c3/return + 6049 + 6050 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) + 6051 # . prologue + 6052 55/push-ebp + 6053 89/<- %ebp 4/r32/esp + 6054 # . save registers + 6055 56/push-esi + 6056 # TODO: bounds-check index + 6057 # esi = arr + 6058 8b/-> *(ebp+8) 6/r32/esi + 6059 # eax = index + 6060 8b/-> *(ebp+0xc) 0/r32/eax + 6061 # eax = *(arr + 12 + index) + 6062 8b/-> *(esi+eax+0xc) 0/r32/eax + 6063 $index:end: + 6064 # . restore registers + 6065 5e/pop-to-esi + 6066 # . epilogue + 6067 89/<- %esp 5/r32/ebp + 6068 5d/pop-to-ebp + 6069 c3/return + 6070 + 6071 ####################################################### + 6072 # Compute type sizes + 6073 ####################################################### + 6074 + 6075 # Compute the sizes of all user-defined types. + 6076 # We'll need the sizes of their elements, which may be other user-defined + 6077 # types, which we will compute as needed. + 6078 + 6079 # Initially, all user-defined types have their sizes set to -2 (invalid) + 6080 populate-mu-type-sizes: + 6081 # . prologue + 6082 55/push-ebp + 6083 89/<- %ebp 4/r32/esp + 6084 # . save registers + 6085 51/push-ecx + 6086 $populate-mu-type-sizes:total-sizes: + 6087 # var curr/ecx: (handle typeinfo) = *Program->types + 6088 8b/-> *_Program-types 1/r32/ecx + 6089 { + 6090 # if (curr == null) break + 6091 81 7/subop/compare %ecx 0/imm32 + 6092 74/jump-if-= break/disp8 + 6093 (populate-mu-type-sizes-in-type %ecx) + 6094 # curr = curr->next + 6095 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next + 6096 eb/jump loop/disp8 + 6097 } + 6098 $populate-mu-type-sizes:offsets: + 6099 # var curr/ecx: (handle typeinfo) = *Program->types + 6100 8b/-> *_Program-types 1/r32/ecx + 6101 { + 6102 # if (curr == null) break + 6103 81 7/subop/compare %ecx 0/imm32 + 6104 74/jump-if-= break/disp8 + 6105 (populate-mu-type-offsets %ecx) + 6106 # curr = curr->next + 6107 8b/-> *(ecx+0xc) 1/r32/ecx # Typeinfo-next + 6108 eb/jump loop/disp8 + 6109 } + 6110 $populate-mu-type-sizes:end: + 6111 # . restore registers + 6112 59/pop-to-ecx + 6113 # . epilogue + 6114 89/<- %esp 5/r32/ebp + 6115 5d/pop-to-ebp + 6116 c3/return + 6117 + 6118 # compute sizes of all fields, recursing as necessary + 6119 # sum up all their sizes to arrive at total size + 6120 # fields may be out of order, but that doesn't affect the answer + 6121 populate-mu-type-sizes-in-type: # T: (handle typeinfo) + 6122 # . prologue + 6123 55/push-ebp + 6124 89/<- %ebp 4/r32/esp + 6125 # . save registers + 6126 50/push-eax + 6127 51/push-ecx + 6128 52/push-edx + 6129 56/push-esi + 6130 57/push-edi + 6131 # esi = T + 6132 8b/-> *(ebp+8) 6/r32/esi + 6133 # if T is already computed, return + 6134 81 7/subop/compare *(esi+8) 0/imm32 # Typeinfo-total-size-in-bytes + 6135 7d/jump-if->= $populate-mu-type-sizes-in-type:end/disp8 + 6136 # if T is being computed, abort + 6137 81 7/subop/compare *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes + 6138 74/jump-if-= $populate-mu-type-sizes-in-type:abort/disp8 + 6139 # tag T (-2 to -1) to avoid infinite recursion + 6140 c7 0/subop/copy *(esi+8) -1/imm32/being-computed # Typeinfo-total-size-in-bytes + 6141 # var total-size/edi: int = 0 + 6142 bf/copy-to-edi 0/imm32 + 6143 # - for every field, if it's a user-defined type, compute its size + 6144 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields + 6145 8b/-> *(esi+4) 1/r32/ecx # Typeinfo-fields + 6146 # var table-size/edx: int = table->write + 6147 8b/-> *ecx 2/r32/edx # stream-write + 6148 # var curr/ecx: (addr table_row) = table->data + 6149 8d/copy-address *(ecx+0xc) 1/r32/ecx + 6150 # var max/edx: (addr table_row) = table->data + table->write + 6151 8d/copy-address *(ecx+edx) 2/r32/edx + 6152 { + 6153 $populate-mu-type-sizes-in-type:loop: + 6154 # if (curr >= max) break + 6155 39/compare %ecx 2/r32/edx + 6156 73/jump-if-addr>= break/disp8 + 6157 # var t/eax: (handle typeinfo-entry) = curr->value + 6158 8b/-> *(ecx+4) 0/r32/eax + 6159 # compute size of t + 6160 (compute-size-of-var *eax) # Typeinfo-entry-input-var => eax + 6161 # result += eax + 6162 01/add-to %edi 0/r32/eax + 6163 # curr += row-size + 6164 81 0/subop/add %ecx 8/imm32 + 6165 # + 6166 eb/jump loop/disp8 + 6167 } + 6168 # - save result + 6169 89/<- *(esi+8) 7/r32/edi # Typeinfo-total-size-in-bytes + 6170 $populate-mu-type-sizes-in-type:end: + 6171 # . restore registers + 6172 5f/pop-to-edi + 6173 5e/pop-to-esi + 6174 5a/pop-to-edx + 6175 59/pop-to-ecx + 6176 58/pop-to-eax + 6177 # . epilogue + 6178 89/<- %esp 5/r32/ebp + 6179 5d/pop-to-ebp + 6180 c3/return + 6181 + 6182 $populate-mu-type-sizes-in-type:abort: + 6183 (write-buffered Stderr "cycle in type definitions\n") + 6184 (flush Stderr) + 6185 # . syscall(exit, 1) + 6186 bb/copy-to-ebx 1/imm32 + 6187 b8/copy-to-eax 1/imm32/exit + 6188 cd/syscall 0x80/imm8 + 6189 # never gets here + 6190 + 6191 # Analogous to size-of, except we need to compute what size-of can just read + 6192 # off the right data structures. + 6193 compute-size-of-var: # in: (handle var) -> result/eax: int + 6194 # . prologue + 6195 55/push-ebp + 6196 89/<- %ebp 4/r32/esp + 6197 # . push registers + 6198 51/push-ecx + 6199 # var t/ecx: (handle tree type-id) = v->type + 6200 8b/-> *(ebp+8) 1/r32/ecx + 6201 8b/-> *(ecx+4) 1/r32/ecx # Var-type + 6202 # if (t->left >= *Max-type-id) t = t->left + 6203 { + 6204 8b/-> *Max-type-id 0/r32/eax + 6205 39/compare *ecx 0/r32/eax # Tree-left + 6206 72/jump-if-addr< break/disp8 + 6207 8b/-> *ecx 1/r32/ecx # Tree-left + 6208 } + 6209 (compute-size-of-type-id *ecx) # Atom-left => eax + 6210 $compute-size-of-var:end: + 6211 # . restore registers + 6212 59/pop-to-ecx + 6213 # . epilogue + 6214 89/<- %esp 5/r32/ebp + 6215 5d/pop-to-ebp + 6216 c3/return + 6217 + 6218 compute-size-of-type-id: # t: type-id -> result/eax: int + 6219 # . prologue + 6220 55/push-ebp + 6221 89/<- %ebp 4/r32/esp + 6222 # + 6223 8b/-> *(ebp+8) 0/r32/eax + 6224 # if v is a literal, return 0 + 6225 3d/compare-eax-and 0/imm32 + 6226 74/jump-if-= $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int + 6227 # if v has a user-defined type, compute its size + 6228 # TODO: support non-atom type + 6229 (find-typeinfo %eax) # => eax + 6230 { + 6231 3d/compare-eax-and 0/imm32 + 6232 74/jump-if-= break/disp8 + 6233 $compute-size-of-type-id:user-defined: + 6234 (populate-mu-type-sizes %eax) + 6235 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes + 6236 eb/jump $compute-size-of-type-id:end/disp8 + 6237 } + 6238 # otherwise return the word size + 6239 b8/copy-to-eax 4/imm32 + 6240 $compute-size-of-type-id:end: + 6241 # . epilogue + 6242 89/<- %esp 5/r32/ebp + 6243 5d/pop-to-ebp + 6244 c3/return + 6245 + 6246 # at this point we have total sizes for all user-defined types + 6247 # compute offsets for each element + 6248 # complication: fields may be out of order + 6249 populate-mu-type-offsets: # in: (handle typeinfo) + 6250 # . prologue + 6251 55/push-ebp + 6252 89/<- %ebp 4/r32/esp + 6253 # . save registers + 6254 50/push-eax + 6255 51/push-ecx + 6256 52/push-edx + 6257 53/push-ebx + 6258 56/push-esi + 6259 57/push-edi + 6260 # var curr-offset/edi: int = 0 + 6261 bf/copy-to-edi 0/imm32 + 6262 # var table/ecx: (handle table string_key (handle typeinfo-entry)) = T->fields + 6263 8b/-> *(ebp+8) 1/r32/ecx + 6264 8b/-> *(ecx+4) 1/r32/ecx # Typeinfo-fields + 6265 # var num-elems/edx: int = table->write / 8 + 6266 8b/-> *ecx 2/r32/edx # stream-write + 6267 c1 5/subop/shift-right-logical %edx 3/imm8 + 6268 # var i/ebx: int = 0 + 6269 bb/copy-to-ebx 0/imm32 + 6270 { + 6271 $populate-mu-type-offsets:loop: + 6272 39/compare %ebx 2/r32/edx + 6273 7d/jump-if->= break/disp8 + 6274 # var v/esi: (handle typeinfo-entry) + 6275 (locate-typeinfo-entry-with-index %ecx %ebx) # => eax + 6276 89/<- %esi 0/r32/eax + 6277 # v->output-var->offset = curr-offset + 6278 8b/-> *(esi+8) 0/r32/eax # Typeinfo-entry-output-var + 6279 89/<- *(eax+0xc) 7/r32/edi # Var-offset + 6280 # curr-offset += size-of(v->input-var) + 6281 8b/-> *esi 0/r32/eax # Typeinfo-entry-input-var + 6282 (size-of %eax) # => eax + 6283 01/add-to %edi 0/r32/eax + 6284 # ++i + 6285 43/increment-ebx + 6286 eb/jump loop/disp8 + 6287 } + 6288 $populate-mu-type-offsets:end: + 6289 # . restore registers + 6290 5f/pop-to-edi + 6291 5e/pop-to-esi + 6292 5b/pop-to-ebx + 6293 5a/pop-to-edx + 6294 59/pop-to-ecx + 6295 58/pop-to-eax + 6296 # . epilogue + 6297 89/<- %esp 5/r32/ebp + 6298 5d/pop-to-ebp + 6299 c3/return + 6300 + 6301 locate-typeinfo-entry-with-index: # table: (handle table string_key (handle typeinfo-entry)), idx: int -> result/eax: (handle typeinfo-entry) + 6302 # . prologue + 6303 55/push-ebp + 6304 89/<- %ebp 4/r32/esp + 6305 # . save registers + 6306 51/push-ecx + 6307 52/push-edx + 6308 53/push-ebx + 6309 56/push-esi + 6310 57/push-edi + 6311 # esi = table + 6312 8b/-> *(ebp+8) 6/r32/esi + 6313 # var curr/ecx: (addr string_key) = table->data + 6314 8d/copy-address *(esi+0xc) 1/r32/ecx + 6315 # var max/edx: (addr byte) = &table->data[table->write] + 6316 8b/-> *esi 2/r32/edx + 6317 8d/copy-address *(ecx+edx) 2/r32/edx + 6318 { + 6319 $locate-typeinfo-entry-with-index:loop: + 6320 39/compare %ecx 2/r32/edx + 6321 73/jump-if-addr>= $locate-typeinfo-entry-with-index:abort/disp8 + 6322 # var v/ebx: (handle typeinfo-entry) + 6323 8b/-> *(ecx+4) 3/r32/ebx + 6324 # if (v->index == idx) return v + 6325 8b/-> *(ebx+4) 0/r32/eax # Typeinfo-entry-index + 6326 39/compare *(ebp+0xc) 0/r32/eax + 6327 89/<- %eax 3/r32/ebx + 6328 74/jump-if-= break/disp8 + 6329 # curr += 8 + 6330 81 0/subop/add %ecx 8/imm32 + 6331 eb/jump loop/disp8 + 6332 } + 6333 $locate-typeinfo-entry-with-index:end: + 6334 # . restore registers + 6335 5f/pop-to-edi + 6336 5e/pop-to-esi + 6337 5b/pop-to-ebx + 6338 5a/pop-to-edx + 6339 59/pop-to-ecx + 6340 # . epilogue + 6341 89/<- %esp 5/r32/ebp + 6342 5d/pop-to-ebp + 6343 c3/return + 6344 + 6345 $locate-typeinfo-entry-with-index:abort: + 6346 (write-buffered Stderr "overflowing typeinfo-entry->index ") + 6347 (print-int32-buffered Stderr %ecx) + 6348 (write-buffered Stderr "\n") + 6349 (flush Stderr) + 6350 # . syscall(exit, 1) + 6351 bb/copy-to-ebx 1/imm32 + 6352 b8/copy-to-eax 1/imm32/exit + 6353 cd/syscall 0x80/imm8 + 6354 # never gets here + 6355 + 6356 ####################################################### + 6357 # Type-checking + 6358 ####################################################### + 6359 + 6360 check-mu-types: + 6361 # . prologue + 6362 55/push-ebp + 6363 89/<- %ebp 4/r32/esp + 6364 # + 6365 $check-mu-types:end: + 6366 # . epilogue + 6367 89/<- %esp 5/r32/ebp + 6368 5d/pop-to-ebp + 6369 c3/return + 6370 + 6371 size-of: # v: (handle var) -> result/eax: int + 6372 # . prologue + 6373 55/push-ebp + 6374 89/<- %ebp 4/r32/esp + 6375 # . save registers + 6376 51/push-ecx + 6377 # var t/ecx: (handle tree type-id) = v->type + 6378 8b/-> *(ebp+8) 1/r32/ecx + 6379 8b/-> *(ecx+4) 1/r32/ecx # Var-type + 6380 # if is-mu-array?(t) return size-of-array(t) + 6381 { + 6382 (is-mu-array? %ecx) # => eax + 6383 3d/compare-eax-and 0/imm32/false + 6384 74/jump-if-= break/disp8 + 6385 (size-of-array %ecx) # => eax + 6386 eb/jump $size-of:end/disp8 + 6387 } + 6388 # if (t->left >= *Max-type-id) t = t->left + 6389 { + 6390 8b/-> *Max-type-id 0/r32/eax + 6391 39/compare *ecx 0/r32/eax # Tree-left + 6392 72/jump-if-addr< break/disp8 + 6393 8b/-> *ecx 1/r32/ecx # Tree-left + 6394 } + 6395 (size-of-type-id *ecx) # Atom-left => eax + 6396 $size-of:end: + 6397 # . restore registers + 6398 59/pop-to-ecx + 6399 # . epilogue + 6400 89/<- %esp 5/r32/ebp + 6401 5d/pop-to-ebp + 6402 c3/return + 6403 + 6404 is-mu-array?: # t: (handle tree type-id) -> result/eax: boolean + 6405 # . prologue + 6406 55/push-ebp + 6407 89/<- %ebp 4/r32/esp + 6408 # . save registers + 6409 51/push-ecx + 6410 # ecx = t->left + 6411 8b/-> *(ebp+8) 1/r32/ecx + 6412 8b/-> *ecx 1/r32/ecx # Tree-left + 6413 # if t is an atomic type, return false + 6414 3b/compare 1/r32/ecx *Max-type-id + 6415 b8/copy-to-eax 0/imm32/false + 6416 72/jump-if-addr< $is-mu-array?:end/disp8 + 6417 # return ecx->value == array + 6418 81 7/subop/compare *ecx 3/imm32/array-type-id # Atom-value + 6419 0f 94/set-if-= %al + 6420 81 4/subop/and %eax 0xff/imm32 + 6421 $is-mu-array?:end: + 6422 # . restore registers + 6423 59/pop-to-ecx + 6424 # . epilogue + 6425 89/<- %esp 5/r32/ebp + 6426 5d/pop-to-ebp + 6427 c3/return + 6428 + 6429 size-of-array: # a: (handle tree type-id) -> result/eax: int + 6430 # . prologue + 6431 55/push-ebp + 6432 89/<- %ebp 4/r32/esp + 6433 # . save registers + 6434 51/push-ecx + 6435 52/push-edx + 6436 # + 6437 8b/-> *(ebp+8) 1/r32/ecx + 6438 # TODO: assert that a->left is 'array' + 6439 8b/-> *(ecx+4) 1/r32/ecx # Tree-right + 6440 # var elem-type/edx: type-id = a->right->value + 6441 8b/-> *ecx 2/r32/edx # Atom-value + 6442 8b/-> *edx 2/r32/edx # Atom-value + 6443 # var array-size/ecx: int = a->right->right->left->value + 6444 8b/-> *(ecx+4) 1/r32/ecx # Tree-right + 6445 8b/-> *ecx 1/r32/ecx # Tree-left + 6446 8b/-> *ecx 1/r32/ecx # Atom-value + 6447 # return array-size * size-of(elem-type) + 6448 (size-of-type-id %edx) # => eax + 6449 f7 4/subop/multiply-into-eax %ecx + 6450 05/add-to-eax 4/imm32 # for array length + 6451 $size-of-array:end: + 6452 # . restore registers + 6453 5a/pop-to-edx + 6454 59/pop-to-ecx + 6455 # . epilogue + 6456 89/<- %esp 5/r32/ebp + 6457 5d/pop-to-ebp + 6458 c3/return + 6459 + 6460 size-of-type-id: # t: type-id -> result/eax: int + 6461 # . prologue + 6462 55/push-ebp + 6463 89/<- %ebp 4/r32/esp + 6464 # + 6465 8b/-> *(ebp+8) 0/r32/eax + 6466 # if v is a literal, return 0 + 6467 3d/compare-eax-and 0/imm32 + 6468 74/jump-if-= $size-of-type-id:end/disp8 # eax changes type from type-id to int + 6469 # if v has a user-defined type, return its size + 6470 # TODO: support non-atom type + 6471 (find-typeinfo %eax) # => eax + 6472 { + 6473 3d/compare-eax-and 0/imm32 + 6474 74/jump-if-= break/disp8 + 6475 $size-of-type-id:user-defined: + 6476 8b/-> *(eax+8) 0/r32/eax # Typeinfo-total-size-in-bytes + 6477 eb/jump $size-of-type-id:end/disp8 + 6478 } + 6479 # otherwise return the word size + 6480 b8/copy-to-eax 4/imm32 + 6481 $size-of-type-id:end: + 6482 # . epilogue + 6483 89/<- %esp 5/r32/ebp + 6484 5d/pop-to-ebp + 6485 c3/return + 6486 + 6487 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean + 6488 # . prologue + 6489 55/push-ebp + 6490 89/<- %ebp 4/r32/esp + 6491 # . save registers + 6492 51/push-ecx + 6493 52/push-edx + 6494 # ecx = a + 6495 8b/-> *(ebp+8) 1/r32/ecx + 6496 # edx = b + 6497 8b/-> *(ebp+0xc) 2/r32/edx + 6498 # if (a == b) return true + 6499 8b/-> %ecx 0/r32/eax # Var-type + 6500 39/compare %edx 0/r32/eax # Var-type + 6501 b8/copy-to-eax 1/imm32/true + 6502 74/jump-if-= $type-equal?:end/disp8 + 6503 # if (a < MAX_TYPE_ID) return false + 6504 81 7/subop/compare %ecx 0x10000/imm32 + 6505 b8/copy-to-eax 0/imm32/false + 6506 72/jump-if-addr< $type-equal?:end/disp8 + 6507 # if (b < MAX_TYPE_ID) return false + 6508 81 7/subop/compare %edx 0x10000/imm32 + 6509 b8/copy-to-eax 0/imm32/false + 6510 72/jump-if-addr< $type-equal?:end/disp8 + 6511 # if (!type-equal?(a->left, b->left)) return false + 6512 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax + 6513 3d/compare-eax-and 0/imm32/false + 6514 74/jump-if-= $type-equal?:end/disp8 + 6515 # return type-equal?(a->right, b->right) + 6516 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax + 6517 $type-equal?:end: + 6518 # . restore registers + 6519 5a/pop-to-edx + 6520 59/pop-to-ecx + 6521 # . epilogue + 6522 89/<- %esp 5/r32/ebp + 6523 5d/pop-to-ebp + 6524 c3/return + 6525 + 6526 ####################################################### + 6527 # Code-generation + 6528 ####################################################### + 6529 + 6530 == data + 6531 + 6532 Curr-block-depth: # (addr int) + 6533 0/imm32 + 6534 Curr-local-stack-offset: # (addr int) + 6535 0/imm32 + 6536 + 6537 == code + 6538 + 6539 emit-subx: # out: (addr buffered-file) + 6540 # . prologue + 6541 55/push-ebp + 6542 89/<- %ebp 4/r32/esp + 6543 # . save registers + 6544 50/push-eax + 6545 51/push-ecx + 6546 57/push-edi + 6547 # edi = out + 6548 8b/-> *(ebp+8) 7/r32/edi + 6549 # var curr/ecx: (handle function) = *Program->functions + 6550 8b/-> *_Program-functions 1/r32/ecx + 6551 { + 6552 # if (curr == null) break + 6553 81 7/subop/compare %ecx 0/imm32 + 6554 0f 84/jump-if-= break/disp32 + 6555 (emit-subx-function %edi %ecx) + 6556 # curr = curr->next + 6557 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next + 6558 e9/jump loop/disp32 + 6559 } + 6560 $emit-subx:end: + 6561 # . restore registers + 6562 5f/pop-to-edi + 6563 59/pop-to-ecx + 6564 58/pop-to-eax + 6565 # . epilogue + 6566 89/<- %esp 5/r32/ebp + 6567 5d/pop-to-ebp + 6568 c3/return + 6569 + 6570 emit-subx-function: # out: (addr buffered-file), f: (handle function) + 6571 # . prologue + 6572 55/push-ebp + 6573 89/<- %ebp 4/r32/esp + 6574 # some preprocessing + 6575 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) + 6576 # . save registers + 6577 50/push-eax + 6578 51/push-ecx + 6579 52/push-edx + 6580 57/push-edi + 6581 # edi = out + 6582 8b/-> *(ebp+8) 7/r32/edi + 6583 # ecx = f + 6584 8b/-> *(ebp+0xc) 1/r32/ecx + 6585 # var vars/edx: (stack (addr var) 256) + 6586 81 5/subop/subtract %esp 0x400/imm32 + 6587 68/push 0x400/imm32/length + 6588 68/push 0/imm32/top + 6589 89/<- %edx 4/r32/esp + 6590 # + 6591 (write-buffered %edi *ecx) + 6592 (write-buffered %edi ":\n") + 6593 # initialize some global state + 6594 c7 0/subop/copy *Curr-block-depth 1/imm32 + 6595 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 + 6596 # + 6597 (emit-subx-prologue %edi) + 6598 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body + 6599 (emit-subx-epilogue %edi) + 6600 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have + 6601 # been cleaned up + 6602 $emit-subx-function:end: + 6603 # . reclaim locals + 6604 81 0/subop/add %esp 408/imm32 + 6605 # . restore registers + 6606 5f/pop-to-edi + 6607 5a/pop-to-edx + 6608 59/pop-to-ecx + 6609 58/pop-to-eax + 6610 # . epilogue + 6611 89/<- %esp 5/r32/ebp + 6612 5d/pop-to-ebp + 6613 c3/return + 6614 + 6615 populate-mu-type-offsets-in-inouts: # f: (handle function) + 6616 # . prologue + 6617 55/push-ebp + 6618 89/<- %ebp 4/r32/esp + 6619 # . save registers + 6620 50/push-eax + 6621 51/push-ecx + 6622 52/push-edx + 6623 53/push-ebx + 6624 57/push-edi + 6625 # var next-offset/edx: int = 8 + 6626 ba/copy-to-edx 8/imm32 + 6627 # var curr/ecx: (handle list var) = f->inouts + 6628 8b/-> *(ebp+8) 1/r32/ecx + 6629 8b/-> *(ecx+8) 1/r32/ecx # Function-inouts + 6630 { + 6631 $populate-mu-type-offsets-in-inouts:loop: + 6632 81 7/subop/compare %ecx 0/imm32 + 6633 74/jump-if-= break/disp8 + 6634 # var v/ebx: (handle var) = curr->value + 6635 8b/-> *ecx 3/r32/ebx # List-value + 6636 # v->offset = next-offset + 6637 89/<- *(ebx+0xc) 2/r32/edx # Var-offset + 6638 # next-offset += size-of(v) + 6639 (size-of %ebx) # => eax + 6640 01/add %edx 0/r32/eax + 6641 # curr = curr->next + 6642 8b/-> *(ecx+4) 1/r32/ecx # List-next + 6643 eb/jump loop/disp8 + 6644 } + 6645 $populate-mu-type-offsets-in-inouts:end: + 6646 # . restore registers + 6647 5f/pop-to-edi + 6648 5b/pop-to-ebx + 6649 5a/pop-to-edx + 6650 59/pop-to-ecx + 6651 58/pop-to-eax + 6652 # . epilogue + 6653 89/<- %esp 5/r32/ebp + 6654 5d/pop-to-ebp + 6655 c3/return + 6656 + 6657 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) + 6658 # . prologue + 6659 55/push-ebp + 6660 89/<- %ebp 4/r32/esp + 6661 # . save registers + 6662 50/push-eax + 6663 51/push-ecx + 6664 52/push-edx + 6665 53/push-ebx + 6666 56/push-esi + 6667 # esi = stmts + 6668 8b/-> *(ebp+0xc) 6/r32/esi + 6669 # var var-seen?/edx: boolean <- copy false + 6670 ba/copy-to-edx 0/imm32/false + 6671 # + 6672 { + 6673 $emit-subx-stmt-list:loop: + 6674 81 7/subop/compare %esi 0/imm32 + 6675 0f 84/jump-if-= break/disp32 + 6676 # var curr-stmt/ecx = stmts->value + 6677 8b/-> *esi 1/r32/ecx # List-value + 6678 { + 6679 $emit-subx-stmt-list:check-for-block: + 6680 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag + 6681 75/jump-if-!= break/disp8 + 6682 $emit-subx-stmt-list:block: + 6683 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) + 6684 } + 6685 { + 6686 $emit-subx-stmt-list:check-for-stmt: + 6687 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag + 6688 0f 85/jump-if-!= break/disp32 + 6689 $emit-subx-stmt-list:stmt1: + 6690 { + 6691 (is-mu-branch? %ecx) # => eax + 6692 3d/compare-eax-and 0/imm32/false + 6693 0f 84/jump-if-= break/disp32 + 6694 $emit-subx-stmt-list:branch-stmt: + 6695 # if !var-seen? break + 6696 81 7/subop/compare %edx 0/imm32/false + 6697 0f 84/jump-if-= break/disp32 + 6698 $emit-subx-stmt-list:branch-stmt-and-var-seen: + 6699 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- + 6725 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- + 6740 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- + 6777 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- + 6796 } + 6797 $emit-subx-stmt-list:1-to-1: + 6798 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) + 6799 } + 6800 { + 6801 $emit-subx-stmt-list:check-for-var-def: + 6802 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag + 6803 75/jump-if-!= break/disp8 + 6804 $emit-subx-stmt-list:var-def: + 6805 (emit-subx-var-def *(ebp+8) %ecx) + 6806 (push *(ebp+0x10) *(ecx+4)) # Vardef-var + 6807 # var-seen? = true + 6808 ba/copy-to-edx 1/imm32/true + 6809 } + 6810 { + 6811 $emit-subx-stmt-list:check-for-reg-var-def: + 6812 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag + 6813 0f 85/jump-if-!= break/disp32 + 6814 $emit-subx-stmt-list:reg-var-def: + 6815 # TODO: ensure that there's exactly one output + 6816 (compute-reg-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) + 6817 # register variable definition + 6818 (push *(ebp+0x10) %eax) + 6819 # emit the instruction as usual + 6820 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) + 6821 # var-seen? = true + 6822 ba/copy-to-edx 1/imm32/true + 6823 } + 6824 $emit-subx-stmt-list:continue: + 6825 # TODO: raise an error on unrecognized Stmt-tag + 6826 8b/-> *(esi+4) 6/r32/esi # List-next + 6827 e9/jump loop/disp32 + 6828 } + 6829 $emit-subx-stmt-list:emit-cleanup: + 6830 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) + 6831 $emit-subx-stmt-list:cleanup: + 6832 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) + 6833 $emit-subx-stmt-list:end: + 6834 # . restore registers + 6835 5e/pop-to-esi + 6836 5b/pop-to-ebx + 6837 5a/pop-to-edx + 6838 59/pop-to-ecx + 6839 58/pop-to-eax + 6840 # . epilogue + 6841 89/<- %esp 5/r32/ebp + 6842 5d/pop-to-ebp + 6843 c3/return + 6844 + 6845 compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (handle reg-var-def), vars: (addr stack (handle var)) -> result/eax: (handle var) + 6846 # . prologue + 6847 55/push-ebp + 6848 89/<- %ebp 4/r32/esp + 6849 # . save registers + 6850 51/push-ecx + 6851 # ecx = stmt + 6852 8b/-> *(ebp+0xc) 1/r32/ecx + 6853 # var output/ecx: (handle var) = curr-stmt->outputs->value + 6854 8b/-> *(ecx+0xc) 1/r32/ecx # Regvardef-inouts + 6855 8b/-> *ecx 1/r32/ecx # List-value + 6856 # v->block-depth = *Curr-block-depth + 6857 8b/-> *Curr-block-depth 0/r32/eax + 6858 89/<- *(ecx+8) 0/r32/eax # Var-block-depth + 6859 # var reg/eax: (handle array byte) = output->register + 6860 8b/-> *(ecx+0x10) 0/r32/eax # Var-register + 6861 # ensure that output is in a register + 6862 3d/compare-eax-and 0/imm32 + 6863 0f 84/jump-if-= $compute-reg-and-maybe-emit-spill:abort/disp32 + 6864 # if already-spilled-this-block?(reg, vars) return + 6865 (already-spilled-this-block? %ecx *(ebp+0x10)) # => eax + 6866 3d/compare-eax-and 0/imm32/false + 6867 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 + 6868 # TODO: assert(size-of(output) == 4) + 6869 # *Curr-local-stack-offset -= 4 + 6870 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 + 6871 # emit spill + 6872 (emit-indent *(ebp+8) *Curr-block-depth) + 6873 (write-buffered *(ebp+8) "ff 6/subop/push %") + 6874 (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register + 6875 (write-buffered *(ebp+8) Newline) + 6876 $compute-reg-and-maybe-emit-spill:end: + 6877 # return output + 6878 89/<- %eax 1/r32/ecx + 6879 # . restore registers + 6880 59/pop-to-ecx + 6881 # . epilogue + 6882 89/<- %esp 5/r32/ebp + 6883 5d/pop-to-ebp + 6884 c3/return + 6885 + 6886 $compute-reg-and-maybe-emit-spill:abort: + 6887 # error("var '" var->name "' initialized from an instruction must live in a register\n") + 6888 (write-buffered Stderr "var '") + 6889 (write-buffered Stderr *eax) # Var-name + 6890 (write-buffered Stderr "' initialized from an instruction must live in a register\n") + 6891 (flush Stderr) + 6892 # . syscall(exit, 1) + 6893 bb/copy-to-ebx 1/imm32 + 6894 b8/copy-to-eax 1/imm32/exit + 6895 cd/syscall 0x80/imm8 + 6896 # never gets here + 6897 + 6898 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) + 6899 # . prologue + 6900 55/push-ebp + 6901 89/<- %ebp 4/r32/esp + 6902 # . save registers + 6903 50/push-eax + 6904 51/push-ecx + 6905 52/push-edx + 6906 # ecx = stmt + 6907 8b/-> *(ebp+0xc) 1/r32/ecx + 6908 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name + 6909 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 6910 8b/-> *edx 2/r32/edx # Stmt-var-value + 6911 8b/-> *edx 2/r32/edx # Var-name + 6912 # clean up until target block + 6913 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) + 6914 # emit jump to target block + 6915 (emit-indent *(ebp+8) *Curr-block-depth) + 6916 (write-buffered *(ebp+8) "e9/jump ") + 6917 (write-buffered *(ebp+8) %edx) + 6918 (string-starts-with? *(ecx+4) "break") + 6919 3d/compare-eax-and 0/imm32/false + 6920 { + 6921 74/jump-if-= break/disp8 + 6922 (write-buffered *(ebp+8) ":break/disp32\n") + 6923 } + 6924 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags + 6925 { + 6926 75/jump-if-!= break/disp8 + 6927 (write-buffered *(ebp+8) ":loop/disp32\n") + 6928 } + 6929 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: + 6930 # . restore registers + 6931 5a/pop-to-edx + 6932 59/pop-to-ecx + 6933 58/pop-to-eax + 6934 # . epilogue + 6935 89/<- %esp 5/r32/ebp + 6936 5d/pop-to-ebp + 6937 c3/return + 6938 + 6939 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean + 6940 # . prologue + 6941 55/push-ebp + 6942 89/<- %ebp 4/r32/esp + 6943 # . save registers + 6944 51/push-ecx + 6945 # ecx = stmt + 6946 8b/-> *(ebp+8) 1/r32/ecx + 6947 # if (stmt->operation starts with "loop") return true + 6948 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax + 6949 3d/compare-eax-and 0/imm32/false + 6950 75/jump-if-not-equal $is-mu-branch?:end/disp8 + 6951 # otherwise return (stmt->operation starts with "break") + 6952 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax + 6953 $is-mu-branch?:end: + 6954 # . restore registers + 6955 59/pop-to-ecx + 6956 # . epilogue + 6957 89/<- %esp 5/r32/ebp + 6958 5d/pop-to-ebp + 6959 c3/return + 6960 + 6961 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) + 6962 # . prologue + 6963 55/push-ebp + 6964 89/<- %ebp 4/r32/esp + 6965 # . save registers + 6966 50/push-eax + 6967 # eax = stmt + 6968 8b/-> *(ebp+0xc) 0/r32/eax + 6969 # + 6970 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) + 6971 (emit-indent *(ebp+8) *Curr-block-depth) + 6972 (write-buffered *(ebp+8) *eax) + 6973 (write-buffered *(ebp+8) " break/disp32\n") + 6974 $emit-reverse-break:end: + 6975 # . restore registers + 6976 58/pop-to-eax + 6977 # . epilogue + 6978 89/<- %esp 5/r32/ebp + 6979 5d/pop-to-ebp + 6980 c3/return + 6981 + 6982 == data + 6983 + 6984 Reverse-branch: # (table string string) + 6985 # a table is a stream + 6986 0xa0/imm32/write + 6987 0/imm32/read + 6988 0xa0/imm32/length + 6989 # data + 6990 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 + 6991 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 + 6992 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 + 6993 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 + 6994 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 + 6995 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 + 6996 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 + 6997 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 + 6998 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 + 6999 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 + 7000 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 + 7001 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 + 7002 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 + 7003 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 + 7004 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 + 7005 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 + 7006 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 + 7007 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 + 7008 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 + 7009 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 + 7010 + 7011 == code + 7012 + 7013 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) + 7014 # . prologue + 7015 55/push-ebp + 7016 89/<- %ebp 4/r32/esp + 7017 # . save registers + 7018 50/push-eax + 7019 51/push-ecx + 7020 52/push-edx + 7021 53/push-ebx + 7022 # ecx = vars + 7023 8b/-> *(ebp+0xc) 1/r32/ecx + 7024 # var eax: int = vars->top + 7025 8b/-> *ecx 0/r32/eax + 7026 # var min/ecx: (address (handle var)) = vars->data + 7027 81 0/subop/add %ecx 8/imm32 + 7028 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] + 7029 81 5/subop/subtract %eax 4/imm32 + 7030 8d/copy-address *(ecx+eax) 0/r32/eax + 7031 # edx = depth + 7032 8b/-> *(ebp+0x10) 2/r32/edx + 7033 { + 7034 $emit-unconditional-jump-to-depth:loop: + 7035 # if (curr < min) break + 7036 39/compare %eax 1/r32/ecx + 7037 0f 82/jump-if-addr< break/disp32 + 7038 # var v/ebx: (handle var) = *curr + 7039 8b/-> *eax 3/r32/ebx + 7040 # if (v->block-depth < until-block-depth) break + 7041 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7042 0f 8c/jump-if-< break/disp32 + 7043 { + 7044 $emit-unconditional-jump-to-depth:check: + 7045 # if v->block-depth != until-block-depth, continue + 7046 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7047 0f 85/jump-if-!= break/disp32 + 7048 $emit-unconditional-jump-to-depth:depth-found: + 7049 # if v is not a literal, continue + 7050 # . var eax: int = size-of(v) + 7051 50/push-eax + 7052 (size-of %ebx) # => eax + 7053 # . if (eax != 0) continue + 7054 3d/compare-eax-and 0/imm32 + 7055 58/pop-to-eax + 7056 # + 7057 0f 85/jump-if-!= break/disp32 + 7058 $emit-unconditional-jump-to-depth:label-found: + 7059 # emit unconditional jump, then return + 7060 (emit-indent *(ebp+8) *Curr-block-depth) + 7061 (write-buffered *(ebp+8) "e9/jump ") + 7062 (write-buffered *(ebp+8) *ebx) # Var-name + 7063 (write-buffered *(ebp+8) ":") + 7064 (write-buffered *(ebp+8) *(ebp+0x14)) + 7065 (write-buffered *(ebp+8) "/disp32\n") + 7066 eb/jump $emit-unconditional-jump-to-depth:end/disp8 + 7067 } + 7068 # curr -= 4 + 7069 2d/subtract-from-eax 4/imm32 + 7070 e9/jump loop/disp32 + 7071 } + 7072 # TODO: error if no label at 'depth' was found + 7073 $emit-unconditional-jump-to-depth:end: + 7074 # . restore registers + 7075 5b/pop-to-ebx + 7076 5a/pop-to-edx + 7077 59/pop-to-ecx + 7078 58/pop-to-eax + 7079 # . epilogue + 7080 89/<- %esp 5/r32/ebp + 7081 5d/pop-to-ebp + 7082 c3/return + 7083 + 7084 # emit clean-up code for 'vars' until some block depth + 7085 # doesn't actually modify 'vars' so we need traverse manually inside the stack + 7086 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int + 7087 # . prologue + 7088 55/push-ebp + 7089 89/<- %ebp 4/r32/esp + 7090 # . save registers + 7091 50/push-eax + 7092 51/push-ecx + 7093 52/push-edx + 7094 53/push-ebx + 7095 # ecx = vars + 7096 8b/-> *(ebp+0xc) 1/r32/ecx + 7097 # var eax: int = vars->top + 7098 8b/-> *ecx 0/r32/eax + 7099 # var min/ecx: (address (handle var)) = vars->data + 7100 81 0/subop/add %ecx 8/imm32 + 7101 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] + 7102 81 5/subop/subtract %eax 4/imm32 + 7103 8d/copy-address *(ecx+eax) 0/r32/eax + 7104 # edx = until-block-depth + 7105 8b/-> *(ebp+0x10) 2/r32/edx + 7106 { + 7107 $emit-cleanup-code-until-depth:loop: + 7108 # if (curr < min) break + 7109 39/compare %eax 1/r32/ecx + 7110 0f 82/jump-if-addr< break/disp32 + 7111 # var v/ebx: (handle var) = *curr + 7112 8b/-> *eax 3/r32/ebx + 7113 # if (v->block-depth < until-block-depth) break + 7114 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 7115 0f 8c/jump-if-< break/disp32 + 7116 # if v is in a register + 7117 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 7118 { + 7119 0f 84/jump-if-= break/disp32 + 7120 50/push-eax + 7121 { + 7122 $emit-cleanup-code-until-depth:check-for-previous-spill: + 7123 (same-register-spilled-before? %ebx *(ebp+0xc) %eax) # => eax + 7124 3d/compare-eax-and 0/imm32/false + 7125 0f 85/jump-if-!= break/disp32 + 7126 $emit-cleanup-code-until-depth:reclaim-var-in-register: + 7127 (emit-indent *(ebp+8) *Curr-block-depth) + 7128 (write-buffered *(ebp+8) "8f 0/subop/pop %") + 7129 (write-buffered *(ebp+8) *(ebx+0x10)) + 7130 (write-buffered *(ebp+8) Newline) + 7131 } + 7132 58/pop-to-eax + 7133 eb/jump $emit-cleanup-code-until-depth:continue/disp8 + 7134 } + 7135 # otherwise v is on the stack + 7136 { + 7137 75/jump-if-!= break/disp8 + 7138 $emit-cleanup-code-until-depth:reclaim-var-on-stack: + 7139 50/push-eax + 7140 (size-of %ebx) # => eax + 7141 # don't emit code for labels + 7142 3d/compare-eax-and 0/imm32 + 7143 74/jump-if-= break/disp8 + 7144 # + 7145 (emit-indent *(ebp+8) *Curr-block-depth) + 7146 (write-buffered *(ebp+8) "81 0/subop/add %esp ") + 7147 (print-int32-buffered *(ebp+8) %eax) + 7148 (write-buffered *(ebp+8) "/imm32\n") + 7149 58/pop-to-eax + 7150 } + 7151 $emit-cleanup-code-until-depth:continue: + 7152 # curr -= 4 + 7153 2d/subtract-from-eax 4/imm32 + 7154 e9/jump loop/disp32 + 7155 } + 7156 $emit-cleanup-code-until-depth:end: + 7157 # . restore registers + 7158 5b/pop-to-ebx + 7159 5a/pop-to-edx + 7160 59/pop-to-ecx + 7161 58/pop-to-eax + 7162 # . epilogue + 7163 89/<- %esp 5/r32/ebp + 7164 5d/pop-to-ebp + 7165 c3/return + 7166 + 7167 # emit clean-up code for 'vars' until a given label is encountered + 7168 # doesn't actually modify 'vars' so we need traverse manually inside the stack + 7169 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) + 7170 # . prologue + 7171 55/push-ebp + 7172 89/<- %ebp 4/r32/esp + 7173 # . save registers + 7174 50/push-eax + 7175 51/push-ecx + 7176 52/push-edx + 7177 53/push-ebx + 7178 # ecx = vars + 7179 8b/-> *(ebp+0xc) 1/r32/ecx + 7180 # var eax: int = vars->top + 7181 8b/-> *ecx 0/r32/eax + 7182 # var min/ecx: (address (handle var)) = vars->data + 7183 81 0/subop/add %ecx 8/imm32 + 7184 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] + 7185 81 5/subop/subtract %eax 4/imm32 + 7186 8d/copy-address *(ecx+eax) 2/r32/edx + 7187 { + 7188 $emit-cleanup-code-until-target:loop: + 7189 # if (curr < min) break + 7190 39/compare %edx 1/r32/ecx + 7191 0f 82/jump-if-addr< break/disp32 + 7192 # var v/ebx: (handle var) = *curr + 7193 8b/-> *edx 3/r32/ebx + 7194 # if (v->name == until-block-label) break + 7195 (string-equal? *ebx *(ebp+0x10)) # => eax + 7196 3d/compare-eax-and 0/imm32/false + 7197 0f 85/jump-if-!= break/disp32 + 7198 # if v is in a register + 7199 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register + 7200 { + 7201 74/jump-if-= break/disp8 + 7202 50/push-eax + 7203 { + 7204 $emit-cleanup-code-until-target:check-for-previous-spill: + 7205 (same-register-spilled-before? %ebx *(ebp+0xc) %edx) # => eax + 7206 3d/compare-eax-and 0/imm32/false + 7207 75/jump-if-!= break/disp8 + 7208 $emit-cleanup-code-until-target:reclaim-var-in-register: + 7209 (emit-indent *(ebp+8) *Curr-block-depth) + 7210 (write-buffered *(ebp+8) "8f 0/subop/pop %") + 7211 (write-buffered *(ebp+8) *(ebx+0x10)) + 7212 (write-buffered *(ebp+8) Newline) + 7213 } + 7214 58/pop-to-eax + 7215 eb/jump $emit-cleanup-code-until-target:continue/disp8 + 7216 } + 7217 # otherwise v is on the stack + 7218 { + 7219 75/jump-if-!= break/disp8 + 7220 $emit-cleanup-code-until-target:reclaim-var-on-stack: + 7221 (size-of %ebx) # => eax + 7222 # don't emit code for labels + 7223 3d/compare-eax-and 0/imm32 + 7224 74/jump-if-= break/disp8 + 7225 # + 7226 (emit-indent *(ebp+8) *Curr-block-depth) + 7227 (write-buffered *(ebp+8) "81 0/subop/add %esp ") + 7228 (print-int32-buffered *(ebp+8) %eax) + 7229 (write-buffered *(ebp+8) "/imm32\n") + 7230 } + 7231 $emit-cleanup-code-until-target:continue: + 7232 # curr -= 4 + 7233 81 5/subop/subtract %edx 4/imm32 + 7234 e9/jump loop/disp32 + 7235 } + 7236 $emit-cleanup-code-until-target:end: + 7237 # . restore registers + 7238 5b/pop-to-ebx + 7239 5a/pop-to-edx + 7240 59/pop-to-ecx + 7241 58/pop-to-eax + 7242 # . epilogue + 7243 89/<- %esp 5/r32/ebp + 7244 5d/pop-to-ebp + 7245 c3/return + 7246 + 7247 # is there already a var with the same block-depth and register as 'v' on the 'vars' stack? + 7248 # v is guaranteed not to be within vars + 7249 already-spilled-this-block?: # v: (handle var), vars: (addr stack (handle var)) -> result/eax: boolean + 7250 # . prologue + 7251 55/push-ebp + 7252 89/<- %ebp 4/r32/esp + 7253 # . save registers + 7254 51/push-ecx + 7255 52/push-edx + 7256 53/push-ebx + 7257 56/push-esi + 7258 57/push-edi + 7259 # ecx = vars + 7260 8b/-> *(ebp+0xc) 1/r32/ecx + 7261 # var eax: int = vars->top + 7262 8b/-> *ecx 0/r32/eax + 7263 # var min/ecx: (address (handle var)) = vars->data + 7264 81 0/subop/add %ecx 8/imm32 + 7265 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] + 7266 81 5/subop/subtract %eax 4/imm32 + 7267 8d/copy-address *(ecx+eax) 2/r32/edx + 7268 # var depth/ebx: int = v->block-depth + 7269 8b/-> *(ebp+8) 3/r32/ebx + 7270 8b/-> *(ebx+8) 3/r32/ebx # Var-block-depth + 7271 # var needle/esi: (handle array byte) = v->register + 7272 8b/-> *(ebp+8) 6/r32/esi + 7273 8b/-> *(esi+0x10) 6/r32/esi # Var-register + 7274 { + 7275 $already-spilled-this-block?:loop: + 7276 # if (curr < min) break + 7277 39/compare %edx 1/r32/ecx + 7278 0f 82/jump-if-addr< break/disp32 + 7279 # var cand/edi: (handle var) = *curr + 7280 8b/-> *edx 7/r32/edi + 7281 # if (cand->block-depth < depth) break + 7282 39/compare *(edi+8) 3/r32/ebx # Var-block-depth + 7283 0f 8c/jump-if-< break/disp32 + 7284 # var cand-reg/edi: (handle array byte) = cand->reg + 7285 8b/-> *(edi+0x10) 7/r32/edi + 7286 # if (cand-reg == null) continue + 7287 { + 7288 $already-spilled-this-block?:check-reg: + 7289 81 7/subop/compare %edi 0/imm32 + 7290 74/jump-if-= break/disp8 + 7291 # if (cand-reg == needle) return true + 7292 (string-equal? %esi %edi) # => eax + 7293 3d/compare-eax-and 0/imm32/false + 7294 74/jump-if-= break/disp8 + 7295 b8/copy-to-eax 1/imm32/true + 7296 eb/jump $already-spilled-this-block?:end/disp8 + 7297 } + 7298 $already-spilled-this-block?:continue: + 7299 # curr -= 4 + 7300 81 5/subop/subtract %edx 4/imm32 + 7301 e9/jump loop/disp32 + 7302 } + 7303 # return false + 7304 b8/copy-to-eax 0/imm32/false + 7305 $already-spilled-this-block?:end: + 7306 # . restore registers + 7307 5f/pop-to-edi + 7308 5e/pop-to-esi + 7309 5b/pop-to-ebx + 7310 5a/pop-to-edx + 7311 59/pop-to-ecx + 7312 # . epilogue + 7313 89/<- %esp 5/r32/ebp + 7314 5d/pop-to-ebp + 7315 c3/return + 7316 + 7317 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? + 7318 # v is guaranteed to be within vars + 7319 # 'start' is provided as an optimization, a pointer within vars + 7320 # *start == v + 7321 same-register-spilled-before?: # v: (handle var), vars: (addr stack (handle var)), start: (addr (handle var)) -> result/eax: boolean + 7322 # . prologue + 7323 55/push-ebp + 7324 89/<- %ebp 4/r32/esp + 7325 # . save registers + 7326 51/push-ecx + 7327 52/push-edx + 7328 53/push-ebx + 7329 56/push-esi + 7330 57/push-edi + 7331 # ecx = v + 7332 8b/-> *(ebp+8) 1/r32/ecx + 7333 # var reg/edx: (handle array byte) = v->register + 7334 8b/-> *(ecx+0x10) 2/r32/edx # Var-register + 7335 # var depth/ebx: int = v->block-depth + 7336 8b/-> *(ecx+8) 3/r32/ebx # Var-block-depth + 7337 # var min/ecx: (address (handle var)) = vars->data + 7338 8b/-> *(ebp+0xc) 1/r32/ecx + 7339 81 0/subop/add %ecx 8/imm32 + 7340 # TODO: check that start >= min and start < &vars->data[top] + 7341 # TODO: check that *start == v + 7342 # var curr/esi: (address (handle var)) = start + 7343 8b/-> *(ebp+0x10) 6/r32/esi + 7344 # curr -= 4 + 7345 81 5/subop/subtract %esi 4/imm32 + 7346 { + 7347 $same-register-spilled-before?:loop: + 7348 # if (curr < min) break + 7349 39/compare %esi 1/r32/ecx + 7350 0f 82/jump-if-addr< break/disp32 + 7351 # var x/eax: (handle var) = *curr + 7352 8b/-> *esi 0/r32/eax + 7353 # if (x->block-depth < depth) break + 7354 39/compare *(eax+8) 3/r32/ebx # Var-block-depth + 7355 0f 8c/jump-if-< break/disp32 + 7356 # if (x->register == 0) continue + 7357 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register + 7358 74/jump-if-= $same-register-spilled-before?:continue/disp8 + 7359 # if (x->register == reg) return true + 7360 (string-equal? *(eax+0x10) %edx) # Var-register => eax + 7361 3d/compare-eax-and 0/imm32/false + 7362 75/jump-if-!= $same-register-spilled-before?:end/disp8 + 7363 $same-register-spilled-before?:continue: + 7364 # curr -= 4 + 7365 81 5/subop/subtract %esi 4/imm32 + 7366 e9/jump loop/disp32 + 7367 } + 7368 $same-register-spilled-before?:false: + 7369 b8/copy-to-eax 0/imm32/false + 7370 $same-register-spilled-before?:end: 7371 # . restore registers - 7372 5e/pop-to-esi - 7373 59/pop-to-ecx - 7374 58/pop-to-eax - 7375 # . epilogue - 7376 89/<- %esp 5/r32/ebp - 7377 5d/pop-to-ebp - 7378 c3/return - 7379 - 7380 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt) - 7381 # . prologue - 7382 55/push-ebp - 7383 89/<- %ebp 4/r32/esp - 7384 # . save registers - 7385 50/push-eax - 7386 51/push-ecx - 7387 52/push-edx - 7388 # eax = stmt - 7389 8b/-> *(ebp+0xc) 0/r32/eax - 7390 # var v/ecx: (handle var) - 7391 8b/-> *(eax+4) 1/r32/ecx # Vardef-var - 7392 # v->block-depth = *Curr-block-depth - 7393 8b/-> *Curr-block-depth 0/r32/eax - 7394 89/<- *(ecx+8) 0/r32/eax # Var-block-depth - 7395 # var n/edx: int = size-of(stmt->var) - 7396 (size-of %ecx) # => eax - 7397 89/<- %edx 0/r32/eax - 7398 # *Curr-local-stack-offset -= n - 7399 29/subtract-from *Curr-local-stack-offset 2/r32/edx - 7400 # v->offset = *Curr-local-stack-offset - 7401 8b/-> *Curr-local-stack-offset 0/r32/eax - 7402 89/<- *(ecx+0xc) 0/r32/eax # Var-offset - 7403 # if v is an array, do something special - 7404 { - 7405 (is-mu-array? *(ecx+4)) # Var-type => eax - 7406 3d/compare-eax-and 0/imm32/false - 7407 0f 84/jump-if-= break/disp32 - 7408 # var array-size-without-length/edx: int = n-4 - 7409 81 5/subop/subtract %edx 4/imm32 - 7410 (emit-indent *(ebp+8) *Curr-block-depth) - 7411 (write-buffered *(ebp+8) "(push-n-zero-bytes ") - 7412 (print-int32-buffered *(ebp+8) %edx) - 7413 (write-buffered *(ebp+8) ")\n") - 7414 (emit-indent *(ebp+8) *Curr-block-depth) - 7415 (write-buffered *(ebp+8) "68/push ") - 7416 (print-int32-buffered *(ebp+8) %edx) - 7417 (write-buffered *(ebp+8) "/imm32\n") - 7418 eb/jump $emit-subx-var-def:end/disp8 - 7419 } - 7420 # while n > 0 - 7421 { - 7422 81 7/subop/compare %edx 0/imm32 - 7423 7e/jump-if-<= break/disp8 - 7424 (emit-indent *(ebp+8) *Curr-block-depth) - 7425 (write-buffered *(ebp+8) "68/push 0/imm32\n") - 7426 # n -= 4 - 7427 81 5/subop/subtract %edx 4/imm32 - 7428 # - 7429 eb/jump loop/disp8 - 7430 } - 7431 $emit-subx-var-def:end: - 7432 # . restore registers - 7433 5a/pop-to-edx - 7434 59/pop-to-ecx - 7435 58/pop-to-eax - 7436 # . epilogue - 7437 89/<- %esp 5/r32/ebp - 7438 5d/pop-to-ebp - 7439 c3/return - 7440 - 7441 emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (handle primitive), functions: (handle function) - 7442 # . prologue - 7443 55/push-ebp - 7444 89/<- %ebp 4/r32/esp - 7445 # . save registers - 7446 50/push-eax - 7447 51/push-ecx - 7448 # - some special-case primitives that don't actually use the 'primitives' data structure - 7449 # ecx = stmt - 7450 8b/-> *(ebp+0xc) 1/r32/ecx - 7451 # array length - 7452 { - 7453 # if (!string-equal?(stmt->operation, "length")) break - 7454 (string-equal? *(ecx+4) "length") # Stmt1-operation => eax - 7455 3d/compare-eax-and 0/imm32 - 7456 0f 84/jump-if-= break/disp32 - 7457 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc)) - 7458 e9/jump $emit-subx-stmt:end/disp32 - 7459 } - 7460 # index into array - 7461 { - 7462 # if (!string-equal?(var->operation, "index")) break - 7463 (string-equal? *(ecx+4) "index") # Stmt1-operation => eax - 7464 3d/compare-eax-and 0/imm32 - 7465 0f 84/jump-if-= break/disp32 - 7466 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc)) - 7467 e9/jump $emit-subx-stmt:end/disp32 - 7468 } - 7469 # compute-offset for index into array - 7470 { - 7471 # if (!string-equal?(var->operation, "compute-offset")) break - 7472 (string-equal? *(ecx+4) "compute-offset") # Stmt1-operation => eax - 7473 3d/compare-eax-and 0/imm32 - 7474 0f 84/jump-if-= break/disp32 - 7475 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc)) - 7476 e9/jump $emit-subx-stmt:end/disp32 - 7477 } - 7478 # get field from record - 7479 { - 7480 # if (!string-equal?(var->operation, "get")) break - 7481 (string-equal? *(ecx+4) "get") # Stmt1-operation => eax - 7482 3d/compare-eax-and 0/imm32 - 7483 0f 84/jump-if-= break/disp32 - 7484 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) - 7485 e9/jump $emit-subx-stmt:end/disp32 - 7486 } - 7487 # - if stmt matches a primitive, emit it - 7488 { - 7489 $emit-subx-stmt:check-for-primitive: - 7490 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax - 7491 3d/compare-eax-and 0/imm32 - 7492 74/jump-if-= break/disp8 - 7493 $emit-subx-stmt:primitive: - 7494 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr - 7495 e9/jump $emit-subx-stmt:end/disp32 - 7496 } - 7497 # - if stmt matches a function, emit a call to it + 7372 5f/pop-to-edi + 7373 5e/pop-to-esi + 7374 5b/pop-to-ebx + 7375 5a/pop-to-edx + 7376 59/pop-to-ecx + 7377 # . epilogue + 7378 89/<- %esp 5/r32/ebp + 7379 5d/pop-to-ebp + 7380 c3/return + 7381 + 7382 # clean up global state for 'vars' until some block depth + 7383 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int + 7384 # . prologue + 7385 55/push-ebp + 7386 89/<- %ebp 4/r32/esp + 7387 # . save registers + 7388 50/push-eax + 7389 51/push-ecx + 7390 56/push-esi + 7391 # esi = vars + 7392 8b/-> *(ebp+8) 6/r32/esi + 7393 # ecx = until-block-depth + 7394 8b/-> *(ebp+0xc) 1/r32/ecx + 7395 { + 7396 $clean-up-blocks:reclaim-loop: + 7397 # if (vars->top <= 0) break + 7398 81 7/subop/compare *esi 0/imm32 # Stack-top + 7399 7e/jump-if-<= break/disp8 + 7400 # var v/eax: (handle var) = top(vars) + 7401 (top %esi) # => eax + 7402 # if (v->block-depth < until-block-depth) break + 7403 39/compare *(eax+8) 1/r32/ecx # Var-block-depth + 7404 7c/jump-if-< break/disp8 + 7405 # if v is on the stack, update Curr-local-stack-offset + 7406 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register + 7407 { + 7408 75/jump-if-!= break/disp8 + 7409 $clean-up-blocks:reclaim-var-on-stack: + 7410 (size-of %eax) # => eax + 7411 01/add *Curr-local-stack-offset 0/r32/eax + 7412 } + 7413 (pop %esi) + 7414 e9/jump loop/disp32 + 7415 } + 7416 $clean-up-blocks:end: + 7417 # . restore registers + 7418 5e/pop-to-esi + 7419 59/pop-to-ecx + 7420 58/pop-to-eax + 7421 # . epilogue + 7422 89/<- %esp 5/r32/ebp + 7423 5d/pop-to-ebp + 7424 c3/return + 7425 + 7426 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt) + 7427 # . prologue + 7428 55/push-ebp + 7429 89/<- %ebp 4/r32/esp + 7430 # . save registers + 7431 50/push-eax + 7432 51/push-ecx + 7433 52/push-edx + 7434 # eax = stmt + 7435 8b/-> *(ebp+0xc) 0/r32/eax + 7436 # var v/ecx: (handle var) + 7437 8b/-> *(eax+4) 1/r32/ecx # Vardef-var + 7438 # v->block-depth = *Curr-block-depth + 7439 8b/-> *Curr-block-depth 0/r32/eax + 7440 89/<- *(ecx+8) 0/r32/eax # Var-block-depth + 7441 # var n/edx: int = size-of(stmt->var) + 7442 (size-of %ecx) # => eax + 7443 89/<- %edx 0/r32/eax + 7444 # *Curr-local-stack-offset -= n + 7445 29/subtract-from *Curr-local-stack-offset 2/r32/edx + 7446 # v->offset = *Curr-local-stack-offset + 7447 8b/-> *Curr-local-stack-offset 0/r32/eax + 7448 89/<- *(ecx+0xc) 0/r32/eax # Var-offset + 7449 # if v is an array, do something special + 7450 { + 7451 (is-mu-array? *(ecx+4)) # Var-type => eax + 7452 3d/compare-eax-and 0/imm32/false + 7453 0f 84/jump-if-= break/disp32 + 7454 # var array-size-without-length/edx: int = n-4 + 7455 81 5/subop/subtract %edx 4/imm32 + 7456 (emit-indent *(ebp+8) *Curr-block-depth) + 7457 (write-buffered *(ebp+8) "(push-n-zero-bytes ") + 7458 (print-int32-buffered *(ebp+8) %edx) + 7459 (write-buffered *(ebp+8) ")\n") + 7460 (emit-indent *(ebp+8) *Curr-block-depth) + 7461 (write-buffered *(ebp+8) "68/push ") + 7462 (print-int32-buffered *(ebp+8) %edx) + 7463 (write-buffered *(ebp+8) "/imm32\n") + 7464 eb/jump $emit-subx-var-def:end/disp8 + 7465 } + 7466 # while n > 0 + 7467 { + 7468 81 7/subop/compare %edx 0/imm32 + 7469 7e/jump-if-<= break/disp8 + 7470 (emit-indent *(ebp+8) *Curr-block-depth) + 7471 (write-buffered *(ebp+8) "68/push 0/imm32\n") + 7472 # n -= 4 + 7473 81 5/subop/subtract %edx 4/imm32 + 7474 # + 7475 eb/jump loop/disp8 + 7476 } + 7477 $emit-subx-var-def:end: + 7478 # . restore registers + 7479 5a/pop-to-edx + 7480 59/pop-to-ecx + 7481 58/pop-to-eax + 7482 # . epilogue + 7483 89/<- %esp 5/r32/ebp + 7484 5d/pop-to-ebp + 7485 c3/return + 7486 + 7487 emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (handle primitive), functions: (handle function) + 7488 # . prologue + 7489 55/push-ebp + 7490 89/<- %ebp 4/r32/esp + 7491 # . save registers + 7492 50/push-eax + 7493 51/push-ecx + 7494 # - some special-case primitives that don't actually use the 'primitives' data structure + 7495 # ecx = stmt + 7496 8b/-> *(ebp+0xc) 1/r32/ecx + 7497 # array length 7498 { - 7499 $emit-subx-stmt:check-for-call: - 7500 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax + 7499 # if (!string-equal?(stmt->operation, "length")) break + 7500 (string-equal? *(ecx+4) "length") # Stmt1-operation => eax 7501 3d/compare-eax-and 0/imm32 - 7502 74/jump-if-= break/disp8 - 7503 $emit-subx-stmt:call: - 7504 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr - 7505 e9/jump $emit-subx-stmt:end/disp32 - 7506 } - 7507 # otherwise, assume it's a SubX function (TODO: how to type-check?!) - 7508 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) - 7509 $emit-subx-stmt:end: - 7510 # . restore registers - 7511 59/pop-to-ecx - 7512 58/pop-to-eax - 7513 # . epilogue - 7514 89/<- %esp 5/r32/ebp - 7515 5d/pop-to-ebp - 7516 c3/return - 7517 - 7518 translate-mu-length-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7519 # . prologue - 7520 55/push-ebp - 7521 89/<- %ebp 4/r32/esp - 7522 # . save registers - 7523 50/push-eax - 7524 51/push-ecx - 7525 # ecx = stmt - 7526 8b/-> *(ebp+0xc) 1/r32/ecx - 7527 # - 7528 (emit-indent *(ebp+8) *Curr-block-depth) - 7529 (write-buffered *(ebp+8) "8b/copy-from *") - 7530 # var base/eax: (handle var) = inouts[0] - 7531 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 7532 8b/-> *eax 0/r32/eax # Stmt-var-value - 7533 # if base is an (address array ...) in a register + 7502 0f 84/jump-if-= break/disp32 + 7503 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc)) + 7504 e9/jump $emit-subx-stmt:end/disp32 + 7505 } + 7506 # index into array + 7507 { + 7508 # if (!string-equal?(var->operation, "index")) break + 7509 (string-equal? *(ecx+4) "index") # Stmt1-operation => eax + 7510 3d/compare-eax-and 0/imm32 + 7511 0f 84/jump-if-= break/disp32 + 7512 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc)) + 7513 e9/jump $emit-subx-stmt:end/disp32 + 7514 } + 7515 # compute-offset for index into array + 7516 { + 7517 # if (!string-equal?(var->operation, "compute-offset")) break + 7518 (string-equal? *(ecx+4) "compute-offset") # Stmt1-operation => eax + 7519 3d/compare-eax-and 0/imm32 + 7520 0f 84/jump-if-= break/disp32 + 7521 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc)) + 7522 e9/jump $emit-subx-stmt:end/disp32 + 7523 } + 7524 # get field from record + 7525 { + 7526 # if (!string-equal?(var->operation, "get")) break + 7527 (string-equal? *(ecx+4) "get") # Stmt1-operation => eax + 7528 3d/compare-eax-and 0/imm32 + 7529 0f 84/jump-if-= break/disp32 + 7530 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) + 7531 e9/jump $emit-subx-stmt:end/disp32 + 7532 } + 7533 # - if stmt matches a primitive, emit it 7534 { - 7535 81 7/subop/compare *(eax+0x10)) 0/imm32 # Var-register - 7536 74/jump-if-= break/disp8 - 7537 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register - 7538 eb/jump $translate-mu-length-stmt:emit-output/disp8 - 7539 } - 7540 # otherwise if base is an (array ...) on the stack - 7541 { - 7542 81 7/subop/compare *(eax+0xc)) 0/imm32 # Var-offset - 7543 74/jump-if-= break/disp8 - 7544 (write-buffered *(ebp+8) "(ebp+") - 7545 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset - 7546 (write-buffered *(ebp+8) ")") - 7547 } - 7548 $translate-mu-length-stmt:emit-output: - 7549 (write-buffered *(ebp+8) " ") - 7550 # outputs[0] "/r32" - 7551 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7552 8b/-> *eax 0/r32/eax # Stmt-var-value - 7553 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7554 (print-int32-buffered *(ebp+8) *eax) - 7555 (write-buffered *(ebp+8) "/r32\n") - 7556 $translate-mu-length-stmt:end: - 7557 # . restore registers - 7558 59/pop-to-ecx - 7559 58/pop-to-eax - 7560 # . epilogue - 7561 89/<- %esp 5/r32/ebp - 7562 5d/pop-to-ebp - 7563 c3/return - 7564 - 7565 translate-mu-index-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7566 # . prologue - 7567 55/push-ebp - 7568 89/<- %ebp 4/r32/esp - 7569 # . save registers + 7535 $emit-subx-stmt:check-for-primitive: + 7536 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax + 7537 3d/compare-eax-and 0/imm32 + 7538 74/jump-if-= break/disp8 + 7539 $emit-subx-stmt:primitive: + 7540 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr + 7541 e9/jump $emit-subx-stmt:end/disp32 + 7542 } + 7543 # - if stmt matches a function, emit a call to it + 7544 { + 7545 $emit-subx-stmt:check-for-call: + 7546 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax + 7547 3d/compare-eax-and 0/imm32 + 7548 74/jump-if-= break/disp8 + 7549 $emit-subx-stmt:call: + 7550 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr + 7551 e9/jump $emit-subx-stmt:end/disp32 + 7552 } + 7553 # otherwise, assume it's a SubX function (TODO: how to type-check?!) + 7554 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) + 7555 $emit-subx-stmt:end: + 7556 # . restore registers + 7557 59/pop-to-ecx + 7558 58/pop-to-eax + 7559 # . epilogue + 7560 89/<- %esp 5/r32/ebp + 7561 5d/pop-to-ebp + 7562 c3/return + 7563 + 7564 translate-mu-length-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7565 # . prologue + 7566 55/push-ebp + 7567 89/<- %ebp 4/r32/esp + 7568 # . save registers + 7569 50/push-eax 7570 51/push-ecx - 7571 # var base/ecx: (handle var) = stmt->inouts[0] + 7571 # ecx = stmt 7572 8b/-> *(ebp+0xc) 1/r32/ecx - 7573 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 7574 8b/-> *ecx 1/r32/ecx # Stmt-var-value - 7575 # if (var->register) do one thing - 7576 { - 7577 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register - 7578 74/jump-if-= break/disp8 - 7579 # TODO: ensure there's no dereference - 7580 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc)) - 7581 eb/jump $translate-mu-index-stmt:end/disp8 - 7582 } - 7583 # if (var->offset) do a different thing - 7584 { - 7585 81 7/subop/compare *(ecx+0xc) 0/imm32 # Var-offset - 7586 74/jump-if-= break/disp8 - 7587 # TODO: ensure there's no dereference - 7588 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc)) - 7589 eb/jump $translate-mu-index-stmt:end/disp8 - 7590 } - 7591 $translate-mu-index-stmt:end: - 7592 # . restore registers - 7593 59/pop-to-ecx - 7594 # . epilogue - 7595 89/<- %esp 5/r32/ebp - 7596 5d/pop-to-ebp - 7597 c3/return - 7598 - 7599 $translate-mu-index-stmt-with-array:error1: - 7600 (write-buffered Stderr "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") - 7601 (flush Stderr) - 7602 # . syscall(exit, 1) - 7603 bb/copy-to-ebx 1/imm32 - 7604 b8/copy-to-eax 1/imm32/exit - 7605 cd/syscall 0x80/imm8 - 7606 # never gets here - 7607 - 7608 $translate-mu-index-stmt-with-array:error2: - 7609 (write-buffered Stderr "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") - 7610 (flush Stderr) - 7611 # . syscall(exit, 1) - 7612 bb/copy-to-ebx 1/imm32 - 7613 b8/copy-to-eax 1/imm32/exit - 7614 cd/syscall 0x80/imm8 - 7615 # never gets here - 7616 - 7617 translate-mu-index-stmt-with-array-in-register: # out: (address buffered-file), stmt: (handle stmt) - 7618 # . prologue - 7619 55/push-ebp - 7620 89/<- %ebp 4/r32/esp - 7621 # . save registers - 7622 50/push-eax - 7623 51/push-ecx - 7624 52/push-edx - 7625 53/push-ebx - 7626 # - 7627 (emit-indent *(ebp+8) *Curr-block-depth) - 7628 (write-buffered *(ebp+8) "8d/copy-address *(") - 7629 # TODO: ensure inouts[0] is in a register and not dereferenced - 7630 $translate-mu-index-stmt-with-array-in-register:emit-base: - 7631 # ecx = stmt - 7632 8b/-> *(ebp+0xc) 1/r32/ecx - 7633 # var base/ebx: (handle var) = inouts[0] - 7634 8b/-> *(ecx+8) 3/r32/ebx # Stmt1-inouts - 7635 8b/-> *ebx 3/r32/ebx # Stmt-var-value - 7636 # print base->register " + " - 7637 (write-buffered *(ebp+8) *(ebx+0x10)) # Var-register - 7638 # - 7639 (write-buffered *(ebp+8) " + ") - 7640 # var index/edx: (handle var) = inouts[1] - 7641 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 7642 8b/-> *(edx+4) 2/r32/edx # Stmt-var-next - 7643 8b/-> *edx 2/r32/edx # Stmt-var-value - 7644 # if index->register - 7645 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register - 7646 { - 7647 0f 84/jump-if-= break/disp32 - 7648 $translate-mu-index-stmt-with-array-in-register:emit-register-index: - 7649 # if index is an int - 7650 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax - 7651 3d/compare-eax-and 0/imm32/false - 7652 { - 7653 0f 84/jump-if-= break/disp32 - 7654 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: - 7655 # print index->register "<<" log2(size-of(element(base->type))) " + 4) " - 7656 # . index->register "<<" - 7657 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7658 (write-buffered *(ebp+8) "<<") - 7659 # . log2(size-of(element(base->type))) - 7660 # TODO: ensure size is a power of 2 - 7661 (array-element-type-id %ebx) # => eax - 7662 (size-of-type-id %eax) # => eax - 7663 (num-shift-rights %eax) # => eax - 7664 (print-int32-buffered *(ebp+8) %eax) - 7665 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 - 7666 } - 7667 # if index->type is any other atom, abort - 7668 8b/-> *(edx+4) 0/r32/eax # Var-type - 7669 8b/-> *eax 0/r32/eax # Tree-left or Atom-value - 7670 3b/compare 0/r32/eax *Max-type-id - 7671 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 - 7672 # if index has type (offset ...) - 7673 (is-simple-mu-type? %eax 7) # offset => eax - 7674 3d/compare-eax-and 0/imm32/false - 7675 { - 7676 0f 84/jump-if-= break/disp32 - 7677 # print index->register " + 4) " - 7678 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: - 7679 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7680 } - 7681 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: - 7682 (write-buffered *(ebp+8) " + 4) ") - 7683 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 - 7684 } - 7685 # otherwise if index is a literal - 7686 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax - 7687 3d/compare-eax-and 0/imm32/false - 7688 { - 7689 0f 84/jump-if-= break/disp32 - 7690 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: - 7691 # var index-value/edx: int = parse-hex-int(index->name) - 7692 (parse-hex-int *edx) # Var-name => eax - 7693 89/<- %edx 0/r32/eax - 7694 # offset = idx-value * size-of(element(base->type)) - 7695 (array-element-type-id %ebx) # => eax - 7696 (size-of-type-id %eax) # => eax - 7697 f7 4/subop/multiply-into-eax %edx # clobbers edx - 7698 # offset += 4 for array size - 7699 05/add-to-eax 4/imm32 - 7700 # TODO: check edx for overflow - 7701 # print offset - 7702 (print-int32-buffered *(ebp+8) %eax) - 7703 (write-buffered *(ebp+8) ") ") - 7704 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 - 7705 } - 7706 # otherwise abort - 7707 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 - 7708 $translate-mu-index-stmt-with-array-in-register:emit-output: - 7709 # outputs[0] "/r32" - 7710 8b/-> *(ebp+0xc) 1/r32/ecx - 7711 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7712 8b/-> *eax 0/r32/eax # Stmt-var-value - 7713 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7714 (print-int32-buffered *(ebp+8) *eax) - 7715 (write-buffered *(ebp+8) "/r32\n") - 7716 $translate-mu-index-stmt-with-array-in-register:end: - 7717 # . restore registers - 7718 5b/pop-to-ebx - 7719 5a/pop-to-edx - 7720 59/pop-to-ecx - 7721 58/pop-to-eax - 7722 # . epilogue - 7723 89/<- %esp 5/r32/ebp - 7724 5d/pop-to-ebp - 7725 c3/return - 7726 - 7727 translate-mu-index-stmt-with-array-on-stack: # out: (address buffered-file), stmt: (handle stmt) - 7728 # . prologue - 7729 55/push-ebp - 7730 89/<- %ebp 4/r32/esp - 7731 # . save registers - 7732 50/push-eax - 7733 51/push-ecx - 7734 52/push-edx - 7735 53/push-ebx - 7736 # - 7737 (emit-indent *(ebp+8) *Curr-block-depth) - 7738 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") - 7739 # var curr/eax = stmt->inouts - 7740 8b/-> *(ebp+0xc) 0/r32/eax - 7741 # var base/ecx: (handle var) = stmt->inouts[0] - 7742 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts - 7743 8b/-> *eax 1/r32/ecx # Stmt-var-value - 7744 # curr = curr->next - 7745 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 7746 # var index/edx: (handle var) = stmt->inouts[1] - 7747 8b/-> *eax 2/r32/edx # Stmt-var-value - 7748 # if index->register - 7749 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register - 7750 { - 7751 0f 84/jump-if-= break/disp32 - 7752 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: - 7753 # if index is an int - 7754 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax - 7755 3d/compare-eax-and 0/imm32/false - 7756 { - 7757 0f 84/jump-if-= break/disp32 - 7758 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: - 7759 # print index->register "<<" log2(size-of(element-type(base))) " + " base->offset+4 - 7760 # . inouts[1]->register "<<" - 7761 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7762 (write-buffered *(ebp+8) "<<") - 7763 # . log2(size-of(element(base))) - 7764 # TODO: ensure size is a power of 2 - 7765 (array-element-type-id %ecx) # => eax - 7766 (size-of-type-id %eax) # => eax - 7767 (num-shift-rights %eax) # => eax - 7768 (print-int32-buffered *(ebp+8) %eax) - 7769 # - 7770 (write-buffered *(ebp+8) " + ") - 7771 # - 7772 8b/-> *(ecx+0xc) 0/r32/eax # Var-offset - 7773 05/add-to-eax 4/imm32 - 7774 (print-int32-buffered *(ebp+8) %eax) - 7775 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 - 7776 } - 7777 # if index->type is any other atom, abort - 7778 8b/-> *(edx+4) 0/r32/eax # Var-type - 7779 8b/-> *eax 0/r32/eax # Tree-left or Atom-value - 7780 3b/compare 0/r32/eax *Max-type-id - 7781 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 - 7782 # if index has type (offset ...) - 7783 (is-simple-mu-type? %eax 7) # offset => eax - 7784 3d/compare-eax-and 0/imm32/false - 7785 { - 7786 0f 84/jump-if-= break/disp32 - 7787 # print index->register - 7788 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: - 7789 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register - 7790 } - 7791 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: - 7792 (write-buffered *(ebp+8) ") ") - 7793 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 - 7794 } - 7795 # otherwise if index is a literal - 7796 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax - 7797 3d/compare-eax-and 0/imm32/false - 7798 { - 7799 0f 84/jump-if-= break/disp32 - 7800 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: - 7801 # var idx-value/edx: int = parse-hex-int(index->name) - 7802 (parse-hex-int *edx) # Var-name => eax - 7803 89/<- %ebx 0/r32/eax - 7804 # offset = idx-value * size-of(element-type(base->type)) - 7805 (array-element-type-id %ecx) # => eax - 7806 (size-of-type-id %eax) # => eax - 7807 f7 4/subop/multiply-into-eax %ebx # clobbers edx - 7808 # offset += base->offset - 7809 03/add-to 0/r32/eax *(ecx+0xc) # Var-offset - 7810 # offset += 4 for array size - 7811 05/add-to-eax 4/imm32 - 7812 # TODO: check edx for overflow - 7813 # print offset - 7814 (print-int32-buffered *(ebp+8) %eax) - 7815 (write-buffered *(ebp+8) ") ") - 7816 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 - 7817 } - 7818 # otherwise abort - 7819 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 - 7820 $translate-mu-index-stmt-with-array-on-stack:emit-output: - 7821 # outputs[0] "/r32" - 7822 8b/-> *(ebp+0xc) 0/r32/eax - 7823 8b/-> *(eax+0xc) 0/r32/eax # Stmt1-outputs - 7824 8b/-> *eax 0/r32/eax # Stmt-var-value - 7825 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7826 (print-int32-buffered *(ebp+8) *eax) - 7827 (write-buffered *(ebp+8) "/r32\n") - 7828 $translate-mu-index-stmt-with-array-on-stack:end: - 7829 # . restore registers - 7830 5b/pop-to-ebx - 7831 5a/pop-to-edx - 7832 59/pop-to-ecx - 7833 58/pop-to-eax - 7834 # . epilogue - 7835 89/<- %esp 5/r32/ebp - 7836 5d/pop-to-ebp - 7837 c3/return - 7838 - 7839 translate-mu-compute-index-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7840 # . prologue - 7841 55/push-ebp - 7842 89/<- %ebp 4/r32/esp - 7843 # . save registers - 7844 50/push-eax - 7845 51/push-ecx - 7846 52/push-edx - 7847 53/push-ebx - 7848 # - 7849 (emit-indent *(ebp+8) *Curr-block-depth) - 7850 (write-buffered *(ebp+8) "69/multiply ") - 7851 $translate-mu-compute-index-stmt:emit-elem-size: - 7852 # ecx = stmt - 7853 8b/-> *(ebp+0xc) 1/r32/ecx - 7854 # var first-inout/edx: (handle stmt-var) = stmt->inouts[0] - 7855 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 7856 # var base/ebx: (handle var) - 7857 8b/-> *edx 3/r32/ebx # Stmt-var-value - 7858 # print size-of(element(base->type)) - 7859 (array-element-type-id %ebx) # => eax - 7860 (size-of-type-id %eax) # => eax - 7861 (print-int32-buffered *(ebp+8) %eax) - 7862 (write-buffered *(ebp+8) "/imm32") - 7863 $translate-mu-compute-index-stmt:emit-index: - 7864 (emit-subx-var-as-rm32 *(ebp+8) *(edx+4)) # Stmt-var-next - 7865 (write-buffered *(ebp+8) Space) - 7866 $translate-mu-compute-index-stmt:emit-output: + 7573 # + 7574 (emit-indent *(ebp+8) *Curr-block-depth) + 7575 (write-buffered *(ebp+8) "8b/copy-from *") + 7576 # var base/eax: (handle var) = inouts[0] + 7577 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 7578 8b/-> *eax 0/r32/eax # Stmt-var-value + 7579 # if base is an (address array ...) in a register + 7580 { + 7581 81 7/subop/compare *(eax+0x10)) 0/imm32 # Var-register + 7582 74/jump-if-= break/disp8 + 7583 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register + 7584 eb/jump $translate-mu-length-stmt:emit-output/disp8 + 7585 } + 7586 # otherwise if base is an (array ...) on the stack + 7587 { + 7588 81 7/subop/compare *(eax+0xc)) 0/imm32 # Var-offset + 7589 74/jump-if-= break/disp8 + 7590 (write-buffered *(ebp+8) "(ebp+") + 7591 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset + 7592 (write-buffered *(ebp+8) ")") + 7593 } + 7594 $translate-mu-length-stmt:emit-output: + 7595 (write-buffered *(ebp+8) " ") + 7596 # outputs[0] "/r32" + 7597 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7598 8b/-> *eax 0/r32/eax # Stmt-var-value + 7599 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7600 (print-int32-buffered *(ebp+8) *eax) + 7601 (write-buffered *(ebp+8) "/r32\n") + 7602 $translate-mu-length-stmt:end: + 7603 # . restore registers + 7604 59/pop-to-ecx + 7605 58/pop-to-eax + 7606 # . epilogue + 7607 89/<- %esp 5/r32/ebp + 7608 5d/pop-to-ebp + 7609 c3/return + 7610 + 7611 translate-mu-index-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7612 # . prologue + 7613 55/push-ebp + 7614 89/<- %ebp 4/r32/esp + 7615 # . save registers + 7616 51/push-ecx + 7617 # var base/ecx: (handle var) = stmt->inouts[0] + 7618 8b/-> *(ebp+0xc) 1/r32/ecx + 7619 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 7620 8b/-> *ecx 1/r32/ecx # Stmt-var-value + 7621 # if (var->register) do one thing + 7622 { + 7623 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register + 7624 74/jump-if-= break/disp8 + 7625 # TODO: ensure there's no dereference + 7626 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc)) + 7627 eb/jump $translate-mu-index-stmt:end/disp8 + 7628 } + 7629 # if (var->offset) do a different thing + 7630 { + 7631 81 7/subop/compare *(ecx+0xc) 0/imm32 # Var-offset + 7632 74/jump-if-= break/disp8 + 7633 # TODO: ensure there's no dereference + 7634 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc)) + 7635 eb/jump $translate-mu-index-stmt:end/disp8 + 7636 } + 7637 $translate-mu-index-stmt:end: + 7638 # . restore registers + 7639 59/pop-to-ecx + 7640 # . epilogue + 7641 89/<- %esp 5/r32/ebp + 7642 5d/pop-to-ebp + 7643 c3/return + 7644 + 7645 $translate-mu-index-stmt-with-array:error1: + 7646 (write-buffered Stderr "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") + 7647 (flush Stderr) + 7648 # . syscall(exit, 1) + 7649 bb/copy-to-ebx 1/imm32 + 7650 b8/copy-to-eax 1/imm32/exit + 7651 cd/syscall 0x80/imm8 + 7652 # never gets here + 7653 + 7654 $translate-mu-index-stmt-with-array:error2: + 7655 (write-buffered Stderr "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") + 7656 (flush Stderr) + 7657 # . syscall(exit, 1) + 7658 bb/copy-to-ebx 1/imm32 + 7659 b8/copy-to-eax 1/imm32/exit + 7660 cd/syscall 0x80/imm8 + 7661 # never gets here + 7662 + 7663 translate-mu-index-stmt-with-array-in-register: # out: (address buffered-file), stmt: (handle stmt) + 7664 # . prologue + 7665 55/push-ebp + 7666 89/<- %ebp 4/r32/esp + 7667 # . save registers + 7668 50/push-eax + 7669 51/push-ecx + 7670 52/push-edx + 7671 53/push-ebx + 7672 # + 7673 (emit-indent *(ebp+8) *Curr-block-depth) + 7674 (write-buffered *(ebp+8) "8d/copy-address *(") + 7675 # TODO: ensure inouts[0] is in a register and not dereferenced + 7676 $translate-mu-index-stmt-with-array-in-register:emit-base: + 7677 # ecx = stmt + 7678 8b/-> *(ebp+0xc) 1/r32/ecx + 7679 # var base/ebx: (handle var) = inouts[0] + 7680 8b/-> *(ecx+8) 3/r32/ebx # Stmt1-inouts + 7681 8b/-> *ebx 3/r32/ebx # Stmt-var-value + 7682 # print base->register " + " + 7683 (write-buffered *(ebp+8) *(ebx+0x10)) # Var-register + 7684 # + 7685 (write-buffered *(ebp+8) " + ") + 7686 # var index/edx: (handle var) = inouts[1] + 7687 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 7688 8b/-> *(edx+4) 2/r32/edx # Stmt-var-next + 7689 8b/-> *edx 2/r32/edx # Stmt-var-value + 7690 # if index->register + 7691 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register + 7692 { + 7693 0f 84/jump-if-= break/disp32 + 7694 $translate-mu-index-stmt-with-array-in-register:emit-register-index: + 7695 # if index is an int + 7696 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax + 7697 3d/compare-eax-and 0/imm32/false + 7698 { + 7699 0f 84/jump-if-= break/disp32 + 7700 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: + 7701 # print index->register "<<" log2(size-of(element(base->type))) " + 4) " + 7702 # . index->register "<<" + 7703 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7704 (write-buffered *(ebp+8) "<<") + 7705 # . log2(size-of(element(base->type))) + 7706 # TODO: ensure size is a power of 2 + 7707 (array-element-type-id %ebx) # => eax + 7708 (size-of-type-id %eax) # => eax + 7709 (num-shift-rights %eax) # => eax + 7710 (print-int32-buffered *(ebp+8) %eax) + 7711 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 + 7712 } + 7713 # if index->type is any other atom, abort + 7714 8b/-> *(edx+4) 0/r32/eax # Var-type + 7715 8b/-> *eax 0/r32/eax # Tree-left or Atom-value + 7716 3b/compare 0/r32/eax *Max-type-id + 7717 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 + 7718 # if index has type (offset ...) + 7719 (is-simple-mu-type? %eax 7) # offset => eax + 7720 3d/compare-eax-and 0/imm32/false + 7721 { + 7722 0f 84/jump-if-= break/disp32 + 7723 # print index->register " + 4) " + 7724 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: + 7725 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7726 } + 7727 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: + 7728 (write-buffered *(ebp+8) " + 4) ") + 7729 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 + 7730 } + 7731 # otherwise if index is a literal + 7732 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax + 7733 3d/compare-eax-and 0/imm32/false + 7734 { + 7735 0f 84/jump-if-= break/disp32 + 7736 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: + 7737 # var index-value/edx: int = parse-hex-int(index->name) + 7738 (parse-hex-int *edx) # Var-name => eax + 7739 89/<- %edx 0/r32/eax + 7740 # offset = idx-value * size-of(element(base->type)) + 7741 (array-element-type-id %ebx) # => eax + 7742 (size-of-type-id %eax) # => eax + 7743 f7 4/subop/multiply-into-eax %edx # clobbers edx + 7744 # offset += 4 for array size + 7745 05/add-to-eax 4/imm32 + 7746 # TODO: check edx for overflow + 7747 # print offset + 7748 (print-int32-buffered *(ebp+8) %eax) + 7749 (write-buffered *(ebp+8) ") ") + 7750 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 + 7751 } + 7752 # otherwise abort + 7753 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 + 7754 $translate-mu-index-stmt-with-array-in-register:emit-output: + 7755 # outputs[0] "/r32" + 7756 8b/-> *(ebp+0xc) 1/r32/ecx + 7757 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7758 8b/-> *eax 0/r32/eax # Stmt-var-value + 7759 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7760 (print-int32-buffered *(ebp+8) *eax) + 7761 (write-buffered *(ebp+8) "/r32\n") + 7762 $translate-mu-index-stmt-with-array-in-register:end: + 7763 # . restore registers + 7764 5b/pop-to-ebx + 7765 5a/pop-to-edx + 7766 59/pop-to-ecx + 7767 58/pop-to-eax + 7768 # . epilogue + 7769 89/<- %esp 5/r32/ebp + 7770 5d/pop-to-ebp + 7771 c3/return + 7772 + 7773 translate-mu-index-stmt-with-array-on-stack: # out: (address buffered-file), stmt: (handle stmt) + 7774 # . prologue + 7775 55/push-ebp + 7776 89/<- %ebp 4/r32/esp + 7777 # . save registers + 7778 50/push-eax + 7779 51/push-ecx + 7780 52/push-edx + 7781 53/push-ebx + 7782 # + 7783 (emit-indent *(ebp+8) *Curr-block-depth) + 7784 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") + 7785 # var curr/eax = stmt->inouts + 7786 8b/-> *(ebp+0xc) 0/r32/eax + 7787 # var base/ecx: (handle var) = stmt->inouts[0] + 7788 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts + 7789 8b/-> *eax 1/r32/ecx # Stmt-var-value + 7790 # curr = curr->next + 7791 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 7792 # var index/edx: (handle var) = stmt->inouts[1] + 7793 8b/-> *eax 2/r32/edx # Stmt-var-value + 7794 # if index->register + 7795 81 7/subop/compare *(edx+0x10) 0/imm32 # Var-register + 7796 { + 7797 0f 84/jump-if-= break/disp32 + 7798 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: + 7799 # if index is an int + 7800 (is-simple-mu-type? *(edx+4) 1) # Var-type, int => eax + 7801 3d/compare-eax-and 0/imm32/false + 7802 { + 7803 0f 84/jump-if-= break/disp32 + 7804 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: + 7805 # print index->register "<<" log2(size-of(element-type(base))) " + " base->offset+4 + 7806 # . inouts[1]->register "<<" + 7807 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7808 (write-buffered *(ebp+8) "<<") + 7809 # . log2(size-of(element(base))) + 7810 # TODO: ensure size is a power of 2 + 7811 (array-element-type-id %ecx) # => eax + 7812 (size-of-type-id %eax) # => eax + 7813 (num-shift-rights %eax) # => eax + 7814 (print-int32-buffered *(ebp+8) %eax) + 7815 # + 7816 (write-buffered *(ebp+8) " + ") + 7817 # + 7818 8b/-> *(ecx+0xc) 0/r32/eax # Var-offset + 7819 05/add-to-eax 4/imm32 + 7820 (print-int32-buffered *(ebp+8) %eax) + 7821 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 + 7822 } + 7823 # if index->type is any other atom, abort + 7824 8b/-> *(edx+4) 0/r32/eax # Var-type + 7825 8b/-> *eax 0/r32/eax # Tree-left or Atom-value + 7826 3b/compare 0/r32/eax *Max-type-id + 7827 0f 82/jump-if-addr< $translate-mu-index-stmt-with-array:error2/disp32 + 7828 # if index has type (offset ...) + 7829 (is-simple-mu-type? %eax 7) # offset => eax + 7830 3d/compare-eax-and 0/imm32/false + 7831 { + 7832 0f 84/jump-if-= break/disp32 + 7833 # print index->register + 7834 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: + 7835 (write-buffered *(ebp+8) *(edx+0x10)) # Var-register + 7836 } + 7837 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: + 7838 (write-buffered *(ebp+8) ") ") + 7839 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 + 7840 } + 7841 # otherwise if index is a literal + 7842 (is-simple-mu-type? *(edx+4) 0) # Var-type => eax + 7843 3d/compare-eax-and 0/imm32/false + 7844 { + 7845 0f 84/jump-if-= break/disp32 + 7846 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: + 7847 # var idx-value/edx: int = parse-hex-int(index->name) + 7848 (parse-hex-int *edx) # Var-name => eax + 7849 89/<- %ebx 0/r32/eax + 7850 # offset = idx-value * size-of(element-type(base->type)) + 7851 (array-element-type-id %ecx) # => eax + 7852 (size-of-type-id %eax) # => eax + 7853 f7 4/subop/multiply-into-eax %ebx # clobbers edx + 7854 # offset += base->offset + 7855 03/add-to 0/r32/eax *(ecx+0xc) # Var-offset + 7856 # offset += 4 for array size + 7857 05/add-to-eax 4/imm32 + 7858 # TODO: check edx for overflow + 7859 # print offset + 7860 (print-int32-buffered *(ebp+8) %eax) + 7861 (write-buffered *(ebp+8) ") ") + 7862 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 + 7863 } + 7864 # otherwise abort + 7865 e9/jump $translate-mu-index-stmt-with-array:error1/disp32 + 7866 $translate-mu-index-stmt-with-array-on-stack:emit-output: 7867 # outputs[0] "/r32" - 7868 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7869 8b/-> *eax 0/r32/eax # Stmt-var-value - 7870 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7871 (print-int32-buffered *(ebp+8) *eax) - 7872 (write-buffered *(ebp+8) "/r32\n") - 7873 $translate-mu-compute-index-stmt:end: - 7874 # . restore registers - 7875 5b/pop-to-ebx - 7876 5a/pop-to-edx - 7877 59/pop-to-ecx - 7878 58/pop-to-eax - 7879 # . epilogue - 7880 89/<- %esp 5/r32/ebp - 7881 5d/pop-to-ebp - 7882 c3/return - 7883 - 7884 translate-mu-get-stmt: # out: (address buffered-file), stmt: (handle stmt) - 7885 # . prologue - 7886 55/push-ebp - 7887 89/<- %ebp 4/r32/esp - 7888 # . save registers - 7889 50/push-eax - 7890 51/push-ecx - 7891 52/push-edx - 7892 # - 7893 (emit-indent *(ebp+8) *Curr-block-depth) - 7894 (write-buffered *(ebp+8) "8d/copy-address ") - 7895 # ecx = stmt - 7896 8b/-> *(ebp+0xc) 1/r32/ecx - 7897 # var offset/edx: int = get offset of stmt - 7898 (mu-get-offset %ecx) # => eax - 7899 89/<- %edx 0/r32/eax - 7900 # var base/eax: (handle var) = stmt->inouts[0] - 7901 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts - 7902 8b/-> *eax 0/r32/eax # Stmt-var-value - 7903 # if base is in a register - 7904 81 7/subop/compare *(eax+0x10) 0/imm32 - 7905 { - 7906 0f 84/jump-if-= break/disp32 - 7907 $translate-mu-get-stmt:emit-register-input: - 7908 # "*(" inouts[0]->register " + " offset ")" - 7909 (write-buffered *(ebp+8) "*(") - 7910 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register - 7911 (write-buffered *(ebp+8) " + ") - 7912 (print-int32-buffered *(ebp+8) %edx) - 7913 (write-buffered *(ebp+8) ") ") - 7914 e9/jump $translate-mu-get-stmt:emit-output/disp32 - 7915 } - 7916 # otherwise base is on the stack - 7917 { - 7918 $translate-mu-get-stmt:emit-stack-input: - 7919 # "*(ebp + " inouts[0]->offset + offset ")" - 7920 (write-buffered *(ebp+8) "*(ebp+") - 7921 03/add-from *(eax+0xc) 2/r32/edx # Var-offset - 7922 (print-int32-buffered *(ebp+8) %edx) - 7923 (write-buffered *(ebp+8) ") ") - 7924 eb/jump $translate-mu-get-stmt:emit-output/disp8 - 7925 } - 7926 $translate-mu-get-stmt:emit-output: - 7927 # outputs[0] "/r32" - 7928 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 7929 8b/-> *eax 0/r32/eax # Stmt-var-value - 7930 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax - 7931 (print-int32-buffered *(ebp+8) *eax) - 7932 (write-buffered *(ebp+8) "/r32\n") - 7933 $translate-mu-get-stmt:end: - 7934 # . restore registers - 7935 5a/pop-to-edx - 7936 59/pop-to-ecx - 7937 58/pop-to-eax - 7938 # . epilogue - 7939 89/<- %esp 5/r32/ebp - 7940 5d/pop-to-ebp - 7941 c3/return - 7942 - 7943 array-element-type-id: # v: (handle var) -> result/eax: type-id - 7944 # precondition: n is positive - 7945 # . prologue - 7946 55/push-ebp - 7947 89/<- %ebp 4/r32/esp - 7948 # - 7949 8b/-> *(ebp+8) 0/r32/eax - 7950 8b/-> *(eax+4) 0/r32/eax # Var-type - 7951 # TODO: ensure type->left is 'addr' - 7952 8b/-> *(eax+4) 0/r32/eax # Tree-right - 7953 # TODO: ensure that type->right is non-null - 7954 # TODO: ensure that type->right->left is 'array' - 7955 8b/-> *(eax+4) 0/r32/eax # Tree-right - 7956 # TODO: ensure that type->right->right is non-null - 7957 8b/-> *eax 0/r32/eax # Tree-left - 7958 8b/-> *eax 0/r32/eax # Atom-value - 7959 $array-element-type-id:end: - 7960 # . epilogue - 7961 89/<- %esp 5/r32/ebp - 7962 5d/pop-to-ebp - 7963 c3/return - 7964 - 7965 power-of-2?: # n: int -> result/eax: boolean - 7966 # precondition: n is positive - 7967 # . prologue - 7968 55/push-ebp - 7969 89/<- %ebp 4/r32/esp - 7970 # var tmp/eax: int = n-1 - 7971 8b/-> *(ebp+8) 0/r32/eax - 7972 48/decrement-eax - 7973 # var tmp2/eax: int = n & tmp - 7974 0b/and-> *(ebp+8) 0/r32/eax - 7975 # return (tmp2 == 0) - 7976 3d/compare-eax-and 0/imm32 - 7977 0f 94/set-byte-if-= %al - 7978 81 4/subop/and %eax 0xff/imm32 - 7979 $power-of-2?:end: - 7980 # . epilogue - 7981 89/<- %esp 5/r32/ebp - 7982 5d/pop-to-ebp - 7983 c3/return - 7984 - 7985 num-shift-rights: # n: int -> result/eax: int - 7986 # precondition: n is a positive power of 2 - 7987 # . prologue - 7988 55/push-ebp - 7989 89/<- %ebp 4/r32/esp - 7990 # . save registers - 7991 51/push-ecx - 7992 # var curr/ecx: int = n - 7993 8b/-> *(ebp+8) 1/r32/ecx - 7994 # result = 0 - 7995 b8/copy-to-eax 0/imm32 - 7996 { - 7997 # if (curr <= 1) break - 7998 81 7/subop/compare %ecx 1/imm32 - 7999 7e/jump-if-<= break/disp8 - 8000 40/increment-eax - 8001 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 - 8002 eb/jump loop/disp8 - 8003 } - 8004 $num-shift-rights:end: - 8005 # . restore registers - 8006 59/pop-to-ecx - 8007 # . epilogue - 8008 89/<- %esp 5/r32/ebp - 8009 5d/pop-to-ebp - 8010 c3/return - 8011 - 8012 mu-get-offset: # stmt: (handle stmt) -> result/eax: int + 7868 8b/-> *(ebp+0xc) 0/r32/eax + 7869 8b/-> *(eax+0xc) 0/r32/eax # Stmt1-outputs + 7870 8b/-> *eax 0/r32/eax # Stmt-var-value + 7871 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7872 (print-int32-buffered *(ebp+8) *eax) + 7873 (write-buffered *(ebp+8) "/r32\n") + 7874 $translate-mu-index-stmt-with-array-on-stack:end: + 7875 # . restore registers + 7876 5b/pop-to-ebx + 7877 5a/pop-to-edx + 7878 59/pop-to-ecx + 7879 58/pop-to-eax + 7880 # . epilogue + 7881 89/<- %esp 5/r32/ebp + 7882 5d/pop-to-ebp + 7883 c3/return + 7884 + 7885 translate-mu-compute-index-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7886 # . prologue + 7887 55/push-ebp + 7888 89/<- %ebp 4/r32/esp + 7889 # . save registers + 7890 50/push-eax + 7891 51/push-ecx + 7892 52/push-edx + 7893 53/push-ebx + 7894 # + 7895 (emit-indent *(ebp+8) *Curr-block-depth) + 7896 (write-buffered *(ebp+8) "69/multiply ") + 7897 $translate-mu-compute-index-stmt:emit-elem-size: + 7898 # ecx = stmt + 7899 8b/-> *(ebp+0xc) 1/r32/ecx + 7900 # var first-inout/edx: (handle stmt-var) = stmt->inouts[0] + 7901 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts + 7902 # var base/ebx: (handle var) + 7903 8b/-> *edx 3/r32/ebx # Stmt-var-value + 7904 # print size-of(element(base->type)) + 7905 (array-element-type-id %ebx) # => eax + 7906 (size-of-type-id %eax) # => eax + 7907 (print-int32-buffered *(ebp+8) %eax) + 7908 (write-buffered *(ebp+8) "/imm32") + 7909 $translate-mu-compute-index-stmt:emit-index: + 7910 (emit-subx-var-as-rm32 *(ebp+8) *(edx+4)) # Stmt-var-next + 7911 (write-buffered *(ebp+8) Space) + 7912 $translate-mu-compute-index-stmt:emit-output: + 7913 # outputs[0] "/r32" + 7914 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7915 8b/-> *eax 0/r32/eax # Stmt-var-value + 7916 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7917 (print-int32-buffered *(ebp+8) *eax) + 7918 (write-buffered *(ebp+8) "/r32\n") + 7919 $translate-mu-compute-index-stmt:end: + 7920 # . restore registers + 7921 5b/pop-to-ebx + 7922 5a/pop-to-edx + 7923 59/pop-to-ecx + 7924 58/pop-to-eax + 7925 # . epilogue + 7926 89/<- %esp 5/r32/ebp + 7927 5d/pop-to-ebp + 7928 c3/return + 7929 + 7930 translate-mu-get-stmt: # out: (address buffered-file), stmt: (handle stmt) + 7931 # . prologue + 7932 55/push-ebp + 7933 89/<- %ebp 4/r32/esp + 7934 # . save registers + 7935 50/push-eax + 7936 51/push-ecx + 7937 52/push-edx + 7938 # + 7939 (emit-indent *(ebp+8) *Curr-block-depth) + 7940 (write-buffered *(ebp+8) "8d/copy-address ") + 7941 # ecx = stmt + 7942 8b/-> *(ebp+0xc) 1/r32/ecx + 7943 # var offset/edx: int = get offset of stmt + 7944 (mu-get-offset %ecx) # => eax + 7945 89/<- %edx 0/r32/eax + 7946 # var base/eax: (handle var) = stmt->inouts[0] + 7947 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts + 7948 8b/-> *eax 0/r32/eax # Stmt-var-value + 7949 # if base is in a register + 7950 81 7/subop/compare *(eax+0x10) 0/imm32 + 7951 { + 7952 0f 84/jump-if-= break/disp32 + 7953 $translate-mu-get-stmt:emit-register-input: + 7954 # "*(" inouts[0]->register " + " offset ")" + 7955 (write-buffered *(ebp+8) "*(") + 7956 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register + 7957 (write-buffered *(ebp+8) " + ") + 7958 (print-int32-buffered *(ebp+8) %edx) + 7959 (write-buffered *(ebp+8) ") ") + 7960 e9/jump $translate-mu-get-stmt:emit-output/disp32 + 7961 } + 7962 # otherwise base is on the stack + 7963 { + 7964 $translate-mu-get-stmt:emit-stack-input: + 7965 # "*(ebp + " inouts[0]->offset + offset ")" + 7966 (write-buffered *(ebp+8) "*(ebp+") + 7967 03/add-from *(eax+0xc) 2/r32/edx # Var-offset + 7968 (print-int32-buffered *(ebp+8) %edx) + 7969 (write-buffered *(ebp+8) ") ") + 7970 eb/jump $translate-mu-get-stmt:emit-output/disp8 + 7971 } + 7972 $translate-mu-get-stmt:emit-output: + 7973 # outputs[0] "/r32" + 7974 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 7975 8b/-> *eax 0/r32/eax # Stmt-var-value + 7976 (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax + 7977 (print-int32-buffered *(ebp+8) *eax) + 7978 (write-buffered *(ebp+8) "/r32\n") + 7979 $translate-mu-get-stmt:end: + 7980 # . restore registers + 7981 5a/pop-to-edx + 7982 59/pop-to-ecx + 7983 58/pop-to-eax + 7984 # . epilogue + 7985 89/<- %esp 5/r32/ebp + 7986 5d/pop-to-ebp + 7987 c3/return + 7988 + 7989 array-element-type-id: # v: (handle var) -> result/eax: type-id + 7990 # precondition: n is positive + 7991 # . prologue + 7992 55/push-ebp + 7993 89/<- %ebp 4/r32/esp + 7994 # + 7995 8b/-> *(ebp+8) 0/r32/eax + 7996 8b/-> *(eax+4) 0/r32/eax # Var-type + 7997 # TODO: ensure type->left is 'addr' + 7998 8b/-> *(eax+4) 0/r32/eax # Tree-right + 7999 # TODO: ensure that type->right is non-null + 8000 # TODO: ensure that type->right->left is 'array' + 8001 8b/-> *(eax+4) 0/r32/eax # Tree-right + 8002 # TODO: ensure that type->right->right is non-null + 8003 8b/-> *eax 0/r32/eax # Tree-left + 8004 8b/-> *eax 0/r32/eax # Atom-value + 8005 $array-element-type-id:end: + 8006 # . epilogue + 8007 89/<- %esp 5/r32/ebp + 8008 5d/pop-to-ebp + 8009 c3/return + 8010 + 8011 power-of-2?: # n: int -> result/eax: boolean + 8012 # precondition: n is positive 8013 # . prologue 8014 55/push-ebp 8015 89/<- %ebp 4/r32/esp - 8016 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next + 8016 # var tmp/eax: int = n-1 8017 8b/-> *(ebp+8) 0/r32/eax - 8018 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts - 8019 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 8020 # var output-var/eax: (handle var) = second-inout->value - 8021 8b/-> *eax 0/r32/eax # Stmt-var-value - 8022 # return output-var->offset - 8023 8b/-> *(eax+0xc) 0/r32/eax # Var-offset - 8024 $emit-get-offset:end: - 8025 # . epilogue - 8026 89/<- %esp 5/r32/ebp - 8027 5d/pop-to-ebp - 8028 c3/return - 8029 - 8030 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) - 8031 # . prologue - 8032 55/push-ebp - 8033 89/<- %ebp 4/r32/esp - 8034 # . save registers - 8035 50/push-eax - 8036 51/push-ecx - 8037 56/push-esi - 8038 # esi = block - 8039 8b/-> *(ebp+0xc) 6/r32/esi - 8040 # block->var->block-depth = *Curr-block-depth - 8041 8b/-> *(esi+8) 0/r32/eax # Block-var - 8042 8b/-> *Curr-block-depth 1/r32/ecx - 8043 89/<- *(eax+8) 1/r32/ecx # Var-block-depth - 8044 # var stmts/eax: (handle list stmt) = block->statements - 8045 8b/-> *(esi+4) 0/r32/eax # Block-stmts - 8046 # - 8047 { - 8048 $emit-subx-block:check-empty: - 8049 3d/compare-eax-and 0/imm32 - 8050 0f 84/jump-if-= break/disp32 - 8051 (emit-indent *(ebp+8) *Curr-block-depth) - 8052 (write-buffered *(ebp+8) "{\n") - 8053 # var v/ecx: (handle var) - 8054 8b/-> *(esi+8) 1/r32/ecx # Block-var - 8055 # - 8056 (write-buffered *(ebp+8) *ecx) # Var-name - 8057 (write-buffered *(ebp+8) ":loop:\n") - 8058 ff 0/subop/increment *Curr-block-depth - 8059 (push *(ebp+0x10) %ecx) - 8060 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) - 8061 (pop *(ebp+0x10)) # => eax - 8062 ff 1/subop/decrement *Curr-block-depth - 8063 (emit-indent *(ebp+8) *Curr-block-depth) - 8064 (write-buffered *(ebp+8) "}\n") - 8065 (write-buffered *(ebp+8) *ecx) # Var-name - 8066 (write-buffered *(ebp+8) ":break:\n") - 8067 } - 8068 $emit-subx-block:end: - 8069 # . restore registers - 8070 5e/pop-to-esi - 8071 59/pop-to-ecx - 8072 58/pop-to-eax - 8073 # . epilogue - 8074 89/<- %esp 5/r32/ebp - 8075 5d/pop-to-ebp - 8076 c3/return - 8077 - 8078 # Primitives supported - 8079 # For each operation, put variants with hard-coded registers before flexible ones. - 8080 == data - 8081 Primitives: - 8082 # - increment/decrement - 8083 _Primitive-inc-eax: - 8084 # var/eax <- increment => 40/increment-eax - 8085 "increment"/imm32/name - 8086 0/imm32/no-inouts - 8087 Single-int-var-in-eax/imm32/outputs - 8088 "40/increment-eax"/imm32/subx-name - 8089 0/imm32/no-rm32 - 8090 0/imm32/no-r32 - 8091 0/imm32/no-imm32 - 8092 0/imm32/no-disp32 - 8093 0/imm32/output-is-write-only - 8094 _Primitive-inc-ecx/imm32/next - 8095 _Primitive-inc-ecx: - 8096 # var/ecx <- increment => 41/increment-ecx - 8097 "increment"/imm32/name - 8098 0/imm32/no-inouts - 8099 Single-int-var-in-ecx/imm32/outputs - 8100 "41/increment-ecx"/imm32/subx-name - 8101 0/imm32/no-rm32 - 8102 0/imm32/no-r32 - 8103 0/imm32/no-imm32 - 8104 0/imm32/no-disp32 - 8105 0/imm32/output-is-write-only - 8106 _Primitive-inc-edx/imm32/next - 8107 _Primitive-inc-edx: - 8108 # var/edx <- increment => 42/increment-edx - 8109 "increment"/imm32/name - 8110 0/imm32/no-inouts - 8111 Single-int-var-in-edx/imm32/outputs - 8112 "42/increment-edx"/imm32/subx-name - 8113 0/imm32/no-rm32 - 8114 0/imm32/no-r32 - 8115 0/imm32/no-imm32 - 8116 0/imm32/no-disp32 - 8117 0/imm32/output-is-write-only - 8118 _Primitive-inc-ebx/imm32/next - 8119 _Primitive-inc-ebx: - 8120 # var/ebx <- increment => 43/increment-ebx - 8121 "increment"/imm32/name - 8122 0/imm32/no-inouts - 8123 Single-int-var-in-ebx/imm32/outputs - 8124 "43/increment-ebx"/imm32/subx-name - 8125 0/imm32/no-rm32 - 8126 0/imm32/no-r32 - 8127 0/imm32/no-imm32 - 8128 0/imm32/no-disp32 - 8129 0/imm32/output-is-write-only - 8130 _Primitive-inc-esi/imm32/next - 8131 _Primitive-inc-esi: - 8132 # var/esi <- increment => 46/increment-esi - 8133 "increment"/imm32/name - 8134 0/imm32/no-inouts - 8135 Single-int-var-in-esi/imm32/outputs - 8136 "46/increment-esi"/imm32/subx-name - 8137 0/imm32/no-rm32 - 8138 0/imm32/no-r32 - 8139 0/imm32/no-imm32 - 8140 0/imm32/no-disp32 - 8141 0/imm32/output-is-write-only - 8142 _Primitive-inc-edi/imm32/next - 8143 _Primitive-inc-edi: - 8144 # var/edi <- increment => 47/increment-edi - 8145 "increment"/imm32/name - 8146 0/imm32/no-inouts - 8147 Single-int-var-in-edi/imm32/outputs - 8148 "47/increment-edi"/imm32/subx-name - 8149 0/imm32/no-rm32 - 8150 0/imm32/no-r32 - 8151 0/imm32/no-imm32 - 8152 0/imm32/no-disp32 - 8153 0/imm32/output-is-write-only - 8154 _Primitive-dec-eax/imm32/next - 8155 _Primitive-dec-eax: - 8156 # var/eax <- decrement => 48/decrement-eax - 8157 "decrement"/imm32/name - 8158 0/imm32/no-inouts - 8159 Single-int-var-in-eax/imm32/outputs - 8160 "48/decrement-eax"/imm32/subx-name - 8161 0/imm32/no-rm32 - 8162 0/imm32/no-r32 - 8163 0/imm32/no-imm32 - 8164 0/imm32/no-disp32 - 8165 0/imm32/output-is-write-only - 8166 _Primitive-dec-ecx/imm32/next - 8167 _Primitive-dec-ecx: - 8168 # var/ecx <- decrement => 49/decrement-ecx - 8169 "decrement"/imm32/name - 8170 0/imm32/no-inouts - 8171 Single-int-var-in-ecx/imm32/outputs - 8172 "49/decrement-ecx"/imm32/subx-name - 8173 0/imm32/no-rm32 - 8174 0/imm32/no-r32 - 8175 0/imm32/no-imm32 - 8176 0/imm32/no-disp32 - 8177 0/imm32/output-is-write-only - 8178 _Primitive-dec-edx/imm32/next - 8179 _Primitive-dec-edx: - 8180 # var/edx <- decrement => 4a/decrement-edx - 8181 "decrement"/imm32/name - 8182 0/imm32/no-inouts - 8183 Single-int-var-in-edx/imm32/outputs - 8184 "4a/decrement-edx"/imm32/subx-name - 8185 0/imm32/no-rm32 - 8186 0/imm32/no-r32 - 8187 0/imm32/no-imm32 - 8188 0/imm32/no-disp32 - 8189 0/imm32/output-is-write-only - 8190 _Primitive-dec-ebx/imm32/next - 8191 _Primitive-dec-ebx: - 8192 # var/ebx <- decrement => 4b/decrement-ebx - 8193 "decrement"/imm32/name - 8194 0/imm32/no-inouts - 8195 Single-int-var-in-ebx/imm32/outputs - 8196 "4b/decrement-ebx"/imm32/subx-name - 8197 0/imm32/no-rm32 - 8198 0/imm32/no-r32 - 8199 0/imm32/no-imm32 - 8200 0/imm32/no-disp32 - 8201 0/imm32/output-is-write-only - 8202 _Primitive-dec-esi/imm32/next - 8203 _Primitive-dec-esi: - 8204 # var/esi <- decrement => 4e/decrement-esi - 8205 "decrement"/imm32/name - 8206 0/imm32/no-inouts - 8207 Single-int-var-in-esi/imm32/outputs - 8208 "4e/decrement-esi"/imm32/subx-name - 8209 0/imm32/no-rm32 - 8210 0/imm32/no-r32 - 8211 0/imm32/no-imm32 - 8212 0/imm32/no-disp32 - 8213 0/imm32/output-is-write-only - 8214 _Primitive-dec-edi/imm32/next - 8215 _Primitive-dec-edi: - 8216 # var/edi <- decrement => 4f/decrement-edi - 8217 "decrement"/imm32/name - 8218 0/imm32/no-inouts - 8219 Single-int-var-in-edi/imm32/outputs - 8220 "4f/decrement-edi"/imm32/subx-name - 8221 0/imm32/no-rm32 - 8222 0/imm32/no-r32 - 8223 0/imm32/no-imm32 - 8224 0/imm32/no-disp32 - 8225 0/imm32/output-is-write-only - 8226 _Primitive-inc-mem/imm32/next - 8227 _Primitive-inc-mem: - 8228 # increment var => ff 0/subop/increment *(ebp+__) - 8229 "increment"/imm32/name - 8230 Single-int-var-in-mem/imm32/inouts - 8231 0/imm32/no-outputs - 8232 "ff 0/subop/increment"/imm32/subx-name - 8233 1/imm32/rm32-is-first-inout - 8234 0/imm32/no-r32 - 8235 0/imm32/no-imm32 - 8236 0/imm32/no-disp32 - 8237 0/imm32/output-is-write-only - 8238 _Primitive-inc-reg/imm32/next - 8239 _Primitive-inc-reg: - 8240 # var/reg <- increment => ff 0/subop/increment %__ - 8241 "increment"/imm32/name - 8242 0/imm32/no-inouts - 8243 Single-int-var-in-some-register/imm32/outputs - 8244 "ff 0/subop/increment"/imm32/subx-name - 8245 3/imm32/rm32-is-first-output - 8246 0/imm32/no-r32 - 8247 0/imm32/no-imm32 - 8248 0/imm32/no-disp32 - 8249 0/imm32/output-is-write-only - 8250 _Primitive-dec-mem/imm32/next - 8251 _Primitive-dec-mem: - 8252 # decrement var => ff 1/subop/decrement *(ebp+__) - 8253 "decrement"/imm32/name - 8254 Single-int-var-in-mem/imm32/inouts - 8255 0/imm32/no-outputs - 8256 "ff 1/subop/decrement"/imm32/subx-name - 8257 1/imm32/rm32-is-first-inout - 8258 0/imm32/no-r32 - 8259 0/imm32/no-imm32 - 8260 0/imm32/no-disp32 - 8261 0/imm32/output-is-write-only - 8262 _Primitive-dec-reg/imm32/next - 8263 _Primitive-dec-reg: - 8264 # var/reg <- decrement => ff 1/subop/decrement %__ - 8265 "decrement"/imm32/name - 8266 0/imm32/no-inouts - 8267 Single-int-var-in-some-register/imm32/outputs - 8268 "ff 1/subop/decrement"/imm32/subx-name - 8269 3/imm32/rm32-is-first-output - 8270 0/imm32/no-r32 - 8271 0/imm32/no-imm32 - 8272 0/imm32/no-disp32 - 8273 0/imm32/output-is-write-only - 8274 _Primitive-add-to-eax/imm32/next - 8275 # - add - 8276 _Primitive-add-to-eax: - 8277 # var/eax <- add lit => 05/add-to-eax lit/imm32 - 8278 "add"/imm32/name - 8279 Single-lit-var/imm32/inouts - 8280 Single-int-var-in-eax/imm32/outputs - 8281 "05/add-to-eax"/imm32/subx-name - 8282 0/imm32/no-rm32 - 8283 0/imm32/no-r32 - 8284 1/imm32/imm32-is-first-inout - 8285 0/imm32/no-disp32 - 8286 0/imm32/output-is-write-only - 8287 _Primitive-add-reg-to-reg/imm32/next - 8288 _Primitive-add-reg-to-reg: - 8289 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 - 8290 "add"/imm32/name - 8291 Single-int-var-in-some-register/imm32/inouts - 8292 Single-int-var-in-some-register/imm32/outputs - 8293 "01/add-to"/imm32/subx-name - 8294 3/imm32/rm32-is-first-output - 8295 1/imm32/r32-is-first-inout - 8296 0/imm32/no-imm32 - 8297 0/imm32/no-disp32 - 8298 0/imm32/output-is-write-only - 8299 _Primitive-add-reg-to-mem/imm32/next - 8300 _Primitive-add-reg-to-mem: - 8301 # add-to var1 var2/reg => 01/add-to var1 var2/r32 - 8302 "add-to"/imm32/name - 8303 Two-args-int-stack-int-reg/imm32/inouts - 8304 0/imm32/outputs - 8305 "01/add-to"/imm32/subx-name - 8306 1/imm32/rm32-is-first-inout - 8307 2/imm32/r32-is-second-inout - 8308 0/imm32/no-imm32 - 8309 0/imm32/no-disp32 - 8310 0/imm32/output-is-write-only - 8311 _Primitive-add-mem-to-reg/imm32/next - 8312 _Primitive-add-mem-to-reg: - 8313 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 - 8314 "add"/imm32/name - 8315 Single-int-var-in-mem/imm32/inouts - 8316 Single-int-var-in-some-register/imm32/outputs - 8317 "03/add"/imm32/subx-name - 8318 1/imm32/rm32-is-first-inout - 8319 3/imm32/r32-is-first-output - 8320 0/imm32/no-imm32 - 8321 0/imm32/no-disp32 - 8322 0/imm32/output-is-write-only - 8323 _Primitive-add-lit-to-reg/imm32/next - 8324 _Primitive-add-lit-to-reg: - 8325 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 - 8326 "add"/imm32/name - 8327 Single-lit-var/imm32/inouts - 8328 Single-int-var-in-some-register/imm32/outputs - 8329 "81 0/subop/add"/imm32/subx-name - 8330 3/imm32/rm32-is-first-output - 8331 0/imm32/no-r32 - 8332 1/imm32/imm32-is-first-inout - 8333 0/imm32/no-disp32 - 8334 0/imm32/output-is-write-only - 8335 _Primitive-add-lit-to-mem/imm32/next - 8336 _Primitive-add-lit-to-mem: - 8337 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 - 8338 "add-to"/imm32/name - 8339 Int-var-and-literal/imm32/inouts - 8340 0/imm32/outputs - 8341 "81 0/subop/add"/imm32/subx-name - 8342 1/imm32/rm32-is-first-inout - 8343 0/imm32/no-r32 - 8344 2/imm32/imm32-is-second-inout - 8345 0/imm32/no-disp32 - 8346 0/imm32/output-is-write-only - 8347 _Primitive-subtract-from-eax/imm32/next - 8348 # - subtract - 8349 _Primitive-subtract-from-eax: - 8350 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 - 8351 "subtract"/imm32/name - 8352 Single-lit-var/imm32/inouts - 8353 Single-int-var-in-eax/imm32/outputs - 8354 "2d/subtract-from-eax"/imm32/subx-name - 8355 0/imm32/no-rm32 - 8356 0/imm32/no-r32 - 8357 1/imm32/imm32-is-first-inout - 8358 0/imm32/no-disp32 - 8359 0/imm32/output-is-write-only - 8360 _Primitive-subtract-reg-from-reg/imm32/next - 8361 _Primitive-subtract-reg-from-reg: - 8362 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 - 8363 "subtract"/imm32/name - 8364 Single-int-var-in-some-register/imm32/inouts - 8365 Single-int-var-in-some-register/imm32/outputs - 8366 "29/subtract-from"/imm32/subx-name - 8367 3/imm32/rm32-is-first-output - 8368 1/imm32/r32-is-first-inout - 8369 0/imm32/no-imm32 - 8370 0/imm32/no-disp32 - 8371 0/imm32/output-is-write-only - 8372 _Primitive-subtract-reg-from-mem/imm32/next - 8373 _Primitive-subtract-reg-from-mem: - 8374 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 - 8375 "subtract-from"/imm32/name - 8376 Two-args-int-stack-int-reg/imm32/inouts - 8377 0/imm32/outputs - 8378 "29/subtract-from"/imm32/subx-name - 8379 1/imm32/rm32-is-first-inout - 8380 2/imm32/r32-is-second-inout - 8381 0/imm32/no-imm32 - 8382 0/imm32/no-disp32 - 8383 0/imm32/output-is-write-only - 8384 _Primitive-subtract-mem-from-reg/imm32/next - 8385 _Primitive-subtract-mem-from-reg: - 8386 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 - 8387 "subtract"/imm32/name - 8388 Single-int-var-in-mem/imm32/inouts - 8389 Single-int-var-in-some-register/imm32/outputs - 8390 "2b/subtract"/imm32/subx-name - 8391 1/imm32/rm32-is-first-inout - 8392 3/imm32/r32-is-first-output - 8393 0/imm32/no-imm32 - 8394 0/imm32/no-disp32 - 8395 0/imm32/output-is-write-only - 8396 _Primitive-subtract-lit-from-reg/imm32/next - 8397 _Primitive-subtract-lit-from-reg: - 8398 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 8399 "subtract"/imm32/name - 8400 Single-lit-var/imm32/inouts - 8401 Single-int-var-in-some-register/imm32/outputs - 8402 "81 5/subop/subtract"/imm32/subx-name - 8403 3/imm32/rm32-is-first-output - 8404 0/imm32/no-r32 - 8405 1/imm32/imm32-is-first-inout - 8406 0/imm32/no-disp32 - 8407 0/imm32/output-is-write-only - 8408 _Primitive-subtract-lit-from-mem/imm32/next - 8409 _Primitive-subtract-lit-from-mem: - 8410 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 8411 "subtract-from"/imm32/name - 8412 Int-var-and-literal/imm32/inouts - 8413 0/imm32/outputs - 8414 "81 5/subop/subtract"/imm32/subx-name - 8415 1/imm32/rm32-is-first-inout - 8416 0/imm32/no-r32 - 8417 2/imm32/imm32-is-first-inout - 8418 0/imm32/no-disp32 - 8419 0/imm32/output-is-write-only - 8420 _Primitive-and-with-eax/imm32/next - 8421 # - and - 8422 _Primitive-and-with-eax: - 8423 # var/eax <- and lit => 25/and-with-eax lit/imm32 - 8424 "and"/imm32/name - 8425 Single-lit-var/imm32/inouts - 8426 Single-int-var-in-eax/imm32/outputs - 8427 "25/and-with-eax"/imm32/subx-name - 8428 0/imm32/no-rm32 - 8429 0/imm32/no-r32 - 8430 1/imm32/imm32-is-first-inout - 8431 0/imm32/no-disp32 - 8432 0/imm32/output-is-write-only - 8433 _Primitive-and-reg-with-reg/imm32/next - 8434 _Primitive-and-reg-with-reg: - 8435 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 - 8436 "and"/imm32/name - 8437 Single-int-var-in-some-register/imm32/inouts - 8438 Single-int-var-in-some-register/imm32/outputs - 8439 "21/and-with"/imm32/subx-name - 8440 3/imm32/rm32-is-first-output - 8441 1/imm32/r32-is-first-inout - 8442 0/imm32/no-imm32 - 8443 0/imm32/no-disp32 - 8444 0/imm32/output-is-write-only - 8445 _Primitive-and-reg-with-mem/imm32/next - 8446 _Primitive-and-reg-with-mem: - 8447 # and-with var1 var2/reg => 21/and-with var1 var2/r32 - 8448 "and-with"/imm32/name - 8449 Two-args-int-stack-int-reg/imm32/inouts - 8450 0/imm32/outputs - 8451 "21/and-with"/imm32/subx-name - 8452 1/imm32/rm32-is-first-inout - 8453 2/imm32/r32-is-second-inout - 8454 0/imm32/no-imm32 - 8455 0/imm32/no-disp32 - 8456 0/imm32/output-is-write-only - 8457 _Primitive-and-mem-with-reg/imm32/next - 8458 _Primitive-and-mem-with-reg: - 8459 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 - 8460 "and"/imm32/name - 8461 Single-int-var-in-mem/imm32/inouts - 8462 Single-int-var-in-some-register/imm32/outputs - 8463 "23/and"/imm32/subx-name - 8464 1/imm32/rm32-is-first-inout - 8465 3/imm32/r32-is-first-output - 8466 0/imm32/no-imm32 - 8467 0/imm32/no-disp32 - 8468 0/imm32/output-is-write-only - 8469 _Primitive-and-lit-with-reg/imm32/next - 8470 _Primitive-and-lit-with-reg: - 8471 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 - 8472 "and"/imm32/name - 8473 Single-lit-var/imm32/inouts - 8474 Single-int-var-in-some-register/imm32/outputs - 8475 "81 4/subop/and"/imm32/subx-name - 8476 3/imm32/rm32-is-first-output - 8477 0/imm32/no-r32 - 8478 1/imm32/imm32-is-first-inout - 8479 0/imm32/no-disp32 - 8480 0/imm32/output-is-write-only - 8481 _Primitive-and-lit-with-mem/imm32/next - 8482 _Primitive-and-lit-with-mem: - 8483 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 - 8484 "and-with"/imm32/name - 8485 Int-var-and-literal/imm32/inouts - 8486 0/imm32/outputs - 8487 "81 4/subop/and"/imm32/subx-name - 8488 1/imm32/rm32-is-first-inout - 8489 0/imm32/no-r32 - 8490 2/imm32/imm32-is-first-inout - 8491 0/imm32/no-disp32 - 8492 0/imm32/output-is-write-only - 8493 _Primitive-or-with-eax/imm32/next - 8494 # - or - 8495 _Primitive-or-with-eax: - 8496 # var/eax <- or lit => 0d/or-with-eax lit/imm32 - 8497 "or"/imm32/name - 8498 Single-lit-var/imm32/inouts - 8499 Single-int-var-in-eax/imm32/outputs - 8500 "0d/or-with-eax"/imm32/subx-name - 8501 0/imm32/no-rm32 - 8502 0/imm32/no-r32 - 8503 1/imm32/imm32-is-first-inout - 8504 0/imm32/no-disp32 - 8505 0/imm32/output-is-write-only - 8506 _Primitive-or-reg-with-reg/imm32/next - 8507 _Primitive-or-reg-with-reg: - 8508 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 - 8509 "or"/imm32/name - 8510 Single-int-var-in-some-register/imm32/inouts - 8511 Single-int-var-in-some-register/imm32/outputs - 8512 "09/or-with"/imm32/subx-name - 8513 3/imm32/rm32-is-first-output - 8514 1/imm32/r32-is-first-inout - 8515 0/imm32/no-imm32 - 8516 0/imm32/no-disp32 - 8517 0/imm32/output-is-write-only - 8518 _Primitive-or-reg-with-mem/imm32/next - 8519 _Primitive-or-reg-with-mem: - 8520 # or-with var1 var2/reg => 09/or-with var1 var2/r32 - 8521 "or-with"/imm32/name - 8522 Two-args-int-stack-int-reg/imm32/inouts - 8523 0/imm32/outputs - 8524 "09/or-with"/imm32/subx-name - 8525 1/imm32/rm32-is-first-inout - 8526 2/imm32/r32-is-second-inout - 8527 0/imm32/no-imm32 - 8528 0/imm32/no-disp32 - 8529 0/imm32/output-is-write-only - 8530 _Primitive-or-mem-with-reg/imm32/next - 8531 _Primitive-or-mem-with-reg: - 8532 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 - 8533 "or"/imm32/name - 8534 Single-int-var-in-mem/imm32/inouts - 8535 Single-int-var-in-some-register/imm32/outputs - 8536 "0b/or"/imm32/subx-name - 8537 1/imm32/rm32-is-first-inout - 8538 3/imm32/r32-is-first-output - 8539 0/imm32/no-imm32 - 8540 0/imm32/no-disp32 - 8541 0/imm32/output-is-write-only - 8542 _Primitive-or-lit-with-reg/imm32/next - 8543 _Primitive-or-lit-with-reg: - 8544 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 - 8545 "or"/imm32/name - 8546 Single-lit-var/imm32/inouts - 8547 Single-int-var-in-some-register/imm32/outputs - 8548 "81 1/subop/or"/imm32/subx-name - 8549 3/imm32/rm32-is-first-output - 8550 0/imm32/no-r32 - 8551 1/imm32/imm32-is-first-inout - 8552 0/imm32/no-disp32 - 8553 0/imm32/output-is-write-only - 8554 _Primitive-or-lit-with-mem/imm32/next - 8555 _Primitive-or-lit-with-mem: - 8556 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 - 8557 "or-with"/imm32/name - 8558 Int-var-and-literal/imm32/inouts - 8559 0/imm32/outputs - 8560 "81 1/subop/or"/imm32/subx-name - 8561 1/imm32/rm32-is-first-inout - 8562 0/imm32/no-r32 - 8563 2/imm32/imm32-is-second-inout - 8564 0/imm32/no-disp32 - 8565 0/imm32/output-is-write-only - 8566 _Primitive-xor-with-eax/imm32/next - 8567 # - xor - 8568 _Primitive-xor-with-eax: - 8569 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 - 8570 "xor"/imm32/name - 8571 Single-lit-var/imm32/inouts - 8572 Single-int-var-in-eax/imm32/outputs - 8573 "35/xor-with-eax"/imm32/subx-name - 8574 0/imm32/no-rm32 - 8575 0/imm32/no-r32 - 8576 1/imm32/imm32-is-first-inout - 8577 0/imm32/no-disp32 - 8578 0/imm32/output-is-write-only - 8579 _Primitive-xor-reg-with-reg/imm32/next - 8580 _Primitive-xor-reg-with-reg: - 8581 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 - 8582 "xor"/imm32/name - 8583 Single-int-var-in-some-register/imm32/inouts - 8584 Single-int-var-in-some-register/imm32/outputs - 8585 "31/xor-with"/imm32/subx-name - 8586 3/imm32/rm32-is-first-output - 8587 1/imm32/r32-is-first-inout - 8588 0/imm32/no-imm32 - 8589 0/imm32/no-disp32 - 8590 0/imm32/output-is-write-only - 8591 _Primitive-xor-reg-with-mem/imm32/next - 8592 _Primitive-xor-reg-with-mem: - 8593 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 - 8594 "xor-with"/imm32/name - 8595 Two-args-int-stack-int-reg/imm32/inouts - 8596 0/imm32/outputs - 8597 "31/xor-with"/imm32/subx-name - 8598 1/imm32/rm32-is-first-inout - 8599 2/imm32/r32-is-second-inout - 8600 0/imm32/no-imm32 - 8601 0/imm32/no-disp32 - 8602 0/imm32/output-is-write-only - 8603 _Primitive-xor-mem-with-reg/imm32/next - 8604 _Primitive-xor-mem-with-reg: - 8605 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 - 8606 "xor"/imm32/name - 8607 Single-int-var-in-mem/imm32/inouts - 8608 Single-int-var-in-some-register/imm32/outputs - 8609 "33/xor"/imm32/subx-name - 8610 1/imm32/rm32-is-first-inout - 8611 3/imm32/r32-is-first-output - 8612 0/imm32/no-imm32 - 8613 0/imm32/no-disp32 - 8614 0/imm32/output-is-write-only - 8615 _Primitive-xor-lit-with-reg/imm32/next - 8616 _Primitive-xor-lit-with-reg: - 8617 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 - 8618 "xor"/imm32/name - 8619 Single-lit-var/imm32/inouts - 8620 Single-int-var-in-some-register/imm32/outputs - 8621 "81 6/subop/xor"/imm32/subx-name - 8622 3/imm32/rm32-is-first-output - 8623 0/imm32/no-r32 - 8624 1/imm32/imm32-is-first-inout - 8625 0/imm32/no-disp32 - 8626 0/imm32/output-is-write-only - 8627 _Primitive-xor-lit-with-mem/imm32/next - 8628 _Primitive-xor-lit-with-mem: - 8629 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 - 8630 "xor-with"/imm32/name - 8631 Int-var-and-literal/imm32/inouts - 8632 0/imm32/outputs - 8633 "81 6/subop/xor"/imm32/subx-name - 8634 1/imm32/rm32-is-first-inout - 8635 0/imm32/no-r32 - 8636 2/imm32/imm32-is-first-inout - 8637 0/imm32/no-disp32 - 8638 0/imm32/output-is-write-only - 8639 _Primitive-copy-to-eax/imm32/next - 8640 # - copy - 8641 _Primitive-copy-to-eax: - 8642 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 - 8643 "copy"/imm32/name - 8644 Single-lit-var/imm32/inouts - 8645 Single-int-var-in-eax/imm32/outputs - 8646 "b8/copy-to-eax"/imm32/subx-name - 8647 0/imm32/no-rm32 - 8648 0/imm32/no-r32 - 8649 1/imm32/imm32-is-first-inout - 8650 0/imm32/no-disp32 - 8651 1/imm32/output-is-write-only - 8652 _Primitive-copy-to-ecx/imm32/next - 8653 _Primitive-copy-to-ecx: - 8654 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 - 8655 "copy"/imm32/name - 8656 Single-lit-var/imm32/inouts - 8657 Single-int-var-in-ecx/imm32/outputs - 8658 "b9/copy-to-ecx"/imm32/subx-name - 8659 0/imm32/no-rm32 - 8660 0/imm32/no-r32 - 8661 1/imm32/imm32-is-first-inout - 8662 0/imm32/no-disp32 - 8663 1/imm32/output-is-write-only - 8664 _Primitive-copy-to-edx/imm32/next - 8665 _Primitive-copy-to-edx: - 8666 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 - 8667 "copy"/imm32/name - 8668 Single-lit-var/imm32/inouts - 8669 Single-int-var-in-edx/imm32/outputs - 8670 "ba/copy-to-edx"/imm32/subx-name - 8671 0/imm32/no-rm32 - 8672 0/imm32/no-r32 - 8673 1/imm32/imm32-is-first-inout - 8674 0/imm32/no-disp32 - 8675 1/imm32/output-is-write-only - 8676 _Primitive-copy-to-ebx/imm32/next - 8677 _Primitive-copy-to-ebx: - 8678 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 - 8679 "copy"/imm32/name - 8680 Single-lit-var/imm32/inouts - 8681 Single-int-var-in-ebx/imm32/outputs - 8682 "bb/copy-to-ebx"/imm32/subx-name - 8683 0/imm32/no-rm32 - 8684 0/imm32/no-r32 - 8685 1/imm32/imm32-is-first-inout - 8686 0/imm32/no-disp32 - 8687 1/imm32/output-is-write-only - 8688 _Primitive-copy-to-esi/imm32/next - 8689 _Primitive-copy-to-esi: - 8690 # var/esi <- copy lit => be/copy-to-esi lit/imm32 - 8691 "copy"/imm32/name - 8692 Single-lit-var/imm32/inouts - 8693 Single-int-var-in-esi/imm32/outputs - 8694 "be/copy-to-esi"/imm32/subx-name - 8695 0/imm32/no-rm32 - 8696 0/imm32/no-r32 - 8697 1/imm32/imm32-is-first-inout - 8698 0/imm32/no-disp32 - 8699 1/imm32/output-is-write-only - 8700 _Primitive-copy-to-edi/imm32/next - 8701 _Primitive-copy-to-edi: - 8702 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 - 8703 "copy"/imm32/name - 8704 Single-lit-var/imm32/inouts - 8705 Single-int-var-in-edi/imm32/outputs - 8706 "bf/copy-to-edi"/imm32/subx-name - 8707 0/imm32/no-rm32 - 8708 0/imm32/no-r32 - 8709 1/imm32/imm32-is-first-inout - 8710 0/imm32/no-disp32 - 8711 1/imm32/output-is-write-only - 8712 _Primitive-copy-reg-to-reg/imm32/next - 8713 _Primitive-copy-reg-to-reg: - 8714 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 - 8715 "copy"/imm32/name - 8716 Single-int-var-in-some-register/imm32/inouts - 8717 Single-int-var-in-some-register/imm32/outputs - 8718 "89/copy-to"/imm32/subx-name - 8719 3/imm32/rm32-is-first-output - 8720 1/imm32/r32-is-first-inout - 8721 0/imm32/no-imm32 - 8722 0/imm32/no-disp32 - 8723 1/imm32/output-is-write-only - 8724 _Primitive-copy-reg-to-mem/imm32/next - 8725 _Primitive-copy-reg-to-mem: - 8726 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 - 8727 "copy-to"/imm32/name - 8728 Two-args-int-stack-int-reg/imm32/inouts - 8729 0/imm32/outputs - 8730 "89/copy-to"/imm32/subx-name - 8731 1/imm32/rm32-is-first-inout - 8732 2/imm32/r32-is-second-inout - 8733 0/imm32/no-imm32 - 8734 0/imm32/no-disp32 - 8735 1/imm32/output-is-write-only - 8736 _Primitive-copy-mem-to-reg/imm32/next - 8737 _Primitive-copy-mem-to-reg: - 8738 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 - 8739 "copy"/imm32/name - 8740 Single-int-var-in-mem/imm32/inouts - 8741 Single-int-var-in-some-register/imm32/outputs - 8742 "8b/copy-from"/imm32/subx-name - 8743 1/imm32/rm32-is-first-inout - 8744 3/imm32/r32-is-first-output - 8745 0/imm32/no-imm32 - 8746 0/imm32/no-disp32 - 8747 1/imm32/output-is-write-only - 8748 _Primitive-copy-lit-to-reg/imm32/next - 8749 _Primitive-copy-lit-to-reg: - 8750 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 - 8751 "copy"/imm32/name - 8752 Single-lit-var/imm32/inouts - 8753 Single-int-var-in-some-register/imm32/outputs - 8754 "c7 0/subop/copy"/imm32/subx-name - 8755 3/imm32/rm32-is-first-output - 8756 0/imm32/no-r32 - 8757 1/imm32/imm32-is-first-inout - 8758 0/imm32/no-disp32 - 8759 1/imm32/output-is-write-only - 8760 _Primitive-copy-lit-to-mem/imm32/next - 8761 _Primitive-copy-lit-to-mem: - 8762 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 - 8763 "copy-to"/imm32/name - 8764 Int-var-and-literal/imm32/inouts - 8765 0/imm32/outputs - 8766 "c7 0/subop/copy"/imm32/subx-name - 8767 1/imm32/rm32-is-first-inout - 8768 0/imm32/no-r32 - 8769 2/imm32/imm32-is-first-inout - 8770 0/imm32/no-disp32 - 8771 1/imm32/output-is-write-only - 8772 _Primitive-compare-mem-with-reg/imm32/next - 8773 # - compare - 8774 _Primitive-compare-mem-with-reg: - 8775 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 - 8776 "compare"/imm32/name - 8777 Two-args-int-stack-int-reg/imm32/inouts - 8778 0/imm32/outputs - 8779 "39/compare->"/imm32/subx-name - 8780 1/imm32/rm32-is-first-inout - 8781 2/imm32/r32-is-second-inout - 8782 0/imm32/no-imm32 - 8783 0/imm32/no-disp32 - 8784 0/imm32/output-is-write-only - 8785 _Primitive-compare-reg-with-mem/imm32/next - 8786 _Primitive-compare-reg-with-mem: - 8787 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 - 8788 "compare"/imm32/name - 8789 Two-args-int-reg-int-stack/imm32/inouts - 8790 0/imm32/outputs - 8791 "3b/compare<-"/imm32/subx-name - 8792 2/imm32/rm32-is-second-inout - 8793 1/imm32/r32-is-first-inout - 8794 0/imm32/no-imm32 - 8795 0/imm32/no-disp32 - 8796 0/imm32/output-is-write-only - 8797 _Primitive-compare-eax-with-literal/imm32/next - 8798 _Primitive-compare-eax-with-literal: - 8799 # compare var1/eax n => 3d/compare-eax-with n/imm32 - 8800 "compare"/imm32/name - 8801 Two-args-int-eax-int-literal/imm32/inouts - 8802 0/imm32/outputs - 8803 "3d/compare-eax-with"/imm32/subx-name - 8804 0/imm32/no-rm32 - 8805 0/imm32/no-r32 - 8806 2/imm32/imm32-is-second-inout - 8807 0/imm32/no-disp32 - 8808 0/imm32/output-is-write-only - 8809 _Primitive-compare-reg-with-literal/imm32/next - 8810 _Primitive-compare-reg-with-literal: - 8811 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 - 8812 "compare"/imm32/name - 8813 Int-var-in-register-and-literal/imm32/inouts - 8814 0/imm32/outputs - 8815 "81 7/subop/compare"/imm32/subx-name - 8816 1/imm32/rm32-is-first-inout - 8817 0/imm32/no-r32 - 8818 2/imm32/imm32-is-second-inout - 8819 0/imm32/no-disp32 - 8820 0/imm32/output-is-write-only - 8821 _Primitive-compare-mem-with-literal/imm32/next - 8822 _Primitive-compare-mem-with-literal: - 8823 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 - 8824 "compare"/imm32/name - 8825 Int-var-and-literal/imm32/inouts - 8826 0/imm32/outputs - 8827 "81 7/subop/compare"/imm32/subx-name - 8828 1/imm32/rm32-is-first-inout - 8829 0/imm32/no-r32 - 8830 2/imm32/imm32-is-second-inout - 8831 0/imm32/no-disp32 - 8832 0/imm32/output-is-write-only - 8833 _Primitive-multiply-reg-by-mem/imm32/next - 8834 # - multiply - 8835 _Primitive-multiply-reg-by-mem: - 8836 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 - 8837 "multiply"/imm32/name - 8838 Single-int-var-in-mem/imm32/inouts - 8839 Single-int-var-in-some-register/imm32/outputs - 8840 "0f af/multiply"/imm32/subx-name - 8841 1/imm32/rm32-is-first-inout - 8842 3/imm32/r32-is-first-output - 8843 0/imm32/no-imm32 - 8844 0/imm32/no-disp32 - 8845 0/imm32/output-is-write-only - 8846 _Primitive-break-if-addr</imm32/next - 8847 # - branches - 8848 _Primitive-break-if-addr<: - 8849 "break-if-addr<"/imm32/name - 8850 0/imm32/inouts - 8851 0/imm32/outputs - 8852 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name - 8853 0/imm32/no-rm32 - 8854 0/imm32/no-r32 - 8855 0/imm32/no-imm32 - 8856 0/imm32/no-disp32 - 8857 0/imm32/no-output - 8858 _Primitive-break-if-addr>=/imm32/next - 8859 _Primitive-break-if-addr>=: - 8860 "break-if-addr>="/imm32/name - 8861 0/imm32/inouts - 8862 0/imm32/outputs - 8863 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name - 8864 0/imm32/no-rm32 - 8865 0/imm32/no-r32 - 8866 0/imm32/no-imm32 - 8867 0/imm32/no-disp32 - 8868 0/imm32/no-output - 8869 _Primitive-break-if-=/imm32/next - 8870 _Primitive-break-if-=: - 8871 "break-if-="/imm32/name - 8872 0/imm32/inouts + 8018 48/decrement-eax + 8019 # var tmp2/eax: int = n & tmp + 8020 0b/and-> *(ebp+8) 0/r32/eax + 8021 # return (tmp2 == 0) + 8022 3d/compare-eax-and 0/imm32 + 8023 0f 94/set-byte-if-= %al + 8024 81 4/subop/and %eax 0xff/imm32 + 8025 $power-of-2?:end: + 8026 # . epilogue + 8027 89/<- %esp 5/r32/ebp + 8028 5d/pop-to-ebp + 8029 c3/return + 8030 + 8031 num-shift-rights: # n: int -> result/eax: int + 8032 # precondition: n is a positive power of 2 + 8033 # . prologue + 8034 55/push-ebp + 8035 89/<- %ebp 4/r32/esp + 8036 # . save registers + 8037 51/push-ecx + 8038 # var curr/ecx: int = n + 8039 8b/-> *(ebp+8) 1/r32/ecx + 8040 # result = 0 + 8041 b8/copy-to-eax 0/imm32 + 8042 { + 8043 # if (curr <= 1) break + 8044 81 7/subop/compare %ecx 1/imm32 + 8045 7e/jump-if-<= break/disp8 + 8046 40/increment-eax + 8047 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 + 8048 eb/jump loop/disp8 + 8049 } + 8050 $num-shift-rights:end: + 8051 # . restore registers + 8052 59/pop-to-ecx + 8053 # . epilogue + 8054 89/<- %esp 5/r32/ebp + 8055 5d/pop-to-ebp + 8056 c3/return + 8057 + 8058 mu-get-offset: # stmt: (handle stmt) -> result/eax: int + 8059 # . prologue + 8060 55/push-ebp + 8061 89/<- %ebp 4/r32/esp + 8062 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next + 8063 8b/-> *(ebp+8) 0/r32/eax + 8064 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts + 8065 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 8066 # var output-var/eax: (handle var) = second-inout->value + 8067 8b/-> *eax 0/r32/eax # Stmt-var-value + 8068 # return output-var->offset + 8069 8b/-> *(eax+0xc) 0/r32/eax # Var-offset + 8070 $emit-get-offset:end: + 8071 # . epilogue + 8072 89/<- %esp 5/r32/ebp + 8073 5d/pop-to-ebp + 8074 c3/return + 8075 + 8076 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) + 8077 # . prologue + 8078 55/push-ebp + 8079 89/<- %ebp 4/r32/esp + 8080 # . save registers + 8081 50/push-eax + 8082 51/push-ecx + 8083 56/push-esi + 8084 # esi = block + 8085 8b/-> *(ebp+0xc) 6/r32/esi + 8086 # block->var->block-depth = *Curr-block-depth + 8087 8b/-> *(esi+8) 0/r32/eax # Block-var + 8088 8b/-> *Curr-block-depth 1/r32/ecx + 8089 89/<- *(eax+8) 1/r32/ecx # Var-block-depth + 8090 # var stmts/eax: (handle list stmt) = block->statements + 8091 8b/-> *(esi+4) 0/r32/eax # Block-stmts + 8092 # + 8093 { + 8094 $emit-subx-block:check-empty: + 8095 3d/compare-eax-and 0/imm32 + 8096 0f 84/jump-if-= break/disp32 + 8097 (emit-indent *(ebp+8) *Curr-block-depth) + 8098 (write-buffered *(ebp+8) "{\n") + 8099 # var v/ecx: (handle var) + 8100 8b/-> *(esi+8) 1/r32/ecx # Block-var + 8101 # + 8102 (write-buffered *(ebp+8) *ecx) # Var-name + 8103 (write-buffered *(ebp+8) ":loop:\n") + 8104 ff 0/subop/increment *Curr-block-depth + 8105 (push *(ebp+0x10) %ecx) + 8106 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) + 8107 (pop *(ebp+0x10)) # => eax + 8108 ff 1/subop/decrement *Curr-block-depth + 8109 (emit-indent *(ebp+8) *Curr-block-depth) + 8110 (write-buffered *(ebp+8) "}\n") + 8111 (write-buffered *(ebp+8) *ecx) # Var-name + 8112 (write-buffered *(ebp+8) ":break:\n") + 8113 } + 8114 $emit-subx-block:end: + 8115 # . restore registers + 8116 5e/pop-to-esi + 8117 59/pop-to-ecx + 8118 58/pop-to-eax + 8119 # . epilogue + 8120 89/<- %esp 5/r32/ebp + 8121 5d/pop-to-ebp + 8122 c3/return + 8123 + 8124 # Primitives supported + 8125 # For each operation, put variants with hard-coded registers before flexible ones. + 8126 == data + 8127 Primitives: + 8128 # - increment/decrement + 8129 _Primitive-inc-eax: + 8130 # var/eax <- increment => 40/increment-eax + 8131 "increment"/imm32/name + 8132 0/imm32/no-inouts + 8133 Single-int-var-in-eax/imm32/outputs + 8134 "40/increment-eax"/imm32/subx-name + 8135 0/imm32/no-rm32 + 8136 0/imm32/no-r32 + 8137 0/imm32/no-imm32 + 8138 0/imm32/no-disp32 + 8139 0/imm32/output-is-write-only + 8140 _Primitive-inc-ecx/imm32/next + 8141 _Primitive-inc-ecx: + 8142 # var/ecx <- increment => 41/increment-ecx + 8143 "increment"/imm32/name + 8144 0/imm32/no-inouts + 8145 Single-int-var-in-ecx/imm32/outputs + 8146 "41/increment-ecx"/imm32/subx-name + 8147 0/imm32/no-rm32 + 8148 0/imm32/no-r32 + 8149 0/imm32/no-imm32 + 8150 0/imm32/no-disp32 + 8151 0/imm32/output-is-write-only + 8152 _Primitive-inc-edx/imm32/next + 8153 _Primitive-inc-edx: + 8154 # var/edx <- increment => 42/increment-edx + 8155 "increment"/imm32/name + 8156 0/imm32/no-inouts + 8157 Single-int-var-in-edx/imm32/outputs + 8158 "42/increment-edx"/imm32/subx-name + 8159 0/imm32/no-rm32 + 8160 0/imm32/no-r32 + 8161 0/imm32/no-imm32 + 8162 0/imm32/no-disp32 + 8163 0/imm32/output-is-write-only + 8164 _Primitive-inc-ebx/imm32/next + 8165 _Primitive-inc-ebx: + 8166 # var/ebx <- increment => 43/increment-ebx + 8167 "increment"/imm32/name + 8168 0/imm32/no-inouts + 8169 Single-int-var-in-ebx/imm32/outputs + 8170 "43/increment-ebx"/imm32/subx-name + 8171 0/imm32/no-rm32 + 8172 0/imm32/no-r32 + 8173 0/imm32/no-imm32 + 8174 0/imm32/no-disp32 + 8175 0/imm32/output-is-write-only + 8176 _Primitive-inc-esi/imm32/next + 8177 _Primitive-inc-esi: + 8178 # var/esi <- increment => 46/increment-esi + 8179 "increment"/imm32/name + 8180 0/imm32/no-inouts + 8181 Single-int-var-in-esi/imm32/outputs + 8182 "46/increment-esi"/imm32/subx-name + 8183 0/imm32/no-rm32 + 8184 0/imm32/no-r32 + 8185 0/imm32/no-imm32 + 8186 0/imm32/no-disp32 + 8187 0/imm32/output-is-write-only + 8188 _Primitive-inc-edi/imm32/next + 8189 _Primitive-inc-edi: + 8190 # var/edi <- increment => 47/increment-edi + 8191 "increment"/imm32/name + 8192 0/imm32/no-inouts + 8193 Single-int-var-in-edi/imm32/outputs + 8194 "47/increment-edi"/imm32/subx-name + 8195 0/imm32/no-rm32 + 8196 0/imm32/no-r32 + 8197 0/imm32/no-imm32 + 8198 0/imm32/no-disp32 + 8199 0/imm32/output-is-write-only + 8200 _Primitive-dec-eax/imm32/next + 8201 _Primitive-dec-eax: + 8202 # var/eax <- decrement => 48/decrement-eax + 8203 "decrement"/imm32/name + 8204 0/imm32/no-inouts + 8205 Single-int-var-in-eax/imm32/outputs + 8206 "48/decrement-eax"/imm32/subx-name + 8207 0/imm32/no-rm32 + 8208 0/imm32/no-r32 + 8209 0/imm32/no-imm32 + 8210 0/imm32/no-disp32 + 8211 0/imm32/output-is-write-only + 8212 _Primitive-dec-ecx/imm32/next + 8213 _Primitive-dec-ecx: + 8214 # var/ecx <- decrement => 49/decrement-ecx + 8215 "decrement"/imm32/name + 8216 0/imm32/no-inouts + 8217 Single-int-var-in-ecx/imm32/outputs + 8218 "49/decrement-ecx"/imm32/subx-name + 8219 0/imm32/no-rm32 + 8220 0/imm32/no-r32 + 8221 0/imm32/no-imm32 + 8222 0/imm32/no-disp32 + 8223 0/imm32/output-is-write-only + 8224 _Primitive-dec-edx/imm32/next + 8225 _Primitive-dec-edx: + 8226 # var/edx <- decrement => 4a/decrement-edx + 8227 "decrement"/imm32/name + 8228 0/imm32/no-inouts + 8229 Single-int-var-in-edx/imm32/outputs + 8230 "4a/decrement-edx"/imm32/subx-name + 8231 0/imm32/no-rm32 + 8232 0/imm32/no-r32 + 8233 0/imm32/no-imm32 + 8234 0/imm32/no-disp32 + 8235 0/imm32/output-is-write-only + 8236 _Primitive-dec-ebx/imm32/next + 8237 _Primitive-dec-ebx: + 8238 # var/ebx <- decrement => 4b/decrement-ebx + 8239 "decrement"/imm32/name + 8240 0/imm32/no-inouts + 8241 Single-int-var-in-ebx/imm32/outputs + 8242 "4b/decrement-ebx"/imm32/subx-name + 8243 0/imm32/no-rm32 + 8244 0/imm32/no-r32 + 8245 0/imm32/no-imm32 + 8246 0/imm32/no-disp32 + 8247 0/imm32/output-is-write-only + 8248 _Primitive-dec-esi/imm32/next + 8249 _Primitive-dec-esi: + 8250 # var/esi <- decrement => 4e/decrement-esi + 8251 "decrement"/imm32/name + 8252 0/imm32/no-inouts + 8253 Single-int-var-in-esi/imm32/outputs + 8254 "4e/decrement-esi"/imm32/subx-name + 8255 0/imm32/no-rm32 + 8256 0/imm32/no-r32 + 8257 0/imm32/no-imm32 + 8258 0/imm32/no-disp32 + 8259 0/imm32/output-is-write-only + 8260 _Primitive-dec-edi/imm32/next + 8261 _Primitive-dec-edi: + 8262 # var/edi <- decrement => 4f/decrement-edi + 8263 "decrement"/imm32/name + 8264 0/imm32/no-inouts + 8265 Single-int-var-in-edi/imm32/outputs + 8266 "4f/decrement-edi"/imm32/subx-name + 8267 0/imm32/no-rm32 + 8268 0/imm32/no-r32 + 8269 0/imm32/no-imm32 + 8270 0/imm32/no-disp32 + 8271 0/imm32/output-is-write-only + 8272 _Primitive-inc-mem/imm32/next + 8273 _Primitive-inc-mem: + 8274 # increment var => ff 0/subop/increment *(ebp+__) + 8275 "increment"/imm32/name + 8276 Single-int-var-in-mem/imm32/inouts + 8277 0/imm32/no-outputs + 8278 "ff 0/subop/increment"/imm32/subx-name + 8279 1/imm32/rm32-is-first-inout + 8280 0/imm32/no-r32 + 8281 0/imm32/no-imm32 + 8282 0/imm32/no-disp32 + 8283 0/imm32/output-is-write-only + 8284 _Primitive-inc-reg/imm32/next + 8285 _Primitive-inc-reg: + 8286 # var/reg <- increment => ff 0/subop/increment %__ + 8287 "increment"/imm32/name + 8288 0/imm32/no-inouts + 8289 Single-int-var-in-some-register/imm32/outputs + 8290 "ff 0/subop/increment"/imm32/subx-name + 8291 3/imm32/rm32-is-first-output + 8292 0/imm32/no-r32 + 8293 0/imm32/no-imm32 + 8294 0/imm32/no-disp32 + 8295 0/imm32/output-is-write-only + 8296 _Primitive-dec-mem/imm32/next + 8297 _Primitive-dec-mem: + 8298 # decrement var => ff 1/subop/decrement *(ebp+__) + 8299 "decrement"/imm32/name + 8300 Single-int-var-in-mem/imm32/inouts + 8301 0/imm32/no-outputs + 8302 "ff 1/subop/decrement"/imm32/subx-name + 8303 1/imm32/rm32-is-first-inout + 8304 0/imm32/no-r32 + 8305 0/imm32/no-imm32 + 8306 0/imm32/no-disp32 + 8307 0/imm32/output-is-write-only + 8308 _Primitive-dec-reg/imm32/next + 8309 _Primitive-dec-reg: + 8310 # var/reg <- decrement => ff 1/subop/decrement %__ + 8311 "decrement"/imm32/name + 8312 0/imm32/no-inouts + 8313 Single-int-var-in-some-register/imm32/outputs + 8314 "ff 1/subop/decrement"/imm32/subx-name + 8315 3/imm32/rm32-is-first-output + 8316 0/imm32/no-r32 + 8317 0/imm32/no-imm32 + 8318 0/imm32/no-disp32 + 8319 0/imm32/output-is-write-only + 8320 _Primitive-add-to-eax/imm32/next + 8321 # - add + 8322 _Primitive-add-to-eax: + 8323 # var/eax <- add lit => 05/add-to-eax lit/imm32 + 8324 "add"/imm32/name + 8325 Single-lit-var/imm32/inouts + 8326 Single-int-var-in-eax/imm32/outputs + 8327 "05/add-to-eax"/imm32/subx-name + 8328 0/imm32/no-rm32 + 8329 0/imm32/no-r32 + 8330 1/imm32/imm32-is-first-inout + 8331 0/imm32/no-disp32 + 8332 0/imm32/output-is-write-only + 8333 _Primitive-add-reg-to-reg/imm32/next + 8334 _Primitive-add-reg-to-reg: + 8335 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 + 8336 "add"/imm32/name + 8337 Single-int-var-in-some-register/imm32/inouts + 8338 Single-int-var-in-some-register/imm32/outputs + 8339 "01/add-to"/imm32/subx-name + 8340 3/imm32/rm32-is-first-output + 8341 1/imm32/r32-is-first-inout + 8342 0/imm32/no-imm32 + 8343 0/imm32/no-disp32 + 8344 0/imm32/output-is-write-only + 8345 _Primitive-add-reg-to-mem/imm32/next + 8346 _Primitive-add-reg-to-mem: + 8347 # add-to var1 var2/reg => 01/add-to var1 var2/r32 + 8348 "add-to"/imm32/name + 8349 Two-args-int-stack-int-reg/imm32/inouts + 8350 0/imm32/outputs + 8351 "01/add-to"/imm32/subx-name + 8352 1/imm32/rm32-is-first-inout + 8353 2/imm32/r32-is-second-inout + 8354 0/imm32/no-imm32 + 8355 0/imm32/no-disp32 + 8356 0/imm32/output-is-write-only + 8357 _Primitive-add-mem-to-reg/imm32/next + 8358 _Primitive-add-mem-to-reg: + 8359 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 + 8360 "add"/imm32/name + 8361 Single-int-var-in-mem/imm32/inouts + 8362 Single-int-var-in-some-register/imm32/outputs + 8363 "03/add"/imm32/subx-name + 8364 1/imm32/rm32-is-first-inout + 8365 3/imm32/r32-is-first-output + 8366 0/imm32/no-imm32 + 8367 0/imm32/no-disp32 + 8368 0/imm32/output-is-write-only + 8369 _Primitive-add-lit-to-reg/imm32/next + 8370 _Primitive-add-lit-to-reg: + 8371 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 + 8372 "add"/imm32/name + 8373 Single-lit-var/imm32/inouts + 8374 Single-int-var-in-some-register/imm32/outputs + 8375 "81 0/subop/add"/imm32/subx-name + 8376 3/imm32/rm32-is-first-output + 8377 0/imm32/no-r32 + 8378 1/imm32/imm32-is-first-inout + 8379 0/imm32/no-disp32 + 8380 0/imm32/output-is-write-only + 8381 _Primitive-add-lit-to-mem/imm32/next + 8382 _Primitive-add-lit-to-mem: + 8383 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 + 8384 "add-to"/imm32/name + 8385 Int-var-and-literal/imm32/inouts + 8386 0/imm32/outputs + 8387 "81 0/subop/add"/imm32/subx-name + 8388 1/imm32/rm32-is-first-inout + 8389 0/imm32/no-r32 + 8390 2/imm32/imm32-is-second-inout + 8391 0/imm32/no-disp32 + 8392 0/imm32/output-is-write-only + 8393 _Primitive-subtract-from-eax/imm32/next + 8394 # - subtract + 8395 _Primitive-subtract-from-eax: + 8396 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 + 8397 "subtract"/imm32/name + 8398 Single-lit-var/imm32/inouts + 8399 Single-int-var-in-eax/imm32/outputs + 8400 "2d/subtract-from-eax"/imm32/subx-name + 8401 0/imm32/no-rm32 + 8402 0/imm32/no-r32 + 8403 1/imm32/imm32-is-first-inout + 8404 0/imm32/no-disp32 + 8405 0/imm32/output-is-write-only + 8406 _Primitive-subtract-reg-from-reg/imm32/next + 8407 _Primitive-subtract-reg-from-reg: + 8408 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 + 8409 "subtract"/imm32/name + 8410 Single-int-var-in-some-register/imm32/inouts + 8411 Single-int-var-in-some-register/imm32/outputs + 8412 "29/subtract-from"/imm32/subx-name + 8413 3/imm32/rm32-is-first-output + 8414 1/imm32/r32-is-first-inout + 8415 0/imm32/no-imm32 + 8416 0/imm32/no-disp32 + 8417 0/imm32/output-is-write-only + 8418 _Primitive-subtract-reg-from-mem/imm32/next + 8419 _Primitive-subtract-reg-from-mem: + 8420 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 + 8421 "subtract-from"/imm32/name + 8422 Two-args-int-stack-int-reg/imm32/inouts + 8423 0/imm32/outputs + 8424 "29/subtract-from"/imm32/subx-name + 8425 1/imm32/rm32-is-first-inout + 8426 2/imm32/r32-is-second-inout + 8427 0/imm32/no-imm32 + 8428 0/imm32/no-disp32 + 8429 0/imm32/output-is-write-only + 8430 _Primitive-subtract-mem-from-reg/imm32/next + 8431 _Primitive-subtract-mem-from-reg: + 8432 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 + 8433 "subtract"/imm32/name + 8434 Single-int-var-in-mem/imm32/inouts + 8435 Single-int-var-in-some-register/imm32/outputs + 8436 "2b/subtract"/imm32/subx-name + 8437 1/imm32/rm32-is-first-inout + 8438 3/imm32/r32-is-first-output + 8439 0/imm32/no-imm32 + 8440 0/imm32/no-disp32 + 8441 0/imm32/output-is-write-only + 8442 _Primitive-subtract-lit-from-reg/imm32/next + 8443 _Primitive-subtract-lit-from-reg: + 8444 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 8445 "subtract"/imm32/name + 8446 Single-lit-var/imm32/inouts + 8447 Single-int-var-in-some-register/imm32/outputs + 8448 "81 5/subop/subtract"/imm32/subx-name + 8449 3/imm32/rm32-is-first-output + 8450 0/imm32/no-r32 + 8451 1/imm32/imm32-is-first-inout + 8452 0/imm32/no-disp32 + 8453 0/imm32/output-is-write-only + 8454 _Primitive-subtract-lit-from-mem/imm32/next + 8455 _Primitive-subtract-lit-from-mem: + 8456 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 8457 "subtract-from"/imm32/name + 8458 Int-var-and-literal/imm32/inouts + 8459 0/imm32/outputs + 8460 "81 5/subop/subtract"/imm32/subx-name + 8461 1/imm32/rm32-is-first-inout + 8462 0/imm32/no-r32 + 8463 2/imm32/imm32-is-first-inout + 8464 0/imm32/no-disp32 + 8465 0/imm32/output-is-write-only + 8466 _Primitive-and-with-eax/imm32/next + 8467 # - and + 8468 _Primitive-and-with-eax: + 8469 # var/eax <- and lit => 25/and-with-eax lit/imm32 + 8470 "and"/imm32/name + 8471 Single-lit-var/imm32/inouts + 8472 Single-int-var-in-eax/imm32/outputs + 8473 "25/and-with-eax"/imm32/subx-name + 8474 0/imm32/no-rm32 + 8475 0/imm32/no-r32 + 8476 1/imm32/imm32-is-first-inout + 8477 0/imm32/no-disp32 + 8478 0/imm32/output-is-write-only + 8479 _Primitive-and-reg-with-reg/imm32/next + 8480 _Primitive-and-reg-with-reg: + 8481 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 + 8482 "and"/imm32/name + 8483 Single-int-var-in-some-register/imm32/inouts + 8484 Single-int-var-in-some-register/imm32/outputs + 8485 "21/and-with"/imm32/subx-name + 8486 3/imm32/rm32-is-first-output + 8487 1/imm32/r32-is-first-inout + 8488 0/imm32/no-imm32 + 8489 0/imm32/no-disp32 + 8490 0/imm32/output-is-write-only + 8491 _Primitive-and-reg-with-mem/imm32/next + 8492 _Primitive-and-reg-with-mem: + 8493 # and-with var1 var2/reg => 21/and-with var1 var2/r32 + 8494 "and-with"/imm32/name + 8495 Two-args-int-stack-int-reg/imm32/inouts + 8496 0/imm32/outputs + 8497 "21/and-with"/imm32/subx-name + 8498 1/imm32/rm32-is-first-inout + 8499 2/imm32/r32-is-second-inout + 8500 0/imm32/no-imm32 + 8501 0/imm32/no-disp32 + 8502 0/imm32/output-is-write-only + 8503 _Primitive-and-mem-with-reg/imm32/next + 8504 _Primitive-and-mem-with-reg: + 8505 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 + 8506 "and"/imm32/name + 8507 Single-int-var-in-mem/imm32/inouts + 8508 Single-int-var-in-some-register/imm32/outputs + 8509 "23/and"/imm32/subx-name + 8510 1/imm32/rm32-is-first-inout + 8511 3/imm32/r32-is-first-output + 8512 0/imm32/no-imm32 + 8513 0/imm32/no-disp32 + 8514 0/imm32/output-is-write-only + 8515 _Primitive-and-lit-with-reg/imm32/next + 8516 _Primitive-and-lit-with-reg: + 8517 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 + 8518 "and"/imm32/name + 8519 Single-lit-var/imm32/inouts + 8520 Single-int-var-in-some-register/imm32/outputs + 8521 "81 4/subop/and"/imm32/subx-name + 8522 3/imm32/rm32-is-first-output + 8523 0/imm32/no-r32 + 8524 1/imm32/imm32-is-first-inout + 8525 0/imm32/no-disp32 + 8526 0/imm32/output-is-write-only + 8527 _Primitive-and-lit-with-mem/imm32/next + 8528 _Primitive-and-lit-with-mem: + 8529 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 + 8530 "and-with"/imm32/name + 8531 Int-var-and-literal/imm32/inouts + 8532 0/imm32/outputs + 8533 "81 4/subop/and"/imm32/subx-name + 8534 1/imm32/rm32-is-first-inout + 8535 0/imm32/no-r32 + 8536 2/imm32/imm32-is-first-inout + 8537 0/imm32/no-disp32 + 8538 0/imm32/output-is-write-only + 8539 _Primitive-or-with-eax/imm32/next + 8540 # - or + 8541 _Primitive-or-with-eax: + 8542 # var/eax <- or lit => 0d/or-with-eax lit/imm32 + 8543 "or"/imm32/name + 8544 Single-lit-var/imm32/inouts + 8545 Single-int-var-in-eax/imm32/outputs + 8546 "0d/or-with-eax"/imm32/subx-name + 8547 0/imm32/no-rm32 + 8548 0/imm32/no-r32 + 8549 1/imm32/imm32-is-first-inout + 8550 0/imm32/no-disp32 + 8551 0/imm32/output-is-write-only + 8552 _Primitive-or-reg-with-reg/imm32/next + 8553 _Primitive-or-reg-with-reg: + 8554 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 + 8555 "or"/imm32/name + 8556 Single-int-var-in-some-register/imm32/inouts + 8557 Single-int-var-in-some-register/imm32/outputs + 8558 "09/or-with"/imm32/subx-name + 8559 3/imm32/rm32-is-first-output + 8560 1/imm32/r32-is-first-inout + 8561 0/imm32/no-imm32 + 8562 0/imm32/no-disp32 + 8563 0/imm32/output-is-write-only + 8564 _Primitive-or-reg-with-mem/imm32/next + 8565 _Primitive-or-reg-with-mem: + 8566 # or-with var1 var2/reg => 09/or-with var1 var2/r32 + 8567 "or-with"/imm32/name + 8568 Two-args-int-stack-int-reg/imm32/inouts + 8569 0/imm32/outputs + 8570 "09/or-with"/imm32/subx-name + 8571 1/imm32/rm32-is-first-inout + 8572 2/imm32/r32-is-second-inout + 8573 0/imm32/no-imm32 + 8574 0/imm32/no-disp32 + 8575 0/imm32/output-is-write-only + 8576 _Primitive-or-mem-with-reg/imm32/next + 8577 _Primitive-or-mem-with-reg: + 8578 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 + 8579 "or"/imm32/name + 8580 Single-int-var-in-mem/imm32/inouts + 8581 Single-int-var-in-some-register/imm32/outputs + 8582 "0b/or"/imm32/subx-name + 8583 1/imm32/rm32-is-first-inout + 8584 3/imm32/r32-is-first-output + 8585 0/imm32/no-imm32 + 8586 0/imm32/no-disp32 + 8587 0/imm32/output-is-write-only + 8588 _Primitive-or-lit-with-reg/imm32/next + 8589 _Primitive-or-lit-with-reg: + 8590 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 + 8591 "or"/imm32/name + 8592 Single-lit-var/imm32/inouts + 8593 Single-int-var-in-some-register/imm32/outputs + 8594 "81 1/subop/or"/imm32/subx-name + 8595 3/imm32/rm32-is-first-output + 8596 0/imm32/no-r32 + 8597 1/imm32/imm32-is-first-inout + 8598 0/imm32/no-disp32 + 8599 0/imm32/output-is-write-only + 8600 _Primitive-or-lit-with-mem/imm32/next + 8601 _Primitive-or-lit-with-mem: + 8602 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 + 8603 "or-with"/imm32/name + 8604 Int-var-and-literal/imm32/inouts + 8605 0/imm32/outputs + 8606 "81 1/subop/or"/imm32/subx-name + 8607 1/imm32/rm32-is-first-inout + 8608 0/imm32/no-r32 + 8609 2/imm32/imm32-is-second-inout + 8610 0/imm32/no-disp32 + 8611 0/imm32/output-is-write-only + 8612 _Primitive-xor-with-eax/imm32/next + 8613 # - xor + 8614 _Primitive-xor-with-eax: + 8615 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 + 8616 "xor"/imm32/name + 8617 Single-lit-var/imm32/inouts + 8618 Single-int-var-in-eax/imm32/outputs + 8619 "35/xor-with-eax"/imm32/subx-name + 8620 0/imm32/no-rm32 + 8621 0/imm32/no-r32 + 8622 1/imm32/imm32-is-first-inout + 8623 0/imm32/no-disp32 + 8624 0/imm32/output-is-write-only + 8625 _Primitive-xor-reg-with-reg/imm32/next + 8626 _Primitive-xor-reg-with-reg: + 8627 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 + 8628 "xor"/imm32/name + 8629 Single-int-var-in-some-register/imm32/inouts + 8630 Single-int-var-in-some-register/imm32/outputs + 8631 "31/xor-with"/imm32/subx-name + 8632 3/imm32/rm32-is-first-output + 8633 1/imm32/r32-is-first-inout + 8634 0/imm32/no-imm32 + 8635 0/imm32/no-disp32 + 8636 0/imm32/output-is-write-only + 8637 _Primitive-xor-reg-with-mem/imm32/next + 8638 _Primitive-xor-reg-with-mem: + 8639 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 + 8640 "xor-with"/imm32/name + 8641 Two-args-int-stack-int-reg/imm32/inouts + 8642 0/imm32/outputs + 8643 "31/xor-with"/imm32/subx-name + 8644 1/imm32/rm32-is-first-inout + 8645 2/imm32/r32-is-second-inout + 8646 0/imm32/no-imm32 + 8647 0/imm32/no-disp32 + 8648 0/imm32/output-is-write-only + 8649 _Primitive-xor-mem-with-reg/imm32/next + 8650 _Primitive-xor-mem-with-reg: + 8651 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 + 8652 "xor"/imm32/name + 8653 Single-int-var-in-mem/imm32/inouts + 8654 Single-int-var-in-some-register/imm32/outputs + 8655 "33/xor"/imm32/subx-name + 8656 1/imm32/rm32-is-first-inout + 8657 3/imm32/r32-is-first-output + 8658 0/imm32/no-imm32 + 8659 0/imm32/no-disp32 + 8660 0/imm32/output-is-write-only + 8661 _Primitive-xor-lit-with-reg/imm32/next + 8662 _Primitive-xor-lit-with-reg: + 8663 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 + 8664 "xor"/imm32/name + 8665 Single-lit-var/imm32/inouts + 8666 Single-int-var-in-some-register/imm32/outputs + 8667 "81 6/subop/xor"/imm32/subx-name + 8668 3/imm32/rm32-is-first-output + 8669 0/imm32/no-r32 + 8670 1/imm32/imm32-is-first-inout + 8671 0/imm32/no-disp32 + 8672 0/imm32/output-is-write-only + 8673 _Primitive-xor-lit-with-mem/imm32/next + 8674 _Primitive-xor-lit-with-mem: + 8675 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 + 8676 "xor-with"/imm32/name + 8677 Int-var-and-literal/imm32/inouts + 8678 0/imm32/outputs + 8679 "81 6/subop/xor"/imm32/subx-name + 8680 1/imm32/rm32-is-first-inout + 8681 0/imm32/no-r32 + 8682 2/imm32/imm32-is-first-inout + 8683 0/imm32/no-disp32 + 8684 0/imm32/output-is-write-only + 8685 _Primitive-copy-to-eax/imm32/next + 8686 # - copy + 8687 _Primitive-copy-to-eax: + 8688 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 + 8689 "copy"/imm32/name + 8690 Single-lit-var/imm32/inouts + 8691 Single-int-var-in-eax/imm32/outputs + 8692 "b8/copy-to-eax"/imm32/subx-name + 8693 0/imm32/no-rm32 + 8694 0/imm32/no-r32 + 8695 1/imm32/imm32-is-first-inout + 8696 0/imm32/no-disp32 + 8697 1/imm32/output-is-write-only + 8698 _Primitive-copy-to-ecx/imm32/next + 8699 _Primitive-copy-to-ecx: + 8700 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 + 8701 "copy"/imm32/name + 8702 Single-lit-var/imm32/inouts + 8703 Single-int-var-in-ecx/imm32/outputs + 8704 "b9/copy-to-ecx"/imm32/subx-name + 8705 0/imm32/no-rm32 + 8706 0/imm32/no-r32 + 8707 1/imm32/imm32-is-first-inout + 8708 0/imm32/no-disp32 + 8709 1/imm32/output-is-write-only + 8710 _Primitive-copy-to-edx/imm32/next + 8711 _Primitive-copy-to-edx: + 8712 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 + 8713 "copy"/imm32/name + 8714 Single-lit-var/imm32/inouts + 8715 Single-int-var-in-edx/imm32/outputs + 8716 "ba/copy-to-edx"/imm32/subx-name + 8717 0/imm32/no-rm32 + 8718 0/imm32/no-r32 + 8719 1/imm32/imm32-is-first-inout + 8720 0/imm32/no-disp32 + 8721 1/imm32/output-is-write-only + 8722 _Primitive-copy-to-ebx/imm32/next + 8723 _Primitive-copy-to-ebx: + 8724 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 + 8725 "copy"/imm32/name + 8726 Single-lit-var/imm32/inouts + 8727 Single-int-var-in-ebx/imm32/outputs + 8728 "bb/copy-to-ebx"/imm32/subx-name + 8729 0/imm32/no-rm32 + 8730 0/imm32/no-r32 + 8731 1/imm32/imm32-is-first-inout + 8732 0/imm32/no-disp32 + 8733 1/imm32/output-is-write-only + 8734 _Primitive-copy-to-esi/imm32/next + 8735 _Primitive-copy-to-esi: + 8736 # var/esi <- copy lit => be/copy-to-esi lit/imm32 + 8737 "copy"/imm32/name + 8738 Single-lit-var/imm32/inouts + 8739 Single-int-var-in-esi/imm32/outputs + 8740 "be/copy-to-esi"/imm32/subx-name + 8741 0/imm32/no-rm32 + 8742 0/imm32/no-r32 + 8743 1/imm32/imm32-is-first-inout + 8744 0/imm32/no-disp32 + 8745 1/imm32/output-is-write-only + 8746 _Primitive-copy-to-edi/imm32/next + 8747 _Primitive-copy-to-edi: + 8748 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 + 8749 "copy"/imm32/name + 8750 Single-lit-var/imm32/inouts + 8751 Single-int-var-in-edi/imm32/outputs + 8752 "bf/copy-to-edi"/imm32/subx-name + 8753 0/imm32/no-rm32 + 8754 0/imm32/no-r32 + 8755 1/imm32/imm32-is-first-inout + 8756 0/imm32/no-disp32 + 8757 1/imm32/output-is-write-only + 8758 _Primitive-copy-reg-to-reg/imm32/next + 8759 _Primitive-copy-reg-to-reg: + 8760 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 + 8761 "copy"/imm32/name + 8762 Single-int-var-in-some-register/imm32/inouts + 8763 Single-int-var-in-some-register/imm32/outputs + 8764 "89/copy-to"/imm32/subx-name + 8765 3/imm32/rm32-is-first-output + 8766 1/imm32/r32-is-first-inout + 8767 0/imm32/no-imm32 + 8768 0/imm32/no-disp32 + 8769 1/imm32/output-is-write-only + 8770 _Primitive-copy-reg-to-mem/imm32/next + 8771 _Primitive-copy-reg-to-mem: + 8772 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 + 8773 "copy-to"/imm32/name + 8774 Two-args-int-stack-int-reg/imm32/inouts + 8775 0/imm32/outputs + 8776 "89/copy-to"/imm32/subx-name + 8777 1/imm32/rm32-is-first-inout + 8778 2/imm32/r32-is-second-inout + 8779 0/imm32/no-imm32 + 8780 0/imm32/no-disp32 + 8781 1/imm32/output-is-write-only + 8782 _Primitive-copy-mem-to-reg/imm32/next + 8783 _Primitive-copy-mem-to-reg: + 8784 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 + 8785 "copy"/imm32/name + 8786 Single-int-var-in-mem/imm32/inouts + 8787 Single-int-var-in-some-register/imm32/outputs + 8788 "8b/copy-from"/imm32/subx-name + 8789 1/imm32/rm32-is-first-inout + 8790 3/imm32/r32-is-first-output + 8791 0/imm32/no-imm32 + 8792 0/imm32/no-disp32 + 8793 1/imm32/output-is-write-only + 8794 _Primitive-copy-lit-to-reg/imm32/next + 8795 _Primitive-copy-lit-to-reg: + 8796 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 + 8797 "copy"/imm32/name + 8798 Single-lit-var/imm32/inouts + 8799 Single-int-var-in-some-register/imm32/outputs + 8800 "c7 0/subop/copy"/imm32/subx-name + 8801 3/imm32/rm32-is-first-output + 8802 0/imm32/no-r32 + 8803 1/imm32/imm32-is-first-inout + 8804 0/imm32/no-disp32 + 8805 1/imm32/output-is-write-only + 8806 _Primitive-copy-lit-to-mem/imm32/next + 8807 _Primitive-copy-lit-to-mem: + 8808 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 + 8809 "copy-to"/imm32/name + 8810 Int-var-and-literal/imm32/inouts + 8811 0/imm32/outputs + 8812 "c7 0/subop/copy"/imm32/subx-name + 8813 1/imm32/rm32-is-first-inout + 8814 0/imm32/no-r32 + 8815 2/imm32/imm32-is-first-inout + 8816 0/imm32/no-disp32 + 8817 1/imm32/output-is-write-only + 8818 _Primitive-address/imm32/next + 8819 # - address + 8820 _Primitive-address: + 8821 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 + 8822 "address"/imm32/name + 8823 Single-int-var-in-mem/imm32/inouts + 8824 Single-addr-var-in-some-register/imm32/outputs + 8825 "8d/copy-address"/imm32/subx-name + 8826 1/imm32/rm32-is-first-inout + 8827 3/imm32/r32-is-first-output + 8828 0/imm32/no-imm32 + 8829 0/imm32/no-disp32 + 8830 1/imm32/output-is-write-only + 8831 _Primitive-compare-mem-with-reg/imm32/next + 8832 # - compare + 8833 _Primitive-compare-mem-with-reg: + 8834 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 + 8835 "compare"/imm32/name + 8836 Two-args-int-stack-int-reg/imm32/inouts + 8837 0/imm32/outputs + 8838 "39/compare->"/imm32/subx-name + 8839 1/imm32/rm32-is-first-inout + 8840 2/imm32/r32-is-second-inout + 8841 0/imm32/no-imm32 + 8842 0/imm32/no-disp32 + 8843 0/imm32/output-is-write-only + 8844 _Primitive-compare-reg-with-mem/imm32/next + 8845 _Primitive-compare-reg-with-mem: + 8846 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 + 8847 "compare"/imm32/name + 8848 Two-args-int-reg-int-stack/imm32/inouts + 8849 0/imm32/outputs + 8850 "3b/compare<-"/imm32/subx-name + 8851 2/imm32/rm32-is-second-inout + 8852 1/imm32/r32-is-first-inout + 8853 0/imm32/no-imm32 + 8854 0/imm32/no-disp32 + 8855 0/imm32/output-is-write-only + 8856 _Primitive-compare-eax-with-literal/imm32/next + 8857 _Primitive-compare-eax-with-literal: + 8858 # compare var1/eax n => 3d/compare-eax-with n/imm32 + 8859 "compare"/imm32/name + 8860 Two-args-int-eax-int-literal/imm32/inouts + 8861 0/imm32/outputs + 8862 "3d/compare-eax-with"/imm32/subx-name + 8863 0/imm32/no-rm32 + 8864 0/imm32/no-r32 + 8865 2/imm32/imm32-is-second-inout + 8866 0/imm32/no-disp32 + 8867 0/imm32/output-is-write-only + 8868 _Primitive-compare-reg-with-literal/imm32/next + 8869 _Primitive-compare-reg-with-literal: + 8870 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 + 8871 "compare"/imm32/name + 8872 Int-var-in-register-and-literal/imm32/inouts 8873 0/imm32/outputs - 8874 "0f 84/jump-if-= break/disp32"/imm32/subx-name - 8875 0/imm32/no-rm32 + 8874 "81 7/subop/compare"/imm32/subx-name + 8875 1/imm32/rm32-is-first-inout 8876 0/imm32/no-r32 - 8877 0/imm32/no-imm32 + 8877 2/imm32/imm32-is-second-inout 8878 0/imm32/no-disp32 - 8879 0/imm32/no-output - 8880 _Primitive-break-if-!=/imm32/next - 8881 _Primitive-break-if-!=: - 8882 "break-if-!="/imm32/name - 8883 0/imm32/inouts - 8884 0/imm32/outputs - 8885 "0f 85/jump-if-!= break/disp32"/imm32/subx-name - 8886 0/imm32/no-rm32 - 8887 0/imm32/no-r32 - 8888 0/imm32/no-imm32 - 8889 0/imm32/no-disp32 - 8890 0/imm32/no-output - 8891 _Primitive-break-if-addr<=/imm32/next - 8892 _Primitive-break-if-addr<=: - 8893 "break-if-addr<="/imm32/name - 8894 0/imm32/inouts - 8895 0/imm32/outputs - 8896 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name - 8897 0/imm32/no-rm32 - 8898 0/imm32/no-r32 - 8899 0/imm32/no-imm32 - 8900 0/imm32/no-disp32 - 8901 0/imm32/no-output - 8902 _Primitive-break-if-addr>/imm32/next - 8903 _Primitive-break-if-addr>: - 8904 "break-if-addr>"/imm32/name - 8905 0/imm32/inouts - 8906 0/imm32/outputs - 8907 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name - 8908 0/imm32/no-rm32 - 8909 0/imm32/no-r32 - 8910 0/imm32/no-imm32 - 8911 0/imm32/no-disp32 - 8912 0/imm32/no-output - 8913 _Primitive-break-if-</imm32/next - 8914 _Primitive-break-if-<: - 8915 "break-if-<"/imm32/name - 8916 0/imm32/inouts - 8917 0/imm32/outputs - 8918 "0f 8c/jump-if-< break/disp32"/imm32/subx-name - 8919 0/imm32/no-rm32 - 8920 0/imm32/no-r32 - 8921 0/imm32/no-imm32 - 8922 0/imm32/no-disp32 - 8923 0/imm32/no-output - 8924 _Primitive-break-if->=/imm32/next - 8925 _Primitive-break-if->=: - 8926 "break-if->="/imm32/name - 8927 0/imm32/inouts - 8928 0/imm32/outputs - 8929 "0f 8d/jump-if->= break/disp32"/imm32/subx-name - 8930 0/imm32/no-rm32 - 8931 0/imm32/no-r32 - 8932 0/imm32/no-imm32 - 8933 0/imm32/no-disp32 - 8934 0/imm32/no-output - 8935 _Primitive-break-if-<=/imm32/next - 8936 _Primitive-break-if-<=: - 8937 "break-if-<="/imm32/name - 8938 0/imm32/inouts - 8939 0/imm32/outputs - 8940 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name - 8941 0/imm32/no-rm32 - 8942 0/imm32/no-r32 - 8943 0/imm32/no-imm32 - 8944 0/imm32/no-disp32 - 8945 0/imm32/no-output - 8946 _Primitive-break-if->/imm32/next - 8947 _Primitive-break-if->: - 8948 "break-if->"/imm32/name - 8949 0/imm32/inouts - 8950 0/imm32/outputs - 8951 "0f 8f/jump-if-> break/disp32"/imm32/subx-name - 8952 0/imm32/no-rm32 - 8953 0/imm32/no-r32 - 8954 0/imm32/no-imm32 - 8955 0/imm32/no-disp32 - 8956 0/imm32/no-output - 8957 _Primitive-break/imm32/next - 8958 _Primitive-break: - 8959 "break"/imm32/name - 8960 0/imm32/inouts - 8961 0/imm32/outputs - 8962 "e9/jump break/disp32"/imm32/subx-name - 8963 0/imm32/no-rm32 - 8964 0/imm32/no-r32 - 8965 0/imm32/no-imm32 - 8966 0/imm32/no-disp32 - 8967 0/imm32/no-output - 8968 _Primitive-loop-if-addr</imm32/next - 8969 _Primitive-loop-if-addr<: - 8970 "loop-if-addr<"/imm32/name - 8971 0/imm32/inouts - 8972 0/imm32/outputs - 8973 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name - 8974 0/imm32/no-rm32 - 8975 0/imm32/no-r32 - 8976 0/imm32/no-imm32 - 8977 0/imm32/no-disp32 - 8978 0/imm32/no-output - 8979 _Primitive-loop-if-addr>=/imm32/next - 8980 _Primitive-loop-if-addr>=: - 8981 "loop-if-addr>="/imm32/name - 8982 0/imm32/inouts - 8983 0/imm32/outputs - 8984 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name - 8985 0/imm32/no-rm32 - 8986 0/imm32/no-r32 - 8987 0/imm32/no-imm32 - 8988 0/imm32/no-disp32 - 8989 0/imm32/no-output - 8990 _Primitive-loop-if-=/imm32/next - 8991 _Primitive-loop-if-=: - 8992 "loop-if-="/imm32/name - 8993 0/imm32/inouts - 8994 0/imm32/outputs - 8995 "0f 84/jump-if-= loop/disp32"/imm32/subx-name - 8996 0/imm32/no-rm32 - 8997 0/imm32/no-r32 - 8998 0/imm32/no-imm32 - 8999 0/imm32/no-disp32 - 9000 0/imm32/no-output - 9001 _Primitive-loop-if-!=/imm32/next - 9002 _Primitive-loop-if-!=: - 9003 "loop-if-!="/imm32/name - 9004 0/imm32/inouts - 9005 0/imm32/outputs - 9006 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name - 9007 0/imm32/no-rm32 - 9008 0/imm32/no-r32 - 9009 0/imm32/no-imm32 - 9010 0/imm32/no-disp32 - 9011 0/imm32/no-output - 9012 _Primitive-loop-if-addr<=/imm32/next - 9013 _Primitive-loop-if-addr<=: - 9014 "loop-if-addr<="/imm32/name - 9015 0/imm32/inouts - 9016 0/imm32/outputs - 9017 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name - 9018 0/imm32/no-rm32 - 9019 0/imm32/no-r32 - 9020 0/imm32/no-imm32 - 9021 0/imm32/no-disp32 - 9022 0/imm32/no-output - 9023 _Primitive-loop-if-addr>/imm32/next - 9024 _Primitive-loop-if-addr>: - 9025 "loop-if-addr>"/imm32/name - 9026 0/imm32/inouts - 9027 0/imm32/outputs - 9028 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name - 9029 0/imm32/no-rm32 - 9030 0/imm32/no-r32 - 9031 0/imm32/no-imm32 - 9032 0/imm32/no-disp32 - 9033 0/imm32/no-output - 9034 _Primitive-loop-if-</imm32/next - 9035 _Primitive-loop-if-<: - 9036 "loop-if-<"/imm32/name - 9037 0/imm32/inouts - 9038 0/imm32/outputs - 9039 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name - 9040 0/imm32/no-rm32 - 9041 0/imm32/no-r32 - 9042 0/imm32/no-imm32 - 9043 0/imm32/no-disp32 - 9044 0/imm32/no-output - 9045 _Primitive-loop-if->=/imm32/next - 9046 _Primitive-loop-if->=: - 9047 "loop-if->="/imm32/name - 9048 0/imm32/inouts - 9049 0/imm32/outputs - 9050 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name - 9051 0/imm32/no-rm32 - 9052 0/imm32/no-r32 - 9053 0/imm32/no-imm32 - 9054 0/imm32/no-disp32 - 9055 0/imm32/no-output - 9056 _Primitive-loop-if-<=/imm32/next - 9057 _Primitive-loop-if-<=: - 9058 "loop-if-<="/imm32/name - 9059 0/imm32/inouts - 9060 0/imm32/outputs - 9061 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name - 9062 0/imm32/no-rm32 - 9063 0/imm32/no-r32 - 9064 0/imm32/no-imm32 - 9065 0/imm32/no-disp32 - 9066 0/imm32/no-output - 9067 _Primitive-loop-if->/imm32/next - 9068 _Primitive-loop-if->: - 9069 "loop-if->"/imm32/name - 9070 0/imm32/inouts - 9071 0/imm32/outputs - 9072 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name - 9073 0/imm32/no-rm32 - 9074 0/imm32/no-r32 - 9075 0/imm32/no-imm32 - 9076 0/imm32/no-disp32 - 9077 0/imm32/no-output - 9078 _Primitive-loop/imm32/next # we probably don't need an unconditional break - 9079 _Primitive-loop: - 9080 "loop"/imm32/name - 9081 0/imm32/inouts - 9082 0/imm32/outputs - 9083 "e9/jump loop/disp32"/imm32/subx-name - 9084 0/imm32/no-rm32 - 9085 0/imm32/no-r32 - 9086 0/imm32/no-imm32 - 9087 0/imm32/no-disp32 - 9088 0/imm32/no-output - 9089 _Primitive-break-if-addr<-named/imm32/next - 9090 # - branches to named blocks - 9091 _Primitive-break-if-addr<-named: - 9092 "break-if-addr<"/imm32/name - 9093 Single-lit-var/imm32/inouts - 9094 0/imm32/outputs - 9095 "0f 82/jump-if-addr<"/imm32/subx-name - 9096 0/imm32/no-rm32 - 9097 0/imm32/no-r32 - 9098 0/imm32/no-imm32 - 9099 1/imm32/disp32-is-first-inout - 9100 0/imm32/no-output - 9101 _Primitive-break-if-addr>=-named/imm32/next - 9102 _Primitive-break-if-addr>=-named: - 9103 "break-if-addr>="/imm32/name - 9104 Single-lit-var/imm32/inouts - 9105 0/imm32/outputs - 9106 "0f 83/jump-if-addr>="/imm32/subx-name - 9107 0/imm32/no-rm32 - 9108 0/imm32/no-r32 - 9109 0/imm32/no-imm32 - 9110 1/imm32/disp32-is-first-inout - 9111 0/imm32/no-output - 9112 _Primitive-break-if-=-named/imm32/next - 9113 _Primitive-break-if-=-named: - 9114 "break-if-="/imm32/name - 9115 Single-lit-var/imm32/inouts - 9116 0/imm32/outputs - 9117 "0f 84/jump-if-="/imm32/subx-name - 9118 0/imm32/no-rm32 - 9119 0/imm32/no-r32 - 9120 0/imm32/no-imm32 - 9121 1/imm32/disp32-is-first-inout - 9122 0/imm32/no-output - 9123 _Primitive-break-if-!=-named/imm32/next - 9124 _Primitive-break-if-!=-named: - 9125 "break-if-!="/imm32/name - 9126 Single-lit-var/imm32/inouts - 9127 0/imm32/outputs - 9128 "0f 85/jump-if-!="/imm32/subx-name - 9129 0/imm32/no-rm32 - 9130 0/imm32/no-r32 - 9131 0/imm32/no-imm32 - 9132 1/imm32/disp32-is-first-inout - 9133 0/imm32/no-output - 9134 _Primitive-break-if-addr<=-named/imm32/next - 9135 _Primitive-break-if-addr<=-named: - 9136 "break-if-addr<="/imm32/name - 9137 Single-lit-var/imm32/inouts - 9138 0/imm32/outputs - 9139 "0f 86/jump-if-addr<="/imm32/subx-name - 9140 0/imm32/no-rm32 - 9141 0/imm32/no-r32 - 9142 0/imm32/no-imm32 - 9143 1/imm32/disp32-is-first-inout - 9144 0/imm32/no-output - 9145 _Primitive-break-if-addr>-named/imm32/next - 9146 _Primitive-break-if-addr>-named: - 9147 "break-if-addr>"/imm32/name - 9148 Single-lit-var/imm32/inouts - 9149 0/imm32/outputs - 9150 "0f 87/jump-if-addr>"/imm32/subx-name - 9151 0/imm32/no-rm32 - 9152 0/imm32/no-r32 - 9153 0/imm32/no-imm32 - 9154 1/imm32/disp32-is-first-inout - 9155 0/imm32/no-output - 9156 _Primitive-break-if-<-named/imm32/next - 9157 _Primitive-break-if-<-named: - 9158 "break-if-<"/imm32/name - 9159 Single-lit-var/imm32/inouts - 9160 0/imm32/outputs - 9161 "0f 8c/jump-if-<"/imm32/subx-name - 9162 0/imm32/no-rm32 - 9163 0/imm32/no-r32 - 9164 0/imm32/no-imm32 - 9165 1/imm32/disp32-is-first-inout - 9166 0/imm32/no-output - 9167 _Primitive-break-if->=-named/imm32/next - 9168 _Primitive-break-if->=-named: - 9169 "break-if->="/imm32/name - 9170 Single-lit-var/imm32/inouts - 9171 0/imm32/outputs - 9172 "0f 8d/jump-if->="/imm32/subx-name - 9173 0/imm32/no-rm32 - 9174 0/imm32/no-r32 - 9175 0/imm32/no-imm32 - 9176 1/imm32/disp32-is-first-inout - 9177 0/imm32/no-output - 9178 _Primitive-break-if-<=-named/imm32/next - 9179 _Primitive-break-if-<=-named: - 9180 "break-if-<="/imm32/name - 9181 Single-lit-var/imm32/inouts - 9182 0/imm32/outputs - 9183 "0f 8e/jump-if-<="/imm32/subx-name - 9184 0/imm32/no-rm32 - 9185 0/imm32/no-r32 - 9186 0/imm32/no-imm32 - 9187 1/imm32/disp32-is-first-inout - 9188 0/imm32/no-output - 9189 _Primitive-break-if->-named/imm32/next - 9190 _Primitive-break-if->-named: - 9191 "break-if->"/imm32/name - 9192 Single-lit-var/imm32/inouts - 9193 0/imm32/outputs - 9194 "0f 8f/jump-if->"/imm32/subx-name - 9195 0/imm32/no-rm32 - 9196 0/imm32/no-r32 - 9197 0/imm32/no-imm32 - 9198 1/imm32/disp32-is-first-inout - 9199 0/imm32/no-output - 9200 _Primitive-break-named/imm32/next - 9201 _Primitive-break-named: - 9202 "break"/imm32/name - 9203 Single-lit-var/imm32/inouts - 9204 0/imm32/outputs - 9205 "e9/jump"/imm32/subx-name - 9206 0/imm32/no-rm32 - 9207 0/imm32/no-r32 - 9208 0/imm32/no-imm32 - 9209 1/imm32/disp32-is-first-inout - 9210 0/imm32/no-output - 9211 _Primitive-loop-if-addr<-named/imm32/next - 9212 _Primitive-loop-if-addr<-named: - 9213 "loop-if-addr<"/imm32/name - 9214 Single-lit-var/imm32/inouts - 9215 0/imm32/outputs - 9216 "0f 82/jump-if-addr<"/imm32/subx-name - 9217 0/imm32/no-rm32 - 9218 0/imm32/no-r32 - 9219 0/imm32/no-imm32 - 9220 1/imm32/disp32-is-first-inout - 9221 0/imm32/no-output - 9222 _Primitive-loop-if-addr>=-named/imm32/next - 9223 _Primitive-loop-if-addr>=-named: - 9224 "loop-if-addr>="/imm32/name - 9225 Single-lit-var/imm32/inouts - 9226 0/imm32/outputs - 9227 "0f 83/jump-if-addr>="/imm32/subx-name - 9228 0/imm32/no-rm32 - 9229 0/imm32/no-r32 - 9230 0/imm32/no-imm32 - 9231 1/imm32/disp32-is-first-inout - 9232 0/imm32/no-output - 9233 _Primitive-loop-if-=-named/imm32/next - 9234 _Primitive-loop-if-=-named: - 9235 "loop-if-="/imm32/name - 9236 Single-lit-var/imm32/inouts - 9237 0/imm32/outputs - 9238 "0f 84/jump-if-="/imm32/subx-name - 9239 0/imm32/no-rm32 - 9240 0/imm32/no-r32 - 9241 0/imm32/no-imm32 - 9242 1/imm32/disp32-is-first-inout - 9243 0/imm32/no-output - 9244 _Primitive-loop-if-!=-named/imm32/next - 9245 _Primitive-loop-if-!=-named: - 9246 "loop-if-!="/imm32/name - 9247 Single-lit-var/imm32/inouts - 9248 0/imm32/outputs - 9249 "0f 85/jump-if-!="/imm32/subx-name - 9250 0/imm32/no-rm32 - 9251 0/imm32/no-r32 - 9252 0/imm32/no-imm32 - 9253 1/imm32/disp32-is-first-inout - 9254 0/imm32/no-output - 9255 _Primitive-loop-if-addr<=-named/imm32/next - 9256 _Primitive-loop-if-addr<=-named: - 9257 "loop-if-addr<="/imm32/name - 9258 Single-lit-var/imm32/inouts - 9259 0/imm32/outputs - 9260 "0f 86/jump-if-addr<="/imm32/subx-name - 9261 0/imm32/no-rm32 - 9262 0/imm32/no-r32 - 9263 0/imm32/no-imm32 - 9264 1/imm32/disp32-is-first-inout - 9265 0/imm32/no-output - 9266 _Primitive-loop-if-addr>-named/imm32/next - 9267 _Primitive-loop-if-addr>-named: - 9268 "loop-if-addr>"/imm32/name - 9269 Single-lit-var/imm32/inouts - 9270 0/imm32/outputs - 9271 "0f 87/jump-if-addr>"/imm32/subx-name - 9272 0/imm32/no-rm32 - 9273 0/imm32/no-r32 - 9274 0/imm32/no-imm32 - 9275 1/imm32/disp32-is-first-inout - 9276 0/imm32/no-output - 9277 _Primitive-loop-if-<-named/imm32/next - 9278 _Primitive-loop-if-<-named: - 9279 "loop-if-<"/imm32/name - 9280 Single-lit-var/imm32/inouts - 9281 0/imm32/outputs - 9282 "0f 8c/jump-if-<"/imm32/subx-name - 9283 0/imm32/no-rm32 - 9284 0/imm32/no-r32 - 9285 0/imm32/no-imm32 - 9286 1/imm32/disp32-is-first-inout - 9287 0/imm32/no-output - 9288 _Primitive-loop-if->=-named/imm32/next - 9289 _Primitive-loop-if->=-named: - 9290 "loop-if->="/imm32/name - 9291 Single-lit-var/imm32/inouts - 9292 0/imm32/outputs - 9293 "0f 8d/jump-if->="/imm32/subx-name - 9294 0/imm32/no-rm32 - 9295 0/imm32/no-r32 - 9296 0/imm32/no-imm32 - 9297 1/imm32/disp32-is-first-inout - 9298 0/imm32/no-output - 9299 _Primitive-loop-if-<=-named/imm32/next - 9300 _Primitive-loop-if-<=-named: - 9301 "loop-if-<="/imm32/name - 9302 Single-lit-var/imm32/inouts - 9303 0/imm32/outputs - 9304 "0f 8e/jump-if-<="/imm32/subx-name - 9305 0/imm32/no-rm32 - 9306 0/imm32/no-r32 - 9307 0/imm32/no-imm32 - 9308 1/imm32/disp32-is-first-inout - 9309 0/imm32/no-output - 9310 _Primitive-loop-if->-named/imm32/next - 9311 _Primitive-loop-if->-named: - 9312 "loop-if->"/imm32/name - 9313 Single-lit-var/imm32/inouts - 9314 0/imm32/outputs - 9315 "0f 8f/jump-if->"/imm32/subx-name - 9316 0/imm32/no-rm32 - 9317 0/imm32/no-r32 - 9318 0/imm32/no-imm32 - 9319 1/imm32/disp32-is-first-inout - 9320 0/imm32/no-output - 9321 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break - 9322 _Primitive-loop-named: - 9323 "loop"/imm32/name - 9324 Single-lit-var/imm32/inouts - 9325 0/imm32/outputs - 9326 "e9/jump"/imm32/subx-name - 9327 0/imm32/no-rm32 - 9328 0/imm32/no-r32 - 9329 0/imm32/no-imm32 - 9330 1/imm32/disp32-is-first-inout - 9331 0/imm32/no-output - 9332 0/imm32/next - 9333 - 9334 Single-int-var-in-mem: - 9335 Int-var-in-mem/imm32 - 9336 0/imm32/next - 9337 - 9338 Int-var-in-mem: - 9339 "arg1"/imm32/name - 9340 Type-int/imm32 - 9341 1/imm32/some-block-depth - 9342 1/imm32/some-stack-offset - 9343 0/imm32/no-register - 9344 - 9345 Two-args-int-stack-int-reg: - 9346 Int-var-in-mem/imm32 - 9347 Single-int-var-in-some-register/imm32/next - 9348 - 9349 Two-args-int-reg-int-stack: - 9350 Int-var-in-some-register/imm32 - 9351 Single-int-var-in-mem/imm32/next - 9352 - 9353 Two-args-int-eax-int-literal: - 9354 Int-var-in-eax/imm32 - 9355 Single-lit-var/imm32/next - 9356 - 9357 Int-var-and-literal: - 9358 Int-var-in-mem/imm32 - 9359 Single-lit-var/imm32/next - 9360 - 9361 Int-var-in-register-and-literal: - 9362 Int-var-in-some-register/imm32 - 9363 Single-lit-var/imm32/next - 9364 - 9365 Single-int-var-in-some-register: - 9366 Int-var-in-some-register/imm32 - 9367 0/imm32/next - 9368 - 9369 Int-var-in-some-register: - 9370 "arg1"/imm32/name - 9371 Type-int/imm32 - 9372 1/imm32/some-block-depth - 9373 0/imm32/no-stack-offset - 9374 Any-register/imm32 - 9375 - 9376 Single-int-var-in-eax: - 9377 Int-var-in-eax/imm32 - 9378 0/imm32/next - 9379 - 9380 Int-var-in-eax: - 9381 "arg1"/imm32/name - 9382 Type-int/imm32 - 9383 1/imm32/some-block-depth - 9384 0/imm32/no-stack-offset - 9385 "eax"/imm32/register - 9386 - 9387 Single-int-var-in-ecx: - 9388 Int-var-in-ecx/imm32 - 9389 0/imm32/next - 9390 - 9391 Int-var-in-ecx: - 9392 "arg1"/imm32/name - 9393 Type-int/imm32 - 9394 1/imm32/some-block-depth - 9395 0/imm32/no-stack-offset - 9396 "ecx"/imm32/register - 9397 - 9398 Single-int-var-in-edx: - 9399 Int-var-in-edx/imm32 - 9400 0/imm32/next - 9401 - 9402 Int-var-in-edx: - 9403 "arg1"/imm32/name - 9404 Type-int/imm32 - 9405 1/imm32/some-block-depth - 9406 0/imm32/no-stack-offset - 9407 "edx"/imm32/register - 9408 - 9409 Single-int-var-in-ebx: - 9410 Int-var-in-ebx/imm32 - 9411 0/imm32/next - 9412 - 9413 Int-var-in-ebx: - 9414 "arg1"/imm32/name - 9415 Type-int/imm32 - 9416 1/imm32/some-block-depth - 9417 0/imm32/no-stack-offset - 9418 "ebx"/imm32/register + 8879 0/imm32/output-is-write-only + 8880 _Primitive-compare-mem-with-literal/imm32/next + 8881 _Primitive-compare-mem-with-literal: + 8882 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 + 8883 "compare"/imm32/name + 8884 Int-var-and-literal/imm32/inouts + 8885 0/imm32/outputs + 8886 "81 7/subop/compare"/imm32/subx-name + 8887 1/imm32/rm32-is-first-inout + 8888 0/imm32/no-r32 + 8889 2/imm32/imm32-is-second-inout + 8890 0/imm32/no-disp32 + 8891 0/imm32/output-is-write-only + 8892 _Primitive-multiply-reg-by-mem/imm32/next + 8893 # - multiply + 8894 _Primitive-multiply-reg-by-mem: + 8895 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 + 8896 "multiply"/imm32/name + 8897 Single-int-var-in-mem/imm32/inouts + 8898 Single-int-var-in-some-register/imm32/outputs + 8899 "0f af/multiply"/imm32/subx-name + 8900 1/imm32/rm32-is-first-inout + 8901 3/imm32/r32-is-first-output + 8902 0/imm32/no-imm32 + 8903 0/imm32/no-disp32 + 8904 0/imm32/output-is-write-only + 8905 _Primitive-break-if-addr</imm32/next + 8906 # - branches + 8907 _Primitive-break-if-addr<: + 8908 "break-if-addr<"/imm32/name + 8909 0/imm32/inouts + 8910 0/imm32/outputs + 8911 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name + 8912 0/imm32/no-rm32 + 8913 0/imm32/no-r32 + 8914 0/imm32/no-imm32 + 8915 0/imm32/no-disp32 + 8916 0/imm32/no-output + 8917 _Primitive-break-if-addr>=/imm32/next + 8918 _Primitive-break-if-addr>=: + 8919 "break-if-addr>="/imm32/name + 8920 0/imm32/inouts + 8921 0/imm32/outputs + 8922 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name + 8923 0/imm32/no-rm32 + 8924 0/imm32/no-r32 + 8925 0/imm32/no-imm32 + 8926 0/imm32/no-disp32 + 8927 0/imm32/no-output + 8928 _Primitive-break-if-=/imm32/next + 8929 _Primitive-break-if-=: + 8930 "break-if-="/imm32/name + 8931 0/imm32/inouts + 8932 0/imm32/outputs + 8933 "0f 84/jump-if-= break/disp32"/imm32/subx-name + 8934 0/imm32/no-rm32 + 8935 0/imm32/no-r32 + 8936 0/imm32/no-imm32 + 8937 0/imm32/no-disp32 + 8938 0/imm32/no-output + 8939 _Primitive-break-if-!=/imm32/next + 8940 _Primitive-break-if-!=: + 8941 "break-if-!="/imm32/name + 8942 0/imm32/inouts + 8943 0/imm32/outputs + 8944 "0f 85/jump-if-!= break/disp32"/imm32/subx-name + 8945 0/imm32/no-rm32 + 8946 0/imm32/no-r32 + 8947 0/imm32/no-imm32 + 8948 0/imm32/no-disp32 + 8949 0/imm32/no-output + 8950 _Primitive-break-if-addr<=/imm32/next + 8951 _Primitive-break-if-addr<=: + 8952 "break-if-addr<="/imm32/name + 8953 0/imm32/inouts + 8954 0/imm32/outputs + 8955 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name + 8956 0/imm32/no-rm32 + 8957 0/imm32/no-r32 + 8958 0/imm32/no-imm32 + 8959 0/imm32/no-disp32 + 8960 0/imm32/no-output + 8961 _Primitive-break-if-addr>/imm32/next + 8962 _Primitive-break-if-addr>: + 8963 "break-if-addr>"/imm32/name + 8964 0/imm32/inouts + 8965 0/imm32/outputs + 8966 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name + 8967 0/imm32/no-rm32 + 8968 0/imm32/no-r32 + 8969 0/imm32/no-imm32 + 8970 0/imm32/no-disp32 + 8971 0/imm32/no-output + 8972 _Primitive-break-if-</imm32/next + 8973 _Primitive-break-if-<: + 8974 "break-if-<"/imm32/name + 8975 0/imm32/inouts + 8976 0/imm32/outputs + 8977 "0f 8c/jump-if-< break/disp32"/imm32/subx-name + 8978 0/imm32/no-rm32 + 8979 0/imm32/no-r32 + 8980 0/imm32/no-imm32 + 8981 0/imm32/no-disp32 + 8982 0/imm32/no-output + 8983 _Primitive-break-if->=/imm32/next + 8984 _Primitive-break-if->=: + 8985 "break-if->="/imm32/name + 8986 0/imm32/inouts + 8987 0/imm32/outputs + 8988 "0f 8d/jump-if->= break/disp32"/imm32/subx-name + 8989 0/imm32/no-rm32 + 8990 0/imm32/no-r32 + 8991 0/imm32/no-imm32 + 8992 0/imm32/no-disp32 + 8993 0/imm32/no-output + 8994 _Primitive-break-if-<=/imm32/next + 8995 _Primitive-break-if-<=: + 8996 "break-if-<="/imm32/name + 8997 0/imm32/inouts + 8998 0/imm32/outputs + 8999 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name + 9000 0/imm32/no-rm32 + 9001 0/imm32/no-r32 + 9002 0/imm32/no-imm32 + 9003 0/imm32/no-disp32 + 9004 0/imm32/no-output + 9005 _Primitive-break-if->/imm32/next + 9006 _Primitive-break-if->: + 9007 "break-if->"/imm32/name + 9008 0/imm32/inouts + 9009 0/imm32/outputs + 9010 "0f 8f/jump-if-> break/disp32"/imm32/subx-name + 9011 0/imm32/no-rm32 + 9012 0/imm32/no-r32 + 9013 0/imm32/no-imm32 + 9014 0/imm32/no-disp32 + 9015 0/imm32/no-output + 9016 _Primitive-break/imm32/next + 9017 _Primitive-break: + 9018 "break"/imm32/name + 9019 0/imm32/inouts + 9020 0/imm32/outputs + 9021 "e9/jump break/disp32"/imm32/subx-name + 9022 0/imm32/no-rm32 + 9023 0/imm32/no-r32 + 9024 0/imm32/no-imm32 + 9025 0/imm32/no-disp32 + 9026 0/imm32/no-output + 9027 _Primitive-loop-if-addr</imm32/next + 9028 _Primitive-loop-if-addr<: + 9029 "loop-if-addr<"/imm32/name + 9030 0/imm32/inouts + 9031 0/imm32/outputs + 9032 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name + 9033 0/imm32/no-rm32 + 9034 0/imm32/no-r32 + 9035 0/imm32/no-imm32 + 9036 0/imm32/no-disp32 + 9037 0/imm32/no-output + 9038 _Primitive-loop-if-addr>=/imm32/next + 9039 _Primitive-loop-if-addr>=: + 9040 "loop-if-addr>="/imm32/name + 9041 0/imm32/inouts + 9042 0/imm32/outputs + 9043 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name + 9044 0/imm32/no-rm32 + 9045 0/imm32/no-r32 + 9046 0/imm32/no-imm32 + 9047 0/imm32/no-disp32 + 9048 0/imm32/no-output + 9049 _Primitive-loop-if-=/imm32/next + 9050 _Primitive-loop-if-=: + 9051 "loop-if-="/imm32/name + 9052 0/imm32/inouts + 9053 0/imm32/outputs + 9054 "0f 84/jump-if-= loop/disp32"/imm32/subx-name + 9055 0/imm32/no-rm32 + 9056 0/imm32/no-r32 + 9057 0/imm32/no-imm32 + 9058 0/imm32/no-disp32 + 9059 0/imm32/no-output + 9060 _Primitive-loop-if-!=/imm32/next + 9061 _Primitive-loop-if-!=: + 9062 "loop-if-!="/imm32/name + 9063 0/imm32/inouts + 9064 0/imm32/outputs + 9065 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name + 9066 0/imm32/no-rm32 + 9067 0/imm32/no-r32 + 9068 0/imm32/no-imm32 + 9069 0/imm32/no-disp32 + 9070 0/imm32/no-output + 9071 _Primitive-loop-if-addr<=/imm32/next + 9072 _Primitive-loop-if-addr<=: + 9073 "loop-if-addr<="/imm32/name + 9074 0/imm32/inouts + 9075 0/imm32/outputs + 9076 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name + 9077 0/imm32/no-rm32 + 9078 0/imm32/no-r32 + 9079 0/imm32/no-imm32 + 9080 0/imm32/no-disp32 + 9081 0/imm32/no-output + 9082 _Primitive-loop-if-addr>/imm32/next + 9083 _Primitive-loop-if-addr>: + 9084 "loop-if-addr>"/imm32/name + 9085 0/imm32/inouts + 9086 0/imm32/outputs + 9087 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name + 9088 0/imm32/no-rm32 + 9089 0/imm32/no-r32 + 9090 0/imm32/no-imm32 + 9091 0/imm32/no-disp32 + 9092 0/imm32/no-output + 9093 _Primitive-loop-if-</imm32/next + 9094 _Primitive-loop-if-<: + 9095 "loop-if-<"/imm32/name + 9096 0/imm32/inouts + 9097 0/imm32/outputs + 9098 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name + 9099 0/imm32/no-rm32 + 9100 0/imm32/no-r32 + 9101 0/imm32/no-imm32 + 9102 0/imm32/no-disp32 + 9103 0/imm32/no-output + 9104 _Primitive-loop-if->=/imm32/next + 9105 _Primitive-loop-if->=: + 9106 "loop-if->="/imm32/name + 9107 0/imm32/inouts + 9108 0/imm32/outputs + 9109 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name + 9110 0/imm32/no-rm32 + 9111 0/imm32/no-r32 + 9112 0/imm32/no-imm32 + 9113 0/imm32/no-disp32 + 9114 0/imm32/no-output + 9115 _Primitive-loop-if-<=/imm32/next + 9116 _Primitive-loop-if-<=: + 9117 "loop-if-<="/imm32/name + 9118 0/imm32/inouts + 9119 0/imm32/outputs + 9120 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name + 9121 0/imm32/no-rm32 + 9122 0/imm32/no-r32 + 9123 0/imm32/no-imm32 + 9124 0/imm32/no-disp32 + 9125 0/imm32/no-output + 9126 _Primitive-loop-if->/imm32/next + 9127 _Primitive-loop-if->: + 9128 "loop-if->"/imm32/name + 9129 0/imm32/inouts + 9130 0/imm32/outputs + 9131 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name + 9132 0/imm32/no-rm32 + 9133 0/imm32/no-r32 + 9134 0/imm32/no-imm32 + 9135 0/imm32/no-disp32 + 9136 0/imm32/no-output + 9137 _Primitive-loop/imm32/next # we probably don't need an unconditional break + 9138 _Primitive-loop: + 9139 "loop"/imm32/name + 9140 0/imm32/inouts + 9141 0/imm32/outputs + 9142 "e9/jump loop/disp32"/imm32/subx-name + 9143 0/imm32/no-rm32 + 9144 0/imm32/no-r32 + 9145 0/imm32/no-imm32 + 9146 0/imm32/no-disp32 + 9147 0/imm32/no-output + 9148 _Primitive-break-if-addr<-named/imm32/next + 9149 # - branches to named blocks + 9150 _Primitive-break-if-addr<-named: + 9151 "break-if-addr<"/imm32/name + 9152 Single-lit-var/imm32/inouts + 9153 0/imm32/outputs + 9154 "0f 82/jump-if-addr<"/imm32/subx-name + 9155 0/imm32/no-rm32 + 9156 0/imm32/no-r32 + 9157 0/imm32/no-imm32 + 9158 1/imm32/disp32-is-first-inout + 9159 0/imm32/no-output + 9160 _Primitive-break-if-addr>=-named/imm32/next + 9161 _Primitive-break-if-addr>=-named: + 9162 "break-if-addr>="/imm32/name + 9163 Single-lit-var/imm32/inouts + 9164 0/imm32/outputs + 9165 "0f 83/jump-if-addr>="/imm32/subx-name + 9166 0/imm32/no-rm32 + 9167 0/imm32/no-r32 + 9168 0/imm32/no-imm32 + 9169 1/imm32/disp32-is-first-inout + 9170 0/imm32/no-output + 9171 _Primitive-break-if-=-named/imm32/next + 9172 _Primitive-break-if-=-named: + 9173 "break-if-="/imm32/name + 9174 Single-lit-var/imm32/inouts + 9175 0/imm32/outputs + 9176 "0f 84/jump-if-="/imm32/subx-name + 9177 0/imm32/no-rm32 + 9178 0/imm32/no-r32 + 9179 0/imm32/no-imm32 + 9180 1/imm32/disp32-is-first-inout + 9181 0/imm32/no-output + 9182 _Primitive-break-if-!=-named/imm32/next + 9183 _Primitive-break-if-!=-named: + 9184 "break-if-!="/imm32/name + 9185 Single-lit-var/imm32/inouts + 9186 0/imm32/outputs + 9187 "0f 85/jump-if-!="/imm32/subx-name + 9188 0/imm32/no-rm32 + 9189 0/imm32/no-r32 + 9190 0/imm32/no-imm32 + 9191 1/imm32/disp32-is-first-inout + 9192 0/imm32/no-output + 9193 _Primitive-break-if-addr<=-named/imm32/next + 9194 _Primitive-break-if-addr<=-named: + 9195 "break-if-addr<="/imm32/name + 9196 Single-lit-var/imm32/inouts + 9197 0/imm32/outputs + 9198 "0f 86/jump-if-addr<="/imm32/subx-name + 9199 0/imm32/no-rm32 + 9200 0/imm32/no-r32 + 9201 0/imm32/no-imm32 + 9202 1/imm32/disp32-is-first-inout + 9203 0/imm32/no-output + 9204 _Primitive-break-if-addr>-named/imm32/next + 9205 _Primitive-break-if-addr>-named: + 9206 "break-if-addr>"/imm32/name + 9207 Single-lit-var/imm32/inouts + 9208 0/imm32/outputs + 9209 "0f 87/jump-if-addr>"/imm32/subx-name + 9210 0/imm32/no-rm32 + 9211 0/imm32/no-r32 + 9212 0/imm32/no-imm32 + 9213 1/imm32/disp32-is-first-inout + 9214 0/imm32/no-output + 9215 _Primitive-break-if-<-named/imm32/next + 9216 _Primitive-break-if-<-named: + 9217 "break-if-<"/imm32/name + 9218 Single-lit-var/imm32/inouts + 9219 0/imm32/outputs + 9220 "0f 8c/jump-if-<"/imm32/subx-name + 9221 0/imm32/no-rm32 + 9222 0/imm32/no-r32 + 9223 0/imm32/no-imm32 + 9224 1/imm32/disp32-is-first-inout + 9225 0/imm32/no-output + 9226 _Primitive-break-if->=-named/imm32/next + 9227 _Primitive-break-if->=-named: + 9228 "break-if->="/imm32/name + 9229 Single-lit-var/imm32/inouts + 9230 0/imm32/outputs + 9231 "0f 8d/jump-if->="/imm32/subx-name + 9232 0/imm32/no-rm32 + 9233 0/imm32/no-r32 + 9234 0/imm32/no-imm32 + 9235 1/imm32/disp32-is-first-inout + 9236 0/imm32/no-output + 9237 _Primitive-break-if-<=-named/imm32/next + 9238 _Primitive-break-if-<=-named: + 9239 "break-if-<="/imm32/name + 9240 Single-lit-var/imm32/inouts + 9241 0/imm32/outputs + 9242 "0f 8e/jump-if-<="/imm32/subx-name + 9243 0/imm32/no-rm32 + 9244 0/imm32/no-r32 + 9245 0/imm32/no-imm32 + 9246 1/imm32/disp32-is-first-inout + 9247 0/imm32/no-output + 9248 _Primitive-break-if->-named/imm32/next + 9249 _Primitive-break-if->-named: + 9250 "break-if->"/imm32/name + 9251 Single-lit-var/imm32/inouts + 9252 0/imm32/outputs + 9253 "0f 8f/jump-if->"/imm32/subx-name + 9254 0/imm32/no-rm32 + 9255 0/imm32/no-r32 + 9256 0/imm32/no-imm32 + 9257 1/imm32/disp32-is-first-inout + 9258 0/imm32/no-output + 9259 _Primitive-break-named/imm32/next + 9260 _Primitive-break-named: + 9261 "break"/imm32/name + 9262 Single-lit-var/imm32/inouts + 9263 0/imm32/outputs + 9264 "e9/jump"/imm32/subx-name + 9265 0/imm32/no-rm32 + 9266 0/imm32/no-r32 + 9267 0/imm32/no-imm32 + 9268 1/imm32/disp32-is-first-inout + 9269 0/imm32/no-output + 9270 _Primitive-loop-if-addr<-named/imm32/next + 9271 _Primitive-loop-if-addr<-named: + 9272 "loop-if-addr<"/imm32/name + 9273 Single-lit-var/imm32/inouts + 9274 0/imm32/outputs + 9275 "0f 82/jump-if-addr<"/imm32/subx-name + 9276 0/imm32/no-rm32 + 9277 0/imm32/no-r32 + 9278 0/imm32/no-imm32 + 9279 1/imm32/disp32-is-first-inout + 9280 0/imm32/no-output + 9281 _Primitive-loop-if-addr>=-named/imm32/next + 9282 _Primitive-loop-if-addr>=-named: + 9283 "loop-if-addr>="/imm32/name + 9284 Single-lit-var/imm32/inouts + 9285 0/imm32/outputs + 9286 "0f 83/jump-if-addr>="/imm32/subx-name + 9287 0/imm32/no-rm32 + 9288 0/imm32/no-r32 + 9289 0/imm32/no-imm32 + 9290 1/imm32/disp32-is-first-inout + 9291 0/imm32/no-output + 9292 _Primitive-loop-if-=-named/imm32/next + 9293 _Primitive-loop-if-=-named: + 9294 "loop-if-="/imm32/name + 9295 Single-lit-var/imm32/inouts + 9296 0/imm32/outputs + 9297 "0f 84/jump-if-="/imm32/subx-name + 9298 0/imm32/no-rm32 + 9299 0/imm32/no-r32 + 9300 0/imm32/no-imm32 + 9301 1/imm32/disp32-is-first-inout + 9302 0/imm32/no-output + 9303 _Primitive-loop-if-!=-named/imm32/next + 9304 _Primitive-loop-if-!=-named: + 9305 "loop-if-!="/imm32/name + 9306 Single-lit-var/imm32/inouts + 9307 0/imm32/outputs + 9308 "0f 85/jump-if-!="/imm32/subx-name + 9309 0/imm32/no-rm32 + 9310 0/imm32/no-r32 + 9311 0/imm32/no-imm32 + 9312 1/imm32/disp32-is-first-inout + 9313 0/imm32/no-output + 9314 _Primitive-loop-if-addr<=-named/imm32/next + 9315 _Primitive-loop-if-addr<=-named: + 9316 "loop-if-addr<="/imm32/name + 9317 Single-lit-var/imm32/inouts + 9318 0/imm32/outputs + 9319 "0f 86/jump-if-addr<="/imm32/subx-name + 9320 0/imm32/no-rm32 + 9321 0/imm32/no-r32 + 9322 0/imm32/no-imm32 + 9323 1/imm32/disp32-is-first-inout + 9324 0/imm32/no-output + 9325 _Primitive-loop-if-addr>-named/imm32/next + 9326 _Primitive-loop-if-addr>-named: + 9327 "loop-if-addr>"/imm32/name + 9328 Single-lit-var/imm32/inouts + 9329 0/imm32/outputs + 9330 "0f 87/jump-if-addr>"/imm32/subx-name + 9331 0/imm32/no-rm32 + 9332 0/imm32/no-r32 + 9333 0/imm32/no-imm32 + 9334 1/imm32/disp32-is-first-inout + 9335 0/imm32/no-output + 9336 _Primitive-loop-if-<-named/imm32/next + 9337 _Primitive-loop-if-<-named: + 9338 "loop-if-<"/imm32/name + 9339 Single-lit-var/imm32/inouts + 9340 0/imm32/outputs + 9341 "0f 8c/jump-if-<"/imm32/subx-name + 9342 0/imm32/no-rm32 + 9343 0/imm32/no-r32 + 9344 0/imm32/no-imm32 + 9345 1/imm32/disp32-is-first-inout + 9346 0/imm32/no-output + 9347 _Primitive-loop-if->=-named/imm32/next + 9348 _Primitive-loop-if->=-named: + 9349 "loop-if->="/imm32/name + 9350 Single-lit-var/imm32/inouts + 9351 0/imm32/outputs + 9352 "0f 8d/jump-if->="/imm32/subx-name + 9353 0/imm32/no-rm32 + 9354 0/imm32/no-r32 + 9355 0/imm32/no-imm32 + 9356 1/imm32/disp32-is-first-inout + 9357 0/imm32/no-output + 9358 _Primitive-loop-if-<=-named/imm32/next + 9359 _Primitive-loop-if-<=-named: + 9360 "loop-if-<="/imm32/name + 9361 Single-lit-var/imm32/inouts + 9362 0/imm32/outputs + 9363 "0f 8e/jump-if-<="/imm32/subx-name + 9364 0/imm32/no-rm32 + 9365 0/imm32/no-r32 + 9366 0/imm32/no-imm32 + 9367 1/imm32/disp32-is-first-inout + 9368 0/imm32/no-output + 9369 _Primitive-loop-if->-named/imm32/next + 9370 _Primitive-loop-if->-named: + 9371 "loop-if->"/imm32/name + 9372 Single-lit-var/imm32/inouts + 9373 0/imm32/outputs + 9374 "0f 8f/jump-if->"/imm32/subx-name + 9375 0/imm32/no-rm32 + 9376 0/imm32/no-r32 + 9377 0/imm32/no-imm32 + 9378 1/imm32/disp32-is-first-inout + 9379 0/imm32/no-output + 9380 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break + 9381 _Primitive-loop-named: + 9382 "loop"/imm32/name + 9383 Single-lit-var/imm32/inouts + 9384 0/imm32/outputs + 9385 "e9/jump"/imm32/subx-name + 9386 0/imm32/no-rm32 + 9387 0/imm32/no-r32 + 9388 0/imm32/no-imm32 + 9389 1/imm32/disp32-is-first-inout + 9390 0/imm32/no-output + 9391 0/imm32/next + 9392 + 9393 Single-int-var-in-mem: + 9394 Int-var-in-mem/imm32 + 9395 0/imm32/next + 9396 + 9397 Int-var-in-mem: + 9398 "arg1"/imm32/name + 9399 Type-int/imm32 + 9400 1/imm32/some-block-depth + 9401 1/imm32/some-stack-offset + 9402 0/imm32/no-register + 9403 + 9404 Two-args-int-stack-int-reg: + 9405 Int-var-in-mem/imm32 + 9406 Single-int-var-in-some-register/imm32/next + 9407 + 9408 Two-args-int-reg-int-stack: + 9409 Int-var-in-some-register/imm32 + 9410 Single-int-var-in-mem/imm32/next + 9411 + 9412 Two-args-int-eax-int-literal: + 9413 Int-var-in-eax/imm32 + 9414 Single-lit-var/imm32/next + 9415 + 9416 Int-var-and-literal: + 9417 Int-var-in-mem/imm32 + 9418 Single-lit-var/imm32/next 9419 - 9420 Single-int-var-in-esi: - 9421 Int-var-in-esi/imm32 - 9422 0/imm32/next + 9420 Int-var-in-register-and-literal: + 9421 Int-var-in-some-register/imm32 + 9422 Single-lit-var/imm32/next 9423 - 9424 Int-var-in-esi: - 9425 "arg1"/imm32/name - 9426 Type-int/imm32 - 9427 1/imm32/some-block-depth - 9428 0/imm32/no-stack-offset - 9429 "esi"/imm32/register - 9430 - 9431 Single-int-var-in-edi: - 9432 Int-var-in-edi/imm32 - 9433 0/imm32/next - 9434 - 9435 Int-var-in-edi: - 9436 "arg1"/imm32/name - 9437 Type-int/imm32 - 9438 1/imm32/some-block-depth - 9439 0/imm32/no-stack-offset - 9440 "edi"/imm32/register - 9441 - 9442 Single-lit-var: - 9443 Lit-var/imm32 - 9444 0/imm32/next + 9424 Single-int-var-in-some-register: + 9425 Int-var-in-some-register/imm32 + 9426 0/imm32/next + 9427 + 9428 Single-addr-var-in-some-register: + 9429 Addr-var-in-some-register/imm32 + 9430 0/imm32/next + 9431 + 9432 Int-var-in-some-register: + 9433 "arg1"/imm32/name + 9434 Type-int/imm32 + 9435 1/imm32/some-block-depth + 9436 0/imm32/no-stack-offset + 9437 Any-register/imm32 + 9438 + 9439 Addr-var-in-some-register: + 9440 "arg1"/imm32/name + 9441 Type-addr/imm32 + 9442 1/imm32/some-block-depth + 9443 0/imm32/no-stack-offset + 9444 Any-register/imm32 9445 - 9446 Lit-var: - 9447 "literal"/imm32/name - 9448 Type-literal/imm32 - 9449 1/imm32/some-block-depth - 9450 0/imm32/no-stack-offset - 9451 0/imm32/no-register - 9452 - 9453 Type-int: - 9454 1/imm32/left/int - 9455 0/imm32/right/null + 9446 Single-int-var-in-eax: + 9447 Int-var-in-eax/imm32 + 9448 0/imm32/next + 9449 + 9450 Int-var-in-eax: + 9451 "arg1"/imm32/name + 9452 Type-int/imm32 + 9453 1/imm32/some-block-depth + 9454 0/imm32/no-stack-offset + 9455 "eax"/imm32/register 9456 - 9457 Type-literal: - 9458 0/imm32/left/literal - 9459 0/imm32/right/null + 9457 Single-int-var-in-ecx: + 9458 Int-var-in-ecx/imm32 + 9459 0/imm32/next 9460 - 9461 == code - 9462 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) - 9463 # . prologue - 9464 55/push-ebp - 9465 89/<- %ebp 4/r32/esp - 9466 # . save registers - 9467 50/push-eax - 9468 51/push-ecx - 9469 # ecx = primitive - 9470 8b/-> *(ebp+0x10) 1/r32/ecx - 9471 # emit primitive name - 9472 (emit-indent *(ebp+8) *Curr-block-depth) - 9473 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name - 9474 # emit rm32 if necessary - 9475 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt - 9476 # emit r32 if necessary - 9477 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt - 9478 # emit imm32 if necessary - 9479 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt - 9480 # emit disp32 if necessary - 9481 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt - 9482 (write-buffered *(ebp+8) Newline) - 9483 $emit-subx-primitive:end: - 9484 # . restore registers - 9485 59/pop-to-ecx - 9486 58/pop-to-eax - 9487 # . epilogue - 9488 89/<- %esp 5/r32/ebp - 9489 5d/pop-to-ebp - 9490 c3/return - 9491 - 9492 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9493 # . prologue - 9494 55/push-ebp - 9495 89/<- %ebp 4/r32/esp - 9496 # . save registers - 9497 50/push-eax - 9498 # if (l == 0) return - 9499 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9500 74/jump-if-= $emit-subx-rm32:end/disp8 - 9501 # var v/eax: (handle var) - 9502 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9503 (emit-subx-var-as-rm32 *(ebp+8) %eax) - 9504 $emit-subx-rm32:end: - 9505 # . restore registers - 9506 58/pop-to-eax - 9507 # . epilogue - 9508 89/<- %esp 5/r32/ebp - 9509 5d/pop-to-ebp - 9510 c3/return + 9461 Int-var-in-ecx: + 9462 "arg1"/imm32/name + 9463 Type-int/imm32 + 9464 1/imm32/some-block-depth + 9465 0/imm32/no-stack-offset + 9466 "ecx"/imm32/register + 9467 + 9468 Single-int-var-in-edx: + 9469 Int-var-in-edx/imm32 + 9470 0/imm32/next + 9471 + 9472 Int-var-in-edx: + 9473 "arg1"/imm32/name + 9474 Type-int/imm32 + 9475 1/imm32/some-block-depth + 9476 0/imm32/no-stack-offset + 9477 "edx"/imm32/register + 9478 + 9479 Single-int-var-in-ebx: + 9480 Int-var-in-ebx/imm32 + 9481 0/imm32/next + 9482 + 9483 Int-var-in-ebx: + 9484 "arg1"/imm32/name + 9485 Type-int/imm32 + 9486 1/imm32/some-block-depth + 9487 0/imm32/no-stack-offset + 9488 "ebx"/imm32/register + 9489 + 9490 Single-int-var-in-esi: + 9491 Int-var-in-esi/imm32 + 9492 0/imm32/next + 9493 + 9494 Int-var-in-esi: + 9495 "arg1"/imm32/name + 9496 Type-int/imm32 + 9497 1/imm32/some-block-depth + 9498 0/imm32/no-stack-offset + 9499 "esi"/imm32/register + 9500 + 9501 Single-int-var-in-edi: + 9502 Int-var-in-edi/imm32 + 9503 0/imm32/next + 9504 + 9505 Int-var-in-edi: + 9506 "arg1"/imm32/name + 9507 Type-int/imm32 + 9508 1/imm32/some-block-depth + 9509 0/imm32/no-stack-offset + 9510 "edi"/imm32/register 9511 - 9512 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) - 9513 # . prologue - 9514 55/push-ebp - 9515 89/<- %ebp 4/r32/esp - 9516 # . save registers - 9517 51/push-ecx - 9518 # eax = l - 9519 8b/-> *(ebp+0xc) 0/r32/eax - 9520 # ecx = stmt - 9521 8b/-> *(ebp+8) 1/r32/ecx - 9522 # if (l == 1) return stmt->inouts - 9523 { - 9524 3d/compare-eax-and 1/imm32 - 9525 75/jump-if-!= break/disp8 - 9526 $get-stmt-operand-from-arg-location:1: - 9527 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 9528 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9529 } - 9530 # if (l == 2) return stmt->inouts->next - 9531 { - 9532 3d/compare-eax-and 2/imm32 - 9533 75/jump-if-!= break/disp8 - 9534 $get-stmt-operand-from-arg-location:2: - 9535 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 9536 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 9537 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9538 } - 9539 # if (l == 3) return stmt->outputs - 9540 { - 9541 3d/compare-eax-and 3/imm32 - 9542 75/jump-if-!= break/disp8 - 9543 $get-stmt-operand-from-arg-location:3: - 9544 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 9545 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 9546 } - 9547 # abort - 9548 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 - 9549 $get-stmt-operand-from-arg-location:end: - 9550 # . restore registers - 9551 59/pop-to-ecx - 9552 # . epilogue - 9553 89/<- %esp 5/r32/ebp - 9554 5d/pop-to-ebp - 9555 c3/return - 9556 - 9557 $get-stmt-operand-from-arg-location:abort: - 9558 # error("invalid arg-location " eax) - 9559 (write-buffered Stderr "invalid arg-location ") - 9560 (print-int32-buffered Stderr %eax) - 9561 (write-buffered Stderr Newline) - 9562 (flush Stderr) - 9563 # . syscall(exit, 1) - 9564 bb/copy-to-ebx 1/imm32 - 9565 b8/copy-to-eax 1/imm32/exit - 9566 cd/syscall 0x80/imm8 - 9567 # never gets here - 9568 - 9569 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9570 # . prologue - 9571 55/push-ebp - 9572 89/<- %ebp 4/r32/esp - 9573 # . save registers - 9574 50/push-eax - 9575 51/push-ecx - 9576 # if (location == 0) return - 9577 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9578 0f 84/jump-if-= $emit-subx-r32:end/disp32 - 9579 # var v/eax: (handle var) - 9580 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9581 8b/-> *eax 0/r32/eax # Stmt-var-value - 9582 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) - 9583 (write-buffered *(ebp+8) Space) - 9584 (print-int32-buffered *(ebp+8) *eax) - 9585 (write-buffered *(ebp+8) "/r32") - 9586 $emit-subx-r32:end: - 9587 # . restore registers - 9588 59/pop-to-ecx - 9589 58/pop-to-eax - 9590 # . epilogue - 9591 89/<- %esp 5/r32/ebp - 9592 5d/pop-to-ebp - 9593 c3/return - 9594 - 9595 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9596 # . prologue - 9597 55/push-ebp - 9598 89/<- %ebp 4/r32/esp - 9599 # . save registers - 9600 50/push-eax - 9601 51/push-ecx - 9602 # if (location == 0) return - 9603 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9604 74/jump-if-= $emit-subx-imm32:end/disp8 - 9605 # var v/eax: (handle var) - 9606 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9607 8b/-> *eax 0/r32/eax # Stmt-var-value - 9608 (write-buffered *(ebp+8) Space) - 9609 (write-buffered *(ebp+8) *eax) # Var-name - 9610 (write-buffered *(ebp+8) "/imm32") - 9611 $emit-subx-imm32:end: - 9612 # . restore registers - 9613 59/pop-to-ecx - 9614 58/pop-to-eax - 9615 # . epilogue - 9616 89/<- %esp 5/r32/ebp - 9617 5d/pop-to-ebp - 9618 c3/return - 9619 - 9620 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 9621 # . prologue - 9622 55/push-ebp - 9623 89/<- %ebp 4/r32/esp - 9624 # . save registers - 9625 50/push-eax - 9626 51/push-ecx - 9627 # if (location == 0) return - 9628 81 7/subop/compare *(ebp+0xc) 0/imm32 - 9629 0f 84/jump-if-= $emit-subx-disp32:end/disp32 - 9630 # var v/eax: (handle var) - 9631 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 9632 8b/-> *eax 0/r32/eax # Stmt-var-value - 9633 (write-buffered *(ebp+8) Space) - 9634 (write-buffered *(ebp+8) *eax) # Var-name - 9635 # hack: if instruction operation starts with "break", emit ":break" - 9636 # var name/ecx: (addr array byte) = stmt->operation - 9637 8b/-> *(ebp+0x10) 0/r32/eax - 9638 8b/-> *(eax+4) 1/r32/ecx - 9639 { - 9640 (string-starts-with? %ecx "break") # => eax - 9641 3d/compare-eax-and 0/imm32/false - 9642 74/jump-if-= break/disp8 - 9643 (write-buffered *(ebp+8) ":break") - 9644 } - 9645 # hack: if instruction operation starts with "loop", emit ":loop" - 9646 { - 9647 (string-starts-with? %ecx "loop") # => eax - 9648 3d/compare-eax-and 0/imm32/false - 9649 74/jump-if-= break/disp8 - 9650 (write-buffered *(ebp+8) ":loop") - 9651 } - 9652 (write-buffered *(ebp+8) "/disp32") - 9653 $emit-subx-disp32:end: - 9654 # . restore registers - 9655 59/pop-to-ecx - 9656 58/pop-to-eax - 9657 # . epilogue - 9658 89/<- %esp 5/r32/ebp - 9659 5d/pop-to-ebp - 9660 c3/return - 9661 - 9662 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) - 9663 # . prologue - 9664 55/push-ebp - 9665 89/<- %ebp 4/r32/esp - 9666 # . save registers - 9667 51/push-ecx - 9668 # - 9669 (emit-indent *(ebp+8) *Curr-block-depth) - 9670 (write-buffered *(ebp+8) "(") - 9671 # - emit function name - 9672 8b/-> *(ebp+0x10) 1/r32/ecx - 9673 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name - 9674 # - emit arguments - 9675 # var curr/ecx: (handle stmt-var) = stmt->inouts - 9676 8b/-> *(ebp+0xc) 1/r32/ecx - 9677 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 9678 { - 9679 # if (curr == null) break - 9680 81 7/subop/compare %ecx 0/imm32 - 9681 74/jump-if-= break/disp8 - 9682 # - 9683 (emit-subx-call-operand *(ebp+8) %ecx) - 9684 # curr = curr->next - 9685 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 9686 eb/jump loop/disp8 - 9687 } - 9688 # - 9689 (write-buffered *(ebp+8) ")\n") - 9690 $emit-subx-call:end: - 9691 # . restore registers - 9692 59/pop-to-ecx - 9693 # . epilogue - 9694 89/<- %esp 5/r32/ebp - 9695 5d/pop-to-ebp - 9696 c3/return - 9697 - 9698 # like a function call, except we have no idea what function it is - 9699 # we hope it's defined in SubX and that the types are ok - 9700 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) - 9701 # . prologue - 9702 55/push-ebp - 9703 89/<- %ebp 4/r32/esp - 9704 # . save registers - 9705 51/push-ecx - 9706 # - 9707 (emit-indent *(ebp+8) *Curr-block-depth) - 9708 (write-buffered *(ebp+8) "(") - 9709 # ecx = stmt - 9710 8b/-> *(ebp+0xc) 1/r32/ecx - 9711 # - emit function name - 9712 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation - 9713 # - emit arguments - 9714 # var curr/ecx: (handle stmt-var) = stmt->inouts - 9715 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 9716 { - 9717 # if (curr == null) break - 9718 81 7/subop/compare %ecx 0/imm32 - 9719 74/jump-if-= break/disp8 - 9720 # - 9721 (emit-subx-call-operand *(ebp+8) %ecx) - 9722 # curr = curr->next - 9723 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 9724 eb/jump loop/disp8 + 9512 Single-lit-var: + 9513 Lit-var/imm32 + 9514 0/imm32/next + 9515 + 9516 Lit-var: + 9517 "literal"/imm32/name + 9518 Type-literal/imm32 + 9519 1/imm32/some-block-depth + 9520 0/imm32/no-stack-offset + 9521 0/imm32/no-register + 9522 + 9523 Type-int: + 9524 1/imm32/left/int + 9525 0/imm32/right/null + 9526 + 9527 Type-literal: + 9528 0/imm32/left/literal + 9529 0/imm32/right/null + 9530 + 9531 Type-addr: + 9532 2/imm32/left/addr + 9533 0/imm32/right/null + 9534 + 9535 == code + 9536 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) + 9537 # . prologue + 9538 55/push-ebp + 9539 89/<- %ebp 4/r32/esp + 9540 # . save registers + 9541 50/push-eax + 9542 51/push-ecx + 9543 # ecx = primitive + 9544 8b/-> *(ebp+0x10) 1/r32/ecx + 9545 # emit primitive name + 9546 (emit-indent *(ebp+8) *Curr-block-depth) + 9547 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name + 9548 # emit rm32 if necessary + 9549 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt + 9550 # emit r32 if necessary + 9551 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt + 9552 # emit imm32 if necessary + 9553 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt + 9554 # emit disp32 if necessary + 9555 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt + 9556 (write-buffered *(ebp+8) Newline) + 9557 $emit-subx-primitive:end: + 9558 # . restore registers + 9559 59/pop-to-ecx + 9560 58/pop-to-eax + 9561 # . epilogue + 9562 89/<- %esp 5/r32/ebp + 9563 5d/pop-to-ebp + 9564 c3/return + 9565 + 9566 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9567 # . prologue + 9568 55/push-ebp + 9569 89/<- %ebp 4/r32/esp + 9570 # . save registers + 9571 50/push-eax + 9572 # if (l == 0) return + 9573 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9574 74/jump-if-= $emit-subx-rm32:end/disp8 + 9575 # var v/eax: (handle var) + 9576 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9577 (emit-subx-var-as-rm32 *(ebp+8) %eax) + 9578 $emit-subx-rm32:end: + 9579 # . restore registers + 9580 58/pop-to-eax + 9581 # . epilogue + 9582 89/<- %esp 5/r32/ebp + 9583 5d/pop-to-ebp + 9584 c3/return + 9585 + 9586 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) + 9587 # . prologue + 9588 55/push-ebp + 9589 89/<- %ebp 4/r32/esp + 9590 # . save registers + 9591 51/push-ecx + 9592 # eax = l + 9593 8b/-> *(ebp+0xc) 0/r32/eax + 9594 # ecx = stmt + 9595 8b/-> *(ebp+8) 1/r32/ecx + 9596 # if (l == 1) return stmt->inouts + 9597 { + 9598 3d/compare-eax-and 1/imm32 + 9599 75/jump-if-!= break/disp8 + 9600 $get-stmt-operand-from-arg-location:1: + 9601 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 9602 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9603 } + 9604 # if (l == 2) return stmt->inouts->next + 9605 { + 9606 3d/compare-eax-and 2/imm32 + 9607 75/jump-if-!= break/disp8 + 9608 $get-stmt-operand-from-arg-location:2: + 9609 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 9610 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 9611 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9612 } + 9613 # if (l == 3) return stmt->outputs + 9614 { + 9615 3d/compare-eax-and 3/imm32 + 9616 75/jump-if-!= break/disp8 + 9617 $get-stmt-operand-from-arg-location:3: + 9618 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 9619 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 9620 } + 9621 # abort + 9622 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 + 9623 $get-stmt-operand-from-arg-location:end: + 9624 # . restore registers + 9625 59/pop-to-ecx + 9626 # . epilogue + 9627 89/<- %esp 5/r32/ebp + 9628 5d/pop-to-ebp + 9629 c3/return + 9630 + 9631 $get-stmt-operand-from-arg-location:abort: + 9632 # error("invalid arg-location " eax) + 9633 (write-buffered Stderr "invalid arg-location ") + 9634 (print-int32-buffered Stderr %eax) + 9635 (write-buffered Stderr Newline) + 9636 (flush Stderr) + 9637 # . syscall(exit, 1) + 9638 bb/copy-to-ebx 1/imm32 + 9639 b8/copy-to-eax 1/imm32/exit + 9640 cd/syscall 0x80/imm8 + 9641 # never gets here + 9642 + 9643 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9644 # . prologue + 9645 55/push-ebp + 9646 89/<- %ebp 4/r32/esp + 9647 # . save registers + 9648 50/push-eax + 9649 51/push-ecx + 9650 # if (location == 0) return + 9651 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9652 0f 84/jump-if-= $emit-subx-r32:end/disp32 + 9653 # var v/eax: (handle var) + 9654 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9655 8b/-> *eax 0/r32/eax # Stmt-var-value + 9656 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) + 9657 (write-buffered *(ebp+8) Space) + 9658 (print-int32-buffered *(ebp+8) *eax) + 9659 (write-buffered *(ebp+8) "/r32") + 9660 $emit-subx-r32:end: + 9661 # . restore registers + 9662 59/pop-to-ecx + 9663 58/pop-to-eax + 9664 # . epilogue + 9665 89/<- %esp 5/r32/ebp + 9666 5d/pop-to-ebp + 9667 c3/return + 9668 + 9669 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9670 # . prologue + 9671 55/push-ebp + 9672 89/<- %ebp 4/r32/esp + 9673 # . save registers + 9674 50/push-eax + 9675 51/push-ecx + 9676 # if (location == 0) return + 9677 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9678 74/jump-if-= $emit-subx-imm32:end/disp8 + 9679 # var v/eax: (handle var) + 9680 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9681 8b/-> *eax 0/r32/eax # Stmt-var-value + 9682 (write-buffered *(ebp+8) Space) + 9683 (write-buffered *(ebp+8) *eax) # Var-name + 9684 (write-buffered *(ebp+8) "/imm32") + 9685 $emit-subx-imm32:end: + 9686 # . restore registers + 9687 59/pop-to-ecx + 9688 58/pop-to-eax + 9689 # . epilogue + 9690 89/<- %esp 5/r32/ebp + 9691 5d/pop-to-ebp + 9692 c3/return + 9693 + 9694 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 9695 # . prologue + 9696 55/push-ebp + 9697 89/<- %ebp 4/r32/esp + 9698 # . save registers + 9699 50/push-eax + 9700 51/push-ecx + 9701 # if (location == 0) return + 9702 81 7/subop/compare *(ebp+0xc) 0/imm32 + 9703 0f 84/jump-if-= $emit-subx-disp32:end/disp32 + 9704 # var v/eax: (handle var) + 9705 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 9706 8b/-> *eax 0/r32/eax # Stmt-var-value + 9707 (write-buffered *(ebp+8) Space) + 9708 (write-buffered *(ebp+8) *eax) # Var-name + 9709 # hack: if instruction operation starts with "break", emit ":break" + 9710 # var name/ecx: (addr array byte) = stmt->operation + 9711 8b/-> *(ebp+0x10) 0/r32/eax + 9712 8b/-> *(eax+4) 1/r32/ecx + 9713 { + 9714 (string-starts-with? %ecx "break") # => eax + 9715 3d/compare-eax-and 0/imm32/false + 9716 74/jump-if-= break/disp8 + 9717 (write-buffered *(ebp+8) ":break") + 9718 } + 9719 # hack: if instruction operation starts with "loop", emit ":loop" + 9720 { + 9721 (string-starts-with? %ecx "loop") # => eax + 9722 3d/compare-eax-and 0/imm32/false + 9723 74/jump-if-= break/disp8 + 9724 (write-buffered *(ebp+8) ":loop") 9725 } - 9726 # - 9727 (write-buffered *(ebp+8) ")\n") - 9728 $emit-hailmary-call:end: - 9729 # . restore registers - 9730 59/pop-to-ecx + 9726 (write-buffered *(ebp+8) "/disp32") + 9727 $emit-subx-disp32:end: + 9728 # . restore registers + 9729 59/pop-to-ecx + 9730 58/pop-to-eax 9731 # . epilogue 9732 89/<- %esp 5/r32/ebp 9733 5d/pop-to-ebp 9734 c3/return 9735 - 9736 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) - 9737 # shares code with emit-subx-var-as-rm32 - 9738 # . prologue - 9739 55/push-ebp - 9740 89/<- %ebp 4/r32/esp - 9741 # . save registers - 9742 50/push-eax - 9743 51/push-ecx - 9744 56/push-esi - 9745 # ecx = s - 9746 8b/-> *(ebp+0xc) 1/r32/ecx - 9747 # var operand/esi: (handle var) = s->value - 9748 8b/-> *ecx 6/r32/esi # Stmt-var-value - 9749 # if (operand->register && s->is-deref?) emit "*__" - 9750 { - 9751 $emit-subx-call-operand:check-for-register-indirect: - 9752 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9753 74/jump-if-= break/disp8 - 9754 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9736 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) + 9737 # . prologue + 9738 55/push-ebp + 9739 89/<- %ebp 4/r32/esp + 9740 # . save registers + 9741 51/push-ecx + 9742 # + 9743 (emit-indent *(ebp+8) *Curr-block-depth) + 9744 (write-buffered *(ebp+8) "(") + 9745 # - emit function name + 9746 8b/-> *(ebp+0x10) 1/r32/ecx + 9747 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name + 9748 # - emit arguments + 9749 # var curr/ecx: (handle stmt-var) = stmt->inouts + 9750 8b/-> *(ebp+0xc) 1/r32/ecx + 9751 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 9752 { + 9753 # if (curr == null) break + 9754 81 7/subop/compare %ecx 0/imm32 9755 74/jump-if-= break/disp8 - 9756 $emit-subx-call-operand:register-indirect: - 9757 (write-buffered *(ebp+8) " *") - 9758 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9759 e9/jump $emit-subx-call-operand:end/disp32 - 9760 } - 9761 # if (operand->register && !s->is-deref?) emit "%__" - 9762 { - 9763 $emit-subx-call-operand:check-for-register-direct: - 9764 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9765 74/jump-if-= break/disp8 - 9766 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9767 75/jump-if-!= break/disp8 - 9768 $emit-subx-call-operand:register-direct: - 9769 (write-buffered *(ebp+8) " %") - 9770 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9771 e9/jump $emit-subx-call-operand:end/disp32 - 9772 } - 9773 # else if (operand->stack-offset) emit "*(ebp+__)" - 9774 { - 9775 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 9776 74/jump-if-= break/disp8 - 9777 $emit-subx-call-operand:stack: - 9778 (write-buffered *(ebp+8) Space) - 9779 (write-buffered *(ebp+8) "*(ebp+") - 9780 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 9781 (write-buffered *(ebp+8) ")") - 9782 e9/jump $emit-subx-call-operand:end/disp32 - 9783 } - 9784 # else if (operand->type == literal) emit "__" - 9785 { - 9786 8b/-> *(esi+4) 0/r32/eax # Var-type - 9787 81 7/subop/compare *eax 0/imm32 # Tree-left - 9788 75/jump-if-!= break/disp8 - 9789 $emit-subx-call-operand:literal: - 9790 (write-buffered *(ebp+8) Space) - 9791 (write-buffered *(ebp+8) *esi) - 9792 } - 9793 $emit-subx-call-operand:end: - 9794 # . restore registers - 9795 5e/pop-to-esi - 9796 59/pop-to-ecx - 9797 58/pop-to-eax - 9798 # . epilogue - 9799 89/<- %esp 5/r32/ebp - 9800 5d/pop-to-ebp - 9801 c3/return - 9802 - 9803 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) - 9804 # . prologue - 9805 55/push-ebp - 9806 89/<- %ebp 4/r32/esp - 9807 # . save registers - 9808 50/push-eax - 9809 51/push-ecx - 9810 56/push-esi - 9811 # ecx = s - 9812 8b/-> *(ebp+0xc) 1/r32/ecx - 9813 # var operand/esi: (handle var) = s->value - 9814 8b/-> *ecx 6/r32/esi # Stmt-var-value - 9815 # if (operand->register && s->is-deref?) emit "*__" - 9816 { - 9817 $emit-subx-var-as-rm32:check-for-register-indirect: - 9818 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9819 74/jump-if-= break/disp8 - 9820 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9821 74/jump-if-= break/disp8 - 9822 $emit-subx-var-as-rm32:register-indirect: - 9823 (write-buffered *(ebp+8) " *") - 9824 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9825 } - 9826 # if (operand->register && !s->is-deref?) emit "%__" - 9827 { - 9828 $emit-subx-var-as-rm32:check-for-register-direct: - 9829 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9830 74/jump-if-= break/disp8 - 9831 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9832 75/jump-if-!= break/disp8 - 9833 $emit-subx-var-as-rm32:register-direct: - 9834 (write-buffered *(ebp+8) " %") - 9835 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 9836 } - 9837 # else if (operand->stack-offset) emit "*(ebp+__)" - 9838 { - 9839 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 9840 74/jump-if-= break/disp8 - 9841 $emit-subx-var-as-rm32:stack: - 9842 (write-buffered *(ebp+8) Space) - 9843 (write-buffered *(ebp+8) "*(ebp+") - 9844 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 9845 (write-buffered *(ebp+8) ")") + 9756 # + 9757 (emit-subx-call-operand *(ebp+8) %ecx) + 9758 # curr = curr->next + 9759 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next + 9760 eb/jump loop/disp8 + 9761 } + 9762 # + 9763 (write-buffered *(ebp+8) ")\n") + 9764 $emit-subx-call:end: + 9765 # . restore registers + 9766 59/pop-to-ecx + 9767 # . epilogue + 9768 89/<- %esp 5/r32/ebp + 9769 5d/pop-to-ebp + 9770 c3/return + 9771 + 9772 # like a function call, except we have no idea what function it is + 9773 # we hope it's defined in SubX and that the types are ok + 9774 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) + 9775 # . prologue + 9776 55/push-ebp + 9777 89/<- %ebp 4/r32/esp + 9778 # . save registers + 9779 51/push-ecx + 9780 # + 9781 (emit-indent *(ebp+8) *Curr-block-depth) + 9782 (write-buffered *(ebp+8) "(") + 9783 # ecx = stmt + 9784 8b/-> *(ebp+0xc) 1/r32/ecx + 9785 # - emit function name + 9786 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation + 9787 # - emit arguments + 9788 # var curr/ecx: (handle stmt-var) = stmt->inouts + 9789 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 9790 { + 9791 # if (curr == null) break + 9792 81 7/subop/compare %ecx 0/imm32 + 9793 74/jump-if-= break/disp8 + 9794 # + 9795 (emit-subx-call-operand *(ebp+8) %ecx) + 9796 # curr = curr->next + 9797 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next + 9798 eb/jump loop/disp8 + 9799 } + 9800 # + 9801 (write-buffered *(ebp+8) ")\n") + 9802 $emit-hailmary-call:end: + 9803 # . restore registers + 9804 59/pop-to-ecx + 9805 # . epilogue + 9806 89/<- %esp 5/r32/ebp + 9807 5d/pop-to-ebp + 9808 c3/return + 9809 + 9810 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) + 9811 # shares code with emit-subx-var-as-rm32 + 9812 # . prologue + 9813 55/push-ebp + 9814 89/<- %ebp 4/r32/esp + 9815 # . save registers + 9816 50/push-eax + 9817 51/push-ecx + 9818 56/push-esi + 9819 # ecx = s + 9820 8b/-> *(ebp+0xc) 1/r32/ecx + 9821 # var operand/esi: (handle var) = s->value + 9822 8b/-> *ecx 6/r32/esi # Stmt-var-value + 9823 # if (operand->register && s->is-deref?) emit "*__" + 9824 { + 9825 $emit-subx-call-operand:check-for-register-indirect: + 9826 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9827 74/jump-if-= break/disp8 + 9828 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9829 74/jump-if-= break/disp8 + 9830 $emit-subx-call-operand:register-indirect: + 9831 (write-buffered *(ebp+8) " *") + 9832 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 9833 e9/jump $emit-subx-call-operand:end/disp32 + 9834 } + 9835 # if (operand->register && !s->is-deref?) emit "%__" + 9836 { + 9837 $emit-subx-call-operand:check-for-register-direct: + 9838 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9839 74/jump-if-= break/disp8 + 9840 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9841 75/jump-if-!= break/disp8 + 9842 $emit-subx-call-operand:register-direct: + 9843 (write-buffered *(ebp+8) " %") + 9844 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 9845 e9/jump $emit-subx-call-operand:end/disp32 9846 } - 9847 $emit-subx-var-as-rm32:end: - 9848 # . restore registers - 9849 5e/pop-to-esi - 9850 59/pop-to-ecx - 9851 58/pop-to-eax - 9852 # . epilogue - 9853 89/<- %esp 5/r32/ebp - 9854 5d/pop-to-ebp - 9855 c3/return - 9856 - 9857 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) - 9858 # . prologue - 9859 55/push-ebp - 9860 89/<- %ebp 4/r32/esp - 9861 # . save registers - 9862 51/push-ecx - 9863 # var curr/ecx: (handle function) = functions - 9864 8b/-> *(ebp+8) 1/r32/ecx - 9865 { - 9866 # if (curr == null) break - 9867 81 7/subop/compare %ecx 0/imm32 - 9868 74/jump-if-= break/disp8 - 9869 # if match(stmt, curr) return curr - 9870 { - 9871 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax - 9872 3d/compare-eax-and 0/imm32/false - 9873 74/jump-if-= break/disp8 - 9874 89/<- %eax 1/r32/ecx - 9875 eb/jump $find-matching-function:end/disp8 - 9876 } - 9877 # curr = curr->next - 9878 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next - 9879 eb/jump loop/disp8 - 9880 } - 9881 # return null - 9882 b8/copy-to-eax 0/imm32 - 9883 $find-matching-function:end: - 9884 # . restore registers - 9885 59/pop-to-ecx - 9886 # . epilogue - 9887 89/<- %esp 5/r32/ebp - 9888 5d/pop-to-ebp - 9889 c3/return - 9890 - 9891 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) - 9892 # . prologue - 9893 55/push-ebp - 9894 89/<- %ebp 4/r32/esp - 9895 # . save registers - 9896 51/push-ecx - 9897 # var curr/ecx: (handle primitive) = primitives - 9898 8b/-> *(ebp+8) 1/r32/ecx - 9899 { - 9900 $find-matching-primitive:loop: - 9901 # if (curr == null) break - 9902 81 7/subop/compare %ecx 0/imm32 - 9903 0f 84/jump-if-= break/disp32 - 9904 #? (write-buffered Stderr "prim: ") - 9905 #? (write-buffered Stderr *ecx) # Primitive-name - 9906 #? (write-buffered Stderr " => ") - 9907 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name - 9908 #? (write-buffered Stderr Newline) - 9909 #? (flush Stderr) - 9910 # if match(curr, stmt) return curr - 9911 { - 9912 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax - 9913 3d/compare-eax-and 0/imm32/false - 9914 74/jump-if-= break/disp8 - 9915 89/<- %eax 1/r32/ecx - 9916 eb/jump $find-matching-primitive:end/disp8 - 9917 } - 9918 $find-matching-primitive:next-primitive: - 9919 # curr = curr->next - 9920 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next - 9921 e9/jump loop/disp32 - 9922 } - 9923 # return null - 9924 b8/copy-to-eax 0/imm32 - 9925 $find-matching-primitive:end: - 9926 # . restore registers - 9927 59/pop-to-ecx - 9928 # . epilogue - 9929 89/<- %esp 5/r32/ebp - 9930 5d/pop-to-ebp - 9931 c3/return - 9932 - 9933 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean - 9934 # . prologue - 9935 55/push-ebp - 9936 89/<- %ebp 4/r32/esp - 9937 # . save registers - 9938 51/push-ecx - 9939 # return function->name == stmt->operation - 9940 8b/-> *(ebp+8) 1/r32/ecx - 9941 8b/-> *(ebp+0xc) 0/r32/eax - 9942 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax - 9943 $mu-stmt-matches-function?:end: - 9944 # . restore registers - 9945 59/pop-to-ecx - 9946 # . epilogue - 9947 89/<- %esp 5/r32/ebp - 9948 5d/pop-to-ebp - 9949 c3/return - 9950 - 9951 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean - 9952 # A mu stmt matches a primitive if the name matches, all the inout vars - 9953 # match, and all the output vars match. - 9954 # Vars match if types match and registers match. - 9955 # In addition, a stmt output matches a primitive's output if types match - 9956 # and the primitive has a wildcard register. - 9957 # . prologue - 9958 55/push-ebp - 9959 89/<- %ebp 4/r32/esp - 9960 # . save registers - 9961 51/push-ecx - 9962 52/push-edx - 9963 53/push-ebx - 9964 56/push-esi - 9965 57/push-edi - 9966 # ecx = stmt - 9967 8b/-> *(ebp+8) 1/r32/ecx - 9968 # edx = primitive - 9969 8b/-> *(ebp+0xc) 2/r32/edx - 9970 { - 9971 $mu-stmt-matches-primitive?:check-name: - 9972 # if (primitive->name != stmt->operation) return false - 9973 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax - 9974 3d/compare-eax-and 0/imm32/false - 9975 75/jump-if-!= break/disp8 - 9976 b8/copy-to-eax 0/imm32 - 9977 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 9978 } - 9979 $mu-stmt-matches-primitive?:check-inouts: - 9980 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) - 9981 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts - 9982 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts - 9983 { - 9984 # if (curr == 0 && curr2 == 0) move on to check outputs + 9847 # else if (operand->stack-offset) emit "*(ebp+__)" + 9848 { + 9849 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset + 9850 74/jump-if-= break/disp8 + 9851 $emit-subx-call-operand:stack: + 9852 (write-buffered *(ebp+8) Space) + 9853 (write-buffered *(ebp+8) "*(ebp+") + 9854 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset + 9855 (write-buffered *(ebp+8) ")") + 9856 e9/jump $emit-subx-call-operand:end/disp32 + 9857 } + 9858 # else if (operand->type == literal) emit "__" + 9859 { + 9860 8b/-> *(esi+4) 0/r32/eax # Var-type + 9861 81 7/subop/compare *eax 0/imm32 # Tree-left + 9862 75/jump-if-!= break/disp8 + 9863 $emit-subx-call-operand:literal: + 9864 (write-buffered *(ebp+8) Space) + 9865 (write-buffered *(ebp+8) *esi) + 9866 } + 9867 $emit-subx-call-operand:end: + 9868 # . restore registers + 9869 5e/pop-to-esi + 9870 59/pop-to-ecx + 9871 58/pop-to-eax + 9872 # . epilogue + 9873 89/<- %esp 5/r32/ebp + 9874 5d/pop-to-ebp + 9875 c3/return + 9876 + 9877 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) + 9878 # . prologue + 9879 55/push-ebp + 9880 89/<- %ebp 4/r32/esp + 9881 # . save registers + 9882 50/push-eax + 9883 51/push-ecx + 9884 56/push-esi + 9885 # ecx = s + 9886 8b/-> *(ebp+0xc) 1/r32/ecx + 9887 # var operand/esi: (handle var) = s->value + 9888 8b/-> *ecx 6/r32/esi # Stmt-var-value + 9889 # if (operand->register && s->is-deref?) emit "*__" + 9890 { + 9891 $emit-subx-var-as-rm32:check-for-register-indirect: + 9892 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9893 74/jump-if-= break/disp8 + 9894 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9895 74/jump-if-= break/disp8 + 9896 $emit-subx-var-as-rm32:register-indirect: + 9897 (write-buffered *(ebp+8) " *") + 9898 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 9899 } + 9900 # if (operand->register && !s->is-deref?) emit "%__" + 9901 { + 9902 $emit-subx-var-as-rm32:check-for-register-direct: + 9903 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9904 74/jump-if-= break/disp8 + 9905 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9906 75/jump-if-!= break/disp8 + 9907 $emit-subx-var-as-rm32:register-direct: + 9908 (write-buffered *(ebp+8) " %") + 9909 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 9910 } + 9911 # else if (operand->stack-offset) emit "*(ebp+__)" + 9912 { + 9913 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset + 9914 74/jump-if-= break/disp8 + 9915 $emit-subx-var-as-rm32:stack: + 9916 (write-buffered *(ebp+8) Space) + 9917 (write-buffered *(ebp+8) "*(ebp+") + 9918 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset + 9919 (write-buffered *(ebp+8) ")") + 9920 } + 9921 $emit-subx-var-as-rm32:end: + 9922 # . restore registers + 9923 5e/pop-to-esi + 9924 59/pop-to-ecx + 9925 58/pop-to-eax + 9926 # . epilogue + 9927 89/<- %esp 5/r32/ebp + 9928 5d/pop-to-ebp + 9929 c3/return + 9930 + 9931 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) + 9932 # . prologue + 9933 55/push-ebp + 9934 89/<- %ebp 4/r32/esp + 9935 # . save registers + 9936 51/push-ecx + 9937 # var curr/ecx: (handle function) = functions + 9938 8b/-> *(ebp+8) 1/r32/ecx + 9939 { + 9940 # if (curr == null) break + 9941 81 7/subop/compare %ecx 0/imm32 + 9942 74/jump-if-= break/disp8 + 9943 # if match(stmt, curr) return curr + 9944 { + 9945 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax + 9946 3d/compare-eax-and 0/imm32/false + 9947 74/jump-if-= break/disp8 + 9948 89/<- %eax 1/r32/ecx + 9949 eb/jump $find-matching-function:end/disp8 + 9950 } + 9951 # curr = curr->next + 9952 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next + 9953 eb/jump loop/disp8 + 9954 } + 9955 # return null + 9956 b8/copy-to-eax 0/imm32 + 9957 $find-matching-function:end: + 9958 # . restore registers + 9959 59/pop-to-ecx + 9960 # . epilogue + 9961 89/<- %esp 5/r32/ebp + 9962 5d/pop-to-ebp + 9963 c3/return + 9964 + 9965 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) + 9966 # . prologue + 9967 55/push-ebp + 9968 89/<- %ebp 4/r32/esp + 9969 # . save registers + 9970 51/push-ecx + 9971 # var curr/ecx: (handle primitive) = primitives + 9972 8b/-> *(ebp+8) 1/r32/ecx + 9973 { + 9974 $find-matching-primitive:loop: + 9975 # if (curr == null) break + 9976 81 7/subop/compare %ecx 0/imm32 + 9977 0f 84/jump-if-= break/disp32 + 9978 #? (write-buffered Stderr "prim: ") + 9979 #? (write-buffered Stderr *ecx) # Primitive-name + 9980 #? (write-buffered Stderr " => ") + 9981 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name + 9982 #? (write-buffered Stderr Newline) + 9983 #? (flush Stderr) + 9984 # if match(curr, stmt) return curr 9985 { - 9986 81 7/subop/compare %esi 0/imm32 - 9987 75/jump-if-!= break/disp8 - 9988 $mu-stmt-matches-primitive?:stmt-inout-is-null: - 9989 { - 9990 81 7/subop/compare %edi 0/imm32 - 9991 75/jump-if-!= break/disp8 - 9992 # - 9993 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 - 9994 } - 9995 # return false - 9996 b8/copy-to-eax 0/imm32/false - 9997 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 9998 } - 9999 # if (curr2 == 0) return false -10000 { -10001 81 7/subop/compare %edi 0/imm32 -10002 75/jump-if-!= break/disp8 -10003 $mu-stmt-matches-primitive?:prim-inout-is-null: -10004 b8/copy-to-eax 0/imm32/false -10005 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10006 } -10007 # if (curr != curr2) return false -10008 { -10009 (operand-matches-primitive? %esi *edi) # List-value => eax -10010 3d/compare-eax-and 0/imm32/false -10011 75/jump-if-!= break/disp8 -10012 b8/copy-to-eax 0/imm32/false -10013 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10014 } -10015 # curr=curr->next -10016 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -10017 # curr2=curr2->next -10018 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -10019 eb/jump loop/disp8 -10020 } -10021 $mu-stmt-matches-primitive?:check-outputs: -10022 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -10023 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -10024 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -10025 { -10026 # if (curr == 0) return (curr2 == 0) -10027 { -10028 $mu-stmt-matches-primitive?:check-output: -10029 81 7/subop/compare %esi 0/imm32 -10030 75/jump-if-!= break/disp8 -10031 { -10032 81 7/subop/compare %edi 0/imm32 -10033 75/jump-if-!= break/disp8 -10034 # return true -10035 b8/copy-to-eax 1/imm32 -10036 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10037 } -10038 # return false -10039 b8/copy-to-eax 0/imm32 -10040 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10041 } -10042 # if (curr2 == 0) return false -10043 { -10044 81 7/subop/compare %edi 0/imm32 -10045 75/jump-if-!= break/disp8 -10046 b8/copy-to-eax 0/imm32 -10047 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10048 } -10049 # if (curr != curr2) return false -10050 { -10051 (operand-matches-primitive? %esi *edi) # List-value => eax -10052 3d/compare-eax-and 0/imm32/false -10053 75/jump-if-!= break/disp8 -10054 b8/copy-to-eax 0/imm32 -10055 e9/jump $mu-stmt-matches-primitive?:end/disp32 -10056 } -10057 # curr=curr->next -10058 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -10059 # curr2=curr2->next -10060 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -10061 eb/jump loop/disp8 -10062 } -10063 $mu-stmt-matches-primitive?:return-true: -10064 b8/copy-to-eax 1/imm32 -10065 $mu-stmt-matches-primitive?:end: -10066 # . restore registers -10067 5f/pop-to-edi -10068 5e/pop-to-esi -10069 5b/pop-to-ebx -10070 5a/pop-to-edx -10071 59/pop-to-ecx -10072 # . epilogue -10073 89/<- %esp 5/r32/ebp -10074 5d/pop-to-ebp -10075 c3/return -10076 -10077 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean -10078 # . prologue -10079 55/push-ebp -10080 89/<- %ebp 4/r32/esp -10081 # . save registers -10082 51/push-ecx -10083 56/push-esi -10084 57/push-edi -10085 # ecx = s -10086 8b/-> *(ebp+8) 1/r32/ecx -10087 # var var/esi : (handle var) = s->value -10088 8b/-> *ecx 6/r32/esi # Stmt-var-value -10089 # edi = prim-var -10090 8b/-> *(ebp+0xc) 7/r32/edi -10091 $operand-matches-primitive?:check-type: -10092 # if (var->type != prim-var->type) return false -10093 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -10094 3d/compare-eax-and 0/imm32/false -10095 b8/copy-to-eax 0/imm32/false -10096 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 -10097 { -10098 $operand-matches-primitive?:check-register: -10099 # if prim-var is in memory and var is in register but dereference, match -10100 { -10101 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10102 0f 85/jump-if-!= break/disp32 -10103 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -10104 74/jump-if-= break/disp8 -10105 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -10106 74/jump-if-= break/disp8 -10107 e9/jump $operand-matches-primitive?:return-true/disp32 -10108 } -10109 # if prim-var is in register and var is in register but dereference, no match -10110 { -10111 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10112 0f 84/jump-if-= break/disp32 -10113 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -10114 0f 84/jump-if-= break/disp32 -10115 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -10116 74/jump-if-= break/disp8 -10117 e9/jump $operand-matches-primitive?:return-false/disp32 -10118 } -10119 # return false if var->register doesn't match prim-var->register -10120 { -10121 # if register addresses are equal, it's a match -10122 8b/-> *(esi+0x10) 0/r32/eax # Var-register -10123 39/compare *(edi+0x10) 0/r32/eax # Var-register -10124 74/jump-if-= break/disp8 -10125 # if either address is 0, return false -10126 3d/compare-eax-and 0/imm32 -10127 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -10128 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -10129 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -10130 # if prim-var->register is wildcard, it's a match -10131 (string-equal? *(edi+0x10) Any-register) # Var-register => eax -10132 3d/compare-eax-and 0/imm32/false -10133 75/jump-if-!= break/disp8 -10134 # if string contents aren't equal, return false -10135 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax -10136 3d/compare-eax-and 0/imm32/false -10137 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -10138 } -10139 } -10140 $operand-matches-primitive?:return-true: -10141 b8/copy-to-eax 1/imm32/true -10142 eb/jump $operand-matches-primitive?:end/disp8 -10143 $operand-matches-primitive?:return-false: -10144 b8/copy-to-eax 0/imm32/false -10145 $operand-matches-primitive?:end: -10146 # . restore registers -10147 5f/pop-to-edi -10148 5e/pop-to-esi -10149 59/pop-to-ecx -10150 # . epilogue -10151 89/<- %esp 5/r32/ebp -10152 5d/pop-to-ebp -10153 c3/return -10154 -10155 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -10156 # . prologue -10157 55/push-ebp -10158 89/<- %ebp 4/r32/esp -10159 # . save registers -10160 51/push-ecx -10161 # var alit/ecx: boolean = is-literal-type?(a) -10162 (is-simple-mu-type? *(ebp+8) 0) # => eax -10163 89/<- %ecx 0/r32/eax -10164 # var blit/eax: boolean = is-literal-type?(b) -10165 (is-simple-mu-type? *(ebp+0xc) 0) # => eax -10166 # return alit == blit -10167 39/compare %eax 1/r32/ecx -10168 0f 94/set-byte-if-= %al -10169 81 4/subop/and %eax 0xff/imm32 -10170 $subx-type-equal?:end: -10171 # . restore registers -10172 59/pop-to-ecx -10173 # . epilogue -10174 89/<- %esp 5/r32/ebp -10175 5d/pop-to-ebp -10176 c3/return -10177 -10178 is-simple-mu-type?: # a: (handle tree type-id), n: type-id -> result/eax: boolean -10179 # . prologue -10180 55/push-ebp -10181 89/<- %ebp 4/r32/esp -10182 # . save registers -10183 51/push-ecx -10184 # ecx = n -10185 8b/-> *(ebp+0xc) 1/r32/ecx -10186 # return (a->value == n) -10187 8b/-> *(ebp+8) 0/r32/eax -10188 39/compare *eax 1/r32/ecx # Atom-type -10189 0f 94/set-byte-if-= %al -10190 81 4/subop/and %eax 0xff/imm32 -10191 $is-simple-mu-type?:end: -10192 # . restore registers -10193 59/pop-to-ecx -10194 # . epilogue -10195 89/<- %esp 5/r32/ebp -10196 5d/pop-to-ebp -10197 c3/return -10198 -10199 test-emit-subx-stmt-primitive: -10200 # Primitive operation on a variable on the stack. -10201 # increment foo -10202 # => -10203 # ff 0/subop/increment *(ebp-8) -10204 # -10205 # There's a variable on the var stack as follows: -10206 # name: 'foo' -10207 # type: int -10208 # stack-offset: -8 -10209 # -10210 # There's a primitive with this info: -10211 # name: 'increment' -10212 # inouts: int/mem -10213 # value: 'ff 0/subop/increment' -10214 # -10215 # There's nothing in functions. -10216 # -10217 # . prologue -10218 55/push-ebp -10219 89/<- %ebp 4/r32/esp -10220 # setup -10221 (clear-stream _test-output-stream) -10222 (clear-stream $_test-output-buffered-file->buffer) -10223 # var type/ecx: (handle tree type-id) = int -10224 68/push 0/imm32/right/null -10225 68/push 1/imm32/left/int -10226 89/<- %ecx 4/r32/esp -10227 # var var-foo/ecx: var -10228 68/push 0/imm32/no-register -10229 68/push -8/imm32/stack-offset -10230 68/push 1/imm32/block-depth -10231 51/push-ecx -10232 68/push "foo"/imm32 -10233 89/<- %ecx 4/r32/esp -10234 # var operand/ebx: (handle stmt-var) -10235 68/push 0/imm32/is-deref:false -10236 68/push 0/imm32/next -10237 51/push-ecx/var-foo -10238 89/<- %ebx 4/r32/esp -10239 # var stmt/esi: statement -10240 68/push 0/imm32/next -10241 68/push 0/imm32/outputs -10242 53/push-ebx/operands -10243 68/push "increment"/imm32/operation -10244 68/push 1/imm32 -10245 89/<- %esi 4/r32/esp -10246 # var primitives/ebx: primitive -10247 68/push 0/imm32/next -10248 68/push 0/imm32/output-is-write-only -10249 68/push 0/imm32/no-disp32 -10250 68/push 0/imm32/no-imm32 -10251 68/push 0/imm32/no-r32 -10252 68/push 1/imm32/rm32-is-first-inout -10253 68/push "ff 0/subop/increment"/imm32/subx-name -10254 68/push 0/imm32/outputs -10255 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -10256 68/push "increment"/imm32/name -10257 89/<- %ebx 4/r32/esp -10258 # convert -10259 c7 0/subop/copy *Curr-block-depth 0/imm32 -10260 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10261 (flush _test-output-buffered-file) -10262 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10268 # check output -10269 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") -10270 # . epilogue -10271 89/<- %esp 5/r32/ebp -10272 5d/pop-to-ebp -10273 c3/return -10274 -10275 test-emit-subx-stmt-primitive-register: -10276 # Primitive operation on a variable in a register. -10277 # foo <- increment -10278 # => -10279 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10280 # -10281 # There's a variable on the var stack as follows: -10282 # name: 'foo' -10283 # type: int -10284 # register: 'eax' -10285 # -10286 # There's a primitive with this info: -10287 # name: 'increment' -10288 # out: int/reg -10289 # value: 'ff 0/subop/increment' + 9986 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax + 9987 3d/compare-eax-and 0/imm32/false + 9988 74/jump-if-= break/disp8 + 9989 89/<- %eax 1/r32/ecx + 9990 eb/jump $find-matching-primitive:end/disp8 + 9991 } + 9992 $find-matching-primitive:next-primitive: + 9993 # curr = curr->next + 9994 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next + 9995 e9/jump loop/disp32 + 9996 } + 9997 # return null + 9998 b8/copy-to-eax 0/imm32 + 9999 $find-matching-primitive:end: +10000 # . restore registers +10001 59/pop-to-ecx +10002 # . epilogue +10003 89/<- %esp 5/r32/ebp +10004 5d/pop-to-ebp +10005 c3/return +10006 +10007 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean +10008 # . prologue +10009 55/push-ebp +10010 89/<- %ebp 4/r32/esp +10011 # . save registers +10012 51/push-ecx +10013 # return function->name == stmt->operation +10014 8b/-> *(ebp+8) 1/r32/ecx +10015 8b/-> *(ebp+0xc) 0/r32/eax +10016 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +10017 $mu-stmt-matches-function?:end: +10018 # . restore registers +10019 59/pop-to-ecx +10020 # . epilogue +10021 89/<- %esp 5/r32/ebp +10022 5d/pop-to-ebp +10023 c3/return +10024 +10025 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean +10026 # A mu stmt matches a primitive if the name matches, all the inout vars +10027 # match, and all the output vars match. +10028 # Vars match if types match and registers match. +10029 # In addition, a stmt output matches a primitive's output if types match +10030 # and the primitive has a wildcard register. +10031 # . prologue +10032 55/push-ebp +10033 89/<- %ebp 4/r32/esp +10034 # . save registers +10035 51/push-ecx +10036 52/push-edx +10037 53/push-ebx +10038 56/push-esi +10039 57/push-edi +10040 # ecx = stmt +10041 8b/-> *(ebp+8) 1/r32/ecx +10042 # edx = primitive +10043 8b/-> *(ebp+0xc) 2/r32/edx +10044 { +10045 $mu-stmt-matches-primitive?:check-name: +10046 # if (primitive->name != stmt->operation) return false +10047 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +10048 3d/compare-eax-and 0/imm32/false +10049 75/jump-if-!= break/disp8 +10050 b8/copy-to-eax 0/imm32 +10051 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10052 } +10053 $mu-stmt-matches-primitive?:check-inouts: +10054 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +10055 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts +10056 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +10057 { +10058 # if (curr == 0 && curr2 == 0) move on to check outputs +10059 { +10060 81 7/subop/compare %esi 0/imm32 +10061 75/jump-if-!= break/disp8 +10062 $mu-stmt-matches-primitive?:stmt-inout-is-null: +10063 { +10064 81 7/subop/compare %edi 0/imm32 +10065 75/jump-if-!= break/disp8 +10066 # +10067 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +10068 } +10069 # return false +10070 b8/copy-to-eax 0/imm32/false +10071 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10072 } +10073 # if (curr2 == 0) return false +10074 { +10075 81 7/subop/compare %edi 0/imm32 +10076 75/jump-if-!= break/disp8 +10077 $mu-stmt-matches-primitive?:prim-inout-is-null: +10078 b8/copy-to-eax 0/imm32/false +10079 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10080 } +10081 # if (curr != curr2) return false +10082 { +10083 (operand-matches-primitive? %esi *edi) # List-value => eax +10084 3d/compare-eax-and 0/imm32/false +10085 75/jump-if-!= break/disp8 +10086 b8/copy-to-eax 0/imm32/false +10087 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10088 } +10089 # curr=curr->next +10090 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +10091 # curr2=curr2->next +10092 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +10093 eb/jump loop/disp8 +10094 } +10095 $mu-stmt-matches-primitive?:check-outputs: +10096 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +10097 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +10098 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +10099 { +10100 # if (curr == 0) return (curr2 == 0) +10101 { +10102 $mu-stmt-matches-primitive?:check-output: +10103 81 7/subop/compare %esi 0/imm32 +10104 75/jump-if-!= break/disp8 +10105 { +10106 81 7/subop/compare %edi 0/imm32 +10107 75/jump-if-!= break/disp8 +10108 # return true +10109 b8/copy-to-eax 1/imm32 +10110 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10111 } +10112 # return false +10113 b8/copy-to-eax 0/imm32 +10114 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10115 } +10116 # if (curr2 == 0) return false +10117 { +10118 81 7/subop/compare %edi 0/imm32 +10119 75/jump-if-!= break/disp8 +10120 b8/copy-to-eax 0/imm32 +10121 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10122 } +10123 # if (curr != curr2) return false +10124 { +10125 (operand-matches-primitive? %esi *edi) # List-value => eax +10126 3d/compare-eax-and 0/imm32/false +10127 75/jump-if-!= break/disp8 +10128 b8/copy-to-eax 0/imm32 +10129 e9/jump $mu-stmt-matches-primitive?:end/disp32 +10130 } +10131 # curr=curr->next +10132 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +10133 # curr2=curr2->next +10134 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +10135 eb/jump loop/disp8 +10136 } +10137 $mu-stmt-matches-primitive?:return-true: +10138 b8/copy-to-eax 1/imm32 +10139 $mu-stmt-matches-primitive?:end: +10140 # . restore registers +10141 5f/pop-to-edi +10142 5e/pop-to-esi +10143 5b/pop-to-ebx +10144 5a/pop-to-edx +10145 59/pop-to-ecx +10146 # . epilogue +10147 89/<- %esp 5/r32/ebp +10148 5d/pop-to-ebp +10149 c3/return +10150 +10151 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean +10152 # . prologue +10153 55/push-ebp +10154 89/<- %ebp 4/r32/esp +10155 # . save registers +10156 51/push-ecx +10157 56/push-esi +10158 57/push-edi +10159 # ecx = s +10160 8b/-> *(ebp+8) 1/r32/ecx +10161 # var var/esi : (handle var) = s->value +10162 8b/-> *ecx 6/r32/esi # Stmt-var-value +10163 # edi = prim-var +10164 8b/-> *(ebp+0xc) 7/r32/edi +10165 $operand-matches-primitive?:check-type: +10166 # if (var->type != prim-var->type) return false +10167 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +10168 3d/compare-eax-and 0/imm32/false +10169 b8/copy-to-eax 0/imm32/false +10170 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 +10171 { +10172 $operand-matches-primitive?:check-register: +10173 # if prim-var is in memory and var is in register but dereference, match +10174 { +10175 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10176 0f 85/jump-if-!= break/disp32 +10177 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10178 74/jump-if-= break/disp8 +10179 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10180 74/jump-if-= break/disp8 +10181 e9/jump $operand-matches-primitive?:return-true/disp32 +10182 } +10183 # if prim-var is in register and var is in register but dereference, no match +10184 { +10185 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10186 0f 84/jump-if-= break/disp32 +10187 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +10188 0f 84/jump-if-= break/disp32 +10189 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +10190 74/jump-if-= break/disp8 +10191 e9/jump $operand-matches-primitive?:return-false/disp32 +10192 } +10193 # return false if var->register doesn't match prim-var->register +10194 { +10195 # if register addresses are equal, it's a match +10196 8b/-> *(esi+0x10) 0/r32/eax # Var-register +10197 39/compare *(edi+0x10) 0/r32/eax # Var-register +10198 74/jump-if-= break/disp8 +10199 # if either address is 0, return false +10200 3d/compare-eax-and 0/imm32 +10201 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +10202 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +10203 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +10204 # if prim-var->register is wildcard, it's a match +10205 (string-equal? *(edi+0x10) Any-register) # Var-register => eax +10206 3d/compare-eax-and 0/imm32/false +10207 75/jump-if-!= break/disp8 +10208 # if string contents aren't equal, return false +10209 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax +10210 3d/compare-eax-and 0/imm32/false +10211 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +10212 } +10213 } +10214 $operand-matches-primitive?:return-true: +10215 b8/copy-to-eax 1/imm32/true +10216 eb/jump $operand-matches-primitive?:end/disp8 +10217 $operand-matches-primitive?:return-false: +10218 b8/copy-to-eax 0/imm32/false +10219 $operand-matches-primitive?:end: +10220 # . restore registers +10221 5f/pop-to-edi +10222 5e/pop-to-esi +10223 59/pop-to-ecx +10224 # . epilogue +10225 89/<- %esp 5/r32/ebp +10226 5d/pop-to-ebp +10227 c3/return +10228 +10229 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +10230 # . prologue +10231 55/push-ebp +10232 89/<- %ebp 4/r32/esp +10233 # . save registers +10234 51/push-ecx +10235 # var alit/ecx: boolean = is-literal-type?(a) +10236 (is-simple-mu-type? *(ebp+8) 0) # => eax +10237 89/<- %ecx 0/r32/eax +10238 # var blit/eax: boolean = is-literal-type?(b) +10239 (is-simple-mu-type? *(ebp+0xc) 0) # => eax +10240 # return alit == blit +10241 39/compare %eax 1/r32/ecx +10242 0f 94/set-byte-if-= %al +10243 81 4/subop/and %eax 0xff/imm32 +10244 $subx-type-equal?:end: +10245 # . restore registers +10246 59/pop-to-ecx +10247 # . epilogue +10248 89/<- %esp 5/r32/ebp +10249 5d/pop-to-ebp +10250 c3/return +10251 +10252 is-simple-mu-type?: # a: (handle tree type-id), n: type-id -> result/eax: boolean +10253 # . prologue +10254 55/push-ebp +10255 89/<- %ebp 4/r32/esp +10256 # . save registers +10257 51/push-ecx +10258 # ecx = n +10259 8b/-> *(ebp+0xc) 1/r32/ecx +10260 # return (a->value == n) +10261 8b/-> *(ebp+8) 0/r32/eax +10262 39/compare *eax 1/r32/ecx # Atom-type +10263 0f 94/set-byte-if-= %al +10264 81 4/subop/and %eax 0xff/imm32 +10265 $is-simple-mu-type?:end: +10266 # . restore registers +10267 59/pop-to-ecx +10268 # . epilogue +10269 89/<- %esp 5/r32/ebp +10270 5d/pop-to-ebp +10271 c3/return +10272 +10273 test-emit-subx-stmt-primitive: +10274 # Primitive operation on a variable on the stack. +10275 # increment foo +10276 # => +10277 # ff 0/subop/increment *(ebp-8) +10278 # +10279 # There's a variable on the var stack as follows: +10280 # name: 'foo' +10281 # type: int +10282 # stack-offset: -8 +10283 # +10284 # There's a primitive with this info: +10285 # name: 'increment' +10286 # inouts: int/mem +10287 # value: 'ff 0/subop/increment' +10288 # +10289 # There's nothing in functions. 10290 # -10291 # There's nothing in functions. -10292 # -10293 # . prologue -10294 55/push-ebp -10295 89/<- %ebp 4/r32/esp -10296 # setup -10297 (clear-stream _test-output-stream) -10298 (clear-stream $_test-output-buffered-file->buffer) -10299 # var type/ecx: (handle tree type-id) = int -10300 68/push 0/imm32/right/null -10301 68/push 1/imm32/left/int -10302 89/<- %ecx 4/r32/esp -10303 # var var-foo/ecx: var in eax -10304 68/push "eax"/imm32/register -10305 68/push 0/imm32/no-stack-offset -10306 68/push 1/imm32/block-depth -10307 51/push-ecx -10308 68/push "foo"/imm32 -10309 89/<- %ecx 4/r32/esp -10310 # var operand/ebx: (handle stmt-var) -10311 68/push 0/imm32/is-deref:false -10312 68/push 0/imm32/next -10313 51/push-ecx/var-foo -10314 89/<- %ebx 4/r32/esp -10315 # var stmt/esi: statement -10316 68/push 0/imm32/next -10317 53/push-ebx/outputs -10318 68/push 0/imm32/inouts -10319 68/push "increment"/imm32/operation -10320 68/push 1/imm32 -10321 89/<- %esi 4/r32/esp -10322 # var formal-var/ebx: var in any register -10323 68/push Any-register/imm32 -10324 68/push 0/imm32/no-stack-offset -10325 68/push 1/imm32/block-depth -10326 ff 6/subop/push *(ecx+4) # Var-type -10327 68/push "dummy"/imm32 -10328 89/<- %ebx 4/r32/esp -10329 # var operand/ebx: (handle stmt-var) -10330 68/push 0/imm32/is-deref:false -10331 68/push 0/imm32/next -10332 53/push-ebx/formal-var -10333 89/<- %ebx 4/r32/esp -10334 # var primitives/ebx: primitive -10335 68/push 0/imm32/next -10336 68/push 0/imm32/output-is-write-only -10337 68/push 0/imm32/no-disp32 -10338 68/push 0/imm32/no-imm32 -10339 68/push 0/imm32/no-r32 -10340 68/push 3/imm32/rm32-in-first-output -10341 68/push "ff 0/subop/increment"/imm32/subx-name -10342 53/push-ebx/outputs -10343 68/push 0/imm32/inouts -10344 68/push "increment"/imm32/name -10345 89/<- %ebx 4/r32/esp -10346 # convert -10347 c7 0/subop/copy *Curr-block-depth 0/imm32 -10348 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10349 (flush _test-output-buffered-file) -10350 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10356 # check output -10357 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") -10358 # . epilogue -10359 89/<- %esp 5/r32/ebp -10360 5d/pop-to-ebp -10361 c3/return -10362 -10363 test-emit-subx-stmt-select-primitive: -10364 # Select the right primitive between overloads. -10365 # foo <- increment -10366 # => -10367 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10368 # -10369 # There's a variable on the var stack as follows: -10370 # name: 'foo' -10371 # type: int -10372 # register: 'eax' -10373 # -10374 # There's two primitives, as follows: -10375 # - name: 'increment' -10376 # out: int/reg -10377 # value: 'ff 0/subop/increment' -10378 # - name: 'increment' -10379 # inout: int/mem -10380 # value: 'ff 0/subop/increment' -10381 # -10382 # There's nothing in functions. -10383 # -10384 # . prologue -10385 55/push-ebp -10386 89/<- %ebp 4/r32/esp -10387 # setup -10388 (clear-stream _test-output-stream) -10389 (clear-stream $_test-output-buffered-file->buffer) -10390 # var type/ecx: (handle tree type-id) = int -10391 68/push 0/imm32/right/null -10392 68/push 1/imm32/left/int -10393 89/<- %ecx 4/r32/esp -10394 # var var-foo/ecx: var in eax -10395 68/push "eax"/imm32/register -10396 68/push 0/imm32/no-stack-offset -10397 68/push 1/imm32/block-depth -10398 51/push-ecx -10399 68/push "foo"/imm32 -10400 89/<- %ecx 4/r32/esp -10401 # var real-outputs/edi: (handle stmt-var) -10402 68/push 0/imm32/is-deref:false -10403 68/push 0/imm32/next -10404 51/push-ecx/var-foo -10405 89/<- %edi 4/r32/esp -10406 # var stmt/esi: statement -10407 68/push 0/imm32/next -10408 57/push-edi/outputs -10409 68/push 0/imm32/inouts -10410 68/push "increment"/imm32/operation -10411 68/push 1/imm32 -10412 89/<- %esi 4/r32/esp -10413 # var formal-var/ebx: var in any register -10414 68/push Any-register/imm32 -10415 68/push 0/imm32/no-stack-offset -10416 68/push 1/imm32/block-depth -10417 ff 6/subop/push *(ecx+4) # Var-type -10418 68/push "dummy"/imm32 +10291 # . prologue +10292 55/push-ebp +10293 89/<- %ebp 4/r32/esp +10294 # setup +10295 (clear-stream _test-output-stream) +10296 (clear-stream $_test-output-buffered-file->buffer) +10297 # var type/ecx: (handle tree type-id) = int +10298 68/push 0/imm32/right/null +10299 68/push 1/imm32/left/int +10300 89/<- %ecx 4/r32/esp +10301 # var var-foo/ecx: var +10302 68/push 0/imm32/no-register +10303 68/push -8/imm32/stack-offset +10304 68/push 1/imm32/block-depth +10305 51/push-ecx +10306 68/push "foo"/imm32 +10307 89/<- %ecx 4/r32/esp +10308 # var operand/ebx: (handle stmt-var) +10309 68/push 0/imm32/is-deref:false +10310 68/push 0/imm32/next +10311 51/push-ecx/var-foo +10312 89/<- %ebx 4/r32/esp +10313 # var stmt/esi: statement +10314 68/push 0/imm32/next +10315 68/push 0/imm32/outputs +10316 53/push-ebx/operands +10317 68/push "increment"/imm32/operation +10318 68/push 1/imm32 +10319 89/<- %esi 4/r32/esp +10320 # var primitives/ebx: primitive +10321 68/push 0/imm32/next +10322 68/push 0/imm32/output-is-write-only +10323 68/push 0/imm32/no-disp32 +10324 68/push 0/imm32/no-imm32 +10325 68/push 0/imm32/no-r32 +10326 68/push 1/imm32/rm32-is-first-inout +10327 68/push "ff 0/subop/increment"/imm32/subx-name +10328 68/push 0/imm32/outputs +10329 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +10330 68/push "increment"/imm32/name +10331 89/<- %ebx 4/r32/esp +10332 # convert +10333 c7 0/subop/copy *Curr-block-depth 0/imm32 +10334 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +10335 (flush _test-output-buffered-file) +10336 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10342 # check output +10343 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") +10344 # . epilogue +10345 89/<- %esp 5/r32/ebp +10346 5d/pop-to-ebp +10347 c3/return +10348 +10349 test-emit-subx-stmt-primitive-register: +10350 # Primitive operation on a variable in a register. +10351 # foo <- increment +10352 # => +10353 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10354 # +10355 # There's a variable on the var stack as follows: +10356 # name: 'foo' +10357 # type: int +10358 # register: 'eax' +10359 # +10360 # There's a primitive with this info: +10361 # name: 'increment' +10362 # out: int/reg +10363 # value: 'ff 0/subop/increment' +10364 # +10365 # There's nothing in functions. +10366 # +10367 # . prologue +10368 55/push-ebp +10369 89/<- %ebp 4/r32/esp +10370 # setup +10371 (clear-stream _test-output-stream) +10372 (clear-stream $_test-output-buffered-file->buffer) +10373 # var type/ecx: (handle tree type-id) = int +10374 68/push 0/imm32/right/null +10375 68/push 1/imm32/left/int +10376 89/<- %ecx 4/r32/esp +10377 # var var-foo/ecx: var in eax +10378 68/push "eax"/imm32/register +10379 68/push 0/imm32/no-stack-offset +10380 68/push 1/imm32/block-depth +10381 51/push-ecx +10382 68/push "foo"/imm32 +10383 89/<- %ecx 4/r32/esp +10384 # var operand/ebx: (handle stmt-var) +10385 68/push 0/imm32/is-deref:false +10386 68/push 0/imm32/next +10387 51/push-ecx/var-foo +10388 89/<- %ebx 4/r32/esp +10389 # var stmt/esi: statement +10390 68/push 0/imm32/next +10391 53/push-ebx/outputs +10392 68/push 0/imm32/inouts +10393 68/push "increment"/imm32/operation +10394 68/push 1/imm32 +10395 89/<- %esi 4/r32/esp +10396 # var formal-var/ebx: var in any register +10397 68/push Any-register/imm32 +10398 68/push 0/imm32/no-stack-offset +10399 68/push 1/imm32/block-depth +10400 ff 6/subop/push *(ecx+4) # Var-type +10401 68/push "dummy"/imm32 +10402 89/<- %ebx 4/r32/esp +10403 # var operand/ebx: (handle stmt-var) +10404 68/push 0/imm32/is-deref:false +10405 68/push 0/imm32/next +10406 53/push-ebx/formal-var +10407 89/<- %ebx 4/r32/esp +10408 # var primitives/ebx: primitive +10409 68/push 0/imm32/next +10410 68/push 0/imm32/output-is-write-only +10411 68/push 0/imm32/no-disp32 +10412 68/push 0/imm32/no-imm32 +10413 68/push 0/imm32/no-r32 +10414 68/push 3/imm32/rm32-in-first-output +10415 68/push "ff 0/subop/increment"/imm32/subx-name +10416 53/push-ebx/outputs +10417 68/push 0/imm32/inouts +10418 68/push "increment"/imm32/name 10419 89/<- %ebx 4/r32/esp -10420 # var formal-outputs/ebx: (handle stmt-var) -10421 68/push 0/imm32/is-deref:false -10422 68/push 0/imm32/next -10423 53/push-ebx/formal-var -10424 89/<- %ebx 4/r32/esp -10425 # var primitive1/ebx: primitive -10426 68/push 0/imm32/next -10427 68/push 0/imm32/output-is-write-only -10428 68/push 0/imm32/no-disp32 -10429 68/push 0/imm32/no-imm32 -10430 68/push 0/imm32/no-r32 -10431 68/push 3/imm32/rm32-in-first-output -10432 68/push "ff 0/subop/increment"/imm32/subx-name -10433 53/push-ebx/outputs/formal-outputs -10434 68/push 0/imm32/inouts -10435 68/push "increment"/imm32/name -10436 89/<- %ebx 4/r32/esp -10437 # var primitives/ebx: primitive -10438 53/push-ebx/next -10439 68/push 0/imm32/output-is-write-only -10440 68/push 0/imm32/no-disp32 -10441 68/push 0/imm32/no-imm32 -10442 68/push 0/imm32/no-r32 -10443 68/push 1/imm32/rm32-is-first-inout -10444 68/push "ff 0/subop/increment"/imm32/subx-name -10445 68/push 0/imm32/outputs -10446 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -10447 68/push "increment"/imm32/name -10448 89/<- %ebx 4/r32/esp -10449 # convert -10450 c7 0/subop/copy *Curr-block-depth 0/imm32 -10451 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10452 (flush _test-output-buffered-file) -10453 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10459 # check output -10460 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") -10461 # . epilogue -10462 89/<- %esp 5/r32/ebp -10463 5d/pop-to-ebp -10464 c3/return -10465 -10466 test-emit-subx-stmt-select-primitive-2: -10467 # Select the right primitive between overloads. -10468 # foo <- increment -10469 # => -10470 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10471 # -10472 # There's a variable on the var stack as follows: -10473 # name: 'foo' -10474 # type: int -10475 # register: 'eax' -10476 # -10477 # There's two primitives, as follows: -10478 # - name: 'increment' -10479 # out: int/reg -10480 # value: 'ff 0/subop/increment' -10481 # - name: 'increment' -10482 # inout: int/mem -10483 # value: 'ff 0/subop/increment' -10484 # -10485 # There's nothing in functions. -10486 # -10487 # . prologue -10488 55/push-ebp -10489 89/<- %ebp 4/r32/esp -10490 # setup -10491 (clear-stream _test-output-stream) -10492 (clear-stream $_test-output-buffered-file->buffer) -10493 # var type/ecx: (handle tree type-id) = int -10494 68/push 0/imm32/right/null -10495 68/push 1/imm32/left/int -10496 89/<- %ecx 4/r32/esp -10497 # var var-foo/ecx: var in eax -10498 68/push "eax"/imm32/register -10499 68/push 0/imm32/no-stack-offset -10500 68/push 1/imm32/block-depth -10501 51/push-ecx -10502 68/push "foo"/imm32 -10503 89/<- %ecx 4/r32/esp -10504 # var inouts/edi: (handle stmt-var) -10505 68/push 0/imm32/is-deref:false -10506 68/push 0/imm32/next -10507 51/push-ecx/var-foo -10508 89/<- %edi 4/r32/esp -10509 # var stmt/esi: statement -10510 68/push 0/imm32/next -10511 68/push 0/imm32/outputs -10512 57/push-edi/inouts -10513 68/push "increment"/imm32/operation -10514 68/push 1/imm32 -10515 89/<- %esi 4/r32/esp -10516 # var formal-var/ebx: var in any register -10517 68/push Any-register/imm32 -10518 68/push 0/imm32/no-stack-offset -10519 68/push 1/imm32/block-depth -10520 ff 6/subop/push *(ecx+4) # Var-type -10521 68/push "dummy"/imm32 +10420 # convert +10421 c7 0/subop/copy *Curr-block-depth 0/imm32 +10422 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +10423 (flush _test-output-buffered-file) +10424 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10430 # check output +10431 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") +10432 # . epilogue +10433 89/<- %esp 5/r32/ebp +10434 5d/pop-to-ebp +10435 c3/return +10436 +10437 test-emit-subx-stmt-select-primitive: +10438 # Select the right primitive between overloads. +10439 # foo <- increment +10440 # => +10441 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10442 # +10443 # There's a variable on the var stack as follows: +10444 # name: 'foo' +10445 # type: int +10446 # register: 'eax' +10447 # +10448 # There's two primitives, as follows: +10449 # - name: 'increment' +10450 # out: int/reg +10451 # value: 'ff 0/subop/increment' +10452 # - name: 'increment' +10453 # inout: int/mem +10454 # value: 'ff 0/subop/increment' +10455 # +10456 # There's nothing in functions. +10457 # +10458 # . prologue +10459 55/push-ebp +10460 89/<- %ebp 4/r32/esp +10461 # setup +10462 (clear-stream _test-output-stream) +10463 (clear-stream $_test-output-buffered-file->buffer) +10464 # var type/ecx: (handle tree type-id) = int +10465 68/push 0/imm32/right/null +10466 68/push 1/imm32/left/int +10467 89/<- %ecx 4/r32/esp +10468 # var var-foo/ecx: var in eax +10469 68/push "eax"/imm32/register +10470 68/push 0/imm32/no-stack-offset +10471 68/push 1/imm32/block-depth +10472 51/push-ecx +10473 68/push "foo"/imm32 +10474 89/<- %ecx 4/r32/esp +10475 # var real-outputs/edi: (handle stmt-var) +10476 68/push 0/imm32/is-deref:false +10477 68/push 0/imm32/next +10478 51/push-ecx/var-foo +10479 89/<- %edi 4/r32/esp +10480 # var stmt/esi: statement +10481 68/push 0/imm32/next +10482 57/push-edi/outputs +10483 68/push 0/imm32/inouts +10484 68/push "increment"/imm32/operation +10485 68/push 1/imm32 +10486 89/<- %esi 4/r32/esp +10487 # var formal-var/ebx: var in any register +10488 68/push Any-register/imm32 +10489 68/push 0/imm32/no-stack-offset +10490 68/push 1/imm32/block-depth +10491 ff 6/subop/push *(ecx+4) # Var-type +10492 68/push "dummy"/imm32 +10493 89/<- %ebx 4/r32/esp +10494 # var formal-outputs/ebx: (handle stmt-var) +10495 68/push 0/imm32/is-deref:false +10496 68/push 0/imm32/next +10497 53/push-ebx/formal-var +10498 89/<- %ebx 4/r32/esp +10499 # var primitive1/ebx: primitive +10500 68/push 0/imm32/next +10501 68/push 0/imm32/output-is-write-only +10502 68/push 0/imm32/no-disp32 +10503 68/push 0/imm32/no-imm32 +10504 68/push 0/imm32/no-r32 +10505 68/push 3/imm32/rm32-in-first-output +10506 68/push "ff 0/subop/increment"/imm32/subx-name +10507 53/push-ebx/outputs/formal-outputs +10508 68/push 0/imm32/inouts +10509 68/push "increment"/imm32/name +10510 89/<- %ebx 4/r32/esp +10511 # var primitives/ebx: primitive +10512 53/push-ebx/next +10513 68/push 0/imm32/output-is-write-only +10514 68/push 0/imm32/no-disp32 +10515 68/push 0/imm32/no-imm32 +10516 68/push 0/imm32/no-r32 +10517 68/push 1/imm32/rm32-is-first-inout +10518 68/push "ff 0/subop/increment"/imm32/subx-name +10519 68/push 0/imm32/outputs +10520 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +10521 68/push "increment"/imm32/name 10522 89/<- %ebx 4/r32/esp -10523 # var operand/ebx: (handle stmt-var) -10524 68/push 0/imm32/is-deref:false -10525 68/push 0/imm32/next -10526 53/push-ebx/formal-var -10527 89/<- %ebx 4/r32/esp -10528 # var primitive1/ebx: primitive -10529 68/push 0/imm32/next -10530 68/push 0/imm32/output-is-write-only -10531 68/push 0/imm32/no-disp32 -10532 68/push 0/imm32/no-imm32 -10533 68/push 0/imm32/no-r32 -10534 68/push 3/imm32/rm32-in-first-output -10535 68/push "ff 0/subop/increment"/imm32/subx-name -10536 53/push-ebx/outputs/formal-outputs -10537 68/push 0/imm32/inouts -10538 68/push "increment"/imm32/name -10539 89/<- %ebx 4/r32/esp -10540 # var primitives/ebx: primitive -10541 53/push-ebx/next -10542 68/push 0/imm32/output-is-write-only -10543 68/push 0/imm32/no-disp32 -10544 68/push 0/imm32/no-imm32 -10545 68/push 0/imm32/no-r32 -10546 68/push 1/imm32/rm32-is-first-inout -10547 68/push "ff 0/subop/increment"/imm32/subx-name -10548 68/push 0/imm32/outputs -10549 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -10550 68/push "increment"/imm32/name -10551 89/<- %ebx 4/r32/esp -10552 # convert -10553 c7 0/subop/copy *Curr-block-depth 0/imm32 -10554 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) -10555 (flush _test-output-buffered-file) -10556 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10562 # check output -10563 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") -10564 # . epilogue -10565 89/<- %esp 5/r32/ebp -10566 5d/pop-to-ebp -10567 c3/return -10568 -10569 test-increment-register: -10570 # Select the right register between overloads. -10571 # foo <- increment -10572 # => -10573 # 50/increment-eax -10574 # -10575 # There's a variable on the var stack as follows: -10576 # name: 'foo' -10577 # type: int -10578 # register: 'eax' -10579 # -10580 # Primitives are the global definitions. -10581 # -10582 # There are no functions defined. -10583 # -10584 # . prologue -10585 55/push-ebp -10586 89/<- %ebp 4/r32/esp -10587 # setup -10588 (clear-stream _test-output-stream) -10589 (clear-stream $_test-output-buffered-file->buffer) -10590 # var type/ecx: (handle tree type-id) = int -10591 68/push 0/imm32/right/null -10592 68/push 1/imm32/left/int -10593 89/<- %ecx 4/r32/esp -10594 # var var-foo/ecx: var in eax -10595 68/push "eax"/imm32/register -10596 68/push 0/imm32/no-stack-offset -10597 68/push 1/imm32/block-depth -10598 51/push-ecx -10599 68/push "foo"/imm32 -10600 89/<- %ecx 4/r32/esp -10601 # var real-outputs/edi: (handle stmt-var) -10602 68/push 0/imm32/is-deref:false +10523 # convert +10524 c7 0/subop/copy *Curr-block-depth 0/imm32 +10525 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +10526 (flush _test-output-buffered-file) +10527 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10533 # check output +10534 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") +10535 # . epilogue +10536 89/<- %esp 5/r32/ebp +10537 5d/pop-to-ebp +10538 c3/return +10539 +10540 test-emit-subx-stmt-select-primitive-2: +10541 # Select the right primitive between overloads. +10542 # foo <- increment +10543 # => +10544 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10545 # +10546 # There's a variable on the var stack as follows: +10547 # name: 'foo' +10548 # type: int +10549 # register: 'eax' +10550 # +10551 # There's two primitives, as follows: +10552 # - name: 'increment' +10553 # out: int/reg +10554 # value: 'ff 0/subop/increment' +10555 # - name: 'increment' +10556 # inout: int/mem +10557 # value: 'ff 0/subop/increment' +10558 # +10559 # There's nothing in functions. +10560 # +10561 # . prologue +10562 55/push-ebp +10563 89/<- %ebp 4/r32/esp +10564 # setup +10565 (clear-stream _test-output-stream) +10566 (clear-stream $_test-output-buffered-file->buffer) +10567 # var type/ecx: (handle tree type-id) = int +10568 68/push 0/imm32/right/null +10569 68/push 1/imm32/left/int +10570 89/<- %ecx 4/r32/esp +10571 # var var-foo/ecx: var in eax +10572 68/push "eax"/imm32/register +10573 68/push 0/imm32/no-stack-offset +10574 68/push 1/imm32/block-depth +10575 51/push-ecx +10576 68/push "foo"/imm32 +10577 89/<- %ecx 4/r32/esp +10578 # var inouts/edi: (handle stmt-var) +10579 68/push 0/imm32/is-deref:false +10580 68/push 0/imm32/next +10581 51/push-ecx/var-foo +10582 89/<- %edi 4/r32/esp +10583 # var stmt/esi: statement +10584 68/push 0/imm32/next +10585 68/push 0/imm32/outputs +10586 57/push-edi/inouts +10587 68/push "increment"/imm32/operation +10588 68/push 1/imm32 +10589 89/<- %esi 4/r32/esp +10590 # var formal-var/ebx: var in any register +10591 68/push Any-register/imm32 +10592 68/push 0/imm32/no-stack-offset +10593 68/push 1/imm32/block-depth +10594 ff 6/subop/push *(ecx+4) # Var-type +10595 68/push "dummy"/imm32 +10596 89/<- %ebx 4/r32/esp +10597 # var operand/ebx: (handle stmt-var) +10598 68/push 0/imm32/is-deref:false +10599 68/push 0/imm32/next +10600 53/push-ebx/formal-var +10601 89/<- %ebx 4/r32/esp +10602 # var primitive1/ebx: primitive 10603 68/push 0/imm32/next -10604 51/push-ecx/var-foo -10605 89/<- %edi 4/r32/esp -10606 # var stmt/esi: statement -10607 68/push 0/imm32/next -10608 57/push-edi/outputs -10609 68/push 0/imm32/inouts -10610 68/push "increment"/imm32/operation -10611 68/push 1/imm32/regular-stmt -10612 89/<- %esi 4/r32/esp -10613 # convert -10614 c7 0/subop/copy *Curr-block-depth 0/imm32 -10615 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10616 (flush _test-output-buffered-file) -10617 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10623 # check output -10624 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -10625 # . epilogue -10626 89/<- %esp 5/r32/ebp -10627 5d/pop-to-ebp -10628 c3/return -10629 -10630 test-increment-var: -10631 # Select the right primitive between overloads. -10632 # foo <- increment -10633 # => -10634 # ff 0/subop/increment %eax # sub-optimal, but should suffice -10635 # -10636 # There's a variable on the var stack as follows: -10637 # name: 'foo' -10638 # type: int -10639 # register: 'eax' -10640 # -10641 # Primitives are the global definitions. -10642 # -10643 # There are no functions defined. -10644 # -10645 # . prologue -10646 55/push-ebp -10647 89/<- %ebp 4/r32/esp -10648 # setup -10649 (clear-stream _test-output-stream) -10650 (clear-stream $_test-output-buffered-file->buffer) -10651 # var type/ecx: (handle tree type-id) = int -10652 68/push 0/imm32/right/null -10653 68/push 1/imm32/left/int -10654 89/<- %ecx 4/r32/esp -10655 # var var-foo/ecx: var in eax -10656 68/push "eax"/imm32/register -10657 68/push 0/imm32/no-stack-offset -10658 68/push 1/imm32/block-depth -10659 51/push-ecx -10660 68/push "foo"/imm32 -10661 89/<- %ecx 4/r32/esp -10662 # var inouts/edi: (handle stmt-var) -10663 68/push 0/imm32/is-deref:false -10664 68/push 0/imm32/next -10665 51/push-ecx/var-foo -10666 89/<- %edi 4/r32/esp -10667 # var stmt/esi: statement -10668 68/push 0/imm32/next -10669 57/push-edi/outputs -10670 68/push 0/imm32/inouts -10671 68/push "increment"/imm32/operation -10672 68/push 1/imm32 -10673 89/<- %esi 4/r32/esp -10674 # convert -10675 c7 0/subop/copy *Curr-block-depth 0/imm32 -10676 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10677 (flush _test-output-buffered-file) -10678 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10684 # check output -10685 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") -10686 # . epilogue -10687 89/<- %esp 5/r32/ebp -10688 5d/pop-to-ebp -10689 c3/return -10690 -10691 test-add-reg-to-reg: -10692 # var1/reg <- add var2/reg -10693 # => -10694 # 01/add %var1 var2 -10695 # -10696 # . prologue -10697 55/push-ebp -10698 89/<- %ebp 4/r32/esp -10699 # setup -10700 (clear-stream _test-output-stream) -10701 (clear-stream $_test-output-buffered-file->buffer) -10702 # var type/ecx: (handle tree type-id) = int -10703 68/push 0/imm32/right/null -10704 68/push 1/imm32/left/int -10705 89/<- %ecx 4/r32/esp -10706 # var var-var1/ecx: var in eax -10707 68/push "eax"/imm32/register -10708 68/push 0/imm32/no-stack-offset -10709 68/push 1/imm32/block-depth -10710 51/push-ecx -10711 68/push "var1"/imm32 -10712 89/<- %ecx 4/r32/esp -10713 # var var-var2/edx: var in ecx -10714 68/push "ecx"/imm32/register -10715 68/push 0/imm32/no-stack-offset -10716 68/push 1/imm32/block-depth -10717 ff 6/subop/push *(ecx+4) # Var-type -10718 68/push "var2"/imm32 -10719 89/<- %edx 4/r32/esp -10720 # var inouts/esi: (handle stmt-var) = [var2] -10721 68/push 0/imm32/is-deref:false -10722 68/push 0/imm32/next -10723 52/push-edx/var-var2 -10724 89/<- %esi 4/r32/esp -10725 # var outputs/edi: (handle stmt-var) = [var1, var2] -10726 68/push 0/imm32/is-deref:false -10727 68/push 0/imm32/next -10728 51/push-ecx/var-var1 -10729 89/<- %edi 4/r32/esp -10730 # var stmt/esi: statement -10731 68/push 0/imm32/next -10732 57/push-edi/outputs -10733 56/push-esi/inouts -10734 68/push "add"/imm32/operation -10735 68/push 1/imm32 -10736 89/<- %esi 4/r32/esp -10737 # convert -10738 c7 0/subop/copy *Curr-block-depth 0/imm32 -10739 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10740 (flush _test-output-buffered-file) -10741 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10747 # check output -10748 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -10749 # . epilogue -10750 89/<- %esp 5/r32/ebp -10751 5d/pop-to-ebp -10752 c3/return -10753 -10754 test-add-reg-to-mem: -10755 # add-to var1 var2/reg -10756 # => -10757 # 01/add *(ebp+__) var2 -10758 # -10759 # . prologue -10760 55/push-ebp -10761 89/<- %ebp 4/r32/esp -10762 # setup -10763 (clear-stream _test-output-stream) -10764 (clear-stream $_test-output-buffered-file->buffer) -10765 # var type/ecx: (handle tree type-id) = int -10766 68/push 0/imm32/right/null -10767 68/push 1/imm32/left/int -10768 89/<- %ecx 4/r32/esp -10769 # var var-var1/ecx: var -10770 68/push 0/imm32/no-register -10771 68/push 8/imm32/stack-offset -10772 68/push 1/imm32/block-depth -10773 51/push-ecx -10774 68/push "var1"/imm32 -10775 89/<- %ecx 4/r32/esp -10776 # var var-var2/edx: var in ecx -10777 68/push "ecx"/imm32/register -10778 68/push 0/imm32/no-stack-offset -10779 68/push 1/imm32/block-depth -10780 ff 6/subop/push *(ecx+4) # Var-type -10781 68/push "var2"/imm32 -10782 89/<- %edx 4/r32/esp -10783 # var inouts/esi: (handle stmt-var) = [var2] -10784 68/push 0/imm32/is-deref:false -10785 68/push 0/imm32/next -10786 52/push-edx/var-var2 -10787 89/<- %esi 4/r32/esp -10788 # var inouts = (handle stmt-var) = [var1, var2] -10789 56/push-esi/next -10790 51/push-ecx/var-var1 -10791 89/<- %esi 4/r32/esp -10792 # var stmt/esi: statement -10793 68/push 0/imm32/next -10794 68/push 0/imm32/outputs -10795 56/push-esi/inouts -10796 68/push "add-to"/imm32/operation -10797 68/push 1/imm32 +10604 68/push 0/imm32/output-is-write-only +10605 68/push 0/imm32/no-disp32 +10606 68/push 0/imm32/no-imm32 +10607 68/push 0/imm32/no-r32 +10608 68/push 3/imm32/rm32-in-first-output +10609 68/push "ff 0/subop/increment"/imm32/subx-name +10610 53/push-ebx/outputs/formal-outputs +10611 68/push 0/imm32/inouts +10612 68/push "increment"/imm32/name +10613 89/<- %ebx 4/r32/esp +10614 # var primitives/ebx: primitive +10615 53/push-ebx/next +10616 68/push 0/imm32/output-is-write-only +10617 68/push 0/imm32/no-disp32 +10618 68/push 0/imm32/no-imm32 +10619 68/push 0/imm32/no-r32 +10620 68/push 1/imm32/rm32-is-first-inout +10621 68/push "ff 0/subop/increment"/imm32/subx-name +10622 68/push 0/imm32/outputs +10623 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +10624 68/push "increment"/imm32/name +10625 89/<- %ebx 4/r32/esp +10626 # convert +10627 c7 0/subop/copy *Curr-block-depth 0/imm32 +10628 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) +10629 (flush _test-output-buffered-file) +10630 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10636 # check output +10637 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") +10638 # . epilogue +10639 89/<- %esp 5/r32/ebp +10640 5d/pop-to-ebp +10641 c3/return +10642 +10643 test-increment-register: +10644 # Select the right register between overloads. +10645 # foo <- increment +10646 # => +10647 # 50/increment-eax +10648 # +10649 # There's a variable on the var stack as follows: +10650 # name: 'foo' +10651 # type: int +10652 # register: 'eax' +10653 # +10654 # Primitives are the global definitions. +10655 # +10656 # There are no functions defined. +10657 # +10658 # . prologue +10659 55/push-ebp +10660 89/<- %ebp 4/r32/esp +10661 # setup +10662 (clear-stream _test-output-stream) +10663 (clear-stream $_test-output-buffered-file->buffer) +10664 # var type/ecx: (handle tree type-id) = int +10665 68/push 0/imm32/right/null +10666 68/push 1/imm32/left/int +10667 89/<- %ecx 4/r32/esp +10668 # var var-foo/ecx: var in eax +10669 68/push "eax"/imm32/register +10670 68/push 0/imm32/no-stack-offset +10671 68/push 1/imm32/block-depth +10672 51/push-ecx +10673 68/push "foo"/imm32 +10674 89/<- %ecx 4/r32/esp +10675 # var real-outputs/edi: (handle stmt-var) +10676 68/push 0/imm32/is-deref:false +10677 68/push 0/imm32/next +10678 51/push-ecx/var-foo +10679 89/<- %edi 4/r32/esp +10680 # var stmt/esi: statement +10681 68/push 0/imm32/next +10682 57/push-edi/outputs +10683 68/push 0/imm32/inouts +10684 68/push "increment"/imm32/operation +10685 68/push 1/imm32/regular-stmt +10686 89/<- %esi 4/r32/esp +10687 # convert +10688 c7 0/subop/copy *Curr-block-depth 0/imm32 +10689 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10690 (flush _test-output-buffered-file) +10691 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10697 # check output +10698 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +10699 # . epilogue +10700 89/<- %esp 5/r32/ebp +10701 5d/pop-to-ebp +10702 c3/return +10703 +10704 test-increment-var: +10705 # Select the right primitive between overloads. +10706 # foo <- increment +10707 # => +10708 # ff 0/subop/increment %eax # sub-optimal, but should suffice +10709 # +10710 # There's a variable on the var stack as follows: +10711 # name: 'foo' +10712 # type: int +10713 # register: 'eax' +10714 # +10715 # Primitives are the global definitions. +10716 # +10717 # There are no functions defined. +10718 # +10719 # . prologue +10720 55/push-ebp +10721 89/<- %ebp 4/r32/esp +10722 # setup +10723 (clear-stream _test-output-stream) +10724 (clear-stream $_test-output-buffered-file->buffer) +10725 # var type/ecx: (handle tree type-id) = int +10726 68/push 0/imm32/right/null +10727 68/push 1/imm32/left/int +10728 89/<- %ecx 4/r32/esp +10729 # var var-foo/ecx: var in eax +10730 68/push "eax"/imm32/register +10731 68/push 0/imm32/no-stack-offset +10732 68/push 1/imm32/block-depth +10733 51/push-ecx +10734 68/push "foo"/imm32 +10735 89/<- %ecx 4/r32/esp +10736 # var inouts/edi: (handle stmt-var) +10737 68/push 0/imm32/is-deref:false +10738 68/push 0/imm32/next +10739 51/push-ecx/var-foo +10740 89/<- %edi 4/r32/esp +10741 # var stmt/esi: statement +10742 68/push 0/imm32/next +10743 57/push-edi/outputs +10744 68/push 0/imm32/inouts +10745 68/push "increment"/imm32/operation +10746 68/push 1/imm32 +10747 89/<- %esi 4/r32/esp +10748 # convert +10749 c7 0/subop/copy *Curr-block-depth 0/imm32 +10750 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10751 (flush _test-output-buffered-file) +10752 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10758 # check output +10759 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") +10760 # . epilogue +10761 89/<- %esp 5/r32/ebp +10762 5d/pop-to-ebp +10763 c3/return +10764 +10765 test-add-reg-to-reg: +10766 # var1/reg <- add var2/reg +10767 # => +10768 # 01/add %var1 var2 +10769 # +10770 # . prologue +10771 55/push-ebp +10772 89/<- %ebp 4/r32/esp +10773 # setup +10774 (clear-stream _test-output-stream) +10775 (clear-stream $_test-output-buffered-file->buffer) +10776 # var type/ecx: (handle tree type-id) = int +10777 68/push 0/imm32/right/null +10778 68/push 1/imm32/left/int +10779 89/<- %ecx 4/r32/esp +10780 # var var-var1/ecx: var in eax +10781 68/push "eax"/imm32/register +10782 68/push 0/imm32/no-stack-offset +10783 68/push 1/imm32/block-depth +10784 51/push-ecx +10785 68/push "var1"/imm32 +10786 89/<- %ecx 4/r32/esp +10787 # var var-var2/edx: var in ecx +10788 68/push "ecx"/imm32/register +10789 68/push 0/imm32/no-stack-offset +10790 68/push 1/imm32/block-depth +10791 ff 6/subop/push *(ecx+4) # Var-type +10792 68/push "var2"/imm32 +10793 89/<- %edx 4/r32/esp +10794 # var inouts/esi: (handle stmt-var) = [var2] +10795 68/push 0/imm32/is-deref:false +10796 68/push 0/imm32/next +10797 52/push-edx/var-var2 10798 89/<- %esi 4/r32/esp -10799 # convert -10800 c7 0/subop/copy *Curr-block-depth 0/imm32 -10801 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10802 (flush _test-output-buffered-file) -10803 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10809 # check output -10810 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -10811 # . epilogue -10812 89/<- %esp 5/r32/ebp -10813 5d/pop-to-ebp -10814 c3/return -10815 -10816 test-add-mem-to-reg: -10817 # var1/reg <- add var2 -10818 # => -10819 # 03/add *(ebp+__) var1 -10820 # -10821 # . prologue -10822 55/push-ebp -10823 89/<- %ebp 4/r32/esp -10824 # setup -10825 (clear-stream _test-output-stream) -10826 (clear-stream $_test-output-buffered-file->buffer) -10827 # var type/ecx: (handle tree type-id) = int -10828 68/push 0/imm32/right/null -10829 68/push 1/imm32/left/int -10830 89/<- %ecx 4/r32/esp -10831 # var var-var1/ecx: var in eax -10832 68/push "eax"/imm32/register -10833 68/push 0/imm32/no-stack-offset -10834 68/push 1/imm32/block-depth -10835 51/push-ecx -10836 68/push "var1"/imm32 -10837 89/<- %ecx 4/r32/esp -10838 # var var-var2/edx: var -10839 68/push 0/imm32/no-register -10840 68/push 8/imm32/stack-offset -10841 68/push 1/imm32/block-depth -10842 ff 6/subop/push *(ecx+4) # Var-type -10843 68/push "var2"/imm32 -10844 89/<- %edx 4/r32/esp -10845 # var inouts/esi: (handle stmt-var) = [var2] -10846 68/push 0/imm32/is-deref:false -10847 68/push 0/imm32/next -10848 52/push-edx/var-var2 -10849 89/<- %esi 4/r32/esp -10850 # var outputs/edi = (handle stmt-var) = [var1] -10851 68/push 0/imm32/is-deref:false -10852 68/push 0/imm32/next -10853 51/push-ecx/var-var1 -10854 89/<- %edi 4/r32/esp -10855 # var stmt/esi: statement -10856 68/push 0/imm32/next -10857 57/push-edi/outputs -10858 56/push-esi/inouts -10859 68/push "add"/imm32/operation -10860 68/push 1/imm32 +10799 # var outputs/edi: (handle stmt-var) = [var1, var2] +10800 68/push 0/imm32/is-deref:false +10801 68/push 0/imm32/next +10802 51/push-ecx/var-var1 +10803 89/<- %edi 4/r32/esp +10804 # var stmt/esi: statement +10805 68/push 0/imm32/next +10806 57/push-edi/outputs +10807 56/push-esi/inouts +10808 68/push "add"/imm32/operation +10809 68/push 1/imm32 +10810 89/<- %esi 4/r32/esp +10811 # convert +10812 c7 0/subop/copy *Curr-block-depth 0/imm32 +10813 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10814 (flush _test-output-buffered-file) +10815 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10821 # check output +10822 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +10823 # . epilogue +10824 89/<- %esp 5/r32/ebp +10825 5d/pop-to-ebp +10826 c3/return +10827 +10828 test-add-reg-to-mem: +10829 # add-to var1 var2/reg +10830 # => +10831 # 01/add *(ebp+__) var2 +10832 # +10833 # . prologue +10834 55/push-ebp +10835 89/<- %ebp 4/r32/esp +10836 # setup +10837 (clear-stream _test-output-stream) +10838 (clear-stream $_test-output-buffered-file->buffer) +10839 # var type/ecx: (handle tree type-id) = int +10840 68/push 0/imm32/right/null +10841 68/push 1/imm32/left/int +10842 89/<- %ecx 4/r32/esp +10843 # var var-var1/ecx: var +10844 68/push 0/imm32/no-register +10845 68/push 8/imm32/stack-offset +10846 68/push 1/imm32/block-depth +10847 51/push-ecx +10848 68/push "var1"/imm32 +10849 89/<- %ecx 4/r32/esp +10850 # var var-var2/edx: var in ecx +10851 68/push "ecx"/imm32/register +10852 68/push 0/imm32/no-stack-offset +10853 68/push 1/imm32/block-depth +10854 ff 6/subop/push *(ecx+4) # Var-type +10855 68/push "var2"/imm32 +10856 89/<- %edx 4/r32/esp +10857 # var inouts/esi: (handle stmt-var) = [var2] +10858 68/push 0/imm32/is-deref:false +10859 68/push 0/imm32/next +10860 52/push-edx/var-var2 10861 89/<- %esi 4/r32/esp -10862 # convert -10863 c7 0/subop/copy *Curr-block-depth 0/imm32 -10864 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10865 (flush _test-output-buffered-file) -10866 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10872 # check output -10873 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -10874 # . epilogue -10875 89/<- %esp 5/r32/ebp -10876 5d/pop-to-ebp -10877 c3/return -10878 -10879 test-add-literal-to-eax: -10880 # var1/eax <- add 0x34 -10881 # => -10882 # 05/add-to-eax 0x34/imm32 -10883 # -10884 # . prologue -10885 55/push-ebp -10886 89/<- %ebp 4/r32/esp -10887 # setup -10888 (clear-stream _test-output-stream) -10889 (clear-stream $_test-output-buffered-file->buffer) -10890 # var type/ecx: (handle tree type-id) = int -10891 68/push 0/imm32/right/null -10892 68/push 1/imm32/left/int -10893 89/<- %ecx 4/r32/esp -10894 # var var-var1/ecx: var in eax -10895 68/push "eax"/imm32/register -10896 68/push 0/imm32/no-stack-offset -10897 68/push 1/imm32/block-depth -10898 51/push-ecx -10899 68/push "var1"/imm32 -10900 89/<- %ecx 4/r32/esp -10901 # var type/edx: (handle tree type-id) = literal +10862 # var inouts = (handle stmt-var) = [var1, var2] +10863 56/push-esi/next +10864 51/push-ecx/var-var1 +10865 89/<- %esi 4/r32/esp +10866 # var stmt/esi: statement +10867 68/push 0/imm32/next +10868 68/push 0/imm32/outputs +10869 56/push-esi/inouts +10870 68/push "add-to"/imm32/operation +10871 68/push 1/imm32 +10872 89/<- %esi 4/r32/esp +10873 # convert +10874 c7 0/subop/copy *Curr-block-depth 0/imm32 +10875 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10876 (flush _test-output-buffered-file) +10877 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10883 # check output +10884 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +10885 # . epilogue +10886 89/<- %esp 5/r32/ebp +10887 5d/pop-to-ebp +10888 c3/return +10889 +10890 test-add-mem-to-reg: +10891 # var1/reg <- add var2 +10892 # => +10893 # 03/add *(ebp+__) var1 +10894 # +10895 # . prologue +10896 55/push-ebp +10897 89/<- %ebp 4/r32/esp +10898 # setup +10899 (clear-stream _test-output-stream) +10900 (clear-stream $_test-output-buffered-file->buffer) +10901 # var type/ecx: (handle tree type-id) = int 10902 68/push 0/imm32/right/null -10903 68/push 0/imm32/left/literal -10904 89/<- %edx 4/r32/esp -10905 # var var-var2/edx: var literal -10906 68/push 0/imm32/no-register +10903 68/push 1/imm32/left/int +10904 89/<- %ecx 4/r32/esp +10905 # var var-var1/ecx: var in eax +10906 68/push "eax"/imm32/register 10907 68/push 0/imm32/no-stack-offset 10908 68/push 1/imm32/block-depth -10909 52/push-edx -10910 68/push "0x34"/imm32 -10911 89/<- %edx 4/r32/esp -10912 # var inouts/esi: (handle stmt-var) = [var2] -10913 68/push 0/imm32/is-deref:false -10914 68/push 0/imm32/next -10915 52/push-edx/var-var2 -10916 89/<- %esi 4/r32/esp -10917 # var outputs/edi: (handle stmt-var) = [var1] -10918 68/push 0/imm32/is-deref:false -10919 68/push 0/imm32/next -10920 51/push-ecx/var-var1 -10921 89/<- %edi 4/r32/esp -10922 # var stmt/esi: statement -10923 68/push 0/imm32/next -10924 57/push-edi/outputs -10925 56/push-esi/inouts -10926 68/push "add"/imm32/operation -10927 68/push 1/imm32 -10928 89/<- %esi 4/r32/esp -10929 # convert -10930 c7 0/subop/copy *Curr-block-depth 0/imm32 -10931 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10932 (flush _test-output-buffered-file) -10933 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10939 # check output -10940 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -10941 # . epilogue -10942 89/<- %esp 5/r32/ebp -10943 5d/pop-to-ebp -10944 c3/return -10945 -10946 test-add-literal-to-reg: -10947 # var1/ecx <- add 0x34 -10948 # => -10949 # 81 0/subop/add %ecx 0x34/imm32 -10950 # -10951 # . prologue -10952 55/push-ebp -10953 89/<- %ebp 4/r32/esp -10954 # setup -10955 (clear-stream _test-output-stream) -10956 (clear-stream $_test-output-buffered-file->buffer) -10957 # var type/ecx: (handle tree type-id) = int -10958 68/push 0/imm32/right/null -10959 68/push 1/imm32/left/int -10960 89/<- %ecx 4/r32/esp -10961 # var var-var1/ecx: var in ecx -10962 68/push "ecx"/imm32/register -10963 68/push 0/imm32/no-stack-offset -10964 68/push 1/imm32/block-depth -10965 51/push-ecx -10966 68/push "var1"/imm32 +10909 51/push-ecx +10910 68/push "var1"/imm32 +10911 89/<- %ecx 4/r32/esp +10912 # var var-var2/edx: var +10913 68/push 0/imm32/no-register +10914 68/push 8/imm32/stack-offset +10915 68/push 1/imm32/block-depth +10916 ff 6/subop/push *(ecx+4) # Var-type +10917 68/push "var2"/imm32 +10918 89/<- %edx 4/r32/esp +10919 # var inouts/esi: (handle stmt-var) = [var2] +10920 68/push 0/imm32/is-deref:false +10921 68/push 0/imm32/next +10922 52/push-edx/var-var2 +10923 89/<- %esi 4/r32/esp +10924 # var outputs/edi = (handle stmt-var) = [var1] +10925 68/push 0/imm32/is-deref:false +10926 68/push 0/imm32/next +10927 51/push-ecx/var-var1 +10928 89/<- %edi 4/r32/esp +10929 # var stmt/esi: statement +10930 68/push 0/imm32/next +10931 57/push-edi/outputs +10932 56/push-esi/inouts +10933 68/push "add"/imm32/operation +10934 68/push 1/imm32 +10935 89/<- %esi 4/r32/esp +10936 # convert +10937 c7 0/subop/copy *Curr-block-depth 0/imm32 +10938 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10939 (flush _test-output-buffered-file) +10940 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10946 # check output +10947 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +10948 # . epilogue +10949 89/<- %esp 5/r32/ebp +10950 5d/pop-to-ebp +10951 c3/return +10952 +10953 test-add-literal-to-eax: +10954 # var1/eax <- add 0x34 +10955 # => +10956 # 05/add-to-eax 0x34/imm32 +10957 # +10958 # . prologue +10959 55/push-ebp +10960 89/<- %ebp 4/r32/esp +10961 # setup +10962 (clear-stream _test-output-stream) +10963 (clear-stream $_test-output-buffered-file->buffer) +10964 # var type/ecx: (handle tree type-id) = int +10965 68/push 0/imm32/right/null +10966 68/push 1/imm32/left/int 10967 89/<- %ecx 4/r32/esp -10968 # var type/edx: (handle tree type-id) = literal -10969 68/push 0/imm32/right/null -10970 68/push 0/imm32/left/literal -10971 89/<- %edx 4/r32/esp -10972 # var var-var2/edx: var literal -10973 68/push 0/imm32/no-register -10974 68/push 0/imm32/no-stack-offset -10975 68/push 1/imm32/block-depth -10976 52/push-edx -10977 68/push "0x34"/imm32 +10968 # var var-var1/ecx: var in eax +10969 68/push "eax"/imm32/register +10970 68/push 0/imm32/no-stack-offset +10971 68/push 1/imm32/block-depth +10972 51/push-ecx +10973 68/push "var1"/imm32 +10974 89/<- %ecx 4/r32/esp +10975 # var type/edx: (handle tree type-id) = literal +10976 68/push 0/imm32/right/null +10977 68/push 0/imm32/left/literal 10978 89/<- %edx 4/r32/esp -10979 # var inouts/esi: (handle stmt-var) = [var2] -10980 68/push 0/imm32/is-deref:false -10981 68/push 0/imm32/next -10982 52/push-edx/var-var2 -10983 89/<- %esi 4/r32/esp -10984 # var outputs/edi: (handle stmt-var) = [var1] -10985 68/push 0/imm32/is-deref:false -10986 68/push 0/imm32/next -10987 51/push-ecx/var-var1 -10988 89/<- %edi 4/r32/esp -10989 # var stmt/esi: statement -10990 68/push 0/imm32/next -10991 57/push-edi/outputs -10992 56/push-esi/inouts -10993 68/push "add"/imm32/operation -10994 68/push 1/imm32 -10995 89/<- %esi 4/r32/esp -10996 # convert -10997 c7 0/subop/copy *Curr-block-depth 0/imm32 -10998 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10999 (flush _test-output-buffered-file) -11000 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11006 # check output -11007 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -11008 # . epilogue -11009 89/<- %esp 5/r32/ebp -11010 5d/pop-to-ebp -11011 c3/return -11012 -11013 test-add-literal-to-mem: -11014 # add-to var1, 0x34 -11015 # => -11016 # 81 0/subop/add %eax 0x34/imm32 -11017 # -11018 # . prologue -11019 55/push-ebp -11020 89/<- %ebp 4/r32/esp -11021 # setup -11022 (clear-stream _test-output-stream) -11023 (clear-stream $_test-output-buffered-file->buffer) -11024 # var type/ecx: (handle tree type-id) = int -11025 68/push 0/imm32/right/null -11026 68/push 1/imm32/left/int -11027 89/<- %ecx 4/r32/esp -11028 # var var-var1/ecx: var -11029 68/push 0/imm32/no-register -11030 68/push 8/imm32/stack-offset -11031 68/push 1/imm32/block-depth -11032 51/push-ecx -11033 68/push "var1"/imm32 +10979 # var var-var2/edx: var literal +10980 68/push 0/imm32/no-register +10981 68/push 0/imm32/no-stack-offset +10982 68/push 1/imm32/block-depth +10983 52/push-edx +10984 68/push "0x34"/imm32 +10985 89/<- %edx 4/r32/esp +10986 # var inouts/esi: (handle stmt-var) = [var2] +10987 68/push 0/imm32/is-deref:false +10988 68/push 0/imm32/next +10989 52/push-edx/var-var2 +10990 89/<- %esi 4/r32/esp +10991 # var outputs/edi: (handle stmt-var) = [var1] +10992 68/push 0/imm32/is-deref:false +10993 68/push 0/imm32/next +10994 51/push-ecx/var-var1 +10995 89/<- %edi 4/r32/esp +10996 # var stmt/esi: statement +10997 68/push 0/imm32/next +10998 57/push-edi/outputs +10999 56/push-esi/inouts +11000 68/push "add"/imm32/operation +11001 68/push 1/imm32 +11002 89/<- %esi 4/r32/esp +11003 # convert +11004 c7 0/subop/copy *Curr-block-depth 0/imm32 +11005 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11006 (flush _test-output-buffered-file) +11007 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11013 # check output +11014 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +11015 # . epilogue +11016 89/<- %esp 5/r32/ebp +11017 5d/pop-to-ebp +11018 c3/return +11019 +11020 test-add-literal-to-reg: +11021 # var1/ecx <- add 0x34 +11022 # => +11023 # 81 0/subop/add %ecx 0x34/imm32 +11024 # +11025 # . prologue +11026 55/push-ebp +11027 89/<- %ebp 4/r32/esp +11028 # setup +11029 (clear-stream _test-output-stream) +11030 (clear-stream $_test-output-buffered-file->buffer) +11031 # var type/ecx: (handle tree type-id) = int +11032 68/push 0/imm32/right/null +11033 68/push 1/imm32/left/int 11034 89/<- %ecx 4/r32/esp -11035 # var type/edx: (handle tree type-id) = literal -11036 68/push 0/imm32/right/null -11037 68/push 0/imm32/left/literal -11038 89/<- %edx 4/r32/esp -11039 # var var-var2/edx: var literal -11040 68/push 0/imm32/no-register -11041 68/push 0/imm32/no-stack-offset -11042 68/push 1/imm32/block-depth -11043 52/push-edx -11044 68/push "0x34"/imm32 +11035 # var var-var1/ecx: var in ecx +11036 68/push "ecx"/imm32/register +11037 68/push 0/imm32/no-stack-offset +11038 68/push 1/imm32/block-depth +11039 51/push-ecx +11040 68/push "var1"/imm32 +11041 89/<- %ecx 4/r32/esp +11042 # var type/edx: (handle tree type-id) = literal +11043 68/push 0/imm32/right/null +11044 68/push 0/imm32/left/literal 11045 89/<- %edx 4/r32/esp -11046 # var inouts/esi: (handle stmt-var) = [var2] -11047 68/push 0/imm32/is-deref:false -11048 68/push 0/imm32/next -11049 52/push-edx/var-var2 -11050 89/<- %esi 4/r32/esp -11051 # var inouts = (handle stmt-var) = [var1, var2] -11052 68/push 0/imm32/is-deref:false -11053 56/push-esi/next -11054 51/push-ecx/var-var1 -11055 89/<- %esi 4/r32/esp -11056 # var stmt/esi: statement -11057 68/push 0/imm32/next -11058 68/push 0/imm32/outputs -11059 56/push-esi/inouts -11060 68/push "add-to"/imm32/operation -11061 68/push 1/imm32 -11062 89/<- %esi 4/r32/esp -11063 # convert -11064 c7 0/subop/copy *Curr-block-depth 0/imm32 -11065 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11066 (flush _test-output-buffered-file) -11067 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11073 # check output -11074 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -11075 # . epilogue -11076 89/<- %esp 5/r32/ebp -11077 5d/pop-to-ebp -11078 c3/return -11079 -11080 test-compare-mem-with-reg: -11081 # compare var1, var2/eax -11082 # => -11083 # 39/compare *(ebp+___) 0/r32/eax -11084 # -11085 # . prologue -11086 55/push-ebp -11087 89/<- %ebp 4/r32/esp -11088 # setup -11089 (clear-stream _test-output-stream) -11090 (clear-stream $_test-output-buffered-file->buffer) -11091 # var type/ecx: (handle tree type-id) = int -11092 68/push 0/imm32/right/null -11093 68/push 1/imm32/left/int -11094 89/<- %ecx 4/r32/esp -11095 # var var-var2/ecx: var in eax -11096 68/push "eax"/imm32/register -11097 68/push 0/imm32/no-stack-offset -11098 68/push 1/imm32/block-depth -11099 51/push-ecx -11100 68/push "var2"/imm32 +11046 # var var-var2/edx: var literal +11047 68/push 0/imm32/no-register +11048 68/push 0/imm32/no-stack-offset +11049 68/push 1/imm32/block-depth +11050 52/push-edx +11051 68/push "0x34"/imm32 +11052 89/<- %edx 4/r32/esp +11053 # var inouts/esi: (handle stmt-var) = [var2] +11054 68/push 0/imm32/is-deref:false +11055 68/push 0/imm32/next +11056 52/push-edx/var-var2 +11057 89/<- %esi 4/r32/esp +11058 # var outputs/edi: (handle stmt-var) = [var1] +11059 68/push 0/imm32/is-deref:false +11060 68/push 0/imm32/next +11061 51/push-ecx/var-var1 +11062 89/<- %edi 4/r32/esp +11063 # var stmt/esi: statement +11064 68/push 0/imm32/next +11065 57/push-edi/outputs +11066 56/push-esi/inouts +11067 68/push "add"/imm32/operation +11068 68/push 1/imm32 +11069 89/<- %esi 4/r32/esp +11070 # convert +11071 c7 0/subop/copy *Curr-block-depth 0/imm32 +11072 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11073 (flush _test-output-buffered-file) +11074 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11080 # check output +11081 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +11082 # . epilogue +11083 89/<- %esp 5/r32/ebp +11084 5d/pop-to-ebp +11085 c3/return +11086 +11087 test-add-literal-to-mem: +11088 # add-to var1, 0x34 +11089 # => +11090 # 81 0/subop/add %eax 0x34/imm32 +11091 # +11092 # . prologue +11093 55/push-ebp +11094 89/<- %ebp 4/r32/esp +11095 # setup +11096 (clear-stream _test-output-stream) +11097 (clear-stream $_test-output-buffered-file->buffer) +11098 # var type/ecx: (handle tree type-id) = int +11099 68/push 0/imm32/right/null +11100 68/push 1/imm32/left/int 11101 89/<- %ecx 4/r32/esp -11102 # var var-var1/edx: var +11102 # var var-var1/ecx: var 11103 68/push 0/imm32/no-register 11104 68/push 8/imm32/stack-offset 11105 68/push 1/imm32/block-depth -11106 ff 6/subop/push *(ecx+4) # Var-type +11106 51/push-ecx 11107 68/push "var1"/imm32 -11108 89/<- %edx 4/r32/esp -11109 # var inouts/esi: (handle stmt-var) = [var2] -11110 68/push 0/imm32/is-deref:false -11111 68/push 0/imm32/next -11112 51/push-ecx/var-var2 -11113 89/<- %esi 4/r32/esp -11114 # inouts = [var1, var2] -11115 68/push 0/imm32/is-deref:false -11116 56/push-esi -11117 52/push-edx/var-var1 -11118 89/<- %esi 4/r32/esp -11119 # var stmt/esi: statement -11120 68/push 0/imm32/next -11121 68/push 0/imm32/outputs -11122 56/push-esi/inouts -11123 68/push "compare"/imm32/operation -11124 68/push 1/imm32 -11125 89/<- %esi 4/r32/esp -11126 # convert -11127 c7 0/subop/copy *Curr-block-depth 0/imm32 -11128 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11129 (flush _test-output-buffered-file) -11130 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11136 # check output -11137 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -11138 # . epilogue -11139 89/<- %esp 5/r32/ebp -11140 5d/pop-to-ebp -11141 c3/return -11142 -11143 test-compare-reg-with-mem: -11144 # compare var1/eax, var2 -11145 # => -11146 # 3b/compare *(ebp+___) 0/r32/eax -11147 # -11148 # . prologue -11149 55/push-ebp -11150 89/<- %ebp 4/r32/esp -11151 # setup -11152 (clear-stream _test-output-stream) -11153 (clear-stream $_test-output-buffered-file->buffer) -11154 # var type/ecx: (handle tree type-id) = int -11155 68/push 0/imm32/right/null -11156 68/push 1/imm32/left/int -11157 89/<- %ecx 4/r32/esp -11158 # var var-var1/ecx: var in eax -11159 68/push "eax"/imm32/register -11160 68/push 0/imm32/no-stack-offset -11161 68/push 1/imm32/block-depth -11162 51/push-ecx -11163 68/push "var1"/imm32 -11164 89/<- %ecx 4/r32/esp -11165 # var var-var2/edx: var -11166 68/push 0/imm32/no-register -11167 68/push 8/imm32/stack-offset -11168 68/push 1/imm32/block-depth -11169 ff 6/subop/push *(ecx+4) # Var-type -11170 68/push "var2"/imm32 -11171 89/<- %edx 4/r32/esp -11172 # var inouts/esi: (handle stmt-var) = [var2] -11173 68/push 0/imm32/is-deref:false -11174 68/push 0/imm32/next -11175 52/push-edx/var-var2 -11176 89/<- %esi 4/r32/esp -11177 # inouts = [var1, var2] -11178 68/push 0/imm32/is-deref:false -11179 56/push-esi -11180 51/push-ecx/var-var1 -11181 89/<- %esi 4/r32/esp -11182 # var stmt/esi: statement -11183 68/push 0/imm32/next -11184 68/push 0/imm32/outputs -11185 56/push-esi/inouts -11186 68/push "compare"/imm32/operation -11187 68/push 1/imm32 -11188 89/<- %esi 4/r32/esp -11189 # convert -11190 c7 0/subop/copy *Curr-block-depth 0/imm32 -11191 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11192 (flush _test-output-buffered-file) -11193 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11199 # check output -11200 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -11201 # . epilogue -11202 89/<- %esp 5/r32/ebp -11203 5d/pop-to-ebp -11204 c3/return -11205 -11206 test-compare-mem-with-literal: -11207 # compare var1, 0x34 -11208 # => -11209 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -11210 # -11211 # . prologue -11212 55/push-ebp -11213 89/<- %ebp 4/r32/esp -11214 # setup -11215 (clear-stream _test-output-stream) -11216 (clear-stream $_test-output-buffered-file->buffer) -11217 # var type/ecx: (handle tree type-id) = int -11218 68/push 0/imm32/right/null -11219 68/push 1/imm32/left/int -11220 89/<- %ecx 4/r32/esp -11221 # var var-var1/ecx: var -11222 68/push 0/imm32/no-register -11223 68/push 8/imm32/stack-offset -11224 68/push 1/imm32/block-depth -11225 51/push-ecx -11226 68/push "var1"/imm32 -11227 89/<- %ecx 4/r32/esp -11228 # var type/edx: (handle tree type-id) = literal +11108 89/<- %ecx 4/r32/esp +11109 # var type/edx: (handle tree type-id) = literal +11110 68/push 0/imm32/right/null +11111 68/push 0/imm32/left/literal +11112 89/<- %edx 4/r32/esp +11113 # var var-var2/edx: var literal +11114 68/push 0/imm32/no-register +11115 68/push 0/imm32/no-stack-offset +11116 68/push 1/imm32/block-depth +11117 52/push-edx +11118 68/push "0x34"/imm32 +11119 89/<- %edx 4/r32/esp +11120 # var inouts/esi: (handle stmt-var) = [var2] +11121 68/push 0/imm32/is-deref:false +11122 68/push 0/imm32/next +11123 52/push-edx/var-var2 +11124 89/<- %esi 4/r32/esp +11125 # var inouts = (handle stmt-var) = [var1, var2] +11126 68/push 0/imm32/is-deref:false +11127 56/push-esi/next +11128 51/push-ecx/var-var1 +11129 89/<- %esi 4/r32/esp +11130 # var stmt/esi: statement +11131 68/push 0/imm32/next +11132 68/push 0/imm32/outputs +11133 56/push-esi/inouts +11134 68/push "add-to"/imm32/operation +11135 68/push 1/imm32 +11136 89/<- %esi 4/r32/esp +11137 # convert +11138 c7 0/subop/copy *Curr-block-depth 0/imm32 +11139 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11140 (flush _test-output-buffered-file) +11141 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11147 # check output +11148 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +11149 # . epilogue +11150 89/<- %esp 5/r32/ebp +11151 5d/pop-to-ebp +11152 c3/return +11153 +11154 test-compare-mem-with-reg: +11155 # compare var1, var2/eax +11156 # => +11157 # 39/compare *(ebp+___) 0/r32/eax +11158 # +11159 # . prologue +11160 55/push-ebp +11161 89/<- %ebp 4/r32/esp +11162 # setup +11163 (clear-stream _test-output-stream) +11164 (clear-stream $_test-output-buffered-file->buffer) +11165 # var type/ecx: (handle tree type-id) = int +11166 68/push 0/imm32/right/null +11167 68/push 1/imm32/left/int +11168 89/<- %ecx 4/r32/esp +11169 # var var-var2/ecx: var in eax +11170 68/push "eax"/imm32/register +11171 68/push 0/imm32/no-stack-offset +11172 68/push 1/imm32/block-depth +11173 51/push-ecx +11174 68/push "var2"/imm32 +11175 89/<- %ecx 4/r32/esp +11176 # var var-var1/edx: var +11177 68/push 0/imm32/no-register +11178 68/push 8/imm32/stack-offset +11179 68/push 1/imm32/block-depth +11180 ff 6/subop/push *(ecx+4) # Var-type +11181 68/push "var1"/imm32 +11182 89/<- %edx 4/r32/esp +11183 # var inouts/esi: (handle stmt-var) = [var2] +11184 68/push 0/imm32/is-deref:false +11185 68/push 0/imm32/next +11186 51/push-ecx/var-var2 +11187 89/<- %esi 4/r32/esp +11188 # inouts = [var1, var2] +11189 68/push 0/imm32/is-deref:false +11190 56/push-esi +11191 52/push-edx/var-var1 +11192 89/<- %esi 4/r32/esp +11193 # var stmt/esi: statement +11194 68/push 0/imm32/next +11195 68/push 0/imm32/outputs +11196 56/push-esi/inouts +11197 68/push "compare"/imm32/operation +11198 68/push 1/imm32 +11199 89/<- %esi 4/r32/esp +11200 # convert +11201 c7 0/subop/copy *Curr-block-depth 0/imm32 +11202 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11203 (flush _test-output-buffered-file) +11204 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11210 # check output +11211 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +11212 # . epilogue +11213 89/<- %esp 5/r32/ebp +11214 5d/pop-to-ebp +11215 c3/return +11216 +11217 test-compare-reg-with-mem: +11218 # compare var1/eax, var2 +11219 # => +11220 # 3b/compare *(ebp+___) 0/r32/eax +11221 # +11222 # . prologue +11223 55/push-ebp +11224 89/<- %ebp 4/r32/esp +11225 # setup +11226 (clear-stream _test-output-stream) +11227 (clear-stream $_test-output-buffered-file->buffer) +11228 # var type/ecx: (handle tree type-id) = int 11229 68/push 0/imm32/right/null -11230 68/push 0/imm32/left/literal -11231 89/<- %edx 4/r32/esp -11232 # var var-var2/edx: var literal -11233 68/push 0/imm32/no-register +11230 68/push 1/imm32/left/int +11231 89/<- %ecx 4/r32/esp +11232 # var var-var1/ecx: var in eax +11233 68/push "eax"/imm32/register 11234 68/push 0/imm32/no-stack-offset 11235 68/push 1/imm32/block-depth -11236 52/push-edx -11237 68/push "0x34"/imm32 -11238 89/<- %edx 4/r32/esp -11239 # var inouts/esi: (handle stmt-var) = [var2] -11240 68/push 0/imm32/is-deref:false -11241 68/push 0/imm32/next -11242 52/push-edx/var-var2 -11243 89/<- %esi 4/r32/esp -11244 # inouts = [var1, var2] -11245 68/push 0/imm32/is-deref:false -11246 56/push-esi/next -11247 51/push-ecx/var-var1 -11248 89/<- %esi 4/r32/esp -11249 # var stmt/esi: statement -11250 68/push 0/imm32/next -11251 68/push 0/imm32/outputs -11252 56/push-esi/inouts -11253 68/push "compare"/imm32/operation -11254 68/push 1/imm32 +11236 51/push-ecx +11237 68/push "var1"/imm32 +11238 89/<- %ecx 4/r32/esp +11239 # var var-var2/edx: var +11240 68/push 0/imm32/no-register +11241 68/push 8/imm32/stack-offset +11242 68/push 1/imm32/block-depth +11243 ff 6/subop/push *(ecx+4) # Var-type +11244 68/push "var2"/imm32 +11245 89/<- %edx 4/r32/esp +11246 # var inouts/esi: (handle stmt-var) = [var2] +11247 68/push 0/imm32/is-deref:false +11248 68/push 0/imm32/next +11249 52/push-edx/var-var2 +11250 89/<- %esi 4/r32/esp +11251 # inouts = [var1, var2] +11252 68/push 0/imm32/is-deref:false +11253 56/push-esi +11254 51/push-ecx/var-var1 11255 89/<- %esi 4/r32/esp -11256 # convert -11257 c7 0/subop/copy *Curr-block-depth 0/imm32 -11258 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11259 (flush _test-output-buffered-file) -11260 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11266 # check output -11267 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -11268 # . epilogue -11269 89/<- %esp 5/r32/ebp -11270 5d/pop-to-ebp -11271 c3/return -11272 -11273 test-compare-eax-with-literal: -11274 # compare var1/eax 0x34 -11275 # => -11276 # 3d/compare-eax-with 0x34/imm32 -11277 # -11278 # . prologue -11279 55/push-ebp -11280 89/<- %ebp 4/r32/esp -11281 # setup -11282 (clear-stream _test-output-stream) -11283 (clear-stream $_test-output-buffered-file->buffer) -11284 # var type/ecx: (handle tree type-id) = int -11285 68/push 0/imm32/right/null -11286 68/push 1/imm32/left/int -11287 89/<- %ecx 4/r32/esp -11288 # var var-var1/ecx: var in eax -11289 68/push "eax"/imm32/register -11290 68/push 0/imm32/no-stack-offset -11291 68/push 1/imm32/block-depth -11292 51/push-ecx -11293 68/push "var1"/imm32 +11256 # var stmt/esi: statement +11257 68/push 0/imm32/next +11258 68/push 0/imm32/outputs +11259 56/push-esi/inouts +11260 68/push "compare"/imm32/operation +11261 68/push 1/imm32 +11262 89/<- %esi 4/r32/esp +11263 # convert +11264 c7 0/subop/copy *Curr-block-depth 0/imm32 +11265 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11266 (flush _test-output-buffered-file) +11267 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11273 # check output +11274 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +11275 # . epilogue +11276 89/<- %esp 5/r32/ebp +11277 5d/pop-to-ebp +11278 c3/return +11279 +11280 test-compare-mem-with-literal: +11281 # compare var1, 0x34 +11282 # => +11283 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +11284 # +11285 # . prologue +11286 55/push-ebp +11287 89/<- %ebp 4/r32/esp +11288 # setup +11289 (clear-stream _test-output-stream) +11290 (clear-stream $_test-output-buffered-file->buffer) +11291 # var type/ecx: (handle tree type-id) = int +11292 68/push 0/imm32/right/null +11293 68/push 1/imm32/left/int 11294 89/<- %ecx 4/r32/esp -11295 # var type/edx: (handle tree type-id) = literal -11296 68/push 0/imm32/right/null -11297 68/push 0/imm32/left/literal -11298 89/<- %edx 4/r32/esp -11299 # var var-var2/edx: var literal -11300 68/push 0/imm32/no-register -11301 68/push 0/imm32/no-stack-offset -11302 68/push 1/imm32/block-depth -11303 52/push-edx -11304 68/push "0x34"/imm32 +11295 # var var-var1/ecx: var +11296 68/push 0/imm32/no-register +11297 68/push 8/imm32/stack-offset +11298 68/push 1/imm32/block-depth +11299 51/push-ecx +11300 68/push "var1"/imm32 +11301 89/<- %ecx 4/r32/esp +11302 # var type/edx: (handle tree type-id) = literal +11303 68/push 0/imm32/right/null +11304 68/push 0/imm32/left/literal 11305 89/<- %edx 4/r32/esp -11306 # var inouts/esi: (handle stmt-var) = [var2] -11307 68/push 0/imm32/is-deref:false -11308 68/push 0/imm32/next -11309 52/push-edx/var-var2 -11310 89/<- %esi 4/r32/esp -11311 # inouts = [var1, var2] -11312 68/push 0/imm32/is-deref:false -11313 56/push-esi/next -11314 51/push-ecx/var-var1 -11315 89/<- %esi 4/r32/esp -11316 # var stmt/esi: statement -11317 68/push 0/imm32/next -11318 68/push 0/imm32/outputs -11319 56/push-esi/inouts -11320 68/push "compare"/imm32/operation -11321 68/push 1/imm32/regular-stmt +11306 # var var-var2/edx: var literal +11307 68/push 0/imm32/no-register +11308 68/push 0/imm32/no-stack-offset +11309 68/push 1/imm32/block-depth +11310 52/push-edx +11311 68/push "0x34"/imm32 +11312 89/<- %edx 4/r32/esp +11313 # var inouts/esi: (handle stmt-var) = [var2] +11314 68/push 0/imm32/is-deref:false +11315 68/push 0/imm32/next +11316 52/push-edx/var-var2 +11317 89/<- %esi 4/r32/esp +11318 # inouts = [var1, var2] +11319 68/push 0/imm32/is-deref:false +11320 56/push-esi/next +11321 51/push-ecx/var-var1 11322 89/<- %esi 4/r32/esp -11323 # convert -11324 c7 0/subop/copy *Curr-block-depth 0/imm32 -11325 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11326 (flush _test-output-buffered-file) -11327 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11333 # check output -11334 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -11335 # . epilogue -11336 89/<- %esp 5/r32/ebp -11337 5d/pop-to-ebp -11338 c3/return -11339 -11340 test-compare-reg-with-literal: -11341 # compare var1/ecx 0x34 -11342 # => -11343 # 81 7/subop/compare %ecx 0x34/imm32 -11344 # -11345 # . prologue -11346 55/push-ebp -11347 89/<- %ebp 4/r32/esp -11348 # setup -11349 (clear-stream _test-output-stream) -11350 (clear-stream $_test-output-buffered-file->buffer) -11351 # var type/ecx: (handle tree type-id) = int -11352 68/push 0/imm32/right/null -11353 68/push 1/imm32/left/int -11354 89/<- %ecx 4/r32/esp -11355 # var var-var1/ecx: var in ecx -11356 68/push "ecx"/imm32/register -11357 68/push 0/imm32/no-stack-offset -11358 68/push 1/imm32/block-depth -11359 51/push-ecx -11360 68/push "var1"/imm32 +11323 # var stmt/esi: statement +11324 68/push 0/imm32/next +11325 68/push 0/imm32/outputs +11326 56/push-esi/inouts +11327 68/push "compare"/imm32/operation +11328 68/push 1/imm32 +11329 89/<- %esi 4/r32/esp +11330 # convert +11331 c7 0/subop/copy *Curr-block-depth 0/imm32 +11332 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11333 (flush _test-output-buffered-file) +11334 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11340 # check output +11341 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +11342 # . epilogue +11343 89/<- %esp 5/r32/ebp +11344 5d/pop-to-ebp +11345 c3/return +11346 +11347 test-compare-eax-with-literal: +11348 # compare var1/eax 0x34 +11349 # => +11350 # 3d/compare-eax-with 0x34/imm32 +11351 # +11352 # . prologue +11353 55/push-ebp +11354 89/<- %ebp 4/r32/esp +11355 # setup +11356 (clear-stream _test-output-stream) +11357 (clear-stream $_test-output-buffered-file->buffer) +11358 # var type/ecx: (handle tree type-id) = int +11359 68/push 0/imm32/right/null +11360 68/push 1/imm32/left/int 11361 89/<- %ecx 4/r32/esp -11362 # var type/edx: (handle tree type-id) = literal -11363 68/push 0/imm32/right/null -11364 68/push 0/imm32/left/literal -11365 89/<- %edx 4/r32/esp -11366 # var var-var2/edx: var literal -11367 68/push 0/imm32/no-register -11368 68/push 0/imm32/no-stack-offset -11369 68/push 1/imm32/block-depth -11370 52/push-edx -11371 68/push "0x34"/imm32 +11362 # var var-var1/ecx: var in eax +11363 68/push "eax"/imm32/register +11364 68/push 0/imm32/no-stack-offset +11365 68/push 1/imm32/block-depth +11366 51/push-ecx +11367 68/push "var1"/imm32 +11368 89/<- %ecx 4/r32/esp +11369 # var type/edx: (handle tree type-id) = literal +11370 68/push 0/imm32/right/null +11371 68/push 0/imm32/left/literal 11372 89/<- %edx 4/r32/esp -11373 # var inouts/esi: (handle stmt-var) = [var2] -11374 68/push 0/imm32/is-deref:false -11375 68/push 0/imm32/next -11376 52/push-edx/var-var2 -11377 89/<- %esi 4/r32/esp -11378 # inouts = [var1, var2] -11379 68/push 0/imm32/is-deref:false -11380 56/push-esi/next -11381 51/push-ecx/var-var1 -11382 89/<- %esi 4/r32/esp -11383 # var stmt/esi: statement -11384 68/push 0/imm32/next -11385 68/push 0/imm32/outputs -11386 56/push-esi/inouts -11387 68/push "compare"/imm32/operation -11388 68/push 1/imm32/regular-stmt +11373 # var var-var2/edx: var literal +11374 68/push 0/imm32/no-register +11375 68/push 0/imm32/no-stack-offset +11376 68/push 1/imm32/block-depth +11377 52/push-edx +11378 68/push "0x34"/imm32 +11379 89/<- %edx 4/r32/esp +11380 # var inouts/esi: (handle stmt-var) = [var2] +11381 68/push 0/imm32/is-deref:false +11382 68/push 0/imm32/next +11383 52/push-edx/var-var2 +11384 89/<- %esi 4/r32/esp +11385 # inouts = [var1, var2] +11386 68/push 0/imm32/is-deref:false +11387 56/push-esi/next +11388 51/push-ecx/var-var1 11389 89/<- %esi 4/r32/esp -11390 # convert -11391 c7 0/subop/copy *Curr-block-depth 0/imm32 -11392 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -11393 (flush _test-output-buffered-file) -11394 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11400 # check output -11401 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -11402 # . epilogue -11403 89/<- %esp 5/r32/ebp -11404 5d/pop-to-ebp -11405 c3/return -11406 -11407 test-emit-subx-stmt-function-call: -11408 # Call a function on a variable on the stack. -11409 # f foo -11410 # => -11411 # (f2 *(ebp-8)) -11412 # (Changing the function name supports overloading in general, but here it -11413 # just serves to help disambiguate things.) -11414 # -11415 # There's a variable on the var stack as follows: -11416 # name: 'foo' -11417 # type: int -11418 # stack-offset: -8 -11419 # -11420 # There's nothing in primitives. -11421 # -11422 # There's a function with this info: -11423 # name: 'f' -11424 # inout: int/mem -11425 # value: 'f2' -11426 # -11427 # . prologue -11428 55/push-ebp -11429 89/<- %ebp 4/r32/esp -11430 # setup -11431 (clear-stream _test-output-stream) -11432 (clear-stream $_test-output-buffered-file->buffer) -11433 # var type/ecx: (handle tree type-id) = int -11434 68/push 0/imm32/right/null -11435 68/push 1/imm32/left/int -11436 89/<- %ecx 4/r32/esp -11437 # var var-foo/ecx: var -11438 68/push 0/imm32/no-register -11439 68/push -8/imm32/stack-offset -11440 68/push 0/imm32/block-depth -11441 51/push-ecx -11442 68/push "foo"/imm32 -11443 89/<- %ecx 4/r32/esp -11444 # var inouts/esi: (handle stmt-var) -11445 68/push 0/imm32/is-deref:false -11446 68/push 0/imm32/next -11447 51/push-ecx/var-foo -11448 89/<- %esi 4/r32/esp -11449 # var stmt/esi: statement -11450 68/push 0/imm32/next -11451 68/push 0/imm32/outputs -11452 56/push-esi/inouts -11453 68/push "f"/imm32/operation -11454 68/push 1/imm32 -11455 89/<- %esi 4/r32/esp -11456 # var functions/ebx: function -11457 68/push 0/imm32/next -11458 68/push 0/imm32/body +11390 # var stmt/esi: statement +11391 68/push 0/imm32/next +11392 68/push 0/imm32/outputs +11393 56/push-esi/inouts +11394 68/push "compare"/imm32/operation +11395 68/push 1/imm32/regular-stmt +11396 89/<- %esi 4/r32/esp +11397 # convert +11398 c7 0/subop/copy *Curr-block-depth 0/imm32 +11399 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +11400 (flush _test-output-buffered-file) +11401 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11407 # check output +11408 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +11409 # . epilogue +11410 89/<- %esp 5/r32/ebp +11411 5d/pop-to-ebp +11412 c3/return +11413 +11414 test-compare-reg-with-literal: +11415 # compare var1/ecx 0x34 +11416 # => +11417 # 81 7/subop/compare %ecx 0x34/imm32 +11418 # +11419 # . prologue +11420 55/push-ebp +11421 89/<- %ebp 4/r32/esp +11422 # setup +11423 (clear-stream _test-output-stream) +11424 (clear-stream $_test-output-buffered-file->buffer) +11425 # var type/ecx: (handle tree type-id) = int +11426 68/push 0/imm32/right/null +11427 68/push 1/imm32/left/int +11428 89/<- %ecx 4/r32/esp +11429 # var var-var1/ecx: var in ecx +11430 68/push "ecx"/imm32/register +11431 68/push 0/imm32/no-stack-offset +11432 68/push 1/imm32/block-depth +11433 51/push-ecx +11434 68/push "var1"/imm32 +11435 89/<- %ecx 4/r32/esp +11436 # var type/edx: (handle tree type-id) = literal +11437 68/push 0/imm32/right/null +11438 68/push 0/imm32/left/literal +11439 89/<- %edx 4/r32/esp +11440 # var var-var2/edx: var literal +11441 68/push 0/imm32/no-register +11442 68/push 0/imm32/no-stack-offset +11443 68/push 1/imm32/block-depth +11444 52/push-edx +11445 68/push "0x34"/imm32 +11446 89/<- %edx 4/r32/esp +11447 # var inouts/esi: (handle stmt-var) = [var2] +11448 68/push 0/imm32/is-deref:false +11449 68/push 0/imm32/next +11450 52/push-edx/var-var2 +11451 89/<- %esi 4/r32/esp +11452 # inouts = [var1, var2] +11453 68/push 0/imm32/is-deref:false +11454 56/push-esi/next +11455 51/push-ecx/var-var1 +11456 89/<- %esi 4/r32/esp +11457 # var stmt/esi: statement +11458 68/push 0/imm32/next 11459 68/push 0/imm32/outputs -11460 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -11461 68/push "f2"/imm32/subx-name -11462 68/push "f"/imm32/name -11463 89/<- %ebx 4/r32/esp +11460 56/push-esi/inouts +11461 68/push "compare"/imm32/operation +11462 68/push 1/imm32/regular-stmt +11463 89/<- %esi 4/r32/esp 11464 # convert -11465 c7 0/subop/copy *Curr-block-depth 0/imm32 -11466 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +11465 c7 0/subop/copy *Curr-block-depth 0/imm32 +11466 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) 11467 (flush _test-output-buffered-file) 11468 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 11474 # check output -11475 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +11475 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") 11476 # . epilogue 11477 89/<- %esp 5/r32/ebp 11478 5d/pop-to-ebp 11479 c3/return 11480 -11481 test-emit-subx-stmt-function-call-with-literal-arg: -11482 # Call a function on a literal. -11483 # f 34 +11481 test-emit-subx-stmt-function-call: +11482 # Call a function on a variable on the stack. +11483 # f foo 11484 # => -11485 # (f2 34) -11486 # -11487 # . prologue -11488 55/push-ebp -11489 89/<- %ebp 4/r32/esp -11490 # setup -11491 (clear-stream _test-output-stream) -11492 (clear-stream $_test-output-buffered-file->buffer) -11493 # var type/ecx: (handle tree type-id) = literal -11494 68/push 0/imm32/right/null -11495 68/push 0/imm32/left/literal -11496 89/<- %ecx 4/r32/esp -11497 # var var-foo/ecx: var literal -11498 68/push 0/imm32/no-register -11499 68/push 0/imm32/no-stack-offset -11500 68/push 0/imm32/block-depth -11501 51/push-ecx -11502 68/push "34"/imm32 -11503 89/<- %ecx 4/r32/esp -11504 # var inouts/esi: (handle stmt-var) -11505 68/push 0/imm32/is-deref:false -11506 68/push 0/imm32/next -11507 51/push-ecx/var-foo -11508 89/<- %esi 4/r32/esp -11509 # var stmt/esi: statement -11510 68/push 0/imm32/next -11511 68/push 0/imm32/outputs -11512 56/push-esi/inouts -11513 68/push "f"/imm32/operation -11514 68/push 1/imm32 -11515 89/<- %esi 4/r32/esp -11516 # var functions/ebx: function -11517 68/push 0/imm32/next -11518 68/push 0/imm32/body -11519 68/push 0/imm32/outputs -11520 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -11521 68/push "f2"/imm32/subx-name -11522 68/push "f"/imm32/name -11523 89/<- %ebx 4/r32/esp -11524 # convert -11525 c7 0/subop/copy *Curr-block-depth 0/imm32 -11526 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) -11527 (flush _test-output-buffered-file) -11528 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -11534 # check output -11535 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") -11536 # . epilogue -11537 89/<- %esp 5/r32/ebp -11538 5d/pop-to-ebp -11539 c3/return -11540 -11541 emit-indent: # out: (addr buffered-file), n: int -11542 # . prologue -11543 55/push-ebp -11544 89/<- %ebp 4/r32/esp -11545 # . save registers -11546 50/push-eax -11547 # var i/eax: int = n -11548 8b/-> *(ebp+0xc) 0/r32/eax -11549 { -11550 # if (i <= 0) break -11551 3d/compare-eax-with 0/imm32 -11552 7e/jump-if-<= break/disp8 -11553 (write-buffered *(ebp+8) " ") -11554 48/decrement-eax -11555 eb/jump loop/disp8 -11556 } -11557 $emit-indent:end: -11558 # . restore registers -11559 58/pop-to-eax -11560 # . epilogue -11561 89/<- %esp 5/r32/ebp -11562 5d/pop-to-ebp -11563 c3/return -11564 -11565 emit-subx-prologue: # out: (addr buffered-file) -11566 # . prologue -11567 55/push-ebp -11568 89/<- %ebp 4/r32/esp -11569 # -11570 (write-buffered *(ebp+8) " # . prologue\n") -11571 (write-buffered *(ebp+8) " 55/push-ebp\n") -11572 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -11573 $emit-subx-prologue:end: -11574 # . epilogue -11575 89/<- %esp 5/r32/ebp -11576 5d/pop-to-ebp -11577 c3/return -11578 -11579 emit-subx-epilogue: # out: (addr buffered-file) -11580 # . prologue -11581 55/push-ebp -11582 89/<- %ebp 4/r32/esp -11583 # -11584 (write-buffered *(ebp+8) " # . epilogue\n") -11585 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -11586 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -11587 (write-buffered *(ebp+8) " c3/return\n") -11588 $emit-subx-epilogue:end: -11589 # . epilogue -11590 89/<- %esp 5/r32/ebp -11591 5d/pop-to-ebp -11592 c3/return +11485 # (f2 *(ebp-8)) +11486 # (Changing the function name supports overloading in general, but here it +11487 # just serves to help disambiguate things.) +11488 # +11489 # There's a variable on the var stack as follows: +11490 # name: 'foo' +11491 # type: int +11492 # stack-offset: -8 +11493 # +11494 # There's nothing in primitives. +11495 # +11496 # There's a function with this info: +11497 # name: 'f' +11498 # inout: int/mem +11499 # value: 'f2' +11500 # +11501 # . prologue +11502 55/push-ebp +11503 89/<- %ebp 4/r32/esp +11504 # setup +11505 (clear-stream _test-output-stream) +11506 (clear-stream $_test-output-buffered-file->buffer) +11507 # var type/ecx: (handle tree type-id) = int +11508 68/push 0/imm32/right/null +11509 68/push 1/imm32/left/int +11510 89/<- %ecx 4/r32/esp +11511 # var var-foo/ecx: var +11512 68/push 0/imm32/no-register +11513 68/push -8/imm32/stack-offset +11514 68/push 0/imm32/block-depth +11515 51/push-ecx +11516 68/push "foo"/imm32 +11517 89/<- %ecx 4/r32/esp +11518 # var inouts/esi: (handle stmt-var) +11519 68/push 0/imm32/is-deref:false +11520 68/push 0/imm32/next +11521 51/push-ecx/var-foo +11522 89/<- %esi 4/r32/esp +11523 # var stmt/esi: statement +11524 68/push 0/imm32/next +11525 68/push 0/imm32/outputs +11526 56/push-esi/inouts +11527 68/push "f"/imm32/operation +11528 68/push 1/imm32 +11529 89/<- %esi 4/r32/esp +11530 # var functions/ebx: function +11531 68/push 0/imm32/next +11532 68/push 0/imm32/body +11533 68/push 0/imm32/outputs +11534 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +11535 68/push "f2"/imm32/subx-name +11536 68/push "f"/imm32/name +11537 89/<- %ebx 4/r32/esp +11538 # convert +11539 c7 0/subop/copy *Curr-block-depth 0/imm32 +11540 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +11541 (flush _test-output-buffered-file) +11542 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11548 # check output +11549 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +11550 # . epilogue +11551 89/<- %esp 5/r32/ebp +11552 5d/pop-to-ebp +11553 c3/return +11554 +11555 test-emit-subx-stmt-function-call-with-literal-arg: +11556 # Call a function on a literal. +11557 # f 34 +11558 # => +11559 # (f2 34) +11560 # +11561 # . prologue +11562 55/push-ebp +11563 89/<- %ebp 4/r32/esp +11564 # setup +11565 (clear-stream _test-output-stream) +11566 (clear-stream $_test-output-buffered-file->buffer) +11567 # var type/ecx: (handle tree type-id) = literal +11568 68/push 0/imm32/right/null +11569 68/push 0/imm32/left/literal +11570 89/<- %ecx 4/r32/esp +11571 # var var-foo/ecx: var literal +11572 68/push 0/imm32/no-register +11573 68/push 0/imm32/no-stack-offset +11574 68/push 0/imm32/block-depth +11575 51/push-ecx +11576 68/push "34"/imm32 +11577 89/<- %ecx 4/r32/esp +11578 # var inouts/esi: (handle stmt-var) +11579 68/push 0/imm32/is-deref:false +11580 68/push 0/imm32/next +11581 51/push-ecx/var-foo +11582 89/<- %esi 4/r32/esp +11583 # var stmt/esi: statement +11584 68/push 0/imm32/next +11585 68/push 0/imm32/outputs +11586 56/push-esi/inouts +11587 68/push "f"/imm32/operation +11588 68/push 1/imm32 +11589 89/<- %esi 4/r32/esp +11590 # var functions/ebx: function +11591 68/push 0/imm32/next +11592 68/push 0/imm32/body +11593 68/push 0/imm32/outputs +11594 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +11595 68/push "f2"/imm32/subx-name +11596 68/push "f"/imm32/name +11597 89/<- %ebx 4/r32/esp +11598 # convert +11599 c7 0/subop/copy *Curr-block-depth 0/imm32 +11600 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +11601 (flush _test-output-buffered-file) +11602 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +11608 # check output +11609 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") +11610 # . epilogue +11611 89/<- %esp 5/r32/ebp +11612 5d/pop-to-ebp +11613 c3/return +11614 +11615 emit-indent: # out: (addr buffered-file), n: int +11616 # . prologue +11617 55/push-ebp +11618 89/<- %ebp 4/r32/esp +11619 # . save registers +11620 50/push-eax +11621 # var i/eax: int = n +11622 8b/-> *(ebp+0xc) 0/r32/eax +11623 { +11624 # if (i <= 0) break +11625 3d/compare-eax-with 0/imm32 +11626 7e/jump-if-<= break/disp8 +11627 (write-buffered *(ebp+8) " ") +11628 48/decrement-eax +11629 eb/jump loop/disp8 +11630 } +11631 $emit-indent:end: +11632 # . restore registers +11633 58/pop-to-eax +11634 # . epilogue +11635 89/<- %esp 5/r32/ebp +11636 5d/pop-to-ebp +11637 c3/return +11638 +11639 emit-subx-prologue: # out: (addr buffered-file) +11640 # . prologue +11641 55/push-ebp +11642 89/<- %ebp 4/r32/esp +11643 # +11644 (write-buffered *(ebp+8) " # . prologue\n") +11645 (write-buffered *(ebp+8) " 55/push-ebp\n") +11646 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +11647 $emit-subx-prologue:end: +11648 # . epilogue +11649 89/<- %esp 5/r32/ebp +11650 5d/pop-to-ebp +11651 c3/return +11652 +11653 emit-subx-epilogue: # out: (addr buffered-file) +11654 # . prologue +11655 55/push-ebp +11656 89/<- %ebp 4/r32/esp +11657 # +11658 (write-buffered *(ebp+8) " # . epilogue\n") +11659 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +11660 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +11661 (write-buffered *(ebp+8) " c3/return\n") +11662 $emit-subx-epilogue:end: +11663 # . epilogue +11664 89/<- %esp 5/r32/ebp +11665 5d/pop-to-ebp +11666 c3/return -- cgit 1.4.1-2-gfad0