about summary refs log tree commit diff stats
path: root/subx/apps/handle.subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx/apps/handle.subx')
-rw-r--r--subx/apps/handle.subx412
1 files changed, 0 insertions, 412 deletions
diff --git a/subx/apps/handle.subx b/subx/apps/handle.subx
deleted file mode 100644
index ba824f85..00000000
--- a/subx/apps/handle.subx
+++ /dev/null
@@ -1,412 +0,0 @@
-# A sketch of Mu-style handles or kinda-safe pointers, that add a modicum of
-# checking to dynamically allocated memory.
-#
-# This approach avoids using 'allocate' directly in favor of two primitives:
-#   - 'new', which allocates some space (the 'payload'), stores the address
-#     along with an opaque 'alloc id' in a 'handle', and prepends the same
-#     alloc id to the payload.
-#   - 'lookup', which checks that the alloc id at the start of a handle matches
-#     the alloc id at the start of the payload before returning the address.
-#
-# Layout of a handle:
-#   offset 0: alloc id
-#   offset 4: address
-#
-# To run (from the subx directory):
-#   $ ./subx translate *.subx apps/handle.subx -o apps/handle
-#   $ ./subx run apps/handle
-# Expected result is a successful lookup followed by a hard abort:
-#   lookup succeeded
-#   lookup failed
-# (This file is a prototype. The 'tests' in it aren't real; failures are
-# expected.)
-
-== code
-#   instruction                     effective address                                                   register    displacement    immediate
-# . op          subop               mod             rm32          base        index         scale       r32
-# . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
-
-# no Entry; the standard library runs all tests by default
-
-new:  # ad : (address allocation-descriptor), n : int, out : (address handle)
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # . save registers
-    50/push-EAX
-    51/push-ECX
-    52/push-EDX
-    # ECX = n+4
-    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0xc/disp8       .                 # copy *(EBP+12) to ECX
-    81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add to ECX
-    # EAX = allocate(ad, ECX)
-    # . . push args
-    51/push-ECX
-    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
-    # . . call
-    e8/call  allocate/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # EDX = out
-    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0x10/disp8      .                 # copy *(EBP+16) to EDX
-    # out->address = EAX
-    89/copy                         1/mod/*+disp8   2/rm32/EDX    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDX+4)
-    # if (EAX == 0) out->alloc_id = 0, return
-    3d/compare-EAX-and  0/imm32
-    75/jump-if-not-equal  $new:continue/disp8
-    c7          0/subop/copy        0/mod/indirect  2/rm32/EDX    .           .             .           .           .               0/imm32           # copy to *EDX
-    eb/jump  $new:end/disp8
-$new:continue:
-    # otherwise:
-    # ECX = *Next-alloc-id
-    8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           1/r32/ECX   Next-alloc-id/disp32              # copy *Next-alloc-id to ECX
-    # *EAX = *Next-alloc-id/ECX
-    89/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EAX
-    # out->alloc_id = *Next-alloc-id
-    89/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EDX
-    # increment *Next-alloc-id
-    ff          0/subop/increment   0/mod/indirect  5/rm32/.disp32            .             .           .           Next-alloc-id/disp32              # increment *Next-alloc-id
-$new:end:
-    # . restore registers
-    5a/pop-to-EDX
-    59/pop-to-ECX
-    58/pop-to-EAX
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-test-new:
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # var heap/EDX : (address allocation-descriptor) = {0, 0}
-    68/push  0/imm32/limit
-    68/push  0/imm32/curr
-    89/copy                         3/mod/direct    2/rm32/EDX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDX
-    # heap = new-segment(512)
-    # . . push args
-    52/push-EDX
-    68/push  0x200/imm32
-    # . . call
-    e8/call  new-segment/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # *Next-alloc-id = 0x34
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .     Next-alloc-id/disp32  0x34/imm32        # copy to *Next-alloc-id
-    # var handle/ECX = {0, 0}
-    68/push  0/imm32/address
-    68/push  0/imm32/alloc-id
-    89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-    # new(heap, 2, handle/ECX)
-    # . . push args
-    51/push-ECX
-    68/push  2/imm32/size
-    52/push-EDX
-    # . . call
-    e8/call  new/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(handle->alloc_id, 0x34, msg)
-    # . . push args
-    68/push  "F - test-new: alloc id of handle"/imm32
-    68/push  0x34/imm32
-    ff          6/subop/push        0/mod/indirect  1/rm32/ECX    .           .             .           .           .               .                 # push *ECX
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(*handle->address, 0x34, msg)
-    # . . push args
-    68/push  "F - test-new: alloc id of payload"/imm32
-    68/push  0x34/imm32
-    8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           2/r32/EDX   4/disp8         .                 # copy *(ECX+4) to EDX
-    ff          6/subop/push        0/mod/indirect  2/rm32/EDX    .           .             .           .           .               .                 # push *EDX
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(*Next-alloc-id, 0x35)
-    # . . push args
-    68/push  "F - test-new: next alloc id"/imm32
-    68/push  0x35/imm32
-    ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Next-alloc-id/disp32              # copy to *Next-alloc-id
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # clean up
-    # . *Next-alloc-id = 1
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .     Next-alloc-id/disp32  1/imm32           # copy to *Next-alloc-id
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-_pending-test-new-failure:
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # . *Next-alloc-id = 0x34
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .           Next-alloc-id/disp32  0x34/imm32  # copy to *Next-alloc-id
-    # define an allocation-descriptor with no space left
-    # . var ad/EAX : (address allocation-descriptor) = {0x10, 0x10}
-    68/push  0x10/imm32/limit
-    68/push  0x10/imm32/curr
-    89/copy                         3/mod/direct    0/rm32/EAX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EAX
-    # . var handle/ECX = {random, random}
-    68/push  1234/imm32/address
-    68/push  5678/imm32/alloc-id
-    89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-    # try to allocate
-    # . new(ad, 2, handle/ECX)
-    # . . push args
-    51/push-ECX
-    68/push  2/imm32/size
-    50/push-EAX
-    # . . call
-    e8/call  new/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # handle should be cleared
-    # . check-ints-equal(handle->alloc_id, 0, msg)
-    # . . push args
-    68/push  "F - test-new-failure: alloc id of handle"/imm32
-    68/push  0/imm32
-    ff          6/subop/push        0/mod/indirect  1/rm32/ECX    .           .             .           .           .               .                 # push *ECX
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # . check-ints-equal(handle->address, 0, msg)
-    # . . push args
-    68/push  "F - test-new-failure: address of handle"/imm32
-    68/push  0/imm32
-    ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # Next-alloc-id should be unmodified
-    # . check-ints-equal(*Next-alloc-id, 0x34)
-    # . . push args
-    68/push  "F - test-new-failure: next alloc id"/imm32
-    68/push  0x34/imm32
-    ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Next-alloc-id/disp32              # copy to *Next-alloc-id
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # clean up
-    # . *Next-alloc-id = 1
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .     Next-alloc-id/disp32  1/imm32           # copy to *Next-alloc-id
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-lookup:  # h : (handle T) -> EAX : (address T)
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # - as a proof of concept for future inlining, uses no general-purpose registers besides the output (EAX)
-    # EAX = handle
-    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
-    # - inline {
-    # push handle->alloc_id
-    ff          6/subop/push        0/mod/indirect  0/rm32/EAX    .           .             .           .           .               .                 # push *EAX
-    # EAX = handle->address (payload)
-    8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # copy *(EAX+4) to EAX
-    # push handle->address
-    50/push-EAX
-    # EAX = payload->alloc_id
-    8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           .           .               .                 # copy *EAX to EAX
-    # if (EAX != handle->alloc_id) abort
-    39/compare                      1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   4/disp8         .                 # compare *(ESP+4) and EAX
-    75/jump-if-not-equal  $lookup:abort/disp8
-    # EAX = pop handle->address
-    58/pop-to-EAX
-    # discard handle->alloc_id
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # add 4
-    05/add-to-EAX  4/imm32
-    # - }
-    # - alternative consuming a second register {
-#?     # ECX = handle->alloc_id
-#?     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
-#?     # EAX = handle->address (payload)
-#?     8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(EAX+4) to EAX
-#?     # if (ECX != *EAX) abort
-#?     39/compare                      0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare *EAX and ECX
-#?     75/jump-if-not-equal  $lookup:abort/disp8
-#?     # add 4 to EAX
-#?     05/add-to-EAX  4/imm32
-    # - }
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-$lookup:abort:
-    # . _write(2/stderr, msg)
-    # . . push args
-    68/push  "lookup failed\n"/imm32
-    68/push  2/imm32/stderr
-    # . . call
-    e8/call  _write/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # . syscall(exit, 1)
-    bb/copy-to-EBX  1/imm32/exit-status
-    b8/copy-to-EAX  1/imm32/exit
-    cd/syscall  0x80/imm8
-
-test-lookup-success:
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # . save registers
-    # var heap/EBX : (address allocation-descriptor) = {0, 0}
-    68/push  0/imm32/limit
-    68/push  0/imm32/curr
-    89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBX
-    # heap = new-segment(512)
-    # . . push args
-    53/push-EBX
-    68/push  0x200/imm32
-    # . . call
-    e8/call  new-segment/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # var handle/ECX = {0, 0}
-    68/push  0/imm32/address
-    68/push  0/imm32/alloc-id
-    89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-    # var old_top/EDX = heap->curr
-    8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # copy *EBX to EDX
-    # new(heap, 2, handle)
-    # . . push args
-    51/push-ECX
-    68/push  2/imm32/size
-    53/push-EBX
-    # . . call
-    e8/call  new/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # EAX = lookup(handle)
-    # . . push args
-    51/push-ECX
-    # . . call
-    e8/call  lookup/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # EAX contains old top of heap, except skipping the alloc id in the payload
-    # . check-ints-equal(EAX, old_top+4, msg)
-    # . . push args
-    68/push  "F - test-lookup-success"/imm32
-    81          0/subop/add         3/mod/direct    2/rm32/EDX    .           .             .           .           .               4/imm32           # add to EDX
-    52/push-EDX
-    50/push-EAX
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # clean up
-    # . *Next-alloc-id = 1
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .     Next-alloc-id/disp32  1/imm32           # copy to *Next-alloc-id
-    # write(2/stderr, "lookup succeeded\n")
-    # . . push args
-    68/push  "lookup succeeded\n"/imm32
-    68/push  2/imm32/stderr
-    # . . call
-    e8/call  write/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # . restore registers
-    5a/pop-to-EDX
-    59/pop-to-ECX
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-test-lookup-failure:
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # var heap/ESI : (address allocation-descriptor) = {0, 0}
-    68/push  0/imm32/limit
-    68/push  0/imm32/curr
-    89/copy                         3/mod/direct    6/rm32/ESI    .           .             .           4/r32/ESP   .               .                 # copy ESP to ESI
-    # heap = new-segment(512)
-    # . . push args
-    56/push-ESI
-    68/push  0x200/imm32
-    # . . call
-    e8/call  new-segment/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # var h1/ECX = {0, 0}
-    68/push  0/imm32/address
-    68/push  0/imm32/alloc-id
-    89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-    # var old_top/EBX = heap->curr
-    8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
-    # first allocation, to h1
-    # . new(heap, 2, h1)
-    # . . push args
-    51/push-ECX
-    68/push  2/imm32/size
-    56/push-ESI
-    # . . call
-    e8/call  new/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # reset heap->curr to mimic reclamation
-    89/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy EBX to *ESI
-    # second allocation that returns the same address as the first
-    # var h2/EDX = {0, 0}
-    68/push  0/imm32/address
-    68/push  0/imm32/alloc-id
-    89/copy                         3/mod/direct    2/rm32/EDX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDX
-    # . new(heap, 2, h2)
-    # . . push args
-    52/push-EDX
-    68/push  2/imm32/size
-    56/push-ESI
-    # . . call
-    e8/call  new/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(h1->address, h2->address, msg)
-    # . . push args
-    68/push  "F - test-lookup-failure"/imm32
-    ff          6/subop/push        1/mod/*+disp8   2/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(EDX+4)
-    ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
-    # . . call
-    e8/call  check-ints-equal/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # lookup(h1) should crash
-    # . . push args
-    51/push-ECX
-    # . . call
-    e8/call  lookup/disp32
-    # should never get past this point
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # clean up
-    # . *Next-alloc-id = 1
-    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .     Next-alloc-id/disp32  1/imm32           # copy to *Next-alloc-id
-    # . epilog
-    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-    5d/pop-to-EBP
-    c3/return
-
-== data
-
-# Monotonically increasing counter for calls to 'new'
-Next-alloc-id:
-    1/imm32
-
-# . . vim:nowrap:textwidth=0