From 114641e2c81805bd99a5713237af3fb16d7ddc10 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 14 Mar 2020 14:46:45 -0700 Subject: 6145 - 'address' operator This could be a can of worms, but I think I have a set of checks that will keep use of addresses type-safe. --- apps/mu | Bin 197345 -> 199082 bytes apps/mu.subx | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mu_instructions | 5 ++++ mu_summary | 8 ++++-- 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/apps/mu b/apps/mu index a59c7674..2497b2ad 100755 Binary files a/apps/mu and b/apps/mu differ diff --git a/apps/mu.subx b/apps/mu.subx index 8160c540..8250ddd1 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -2258,6 +2258,52 @@ test-convert-function-with-local-array-var-in-mem: 5d/pop-to-ebp c3/return +test-convert-address: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-input-stream) + (clear-stream $_test-input-buffered-file->buffer) + (clear-stream _test-output-stream) + (clear-stream $_test-output-buffered-file->buffer) + # + (write _test-input-stream "fn foo {\n") + (write _test-input-stream " var a: int\n") + (write _test-input-stream " var b/eax: (addr int) <- address a\n") + (write _test-input-stream "}\n") + # convert + (convert-mu _test-input-buffered-file _test-output-buffered-file) + (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 "foo:" "F - test-convert-address/0") + (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-address/1") + (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-address/2") + (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-address/3") + (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-address/4") + (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-address/5") + (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-address/6") + (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-address/7") + (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-address/8") + (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-address/9") + (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-address/10") + (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-address/11") + (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-address/12") + (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-address/13") + (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-address/14") + (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-address/15") + (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-address/16") + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + test-convert-length-of-array: # . prologue 55/push-ebp @@ -8769,6 +8815,19 @@ _Primitive-copy-lit-to-mem: 2/imm32/imm32-is-first-inout 0/imm32/no-disp32 1/imm32/output-is-write-only + _Primitive-address/imm32/next +# - address +_Primitive-address: + # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 + "address"/imm32/name + Single-int-var-in-mem/imm32/inouts + Single-addr-var-in-some-register/imm32/outputs + "8d/copy-address"/imm32/subx-name + 1/imm32/rm32-is-first-inout + 3/imm32/r32-is-first-output + 0/imm32/no-imm32 + 0/imm32/no-disp32 + 1/imm32/output-is-write-only _Primitive-compare-mem-with-reg/imm32/next # - compare _Primitive-compare-mem-with-reg: @@ -9366,6 +9425,10 @@ Single-int-var-in-some-register: Int-var-in-some-register/imm32 0/imm32/next +Single-addr-var-in-some-register: + Addr-var-in-some-register/imm32 + 0/imm32/next + Int-var-in-some-register: "arg1"/imm32/name Type-int/imm32 @@ -9373,6 +9436,13 @@ Int-var-in-some-register: 0/imm32/no-stack-offset Any-register/imm32 +Addr-var-in-some-register: + "arg1"/imm32/name + Type-addr/imm32 + 1/imm32/some-block-depth + 0/imm32/no-stack-offset + Any-register/imm32 + Single-int-var-in-eax: Int-var-in-eax/imm32 0/imm32/next @@ -9458,6 +9528,10 @@ Type-literal: 0/imm32/left/literal 0/imm32/right/null +Type-addr: + 2/imm32/left/addr + 0/imm32/right/null + == code emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) # . prologue diff --git a/mu_instructions b/mu_instructions index a66ea67e..430a4651 100644 --- a/mu_instructions +++ b/mu_instructions @@ -205,6 +205,11 @@ loop-if-addr<= label {.name="loop-if-addr<=", .inouts=[label], loop-if-addr>= {.name="loop-if-addr>=", .subx-name="0f 83/jump-if-addr>= loop/disp32"} loop-if-addr>= label {.name="loop-if-addr>=", .inouts=[label], .subx-name="0f 83/jump-if-addr>=", .disp32=inouts[0] ":loop"} +Address operations + +var/reg: (addr T) <- address var: T + {.name="address", .inouts=[var], .outputs=[reg], .subx-name="8d/copy-address", .rm32="*(ebp+" inouts[0].stack-offset ")", .r32=outputs[0]} + Array operations var/reg <- length arr/reg2: (addr array T) diff --git a/mu_summary b/mu_summary index 7ecea2b1..d098d28f 100644 --- a/mu_summary +++ b/mu_summary @@ -195,6 +195,10 @@ Similarly, conditional loops: loop-if-addr>= loop-if-addr>= label +## Address operations + + var/reg: (addr T) <- address var: T # var must be in mem (on the stack) + ## Array operations var/reg: int <- length arr/reg: (addr array T) @@ -203,8 +207,8 @@ Similarly, conditional loops: var/reg: (addr T) <- index arr/reg: (addr array T), n var/reg: (addr T) <- index arr: (array T sz), n - var/reg: (offset T) <- compute-offset arr: (addr array T), idx/reg: int # arr can be in reg or mem - var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int # arr can be in reg or mem + var/reg: (offset T) <- compute-offset arr: (addr array T), idx/reg: int # arr can be in reg or mem + var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int # arr can be in reg or mem var/reg: (addr T) <- index arr/reg: (addr array T), idx/reg: (offset T) ## User-defined types -- cgit 1.4.1-2-gfad0