about summary refs log tree commit diff stats
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rwxr-xr-xlinux/mubin602291 -> 603681 bytes
-rw-r--r--linux/mu.subx155
2 files changed, 152 insertions, 3 deletions
diff --git a/linux/mu b/linux/mu
index e8ceb38f..a8d00898 100755
--- a/linux/mu
+++ b/linux/mu
Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx
index 0dcfb6fc..2326f4b1 100644
--- a/linux/mu.subx
+++ b/linux/mu.subx
@@ -481,6 +481,7 @@ Entry:
     # . prologue
     89/<- %ebp 4/r32/esp
     (new-segment *Heap-size Heap)
+#?     (test-address-with-right-type-for-stream)
     # if (argv[1] == "test') run-tests()
     {
       # if (argc <= 1) break
@@ -27258,7 +27259,7 @@ $emit-subx-stmt-list:check-for-var-def:
         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
         75/jump-if-!= break/disp8
 $emit-subx-stmt-list:var-def:
-        (emit-subx-var-def *(ebp+8) %ecx)
+        (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
@@ -28487,7 +28488,7 @@ $reg-in-function-outputs?:end:
     5d/pop-to-ebp
     c3/return
 
-emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
+emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -28532,7 +28533,8 @@ emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
       0f 84/jump-if-= break/disp32
       # var array-size-without-size/edx: int = n-12
       81 5/subop/subtract %edx 0xc/imm32
-      (emit-array-data-initialization *(ebp+8) %edx)
+      (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
+      (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
       # emit read and write pointers
       (emit-indent *(ebp+8) *Curr-block-depth)
       (write-buffered *(ebp+8) "68/push 0/imm32\n")
@@ -28581,6 +28583,50 @@ $emit-array-data-initialization:end:
     5d/pop-to-ebp
     c3/return
 
+emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    # Optimization: if it's a stream of bytes, don't initialize.
+    #
+    # We often construct large temporary streams on the stack for 'trace'
+    # statements. Initializing such streams can significantly slow programs
+    # down.
+    #
+    # Mu doesn't really depend on initializing stream contents for type- or
+    # memory-safety; we're mostly doing so to make it easy to debug unsafe
+    # SubX code that misuses stream objects by manipulating read/write
+    # pointers. But you can't _really_ protect from unsafe SubX, so I think we
+    # don't give up much safety or security here.
+    {
+      (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
+      3d/compare-eax-and 8/imm32/byte
+      75/jump-if-!= break/disp8
+      (emit-indent *(ebp+8) *Curr-block-depth)
+      (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
+      (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
+      (write-buffered *(ebp+8) "/imm32\n")
+      eb/jump $emit-stream-data-initialization:emit-length/disp8
+    }
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "(push-n-zero-bytes ")
+    (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
+    (write-buffered *(ebp+8) ")\n")
+$emit-stream-data-initialization:emit-length:
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "68/push ")
+    (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
+    (write-buffered *(ebp+8) "/imm32\n")
+$emit-stream-data-initialization:end:
+    # . restore registers
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
@@ -29038,6 +29084,109 @@ $size-of-type-id-as-array-element:end:
     5d/pop-to-ebp
     c3/return
 
+stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
+    # precondition: n is positive
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # eax = type
+    8b/-> *(ebp+8) 0/r32/eax
+    # if type == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-== $stream-element-type-id:error0/disp32
+    # if type->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
+    0f 85/jump-if-!= $stream-element-type-id:error1/disp32
+    # if (type->left == addr) type = type->right
+    {
+      50/push-eax
+      (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+      (simple-mu-type? %eax 2)  # addr => eax
+      3d/compare-eax-with 0/imm32/false
+      58/pop-to-eax
+      74/jump-if-= break/disp8
+$stream-element-type-id:skip-addr:
+      (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    }
+    # if type == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-= $stream-element-type-id:error2/disp32
+    # if type->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
+    0f 85/jump-if-!= $stream-element-type-id:error2/disp32
+    # if type->left != stream abort
+    {
+      50/push-eax
+      (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+      (simple-mu-type? %eax 0xb)  # stream => eax
+      3d/compare-eax-with 0/imm32/false
+      58/pop-to-eax
+$stream-element-type-id:no-stream:
+      0f 84/jump-if-= $stream-element-type-id:error2/disp32
+    }
+$stream-element-type-id:skip-stream:
+    # type = type->right
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # if type == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-= $stream-element-type-id:error2/disp32
+    # if type->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
+    0f 85/jump-if-!= $stream-element-type-id:error2/disp32
+    # t = type->left
+    (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+    # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
+    {
+      81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
+      75/jump-if-!= break/disp8
+      (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+    }
+    # return type->value
+    8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
+$stream-element-type-id:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+$stream-element-type-id:error0:
+    (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has no type\n")
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
+$stream-element-type-id:error1:
+    (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has atomic type ")
+    (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
+    (write-buffered *(ebp+0xc) Newline)
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
+$stream-element-type-id:error2:
+    (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has non-stream type\n")
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
     # . prologue
     55/push-ebp