From dd6c5fff9edaf95c2c3393fc76ea276e4939a7c6 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 18 Nov 2019 17:29:50 -0800 Subject: 5755 Support function calls with literal arguments. --- apps/mu | Bin 52125 -> 52483 bytes apps/mu.subx | 66 ++ html/apps/mu.subx.html | 1855 +++++++++++++++++++++++++----------------------- 3 files changed, 1024 insertions(+), 897 deletions(-) diff --git a/apps/mu b/apps/mu index 6a2e1953..e337b555 100755 Binary files a/apps/mu and b/apps/mu differ diff --git a/apps/mu.subx b/apps/mu.subx index 8e10c7dc..9f4daec1 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -1237,6 +1237,14 @@ $emit-subx-call-operand:stack: (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset (write-buffered *(ebp+8) ")") } + # else if (operand->type == literal) emit "__" + { + 81 7/subop/compare *(eax+4) 0/imm32 # Var-type + 75/jump-if-not-equal break/disp8 +$emit-subx-call-operand:literal: + (write-buffered *(ebp+8) Space) + (write-buffered *(ebp+8) *eax) + } $emit-subx-call-operand:end: # . restore registers 58/pop-to-eax @@ -2159,6 +2167,64 @@ test-emit-subx-statement-function-call: 5d/pop-to-ebp c3/return +test-emit-subx-statement-function-call-with-literal-arg: + # Call a function on a literal. + # f 34 + # => + # (f2 34) + # + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-output-stream) + (clear-stream _test-output-buffered-file->buffer) + # var-foo/ecx : literal + 68/push 0/imm32/no-register + 68/push 0/imm32/no-stack-offset + 68/push 0/imm32/block-depth + 68/push 0/imm32/type-literal + 68/push "34"/imm32 + 89/<- %ecx 4/r32/esp + # vars/edx = (stack 1) + 51/push-ecx/var-foo + 68/push 1/imm32/data-length + 68/push 1/imm32/top + 89/<- %edx 4/r32/esp + # operands/esi : (list var) + 68/push 0/imm32/next + 51/push-ecx/var-foo + 89/<- %esi 4/r32/esp + # stmt/esi : statement + 68/push 0/imm32/next + 68/push 0/imm32/outputs + 56/push-esi/inouts + 68/push "f"/imm32/operation + 89/<- %esi 4/r32/esp + # functions/ebx : function + 68/push 0/imm32/next + 68/push 0/imm32/body + 68/push 0/imm32/outputs + 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call + 68/push "f2"/imm32/subx-name + 68/push "f"/imm32/name + 89/<- %ebx 4/r32/esp + # convert + (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) + (flush _test-output-buffered-file) +#? # dump _test-output-stream {{{ +#? (write 2 "^") +#? (write-stream 2 _test-output-stream) +#? (write 2 "$\n") +#? (rewind-stream _test-output-stream) +#? # }}} + # check output + (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + emit-subx-prologue: # out : (address buffered-file) # . prologue 55/push-ebp diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index a68c3c7c..fc4f81bf 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -912,9 +912,9 @@ if ('onhashchange' in window) { 870 # 871 (write-buffered %edi *ecx) 872 (write-buffered %edi ":\n") - 873 (emit-subx-prologue %edi) + 873 (emit-subx-prologue %edi) 874 (emit-subx-block %edi *(ecx+0x10)) # Function-body - 875 (emit-subx-epilogue %edi) + 875 (emit-subx-epilogue %edi) 876 $emit-subx-function:end: 877 # . restore registers 878 5f/pop-to-edi @@ -946,7 +946,7 @@ if ('onhashchange' in window) { 904 # if stmt matches a primitive, emit it 905 { 906 $emit-subx-statement:primitive: - 907 (find-matching-primitive *(ebp+0x14) *(ebp+0xc)) # primitives, stmt => curr/eax + 907 (find-matching-primitive *(ebp+0x14) *(ebp+0xc)) # primitives, stmt => curr/eax 908 3d/compare-eax-and 0/imm32 909 74/jump-if-equal break/disp8 910 (emit-subx-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr @@ -955,7 +955,7 @@ if ('onhashchange' in window) { 913 # else if stmt matches a function, emit a call to it 914 { 915 $emit-subx-statement:call: - 916 (find-matching-function *(ebp+0x18) *(ebp+0xc)) # functions, stmt => curr/eax + 916 (find-matching-function *(ebp+0x18) *(ebp+0xc)) # functions, stmt => curr/eax 917 3d/compare-eax-and 0/imm32 918 74/jump-if-equal break/disp8 919 (emit-subx-call *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr @@ -1279,911 +1279,972 @@ if ('onhashchange' in window) { 1237 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset 1238 (write-buffered *(ebp+8) ")") 1239 } -1240 $emit-subx-call-operand:end: -1241 # . restore registers -1242 58/pop-to-eax -1243 # . epilogue -1244 89/<- %esp 5/r32/ebp -1245 5d/pop-to-ebp -1246 c3/return -1247 -1248 find-matching-function: # functions : (address function), stmt : (address statement) -> result/eax : (address function) -1249 # . prologue -1250 55/push-ebp -1251 89/<- %ebp 4/r32/esp -1252 # . save registers -1253 51/push-ecx -1254 # var curr/ecx : (address function) = functions -1255 8b/-> *(ebp+8) 1/r32/ecx -1256 { -1257 # if (curr == null) break -1258 81 7/subop/compare %ecx 0/imm32 -1259 74/jump-if-equal break/disp8 -1260 # if match(curr, stmt) return curr -1261 { -1262 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -1263 3d/compare-eax-and 0/imm32 -1264 74/jump-if-equal break/disp8 -1265 89/<- %eax 1/r32/ecx -1266 eb/jump $find-matching-function:end/disp8 -1267 } -1268 # curr = curr->next -1269 8b/-> *(ecx+0x10) 1/r32/ecx # Function-next -1270 eb/jump loop/disp8 -1271 } -1272 # return null -1273 b8/copy-to-eax 0/imm32 -1274 $find-matching-function:end: -1275 # . restore registers -1276 59/pop-to-ecx -1277 # . epilogue -1278 89/<- %esp 5/r32/ebp -1279 5d/pop-to-ebp -1280 c3/return -1281 -1282 find-matching-primitive: # primitives : (address primitive), stmt : (address statement) -> result/eax : (address primitive) -1283 # . prologue -1284 55/push-ebp -1285 89/<- %ebp 4/r32/esp -1286 # . save registers -1287 51/push-ecx -1288 # var curr/ecx : (address primitive) = primitives -1289 8b/-> *(ebp+8) 1/r32/ecx -1290 { -1291 $find-matching-primitive:loop: -1292 # if (curr == null) break -1293 81 7/subop/compare %ecx 0/imm32 -1294 74/jump-if-equal break/disp8 -1295 # if match(curr, stmt) return curr -1296 { -1297 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -1298 3d/compare-eax-and 0/imm32 -1299 74/jump-if-equal break/disp8 -1300 89/<- %eax 1/r32/ecx -1301 eb/jump $find-matching-function:end/disp8 -1302 } -1303 $find-matching-primitive:next-primitive: -1304 # curr = curr->next -1305 8b/-> *(ecx+0x1c) 1/r32/ecx # Primitive-next -1306 eb/jump loop/disp8 -1307 } -1308 # return null -1309 b8/copy-to-eax 0/imm32 -1310 $find-matching-primitive:end: -1311 # . restore registers -1312 59/pop-to-ecx -1313 # . epilogue -1314 89/<- %esp 5/r32/ebp -1315 5d/pop-to-ebp -1316 c3/return -1317 -1318 mu-stmt-matches-function?: # stmt : (address statement), function : (address opcode-info) => result/eax : boolean -1319 # . prologue -1320 55/push-ebp -1321 89/<- %ebp 4/r32/esp -1322 # . save registers -1323 51/push-ecx -1324 # return primitive->name == stmt->operation -1325 8b/-> *(ebp+8) 1/r32/ecx -1326 8b/-> *(ebp+0xc) 0/r32/eax -1327 (string-equal? *ecx *eax) # => eax -1328 $mu-stmt-matches-function?:end: -1329 # . restore registers -1330 59/pop-to-ecx -1331 # . epilogue -1332 89/<- %esp 5/r32/ebp -1333 5d/pop-to-ebp -1334 c3/return -1335 -1336 mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean -1337 # A mu stmt matches a primitive if the name matches, all the inout vars -1338 # match, and all the output vars match. -1339 # Vars match if types match and registers match. -1340 # In addition, a stmt output matches a primitive's output if types match -1341 # and the primitive has a wildcard register. -1342 # . prologue -1343 55/push-ebp -1344 89/<- %ebp 4/r32/esp -1345 # . save registers -1346 51/push-ecx -1347 52/push-edx -1348 53/push-ebx -1349 56/push-esi -1350 57/push-edi -1351 # ecx = stmt -1352 8b/-> *(ebp+8) 1/r32/ecx -1353 # edx = primitive -1354 8b/-> *(ebp+0xc) 2/r32/edx -1355 { -1356 $mu-stmt-matches-primitive?:check-name: -1357 # if (primitive->name != stmt->operation) return false -1358 (string-equal? *ecx *edx) # => eax -1359 3d/compare-eax-and 0/imm32 -1360 75/jump-if-not-equal break/disp8 -1361 b8/copy-to-eax 0/imm32 -1362 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1363 } -1364 $mu-stmt-matches-primitive?:check-inouts: -1365 # curr = stmt->inouts -1366 8b/-> *(ecx+4) 6/r32/esi # Stmt-inouts -1367 # curr2 = primitive->inouts -1368 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -1369 { -1370 # if (curr == 0) return (curr2 == 0) -1371 { -1372 81 7/subop/compare %esi 0/imm32 -1373 75/jump-if-not-equal break/disp8 -1374 { -1375 81 7/subop/compare %edi 0/imm32 -1376 75/jump-if-not-equal break/disp8 -1377 # return true -1378 b8/copy-to-eax 1/imm32 -1379 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1380 } -1381 # return false -1382 b8/copy-to-eax 0/imm32 -1383 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1384 } -1385 # if (curr2 == 0) return false -1386 { -1387 81 7/subop/compare %edi 0/imm32 -1388 75/jump-if-not-equal break/disp8 -1389 b8/copy-to-eax 0/imm32 -1390 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1391 } -1392 # if (curr != curr2) return false -1393 { -1394 (operand-matches-primitive? *esi *edi) # => eax -1395 3d/compare-eax-and 0/imm32 +1240 # else if (operand->type == literal) emit "__" +1241 { +1242 81 7/subop/compare *(eax+4) 0/imm32 # Var-type +1243 75/jump-if-not-equal break/disp8 +1244 $emit-subx-call-operand:literal: +1245 (write-buffered *(ebp+8) Space) +1246 (write-buffered *(ebp+8) *eax) +1247 } +1248 $emit-subx-call-operand:end: +1249 # . restore registers +1250 58/pop-to-eax +1251 # . epilogue +1252 89/<- %esp 5/r32/ebp +1253 5d/pop-to-ebp +1254 c3/return +1255 +1256 find-matching-function: # functions : (address function), stmt : (address statement) -> result/eax : (address function) +1257 # . prologue +1258 55/push-ebp +1259 89/<- %ebp 4/r32/esp +1260 # . save registers +1261 51/push-ecx +1262 # var curr/ecx : (address function) = functions +1263 8b/-> *(ebp+8) 1/r32/ecx +1264 { +1265 # if (curr == null) break +1266 81 7/subop/compare %ecx 0/imm32 +1267 74/jump-if-equal break/disp8 +1268 # if match(curr, stmt) return curr +1269 { +1270 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +1271 3d/compare-eax-and 0/imm32 +1272 74/jump-if-equal break/disp8 +1273 89/<- %eax 1/r32/ecx +1274 eb/jump $find-matching-function:end/disp8 +1275 } +1276 # curr = curr->next +1277 8b/-> *(ecx+0x10) 1/r32/ecx # Function-next +1278 eb/jump loop/disp8 +1279 } +1280 # return null +1281 b8/copy-to-eax 0/imm32 +1282 $find-matching-function:end: +1283 # . restore registers +1284 59/pop-to-ecx +1285 # . epilogue +1286 89/<- %esp 5/r32/ebp +1287 5d/pop-to-ebp +1288 c3/return +1289 +1290 find-matching-primitive: # primitives : (address primitive), stmt : (address statement) -> result/eax : (address primitive) +1291 # . prologue +1292 55/push-ebp +1293 89/<- %ebp 4/r32/esp +1294 # . save registers +1295 51/push-ecx +1296 # var curr/ecx : (address primitive) = primitives +1297 8b/-> *(ebp+8) 1/r32/ecx +1298 { +1299 $find-matching-primitive:loop: +1300 # if (curr == null) break +1301 81 7/subop/compare %ecx 0/imm32 +1302 74/jump-if-equal break/disp8 +1303 # if match(curr, stmt) return curr +1304 { +1305 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +1306 3d/compare-eax-and 0/imm32 +1307 74/jump-if-equal break/disp8 +1308 89/<- %eax 1/r32/ecx +1309 eb/jump $find-matching-function:end/disp8 +1310 } +1311 $find-matching-primitive:next-primitive: +1312 # curr = curr->next +1313 8b/-> *(ecx+0x1c) 1/r32/ecx # Primitive-next +1314 eb/jump loop/disp8 +1315 } +1316 # return null +1317 b8/copy-to-eax 0/imm32 +1318 $find-matching-primitive:end: +1319 # . restore registers +1320 59/pop-to-ecx +1321 # . epilogue +1322 89/<- %esp 5/r32/ebp +1323 5d/pop-to-ebp +1324 c3/return +1325 +1326 mu-stmt-matches-function?: # stmt : (address statement), function : (address opcode-info) => result/eax : boolean +1327 # . prologue +1328 55/push-ebp +1329 89/<- %ebp 4/r32/esp +1330 # . save registers +1331 51/push-ecx +1332 # return primitive->name == stmt->operation +1333 8b/-> *(ebp+8) 1/r32/ecx +1334 8b/-> *(ebp+0xc) 0/r32/eax +1335 (string-equal? *ecx *eax) # => eax +1336 $mu-stmt-matches-function?:end: +1337 # . restore registers +1338 59/pop-to-ecx +1339 # . epilogue +1340 89/<- %esp 5/r32/ebp +1341 5d/pop-to-ebp +1342 c3/return +1343 +1344 mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean +1345 # A mu stmt matches a primitive if the name matches, all the inout vars +1346 # match, and all the output vars match. +1347 # Vars match if types match and registers match. +1348 # In addition, a stmt output matches a primitive's output if types match +1349 # and the primitive has a wildcard register. +1350 # . prologue +1351 55/push-ebp +1352 89/<- %ebp 4/r32/esp +1353 # . save registers +1354 51/push-ecx +1355 52/push-edx +1356 53/push-ebx +1357 56/push-esi +1358 57/push-edi +1359 # ecx = stmt +1360 8b/-> *(ebp+8) 1/r32/ecx +1361 # edx = primitive +1362 8b/-> *(ebp+0xc) 2/r32/edx +1363 { +1364 $mu-stmt-matches-primitive?:check-name: +1365 # if (primitive->name != stmt->operation) return false +1366 (string-equal? *ecx *edx) # => eax +1367 3d/compare-eax-and 0/imm32 +1368 75/jump-if-not-equal break/disp8 +1369 b8/copy-to-eax 0/imm32 +1370 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1371 } +1372 $mu-stmt-matches-primitive?:check-inouts: +1373 # curr = stmt->inouts +1374 8b/-> *(ecx+4) 6/r32/esi # Stmt-inouts +1375 # curr2 = primitive->inouts +1376 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +1377 { +1378 # if (curr == 0) return (curr2 == 0) +1379 { +1380 81 7/subop/compare %esi 0/imm32 +1381 75/jump-if-not-equal break/disp8 +1382 { +1383 81 7/subop/compare %edi 0/imm32 +1384 75/jump-if-not-equal break/disp8 +1385 # return true +1386 b8/copy-to-eax 1/imm32 +1387 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1388 } +1389 # return false +1390 b8/copy-to-eax 0/imm32 +1391 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1392 } +1393 # if (curr2 == 0) return false +1394 { +1395 81 7/subop/compare %edi 0/imm32 1396 75/jump-if-not-equal break/disp8 1397 b8/copy-to-eax 0/imm32 1398 e9/jump $mu-stmt-matches-primitive?:end/disp32 1399 } -1400 # curr=curr->next -1401 8b/-> *(ecx+4) 1/r32/ecx # Operand-next -1402 # curr2=curr2->next -1403 8b/-> *(edx+4) 2/r32/edx # Operand-next -1404 } -1405 $mu-stmt-matches-primitive?:check-outputs: -1406 # ecx = stmt -1407 8b/-> *(ebp+8) 1/r32/ecx -1408 # edx = primitive -1409 8b/-> *(ebp+0xc) 2/r32/edx -1410 # curr = stmt->outputs -1411 8b/-> *(ecx+8) 6/r32/esi # Stmt-outputs -1412 # curr2 = primitive->outputs -1413 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -1414 { -1415 # if (curr == 0) return (curr2 == 0) -1416 { -1417 81 7/subop/compare %esi 0/imm32 -1418 75/jump-if-not-equal break/disp8 -1419 { -1420 81 7/subop/compare %edi 0/imm32 -1421 75/jump-if-not-equal break/disp8 -1422 # return true -1423 b8/copy-to-eax 1/imm32 -1424 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1425 } -1426 # return false -1427 b8/copy-to-eax 0/imm32 -1428 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1429 } -1430 # if (curr2 == 0) return false -1431 { -1432 81 7/subop/compare %edi 0/imm32 -1433 75/jump-if-not-equal break/disp8 -1434 b8/copy-to-eax 0/imm32 -1435 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1436 } -1437 # if (curr != curr2) return false -1438 { -1439 (operand-matches-primitive? *esi *edi) # => eax -1440 3d/compare-eax-and 0/imm32 +1400 # if (curr != curr2) return false +1401 { +1402 (operand-matches-primitive? *esi *edi) # => eax +1403 3d/compare-eax-and 0/imm32 +1404 75/jump-if-not-equal break/disp8 +1405 b8/copy-to-eax 0/imm32 +1406 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1407 } +1408 # curr=curr->next +1409 8b/-> *(ecx+4) 1/r32/ecx # Operand-next +1410 # curr2=curr2->next +1411 8b/-> *(edx+4) 2/r32/edx # Operand-next +1412 } +1413 $mu-stmt-matches-primitive?:check-outputs: +1414 # ecx = stmt +1415 8b/-> *(ebp+8) 1/r32/ecx +1416 # edx = primitive +1417 8b/-> *(ebp+0xc) 2/r32/edx +1418 # curr = stmt->outputs +1419 8b/-> *(ecx+8) 6/r32/esi # Stmt-outputs +1420 # curr2 = primitive->outputs +1421 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +1422 { +1423 # if (curr == 0) return (curr2 == 0) +1424 { +1425 81 7/subop/compare %esi 0/imm32 +1426 75/jump-if-not-equal break/disp8 +1427 { +1428 81 7/subop/compare %edi 0/imm32 +1429 75/jump-if-not-equal break/disp8 +1430 # return true +1431 b8/copy-to-eax 1/imm32 +1432 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1433 } +1434 # return false +1435 b8/copy-to-eax 0/imm32 +1436 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1437 } +1438 # if (curr2 == 0) return false +1439 { +1440 81 7/subop/compare %edi 0/imm32 1441 75/jump-if-not-equal break/disp8 1442 b8/copy-to-eax 0/imm32 1443 e9/jump $mu-stmt-matches-primitive?:end/disp32 1444 } -1445 # curr=curr->next -1446 8b/-> *(ecx+4) 1/r32/ecx # Operand-next -1447 # curr2=curr2->next -1448 8b/-> *(edx+4) 2/r32/edx # Operand-next -1449 } -1450 $mu-stmt-matches-primitive?:return-true: -1451 b8/copy-to-eax 1/imm32 -1452 $mu-stmt-matches-primitive?:end: -1453 # . restore registers -1454 5f/pop-to-edi -1455 5e/pop-to-esi -1456 5b/pop-to-ebx -1457 5a/pop-to-edx -1458 59/pop-to-ecx -1459 # . epilogue -1460 89/<- %esp 5/r32/ebp -1461 5d/pop-to-ebp -1462 c3/return -1463 -1464 operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean -1465 # . prologue -1466 55/push-ebp -1467 89/<- %ebp 4/r32/esp -1468 # . save registers -1469 56/push-esi -1470 57/push-edi -1471 # esi = var -1472 8b/-> *(ebp+8) 6/r32/esi -1473 # edi = primout-var -1474 8b/-> *(ebp+0xc) 7/r32/edi -1475 # if (var->type != primout-var->type) return false -1476 # TODO -1477 # return false if var->register doesn't match primout-var->register -1478 { -1479 # if addresses are equal, don't return here -1480 8b/-> *(esi+0x10) 0/r32/eax -1481 39/compare *(edi+0x10) 0/r32/eax -1482 74/jump-if-equal break/disp8 -1483 # if either address is 0, return false -1484 3d/compare-eax-and 0/imm32 -1485 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -1486 81 7/subop/compare *(edi+0x10) 0/imm32 -1487 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -1488 # if primout-var->register is "*", return true -1489 (string-equal? *(edi+0x10) "*") # Var-register -1490 3d/compare-eax-and 0/imm32 -1491 b8/copy-to-eax 1/imm32/true -1492 75/jump-if-not-equal $operand-matches-primitive?:end/disp8 -1493 # if string contents don't match, return false -1494 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -1495 3d/compare-eax-and 0/imm32 -1496 b8/copy-to-eax 0/imm32/false -1497 74/jump-if-equal $operand-matches-primitive?:end/disp8 -1498 } -1499 # return true -1500 b8/copy-to-eax 1/imm32/true -1501 $operand-matches-primitive?:end: -1502 # . restore registers -1503 5f/pop-to-edi -1504 5e/pop-to-esi -1505 # . epilogue -1506 89/<- %esp 5/r32/ebp -1507 5d/pop-to-ebp -1508 c3/return -1509 -1510 test-emit-subx-statement-primitive: -1511 # Primitive operation on a variable on the stack. -1512 # increment foo -1513 # => -1514 # ff 0/subop/increment *(ebp-8) -1515 # -1516 # There's a variable on the var stack as follows: -1517 # name: 'foo' -1518 # type: int -1519 # stack-offset: -8 -1520 # -1521 # There's a primitive with this info: -1522 # name: 'increment' -1523 # inouts: int/mem -1524 # value: 'ff 0/subop/increment' -1525 # -1526 # There's nothing in functions. -1527 # -1528 # . prologue -1529 55/push-ebp -1530 89/<- %ebp 4/r32/esp -1531 # setup -1532 (clear-stream _test-output-stream) -1533 (clear-stream _test-output-buffered-file->buffer) -1534 # var-foo/ecx : var -1535 68/push 0/imm32/no-register -1536 68/push -8/imm32/stack-offset -1537 68/push 1/imm32/block-depth -1538 68/push 1/imm32/type-int -1539 68/push "foo"/imm32 -1540 89/<- %ecx 4/r32/esp -1541 #? $aa-var-in-ecx: -1542 # vars/edx : (stack 1) -1543 51/push-ecx/var-foo -1544 68/push 1/imm32/data-length -1545 68/push 1/imm32/top -1546 89/<- %edx 4/r32/esp -1547 #? $aa-vars-in-edx: -1548 # operand/ebx : (list var) -1549 68/push 0/imm32/next -1550 51/push-ecx/var-foo -1551 89/<- %ebx 4/r32/esp -1552 #? $aa-stmt-operand-in-ebx: -1553 # stmt/esi : statement -1554 68/push 0/imm32/next -1555 68/push 0/imm32/outputs -1556 53/push-ebx/operands -1557 68/push "increment"/imm32/operation -1558 89/<- %esi 4/r32/esp -1559 #? $aa-stmt-in-esi: -1560 # primitives/ebx : primitive -1561 68/push 0/imm32/next -1562 68/push 0/imm32/no-imm32 -1563 68/push 0/imm32/no-r32 -1564 68/push 1/imm32/rm32-is-first-inout -1565 68/push "ff 0/subop/increment"/imm32/subx-name -1566 68/push 0/imm32/outputs -1567 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -1568 68/push "increment"/imm32/name -1569 89/<- %ebx 4/r32/esp -1570 $aa-primitive-in-ebx: -1571 # convert -1572 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1573 (flush _test-output-buffered-file) -1574 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1580 # check output -1581 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -1582 # . epilogue -1583 89/<- %esp 5/r32/ebp -1584 5d/pop-to-ebp -1585 c3/return -1586 -1587 test-emit-subx-statement-primitive-register: -1588 # Primitive operation on a variable in a register. -1589 # foo <- increment -1590 # => -1591 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1592 # -1593 # There's a variable on the var stack as follows: -1594 # name: 'foo' -1595 # type: int -1596 # register: 'eax' -1597 # -1598 # There's a primitive with this info: -1599 # name: 'increment' -1600 # out: int/reg -1601 # value: 'ff 0/subop/increment' -1602 # -1603 # There's nothing in functions. -1604 # -1605 # . prologue -1606 55/push-ebp -1607 89/<- %ebp 4/r32/esp -1608 # setup -1609 (clear-stream _test-output-stream) -1610 (clear-stream _test-output-buffered-file->buffer) -1611 # var-foo/ecx : var in eax -1612 68/push "eax"/imm32/register -1613 68/push 0/imm32/no-stack-offset -1614 68/push 1/imm32/block-depth -1615 68/push 1/imm32/type-int -1616 68/push "foo"/imm32 -1617 89/<- %ecx 4/r32/esp -1618 # vars/edx : (stack 1) -1619 51/push-ecx/var-foo -1620 68/push 1/imm32/data-length -1621 68/push 1/imm32/top -1622 89/<- %edx 4/r32/esp -1623 # operand/ebx : (list var) -1624 68/push 0/imm32/next -1625 51/push-ecx/var-foo -1626 89/<- %ebx 4/r32/esp -1627 # stmt/esi : statement -1628 68/push 0/imm32/next -1629 53/push-ebx/outputs -1630 68/push 0/imm32/inouts -1631 68/push "increment"/imm32/operation -1632 89/<- %esi 4/r32/esp -1633 # formal-var/ebx : var in any register -1634 68/push Any-register/imm32 -1635 68/push 0/imm32/no-stack-offset -1636 68/push 1/imm32/block-depth -1637 68/push 1/imm32/type-int -1638 68/push "dummy"/imm32 -1639 89/<- %ebx 4/r32/esp -1640 # operand/ebx : (list var) -1641 68/push 0/imm32/next -1642 53/push-ebx/formal-var -1643 89/<- %ebx 4/r32/esp -1644 # primitives/ebx : primitive -1645 68/push 0/imm32/next -1646 68/push 0/imm32/no-imm32 -1647 68/push 0/imm32/no-r32 -1648 68/push 3/imm32/rm32-in-first-output -1649 68/push "ff 0/subop/increment"/imm32/subx-name -1650 53/push-ebx/outputs -1651 68/push 0/imm32/inouts -1652 68/push "increment"/imm32/name -1653 89/<- %ebx 4/r32/esp -1654 # convert -1655 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1656 (flush _test-output-buffered-file) -1657 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1663 # check output -1664 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -1665 # . epilogue -1666 89/<- %esp 5/r32/ebp -1667 5d/pop-to-ebp -1668 c3/return -1669 -1670 test-emit-subx-statement-select-primitive: -1671 # Select the right primitive between overloads. -1672 # foo <- increment -1673 # => -1674 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1675 # -1676 # There's a variable on the var stack as follows: -1677 # name: 'foo' -1678 # type: int -1679 # register: 'eax' -1680 # -1681 # There's two primitives, as follows: -1682 # - name: 'increment' -1683 # out: int/reg -1684 # value: 'ff 0/subop/increment' -1685 # - name: 'increment' -1686 # inout: int/mem -1687 # value: 'ff 0/subop/increment' +1445 # if (curr != curr2) return false +1446 { +1447 (operand-matches-primitive? *esi *edi) # => eax +1448 3d/compare-eax-and 0/imm32 +1449 75/jump-if-not-equal break/disp8 +1450 b8/copy-to-eax 0/imm32 +1451 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1452 } +1453 # curr=curr->next +1454 8b/-> *(ecx+4) 1/r32/ecx # Operand-next +1455 # curr2=curr2->next +1456 8b/-> *(edx+4) 2/r32/edx # Operand-next +1457 } +1458 $mu-stmt-matches-primitive?:return-true: +1459 b8/copy-to-eax 1/imm32 +1460 $mu-stmt-matches-primitive?:end: +1461 # . restore registers +1462 5f/pop-to-edi +1463 5e/pop-to-esi +1464 5b/pop-to-ebx +1465 5a/pop-to-edx +1466 59/pop-to-ecx +1467 # . epilogue +1468 89/<- %esp 5/r32/ebp +1469 5d/pop-to-ebp +1470 c3/return +1471 +1472 operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean +1473 # . prologue +1474 55/push-ebp +1475 89/<- %ebp 4/r32/esp +1476 # . save registers +1477 56/push-esi +1478 57/push-edi +1479 # esi = var +1480 8b/-> *(ebp+8) 6/r32/esi +1481 # edi = primout-var +1482 8b/-> *(ebp+0xc) 7/r32/edi +1483 # if (var->type != primout-var->type) return false +1484 # TODO +1485 # return false if var->register doesn't match primout-var->register +1486 { +1487 # if addresses are equal, don't return here +1488 8b/-> *(esi+0x10) 0/r32/eax +1489 39/compare *(edi+0x10) 0/r32/eax +1490 74/jump-if-equal break/disp8 +1491 # if either address is 0, return false +1492 3d/compare-eax-and 0/imm32 +1493 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +1494 81 7/subop/compare *(edi+0x10) 0/imm32 +1495 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +1496 # if primout-var->register is "*", return true +1497 (string-equal? *(edi+0x10) "*") # Var-register +1498 3d/compare-eax-and 0/imm32 +1499 b8/copy-to-eax 1/imm32/true +1500 75/jump-if-not-equal $operand-matches-primitive?:end/disp8 +1501 # if string contents don't match, return false +1502 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register +1503 3d/compare-eax-and 0/imm32 +1504 b8/copy-to-eax 0/imm32/false +1505 74/jump-if-equal $operand-matches-primitive?:end/disp8 +1506 } +1507 # return true +1508 b8/copy-to-eax 1/imm32/true +1509 $operand-matches-primitive?:end: +1510 # . restore registers +1511 5f/pop-to-edi +1512 5e/pop-to-esi +1513 # . epilogue +1514 89/<- %esp 5/r32/ebp +1515 5d/pop-to-ebp +1516 c3/return +1517 +1518 test-emit-subx-statement-primitive: +1519 # Primitive operation on a variable on the stack. +1520 # increment foo +1521 # => +1522 # ff 0/subop/increment *(ebp-8) +1523 # +1524 # There's a variable on the var stack as follows: +1525 # name: 'foo' +1526 # type: int +1527 # stack-offset: -8 +1528 # +1529 # There's a primitive with this info: +1530 # name: 'increment' +1531 # inouts: int/mem +1532 # value: 'ff 0/subop/increment' +1533 # +1534 # There's nothing in functions. +1535 # +1536 # . prologue +1537 55/push-ebp +1538 89/<- %ebp 4/r32/esp +1539 # setup +1540 (clear-stream _test-output-stream) +1541 (clear-stream _test-output-buffered-file->buffer) +1542 # var-foo/ecx : var +1543 68/push 0/imm32/no-register +1544 68/push -8/imm32/stack-offset +1545 68/push 1/imm32/block-depth +1546 68/push 1/imm32/type-int +1547 68/push "foo"/imm32 +1548 89/<- %ecx 4/r32/esp +1549 #? $aa-var-in-ecx: +1550 # vars/edx : (stack 1) +1551 51/push-ecx/var-foo +1552 68/push 1/imm32/data-length +1553 68/push 1/imm32/top +1554 89/<- %edx 4/r32/esp +1555 #? $aa-vars-in-edx: +1556 # operand/ebx : (list var) +1557 68/push 0/imm32/next +1558 51/push-ecx/var-foo +1559 89/<- %ebx 4/r32/esp +1560 #? $aa-stmt-operand-in-ebx: +1561 # stmt/esi : statement +1562 68/push 0/imm32/next +1563 68/push 0/imm32/outputs +1564 53/push-ebx/operands +1565 68/push "increment"/imm32/operation +1566 89/<- %esi 4/r32/esp +1567 #? $aa-stmt-in-esi: +1568 # primitives/ebx : primitive +1569 68/push 0/imm32/next +1570 68/push 0/imm32/no-imm32 +1571 68/push 0/imm32/no-r32 +1572 68/push 1/imm32/rm32-is-first-inout +1573 68/push "ff 0/subop/increment"/imm32/subx-name +1574 68/push 0/imm32/outputs +1575 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +1576 68/push "increment"/imm32/name +1577 89/<- %ebx 4/r32/esp +1578 $aa-primitive-in-ebx: +1579 # convert +1580 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1581 (flush _test-output-buffered-file) +1582 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1588 # check output +1589 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") +1590 # . epilogue +1591 89/<- %esp 5/r32/ebp +1592 5d/pop-to-ebp +1593 c3/return +1594 +1595 test-emit-subx-statement-primitive-register: +1596 # Primitive operation on a variable in a register. +1597 # foo <- increment +1598 # => +1599 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1600 # +1601 # There's a variable on the var stack as follows: +1602 # name: 'foo' +1603 # type: int +1604 # register: 'eax' +1605 # +1606 # There's a primitive with this info: +1607 # name: 'increment' +1608 # out: int/reg +1609 # value: 'ff 0/subop/increment' +1610 # +1611 # There's nothing in functions. +1612 # +1613 # . prologue +1614 55/push-ebp +1615 89/<- %ebp 4/r32/esp +1616 # setup +1617 (clear-stream _test-output-stream) +1618 (clear-stream _test-output-buffered-file->buffer) +1619 # var-foo/ecx : var in eax +1620 68/push "eax"/imm32/register +1621 68/push 0/imm32/no-stack-offset +1622 68/push 1/imm32/block-depth +1623 68/push 1/imm32/type-int +1624 68/push "foo"/imm32 +1625 89/<- %ecx 4/r32/esp +1626 # vars/edx : (stack 1) +1627 51/push-ecx/var-foo +1628 68/push 1/imm32/data-length +1629 68/push 1/imm32/top +1630 89/<- %edx 4/r32/esp +1631 # operand/ebx : (list var) +1632 68/push 0/imm32/next +1633 51/push-ecx/var-foo +1634 89/<- %ebx 4/r32/esp +1635 # stmt/esi : statement +1636 68/push 0/imm32/next +1637 53/push-ebx/outputs +1638 68/push 0/imm32/inouts +1639 68/push "increment"/imm32/operation +1640 89/<- %esi 4/r32/esp +1641 # formal-var/ebx : var in any register +1642 68/push Any-register/imm32 +1643 68/push 0/imm32/no-stack-offset +1644 68/push 1/imm32/block-depth +1645 68/push 1/imm32/type-int +1646 68/push "dummy"/imm32 +1647 89/<- %ebx 4/r32/esp +1648 # operand/ebx : (list var) +1649 68/push 0/imm32/next +1650 53/push-ebx/formal-var +1651 89/<- %ebx 4/r32/esp +1652 # primitives/ebx : primitive +1653 68/push 0/imm32/next +1654 68/push 0/imm32/no-imm32 +1655 68/push 0/imm32/no-r32 +1656 68/push 3/imm32/rm32-in-first-output +1657 68/push "ff 0/subop/increment"/imm32/subx-name +1658 53/push-ebx/outputs +1659 68/push 0/imm32/inouts +1660 68/push "increment"/imm32/name +1661 89/<- %ebx 4/r32/esp +1662 # convert +1663 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1664 (flush _test-output-buffered-file) +1665 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1671 # check output +1672 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") +1673 # . epilogue +1674 89/<- %esp 5/r32/ebp +1675 5d/pop-to-ebp +1676 c3/return +1677 +1678 test-emit-subx-statement-select-primitive: +1679 # Select the right primitive between overloads. +1680 # foo <- increment +1681 # => +1682 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1683 # +1684 # There's a variable on the var stack as follows: +1685 # name: 'foo' +1686 # type: int +1687 # register: 'eax' 1688 # -1689 # There's nothing in functions. -1690 # -1691 # . prologue -1692 55/push-ebp -1693 89/<- %ebp 4/r32/esp -1694 # setup -1695 (clear-stream _test-output-stream) -1696 (clear-stream _test-output-buffered-file->buffer) -1697 # var-foo/ecx : var in eax -1698 68/push "eax"/imm32/register -1699 68/push 0/imm32/no-stack-offset -1700 68/push 1/imm32/block-depth -1701 68/push 1/imm32/type-int -1702 68/push "foo"/imm32 -1703 89/<- %ecx 4/r32/esp -1704 # vars/edx : (stack 1) -1705 51/push-ecx/var-foo -1706 68/push 1/imm32/data-length -1707 68/push 1/imm32/top -1708 89/<- %edx 4/r32/esp -1709 # real-outputs/edi : (list var) -1710 68/push 0/imm32/next -1711 51/push-ecx/var-foo -1712 89/<- %edi 4/r32/esp -1713 # stmt/esi : statement -1714 68/push 0/imm32/next -1715 57/push-edi/outputs -1716 68/push 0/imm32/inouts -1717 68/push "increment"/imm32/operation -1718 89/<- %esi 4/r32/esp -1719 # formal-var/ebx : var in any register -1720 68/push Any-register/imm32 -1721 68/push 0/imm32/no-stack-offset -1722 68/push 1/imm32/block-depth -1723 68/push 1/imm32/type-int -1724 68/push "dummy"/imm32 -1725 89/<- %ebx 4/r32/esp -1726 # formal-outputs/ebx : (list var) -1727 68/push 0/imm32/next -1728 53/push-ebx/formal-var -1729 89/<- %ebx 4/r32/esp -1730 # primitive1/ebx : primitive -1731 68/push 0/imm32/next -1732 68/push 0/imm32/no-imm32 -1733 68/push 0/imm32/no-r32 -1734 68/push 3/imm32/rm32-in-first-output -1735 68/push "ff 0/subop/increment"/imm32/subx-name -1736 53/push-ebx/outputs/formal-outputs -1737 68/push 0/imm32/inouts -1738 68/push "increment"/imm32/name -1739 89/<- %ebx 4/r32/esp -1740 # primitives/ebx : primitive -1741 53/push-ebx/next -1742 68/push 0/imm32/no-imm32 -1743 68/push 0/imm32/no-r32 -1744 68/push 1/imm32/rm32-is-first-inout -1745 68/push "ff 0/subop/increment"/imm32/subx-name -1746 68/push 0/imm32/outputs -1747 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -1748 68/push "increment"/imm32/name -1749 89/<- %ebx 4/r32/esp -1750 # convert -1751 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1752 (flush _test-output-buffered-file) -1753 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1759 # check output -1760 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -1761 # . epilogue -1762 89/<- %esp 5/r32/ebp -1763 5d/pop-to-ebp -1764 c3/return -1765 -1766 test-emit-subx-statement-select-primitive-2: -1767 # Select the right primitive between overloads. -1768 # foo <- increment -1769 # => -1770 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1771 # -1772 # There's a variable on the var stack as follows: -1773 # name: 'foo' -1774 # type: int -1775 # register: 'eax' -1776 # -1777 # There's two primitives, as follows: -1778 # - name: 'increment' -1779 # out: int/reg -1780 # value: 'ff 0/subop/increment' -1781 # - name: 'increment' -1782 # inout: int/mem -1783 # value: 'ff 0/subop/increment' +1689 # There's two primitives, as follows: +1690 # - name: 'increment' +1691 # out: int/reg +1692 # value: 'ff 0/subop/increment' +1693 # - name: 'increment' +1694 # inout: int/mem +1695 # value: 'ff 0/subop/increment' +1696 # +1697 # There's nothing in functions. +1698 # +1699 # . prologue +1700 55/push-ebp +1701 89/<- %ebp 4/r32/esp +1702 # setup +1703 (clear-stream _test-output-stream) +1704 (clear-stream _test-output-buffered-file->buffer) +1705 # var-foo/ecx : var in eax +1706 68/push "eax"/imm32/register +1707 68/push 0/imm32/no-stack-offset +1708 68/push 1/imm32/block-depth +1709 68/push 1/imm32/type-int +1710 68/push "foo"/imm32 +1711 89/<- %ecx 4/r32/esp +1712 # vars/edx : (stack 1) +1713 51/push-ecx/var-foo +1714 68/push 1/imm32/data-length +1715 68/push 1/imm32/top +1716 89/<- %edx 4/r32/esp +1717 # real-outputs/edi : (list var) +1718 68/push 0/imm32/next +1719 51/push-ecx/var-foo +1720 89/<- %edi 4/r32/esp +1721 # stmt/esi : statement +1722 68/push 0/imm32/next +1723 57/push-edi/outputs +1724 68/push 0/imm32/inouts +1725 68/push "increment"/imm32/operation +1726 89/<- %esi 4/r32/esp +1727 # formal-var/ebx : var in any register +1728 68/push Any-register/imm32 +1729 68/push 0/imm32/no-stack-offset +1730 68/push 1/imm32/block-depth +1731 68/push 1/imm32/type-int +1732 68/push "dummy"/imm32 +1733 89/<- %ebx 4/r32/esp +1734 # formal-outputs/ebx : (list var) +1735 68/push 0/imm32/next +1736 53/push-ebx/formal-var +1737 89/<- %ebx 4/r32/esp +1738 # primitive1/ebx : primitive +1739 68/push 0/imm32/next +1740 68/push 0/imm32/no-imm32 +1741 68/push 0/imm32/no-r32 +1742 68/push 3/imm32/rm32-in-first-output +1743 68/push "ff 0/subop/increment"/imm32/subx-name +1744 53/push-ebx/outputs/formal-outputs +1745 68/push 0/imm32/inouts +1746 68/push "increment"/imm32/name +1747 89/<- %ebx 4/r32/esp +1748 # primitives/ebx : primitive +1749 53/push-ebx/next +1750 68/push 0/imm32/no-imm32 +1751 68/push 0/imm32/no-r32 +1752 68/push 1/imm32/rm32-is-first-inout +1753 68/push "ff 0/subop/increment"/imm32/subx-name +1754 68/push 0/imm32/outputs +1755 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +1756 68/push "increment"/imm32/name +1757 89/<- %ebx 4/r32/esp +1758 # convert +1759 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1760 (flush _test-output-buffered-file) +1761 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1767 # check output +1768 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") +1769 # . epilogue +1770 89/<- %esp 5/r32/ebp +1771 5d/pop-to-ebp +1772 c3/return +1773 +1774 test-emit-subx-statement-select-primitive-2: +1775 # Select the right primitive between overloads. +1776 # foo <- increment +1777 # => +1778 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1779 # +1780 # There's a variable on the var stack as follows: +1781 # name: 'foo' +1782 # type: int +1783 # register: 'eax' 1784 # -1785 # There's nothing in functions. -1786 # -1787 # . prologue -1788 55/push-ebp -1789 89/<- %ebp 4/r32/esp -1790 # setup -1791 (clear-stream _test-output-stream) -1792 (clear-stream _test-output-buffered-file->buffer) -1793 # var-foo/ecx : var in eax -1794 68/push "eax"/imm32/register -1795 68/push 0/imm32/no-stack-offset -1796 68/push 1/imm32/block-depth -1797 68/push 1/imm32/type-int -1798 68/push "foo"/imm32 -1799 89/<- %ecx 4/r32/esp -1800 # vars/edx : (stack 1) -1801 51/push-ecx/var-foo -1802 68/push 1/imm32/data-length -1803 68/push 1/imm32/top -1804 89/<- %edx 4/r32/esp -1805 # inouts/edi : (list var) -1806 68/push 0/imm32/next -1807 51/push-ecx/var-foo -1808 89/<- %edi 4/r32/esp -1809 # stmt/esi : statement -1810 68/push 0/imm32/next -1811 68/push 0/imm32/outputs -1812 57/push-edi/inouts -1813 68/push "increment"/imm32/operation -1814 89/<- %esi 4/r32/esp -1815 # formal-var/ebx : var in any register -1816 68/push Any-register/imm32 -1817 68/push 0/imm32/no-stack-offset -1818 68/push 1/imm32/block-depth -1819 68/push 1/imm32/type-int -1820 68/push "dummy"/imm32 -1821 89/<- %ebx 4/r32/esp -1822 # operand/ebx : (list var) -1823 68/push 0/imm32/next -1824 53/push-ebx/formal-var -1825 89/<- %ebx 4/r32/esp -1826 # primitive1/ebx : primitive -1827 68/push 0/imm32/next -1828 68/push 0/imm32/no-imm32 -1829 68/push 0/imm32/no-r32 -1830 68/push 3/imm32/rm32-in-first-output -1831 68/push "ff 0/subop/increment"/imm32/subx-name -1832 53/push-ebx/outputs/formal-outputs -1833 68/push 0/imm32/inouts -1834 68/push "increment"/imm32/name -1835 89/<- %ebx 4/r32/esp -1836 # primitives/ebx : primitive -1837 53/push-ebx/next -1838 68/push 0/imm32/no-imm32 -1839 68/push 0/imm32/no-r32 -1840 68/push 1/imm32/rm32-is-first-inout -1841 68/push "ff 0/subop/increment"/imm32/subx-name -1842 68/push 0/imm32/outputs -1843 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -1844 68/push "increment"/imm32/name -1845 89/<- %ebx 4/r32/esp -1846 # convert -1847 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1848 (flush _test-output-buffered-file) -1849 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1855 # check output -1856 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -1857 # . epilogue -1858 89/<- %esp 5/r32/ebp -1859 5d/pop-to-ebp -1860 c3/return -1861 -1862 test-increment-register: -1863 # Select the right primitive between overloads. -1864 # foo <- increment -1865 # => -1866 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1867 # -1868 # There's a variable on the var stack as follows: -1869 # name: 'foo' -1870 # type: int -1871 # register: 'eax' -1872 # -1873 # Primitives are the global definitions. -1874 # -1875 # There are no functions defined. -1876 # -1877 # . prologue -1878 55/push-ebp -1879 89/<- %ebp 4/r32/esp -1880 # setup -1881 (clear-stream _test-output-stream) -1882 (clear-stream _test-output-buffered-file->buffer) -1883 # var-foo/ecx : var in eax -1884 68/push "eax"/imm32/register -1885 68/push 0/imm32/no-stack-offset -1886 68/push 1/imm32/block-depth -1887 68/push 1/imm32/type-int -1888 68/push "foo"/imm32 -1889 89/<- %ecx 4/r32/esp -1890 # vars/edx : (stack 1) -1891 51/push-ecx/var-foo -1892 68/push 1/imm32/data-length -1893 68/push 1/imm32/top -1894 89/<- %edx 4/r32/esp -1895 # real-outputs/edi : (list var) -1896 68/push 0/imm32/next -1897 51/push-ecx/var-foo -1898 89/<- %edi 4/r32/esp -1899 # stmt/esi : statement -1900 68/push 0/imm32/next -1901 57/push-edi/outputs -1902 68/push 0/imm32/inouts -1903 68/push "increment"/imm32/operation -1904 89/<- %esi 4/r32/esp -1905 # convert -1906 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) -1907 (flush _test-output-buffered-file) -1908 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1914 # check output -1915 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-register") -1916 # . epilogue -1917 89/<- %esp 5/r32/ebp -1918 5d/pop-to-ebp -1919 c3/return -1920 -1921 test-increment-var: -1922 # Select the right primitive between overloads. -1923 # foo <- increment -1924 # => -1925 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1926 # -1927 # There's a variable on the var stack as follows: -1928 # name: 'foo' -1929 # type: int -1930 # register: 'eax' -1931 # -1932 # Primitives are the global definitions. -1933 # -1934 # There are no functions defined. -1935 # -1936 # . prologue -1937 55/push-ebp -1938 89/<- %ebp 4/r32/esp -1939 # setup -1940 (clear-stream _test-output-stream) -1941 (clear-stream _test-output-buffered-file->buffer) -1942 # var-foo/ecx : var in eax -1943 68/push "eax"/imm32/register -1944 68/push 0/imm32/no-stack-offset -1945 68/push 1/imm32/block-depth -1946 68/push 1/imm32/type-int -1947 68/push "foo"/imm32 -1948 89/<- %ecx 4/r32/esp -1949 # vars/edx : (stack 1) -1950 51/push-ecx/var-foo -1951 68/push 1/imm32/data-length -1952 68/push 1/imm32/top -1953 89/<- %edx 4/r32/esp -1954 # inouts/edi : (list var) -1955 68/push 0/imm32/next -1956 51/push-ecx/var-foo -1957 89/<- %edi 4/r32/esp -1958 # stmt/esi : statement -1959 68/push 0/imm32/next -1960 68/push 0/imm32/outputs -1961 57/push-edi/inouts -1962 68/push "increment"/imm32/operation -1963 89/<- %esi 4/r32/esp -1964 # convert -1965 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) -1966 (flush _test-output-buffered-file) -1967 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1973 # check output -1974 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") -1975 # . epilogue -1976 89/<- %esp 5/r32/ebp -1977 5d/pop-to-ebp -1978 c3/return -1979 -1980 test-add-reg-to-reg: -1981 # var1/reg <- add var2/reg -1982 # => -1983 # 01 %var1 var2 -1984 # -1985 # . prologue -1986 55/push-ebp -1987 89/<- %ebp 4/r32/esp -1988 # setup -1989 (clear-stream _test-output-stream) -1990 (clear-stream _test-output-buffered-file->buffer) -1991 # var-var1/ecx : var in eax -1992 68/push "eax"/imm32/register -1993 68/push 0/imm32/no-stack-offset -1994 68/push 1/imm32/block-depth -1995 68/push 1/imm32/type-int -1996 68/push "var1"/imm32 -1997 89/<- %ecx 4/r32/esp -1998 # var-var2/edx : var in ecx -1999 68/push "ecx"/imm32/register -2000 68/push 0/imm32/no-stack-offset -2001 68/push 1/imm32/block-depth -2002 68/push 1/imm32/type-int -2003 68/push "var2"/imm32 -2004 89/<- %edx 4/r32/esp -2005 # inouts/esi : (list var2) -2006 68/push 0/imm32/next -2007 52/push-edx/var-var2 -2008 89/<- %esi 4/r32/esp -2009 # outputs/edi : (list var1) -2010 68/push 0/imm32/next -2011 51/push-ecx/var-var1 -2012 89/<- %edi 4/r32/esp -2013 # stmt/esi : statement +1785 # There's two primitives, as follows: +1786 # - name: 'increment' +1787 # out: int/reg +1788 # value: 'ff 0/subop/increment' +1789 # - name: 'increment' +1790 # inout: int/mem +1791 # value: 'ff 0/subop/increment' +1792 # +1793 # There's nothing in functions. +1794 # +1795 # . prologue +1796 55/push-ebp +1797 89/<- %ebp 4/r32/esp +1798 # setup +1799 (clear-stream _test-output-stream) +1800 (clear-stream _test-output-buffered-file->buffer) +1801 # var-foo/ecx : var in eax +1802 68/push "eax"/imm32/register +1803 68/push 0/imm32/no-stack-offset +1804 68/push 1/imm32/block-depth +1805 68/push 1/imm32/type-int +1806 68/push "foo"/imm32 +1807 89/<- %ecx 4/r32/esp +1808 # vars/edx : (stack 1) +1809 51/push-ecx/var-foo +1810 68/push 1/imm32/data-length +1811 68/push 1/imm32/top +1812 89/<- %edx 4/r32/esp +1813 # inouts/edi : (list var) +1814 68/push 0/imm32/next +1815 51/push-ecx/var-foo +1816 89/<- %edi 4/r32/esp +1817 # stmt/esi : statement +1818 68/push 0/imm32/next +1819 68/push 0/imm32/outputs +1820 57/push-edi/inouts +1821 68/push "increment"/imm32/operation +1822 89/<- %esi 4/r32/esp +1823 # formal-var/ebx : var in any register +1824 68/push Any-register/imm32 +1825 68/push 0/imm32/no-stack-offset +1826 68/push 1/imm32/block-depth +1827 68/push 1/imm32/type-int +1828 68/push "dummy"/imm32 +1829 89/<- %ebx 4/r32/esp +1830 # operand/ebx : (list var) +1831 68/push 0/imm32/next +1832 53/push-ebx/formal-var +1833 89/<- %ebx 4/r32/esp +1834 # primitive1/ebx : primitive +1835 68/push 0/imm32/next +1836 68/push 0/imm32/no-imm32 +1837 68/push 0/imm32/no-r32 +1838 68/push 3/imm32/rm32-in-first-output +1839 68/push "ff 0/subop/increment"/imm32/subx-name +1840 53/push-ebx/outputs/formal-outputs +1841 68/push 0/imm32/inouts +1842 68/push "increment"/imm32/name +1843 89/<- %ebx 4/r32/esp +1844 # primitives/ebx : primitive +1845 53/push-ebx/next +1846 68/push 0/imm32/no-imm32 +1847 68/push 0/imm32/no-r32 +1848 68/push 1/imm32/rm32-is-first-inout +1849 68/push "ff 0/subop/increment"/imm32/subx-name +1850 68/push 0/imm32/outputs +1851 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +1852 68/push "increment"/imm32/name +1853 89/<- %ebx 4/r32/esp +1854 # convert +1855 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1856 (flush _test-output-buffered-file) +1857 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1863 # check output +1864 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") +1865 # . epilogue +1866 89/<- %esp 5/r32/ebp +1867 5d/pop-to-ebp +1868 c3/return +1869 +1870 test-increment-register: +1871 # Select the right primitive between overloads. +1872 # foo <- increment +1873 # => +1874 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1875 # +1876 # There's a variable on the var stack as follows: +1877 # name: 'foo' +1878 # type: int +1879 # register: 'eax' +1880 # +1881 # Primitives are the global definitions. +1882 # +1883 # There are no functions defined. +1884 # +1885 # . prologue +1886 55/push-ebp +1887 89/<- %ebp 4/r32/esp +1888 # setup +1889 (clear-stream _test-output-stream) +1890 (clear-stream _test-output-buffered-file->buffer) +1891 # var-foo/ecx : var in eax +1892 68/push "eax"/imm32/register +1893 68/push 0/imm32/no-stack-offset +1894 68/push 1/imm32/block-depth +1895 68/push 1/imm32/type-int +1896 68/push "foo"/imm32 +1897 89/<- %ecx 4/r32/esp +1898 # vars/edx : (stack 1) +1899 51/push-ecx/var-foo +1900 68/push 1/imm32/data-length +1901 68/push 1/imm32/top +1902 89/<- %edx 4/r32/esp +1903 # real-outputs/edi : (list var) +1904 68/push 0/imm32/next +1905 51/push-ecx/var-foo +1906 89/<- %edi 4/r32/esp +1907 # stmt/esi : statement +1908 68/push 0/imm32/next +1909 57/push-edi/outputs +1910 68/push 0/imm32/inouts +1911 68/push "increment"/imm32/operation +1912 89/<- %esi 4/r32/esp +1913 # convert +1914 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) +1915 (flush _test-output-buffered-file) +1916 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1922 # check output +1923 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-register") +1924 # . epilogue +1925 89/<- %esp 5/r32/ebp +1926 5d/pop-to-ebp +1927 c3/return +1928 +1929 test-increment-var: +1930 # Select the right primitive between overloads. +1931 # foo <- increment +1932 # => +1933 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1934 # +1935 # There's a variable on the var stack as follows: +1936 # name: 'foo' +1937 # type: int +1938 # register: 'eax' +1939 # +1940 # Primitives are the global definitions. +1941 # +1942 # There are no functions defined. +1943 # +1944 # . prologue +1945 55/push-ebp +1946 89/<- %ebp 4/r32/esp +1947 # setup +1948 (clear-stream _test-output-stream) +1949 (clear-stream _test-output-buffered-file->buffer) +1950 # var-foo/ecx : var in eax +1951 68/push "eax"/imm32/register +1952 68/push 0/imm32/no-stack-offset +1953 68/push 1/imm32/block-depth +1954 68/push 1/imm32/type-int +1955 68/push "foo"/imm32 +1956 89/<- %ecx 4/r32/esp +1957 # vars/edx : (stack 1) +1958 51/push-ecx/var-foo +1959 68/push 1/imm32/data-length +1960 68/push 1/imm32/top +1961 89/<- %edx 4/r32/esp +1962 # inouts/edi : (list var) +1963 68/push 0/imm32/next +1964 51/push-ecx/var-foo +1965 89/<- %edi 4/r32/esp +1966 # stmt/esi : statement +1967 68/push 0/imm32/next +1968 68/push 0/imm32/outputs +1969 57/push-edi/inouts +1970 68/push "increment"/imm32/operation +1971 89/<- %esi 4/r32/esp +1972 # convert +1973 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) +1974 (flush _test-output-buffered-file) +1975 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1981 # check output +1982 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var") +1983 # . epilogue +1984 89/<- %esp 5/r32/ebp +1985 5d/pop-to-ebp +1986 c3/return +1987 +1988 test-add-reg-to-reg: +1989 # var1/reg <- add var2/reg +1990 # => +1991 # 01 %var1 var2 +1992 # +1993 # . prologue +1994 55/push-ebp +1995 89/<- %ebp 4/r32/esp +1996 # setup +1997 (clear-stream _test-output-stream) +1998 (clear-stream _test-output-buffered-file->buffer) +1999 # var-var1/ecx : var in eax +2000 68/push "eax"/imm32/register +2001 68/push 0/imm32/no-stack-offset +2002 68/push 1/imm32/block-depth +2003 68/push 1/imm32/type-int +2004 68/push "var1"/imm32 +2005 89/<- %ecx 4/r32/esp +2006 # var-var2/edx : var in ecx +2007 68/push "ecx"/imm32/register +2008 68/push 0/imm32/no-stack-offset +2009 68/push 1/imm32/block-depth +2010 68/push 1/imm32/type-int +2011 68/push "var2"/imm32 +2012 89/<- %edx 4/r32/esp +2013 # inouts/esi : (list var2) 2014 68/push 0/imm32/next -2015 57/push-edi/outputs -2016 56/push-esi/inouts -2017 68/push "add"/imm32/operation -2018 89/<- %esi 4/r32/esp -2019 # convert -2020 (emit-subx-statement _test-output-buffered-file %esi 0 Primitives 0) -2021 (flush _test-output-buffered-file) -2022 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -2028 # check output -2029 (check-next-stream-line-equal _test-output-stream "01 %eax 0x00000001/r32" "F - test-add-reg-to-reg") -2030 # . epilogue -2031 89/<- %esp 5/r32/ebp -2032 5d/pop-to-ebp -2033 c3/return -2034 -2035 test-add-literal-to-reg: -2036 # var1/eax <- add 0x34 -2037 # => -2038 # 81 0/subop/add %eax 0x34/imm32 -2039 # -2040 # . prologue -2041 55/push-ebp -2042 89/<- %ebp 4/r32/esp -2043 # setup -2044 (clear-stream _test-output-stream) -2045 (clear-stream _test-output-buffered-file->buffer) -2046 # var-var1/ecx : var in eax -2047 68/push "eax"/imm32/register -2048 68/push 0/imm32/no-stack-offset -2049 68/push 1/imm32/block-depth -2050 68/push 1/imm32/type-int -2051 68/push "var1"/imm32 -2052 89/<- %ecx 4/r32/esp -2053 # var-var2/edx : var literal -2054 68/push 0/imm32/no-register -2055 68/push 0/imm32/no-stack-offset -2056 68/push 1/imm32/block-depth -2057 68/push 0/imm32/type-literal -2058 68/push "0x34"/imm32 -2059 89/<- %edx 4/r32/esp -2060 # inouts/esi : (list var2) -2061 68/push 0/imm32/next -2062 52/push-edx/var-var2 -2063 89/<- %esi 4/r32/esp -2064 # outputs/edi : (list var1) -2065 68/push 0/imm32/next -2066 51/push-ecx/var-var1 -2067 89/<- %edi 4/r32/esp -2068 # stmt/esi : statement +2015 52/push-edx/var-var2 +2016 89/<- %esi 4/r32/esp +2017 # outputs/edi : (list var1) +2018 68/push 0/imm32/next +2019 51/push-ecx/var-var1 +2020 89/<- %edi 4/r32/esp +2021 # stmt/esi : statement +2022 68/push 0/imm32/next +2023 57/push-edi/outputs +2024 56/push-esi/inouts +2025 68/push "add"/imm32/operation +2026 89/<- %esi 4/r32/esp +2027 # convert +2028 (emit-subx-statement _test-output-buffered-file %esi 0 Primitives 0) +2029 (flush _test-output-buffered-file) +2030 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +2036 # check output +2037 (check-next-stream-line-equal _test-output-stream "01 %eax 0x00000001/r32" "F - test-add-reg-to-reg") +2038 # . epilogue +2039 89/<- %esp 5/r32/ebp +2040 5d/pop-to-ebp +2041 c3/return +2042 +2043 test-add-literal-to-reg: +2044 # var1/eax <- add 0x34 +2045 # => +2046 # 81 0/subop/add %eax 0x34/imm32 +2047 # +2048 # . prologue +2049 55/push-ebp +2050 89/<- %ebp 4/r32/esp +2051 # setup +2052 (clear-stream _test-output-stream) +2053 (clear-stream _test-output-buffered-file->buffer) +2054 # var-var1/ecx : var in eax +2055 68/push "eax"/imm32/register +2056 68/push 0/imm32/no-stack-offset +2057 68/push 1/imm32/block-depth +2058 68/push 1/imm32/type-int +2059 68/push "var1"/imm32 +2060 89/<- %ecx 4/r32/esp +2061 # var-var2/edx : var literal +2062 68/push 0/imm32/no-register +2063 68/push 0/imm32/no-stack-offset +2064 68/push 1/imm32/block-depth +2065 68/push 0/imm32/type-literal +2066 68/push "0x34"/imm32 +2067 89/<- %edx 4/r32/esp +2068 # inouts/esi : (list var2) 2069 68/push 0/imm32/next -2070 57/push-edi/outputs -2071 56/push-esi/inouts -2072 68/push "add"/imm32/operation -2073 89/<- %esi 4/r32/esp -2074 # convert -2075 (emit-subx-statement _test-output-buffered-file %esi 0 Primitives 0) -2076 (flush _test-output-buffered-file) -2077 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -2083 # check output -2084 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %eax 0x34/imm32" "F - test-add-literal-to-reg") -2085 # . epilogue -2086 89/<- %esp 5/r32/ebp -2087 5d/pop-to-ebp -2088 c3/return -2089 -2090 test-emit-subx-statement-function-call: -2091 # Call a function on a variable on the stack. -2092 # f foo -2093 # => -2094 # (f2 *(ebp-8)) -2095 # (Changing the function name supports overloading in general, but here it -2096 # just serves to help disambiguate things.) -2097 # -2098 # There's a variable on the var stack as follows: -2099 # name: 'foo' -2100 # type: int -2101 # stack-offset: -8 -2102 # -2103 # There's nothing in primitives. -2104 # -2105 # There's a function with this info: -2106 # name: 'f' -2107 # inout: int/mem -2108 # value: 'f2' -2109 # -2110 # . prologue -2111 55/push-ebp -2112 89/<- %ebp 4/r32/esp -2113 # setup -2114 (clear-stream _test-output-stream) -2115 (clear-stream _test-output-buffered-file->buffer) -2116 # var-foo/ecx : var -2117 68/push 0/imm32/no-register -2118 68/push -8/imm32/stack-offset -2119 68/push 0/imm32/block-depth -2120 68/push 1/imm32/type-int -2121 68/push "foo"/imm32 -2122 89/<- %ecx 4/r32/esp -2123 # vars/edx = (stack 1) -2124 51/push-ecx/var-foo -2125 68/push 1/imm32/data-length -2126 68/push 1/imm32/top -2127 89/<- %edx 4/r32/esp -2128 # operands/esi : (list var) -2129 68/push 0/imm32/next -2130 51/push-ecx/var-foo -2131 89/<- %esi 4/r32/esp -2132 # stmt/esi : statement -2133 68/push 0/imm32/next -2134 68/push 0/imm32/outputs -2135 56/push-esi/inouts -2136 68/push "f"/imm32/operation -2137 89/<- %esi 4/r32/esp -2138 # functions/ebx : function -2139 68/push 0/imm32/next -2140 68/push 0/imm32/body -2141 68/push 0/imm32/outputs -2142 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -2143 68/push "f2"/imm32/subx-name -2144 68/push "f"/imm32/name -2145 89/<- %ebx 4/r32/esp -2146 # convert -2147 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) -2148 (flush _test-output-buffered-file) -2149 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -2155 # check output -2156 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -2157 # . epilogue -2158 89/<- %esp 5/r32/ebp -2159 5d/pop-to-ebp -2160 c3/return -2161 -2162 emit-subx-prologue: # out : (address buffered-file) -2163 # . prologue -2164 55/push-ebp -2165 89/<- %ebp 4/r32/esp -2166 # -2167 (write-buffered *(ebp+8) "# . prologue\n") -2168 (write-buffered *(ebp+8) "55/push-ebp\n") -2169 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") -2170 $emit-subx-prologue:end: -2171 # . epilogue -2172 89/<- %esp 5/r32/ebp -2173 5d/pop-to-ebp -2174 c3/return -2175 -2176 emit-subx-epilogue: # out : (address buffered-file) -2177 # . prologue -2178 55/push-ebp -2179 89/<- %ebp 4/r32/esp -2180 # -2181 (write-buffered *(ebp+8) "# . epilogue\n") -2182 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") -2183 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") -2184 (write-buffered *(ebp+8) "c3/return\n") -2185 $emit-subx-epilogue:end: -2186 # . epilogue -2187 89/<- %esp 5/r32/ebp -2188 5d/pop-to-ebp -2189 c3/return +2070 52/push-edx/var-var2 +2071 89/<- %esi 4/r32/esp +2072 # outputs/edi : (list var1) +2073 68/push 0/imm32/next +2074 51/push-ecx/var-var1 +2075 89/<- %edi 4/r32/esp +2076 # stmt/esi : statement +2077 68/push 0/imm32/next +2078 57/push-edi/outputs +2079 56/push-esi/inouts +2080 68/push "add"/imm32/operation +2081 89/<- %esi 4/r32/esp +2082 # convert +2083 (emit-subx-statement _test-output-buffered-file %esi 0 Primitives 0) +2084 (flush _test-output-buffered-file) +2085 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +2091 # check output +2092 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %eax 0x34/imm32" "F - test-add-literal-to-reg") +2093 # . epilogue +2094 89/<- %esp 5/r32/ebp +2095 5d/pop-to-ebp +2096 c3/return +2097 +2098 test-emit-subx-statement-function-call: +2099 # Call a function on a variable on the stack. +2100 # f foo +2101 # => +2102 # (f2 *(ebp-8)) +2103 # (Changing the function name supports overloading in general, but here it +2104 # just serves to help disambiguate things.) +2105 # +2106 # There's a variable on the var stack as follows: +2107 # name: 'foo' +2108 # type: int +2109 # stack-offset: -8 +2110 # +2111 # There's nothing in primitives. +2112 # +2113 # There's a function with this info: +2114 # name: 'f' +2115 # inout: int/mem +2116 # value: 'f2' +2117 # +2118 # . prologue +2119 55/push-ebp +2120 89/<- %ebp 4/r32/esp +2121 # setup +2122 (clear-stream _test-output-stream) +2123 (clear-stream _test-output-buffered-file->buffer) +2124 # var-foo/ecx : var +2125 68/push 0/imm32/no-register +2126 68/push -8/imm32/stack-offset +2127 68/push 0/imm32/block-depth +2128 68/push 1/imm32/type-int +2129 68/push "foo"/imm32 +2130 89/<- %ecx 4/r32/esp +2131 # vars/edx = (stack 1) +2132 51/push-ecx/var-foo +2133 68/push 1/imm32/data-length +2134 68/push 1/imm32/top +2135 89/<- %edx 4/r32/esp +2136 # operands/esi : (list var) +2137 68/push 0/imm32/next +2138 51/push-ecx/var-foo +2139 89/<- %esi 4/r32/esp +2140 # stmt/esi : statement +2141 68/push 0/imm32/next +2142 68/push 0/imm32/outputs +2143 56/push-esi/inouts +2144 68/push "f"/imm32/operation +2145 89/<- %esi 4/r32/esp +2146 # functions/ebx : function +2147 68/push 0/imm32/next +2148 68/push 0/imm32/body +2149 68/push 0/imm32/outputs +2150 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +2151 68/push "f2"/imm32/subx-name +2152 68/push "f"/imm32/name +2153 89/<- %ebx 4/r32/esp +2154 # convert +2155 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) +2156 (flush _test-output-buffered-file) +2157 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +2163 # check output +2164 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") +2165 # . epilogue +2166 89/<- %esp 5/r32/ebp +2167 5d/pop-to-ebp +2168 c3/return +2169 +2170 test-emit-subx-statement-function-call-with-literal-arg: +2171 # Call a function on a literal. +2172 # f 34 +2173 # => +2174 # (f2 34) +2175 # +2176 # . prologue +2177 55/push-ebp +2178 89/<- %ebp 4/r32/esp +2179 # setup +2180 (clear-stream _test-output-stream) +2181 (clear-stream _test-output-buffered-file->buffer) +2182 # var-foo/ecx : literal +2183 68/push 0/imm32/no-register +2184 68/push 0/imm32/no-stack-offset +2185 68/push 0/imm32/block-depth +2186 68/push 0/imm32/type-literal +2187 68/push "34"/imm32 +2188 89/<- %ecx 4/r32/esp +2189 # vars/edx = (stack 1) +2190 51/push-ecx/var-foo +2191 68/push 1/imm32/data-length +2192 68/push 1/imm32/top +2193 89/<- %edx 4/r32/esp +2194 # operands/esi : (list var) +2195 68/push 0/imm32/next +2196 51/push-ecx/var-foo +2197 89/<- %esi 4/r32/esp +2198 # stmt/esi : statement +2199 68/push 0/imm32/next +2200 68/push 0/imm32/outputs +2201 56/push-esi/inouts +2202 68/push "f"/imm32/operation +2203 89/<- %esi 4/r32/esp +2204 # functions/ebx : function +2205 68/push 0/imm32/next +2206 68/push 0/imm32/body +2207 68/push 0/imm32/outputs +2208 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +2209 68/push "f2"/imm32/subx-name +2210 68/push "f"/imm32/name +2211 89/<- %ebx 4/r32/esp +2212 # convert +2213 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) +2214 (flush _test-output-buffered-file) +2215 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +2221 # check output +2222 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") +2223 # . epilogue +2224 89/<- %esp 5/r32/ebp +2225 5d/pop-to-ebp +2226 c3/return +2227 +2228 emit-subx-prologue: # out : (address buffered-file) +2229 # . prologue +2230 55/push-ebp +2231 89/<- %ebp 4/r32/esp +2232 # +2233 (write-buffered *(ebp+8) "# . prologue\n") +2234 (write-buffered *(ebp+8) "55/push-ebp\n") +2235 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") +2236 $emit-subx-prologue:end: +2237 # . epilogue +2238 89/<- %esp 5/r32/ebp +2239 5d/pop-to-ebp +2240 c3/return +2241 +2242 emit-subx-epilogue: # out : (address buffered-file) +2243 # . prologue +2244 55/push-ebp +2245 89/<- %ebp 4/r32/esp +2246 # +2247 (write-buffered *(ebp+8) "# . epilogue\n") +2248 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") +2249 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") +2250 (write-buffered *(ebp+8) "c3/return\n") +2251 $emit-subx-epilogue:end: +2252 # . epilogue +2253 89/<- %esp 5/r32/ebp +2254 5d/pop-to-ebp +2255 c3/return -- cgit 1.4.1-2-gfad0