-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
6684 - experimental primitives for streams
This is a hacky special case. The alternative would be more general support for generics. One observation: we might be able to type-check some primitives using `sig`s. Only if they don't return anything, since primitives usually need to support arbitrary registers. I'm not doing that yet, though. It eliminates the possibility of writing tests for them in mu.subx, which can't see 400.mu. But it's an alternative: sig allocate out: (addr handle _) sig populate out: (addr handle array _), n: int sig populate-stream out: (addr handle stream _), n: int sig read-from-stream s: (addr stream _T), out: (addr _T) sig write-to-stream s: (addr stream _T), in: (addr _T) We could write the tests in Mu. But then we're testing behavior rather than the code generated. There are trade-offs. By performing type-checking in mu.subx I retain the option to write both kinds of tests.
- Loading branch information
Showing
4 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Some unsafe methods not intended to be used directly in SubX, only through | ||
# Mu after proper type-checking. | ||
|
||
write-to-stream: # s: (addr stream), in: (addr byte), n: int | ||
# . prologue | ||
55/push-ebp | ||
89/<- %ebp 4/r32/esp | ||
# . save registers | ||
50/push-eax | ||
51/push-ecx | ||
52/push-edx | ||
53/push-ebx | ||
57/push-edi | ||
# edi = s | ||
8b/-> *(ebp+8) 7/r32/edi | ||
# var swrite/edx: int = s->write | ||
8b/-> *edi 2/r32/edx | ||
# if (swrite + n > s->size) abort | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
01/add-to %ecx 2/r32/edx | ||
3b/compare 1/r32/ecx *(edi+8) | ||
0f 8f/jump-if-> $write-to-stream:abort/disp32 | ||
# var out/edx: (addr byte) = s->data + s->write | ||
8d/copy-address *(edi+edx+0xc) 2/r32/edx | ||
# var outend/ebx: (addr byte) = out + n | ||
8b/-> *(ebp+0x10) 3/r32/ebx | ||
8d/copy-address *(edx+ebx) 3/r32/ebx | ||
# eax = in | ||
8b/-> *(ebp+0xc) 0/r32/eax | ||
# var inend/ecx: (addr byte) = in + n | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
8d/copy-address *(eax+ecx) 1/r32/ecx | ||
# | ||
(_append-4 %edx %ebx %eax %ecx) # => eax | ||
# s->write += n | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
01/add-to *edi 1/r32/ecx | ||
$write-to-stream:end: | ||
# . restore registers | ||
5f/pop-to-edi | ||
5b/pop-to-ebx | ||
5a/pop-to-edx | ||
59/pop-to-ecx | ||
58/pop-to-eax | ||
# . epilogue | ||
89/<- %esp 5/r32/ebp | ||
5d/pop-to-ebp | ||
c3/return | ||
|
||
$write-to-stream:abort: | ||
(write-buffered Stderr "write-to-stream: stream full\n") | ||
(flush Stderr) | ||
bb/copy-to-ebx 1/imm32 | ||
(syscall_exit) | ||
# never gets here | ||
|
||
read-from-stream: # s: (addr stream), out: (addr byte), n: int | ||
# . prologue | ||
55/push-ebp | ||
89/<- %ebp 4/r32/esp | ||
# . save registers | ||
50/push-eax | ||
51/push-ecx | ||
52/push-edx | ||
53/push-ebx | ||
56/push-esi | ||
# esi = s | ||
8b/-> *(ebp+8) 6/r32/esi | ||
# var sread/edx: int = s->read | ||
8b/-> *(esi+4) 2/r32/edx | ||
# if (sread + n > s->write) abort | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
01/add-to %ecx 2/r32/edx | ||
3b/compare 1/r32/ecx *esi | ||
0f 8f/jump-if-> $read-from-stream:abort/disp32 | ||
# var in/edx: (addr byte) = s->data + s->read | ||
8d/copy-address *(esi+edx+0xc) 2/r32/edx | ||
# var inend/ebx: (addr byte) = in + n | ||
8b/-> *(ebp+0x10) 3/r32/ebx | ||
8d/copy-address *(edx+ebx) 3/r32/ebx | ||
# eax = out | ||
8b/-> *(ebp+0xc) 0/r32/eax | ||
# var outend/ecx: (addr byte) = out + n | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
8d/copy-address *(eax+ecx) 1/r32/ecx | ||
# | ||
(_append-4 %eax %ecx %edx %ebx) # => eax | ||
# s->read += n | ||
8b/-> *(ebp+0x10) 1/r32/ecx | ||
01/add-to *(esi+4) 1/r32/ecx | ||
$read-from-stream:end: | ||
# . restore registers | ||
5e/pop-to-esi | ||
5b/pop-to-ebx | ||
5a/pop-to-edx | ||
59/pop-to-ecx | ||
58/pop-to-eax | ||
# . epilogue | ||
89/<- %esp 5/r32/ebp | ||
5d/pop-to-ebp | ||
c3/return | ||
|
||
$read-from-stream:abort: | ||
(write-buffered Stderr "read-from-stream: stream empty\n") | ||
(flush Stderr) | ||
bb/copy-to-ebx 1/imm32 | ||
(syscall_exit) | ||
# never gets here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Tests for Mu's stream primitives. | ||
|
||
fn test-stream { | ||
# write an int to a stream, then read it back | ||
var s: (stream int 4) | ||
var s2/ecx: (addr stream int 4) <- address s | ||
var x: int | ||
copy-to x, 0x34 | ||
var x2/edx: (addr int) <- address x | ||
write-to-stream s2, x2 | ||
var y: int | ||
var y2/ebx: (addr int) <- address y | ||
read-from-stream s2, y2 | ||
check-ints-equal y, 0x34, "F - test-stream" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters