test: Cover lexical region lowering
2a67faea10bc90ec2c810c94e06b752a2e30905084878116431fed5bc6668aea
1 parent
9a8d09d2
Makefile
+12 -3
| 1 | 1 | # Radiance build file. |
|
| 2 | 2 | ||
| 3 | 3 | # Core standard library modules. |
|
| 4 | 4 | STD := -pkg std $(patsubst %,-mod %,$(shell cat std.lib)) |
|
| 5 | + | # Session allocation support for standalone lowering fixtures. |
|
| 6 | + | TEST_FIXTURE_STD_LIB := $(shell cat test/support/std.lib) |
|
| 7 | + | TEST_FIXTURE_STD := -pkg std $(patsubst %,-mod %,$(TEST_FIXTURE_STD_LIB)) |
|
| 5 | 8 | ||
| 6 | 9 | # Full standard library with test modules. |
|
| 7 | 10 | STD_TEST := $(STD) $(patsubst %,-mod %,$(shell cat std.lib.test)) |
|
| 8 | 11 | ||
| 9 | 12 | # Source files. |
| 39 | 42 | ||
| 40 | 43 | SEED := seed/radiance.rv64 |
|
| 41 | 44 | COMPILER_SRC := compiler/radiance.rad compiler/radiance/codegen.rad |
|
| 42 | 45 | SEED_OPTS := $(STD) -pkg radiance $(patsubst %,-mod %,$(COMPILER_SRC)) -entry radiance |
|
| 43 | 46 | ||
| 44 | - | $(RAD_BIN): $(STD_LIB) $(COMPILER_SRC) | $(BIN_DIR) |
|
| 47 | + | $(RAD_BIN): $(STD_LIB) $(COMPILER_SRC) std.lib | $(BIN_DIR) |
|
| 45 | 48 | @echo "radiance $(SEED) => $@" |
|
| 46 | 49 | @$(EMU) $(EMU_FLAGS) -run $(SEED) $(SEED_OPTS) -o $@ |
|
| 47 | 50 | ||
| 48 | 51 | $(BIN_DIR): |
|
| 49 | 52 | @mkdir -p $@ |
| 54 | 57 | ||
| 55 | 58 | std-test: $(STD_LIB_TEST) |
|
| 56 | 59 | @echo |
|
| 57 | 60 | @$(EMU) $(EMU_FLAGS) -run $(STD_LIB_TEST) |
|
| 58 | 61 | ||
| 59 | - | $(STD_LIB_TEST): $(STD_LIB) $(RAD_BIN) |
|
| 62 | + | $(STD_LIB_TEST): $(STD_LIB) $(RAD_BIN) std.lib std.lib.test |
|
| 60 | 63 | @echo "radiance -test $(STD_TEST) -entry std -o $@" |
|
| 61 | 64 | @$(RADIANCE) -test $(STD_TEST) -entry std -o $@ |
|
| 62 | 65 | ||
| 63 | 66 | clean-std-test: |
|
| 64 | 67 | @rm -f lib/std.test.rv64 \ |
| 91 | 94 | ||
| 92 | 95 | # A `.rad` executable test can have a same-basename `.ras` module. |
|
| 93 | 96 | $(patsubst %.ras,%.rv64,$(BIN_TEST_RAD_ASM_SRC)): %.rv64: %.ras |
|
| 94 | 97 | $(patsubst %.start.ras,%.rv64,$(BIN_TEST_RAD_START_SRC)): %.rv64: %.start.ras |
|
| 95 | 98 | ||
| 99 | + | # Package fixtures can request session support. |
|
| 100 | + | BIN_TEST_SESSION_SRC := $(shell grep -l '^//! session-support$$' $(BIN_TEST_RAD_EXE_SRC)) |
|
| 101 | + | $(BIN_TEST_SESSION_SRC:.rad=.rv64): TEST_STD_FLAGS := $(TEST_FIXTURE_STD) |
|
| 102 | + | $(BIN_TEST_SESSION_SRC:.rad=.rv64): TEST_ENTRY_FLAGS := -entry test |
|
| 103 | + | $(BIN_TEST_SESSION_SRC:.rad=.rv64): $(TEST_FIXTURE_STD_LIB) test/support/std.lib |
|
| 104 | + | ||
| 96 | 105 | # Compile each executable test to a binary. |
|
| 97 | 106 | $(BIN_TEST_DIR)/%.rv64: $(BIN_TEST_DIR)/%.rad $(RAD_BIN) |
|
| 98 | 107 | @echo "radiance $< => $@" |
|
| 99 | - | @$(RADIANCE) -pkg test -mod $< $(patsubst %,-mod %,$(wildcard $(@:.rv64=)/*.rad)) $(patsubst %,-start %,$(wildcard $(@:.rv64=.start.ras))) $(patsubst %,-mod %,$(wildcard $(@:.rv64=.ras))) -o $@ |
|
| 108 | + | @$(RADIANCE) $(TEST_STD_FLAGS) -pkg test -mod $< $(TEST_ENTRY_FLAGS) $(patsubst %,-mod %,$(wildcard $(@:.rv64=)/*.rad)) $(patsubst %,-start %,$(wildcard $(@:.rv64=.start.ras))) $(patsubst %,-mod %,$(wildcard $(@:.rv64=.ras))) -o $@ |
|
| 100 | 109 | ||
| 101 | 110 | $(BIN_TEST_DIR)/%.rv64: $(BIN_TEST_DIR)/%.ras $(BIN_RUNNER) |
|
| 102 | 111 | @echo "asm $< => $@" |
|
| 103 | 112 | @$(EMU) $(EMU_FLAGS) -run $(BIN_RUNNER) -- assemble $< $@ |
|
| 104 | 113 |
test/package-golden
added
+50 -0
| 1 | + | #!/bin/sh |
|
| 2 | + | # Compare one package's emitted IL with its golden file and session support. |
|
| 3 | + | set -eu |
|
| 4 | + | ||
| 5 | + | source=$1 |
|
| 6 | + | expected=${source%.rad}.ril |
|
| 7 | + | module=$(basename "${source%.rad}") |
|
| 8 | + | work=$(mktemp -d) |
|
| 9 | + | trap 'rm -rf "$work"' EXIT HUP INT TERM |
|
| 10 | + | ||
| 11 | + | set -- -pkg std |
|
| 12 | + | while IFS= read -r source_module; do |
|
| 13 | + | set -- "$@" -mod "$source_module" |
|
| 14 | + | done < test/support/std.lib |
|
| 15 | + | set -- "$@" -pkg test -mod "$source" -entry test -dump il |
|
| 16 | + | for source_module in "${source%.rad}"/*.rad; do |
|
| 17 | + | if [ -f "$source_module" ]; then |
|
| 18 | + | set -- "$@" -mod "$source_module" |
|
| 19 | + | fi |
|
| 20 | + | done |
|
| 21 | + | ||
| 22 | + | if ! ${RAD_EMULATOR:-emulator} -memory-size=385024 -data-size=348160 \ |
|
| 23 | + | -stack-size=1024 -run bin/radiance.rv64.dev "$@" >"$work/program.il" 2>"$work/compiler.log"; then |
|
| 24 | + | cat "$work/compiler.log" |
|
| 25 | + | cat "$work/program.il" |
|
| 26 | + | exit 1 |
|
| 27 | + | fi |
|
| 28 | + | ||
| 29 | + | # Top-level function and data definitions carry the source module's prefix. |
|
| 30 | + | awk -v prefix="\$\"$module::" ' |
|
| 31 | + | /^(fn |data )/ { keep = index($0, prefix) > 0 } |
|
| 32 | + | keep { print } |
|
| 33 | + | /^}/ { if (keep) print ""; keep = 0 } |
|
| 34 | + | ' "$work/program.il" >"$work/actual.ril" |
|
| 35 | + | if [ ! -s "$work/actual.ril" ]; then |
|
| 36 | + | echo "error: no IL definitions found for $module" |
|
| 37 | + | exit 1 |
|
| 38 | + | fi |
|
| 39 | + | ||
| 40 | + | # Golden comparisons ignore comments, indentation, and blank lines. |
|
| 41 | + | for kind in actual expected; do |
|
| 42 | + | input=$expected |
|
| 43 | + | if [ "$kind" = actual ]; then input=$work/actual.ril; fi |
|
| 44 | + | awk '{ sub(/\/\/.*/, ""); gsub(/^[ \t]+|[ \t]+$/, ""); if (length) print }' \ |
|
| 45 | + | "$input" >"$work/$kind.normalized" |
|
| 46 | + | done |
|
| 47 | + | if ! cmp -s "$work/expected.normalized" "$work/actual.normalized"; then |
|
| 48 | + | diff -u "$expected" "$work/actual.ril" || true |
|
| 49 | + | exit 1 |
|
| 50 | + | fi |
test/run
+12 -1
| 6 | 6 | # `test/tests/`. |
|
| 7 | 7 | # |
|
| 8 | 8 | # For each test: |
|
| 9 | 9 | # - If a `.ril` file exists alongside it, the IL output is checked |
|
| 10 | 10 | # against it via the runner binary. |
|
| 11 | + | # - If `//! session-support` appears, the IL check uses the fixture allocator |
|
| 12 | + | # package required by session allocation. |
|
| 11 | 13 | # - If `//! returns: N` appears in the file, the test is compiled to |
|
| 12 | 14 | # a binary and executed; the exit code must match N. |
|
| 13 | 15 | # - If `//! rw-data-size: N` appears in the file, the emitted image header's |
|
| 14 | 16 | # rwdata size must match N bytes. |
|
| 15 | 17 |
| 51 | 53 | ||
| 52 | 54 | ril="${base}.ril" |
|
| 53 | 55 | bin="${base}.rv64" |
|
| 54 | 56 | # IL check: run the runner if a .ril file exists. |
|
| 55 | 57 | if [ -f "$ril" ]; then |
|
| 56 | - | if $EMU "$RUNNER" -- "$test"; then |
|
| 58 | + | if grep -q '^//! session-support$' "$test"; then |
|
| 59 | + | echo -n "test $test ... " |
|
| 60 | + | if test/package-golden "$test"; then |
|
| 61 | + | echo "ok" |
|
| 62 | + | passed=$((passed + 1)) |
|
| 63 | + | else |
|
| 64 | + | echo "FAILED" |
|
| 65 | + | failed=$((failed + 1)) |
|
| 66 | + | fi |
|
| 67 | + | elif $EMU "$RUNNER" -- "$test"; then |
|
| 57 | 68 | passed=$((passed + 1)) |
|
| 58 | 69 | else |
|
| 59 | 70 | failed=$((failed + 1)) |
|
| 60 | 71 | fi |
|
| 61 | 72 | fi |
test/support/std.lib
added
+3 -0
| 1 | + | test/support/std.rad |
|
| 2 | + | test/support/std/lang.rad |
|
| 3 | + | test/support/std/lang/alloc.rad |
test/support/std.rad
added
+3 -0
| 1 | + | //! Minimal standard package root for binary lowering fixtures. |
|
| 2 | + | ||
| 3 | + | export mod lang; |
test/support/std/lang.rad
added
+3 -0
| 1 | + | //! Language support for binary lowering fixtures. |
|
| 2 | + | ||
| 3 | + | export mod alloc; |
test/support/std/lang/alloc.rad
added
+93 -0
| 1 | + | //! Arena allocation support for binary lowering fixtures. |
|
| 2 | + | ||
| 3 | + | /// Error returned when an arena cannot satisfy an allocation. |
|
| 4 | + | export union AllocError: Copy { |
|
| 5 | + | /// The arena has insufficient storage. |
|
| 6 | + | OutOfMemory, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Bump allocator backed by a byte slice. |
|
| 10 | + | export record Arena { |
|
| 11 | + | /// Backing storage. |
|
| 12 | + | data: *mut [u8], |
|
| 13 | + | /// Current allocation offset in bytes. |
|
| 14 | + | offset: u32, |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | /// Create an arena backed by `data`. |
|
| 18 | + | export fn new(data: *mut [u8]) -> Arena { |
|
| 19 | + | return Arena { data, offset: 0 }; |
|
| 20 | + | } |
|
| 21 | + | ||
| 22 | + | /// Reset the arena to its initial empty state. |
|
| 23 | + | export fn reset(arena: &mut Arena) { |
|
| 24 | + | set arena.offset = 0; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | /// Return the number of bytes committed in the arena. |
|
| 28 | + | export fn used(arena: &Arena) -> u32 { |
|
| 29 | + | return arena.offset; |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | /// Allocate aligned storage without changing the arena after failure. |
|
| 33 | + | export unsafe fn alloc(arena: *unsafe mut Arena, size: u32, alignment: u32) -> *mut opaque throws (AllocError) { |
|
| 34 | + | assert alignment > 0; |
|
| 35 | + | assert size > 0; |
|
| 36 | + | assert (alignment & (alignment - 1)) == 0; |
|
| 37 | + | ||
| 38 | + | let capacity = arena.data.len; |
|
| 39 | + | if arena.offset >= capacity { |
|
| 40 | + | throw AllocError::OutOfMemory; |
|
| 41 | + | } |
|
| 42 | + | let address = &arena.data[0] as u64; |
|
| 43 | + | let mask = (alignment - 1) as u64; |
|
| 44 | + | let remainder = ((address & mask) + (arena.offset as u64 & mask)) & mask; |
|
| 45 | + | let padding = ((alignment as u64 - remainder) & mask) as u32; |
|
| 46 | + | let available = capacity - arena.offset; |
|
| 47 | + | if padding > available or size > available - padding { |
|
| 48 | + | throw AllocError::OutOfMemory; |
|
| 49 | + | } |
|
| 50 | + | let aligned = arena.offset + padding; |
|
| 51 | + | let base: *mut u8 = &mut arena.data[aligned]; |
|
| 52 | + | set arena.offset = aligned + size; |
|
| 53 | + | return base as *mut opaque; |
|
| 54 | + | } |
|
| 55 | + | ||
| 56 | + | /// Allocate raw storage that remains valid until the arena is reset. |
|
| 57 | + | export unsafe fn allocRaw(arena: &mut Arena, size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError) { |
|
| 58 | + | let owner = try alloc(&mut *arena, size, alignment); |
|
| 59 | + | let byte = owner as *mut u8; |
|
| 60 | + | return &mut *byte as *unsafe mut opaque; |
|
| 61 | + | } |
|
| 62 | + | ||
| 63 | + | /// Allocate a raw slice that remains valid until the arena is reset. |
|
| 64 | + | export unsafe fn allocRawSlice(arena: &mut Arena, size: u32, alignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError) { |
|
| 65 | + | if count == 0 { |
|
| 66 | + | return &mut []; |
|
| 67 | + | } |
|
| 68 | + | if size <> 0 and count > 4294967295 / size { |
|
| 69 | + | throw AllocError::OutOfMemory; |
|
| 70 | + | } |
|
| 71 | + | let raw = try allocRaw(arena, size * count, alignment); |
|
| 72 | + | return @sliceOf(raw, count); |
|
| 73 | + | } |
|
| 74 | + | ||
| 75 | + | /// Raw storage provider for allocation sessions. |
|
| 76 | + | export trait Alloc { |
|
| 77 | + | /// Reserve one uninitialized object. |
|
| 78 | + | unsafe fn (&mut Alloc) reserve(size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError); |
|
| 79 | + | /// Reserve an uninitialized slice. |
|
| 80 | + | unsafe fn (&mut Alloc) reserveSlice(itemSize: u32, itemAlignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError); |
|
| 81 | + | } |
|
| 82 | + | ||
| 83 | + | instance Alloc for Arena { |
|
| 84 | + | /// Reserve one uninitialized object in the arena. |
|
| 85 | + | unsafe fn (arena: &mut Arena) reserve(size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError) { |
|
| 86 | + | return try allocRaw(arena, size, alignment); |
|
| 87 | + | } |
|
| 88 | + | ||
| 89 | + | /// Reserve an uninitialized slice in the arena. |
|
| 90 | + | unsafe fn (arena: &mut Arena) reserveSlice(size: u32, alignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError) { |
|
| 91 | + | return try allocRawSlice(arena, size, alignment, count); |
|
| 92 | + | } |
|
| 93 | + | } |
test/tests/binding.storage.rad
added
+21 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Aggregate whose fields need initialized storage. |
|
| 4 | + | record Pair: Copy { |
|
| 5 | + | /// First summand. |
|
| 6 | + | first: u32, |
|
| 7 | + | /// Second summand. |
|
| 8 | + | second: u32, |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | @default unsafe fn main() -> u32 { |
|
| 12 | + | let mut pair: Pair = undefined; |
|
| 13 | + | set pair.first = 40; |
|
| 14 | + | set pair.second = 2; |
|
| 15 | + | let numbers: [u32; 2] = [40, 2]; |
|
| 16 | + | assert pair.first == numbers[0]; |
|
| 17 | + | assert pair.second == numbers[1]; |
|
| 18 | + | let wrapped: ?Pair = pair; |
|
| 19 | + | let value = wrapped else panic; |
|
| 20 | + | return value.first + value.second; |
|
| 21 | + | } |
test/tests/binding.storage.ril
added
+43 -0
| 1 | + | fn w32 $main() { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %0 8 4; |
|
| 4 | + | store w32 40 %0 0; |
|
| 5 | + | store w32 2 %0 4; |
|
| 6 | + | reserve %1 8 4; |
|
| 7 | + | store w32 40 %1 0; |
|
| 8 | + | store w32 2 %1 4; |
|
| 9 | + | load w32 %2 %0 0; |
|
| 10 | + | load w32 %3 %1 0; |
|
| 11 | + | br.eq w32 %2 %3 @assert.ok2 @assert.fail1; |
|
| 12 | + | @assert.fail1 |
|
| 13 | + | unreachable; |
|
| 14 | + | @assert.ok2 |
|
| 15 | + | load w32 %4 %0 4; |
|
| 16 | + | mul w64 %5 1 4; |
|
| 17 | + | add w64 %6 %1 %5; |
|
| 18 | + | load w32 %7 %6 0; |
|
| 19 | + | br.eq w32 %4 %7 @assert.ok4 @assert.fail3; |
|
| 20 | + | @assert.fail3 |
|
| 21 | + | unreachable; |
|
| 22 | + | @assert.ok4 |
|
| 23 | + | reserve %8 12 4; |
|
| 24 | + | store w8 1 %8 0; |
|
| 25 | + | add w64 %9 %8 4; |
|
| 26 | + | blit %9 %0 8; |
|
| 27 | + | reserve %10 12 4; |
|
| 28 | + | blit %10 %8 12; |
|
| 29 | + | reserve %11 12 4; |
|
| 30 | + | blit %11 %10 12; |
|
| 31 | + | load w8 %12 %11 0; |
|
| 32 | + | br.ne w32 %12 0 @success5 @else6; |
|
| 33 | + | @success5 |
|
| 34 | + | add w64 %13 %11 4; |
|
| 35 | + | jmp @merge7; |
|
| 36 | + | @else6 |
|
| 37 | + | unreachable; |
|
| 38 | + | @merge7 |
|
| 39 | + | load w32 %14 %13 0; |
|
| 40 | + | load w32 %15 %13 4; |
|
| 41 | + | add w32 %16 %14 %15; |
|
| 42 | + | ret %16; |
|
| 43 | + | } |
test/tests/data.optional.nil.rad
added
+31 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Payload with alignment padding inside a tagged optional. |
|
| 4 | + | record Payload: Copy { |
|
| 5 | + | /// Small prefix. |
|
| 6 | + | prefix: u8, |
|
| 7 | + | /// Aligned value. |
|
| 8 | + | value: u64, |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | /// Initialized nullable pointer table. |
|
| 12 | + | unsafe static POINTERS: [?*u32; 3] = [nil; 3]; |
|
| 13 | + | /// Initialized nullable slice. |
|
| 14 | + | unsafe static SLICE: ?*[u8] = nil; |
|
| 15 | + | /// Initialized tagged record optionals. |
|
| 16 | + | unsafe static RECORDS: [?Payload; 2] = [nil, nil]; |
|
| 17 | + | /// Initialized nested optional. |
|
| 18 | + | unsafe static NESTED: ??u32 = nil; |
|
| 19 | + | ||
| 20 | + | @default unsafe fn main() -> u32 { |
|
| 21 | + | for pointer in &POINTERS[..] { |
|
| 22 | + | assert pointer == nil; |
|
| 23 | + | } |
|
| 24 | + | assert SLICE == nil; |
|
| 25 | + | assert RECORDS[0] == nil; |
|
| 26 | + | assert RECORDS[1] == nil; |
|
| 27 | + | assert NESTED == nil; |
|
| 28 | + | set RECORDS[1] = Payload { prefix: 2, value: 40 }; |
|
| 29 | + | let result = RECORDS[1] else panic; |
|
| 30 | + | return result.prefix as u32 + result.value as u32; |
|
| 31 | + | } |
test/tests/data.optional.nil.ril
added
+103 -0
| 1 | + | data mut $POINTERS align 8 { |
|
| 2 | + | w8 0 * 8; |
|
| 3 | + | w8 0 * 8; |
|
| 4 | + | w8 0 * 8; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | data mut $SLICE align 8 { |
|
| 8 | + | w8 0 * 16; |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | data mut $RECORDS align 8 { |
|
| 12 | + | w8 0 * 24; |
|
| 13 | + | w8 0 * 24; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | data mut $NESTED align 4 { |
|
| 17 | + | w8 0 * 12; |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | fn w32 $main() { |
|
| 21 | + | @entry0 |
|
| 22 | + | copy %0 $POINTERS; |
|
| 23 | + | reserve %1 16 8; |
|
| 24 | + | store w64 %0 %1 0; |
|
| 25 | + | store w32 3 %1 8; |
|
| 26 | + | store w32 3 %1 12; |
|
| 27 | + | load w32 %2 %1 8; |
|
| 28 | + | load w64 %3 %1 0; |
|
| 29 | + | jmp @loop1(0); |
|
| 30 | + | @loop1(w32 %4) |
|
| 31 | + | br.slt w32 %4 %2 @body2 @merge3; |
|
| 32 | + | @body2 |
|
| 33 | + | mul w64 %5 %4 8; |
|
| 34 | + | add w64 %6 %3 %5; |
|
| 35 | + | load w64 %7 %6 0; |
|
| 36 | + | br.eq w64 %7 0 @assert.ok5 @assert.fail4; |
|
| 37 | + | @merge3 |
|
| 38 | + | copy %9 $SLICE; |
|
| 39 | + | load w64 %10 %9 0; |
|
| 40 | + | eq w64 %11 %10 0; |
|
| 41 | + | br.ne w32 %11 0 @assert.ok7 @assert.fail6; |
|
| 42 | + | @assert.fail4 |
|
| 43 | + | unreachable; |
|
| 44 | + | @assert.ok5 |
|
| 45 | + | add w32 %8 %4 1; |
|
| 46 | + | jmp @loop1(%8); |
|
| 47 | + | @assert.fail6 |
|
| 48 | + | unreachable; |
|
| 49 | + | @assert.ok7 |
|
| 50 | + | copy %12 $RECORDS; |
|
| 51 | + | load w8 %13 %12 0; |
|
| 52 | + | eq w8 %14 %13 0; |
|
| 53 | + | br.ne w32 %14 0 @assert.ok9 @assert.fail8; |
|
| 54 | + | @assert.fail8 |
|
| 55 | + | unreachable; |
|
| 56 | + | @assert.ok9 |
|
| 57 | + | copy %15 $RECORDS; |
|
| 58 | + | mul w64 %16 1 24; |
|
| 59 | + | add w64 %17 %15 %16; |
|
| 60 | + | load w8 %18 %17 0; |
|
| 61 | + | eq w8 %19 %18 0; |
|
| 62 | + | br.ne w32 %19 0 @assert.ok11 @assert.fail10; |
|
| 63 | + | @assert.fail10 |
|
| 64 | + | unreachable; |
|
| 65 | + | @assert.ok11 |
|
| 66 | + | copy %20 $NESTED; |
|
| 67 | + | load w8 %21 %20 0; |
|
| 68 | + | eq w8 %22 %21 0; |
|
| 69 | + | br.ne w32 %22 0 @assert.ok13 @assert.fail12; |
|
| 70 | + | @assert.fail12 |
|
| 71 | + | unreachable; |
|
| 72 | + | @assert.ok13 |
|
| 73 | + | reserve %23 16 8; |
|
| 74 | + | store w8 2 %23 0; |
|
| 75 | + | store w64 40 %23 8; |
|
| 76 | + | reserve %24 24 8; |
|
| 77 | + | store w8 1 %24 0; |
|
| 78 | + | add w64 %25 %24 8; |
|
| 79 | + | blit %25 %23 16; |
|
| 80 | + | copy %26 $RECORDS; |
|
| 81 | + | mul w64 %27 1 24; |
|
| 82 | + | add w64 %28 %26 %27; |
|
| 83 | + | blit %28 %24 24; |
|
| 84 | + | copy %29 $RECORDS; |
|
| 85 | + | mul w64 %30 1 24; |
|
| 86 | + | add w64 %31 %29 %30; |
|
| 87 | + | reserve %32 24 8; |
|
| 88 | + | blit %32 %31 24; |
|
| 89 | + | load w8 %33 %32 0; |
|
| 90 | + | br.ne w32 %33 0 @success14 @else15; |
|
| 91 | + | @success14 |
|
| 92 | + | add w64 %34 %32 8; |
|
| 93 | + | jmp @merge16; |
|
| 94 | + | @else15 |
|
| 95 | + | unreachable; |
|
| 96 | + | @merge16 |
|
| 97 | + | load w8 %35 %34 0; |
|
| 98 | + | zext w8 %36 %35; |
|
| 99 | + | load w64 %37 %34 8; |
|
| 100 | + | zext w32 %38 %37; |
|
| 101 | + | add w32 %39 %36 %38; |
|
| 102 | + | ret %39; |
|
| 103 | + | } |
test/tests/data.optional.value.rad
added
+63 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Aligned record payload in a present optional. |
|
| 4 | + | record Payload: Copy { |
|
| 5 | + | /// Small prefix before the aligned value. |
|
| 6 | + | prefix: u8, |
|
| 7 | + | /// Value used to check payload alignment. |
|
| 8 | + | number: u64, |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | /// Tagged payload with both empty and initialized variants. |
|
| 12 | + | union Value: Copy { Empty, Number(i64), Pair { left: u8, right: u64 } } |
|
| 13 | + | ||
| 14 | + | /// Optional payload in a tagged instruction. |
|
| 15 | + | union Instruction: Copy { Return { value: ?Value } } |
|
| 16 | + | ||
| 17 | + | /// Optional constant reused as a nested optional payload. |
|
| 18 | + | constant PRESENT: ?u32 = 42; |
|
| 19 | + | /// Absent inner payload used in a present outer optional. |
|
| 20 | + | constant ABSENT: ?u32 = nil; |
|
| 21 | + | /// Present aligned record initializer. |
|
| 22 | + | unsafe static RECORD: ?Payload = Payload { prefix: 2, number: 40 }; |
|
| 23 | + | /// Present outer optional that contains a present value. |
|
| 24 | + | unsafe static NESTED: ??u32 = PRESENT; |
|
| 25 | + | /// Present outer optional that contains an absent value. |
|
| 26 | + | unsafe static NESTED_NIL: ??u32 = ABSENT; |
|
| 27 | + | /// Repeated present optional values. |
|
| 28 | + | unsafe static REPEATED: [?u32; 2] = [PRESENT; 2]; |
|
| 29 | + | /// Present nullable slice initializer. |
|
| 30 | + | unsafe static TEXT: ?*[u8] = "answer"; |
|
| 31 | + | ||
| 32 | + | @default unsafe fn main() -> u32 { |
|
| 33 | + | let instructions = &[ |
|
| 34 | + | Instruction::Return { value: Value::Number(42) }, |
|
| 35 | + | Instruction::Return { value: Value::Pair { left: 2, right: 40 } }, |
|
| 36 | + | Instruction::Return { value: Value::Empty } |
|
| 37 | + | ]; |
|
| 38 | + | let case Instruction::Return { value } = instructions[0] else panic; |
|
| 39 | + | let present = value else panic; |
|
| 40 | + | let case Value::Number(number) = present else panic; |
|
| 41 | + | assert number == 42; |
|
| 42 | + | let case Instruction::Return { value: second } = instructions[1] else panic; |
|
| 43 | + | let pair = second else panic; |
|
| 44 | + | let case Value::Pair { left, right } = pair else panic; |
|
| 45 | + | assert left as u64 + right == 42; |
|
| 46 | + | let case Instruction::Return { value: third } = instructions[2] else panic; |
|
| 47 | + | let empty = third else panic; |
|
| 48 | + | let case Value::Empty = empty else panic; |
|
| 49 | + | let rec = RECORD else panic; |
|
| 50 | + | assert rec.prefix as u64 + rec.number == 42; |
|
| 51 | + | let inner = NESTED else panic; |
|
| 52 | + | let answer = inner else panic; |
|
| 53 | + | assert answer == 42; |
|
| 54 | + | let missing = NESTED_NIL else panic; |
|
| 55 | + | assert missing == nil; |
|
| 56 | + | for item in &REPEATED[..] { |
|
| 57 | + | let value = item else panic; |
|
| 58 | + | assert value == 42; |
|
| 59 | + | } |
|
| 60 | + | let text = TEXT else panic; |
|
| 61 | + | assert text.len == 6; |
|
| 62 | + | return number as u32; |
|
| 63 | + | } |
test/tests/data.optional.value.ril
added
+320 -0
| 1 | + | data $PRESENT align 4 { |
|
| 2 | + | w8 1; |
|
| 3 | + | undef * 3; |
|
| 4 | + | w32 42; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | data $ABSENT align 4 { |
|
| 8 | + | w8 0 * 8; |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | data mut $RECORD align 8 { |
|
| 12 | + | w8 1; |
|
| 13 | + | undef * 7; |
|
| 14 | + | w8 2; |
|
| 15 | + | undef * 7; |
|
| 16 | + | w64 40; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | data mut $NESTED align 4 { |
|
| 20 | + | w8 1; |
|
| 21 | + | undef * 3; |
|
| 22 | + | w8 1; |
|
| 23 | + | undef * 3; |
|
| 24 | + | w32 42; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | data mut $NESTED_NIL align 4 { |
|
| 28 | + | w8 1; |
|
| 29 | + | undef * 3; |
|
| 30 | + | w8 0 * 8; |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | data mut $REPEATED align 4 { |
|
| 34 | + | w8 1; |
|
| 35 | + | undef * 3; |
|
| 36 | + | w32 42; |
|
| 37 | + | w8 1; |
|
| 38 | + | undef * 3; |
|
| 39 | + | w32 42; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | data $TEXT$literal$6 align 1 { |
|
| 43 | + | str "answer"; |
|
| 44 | + | } |
|
| 45 | + | ||
| 46 | + | data mut $TEXT align 8 { |
|
| 47 | + | sym $TEXT$literal$6; |
|
| 48 | + | w32 6; |
|
| 49 | + | w32 6; |
|
| 50 | + | } |
|
| 51 | + | ||
| 52 | + | data $main$literal$0 align 8 { |
|
| 53 | + | w8 0; |
|
| 54 | + | undef * 7; |
|
| 55 | + | w8 1; |
|
| 56 | + | undef * 7; |
|
| 57 | + | w8 1; |
|
| 58 | + | undef * 7; |
|
| 59 | + | w64 42; |
|
| 60 | + | undef * 8; |
|
| 61 | + | w8 0; |
|
| 62 | + | undef * 7; |
|
| 63 | + | w8 1; |
|
| 64 | + | undef * 7; |
|
| 65 | + | w8 2; |
|
| 66 | + | undef * 7; |
|
| 67 | + | w8 2; |
|
| 68 | + | undef * 7; |
|
| 69 | + | w64 40; |
|
| 70 | + | w8 0; |
|
| 71 | + | undef * 7; |
|
| 72 | + | w8 1; |
|
| 73 | + | undef * 7; |
|
| 74 | + | w8 0; |
|
| 75 | + | undef * 7; |
|
| 76 | + | undef * 16; |
|
| 77 | + | } |
|
| 78 | + | ||
| 79 | + | fn w32 $main() { |
|
| 80 | + | @entry0 |
|
| 81 | + | copy %0 $main$literal$0; |
|
| 82 | + | reserve %1 16 8; |
|
| 83 | + | store w64 %0 %1 0; |
|
| 84 | + | store w32 3 %1 8; |
|
| 85 | + | store w32 3 %1 12; |
|
| 86 | + | load w32 %2 %1 8; |
|
| 87 | + | br.ult w32 0 %2 @guard#pass1 @guard#trap2; |
|
| 88 | + | @guard#pass1 |
|
| 89 | + | load w64 %3 %1 0; |
|
| 90 | + | reserve %4 40 8; |
|
| 91 | + | blit %4 %3 40; |
|
| 92 | + | load w8 %5 %4 0; |
|
| 93 | + | br.eq w8 %5 0 @success3 @else4; |
|
| 94 | + | @guard#trap2 |
|
| 95 | + | ebreak; |
|
| 96 | + | unreachable; |
|
| 97 | + | @success3 |
|
| 98 | + | add w64 %6 %4 8; |
|
| 99 | + | jmp @merge5; |
|
| 100 | + | @else4 |
|
| 101 | + | unreachable; |
|
| 102 | + | @merge5 |
|
| 103 | + | reserve %7 32 8; |
|
| 104 | + | blit %7 %6 32; |
|
| 105 | + | load w8 %8 %7 0; |
|
| 106 | + | br.ne w32 %8 0 @success6 @else7; |
|
| 107 | + | @success6 |
|
| 108 | + | add w64 %9 %7 8; |
|
| 109 | + | jmp @merge8; |
|
| 110 | + | @else7 |
|
| 111 | + | unreachable; |
|
| 112 | + | @merge8 |
|
| 113 | + | reserve %10 24 8; |
|
| 114 | + | blit %10 %9 24; |
|
| 115 | + | load w8 %11 %10 0; |
|
| 116 | + | br.eq w8 %11 1 @success9 @else10; |
|
| 117 | + | @success9 |
|
| 118 | + | sload w64 %12 %10 8; |
|
| 119 | + | jmp @merge11; |
|
| 120 | + | @else10 |
|
| 121 | + | unreachable; |
|
| 122 | + | @merge11 |
|
| 123 | + | br.eq w64 %12 42 @assert.ok13 @assert.fail12; |
|
| 124 | + | @assert.fail12 |
|
| 125 | + | unreachable; |
|
| 126 | + | @assert.ok13 |
|
| 127 | + | load w32 %13 %1 8; |
|
| 128 | + | br.ult w32 1 %13 @guard#pass14 @guard#trap15; |
|
| 129 | + | @guard#pass14 |
|
| 130 | + | load w64 %14 %1 0; |
|
| 131 | + | mul w64 %15 1 40; |
|
| 132 | + | add w64 %16 %14 %15; |
|
| 133 | + | reserve %17 40 8; |
|
| 134 | + | blit %17 %16 40; |
|
| 135 | + | load w8 %18 %17 0; |
|
| 136 | + | br.eq w8 %18 0 @success16 @else17; |
|
| 137 | + | @guard#trap15 |
|
| 138 | + | ebreak; |
|
| 139 | + | unreachable; |
|
| 140 | + | @success16 |
|
| 141 | + | add w64 %19 %17 8; |
|
| 142 | + | jmp @merge18; |
|
| 143 | + | @else17 |
|
| 144 | + | unreachable; |
|
| 145 | + | @merge18 |
|
| 146 | + | reserve %20 32 8; |
|
| 147 | + | blit %20 %19 32; |
|
| 148 | + | load w8 %21 %20 0; |
|
| 149 | + | br.ne w32 %21 0 @success19 @else20; |
|
| 150 | + | @success19 |
|
| 151 | + | add w64 %22 %20 8; |
|
| 152 | + | jmp @merge21; |
|
| 153 | + | @else20 |
|
| 154 | + | unreachable; |
|
| 155 | + | @merge21 |
|
| 156 | + | reserve %23 24 8; |
|
| 157 | + | blit %23 %22 24; |
|
| 158 | + | load w8 %24 %23 0; |
|
| 159 | + | br.eq w8 %24 2 @success22 @else23; |
|
| 160 | + | @success22 |
|
| 161 | + | add w64 %25 %23 8; |
|
| 162 | + | load w8 %26 %25 0; |
|
| 163 | + | load w64 %27 %25 8; |
|
| 164 | + | jmp @merge24; |
|
| 165 | + | @else23 |
|
| 166 | + | unreachable; |
|
| 167 | + | @merge24 |
|
| 168 | + | zext w8 %28 %26; |
|
| 169 | + | add w64 %29 %28 %27; |
|
| 170 | + | br.eq w64 %29 42 @assert.ok26 @assert.fail25; |
|
| 171 | + | @assert.fail25 |
|
| 172 | + | unreachable; |
|
| 173 | + | @assert.ok26 |
|
| 174 | + | load w32 %30 %1 8; |
|
| 175 | + | br.ult w32 2 %30 @guard#pass27 @guard#trap28; |
|
| 176 | + | @guard#pass27 |
|
| 177 | + | load w64 %31 %1 0; |
|
| 178 | + | mul w64 %32 2 40; |
|
| 179 | + | add w64 %33 %31 %32; |
|
| 180 | + | reserve %34 40 8; |
|
| 181 | + | blit %34 %33 40; |
|
| 182 | + | load w8 %35 %34 0; |
|
| 183 | + | br.eq w8 %35 0 @success29 @else30; |
|
| 184 | + | @guard#trap28 |
|
| 185 | + | ebreak; |
|
| 186 | + | unreachable; |
|
| 187 | + | @success29 |
|
| 188 | + | add w64 %36 %34 8; |
|
| 189 | + | jmp @merge31; |
|
| 190 | + | @else30 |
|
| 191 | + | unreachable; |
|
| 192 | + | @merge31 |
|
| 193 | + | reserve %37 32 8; |
|
| 194 | + | blit %37 %36 32; |
|
| 195 | + | load w8 %38 %37 0; |
|
| 196 | + | br.ne w32 %38 0 @success32 @else33; |
|
| 197 | + | @success32 |
|
| 198 | + | add w64 %39 %37 8; |
|
| 199 | + | jmp @merge34; |
|
| 200 | + | @else33 |
|
| 201 | + | unreachable; |
|
| 202 | + | @merge34 |
|
| 203 | + | reserve %40 24 8; |
|
| 204 | + | blit %40 %39 24; |
|
| 205 | + | load w8 %41 %40 0; |
|
| 206 | + | br.eq w8 %41 0 @success35 @else36; |
|
| 207 | + | @success35 |
|
| 208 | + | jmp @merge37; |
|
| 209 | + | @else36 |
|
| 210 | + | unreachable; |
|
| 211 | + | @merge37 |
|
| 212 | + | copy %42 $RECORD; |
|
| 213 | + | reserve %43 24 8; |
|
| 214 | + | blit %43 %42 24; |
|
| 215 | + | load w8 %44 %43 0; |
|
| 216 | + | br.ne w32 %44 0 @success38 @else39; |
|
| 217 | + | @success38 |
|
| 218 | + | add w64 %45 %43 8; |
|
| 219 | + | jmp @merge40; |
|
| 220 | + | @else39 |
|
| 221 | + | unreachable; |
|
| 222 | + | @merge40 |
|
| 223 | + | load w8 %46 %45 0; |
|
| 224 | + | zext w8 %47 %46; |
|
| 225 | + | load w64 %48 %45 8; |
|
| 226 | + | add w64 %49 %47 %48; |
|
| 227 | + | br.eq w64 %49 42 @assert.ok42 @assert.fail41; |
|
| 228 | + | @assert.fail41 |
|
| 229 | + | unreachable; |
|
| 230 | + | @assert.ok42 |
|
| 231 | + | copy %50 $NESTED; |
|
| 232 | + | reserve %51 12 4; |
|
| 233 | + | blit %51 %50 12; |
|
| 234 | + | load w8 %52 %51 0; |
|
| 235 | + | br.ne w32 %52 0 @success43 @else44; |
|
| 236 | + | @success43 |
|
| 237 | + | add w64 %53 %51 4; |
|
| 238 | + | jmp @merge45; |
|
| 239 | + | @else44 |
|
| 240 | + | unreachable; |
|
| 241 | + | @merge45 |
|
| 242 | + | reserve %54 8 4; |
|
| 243 | + | blit %54 %53 8; |
|
| 244 | + | load w8 %55 %54 0; |
|
| 245 | + | br.ne w32 %55 0 @success46 @else47; |
|
| 246 | + | @success46 |
|
| 247 | + | load w32 %56 %54 4; |
|
| 248 | + | jmp @merge48; |
|
| 249 | + | @else47 |
|
| 250 | + | unreachable; |
|
| 251 | + | @merge48 |
|
| 252 | + | br.eq w32 %56 42 @assert.ok50 @assert.fail49; |
|
| 253 | + | @assert.fail49 |
|
| 254 | + | unreachable; |
|
| 255 | + | @assert.ok50 |
|
| 256 | + | copy %57 $NESTED_NIL; |
|
| 257 | + | reserve %58 12 4; |
|
| 258 | + | blit %58 %57 12; |
|
| 259 | + | load w8 %59 %58 0; |
|
| 260 | + | br.ne w32 %59 0 @success51 @else52; |
|
| 261 | + | @success51 |
|
| 262 | + | add w64 %60 %58 4; |
|
| 263 | + | jmp @merge53; |
|
| 264 | + | @else52 |
|
| 265 | + | unreachable; |
|
| 266 | + | @merge53 |
|
| 267 | + | load w8 %61 %60 0; |
|
| 268 | + | eq w8 %62 %61 0; |
|
| 269 | + | br.ne w32 %62 0 @assert.ok55 @assert.fail54; |
|
| 270 | + | @assert.fail54 |
|
| 271 | + | unreachable; |
|
| 272 | + | @assert.ok55 |
|
| 273 | + | copy %63 $REPEATED; |
|
| 274 | + | reserve %64 16 8; |
|
| 275 | + | store w64 %63 %64 0; |
|
| 276 | + | store w32 2 %64 8; |
|
| 277 | + | store w32 2 %64 12; |
|
| 278 | + | load w32 %65 %64 8; |
|
| 279 | + | load w64 %66 %64 0; |
|
| 280 | + | jmp @loop56(0); |
|
| 281 | + | @loop56(w32 %67) |
|
| 282 | + | br.slt w32 %67 %65 @body57 @merge58; |
|
| 283 | + | @body57 |
|
| 284 | + | mul w64 %68 %67 8; |
|
| 285 | + | add w64 %69 %66 %68; |
|
| 286 | + | reserve %70 8 4; |
|
| 287 | + | blit %70 %69 8; |
|
| 288 | + | load w8 %71 %70 0; |
|
| 289 | + | br.ne w32 %71 0 @success59 @else60; |
|
| 290 | + | @merge58 |
|
| 291 | + | copy %74 $TEXT; |
|
| 292 | + | reserve %75 16 8; |
|
| 293 | + | blit %75 %74 16; |
|
| 294 | + | load w64 %76 %75 0; |
|
| 295 | + | br.ne w32 %76 0 @success64 @else65; |
|
| 296 | + | @success59 |
|
| 297 | + | load w32 %72 %70 4; |
|
| 298 | + | jmp @merge61; |
|
| 299 | + | @else60 |
|
| 300 | + | unreachable; |
|
| 301 | + | @merge61 |
|
| 302 | + | br.eq w32 %72 42 @assert.ok63 @assert.fail62; |
|
| 303 | + | @assert.fail62 |
|
| 304 | + | unreachable; |
|
| 305 | + | @assert.ok63 |
|
| 306 | + | add w32 %73 %67 1; |
|
| 307 | + | jmp @loop56(%73); |
|
| 308 | + | @success64 |
|
| 309 | + | jmp @merge66; |
|
| 310 | + | @else65 |
|
| 311 | + | unreachable; |
|
| 312 | + | @merge66 |
|
| 313 | + | load w32 %77 %75 8; |
|
| 314 | + | br.eq w32 %77 6 @assert.ok68 @assert.fail67; |
|
| 315 | + | @assert.fail67 |
|
| 316 | + | unreachable; |
|
| 317 | + | @assert.ok68 |
|
| 318 | + | zext w32 %79 %12; |
|
| 319 | + | ret %79; |
|
| 320 | + | } |
test/tests/lowering.scratch.context.rad
added
+122 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Exercise all sixteen loop slots and their delayed continue targets. |
|
| 4 | + | fn nestedTargets() -> i32 { |
|
| 5 | + | let mut total: i32 = 0; |
|
| 6 | + | for index0 in 0..3 { |
|
| 7 | + | if index0 == 0 { |
|
| 8 | + | continue; |
|
| 9 | + | } |
|
| 10 | + | for index1 in 0..3 { |
|
| 11 | + | if index1 == 0 { |
|
| 12 | + | continue; |
|
| 13 | + | } |
|
| 14 | + | for index2 in 0..3 { |
|
| 15 | + | if index2 == 0 { |
|
| 16 | + | continue; |
|
| 17 | + | } |
|
| 18 | + | for index3 in 0..3 { |
|
| 19 | + | if index3 == 0 { |
|
| 20 | + | continue; |
|
| 21 | + | } |
|
| 22 | + | for index4 in 0..3 { |
|
| 23 | + | if index4 == 0 { |
|
| 24 | + | continue; |
|
| 25 | + | } |
|
| 26 | + | for index5 in 0..3 { |
|
| 27 | + | if index5 == 0 { |
|
| 28 | + | continue; |
|
| 29 | + | } |
|
| 30 | + | for index6 in 0..3 { |
|
| 31 | + | if index6 == 0 { |
|
| 32 | + | continue; |
|
| 33 | + | } |
|
| 34 | + | for index7 in 0..3 { |
|
| 35 | + | if index7 == 0 { |
|
| 36 | + | continue; |
|
| 37 | + | } |
|
| 38 | + | for index8 in 0..3 { |
|
| 39 | + | if index8 == 0 { |
|
| 40 | + | continue; |
|
| 41 | + | } |
|
| 42 | + | for index9 in 0..3 { |
|
| 43 | + | if index9 == 0 { |
|
| 44 | + | continue; |
|
| 45 | + | } |
|
| 46 | + | for index10 in 0..3 { |
|
| 47 | + | if index10 == 0 { |
|
| 48 | + | continue; |
|
| 49 | + | } |
|
| 50 | + | for index11 in 0..3 { |
|
| 51 | + | if index11 == 0 { |
|
| 52 | + | continue; |
|
| 53 | + | } |
|
| 54 | + | for index12 in 0..3 { |
|
| 55 | + | if index12 == 0 { |
|
| 56 | + | continue; |
|
| 57 | + | } |
|
| 58 | + | for index13 in 0..3 { |
|
| 59 | + | if index13 == 0 { |
|
| 60 | + | continue; |
|
| 61 | + | } |
|
| 62 | + | for index14 in 0..3 { |
|
| 63 | + | if index14 == 0 { |
|
| 64 | + | continue; |
|
| 65 | + | } |
|
| 66 | + | for index15 in 0..3 { |
|
| 67 | + | if index15 == 0 { |
|
| 68 | + | continue; |
|
| 69 | + | } |
|
| 70 | + | set total += 42; |
|
| 71 | + | break; |
|
| 72 | + | } |
|
| 73 | + | break; |
|
| 74 | + | } |
|
| 75 | + | break; |
|
| 76 | + | } |
|
| 77 | + | break; |
|
| 78 | + | } |
|
| 79 | + | break; |
|
| 80 | + | } |
|
| 81 | + | break; |
|
| 82 | + | } |
|
| 83 | + | break; |
|
| 84 | + | } |
|
| 85 | + | break; |
|
| 86 | + | } |
|
| 87 | + | break; |
|
| 88 | + | } |
|
| 89 | + | break; |
|
| 90 | + | } |
|
| 91 | + | break; |
|
| 92 | + | } |
|
| 93 | + | break; |
|
| 94 | + | } |
|
| 95 | + | break; |
|
| 96 | + | } |
|
| 97 | + | break; |
|
| 98 | + | } |
|
| 99 | + | break; |
|
| 100 | + | } |
|
| 101 | + | break; |
|
| 102 | + | } |
|
| 103 | + | return total; |
|
| 104 | + | } |
|
| 105 | + | ||
| 106 | + | /// Use all eight source-parameter bindings. |
|
| 107 | + | fn parameters(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) -> i32 { |
|
| 108 | + | return a + b + c + d + e + f + g + h; |
|
| 109 | + | } |
|
| 110 | + | ||
| 111 | + | /// Bind seven source parameters beside the hidden aggregate-return parameter. |
|
| 112 | + | fn aggregate(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32) -> [i32; 2] { |
|
| 113 | + | return [a + b + c + d + e + f + g, 42]; |
|
| 114 | + | } |
|
| 115 | + | ||
| 116 | + | @default fn main() -> i32 { |
|
| 117 | + | assert parameters(1, 2, 3, 4, 5, 6, 7, 14) == 42; |
|
| 118 | + | let pair = aggregate(1, 2, 3, 4, 5, 6, 21); |
|
| 119 | + | assert pair[0] == 42; |
|
| 120 | + | assert pair[1] == 42; |
|
| 121 | + | return nestedTargets(); |
|
| 122 | + | } |
test/tests/lowering.scratch.context.ril
added
+265 -0
| 1 | + | fn w32 $nestedTargets() { |
|
| 2 | + | @entry0 |
|
| 3 | + | jmp @loop1(0, 0); |
|
| 4 | + | @loop1(w64 %0, w32 %47) |
|
| 5 | + | br.slt w64 %0 3 @body2 @merge3(%47); |
|
| 6 | + | @body2 |
|
| 7 | + | br.eq w64 %0 0 @then4 @merge5; |
|
| 8 | + | @merge3(w32 %49) |
|
| 9 | + | ret %49; |
|
| 10 | + | @then4 |
|
| 11 | + | jmp @step6; |
|
| 12 | + | @merge5 |
|
| 13 | + | jmp @loop7(0, %47); |
|
| 14 | + | @step6 |
|
| 15 | + | add w64 %48 %0 1; |
|
| 16 | + | jmp @loop1(%48, %47); |
|
| 17 | + | @loop7(w64 %1, w32 %45) |
|
| 18 | + | br.slt w64 %1 3 @body8 @merge9(%45); |
|
| 19 | + | @body8 |
|
| 20 | + | br.eq w64 %1 0 @then10 @merge11; |
|
| 21 | + | @merge9(w32 %50) |
|
| 22 | + | jmp @merge3(%50); |
|
| 23 | + | @then10 |
|
| 24 | + | jmp @step12; |
|
| 25 | + | @merge11 |
|
| 26 | + | jmp @loop13(0, %45); |
|
| 27 | + | @step12 |
|
| 28 | + | add w64 %46 %1 1; |
|
| 29 | + | jmp @loop7(%46, %45); |
|
| 30 | + | @loop13(w64 %2, w32 %43) |
|
| 31 | + | br.slt w64 %2 3 @body14 @merge15(%43); |
|
| 32 | + | @body14 |
|
| 33 | + | br.eq w64 %2 0 @then16 @merge17; |
|
| 34 | + | @merge15(w32 %51) |
|
| 35 | + | jmp @merge9(%51); |
|
| 36 | + | @then16 |
|
| 37 | + | jmp @step18; |
|
| 38 | + | @merge17 |
|
| 39 | + | jmp @loop19(0, %43); |
|
| 40 | + | @step18 |
|
| 41 | + | add w64 %44 %2 1; |
|
| 42 | + | jmp @loop13(%44, %43); |
|
| 43 | + | @loop19(w64 %3, w32 %41) |
|
| 44 | + | br.slt w64 %3 3 @body20 @merge21(%41); |
|
| 45 | + | @body20 |
|
| 46 | + | br.eq w64 %3 0 @then22 @merge23; |
|
| 47 | + | @merge21(w32 %52) |
|
| 48 | + | jmp @merge15(%52); |
|
| 49 | + | @then22 |
|
| 50 | + | jmp @step24; |
|
| 51 | + | @merge23 |
|
| 52 | + | jmp @loop25(0, %41); |
|
| 53 | + | @step24 |
|
| 54 | + | add w64 %42 %3 1; |
|
| 55 | + | jmp @loop19(%42, %41); |
|
| 56 | + | @loop25(w64 %4, w32 %39) |
|
| 57 | + | br.slt w64 %4 3 @body26 @merge27(%39); |
|
| 58 | + | @body26 |
|
| 59 | + | br.eq w64 %4 0 @then28 @merge29; |
|
| 60 | + | @merge27(w32 %53) |
|
| 61 | + | jmp @merge21(%53); |
|
| 62 | + | @then28 |
|
| 63 | + | jmp @step30; |
|
| 64 | + | @merge29 |
|
| 65 | + | jmp @loop31(0, %39); |
|
| 66 | + | @step30 |
|
| 67 | + | add w64 %40 %4 1; |
|
| 68 | + | jmp @loop25(%40, %39); |
|
| 69 | + | @loop31(w64 %5, w32 %37) |
|
| 70 | + | br.slt w64 %5 3 @body32 @merge33(%37); |
|
| 71 | + | @body32 |
|
| 72 | + | br.eq w64 %5 0 @then34 @merge35; |
|
| 73 | + | @merge33(w32 %54) |
|
| 74 | + | jmp @merge27(%54); |
|
| 75 | + | @then34 |
|
| 76 | + | jmp @step36; |
|
| 77 | + | @merge35 |
|
| 78 | + | jmp @loop37(0, %37); |
|
| 79 | + | @step36 |
|
| 80 | + | add w64 %38 %5 1; |
|
| 81 | + | jmp @loop31(%38, %37); |
|
| 82 | + | @loop37(w64 %6, w32 %35) |
|
| 83 | + | br.slt w64 %6 3 @body38 @merge39(%35); |
|
| 84 | + | @body38 |
|
| 85 | + | br.eq w64 %6 0 @then40 @merge41; |
|
| 86 | + | @merge39(w32 %55) |
|
| 87 | + | jmp @merge33(%55); |
|
| 88 | + | @then40 |
|
| 89 | + | jmp @step42; |
|
| 90 | + | @merge41 |
|
| 91 | + | jmp @loop43(0, %35); |
|
| 92 | + | @step42 |
|
| 93 | + | add w64 %36 %6 1; |
|
| 94 | + | jmp @loop37(%36, %35); |
|
| 95 | + | @loop43(w64 %7, w32 %33) |
|
| 96 | + | br.slt w64 %7 3 @body44 @merge45(%33); |
|
| 97 | + | @body44 |
|
| 98 | + | br.eq w64 %7 0 @then46 @merge47; |
|
| 99 | + | @merge45(w32 %56) |
|
| 100 | + | jmp @merge39(%56); |
|
| 101 | + | @then46 |
|
| 102 | + | jmp @step48; |
|
| 103 | + | @merge47 |
|
| 104 | + | jmp @loop49(0, %33); |
|
| 105 | + | @step48 |
|
| 106 | + | add w64 %34 %7 1; |
|
| 107 | + | jmp @loop43(%34, %33); |
|
| 108 | + | @loop49(w64 %8, w32 %31) |
|
| 109 | + | br.slt w64 %8 3 @body50 @merge51(%31); |
|
| 110 | + | @body50 |
|
| 111 | + | br.eq w64 %8 0 @then52 @merge53; |
|
| 112 | + | @merge51(w32 %57) |
|
| 113 | + | jmp @merge45(%57); |
|
| 114 | + | @then52 |
|
| 115 | + | jmp @step54; |
|
| 116 | + | @merge53 |
|
| 117 | + | jmp @loop55(0, %31); |
|
| 118 | + | @step54 |
|
| 119 | + | add w64 %32 %8 1; |
|
| 120 | + | jmp @loop49(%32, %31); |
|
| 121 | + | @loop55(w64 %9, w32 %29) |
|
| 122 | + | br.slt w64 %9 3 @body56 @merge57(%29); |
|
| 123 | + | @body56 |
|
| 124 | + | br.eq w64 %9 0 @then58 @merge59; |
|
| 125 | + | @merge57(w32 %58) |
|
| 126 | + | jmp @merge51(%58); |
|
| 127 | + | @then58 |
|
| 128 | + | jmp @step60; |
|
| 129 | + | @merge59 |
|
| 130 | + | jmp @loop61(0, %29); |
|
| 131 | + | @step60 |
|
| 132 | + | add w64 %30 %9 1; |
|
| 133 | + | jmp @loop55(%30, %29); |
|
| 134 | + | @loop61(w64 %10, w32 %27) |
|
| 135 | + | br.slt w64 %10 3 @body62 @merge63(%27); |
|
| 136 | + | @body62 |
|
| 137 | + | br.eq w64 %10 0 @then64 @merge65; |
|
| 138 | + | @merge63(w32 %59) |
|
| 139 | + | jmp @merge57(%59); |
|
| 140 | + | @then64 |
|
| 141 | + | jmp @step66; |
|
| 142 | + | @merge65 |
|
| 143 | + | jmp @loop67(0, %27); |
|
| 144 | + | @step66 |
|
| 145 | + | add w64 %28 %10 1; |
|
| 146 | + | jmp @loop61(%28, %27); |
|
| 147 | + | @loop67(w64 %11, w32 %25) |
|
| 148 | + | br.slt w64 %11 3 @body68 @merge69(%25); |
|
| 149 | + | @body68 |
|
| 150 | + | br.eq w64 %11 0 @then70 @merge71; |
|
| 151 | + | @merge69(w32 %60) |
|
| 152 | + | jmp @merge63(%60); |
|
| 153 | + | @then70 |
|
| 154 | + | jmp @step72; |
|
| 155 | + | @merge71 |
|
| 156 | + | jmp @loop73(0, %25); |
|
| 157 | + | @step72 |
|
| 158 | + | add w64 %26 %11 1; |
|
| 159 | + | jmp @loop67(%26, %25); |
|
| 160 | + | @loop73(w64 %12, w32 %23) |
|
| 161 | + | br.slt w64 %12 3 @body74 @merge75(%23); |
|
| 162 | + | @body74 |
|
| 163 | + | br.eq w64 %12 0 @then76 @merge77; |
|
| 164 | + | @merge75(w32 %61) |
|
| 165 | + | jmp @merge69(%61); |
|
| 166 | + | @then76 |
|
| 167 | + | jmp @step78; |
|
| 168 | + | @merge77 |
|
| 169 | + | jmp @loop79(0, %23); |
|
| 170 | + | @step78 |
|
| 171 | + | add w64 %24 %12 1; |
|
| 172 | + | jmp @loop73(%24, %23); |
|
| 173 | + | @loop79(w64 %13, w32 %21) |
|
| 174 | + | br.slt w64 %13 3 @body80 @merge81(%21); |
|
| 175 | + | @body80 |
|
| 176 | + | br.eq w64 %13 0 @then82 @merge83; |
|
| 177 | + | @merge81(w32 %62) |
|
| 178 | + | jmp @merge75(%62); |
|
| 179 | + | @then82 |
|
| 180 | + | jmp @step84; |
|
| 181 | + | @merge83 |
|
| 182 | + | jmp @loop85(0, %21); |
|
| 183 | + | @step84 |
|
| 184 | + | add w64 %22 %13 1; |
|
| 185 | + | jmp @loop79(%22, %21); |
|
| 186 | + | @loop85(w64 %14, w32 %19) |
|
| 187 | + | br.slt w64 %14 3 @body86 @merge87(%19); |
|
| 188 | + | @body86 |
|
| 189 | + | br.eq w64 %14 0 @then88 @merge89; |
|
| 190 | + | @merge87(w32 %63) |
|
| 191 | + | jmp @merge81(%63); |
|
| 192 | + | @then88 |
|
| 193 | + | jmp @step90; |
|
| 194 | + | @merge89 |
|
| 195 | + | jmp @loop91(0, %19); |
|
| 196 | + | @step90 |
|
| 197 | + | add w64 %20 %14 1; |
|
| 198 | + | jmp @loop85(%20, %19); |
|
| 199 | + | @loop91(w64 %15, w32 %16) |
|
| 200 | + | br.slt w64 %15 3 @body92 @merge93(%16); |
|
| 201 | + | @body92 |
|
| 202 | + | br.eq w64 %15 0 @then94 @merge95; |
|
| 203 | + | @merge93(w32 %64) |
|
| 204 | + | jmp @merge87(%64); |
|
| 205 | + | @then94 |
|
| 206 | + | jmp @step96; |
|
| 207 | + | @merge95 |
|
| 208 | + | add w32 %17 %16 42; |
|
| 209 | + | jmp @merge93(%17); |
|
| 210 | + | @step96 |
|
| 211 | + | add w64 %18 %15 1; |
|
| 212 | + | jmp @loop91(%18, %16); |
|
| 213 | + | } |
|
| 214 | + | ||
| 215 | + | fn w32 $parameters(w32 %0, w32 %1, w32 %2, w32 %3, w32 %4, w32 %5, w32 %6, w32 %7) { |
|
| 216 | + | @entry0 |
|
| 217 | + | add w32 %8 %0 %1; |
|
| 218 | + | add w32 %9 %8 %2; |
|
| 219 | + | add w32 %10 %9 %3; |
|
| 220 | + | add w32 %11 %10 %4; |
|
| 221 | + | add w32 %12 %11 %5; |
|
| 222 | + | add w32 %13 %12 %6; |
|
| 223 | + | add w32 %14 %13 %7; |
|
| 224 | + | ret %14; |
|
| 225 | + | } |
|
| 226 | + | ||
| 227 | + | fn w64 $aggregate(w64 %0, w32 %1, w32 %2, w32 %3, w32 %4, w32 %5, w32 %6, w32 %7) { |
|
| 228 | + | @entry0 |
|
| 229 | + | reserve %8 8 4; |
|
| 230 | + | add w32 %9 %1 %2; |
|
| 231 | + | add w32 %10 %9 %3; |
|
| 232 | + | add w32 %11 %10 %4; |
|
| 233 | + | add w32 %12 %11 %5; |
|
| 234 | + | add w32 %13 %12 %6; |
|
| 235 | + | add w32 %14 %13 %7; |
|
| 236 | + | store w32 %14 %8 0; |
|
| 237 | + | store w32 42 %8 4; |
|
| 238 | + | blit %0 %8 8; |
|
| 239 | + | ret %0; |
|
| 240 | + | } |
|
| 241 | + | ||
| 242 | + | fn w32 $main() { |
|
| 243 | + | @entry0 |
|
| 244 | + | call w32 %0 $parameters(1, 2, 3, 4, 5, 6, 7, 14); |
|
| 245 | + | br.eq w32 %0 42 @assert.ok2 @assert.fail1; |
|
| 246 | + | @assert.fail1 |
|
| 247 | + | unreachable; |
|
| 248 | + | @assert.ok2 |
|
| 249 | + | reserve %1 8 4; |
|
| 250 | + | call w64 %2 $aggregate(%1, 1, 2, 3, 4, 5, 6, 21); |
|
| 251 | + | sload w32 %3 %2 0; |
|
| 252 | + | br.eq w32 %3 42 @assert.ok4 @assert.fail3; |
|
| 253 | + | @assert.fail3 |
|
| 254 | + | unreachable; |
|
| 255 | + | @assert.ok4 |
|
| 256 | + | mul w64 %4 1 4; |
|
| 257 | + | add w64 %5 %2 %4; |
|
| 258 | + | sload w32 %6 %5 0; |
|
| 259 | + | br.eq w32 %6 42 @assert.ok6 @assert.fail5; |
|
| 260 | + | @assert.fail5 |
|
| 261 | + | unreachable; |
|
| 262 | + | @assert.ok6 |
|
| 263 | + | call w32 %7 $nestedTargets(); |
|
| 264 | + | ret %7; |
|
| 265 | + | } |
test/tests/match.pointer.bindings.rad
added
+32 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record Item: Copy { value: u32 } |
|
| 4 | + | ||
| 5 | + | @default fn main() -> u32 { |
|
| 6 | + | let mut item = Item { value: 0 }; |
|
| 7 | + | match &mut item { |
|
| 8 | + | case Item { value } => { |
|
| 9 | + | set *value = 21; |
|
| 10 | + | }, |
|
| 11 | + | else => panic, |
|
| 12 | + | } |
|
| 13 | + | assert item.value == 21; |
|
| 14 | + | ||
| 15 | + | let mut values: [u32; 2] = [10, 11]; |
|
| 16 | + | match &mut values { |
|
| 17 | + | case [first, second] => { |
|
| 18 | + | set *first += 1; |
|
| 19 | + | set *second += 1; |
|
| 20 | + | }, |
|
| 21 | + | } |
|
| 22 | + | assert values[0] == 11; |
|
| 23 | + | assert values[1] == 12; |
|
| 24 | + | ||
| 25 | + | let mut result: u32 = 0; |
|
| 26 | + | match &mut result { |
|
| 27 | + | value => { |
|
| 28 | + | set *value = item.value + values[0] + values[1] - 2; |
|
| 29 | + | }, |
|
| 30 | + | } |
|
| 31 | + | return result; |
|
| 32 | + | } |
test/tests/match.pointer.bindings.ril
added
+68 -0
| 1 | + | fn w32 $main() { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %0 4 4; |
|
| 4 | + | store w32 0 %0 0; |
|
| 5 | + | jmp @arm1; |
|
| 6 | + | @arm1 |
|
| 7 | + | jmp @case2; |
|
| 8 | + | @case2 |
|
| 9 | + | store w32 21 %0 0; |
|
| 10 | + | jmp @merge4; |
|
| 11 | + | @arm3 |
|
| 12 | + | jmp @else5; |
|
| 13 | + | @merge4 |
|
| 14 | + | load w32 %1 %0 0; |
|
| 15 | + | br.eq w32 %1 21 @assert.ok8 @assert.fail7; |
|
| 16 | + | @else5 |
|
| 17 | + | unreachable; |
|
| 18 | + | @assert.fail7 |
|
| 19 | + | unreachable; |
|
| 20 | + | @assert.ok8 |
|
| 21 | + | reserve %2 8 4; |
|
| 22 | + | store w32 10 %2 0; |
|
| 23 | + | store w32 11 %2 4; |
|
| 24 | + | jmp @arm9; |
|
| 25 | + | @arm9 |
|
| 26 | + | jmp @case10; |
|
| 27 | + | @case10 |
|
| 28 | + | add w64 %3 %2 4; |
|
| 29 | + | load w32 %4 %2 0; |
|
| 30 | + | add w32 %5 %4 1; |
|
| 31 | + | store w32 %5 %2 0; |
|
| 32 | + | load w32 %6 %3 0; |
|
| 33 | + | add w32 %7 %6 1; |
|
| 34 | + | store w32 %7 %3 0; |
|
| 35 | + | jmp @merge12; |
|
| 36 | + | @merge12 |
|
| 37 | + | load w32 %8 %2 0; |
|
| 38 | + | br.eq w32 %8 11 @assert.ok14 @assert.fail13; |
|
| 39 | + | @assert.fail13 |
|
| 40 | + | unreachable; |
|
| 41 | + | @assert.ok14 |
|
| 42 | + | mul w64 %9 1 4; |
|
| 43 | + | add w64 %10 %2 %9; |
|
| 44 | + | load w32 %11 %10 0; |
|
| 45 | + | br.eq w32 %11 12 @assert.ok16 @assert.fail15; |
|
| 46 | + | @assert.fail15 |
|
| 47 | + | unreachable; |
|
| 48 | + | @assert.ok16 |
|
| 49 | + | reserve %12 4 4; |
|
| 50 | + | store w32 0 %12 0; |
|
| 51 | + | jmp @arm17; |
|
| 52 | + | @arm17 |
|
| 53 | + | jmp @case18; |
|
| 54 | + | @case18 |
|
| 55 | + | load w32 %13 %0 0; |
|
| 56 | + | load w32 %14 %2 0; |
|
| 57 | + | add w32 %15 %13 %14; |
|
| 58 | + | mul w64 %16 1 4; |
|
| 59 | + | add w64 %17 %2 %16; |
|
| 60 | + | load w32 %18 %17 0; |
|
| 61 | + | add w32 %19 %15 %18; |
|
| 62 | + | sub w32 %20 %19 2; |
|
| 63 | + | store w32 %20 %12 0; |
|
| 64 | + | jmp @merge20; |
|
| 65 | + | @merge20 |
|
| 66 | + | load w32 %21 %12 0; |
|
| 67 | + | ret %21; |
|
| 68 | + | } |
test/tests/ref.qualified.static.rad
added
+12 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | mod storage; |
|
| 4 | + | ||
| 5 | + | /// Update a statically stored scalar through a checked mutable reference. |
|
| 6 | + | fn update(value: &mut i32) { set *value = 42; } |
|
| 7 | + | ||
| 8 | + | /// Return the value written through the qualified reference. |
|
| 9 | + | @default fn main() -> i32 { |
|
| 10 | + | update(&mut storage::VALUE); |
|
| 11 | + | return storage::VALUE; |
|
| 12 | + | } |
test/tests/ref.qualified.static/storage.rad
added
+4 -0
| 1 | + | //! Storage for the qualified static reference test. |
|
| 2 | + | ||
| 3 | + | /// Mutable scalar used through a module-qualified checked borrow. |
|
| 4 | + | export static VALUE: i32 = 7; |
test/tests/regions.body.scope.rad
added
+9 -0
| 1 | + | // Function bodies use the same region identity as their signatures. |
|
| 2 | + | ||
| 3 | + | fn read_1 'r (p: &'r u8) -> u8 { let q: &'r u8 = p; return *q; } |
|
| 4 | + | ||
| 5 | + | fn read_2 'r (p: &'r [u8]) -> u8 { let q: &'r [u8] = p; return q[0]; } |
|
| 6 | + | ||
| 7 | + | fn consume_3(p: &u8) {} |
|
| 8 | + | ||
| 9 | + | fn call_3 'r (p: &'r u8) { consume_3(p); } |
test/tests/regions.body.scope.ril
added
+31 -0
| 1 | + | fn w8 $read_1(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w8 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w8 $read_2(w64 %0) { |
|
| 8 | + | @entry0 |
|
| 9 | + | reserve %1 16 8; |
|
| 10 | + | blit %1 %0 16; |
|
| 11 | + | load w32 %2 %1 8; |
|
| 12 | + | br.ult w32 0 %2 @guard#pass1 @guard#trap2; |
|
| 13 | + | @guard#pass1 |
|
| 14 | + | load w64 %3 %1 0; |
|
| 15 | + | load w8 %4 %3 0; |
|
| 16 | + | ret %4; |
|
| 17 | + | @guard#trap2 |
|
| 18 | + | ebreak; |
|
| 19 | + | unreachable; |
|
| 20 | + | } |
|
| 21 | + | ||
| 22 | + | fn w64 $consume_3(w64 %0) { |
|
| 23 | + | @entry0 |
|
| 24 | + | ret; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | fn w64 $call_3(w64 %0) { |
|
| 28 | + | @entry0 |
|
| 29 | + | call w64 $consume_3(%0); |
|
| 30 | + | ret; |
|
| 31 | + | } |
test/tests/regions.borrow.calls.rad
added
+30 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record Pair { |
|
| 4 | + | left: u32, |
|
| 5 | + | right: u32, |
|
| 6 | + | } |
|
| 7 | + | ||
| 8 | + | fn read 'r (p: &'r u32) -> u32 { return *p; } |
|
| 9 | + | fn bump 'r (p: &'r mut u32) { set *p += 1; } |
|
| 10 | + | fn apply 'r (p: &'r u32, op: fn(&'r u32) -> u32) -> u32 { return op(p); } |
|
| 11 | + | ||
| 12 | + | fn recurse 'r (p: &'r u32, depth: u32) -> u32 { |
|
| 13 | + | if depth == 0 { |
|
| 14 | + | return read(p); |
|
| 15 | + | } |
|
| 16 | + | return recurse(p, depth - 1); |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | @default fn main() -> u32 { |
|
| 20 | + | let mut pair = Pair { left: 20, right: 21 }; |
|
| 21 | + | let left: 'whole = &mut pair.left, right = &mut pair.right in { |
|
| 22 | + | let p: 'change = &mut *left in { bump(p); } |
|
| 23 | + | let l: 'child = &*left, r = &*right in { |
|
| 24 | + | assert apply(l, read 'child) == 21; |
|
| 25 | + | assert recurse(r, 2) == 21; |
|
| 26 | + | } |
|
| 27 | + | set *left += *right; |
|
| 28 | + | } |
|
| 29 | + | return pair.left; |
|
| 30 | + | } |
test/tests/regions.borrow.calls.ril
added
+57 -0
| 1 | + | fn w32 $read(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w64 $bump(w64 %0) { |
|
| 8 | + | @entry0 |
|
| 9 | + | load w32 %1 %0 0; |
|
| 10 | + | add w32 %2 %1 1; |
|
| 11 | + | store w32 %2 %0 0; |
|
| 12 | + | ret; |
|
| 13 | + | } |
|
| 14 | + | ||
| 15 | + | fn w32 $apply(w64 %0, w64 %1) { |
|
| 16 | + | @entry0 |
|
| 17 | + | call w32 %2 %1(%0); |
|
| 18 | + | ret %2; |
|
| 19 | + | } |
|
| 20 | + | ||
| 21 | + | fn w32 $recurse(w64 %0, w32 %1) { |
|
| 22 | + | @entry0 |
|
| 23 | + | br.eq w32 %1 0 @then1 @merge2; |
|
| 24 | + | @then1 |
|
| 25 | + | call w32 %2 $read(%0); |
|
| 26 | + | ret %2; |
|
| 27 | + | @merge2 |
|
| 28 | + | sub w32 %3 %1 1; |
|
| 29 | + | call w32 %4 $recurse(%0, %3); |
|
| 30 | + | ret %4; |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | fn w32 $main() { |
|
| 34 | + | @entry0 |
|
| 35 | + | reserve %0 8 4; |
|
| 36 | + | store w32 20 %0 0; |
|
| 37 | + | store w32 21 %0 4; |
|
| 38 | + | add w64 %1 %0 4; |
|
| 39 | + | call w64 $bump(%0); |
|
| 40 | + | copy %2 $read; |
|
| 41 | + | call w32 %3 $apply(%0, %2); |
|
| 42 | + | br.eq w32 %3 21 @assert.ok2 @assert.fail1; |
|
| 43 | + | @assert.fail1 |
|
| 44 | + | unreachable; |
|
| 45 | + | @assert.ok2 |
|
| 46 | + | call w32 %4 $recurse(%1, 2); |
|
| 47 | + | br.eq w32 %4 21 @assert.ok4 @assert.fail3; |
|
| 48 | + | @assert.fail3 |
|
| 49 | + | unreachable; |
|
| 50 | + | @assert.ok4 |
|
| 51 | + | load w32 %5 %0 0; |
|
| 52 | + | load w32 %6 %1 0; |
|
| 53 | + | add w32 %7 %5 %6; |
|
| 54 | + | store w32 %7 %0 0; |
|
| 55 | + | load w32 %8 %0 0; |
|
| 56 | + | ret %8; |
|
| 57 | + | } |
test/tests/regions.borrow.control.rad
added
+32 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | union Failure { Failed } |
|
| 4 | + | ||
| 5 | + | fn fail 'r (p: &'r mut u32) throws (Failure) { |
|
| 6 | + | set *p += 1; |
|
| 7 | + | throw Failure::Failed; |
|
| 8 | + | } |
|
| 9 | + | ||
| 10 | + | @default fn main() -> u32 { |
|
| 11 | + | let mut value: u32 = 37; |
|
| 12 | + | for i in 0..3 { |
|
| 13 | + | let p: 'iteration = &mut value in { |
|
| 14 | + | set *p += 1; |
|
| 15 | + | if i < 2 { |
|
| 16 | + | continue; |
|
| 17 | + | } |
|
| 18 | + | break; |
|
| 19 | + | } |
|
| 20 | + | } |
|
| 21 | + | let p: 'errors = &mut value in { |
|
| 22 | + | let q: 'first = &mut *p in { |
|
| 23 | + | try fail(q) catch { |
|
| 24 | + | }; |
|
| 25 | + | } |
|
| 26 | + | let q: 'second = &mut *p in { |
|
| 27 | + | try fail(q) catch { |
|
| 28 | + | }; |
|
| 29 | + | } |
|
| 30 | + | } |
|
| 31 | + | return value; |
|
| 32 | + | } |
test/tests/regions.borrow.control.ril
added
+53 -0
| 1 | + | fn w64 $fail(w64 %0, w64 %1) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %2 %1 0; |
|
| 4 | + | add w32 %3 %2 1; |
|
| 5 | + | store w32 %3 %1 0; |
|
| 6 | + | reserve %4 9 8; |
|
| 7 | + | store w64 1 %4 0; |
|
| 8 | + | store w8 0 %4 8; |
|
| 9 | + | blit %0 %4 9; |
|
| 10 | + | ret %0; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $main() { |
|
| 14 | + | @entry0 |
|
| 15 | + | reserve %0 4 4; |
|
| 16 | + | store w32 37 %0 0; |
|
| 17 | + | jmp @loop1(0, %0); |
|
| 18 | + | @loop1(w64 %1, w32 %2) |
|
| 19 | + | br.slt w64 %1 3 @body2 @merge3; |
|
| 20 | + | @body2 |
|
| 21 | + | load w32 %3 %2 0; |
|
| 22 | + | add w32 %4 %3 1; |
|
| 23 | + | store w32 %4 %2 0; |
|
| 24 | + | br.slt w64 %1 2 @then4 @merge5; |
|
| 25 | + | @merge3 |
|
| 26 | + | reserve %7 9 8; |
|
| 27 | + | call w64 %8 $fail(%7, %2); |
|
| 28 | + | load w64 %9 %8 0; |
|
| 29 | + | br.ne w32 %9 0 @err8 @ok7; |
|
| 30 | + | @then4 |
|
| 31 | + | jmp @step6; |
|
| 32 | + | @merge5 |
|
| 33 | + | jmp @merge3; |
|
| 34 | + | @step6 |
|
| 35 | + | add w64 %5 %1 1; |
|
| 36 | + | jmp @loop1(%5, %2); |
|
| 37 | + | @ok7 |
|
| 38 | + | jmp @merge9; |
|
| 39 | + | @err8 |
|
| 40 | + | jmp @merge9; |
|
| 41 | + | @merge9 |
|
| 42 | + | reserve %11 9 8; |
|
| 43 | + | call w64 %12 $fail(%11, %2); |
|
| 44 | + | load w64 %13 %12 0; |
|
| 45 | + | br.ne w32 %13 0 @err11 @ok10; |
|
| 46 | + | @ok10 |
|
| 47 | + | jmp @merge12; |
|
| 48 | + | @err11 |
|
| 49 | + | jmp @merge12; |
|
| 50 | + | @merge12 |
|
| 51 | + | load w32 %16 %2 0; |
|
| 52 | + | ret %16; |
|
| 53 | + | } |
test/tests/regions.borrow.erasure.rad
added
+9 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | fn bump 'r (p: &'r mut u32) { set *p += 1; } |
|
| 4 | + | @default fn main() -> u32 { |
|
| 5 | + | let mut x: u32 = 40; |
|
| 6 | + | let p: 'a = &mut x in { bump(p); } |
|
| 7 | + | let p: 'b = &mut x in { bump 'b (p); } |
|
| 8 | + | return x; |
|
| 9 | + | } |
test/tests/regions.borrow.erasure.ril
added
+17 -0
| 1 | + | fn w64 $bump(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | add w32 %2 %1 1; |
|
| 5 | + | store w32 %2 %0 0; |
|
| 6 | + | ret; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w32 $main() { |
|
| 10 | + | @entry0 |
|
| 11 | + | reserve %0 4 4; |
|
| 12 | + | store w32 40 %0 0; |
|
| 13 | + | call w64 $bump(%0); |
|
| 14 | + | call w64 $bump(%0); |
|
| 15 | + | load w32 %1 %0 0; |
|
| 16 | + | ret %1; |
|
| 17 | + | } |
test/tests/regions.borrow.headers.rad
added
+11 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | @default fn main() -> u32 { |
|
| 4 | + | let x: u32 = 20; |
|
| 5 | + | let a: u32 = 22; |
|
| 6 | + | let x: 'r = &a, other = &x in { |
|
| 7 | + | assert *x == 22; |
|
| 8 | + | assert *other == 20; |
|
| 9 | + | return *x + *other; |
|
| 10 | + | } |
|
| 11 | + | } |
test/tests/regions.borrow.headers.ril
added
+21 -0
| 1 | + | fn w32 $main() { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %0 4 4; |
|
| 4 | + | store w32 20 %0 0; |
|
| 5 | + | reserve %1 4 4; |
|
| 6 | + | store w32 22 %1 0; |
|
| 7 | + | load w32 %2 %1 0; |
|
| 8 | + | br.eq w32 %2 22 @assert.ok2 @assert.fail1; |
|
| 9 | + | @assert.fail1 |
|
| 10 | + | unreachable; |
|
| 11 | + | @assert.ok2 |
|
| 12 | + | load w32 %3 %0 0; |
|
| 13 | + | br.eq w32 %3 20 @assert.ok4 @assert.fail3; |
|
| 14 | + | @assert.fail3 |
|
| 15 | + | unreachable; |
|
| 16 | + | @assert.ok4 |
|
| 17 | + | load w32 %4 %1 0; |
|
| 18 | + | load w32 %5 %0 0; |
|
| 19 | + | add w32 %6 %4 %5; |
|
| 20 | + | ret %6; |
|
| 21 | + | } |
test/tests/regions.borrow.local.rad
added
+5 -0
| 1 | + | // A block-local value cannot supply storage for the whole enclosing region. |
|
| 2 | + | ||
| 3 | + | fn read 'r (p: &'r u32) -> u32 { return *p; } |
|
| 4 | + | ||
| 5 | + | fn run() { let x: u32 = 1; let p: 'outer = &x in { let y: u32 = 2; let q: 'inner = &y in { assert read(q) == 2; } } } |
test/tests/regions.borrow.local.ril
added
+19 -0
| 1 | + | fn w32 $read(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w64 $run() { |
|
| 8 | + | @entry0 |
|
| 9 | + | reserve %0 4 4; |
|
| 10 | + | store w32 1 %0 0; |
|
| 11 | + | reserve %1 4 4; |
|
| 12 | + | store w32 2 %1 0; |
|
| 13 | + | call w32 %2 $read(%1); |
|
| 14 | + | br.eq w32 %2 2 @assert.ok2 @assert.fail1; |
|
| 15 | + | @assert.fail1 |
|
| 16 | + | unreachable; |
|
| 17 | + | @assert.ok2 |
|
| 18 | + | ret; |
|
| 19 | + | } |
test/tests/regions.borrow.siblings.rad
added
+3 -0
| 1 | + | // Borrow headers require existing places and accessible, distinct region names. |
|
| 2 | + | ||
| 3 | + | fn run() { let x: u32 = 1; let p: 'r = &x in {} let p: 'r = &x in {} } |
test/tests/regions.borrow.siblings.ril
added
+6 -0
| 1 | + | fn w64 $run() { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %0 4 4; |
|
| 4 | + | store w32 1 %0 0; |
|
| 5 | + | ret; |
|
| 6 | + | } |
test/tests/regions.borrow.valid.rad
added
+17 -0
| 1 | + | // Concrete borrow blocks supply named regions to generic functions. |
|
| 2 | + | ||
| 3 | + | fn read_1 'r (p: &'r u32) -> u32 { return *p; } |
|
| 4 | + | ||
| 5 | + | fn run_1() -> u32 { let x: u32 = 42; let p: 'local = &x in { return read_1(p); } } |
|
| 6 | + | ||
| 7 | + | fn bump_2 'r (p: &'r mut u32) { set *p += 1; } |
|
| 8 | + | ||
| 9 | + | fn run_2() -> u32 { let mut x: u32 = 41; let p: 'local = &mut x in { bump_2(p); } return x; } |
|
| 10 | + | ||
| 11 | + | fn run_3() { let mut x: u32 = 1; let p: 'a = &mut x in { let q: 'b = &mut *p in { set *q = 2; } set *p = 3; } set x = 4; } |
|
| 12 | + | ||
| 13 | + | fn run_4 'a (p: &'a mut u32) { let q: 'b = &mut *p where 'a: 'b in { set *q = 2; } set *p = 3; } |
|
| 14 | + | ||
| 15 | + | record Pair_5 { a: u32, b: u32 } |
|
| 16 | + | ||
| 17 | + | fn run_5() { let mut pair = Pair_5 { a: 1, b: 2 }; let a: 'r = &mut pair.a, b = &mut pair.b in { set *a = *b; } } |
test/tests/regions.borrow.valid.ril
added
+58 -0
| 1 | + | fn w32 $read_1(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w32 $run_1() { |
|
| 8 | + | @entry0 |
|
| 9 | + | reserve %0 4 4; |
|
| 10 | + | store w32 42 %0 0; |
|
| 11 | + | call w32 %1 $read_1(%0); |
|
| 12 | + | ret %1; |
|
| 13 | + | } |
|
| 14 | + | ||
| 15 | + | fn w64 $bump_2(w64 %0) { |
|
| 16 | + | @entry0 |
|
| 17 | + | load w32 %1 %0 0; |
|
| 18 | + | add w32 %2 %1 1; |
|
| 19 | + | store w32 %2 %0 0; |
|
| 20 | + | ret; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | fn w32 $run_2() { |
|
| 24 | + | @entry0 |
|
| 25 | + | reserve %0 4 4; |
|
| 26 | + | store w32 41 %0 0; |
|
| 27 | + | call w64 $bump_2(%0); |
|
| 28 | + | load w32 %1 %0 0; |
|
| 29 | + | ret %1; |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | fn w64 $run_3() { |
|
| 33 | + | @entry0 |
|
| 34 | + | reserve %0 4 4; |
|
| 35 | + | store w32 1 %0 0; |
|
| 36 | + | store w32 2 %0 0; |
|
| 37 | + | store w32 3 %0 0; |
|
| 38 | + | store w32 4 %0 0; |
|
| 39 | + | ret; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | fn w64 $run_4(w64 %0) { |
|
| 43 | + | @entry0 |
|
| 44 | + | store w32 2 %0 0; |
|
| 45 | + | store w32 3 %0 0; |
|
| 46 | + | ret; |
|
| 47 | + | } |
|
| 48 | + | ||
| 49 | + | fn w64 $run_5() { |
|
| 50 | + | @entry0 |
|
| 51 | + | reserve %0 8 4; |
|
| 52 | + | store w32 1 %0 0; |
|
| 53 | + | store w32 2 %0 4; |
|
| 54 | + | add w64 %1 %0 4; |
|
| 55 | + | load w32 %2 %1 0; |
|
| 56 | + | store w32 %2 %0 0; |
|
| 57 | + | ret; |
|
| 58 | + | } |
test/tests/regions.calls.callback.rad
added
+7 -0
| 1 | + | // Callback signatures preserve the same region substitution as data arguments. |
|
| 2 | + | ||
| 3 | + | fn read 'r (p: &'r u32) -> u32 { return *p; } |
|
| 4 | + | ||
| 5 | + | fn useOp 'r (p: &'r u32, op: fn(&'r u32) -> u32) -> u32 { return op(p); } |
|
| 6 | + | ||
| 7 | + | fn relay 's (p: &'s u32) -> u32 { return useOp(p, read 's); } |
test/tests/regions.calls.callback.ril
added
+18 -0
| 1 | + | fn w32 $read(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w32 $useOp(w64 %0, w64 %1) { |
|
| 8 | + | @entry0 |
|
| 9 | + | call w32 %2 %1(%0); |
|
| 10 | + | ret %2; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $relay(w64 %0) { |
|
| 14 | + | @entry0 |
|
| 15 | + | copy %1 $read; |
|
| 16 | + | call w32 %2 $useOp(%0, %1); |
|
| 17 | + | ret %2; |
|
| 18 | + | } |
test/tests/regions.calls.inferred.rad
added
+24 -0
| 1 | + | // Calls bind symbolic regions to the caller's reference regions. |
|
| 2 | + | ||
| 3 | + | fn read_1 'r (p: &'r u32) -> u32 { return *p; } |
|
| 4 | + | ||
| 5 | + | fn relay_1 's (p: &'s u32) -> u32 { return read_1(p); } |
|
| 6 | + | ||
| 7 | + | fn read_2 'r (p: &'r [u32]) -> u32 { return p[0]; } |
|
| 8 | + | ||
| 9 | + | fn relay_2 's (p: &'s [u32]) -> u32 { return read_2(p); } |
|
| 10 | + | ||
| 11 | + | fn bump_3 'r (p: &'r mut u32) { set *p += 1; } |
|
| 12 | + | ||
| 13 | + | fn relay_3 's (p: &'s mut u32) { |
|
| 14 | + | let q: 'first = &mut *p where 's: 'first in { bump_3(q); } |
|
| 15 | + | let q: 'second = &mut *p where 's: 'second in { bump_3(q); } |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | fn read_4 'r (p: &'r u32) -> u32 { return *p; } |
|
| 19 | + | ||
| 20 | + | fn relay_4 's (p: &'s u32) -> u32 { let op = read_4 's; return op(p); } |
|
| 21 | + | ||
| 22 | + | fn answer_5 'r () -> u32 { return 42; } |
|
| 23 | + | ||
| 24 | + | fn relay_5 's () -> u32 { return answer_5 's (); } |
test/tests/regions.calls.inferred.ril
added
+69 -0
| 1 | + | fn w32 $read_1(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w32 $relay_1(w64 %0) { |
|
| 8 | + | @entry0 |
|
| 9 | + | call w32 %1 $read_1(%0); |
|
| 10 | + | ret %1; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $read_2(w64 %0) { |
|
| 14 | + | @entry0 |
|
| 15 | + | load w32 %1 %0 8; |
|
| 16 | + | br.ult w32 0 %1 @guard#pass1 @guard#trap2; |
|
| 17 | + | @guard#pass1 |
|
| 18 | + | load w64 %2 %0 0; |
|
| 19 | + | load w32 %3 %2 0; |
|
| 20 | + | ret %3; |
|
| 21 | + | @guard#trap2 |
|
| 22 | + | ebreak; |
|
| 23 | + | unreachable; |
|
| 24 | + | } |
|
| 25 | + | ||
| 26 | + | fn w32 $relay_2(w64 %0) { |
|
| 27 | + | @entry0 |
|
| 28 | + | call w32 %1 $read_2(%0); |
|
| 29 | + | ret %1; |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | fn w64 $bump_3(w64 %0) { |
|
| 33 | + | @entry0 |
|
| 34 | + | load w32 %1 %0 0; |
|
| 35 | + | add w32 %2 %1 1; |
|
| 36 | + | store w32 %2 %0 0; |
|
| 37 | + | ret; |
|
| 38 | + | } |
|
| 39 | + | ||
| 40 | + | fn w64 $relay_3(w64 %0) { |
|
| 41 | + | @entry0 |
|
| 42 | + | call w64 $bump_3(%0); |
|
| 43 | + | call w64 $bump_3(%0); |
|
| 44 | + | ret; |
|
| 45 | + | } |
|
| 46 | + | ||
| 47 | + | fn w32 $read_4(w64 %0) { |
|
| 48 | + | @entry0 |
|
| 49 | + | load w32 %1 %0 0; |
|
| 50 | + | ret %1; |
|
| 51 | + | } |
|
| 52 | + | ||
| 53 | + | fn w32 $relay_4(w64 %0) { |
|
| 54 | + | @entry0 |
|
| 55 | + | copy %1 $read_4; |
|
| 56 | + | call w32 %2 %1(%0); |
|
| 57 | + | ret %2; |
|
| 58 | + | } |
|
| 59 | + | ||
| 60 | + | fn w32 $answer_5() { |
|
| 61 | + | @entry0 |
|
| 62 | + | ret 42; |
|
| 63 | + | } |
|
| 64 | + | ||
| 65 | + | fn w32 $relay_5() { |
|
| 66 | + | @entry0 |
|
| 67 | + | call w32 %0 $answer_5(); |
|
| 68 | + | ret %0; |
|
| 69 | + | } |
test/tests/regions.calls.nil.rad
added
+38 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// A shared value stored inline in an optional result. |
|
| 4 | + | record View: 'r + Copy { |
|
| 5 | + | /// Referenced value. |
|
| 6 | + | value: &'r u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Select a nullable reference, with a fallback. |
|
| 10 | + | fn select 'r (first: &'r u32, second: ?&'r u32) -> u32 { |
|
| 11 | + | if let value = second { |
|
| 12 | + | return *value; |
|
| 13 | + | } |
|
| 14 | + | return *first; |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | /// Infer the region from an argument after the nil argument. |
|
| 18 | + | fn fallback 'r (first: ?View 'r, second: &'r u32) -> u32 { |
|
| 19 | + | if let view = first { |
|
| 20 | + | return *view.value; |
|
| 21 | + | } |
|
| 22 | + | return *second; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | /// Complete both branches of an initially untyped nil expression. |
|
| 26 | + | fn conditional 'r (value: &'r u32, flag: bool) -> u32 { |
|
| 27 | + | return select(value, nil if flag else nil); |
|
| 28 | + | } |
|
| 29 | + | ||
| 30 | + | @default fn main() -> u32 { |
|
| 31 | + | let value: u32 = 42; |
|
| 32 | + | let shared: 'r = &value in { |
|
| 33 | + | assert select(shared, nil) == 42; |
|
| 34 | + | assert fallback(nil, shared) == 42; |
|
| 35 | + | assert conditional(shared, true) == 42; |
|
| 36 | + | return conditional(shared, false); |
|
| 37 | + | } |
|
| 38 | + | } |
test/tests/regions.calls.nil.ril
added
+67 -0
| 1 | + | fn w32 $select(w64 %0, w64 %1) { |
|
| 2 | + | @entry0 |
|
| 3 | + | br.ne w32 %1 0 @then1 @else2; |
|
| 4 | + | @then1 |
|
| 5 | + | load w32 %2 %1 0; |
|
| 6 | + | ret %2; |
|
| 7 | + | @else2 |
|
| 8 | + | jmp @merge3; |
|
| 9 | + | @merge3 |
|
| 10 | + | load w32 %3 %0 0; |
|
| 11 | + | ret %3; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | fn w32 $fallback(w64 %0, w64 %1) { |
|
| 15 | + | @entry0 |
|
| 16 | + | reserve %2 16 8; |
|
| 17 | + | blit %2 %0 16; |
|
| 18 | + | load w8 %3 %2 0; |
|
| 19 | + | br.ne w32 %3 0 @then1 @else2; |
|
| 20 | + | @then1 |
|
| 21 | + | add w64 %4 %2 8; |
|
| 22 | + | load w64 %5 %4 0; |
|
| 23 | + | load w32 %6 %5 0; |
|
| 24 | + | ret %6; |
|
| 25 | + | @else2 |
|
| 26 | + | jmp @merge3; |
|
| 27 | + | @merge3 |
|
| 28 | + | load w32 %7 %1 0; |
|
| 29 | + | ret %7; |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | fn w32 $conditional(w64 %0, w8 %1) { |
|
| 33 | + | @entry0 |
|
| 34 | + | br.ne w32 %1 0 @cond#then1 @cond#else2; |
|
| 35 | + | @cond#then1 |
|
| 36 | + | jmp @cond#merge3(0); |
|
| 37 | + | @cond#else2 |
|
| 38 | + | jmp @cond#merge3(0); |
|
| 39 | + | @cond#merge3(w64 %2) |
|
| 40 | + | call w32 %3 $select(%0, %2); |
|
| 41 | + | ret %3; |
|
| 42 | + | } |
|
| 43 | + | ||
| 44 | + | fn w32 $main() { |
|
| 45 | + | @entry0 |
|
| 46 | + | reserve %0 4 4; |
|
| 47 | + | store w32 42 %0 0; |
|
| 48 | + | call w32 %1 $select(%0, 0); |
|
| 49 | + | br.eq w32 %1 42 @assert.ok2 @assert.fail1; |
|
| 50 | + | @assert.fail1 |
|
| 51 | + | unreachable; |
|
| 52 | + | @assert.ok2 |
|
| 53 | + | reserve %2 16 8; |
|
| 54 | + | store w8 0 %2 0; |
|
| 55 | + | call w32 %3 $fallback(%2, %0); |
|
| 56 | + | br.eq w32 %3 42 @assert.ok4 @assert.fail3; |
|
| 57 | + | @assert.fail3 |
|
| 58 | + | unreachable; |
|
| 59 | + | @assert.ok4 |
|
| 60 | + | call w32 %4 $conditional(%0, 1); |
|
| 61 | + | br.eq w32 %4 42 @assert.ok6 @assert.fail5; |
|
| 62 | + | @assert.fail5 |
|
| 63 | + | unreachable; |
|
| 64 | + | @assert.ok6 |
|
| 65 | + | call w32 %5 $conditional(%0, 0); |
|
| 66 | + | ret %5; |
|
| 67 | + | } |
test/tests/regions.calls.ownership.rad
added
+21 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | fn temporary(p: &mut u32) { set *p += 1; } |
|
| 4 | + | fn take 'r (p: &'r mut u32) { set *p += 1; } |
|
| 5 | + | fn forward 'r (p: &'r mut u32) { take(p); } |
|
| 6 | + | fn read 'r (p: &'r u32) -> u32 { return *p; } |
|
| 7 | + | ||
| 8 | + | @default fn main() -> u32 { |
|
| 9 | + | let mut value: u32 = 38; |
|
| 10 | + | let p: 'outer = &mut value in { |
|
| 11 | + | temporary(p); |
|
| 12 | + | temporary(p); |
|
| 13 | + | let q: 'first = &mut *p in { take(q); } |
|
| 14 | + | let q: 'second = &mut *p in { forward(q); } |
|
| 15 | + | let q: 'shared = &*p in { |
|
| 16 | + | assert read(q) == 42; |
|
| 17 | + | assert read(q) == 42; |
|
| 18 | + | } |
|
| 19 | + | } |
|
| 20 | + | return value; |
|
| 21 | + | } |
test/tests/regions.calls.ownership.ril
added
+49 -0
| 1 | + | fn w64 $temporary(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | add w32 %2 %1 1; |
|
| 5 | + | store w32 %2 %0 0; |
|
| 6 | + | ret; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w64 $take(w64 %0) { |
|
| 10 | + | @entry0 |
|
| 11 | + | load w32 %1 %0 0; |
|
| 12 | + | add w32 %2 %1 1; |
|
| 13 | + | store w32 %2 %0 0; |
|
| 14 | + | ret; |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | fn w64 $forward(w64 %0) { |
|
| 18 | + | @entry0 |
|
| 19 | + | call w64 $take(%0); |
|
| 20 | + | ret; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | fn w32 $read(w64 %0) { |
|
| 24 | + | @entry0 |
|
| 25 | + | load w32 %1 %0 0; |
|
| 26 | + | ret %1; |
|
| 27 | + | } |
|
| 28 | + | ||
| 29 | + | fn w32 $main() { |
|
| 30 | + | @entry0 |
|
| 31 | + | reserve %0 4 4; |
|
| 32 | + | store w32 38 %0 0; |
|
| 33 | + | call w64 $temporary(%0); |
|
| 34 | + | call w64 $temporary(%0); |
|
| 35 | + | call w64 $take(%0); |
|
| 36 | + | call w64 $forward(%0); |
|
| 37 | + | call w32 %1 $read(%0); |
|
| 38 | + | br.eq w32 %1 42 @assert.ok2 @assert.fail1; |
|
| 39 | + | @assert.fail1 |
|
| 40 | + | unreachable; |
|
| 41 | + | @assert.ok2 |
|
| 42 | + | call w32 %2 $read(%0); |
|
| 43 | + | br.eq w32 %2 42 @assert.ok4 @assert.fail3; |
|
| 44 | + | @assert.fail3 |
|
| 45 | + | unreachable; |
|
| 46 | + | @assert.ok4 |
|
| 47 | + | load w32 %3 %0 0; |
|
| 48 | + | ret %3; |
|
| 49 | + | } |
test/tests/regions.calls.parents.rad
added
+5 -0
| 1 | + | // Inferred and explicit region arguments must satisfy declared parent relations. |
|
| 2 | + | ||
| 3 | + | fn pair 'p 'c (p: &'p u32, c: &'c u32) where 'p: 'c {} |
|
| 4 | + | ||
| 5 | + | fn relay 'a 'b (a: &'a u32, b: &'b u32) where 'a: 'b { pair(a, b); pair 'a 'b (a, b); pair 'a 'a (a, a); } |
test/tests/regions.calls.parents.ril
added
+12 -0
| 1 | + | fn w64 $pair(w64 %0, w64 %1) { |
|
| 2 | + | @entry0 |
|
| 3 | + | ret; |
|
| 4 | + | } |
|
| 5 | + | ||
| 6 | + | fn w64 $relay(w64 %0, w64 %1) { |
|
| 7 | + | @entry0 |
|
| 8 | + | call w64 $pair(%0, %1); |
|
| 9 | + | call w64 $pair(%0, %1); |
|
| 10 | + | call w64 $pair(%0, %0); |
|
| 11 | + | ret; |
|
| 12 | + | } |
test/tests/regions.calls.raw.rad
added
+15 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record View: 'r + Copy { value: &'r u32 } |
|
| 4 | + | ||
| 5 | + | fn read 'r (view: *unsafe View 'r) -> u32 { |
|
| 6 | + | unsafe { return *view.value; } |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | @default unsafe fn main() -> u32 { |
|
| 10 | + | let value: u32 = 21; |
|
| 11 | + | let p: 'data = &value in { |
|
| 12 | + | let view: View 'data = View { value: p }; |
|
| 13 | + | return read(&view) + read(&view if true else &view); |
|
| 14 | + | } |
|
| 15 | + | } |
test/tests/regions.calls.raw.ril
added
+25 -0
| 1 | + | fn w32 $read(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w64 %1 %0 0; |
|
| 4 | + | load w32 %2 %1 0; |
|
| 5 | + | ret %2; |
|
| 6 | + | } |
|
| 7 | + | ||
| 8 | + | fn w32 $main() { |
|
| 9 | + | @entry0 |
|
| 10 | + | reserve %0 4 4; |
|
| 11 | + | store w32 21 %0 0; |
|
| 12 | + | reserve %1 8 8; |
|
| 13 | + | store w64 %0 %1 0; |
|
| 14 | + | call w32 %2 $read(%1); |
|
| 15 | + | copy %3 1; |
|
| 16 | + | br.ne w32 %3 0 @cond#then1 @cond#else2; |
|
| 17 | + | @cond#then1 |
|
| 18 | + | jmp @cond#merge3(%1); |
|
| 19 | + | @cond#else2 |
|
| 20 | + | jmp @cond#merge3(%1); |
|
| 21 | + | @cond#merge3(w64 %4) |
|
| 22 | + | call w32 %5 $read(%4); |
|
| 23 | + | add w32 %6 %2 %5; |
|
| 24 | + | ret %6; |
|
| 25 | + | } |
test/tests/regions.calls.recursive.rad
added
+17 -0
| 1 | + | // Recursive applications preserve one checked source signature. |
|
| 2 | + | ||
| 3 | + | fn recurse_1 'r (p: &'r u32, depth: u32) -> u32 { |
|
| 4 | + | if depth == 0 { |
|
| 5 | + | return *p; |
|
| 6 | + | } |
|
| 7 | + | return recurse_1(p, depth - 1); |
|
| 8 | + | } |
|
| 9 | + | ||
| 10 | + | fn left_2 'a (p: &'a u32, depth: u32) -> u32 { |
|
| 11 | + | if depth == 0 { |
|
| 12 | + | return *p; |
|
| 13 | + | } |
|
| 14 | + | return right_2(p, depth - 1); |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | fn right_2 'b (p: &'b u32, depth: u32) -> u32 { return left_2(p, depth); } |
test/tests/regions.calls.recursive.ril
added
+29 -0
| 1 | + | fn w32 $recurse_1(w64 %0, w32 %1) { |
|
| 2 | + | @entry0 |
|
| 3 | + | br.eq w32 %1 0 @then1 @merge2; |
|
| 4 | + | @then1 |
|
| 5 | + | load w32 %2 %0 0; |
|
| 6 | + | ret %2; |
|
| 7 | + | @merge2 |
|
| 8 | + | sub w32 %3 %1 1; |
|
| 9 | + | call w32 %4 $recurse_1(%0, %3); |
|
| 10 | + | ret %4; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $left_2(w64 %0, w32 %1) { |
|
| 14 | + | @entry0 |
|
| 15 | + | br.eq w32 %1 0 @then1 @merge2; |
|
| 16 | + | @then1 |
|
| 17 | + | load w32 %2 %0 0; |
|
| 18 | + | ret %2; |
|
| 19 | + | @merge2 |
|
| 20 | + | sub w32 %3 %1 1; |
|
| 21 | + | call w32 %4 $right_2(%0, %3); |
|
| 22 | + | ret %4; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | fn w32 $right_2(w64 %0, w32 %1) { |
|
| 26 | + | @entry0 |
|
| 27 | + | call w32 %2 $left_2(%0, %1); |
|
| 28 | + | ret %2; |
|
| 29 | + | } |
test/tests/regions.cell.graph.rad
added
+46 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// State with an immutable link into the graph. |
|
| 7 | + | union State: 'r + Copy { |
|
| 8 | + | Pending, |
|
| 9 | + | Ready(&'r Body 'r), |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | /// Graph node that retains its shared state cell. |
|
| 13 | + | record Body: 'r + Copy { |
|
| 14 | + | /// State shared by graph aliases. |
|
| 15 | + | state: &'r cell State 'r, |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | /// Read a retained graph link after the cell changes its active variant. |
|
| 19 | + | fn snapshot 'r (state: &'r cell State 'r) -> u32 { |
|
| 20 | + | let previous = *state; |
|
| 21 | + | set *state = State 'r::Pending; |
|
| 22 | + | match previous { |
|
| 23 | + | case State 'r::Ready(body) => { |
|
| 24 | + | match *body.state { |
|
| 25 | + | case State 'r::Pending => return 42, |
|
| 26 | + | else => panic, |
|
| 27 | + | } |
|
| 28 | + | }, |
|
| 29 | + | else => panic, |
|
| 30 | + | } |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | @default unsafe fn main() -> u32 { |
|
| 34 | + | static DATA: [u8; 1024] = [0; 1024]; |
|
| 35 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 36 | + | let mut result: u32 = 0; |
|
| 37 | + | use arena as graph in { |
|
| 38 | + | let initial = try! graph.new(State 'graph::Pending); |
|
| 39 | + | let state = initial as &'graph cell State 'graph; |
|
| 40 | + | let body: &'graph Body 'graph = try! graph.new(Body 'graph { state }); |
|
| 41 | + | set *state = State 'graph::Ready(body); |
|
| 42 | + | set result = snapshot(state); |
|
| 43 | + | } |
|
| 44 | + | alloc::reset(&mut arena); |
|
| 45 | + | return result; |
|
| 46 | + | } |
test/tests/regions.cell.graph.ril
added
+105 -0
| 1 | + | data mut $"regions.cell.graph::regions.cell.graph::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 1024; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w32 $"regions.cell.graph::snapshot"(w64 %0) { |
|
| 6 | + | @entry0 |
|
| 7 | + | reserve %1 16 8; |
|
| 8 | + | blit %1 %0 16; |
|
| 9 | + | reserve %2 16 8; |
|
| 10 | + | store w8 0 %2 0; |
|
| 11 | + | blit %0 %2 16; |
|
| 12 | + | reserve %3 16 8; |
|
| 13 | + | blit %3 %1 16; |
|
| 14 | + | jmp @arm1; |
|
| 15 | + | @arm1 |
|
| 16 | + | load w8 %4 %3 0; |
|
| 17 | + | br.eq w8 %4 1 @case2 @arm3; |
|
| 18 | + | @case2 |
|
| 19 | + | load w64 %5 %3 8; |
|
| 20 | + | load w64 %6 %5 0; |
|
| 21 | + | reserve %7 16 8; |
|
| 22 | + | blit %7 %6 16; |
|
| 23 | + | reserve %8 16 8; |
|
| 24 | + | blit %8 %7 16; |
|
| 25 | + | jmp @arm4; |
|
| 26 | + | @arm3 |
|
| 27 | + | jmp @else9; |
|
| 28 | + | @arm4 |
|
| 29 | + | load w8 %9 %8 0; |
|
| 30 | + | br.eq w8 %9 0 @case5 @arm6; |
|
| 31 | + | @case5 |
|
| 32 | + | ret 42; |
|
| 33 | + | @arm6 |
|
| 34 | + | jmp @else7; |
|
| 35 | + | @else7 |
|
| 36 | + | unreachable; |
|
| 37 | + | @else9 |
|
| 38 | + | unreachable; |
|
| 39 | + | } |
|
| 40 | + | ||
| 41 | + | fn w32 $"regions.cell.graph::main"() { |
|
| 42 | + | @entry0 |
|
| 43 | + | copy %0 $"regions.cell.graph::regions.cell.graph::main$nominal$DATA"; |
|
| 44 | + | reserve %1 16 8; |
|
| 45 | + | store w64 %0 %1 0; |
|
| 46 | + | store w32 1024 %1 8; |
|
| 47 | + | store w32 1024 %1 12; |
|
| 48 | + | reserve %2 24 8; |
|
| 49 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 50 | + | reserve %4 16 8; |
|
| 51 | + | store w64 %3 %4 0; |
|
| 52 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 53 | + | load w64 %5 %4 0; |
|
| 54 | + | load w64 %6 %4 8; |
|
| 55 | + | load w64 %7 %6 0; |
|
| 56 | + | reserve %8 16 8; |
|
| 57 | + | store w8 0 %8 0; |
|
| 58 | + | reserve %9 16 8; |
|
| 59 | + | blit %9 %8 16; |
|
| 60 | + | reserve %10 16 8; |
|
| 61 | + | call w64 %11 %7(%10, %5, 16, 8); |
|
| 62 | + | load w64 %12 %11 0; |
|
| 63 | + | reserve %13 8 8; |
|
| 64 | + | br.ne w32 %12 0 @err2 @ok1; |
|
| 65 | + | @ok1 |
|
| 66 | + | load w64 %14 %11 8; |
|
| 67 | + | blit %14 %9 16; |
|
| 68 | + | load w64 %15 %11 8; |
|
| 69 | + | store w64 %15 %13 0; |
|
| 70 | + | jmp @merge3; |
|
| 71 | + | @err2 |
|
| 72 | + | unreachable; |
|
| 73 | + | @merge3 |
|
| 74 | + | load w64 %16 %13 0; |
|
| 75 | + | load w64 %17 %4 0; |
|
| 76 | + | load w64 %18 %4 8; |
|
| 77 | + | load w64 %19 %18 0; |
|
| 78 | + | reserve %20 8 8; |
|
| 79 | + | store w64 %16 %20 0; |
|
| 80 | + | reserve %21 16 8; |
|
| 81 | + | call w64 %22 %19(%21, %17, 8, 8); |
|
| 82 | + | load w64 %23 %22 0; |
|
| 83 | + | reserve %24 8 8; |
|
| 84 | + | br.ne w32 %23 0 @err5 @ok4; |
|
| 85 | + | @ok4 |
|
| 86 | + | load w64 %25 %22 8; |
|
| 87 | + | blit %25 %20 8; |
|
| 88 | + | load w64 %26 %22 8; |
|
| 89 | + | store w64 %26 %24 0; |
|
| 90 | + | jmp @merge6; |
|
| 91 | + | @err5 |
|
| 92 | + | unreachable; |
|
| 93 | + | @merge6 |
|
| 94 | + | load w64 %27 %24 0; |
|
| 95 | + | reserve %28 8 8; |
|
| 96 | + | store w64 %27 %28 0; |
|
| 97 | + | reserve %29 16 8; |
|
| 98 | + | store w8 1 %29 0; |
|
| 99 | + | add w64 %30 %29 8; |
|
| 100 | + | blit %30 %28 8; |
|
| 101 | + | blit %16 %29 16; |
|
| 102 | + | call w32 %31 $"regions.cell.graph::snapshot"(%16); |
|
| 103 | + | call w64 $"std::lang::alloc::reset"(%3); |
|
| 104 | + | ret %31; |
|
| 105 | + | } |
test/tests/regions.cell.pointer.rad
added
+106 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | record Pair: Copy { a: u32, b: u32 } |
|
| 7 | + | record Entry: 'r + Copy { index: &'r cell u32 } |
|
| 8 | + | ||
| 9 | + | /// A copied union retains its reference after the cell changes its tag. |
|
| 10 | + | union Link: 'r + Copy { Value(&'r u32), Empty } |
|
| 11 | + | ||
| 12 | + | fn unionCell 'r (allocation: &Session 'r) -> u32 { |
|
| 13 | + | let value = try! allocation.new(19 as u32); |
|
| 14 | + | let shared: &'r u32 = value; |
|
| 15 | + | let initial: Link 'r = Link::Value(shared); |
|
| 16 | + | let storage = try! allocation.new(initial); |
|
| 17 | + | let pointer = storage as &'r cell Link 'r; |
|
| 18 | + | let snapshot = *pointer; |
|
| 19 | + | set *pointer = Link::Empty; |
|
| 20 | + | match *pointer { |
|
| 21 | + | case Link::Empty => { |
|
| 22 | + | }, |
|
| 23 | + | case Link::Value(_) => panic, |
|
| 24 | + | } |
|
| 25 | + | match snapshot { |
|
| 26 | + | case Link::Value(retained) => return *retained, |
|
| 27 | + | case Link::Empty => panic, |
|
| 28 | + | } |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | fn local() -> u32 { |
|
| 32 | + | let mut value: u32 = 0; |
|
| 33 | + | { |
|
| 34 | + | let pointer = &mut value as &cell u32; |
|
| 35 | + | let alias = pointer; |
|
| 36 | + | set *alias = 7; |
|
| 37 | + | assert *pointer == 7; |
|
| 38 | + | set *pointer = 8; |
|
| 39 | + | assert *alias == 8; |
|
| 40 | + | set *alias = 7; |
|
| 41 | + | } |
|
| 42 | + | return value; |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | fn update(pointer: *cell u32) { set *pointer = 20; } |
|
| 46 | + | fn read 'r (pointer: &'r cell u32) -> u32 { return *pointer; } |
|
| 47 | + | fn relay 'r (pointer: &'r cell u32) -> &'r cell u32 { return pointer; } |
|
| 48 | + | ||
| 49 | + | /// Count evaluations of a compound assignment target. |
|
| 50 | + | fn select(pointer: *cell u32, calls: *cell u32) -> *cell u32 { |
|
| 51 | + | set *calls += 1; |
|
| 52 | + | return pointer; |
|
| 53 | + | } |
|
| 54 | + | ||
| 55 | + | /// Replace shared storage while retaining a value argument snapshot. |
|
| 56 | + | fn replace 'r (snapshot: Pair, pointer: &'r cell Pair) -> u32 { |
|
| 57 | + | set *pointer = Pair { a: 5, b: 6 }; |
|
| 58 | + | return snapshot.a; |
|
| 59 | + | } |
|
| 60 | + | ||
| 61 | + | @default fn main() -> u32 { |
|
| 62 | + | assert local() == 7; |
|
| 63 | + | assert @sizeOf(*cell u32) == @sizeOf(*mut u32); |
|
| 64 | + | static VALUE: u32 = 0; |
|
| 65 | + | let pointer: *mut u32 = &mut VALUE; |
|
| 66 | + | let cell = pointer as *cell u32; |
|
| 67 | + | let alias = cell; |
|
| 68 | + | update(alias); |
|
| 69 | + | assert *cell == 20; |
|
| 70 | + | static CALLS: u32 = 0; |
|
| 71 | + | let calls = &mut CALLS as *cell u32; |
|
| 72 | + | set *select(cell, calls) += 1; |
|
| 73 | + | assert *calls == 1; |
|
| 74 | + | assert *cell == 21; |
|
| 75 | + | set *cell = 20; |
|
| 76 | + | ||
| 77 | + | static DATA: [u8; 256] = [0; 256]; |
|
| 78 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 79 | + | use arena as objects in { |
|
| 80 | + | assert unionCell(&objects) == 19; |
|
| 81 | + | let value = try! objects.new(22 as u32); |
|
| 82 | + | let shared = value as &'objects cell u32; |
|
| 83 | + | let optional: ?&'objects cell u32 = shared; |
|
| 84 | + | if let present = optional { |
|
| 85 | + | assert *present == 22; |
|
| 86 | + | } else { |
|
| 87 | + | panic; |
|
| 88 | + | } |
|
| 89 | + | let pointers = try! objects.fill(shared, 2); |
|
| 90 | + | set *pointers[1] = 22; |
|
| 91 | + | let entry: Entry 'objects = Entry { index: relay(shared) }; |
|
| 92 | + | let copy = entry; |
|
| 93 | + | set *copy.index = 21; |
|
| 94 | + | assert read(entry.index) == 21; |
|
| 95 | + | set *shared = 22; |
|
| 96 | + | let pair = try! objects.new(Pair { a: 1, b: 2 }); |
|
| 97 | + | let pairCell = pair as &'objects cell Pair; |
|
| 98 | + | let snapshot = *pairCell; |
|
| 99 | + | set *pairCell = Pair { a: 3, b: 4 }; |
|
| 100 | + | assert snapshot.a == 1 and snapshot.b == 2; |
|
| 101 | + | assert (*pairCell).b == 4; |
|
| 102 | + | assert replace(*pairCell, pairCell) == 3; |
|
| 103 | + | assert (*pairCell).a == 5; |
|
| 104 | + | return *cell + *shared; |
|
| 105 | + | } |
|
| 106 | + | } |
test/tests/regions.cell.pointer.ril
added
+358 -0
| 1 | + | data mut $"regions.cell.pointer::regions.cell.pointer::main$nominal$VALUE" align 4 { |
|
| 2 | + | w32 0; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data mut $"regions.cell.pointer::regions.cell.pointer::main$nominal$CALLS" align 4 { |
|
| 6 | + | w32 0; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | data mut $"regions.cell.pointer::regions.cell.pointer::main$nominal$DATA" align 1 { |
|
| 10 | + | w8 0 * 256; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $"regions.cell.pointer::unionCell"(w64 %0) { |
|
| 14 | + | @entry0 |
|
| 15 | + | load w64 %1 %0 0; |
|
| 16 | + | load w64 %2 %0 8; |
|
| 17 | + | load w64 %3 %2 0; |
|
| 18 | + | zext w32 %4 19; |
|
| 19 | + | reserve %5 16 8; |
|
| 20 | + | call w64 %6 %3(%5, %1, 4, 4); |
|
| 21 | + | load w64 %7 %6 0; |
|
| 22 | + | reserve %8 8 8; |
|
| 23 | + | br.ne w32 %7 0 @err2 @ok1; |
|
| 24 | + | @ok1 |
|
| 25 | + | load w64 %9 %6 8; |
|
| 26 | + | store w32 %4 %9 0; |
|
| 27 | + | load w64 %10 %6 8; |
|
| 28 | + | store w64 %10 %8 0; |
|
| 29 | + | jmp @merge3; |
|
| 30 | + | @err2 |
|
| 31 | + | unreachable; |
|
| 32 | + | @merge3 |
|
| 33 | + | load w64 %11 %8 0; |
|
| 34 | + | reserve %12 8 8; |
|
| 35 | + | store w64 %11 %12 0; |
|
| 36 | + | reserve %13 16 8; |
|
| 37 | + | store w8 0 %13 0; |
|
| 38 | + | add w64 %14 %13 8; |
|
| 39 | + | blit %14 %12 8; |
|
| 40 | + | load w64 %15 %0 0; |
|
| 41 | + | load w64 %16 %0 8; |
|
| 42 | + | load w64 %17 %16 0; |
|
| 43 | + | reserve %18 16 8; |
|
| 44 | + | blit %18 %13 16; |
|
| 45 | + | reserve %19 16 8; |
|
| 46 | + | call w64 %20 %17(%19, %15, 16, 8); |
|
| 47 | + | load w64 %21 %20 0; |
|
| 48 | + | reserve %22 8 8; |
|
| 49 | + | br.ne w32 %21 0 @err5 @ok4; |
|
| 50 | + | @ok4 |
|
| 51 | + | load w64 %23 %20 8; |
|
| 52 | + | blit %23 %18 16; |
|
| 53 | + | load w64 %24 %20 8; |
|
| 54 | + | store w64 %24 %22 0; |
|
| 55 | + | jmp @merge6; |
|
| 56 | + | @err5 |
|
| 57 | + | unreachable; |
|
| 58 | + | @merge6 |
|
| 59 | + | load w64 %25 %22 0; |
|
| 60 | + | reserve %26 16 8; |
|
| 61 | + | blit %26 %25 16; |
|
| 62 | + | reserve %27 16 8; |
|
| 63 | + | store w8 1 %27 0; |
|
| 64 | + | blit %25 %27 16; |
|
| 65 | + | reserve %28 16 8; |
|
| 66 | + | blit %28 %25 16; |
|
| 67 | + | reserve %29 16 8; |
|
| 68 | + | blit %29 %28 16; |
|
| 69 | + | jmp @arm7; |
|
| 70 | + | @arm7 |
|
| 71 | + | load w8 %30 %29 0; |
|
| 72 | + | br.eq w8 %30 1 @case8 @arm9; |
|
| 73 | + | @case8 |
|
| 74 | + | jmp @merge10; |
|
| 75 | + | @arm9 |
|
| 76 | + | jmp @case11; |
|
| 77 | + | @merge10 |
|
| 78 | + | reserve %31 16 8; |
|
| 79 | + | blit %31 %26 16; |
|
| 80 | + | jmp @arm13; |
|
| 81 | + | @case11 |
|
| 82 | + | unreachable; |
|
| 83 | + | @arm13 |
|
| 84 | + | load w8 %32 %31 0; |
|
| 85 | + | br.eq w8 %32 0 @case14 @arm15; |
|
| 86 | + | @case14 |
|
| 87 | + | load w64 %33 %31 8; |
|
| 88 | + | load w32 %34 %33 0; |
|
| 89 | + | ret %34; |
|
| 90 | + | @arm15 |
|
| 91 | + | jmp @case16; |
|
| 92 | + | @case16 |
|
| 93 | + | unreachable; |
|
| 94 | + | } |
|
| 95 | + | ||
| 96 | + | fn w32 $"regions.cell.pointer::local"() { |
|
| 97 | + | @entry0 |
|
| 98 | + | reserve %0 4 4; |
|
| 99 | + | store w32 0 %0 0; |
|
| 100 | + | store w32 7 %0 0; |
|
| 101 | + | load w32 %1 %0 0; |
|
| 102 | + | br.eq w32 %1 7 @assert.ok2 @assert.fail1; |
|
| 103 | + | @assert.fail1 |
|
| 104 | + | unreachable; |
|
| 105 | + | @assert.ok2 |
|
| 106 | + | store w32 8 %0 0; |
|
| 107 | + | load w32 %2 %0 0; |
|
| 108 | + | br.eq w32 %2 8 @assert.ok4 @assert.fail3; |
|
| 109 | + | @assert.fail3 |
|
| 110 | + | unreachable; |
|
| 111 | + | @assert.ok4 |
|
| 112 | + | store w32 7 %0 0; |
|
| 113 | + | load w32 %3 %0 0; |
|
| 114 | + | ret %3; |
|
| 115 | + | } |
|
| 116 | + | ||
| 117 | + | fn w64 $"regions.cell.pointer::update"(w64 %0) { |
|
| 118 | + | @entry0 |
|
| 119 | + | store w32 20 %0 0; |
|
| 120 | + | ret; |
|
| 121 | + | } |
|
| 122 | + | ||
| 123 | + | fn w32 $"regions.cell.pointer::read"(w64 %0) { |
|
| 124 | + | @entry0 |
|
| 125 | + | load w32 %1 %0 0; |
|
| 126 | + | ret %1; |
|
| 127 | + | } |
|
| 128 | + | ||
| 129 | + | fn w64 $"regions.cell.pointer::relay"(w64 %0) { |
|
| 130 | + | @entry0 |
|
| 131 | + | ret %0; |
|
| 132 | + | } |
|
| 133 | + | ||
| 134 | + | fn w64 $"regions.cell.pointer::select"(w64 %0, w64 %1) { |
|
| 135 | + | @entry0 |
|
| 136 | + | load w32 %2 %1 0; |
|
| 137 | + | add w32 %3 %2 1; |
|
| 138 | + | store w32 %3 %1 0; |
|
| 139 | + | ret %0; |
|
| 140 | + | } |
|
| 141 | + | ||
| 142 | + | fn w32 $"regions.cell.pointer::replace"(w64 %0, w64 %1) { |
|
| 143 | + | @entry0 |
|
| 144 | + | reserve %2 8 4; |
|
| 145 | + | store w32 5 %2 0; |
|
| 146 | + | store w32 6 %2 4; |
|
| 147 | + | blit %1 %2 8; |
|
| 148 | + | load w32 %3 %0 0; |
|
| 149 | + | ret %3; |
|
| 150 | + | } |
|
| 151 | + | ||
| 152 | + | fn w32 $"regions.cell.pointer::main"() { |
|
| 153 | + | @entry0 |
|
| 154 | + | call w32 %0 $"regions.cell.pointer::local"(); |
|
| 155 | + | br.eq w32 %0 7 @assert.ok2 @assert.fail1; |
|
| 156 | + | @assert.fail1 |
|
| 157 | + | unreachable; |
|
| 158 | + | @assert.ok2 |
|
| 159 | + | br.eq w32 8 8 @assert.ok4 @assert.fail3; |
|
| 160 | + | @assert.fail3 |
|
| 161 | + | unreachable; |
|
| 162 | + | @assert.ok4 |
|
| 163 | + | copy %1 $"regions.cell.pointer::regions.cell.pointer::main$nominal$VALUE"; |
|
| 164 | + | call w64 $"regions.cell.pointer::update"(%1); |
|
| 165 | + | load w32 %2 %1 0; |
|
| 166 | + | br.eq w32 %2 20 @assert.ok6 @assert.fail5; |
|
| 167 | + | @assert.fail5 |
|
| 168 | + | unreachable; |
|
| 169 | + | @assert.ok6 |
|
| 170 | + | copy %3 $"regions.cell.pointer::regions.cell.pointer::main$nominal$CALLS"; |
|
| 171 | + | call w64 %4 $"regions.cell.pointer::select"(%1, %3); |
|
| 172 | + | load w32 %5 %4 0; |
|
| 173 | + | add w32 %6 %5 1; |
|
| 174 | + | store w32 %6 %4 0; |
|
| 175 | + | load w32 %7 %3 0; |
|
| 176 | + | br.eq w32 %7 1 @assert.ok8 @assert.fail7; |
|
| 177 | + | @assert.fail7 |
|
| 178 | + | unreachable; |
|
| 179 | + | @assert.ok8 |
|
| 180 | + | load w32 %8 %1 0; |
|
| 181 | + | br.eq w32 %8 21 @assert.ok10 @assert.fail9; |
|
| 182 | + | @assert.fail9 |
|
| 183 | + | unreachable; |
|
| 184 | + | @assert.ok10 |
|
| 185 | + | store w32 20 %1 0; |
|
| 186 | + | copy %9 $"regions.cell.pointer::regions.cell.pointer::main$nominal$DATA"; |
|
| 187 | + | reserve %10 16 8; |
|
| 188 | + | store w64 %9 %10 0; |
|
| 189 | + | store w32 256 %10 8; |
|
| 190 | + | store w32 256 %10 12; |
|
| 191 | + | reserve %11 24 8; |
|
| 192 | + | call w64 %12 $"std::lang::alloc::new"(%11, %10); |
|
| 193 | + | reserve %13 16 8; |
|
| 194 | + | store w64 %12 %13 0; |
|
| 195 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %13 8; |
|
| 196 | + | call w32 %14 $"regions.cell.pointer::unionCell"(%13); |
|
| 197 | + | br.eq w32 %14 19 @assert.ok12 @assert.fail11; |
|
| 198 | + | @assert.fail11 |
|
| 199 | + | unreachable; |
|
| 200 | + | @assert.ok12 |
|
| 201 | + | load w64 %15 %13 0; |
|
| 202 | + | load w64 %16 %13 8; |
|
| 203 | + | load w64 %17 %16 0; |
|
| 204 | + | zext w32 %18 22; |
|
| 205 | + | reserve %19 16 8; |
|
| 206 | + | call w64 %20 %17(%19, %15, 4, 4); |
|
| 207 | + | load w64 %21 %20 0; |
|
| 208 | + | reserve %22 8 8; |
|
| 209 | + | br.ne w32 %21 0 @err14 @ok13; |
|
| 210 | + | @ok13 |
|
| 211 | + | load w64 %23 %20 8; |
|
| 212 | + | store w32 %18 %23 0; |
|
| 213 | + | load w64 %24 %20 8; |
|
| 214 | + | store w64 %24 %22 0; |
|
| 215 | + | jmp @merge15; |
|
| 216 | + | @err14 |
|
| 217 | + | unreachable; |
|
| 218 | + | @merge15 |
|
| 219 | + | load w64 %25 %22 0; |
|
| 220 | + | reserve %26 16 8; |
|
| 221 | + | store w8 1 %26 0; |
|
| 222 | + | store w64 %25 %26 8; |
|
| 223 | + | reserve %27 16 8; |
|
| 224 | + | blit %27 %26 16; |
|
| 225 | + | reserve %28 16 8; |
|
| 226 | + | blit %28 %27 16; |
|
| 227 | + | load w8 %29 %28 0; |
|
| 228 | + | br.ne w32 %29 0 @then16 @else17; |
|
| 229 | + | @then16 |
|
| 230 | + | load w64 %30 %28 8; |
|
| 231 | + | load w32 %31 %30 0; |
|
| 232 | + | br.eq w32 %31 22 @assert.ok19 @assert.fail18; |
|
| 233 | + | @else17 |
|
| 234 | + | unreachable; |
|
| 235 | + | @assert.fail18 |
|
| 236 | + | unreachable; |
|
| 237 | + | @assert.ok19 |
|
| 238 | + | jmp @merge20; |
|
| 239 | + | @merge20 |
|
| 240 | + | load w64 %32 %13 0; |
|
| 241 | + | load w64 %33 %13 8; |
|
| 242 | + | load w64 %34 %33 8; |
|
| 243 | + | reserve %35 24 8; |
|
| 244 | + | call w64 %36 %34(%35, %32, 8, 8, 2); |
|
| 245 | + | load w64 %37 %36 0; |
|
| 246 | + | reserve %38 16 8; |
|
| 247 | + | br.ne w32 %37 0 @err22 @ok21; |
|
| 248 | + | @ok21 |
|
| 249 | + | load w64 %39 %36 8; |
|
| 250 | + | jmp @fill23(0); |
|
| 251 | + | @err22 |
|
| 252 | + | unreachable; |
|
| 253 | + | @fill23(w32 %40) |
|
| 254 | + | br.ult w32 %40 2 @fill24 @fill25; |
|
| 255 | + | @fill24 |
|
| 256 | + | mul w64 %41 %40 8; |
|
| 257 | + | add w64 %42 %39 %41; |
|
| 258 | + | store w64 %25 %42 0; |
|
| 259 | + | add w32 %43 %40 1; |
|
| 260 | + | jmp @fill23(%43); |
|
| 261 | + | @fill25 |
|
| 262 | + | add w64 %44 %36 8; |
|
| 263 | + | blit %38 %44 16; |
|
| 264 | + | jmp @merge26; |
|
| 265 | + | @merge26 |
|
| 266 | + | load w32 %45 %38 8; |
|
| 267 | + | br.ult w32 1 %45 @guard#pass27 @guard#trap28; |
|
| 268 | + | @guard#pass27 |
|
| 269 | + | load w64 %46 %38 0; |
|
| 270 | + | mul w64 %47 1 8; |
|
| 271 | + | add w64 %48 %46 %47; |
|
| 272 | + | load w64 %49 %48 0; |
|
| 273 | + | store w32 22 %49 0; |
|
| 274 | + | reserve %50 8 8; |
|
| 275 | + | call w64 %52 $"regions.cell.pointer::relay"(%25); |
|
| 276 | + | store w64 %52 %50 0; |
|
| 277 | + | reserve %53 8 8; |
|
| 278 | + | blit %53 %50 8; |
|
| 279 | + | load w64 %54 %53 0; |
|
| 280 | + | store w32 21 %54 0; |
|
| 281 | + | load w64 %55 %50 0; |
|
| 282 | + | call w32 %56 $"regions.cell.pointer::read"(%55); |
|
| 283 | + | br.eq w32 %56 21 @assert.ok30 @assert.fail29; |
|
| 284 | + | @guard#trap28 |
|
| 285 | + | ebreak; |
|
| 286 | + | unreachable; |
|
| 287 | + | @assert.fail29 |
|
| 288 | + | unreachable; |
|
| 289 | + | @assert.ok30 |
|
| 290 | + | store w32 22 %25 0; |
|
| 291 | + | load w64 %58 %13 0; |
|
| 292 | + | load w64 %59 %13 8; |
|
| 293 | + | load w64 %60 %59 0; |
|
| 294 | + | reserve %61 8 4; |
|
| 295 | + | store w32 1 %61 0; |
|
| 296 | + | store w32 2 %61 4; |
|
| 297 | + | reserve %62 16 8; |
|
| 298 | + | call w64 %63 %60(%62, %58, 8, 4); |
|
| 299 | + | load w64 %64 %63 0; |
|
| 300 | + | reserve %65 8 8; |
|
| 301 | + | br.ne w32 %64 0 @err32 @ok31; |
|
| 302 | + | @ok31 |
|
| 303 | + | load w64 %66 %63 8; |
|
| 304 | + | blit %66 %61 8; |
|
| 305 | + | load w64 %67 %63 8; |
|
| 306 | + | store w64 %67 %65 0; |
|
| 307 | + | jmp @merge33; |
|
| 308 | + | @err32 |
|
| 309 | + | unreachable; |
|
| 310 | + | @merge33 |
|
| 311 | + | load w64 %68 %65 0; |
|
| 312 | + | reserve %69 8 4; |
|
| 313 | + | blit %69 %68 8; |
|
| 314 | + | reserve %70 8 4; |
|
| 315 | + | store w32 3 %70 0; |
|
| 316 | + | store w32 4 %70 4; |
|
| 317 | + | blit %68 %70 8; |
|
| 318 | + | load w32 %72 %69 0; |
|
| 319 | + | br.eq w32 %72 1 @and#then36 @and#else37; |
|
| 320 | + | @assert.fail34 |
|
| 321 | + | unreachable; |
|
| 322 | + | @assert.ok35 |
|
| 323 | + | reserve %76 8 4; |
|
| 324 | + | blit %76 %68 8; |
|
| 325 | + | load w32 %77 %76 4; |
|
| 326 | + | br.eq w32 %77 4 @assert.ok40 @assert.fail39; |
|
| 327 | + | @and#then36 |
|
| 328 | + | load w32 %73 %69 4; |
|
| 329 | + | eq w32 %74 %73 2; |
|
| 330 | + | jmp @and#end38(%74); |
|
| 331 | + | @and#else37 |
|
| 332 | + | jmp @and#end38(0); |
|
| 333 | + | @and#end38(w8 %71) |
|
| 334 | + | br.ne w32 %71 0 @assert.ok35 @assert.fail34; |
|
| 335 | + | @assert.fail39 |
|
| 336 | + | unreachable; |
|
| 337 | + | @assert.ok40 |
|
| 338 | + | reserve %78 8 4; |
|
| 339 | + | blit %78 %68 8; |
|
| 340 | + | reserve %79 8 4; |
|
| 341 | + | blit %79 %78 8; |
|
| 342 | + | call w32 %80 $"regions.cell.pointer::replace"(%79, %68); |
|
| 343 | + | br.eq w32 %80 3 @assert.ok42 @assert.fail41; |
|
| 344 | + | @assert.fail41 |
|
| 345 | + | unreachable; |
|
| 346 | + | @assert.ok42 |
|
| 347 | + | reserve %81 8 4; |
|
| 348 | + | blit %81 %68 8; |
|
| 349 | + | load w32 %82 %81 0; |
|
| 350 | + | br.eq w32 %82 5 @assert.ok44 @assert.fail43; |
|
| 351 | + | @assert.fail43 |
|
| 352 | + | unreachable; |
|
| 353 | + | @assert.ok44 |
|
| 354 | + | load w32 %85 %1 0; |
|
| 355 | + | load w32 %87 %25 0; |
|
| 356 | + | add w32 %88 %85 %87; |
|
| 357 | + | ret %88; |
|
| 358 | + | } |
test/tests/regions.cell.recursive.rad
added
+29 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// Node with a link through shared mutable storage. |
|
| 7 | + | union Node: 'r + Copy { |
|
| 8 | + | End, |
|
| 9 | + | Link(&'r cell Node 'r), |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | @default unsafe fn main() -> u32 { |
|
| 13 | + | static DATA: [u8; 256] = [0; 256]; |
|
| 14 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 15 | + | use arena as graph in { |
|
| 16 | + | let initial = try! graph.new(Node 'graph::End); |
|
| 17 | + | let node = initial as &'graph cell Node 'graph; |
|
| 18 | + | set *node = Node 'graph::Link(node); |
|
| 19 | + | let snapshot = *node; |
|
| 20 | + | match snapshot { |
|
| 21 | + | case Node 'graph::Link(alias) => set *alias = Node 'graph::End, |
|
| 22 | + | case Node 'graph::End => panic, |
|
| 23 | + | } |
|
| 24 | + | match *node { |
|
| 25 | + | case Node 'graph::End => return 42, |
|
| 26 | + | case Node 'graph::Link(_) => panic, |
|
| 27 | + | } |
|
| 28 | + | } |
|
| 29 | + | } |
test/tests/regions.cell.recursive.ril
added
+79 -0
| 1 | + | data mut $"regions.cell.recursive::regions.cell.recursive::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 256; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w32 $"regions.cell.recursive::main"() { |
|
| 6 | + | @entry0 |
|
| 7 | + | copy %0 $"regions.cell.recursive::regions.cell.recursive::main$nominal$DATA"; |
|
| 8 | + | reserve %1 16 8; |
|
| 9 | + | store w64 %0 %1 0; |
|
| 10 | + | store w32 256 %1 8; |
|
| 11 | + | store w32 256 %1 12; |
|
| 12 | + | reserve %2 24 8; |
|
| 13 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 14 | + | reserve %4 16 8; |
|
| 15 | + | store w64 %3 %4 0; |
|
| 16 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 17 | + | load w64 %5 %4 0; |
|
| 18 | + | load w64 %6 %4 8; |
|
| 19 | + | load w64 %7 %6 0; |
|
| 20 | + | reserve %8 16 8; |
|
| 21 | + | store w8 0 %8 0; |
|
| 22 | + | reserve %9 16 8; |
|
| 23 | + | blit %9 %8 16; |
|
| 24 | + | reserve %10 16 8; |
|
| 25 | + | call w64 %11 %7(%10, %5, 16, 8); |
|
| 26 | + | load w64 %12 %11 0; |
|
| 27 | + | reserve %13 8 8; |
|
| 28 | + | br.ne w32 %12 0 @err2 @ok1; |
|
| 29 | + | @ok1 |
|
| 30 | + | load w64 %14 %11 8; |
|
| 31 | + | blit %14 %9 16; |
|
| 32 | + | load w64 %15 %11 8; |
|
| 33 | + | store w64 %15 %13 0; |
|
| 34 | + | jmp @merge3; |
|
| 35 | + | @err2 |
|
| 36 | + | unreachable; |
|
| 37 | + | @merge3 |
|
| 38 | + | load w64 %16 %13 0; |
|
| 39 | + | reserve %17 8 8; |
|
| 40 | + | store w64 %16 %17 0; |
|
| 41 | + | reserve %18 16 8; |
|
| 42 | + | store w8 1 %18 0; |
|
| 43 | + | add w64 %19 %18 8; |
|
| 44 | + | blit %19 %17 8; |
|
| 45 | + | blit %16 %18 16; |
|
| 46 | + | reserve %20 16 8; |
|
| 47 | + | blit %20 %16 16; |
|
| 48 | + | reserve %21 16 8; |
|
| 49 | + | blit %21 %20 16; |
|
| 50 | + | jmp @arm4; |
|
| 51 | + | @arm4 |
|
| 52 | + | load w8 %22 %21 0; |
|
| 53 | + | br.eq w8 %22 1 @case5 @arm6; |
|
| 54 | + | @case5 |
|
| 55 | + | load w64 %23 %21 8; |
|
| 56 | + | reserve %24 16 8; |
|
| 57 | + | store w8 0 %24 0; |
|
| 58 | + | blit %23 %24 16; |
|
| 59 | + | jmp @merge7; |
|
| 60 | + | @arm6 |
|
| 61 | + | jmp @case8; |
|
| 62 | + | @merge7 |
|
| 63 | + | reserve %25 16 8; |
|
| 64 | + | blit %25 %16 16; |
|
| 65 | + | reserve %26 16 8; |
|
| 66 | + | blit %26 %25 16; |
|
| 67 | + | jmp @arm10; |
|
| 68 | + | @case8 |
|
| 69 | + | unreachable; |
|
| 70 | + | @arm10 |
|
| 71 | + | load w8 %27 %26 0; |
|
| 72 | + | br.eq w8 %27 0 @case11 @arm12; |
|
| 73 | + | @case11 |
|
| 74 | + | ret 42; |
|
| 75 | + | @arm12 |
|
| 76 | + | jmp @case13; |
|
| 77 | + | @case13 |
|
| 78 | + | unreachable; |
|
| 79 | + | } |
test/tests/regions.compiler.bitset.rad
added
+267 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | //! Bitset utilities for register tracking. |
|
| 5 | + | //! |
|
| 6 | + | //! Provides efficient bit-level set operations for tracking live registers |
|
| 7 | + | //! during liveness analysis and register allocation. |
|
| 8 | + | ||
| 9 | + | use std::lang::alloc; |
|
| 10 | + | ||
| 11 | + | /// Return the minimum of two 32-bit values. |
|
| 12 | + | fn min(a: u32, b: u32) -> u32 { |
|
| 13 | + | if a < b { |
|
| 14 | + | return a; |
|
| 15 | + | } |
|
| 16 | + | return b; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Calculate the number of 32-bit words needed to store `n` bits. |
|
| 20 | + | fn wordsFor(n: u32) -> u32 { |
|
| 21 | + | return (n + 31) / 32; |
|
| 22 | + | } |
|
| 23 | + | ||
| 24 | + | /// A fixed-size bitset backed by an array of 32-bit words. |
|
| 25 | + | record Bitset: 'bits { |
|
| 26 | + | /// Backing words. The storage must outlive the bitset and its iterators. |
|
| 27 | + | bits: &'bits mut [u32], |
|
| 28 | + | /// Number of bits this bitset can hold. |
|
| 29 | + | len: u32, |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | /// Create a new bitset backed by the given zero-initialized storage. |
|
| 33 | + | /// The storage must outlive the bitset and its iterators. |
|
| 34 | + | fn new 'bits (bits: &'bits mut [u32]) -> Bitset 'bits { |
|
| 35 | + | let len = bits.len * 32; |
|
| 36 | + | return Bitset { bits: bits, len }; |
|
| 37 | + | } |
|
| 38 | + | ||
| 39 | + | /// Create a new bitset backed by the given storage, zeroing it first. |
|
| 40 | + | /// The storage must outlive the bitset and its iterators. |
|
| 41 | + | fn init 'bits (bits: &'bits mut [u32]) -> Bitset 'bits { |
|
| 42 | + | for i in 0..bits.len { |
|
| 43 | + | set bits[i] = 0; |
|
| 44 | + | } |
|
| 45 | + | return new(bits); |
|
| 46 | + | } |
|
| 47 | + | ||
| 48 | + | /// Create a bitset from arena allocation. |
|
| 49 | + | fn allocate 'bits (allocation: &Session 'bits, len: u32) -> Bitset 'bits throws (alloc::AllocError) { |
|
| 50 | + | let bits = try allocation.fill(0 as u32, wordsFor(len)); |
|
| 51 | + | return new(bits); |
|
| 52 | + | } |
|
| 53 | + | ||
| 54 | + | /// Set bit `n` in the bitset. |
|
| 55 | + | fn put 'bits (bs: &mut Bitset 'bits, n: u32) { |
|
| 56 | + | if n >= bs.len { |
|
| 57 | + | return; |
|
| 58 | + | } |
|
| 59 | + | let word = n / 32; |
|
| 60 | + | let b = n % 32; |
|
| 61 | + | ||
| 62 | + | set bs.bits[word] |= (1 << b); |
|
| 63 | + | } |
|
| 64 | + | ||
| 65 | + | /// Clear bit `n` in the bitset. |
|
| 66 | + | fn clear 'bits (bs: &mut Bitset 'bits, n: u32) { |
|
| 67 | + | if n >= bs.len { |
|
| 68 | + | return; |
|
| 69 | + | } |
|
| 70 | + | let word = n / 32; |
|
| 71 | + | let b = n % 32; |
|
| 72 | + | ||
| 73 | + | set bs.bits[word] &= ~(1 << b); |
|
| 74 | + | } |
|
| 75 | + | ||
| 76 | + | /// Check if bit `n` is set. |
|
| 77 | + | fn contains 'bits (bs: &Bitset 'bits, n: u32) -> bool { |
|
| 78 | + | if n >= bs.len { |
|
| 79 | + | return false; |
|
| 80 | + | } |
|
| 81 | + | let word = n / 32; |
|
| 82 | + | let b = n % 32; |
|
| 83 | + | ||
| 84 | + | return (bs.bits[word] & (1 << b)) <> 0; |
|
| 85 | + | } |
|
| 86 | + | ||
| 87 | + | /// Count the number of set bits. |
|
| 88 | + | fn count 'bits (bs: &Bitset 'bits) -> u32 { |
|
| 89 | + | let mut total: u32 = 0; |
|
| 90 | + | let numWords = bs.bits.len; |
|
| 91 | + | for i in 0..numWords { |
|
| 92 | + | let word = bs.bits[i]; |
|
| 93 | + | if word <> 0 { |
|
| 94 | + | set total += popCount(word); |
|
| 95 | + | } |
|
| 96 | + | } |
|
| 97 | + | return total; |
|
| 98 | + | } |
|
| 99 | + | ||
| 100 | + | /// Population count for a 32-bit word. |
|
| 101 | + | fn popCount(x: u32) -> u32 { |
|
| 102 | + | let mut n = x; |
|
| 103 | + | set n -= ((n >> 1) & 0x55555555); |
|
| 104 | + | set n = (n & 0x33333333) + ((n >> 2) & 0x33333333); |
|
| 105 | + | set n = (n + (n >> 4)) & 0x0F0F0F0F; |
|
| 106 | + | set n += (n >> 8); |
|
| 107 | + | set n += (n >> 16); |
|
| 108 | + | ||
| 109 | + | return n & 0x3F; |
|
| 110 | + | } |
|
| 111 | + | ||
| 112 | + | /// Union: `dst = dst | src`. |
|
| 113 | + | fn union_ 'bits (dst: &mut Bitset 'bits, src: &Bitset 'bits) { |
|
| 114 | + | let numWords = dst.bits.len; |
|
| 115 | + | let srcWords = src.bits.len; |
|
| 116 | + | let minWords = min(numWords, srcWords); |
|
| 117 | + | for i in 0..minWords { |
|
| 118 | + | set dst.bits[i] |= src.bits[i]; |
|
| 119 | + | } |
|
| 120 | + | } |
|
| 121 | + | ||
| 122 | + | /// Subtract: `dst = dst - src`. |
|
| 123 | + | fn subtract 'bits (dst: &mut Bitset 'bits, src: &Bitset 'bits) { |
|
| 124 | + | let numWords = dst.bits.len; |
|
| 125 | + | let srcWords = src.bits.len; |
|
| 126 | + | let minWords = min(numWords, srcWords); |
|
| 127 | + | for i in 0..minWords { |
|
| 128 | + | set dst.bits[i] &= ~src.bits[i]; |
|
| 129 | + | } |
|
| 130 | + | } |
|
| 131 | + | ||
| 132 | + | /// Check if two bitsets are equal. |
|
| 133 | + | fn eq 'bits (a: &Bitset 'bits, b: &Bitset 'bits) -> bool { |
|
| 134 | + | let numWordsA = a.bits.len; |
|
| 135 | + | let numWordsB = b.bits.len; |
|
| 136 | + | let minWords = min(numWordsA, numWordsB); |
|
| 137 | + | ||
| 138 | + | for i in 0..minWords { |
|
| 139 | + | if a.bits[i] <> b.bits[i] { |
|
| 140 | + | return false; |
|
| 141 | + | } |
|
| 142 | + | } |
|
| 143 | + | for i in minWords..numWordsA { |
|
| 144 | + | if a.bits[i] <> 0 { |
|
| 145 | + | return false; |
|
| 146 | + | } |
|
| 147 | + | } |
|
| 148 | + | for i in minWords..numWordsB { |
|
| 149 | + | if b.bits[i] <> 0 { |
|
| 150 | + | return false; |
|
| 151 | + | } |
|
| 152 | + | } |
|
| 153 | + | return true; |
|
| 154 | + | } |
|
| 155 | + | ||
| 156 | + | /// Copy bits from source to destination. |
|
| 157 | + | fn copy 'bits (dst: &mut Bitset 'bits, src: &Bitset 'bits) { |
|
| 158 | + | let numWords = dst.bits.len; |
|
| 159 | + | let srcWords = src.bits.len; |
|
| 160 | + | let minWords = min(numWords, srcWords); |
|
| 161 | + | ||
| 162 | + | for i in 0..minWords { |
|
| 163 | + | set dst.bits[i] = src.bits[i]; |
|
| 164 | + | } |
|
| 165 | + | // Clear remaining words if destination is larger. |
|
| 166 | + | for i in minWords..numWords { |
|
| 167 | + | set dst.bits[i] = 0; |
|
| 168 | + | } |
|
| 169 | + | } |
|
| 170 | + | ||
| 171 | + | /// Clear all bits. |
|
| 172 | + | fn clearAll 'bits (bs: &mut Bitset 'bits) { |
|
| 173 | + | let numWords = bs.bits.len; |
|
| 174 | + | for i in 0..numWords { |
|
| 175 | + | set bs.bits[i] = 0; |
|
| 176 | + | } |
|
| 177 | + | } |
|
| 178 | + | ||
| 179 | + | /// Iterator state for iterating set bits. |
|
| 180 | + | record BitIter: Copy { |
|
| 181 | + | /// Current word index. |
|
| 182 | + | wordIdx: u32, |
|
| 183 | + | /// Remaining bits in the current word (visited bits cleared). |
|
| 184 | + | remaining: u32, |
|
| 185 | + | } |
|
| 186 | + | ||
| 187 | + | /// Create an iterator over set bits. |
|
| 188 | + | /// The cursor retains the first word mask and its position. |
|
| 189 | + | fn iter 'bits (bs: &Bitset 'bits) -> BitIter { |
|
| 190 | + | let remaining = bs.bits[0] if bs.len > 0 else 0; |
|
| 191 | + | return BitIter { wordIdx: 0, remaining }; |
|
| 192 | + | } |
|
| 193 | + | ||
| 194 | + | /// Get the next set bit, or nil if none remain. |
|
| 195 | + | fn iterNext 'bits (it: &mut BitIter, bs: &Bitset 'bits) -> ?u32 { |
|
| 196 | + | let numWords = bs.bits.len; |
|
| 197 | + | // Skip to next non-zero word. |
|
| 198 | + | while it.remaining == 0 { |
|
| 199 | + | set it.wordIdx += 1; |
|
| 200 | + | if it.wordIdx >= numWords { |
|
| 201 | + | return nil; |
|
| 202 | + | } |
|
| 203 | + | set it.remaining = bs.bits[it.wordIdx]; |
|
| 204 | + | } |
|
| 205 | + | // Find lowest set bit position using de Bruijn sequence. |
|
| 206 | + | let b = ctz(it.remaining); |
|
| 207 | + | let n = it.wordIdx * 32 + b; |
|
| 208 | + | if n >= bs.len { |
|
| 209 | + | return nil; |
|
| 210 | + | } |
|
| 211 | + | // Clear the lowest set bit. |
|
| 212 | + | set it.remaining &= it.remaining - 1; |
|
| 213 | + | ||
| 214 | + | return n; |
|
| 215 | + | } |
|
| 216 | + | ||
| 217 | + | /// Count trailing zeros in a 32-bit value. |
|
| 218 | + | /// Returns the bit position of the lowest set bit (0-31). |
|
| 219 | + | /// Behavior is undefined if `x` is 0. |
|
| 220 | + | fn ctz(x: u32) -> u32 { |
|
| 221 | + | // De Bruijn sequence for 32-bit CTZ. |
|
| 222 | + | constant DEBRUIJN: u32 = 0x077CB531; |
|
| 223 | + | constant TABLE: [u8; 32] = [ |
|
| 224 | + | 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, |
|
| 225 | + | 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, |
|
| 226 | + | ]; |
|
| 227 | + | // Isolate lowest set bit, multiply by de Bruijn constant, look up. |
|
| 228 | + | let isolated = x & (~x + 1); |
|
| 229 | + | ||
| 230 | + | return TABLE[(isolated * DEBRUIJN) >> 27] as u32; |
|
| 231 | + | } |
|
| 232 | + | ||
| 233 | + | @default fn main() -> u32 { |
|
| 234 | + | static DATA: [u8; 256] = [0; 256]; |
|
| 235 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 236 | + | use arena as words in { |
|
| 237 | + | let mut first = try! allocate(&words, 96); |
|
| 238 | + | let mut second = try! allocate(&words, 96); |
|
| 239 | + | put(&mut first, 1); |
|
| 240 | + | put(&mut first, 41); |
|
| 241 | + | put(&mut second, 41); |
|
| 242 | + | put(&mut second, 65); |
|
| 243 | + | union_(&mut first, &second); |
|
| 244 | + | assert count(&first) == 3; |
|
| 245 | + | subtract(&mut first, &second); |
|
| 246 | + | assert count(&first) == 1 and contains(&first, 1); |
|
| 247 | + | copy(&mut first, &second); |
|
| 248 | + | assert eq(&first, &second); |
|
| 249 | + | { |
|
| 250 | + | let mut cursor = iter(&first); |
|
| 251 | + | assert iterNext(&mut cursor, &first) == 41; |
|
| 252 | + | clear(&mut first, 41); |
|
| 253 | + | assert iterNext(&mut cursor, &first) == 65; |
|
| 254 | + | assert iterNext(&mut cursor, &first) == nil; |
|
| 255 | + | } |
|
| 256 | + | clearAll(&mut first); |
|
| 257 | + | assert count(&first) == 0; |
|
| 258 | + | put(&mut first, 42); |
|
| 259 | + | clear(&mut second, 65); |
|
| 260 | + | assert count(&second) == 1; |
|
| 261 | + | { |
|
| 262 | + | let mut cursor = iter(&first); |
|
| 263 | + | let result = iterNext(&mut cursor, &first) else return 0; |
|
| 264 | + | return result; |
|
| 265 | + | } |
|
| 266 | + | } |
|
| 267 | + | } |
test/tests/regions.compiler.bitset.ril
added
+745 -0
| 1 | + | data $"regions.compiler.bitset::regions.compiler.bitset::ctz$nominal$DEBRUIJN" align 4 { |
|
| 2 | + | w32 125613361; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data $"regions.compiler.bitset::regions.compiler.bitset::ctz$nominal$TABLE" align 1 { |
|
| 6 | + | w8 0; |
|
| 7 | + | w8 1; |
|
| 8 | + | w8 28; |
|
| 9 | + | w8 2; |
|
| 10 | + | w8 29; |
|
| 11 | + | w8 14; |
|
| 12 | + | w8 24; |
|
| 13 | + | w8 3; |
|
| 14 | + | w8 30; |
|
| 15 | + | w8 22; |
|
| 16 | + | w8 20; |
|
| 17 | + | w8 15; |
|
| 18 | + | w8 25; |
|
| 19 | + | w8 17; |
|
| 20 | + | w8 4; |
|
| 21 | + | w8 8; |
|
| 22 | + | w8 31; |
|
| 23 | + | w8 27; |
|
| 24 | + | w8 13; |
|
| 25 | + | w8 23; |
|
| 26 | + | w8 21; |
|
| 27 | + | w8 19; |
|
| 28 | + | w8 16; |
|
| 29 | + | w8 7; |
|
| 30 | + | w8 26; |
|
| 31 | + | w8 12; |
|
| 32 | + | w8 18; |
|
| 33 | + | w8 6; |
|
| 34 | + | w8 11; |
|
| 35 | + | w8 5; |
|
| 36 | + | w8 10; |
|
| 37 | + | w8 9; |
|
| 38 | + | } |
|
| 39 | + | ||
| 40 | + | data mut $"regions.compiler.bitset::regions.compiler.bitset::main$nominal$DATA" align 1 { |
|
| 41 | + | w8 0 * 256; |
|
| 42 | + | } |
|
| 43 | + | ||
| 44 | + | fn w32 $"regions.compiler.bitset::min"(w32 %0, w32 %1) { |
|
| 45 | + | @entry0 |
|
| 46 | + | br.ult w32 %0 %1 @then1 @merge2; |
|
| 47 | + | @then1 |
|
| 48 | + | ret %0; |
|
| 49 | + | @merge2 |
|
| 50 | + | ret %1; |
|
| 51 | + | } |
|
| 52 | + | ||
| 53 | + | fn w32 $"regions.compiler.bitset::wordsFor"(w32 %0) { |
|
| 54 | + | @entry0 |
|
| 55 | + | add w32 %1 %0 31; |
|
| 56 | + | udiv w32 %2 %1 32; |
|
| 57 | + | ret %2; |
|
| 58 | + | } |
|
| 59 | + | ||
| 60 | + | fn w64 $"regions.compiler.bitset::new"(w64 %0, w64 %1) { |
|
| 61 | + | @entry0 |
|
| 62 | + | load w32 %2 %1 8; |
|
| 63 | + | mul w32 %3 %2 32; |
|
| 64 | + | reserve %4 24 8; |
|
| 65 | + | blit %4 %1 16; |
|
| 66 | + | store w32 %3 %4 16; |
|
| 67 | + | blit %0 %4 24; |
|
| 68 | + | ret %0; |
|
| 69 | + | } |
|
| 70 | + | ||
| 71 | + | fn w64 $"regions.compiler.bitset::init"(w64 %0, w64 %1) { |
|
| 72 | + | @entry0 |
|
| 73 | + | load w32 %2 %1 8; |
|
| 74 | + | jmp @loop1(0, %1); |
|
| 75 | + | @loop1(w32 %3, w64 %4) |
|
| 76 | + | br.ult w32 %3 %2 @body2 @merge3; |
|
| 77 | + | @body2 |
|
| 78 | + | load w32 %5 %4 8; |
|
| 79 | + | br.ult w32 %3 %5 @guard#pass4 @guard#trap5; |
|
| 80 | + | @merge3 |
|
| 81 | + | reserve %10 24 8; |
|
| 82 | + | call w64 %11 $"regions.compiler.bitset::new"(%10, %4); |
|
| 83 | + | blit %0 %11 24; |
|
| 84 | + | ret %0; |
|
| 85 | + | @guard#pass4 |
|
| 86 | + | load w64 %6 %4 0; |
|
| 87 | + | mul w64 %7 %3 4; |
|
| 88 | + | add w64 %8 %6 %7; |
|
| 89 | + | store w32 0 %8 0; |
|
| 90 | + | add w32 %9 %3 1; |
|
| 91 | + | jmp @loop1(%9, %4); |
|
| 92 | + | @guard#trap5 |
|
| 93 | + | ebreak; |
|
| 94 | + | unreachable; |
|
| 95 | + | } |
|
| 96 | + | ||
| 97 | + | fn w64 $"regions.compiler.bitset::allocate"(w64 %0, w64 %1, w32 %2) { |
|
| 98 | + | @entry0 |
|
| 99 | + | load w64 %3 %1 0; |
|
| 100 | + | load w64 %4 %1 8; |
|
| 101 | + | load w64 %5 %4 8; |
|
| 102 | + | zext w32 %6 0; |
|
| 103 | + | call w32 %7 $"regions.compiler.bitset::wordsFor"(%2); |
|
| 104 | + | reserve %8 24 8; |
|
| 105 | + | call w64 %9 %5(%8, %3, 4, 4, %7); |
|
| 106 | + | load w64 %10 %9 0; |
|
| 107 | + | reserve %11 16 8; |
|
| 108 | + | br.ne w32 %10 0 @err2 @ok1; |
|
| 109 | + | @ok1 |
|
| 110 | + | load w64 %12 %9 8; |
|
| 111 | + | jmp @fill3(0); |
|
| 112 | + | @err2 |
|
| 113 | + | reserve %18 32 8; |
|
| 114 | + | store w64 %10 %18 0; |
|
| 115 | + | add w64 %19 %9 8; |
|
| 116 | + | add w64 %20 %18 8; |
|
| 117 | + | blit %20 %19 1; |
|
| 118 | + | blit %0 %18 32; |
|
| 119 | + | ret %0; |
|
| 120 | + | @fill3(w32 %13) |
|
| 121 | + | br.ult w32 %13 %7 @fill4 @fill5; |
|
| 122 | + | @fill4 |
|
| 123 | + | mul w64 %14 %13 4; |
|
| 124 | + | add w64 %15 %12 %14; |
|
| 125 | + | store w32 %6 %15 0; |
|
| 126 | + | add w32 %16 %13 1; |
|
| 127 | + | jmp @fill3(%16); |
|
| 128 | + | @fill5 |
|
| 129 | + | add w64 %17 %9 8; |
|
| 130 | + | blit %11 %17 16; |
|
| 131 | + | jmp @merge6; |
|
| 132 | + | @merge6 |
|
| 133 | + | reserve %21 24 8; |
|
| 134 | + | call w64 %22 $"regions.compiler.bitset::new"(%21, %11); |
|
| 135 | + | reserve %23 32 8; |
|
| 136 | + | store w64 0 %23 0; |
|
| 137 | + | add w64 %24 %23 8; |
|
| 138 | + | blit %24 %22 24; |
|
| 139 | + | blit %0 %23 32; |
|
| 140 | + | ret %0; |
|
| 141 | + | } |
|
| 142 | + | ||
| 143 | + | fn w64 $"regions.compiler.bitset::put"(w64 %0, w32 %1) { |
|
| 144 | + | @entry0 |
|
| 145 | + | load w32 %2 %0 16; |
|
| 146 | + | br.ult w32 %1 %2 @merge2 @then1; |
|
| 147 | + | @then1 |
|
| 148 | + | ret undefined; |
|
| 149 | + | @merge2 |
|
| 150 | + | udiv w32 %3 %1 32; |
|
| 151 | + | urem w32 %4 %1 32; |
|
| 152 | + | load w32 %5 %0 8; |
|
| 153 | + | br.ult w32 %3 %5 @guard#pass3 @guard#trap4; |
|
| 154 | + | @guard#pass3 |
|
| 155 | + | load w64 %6 %0 0; |
|
| 156 | + | mul w64 %7 %3 4; |
|
| 157 | + | add w64 %8 %6 %7; |
|
| 158 | + | load w32 %9 %8 0; |
|
| 159 | + | shl w32 %10 1 %4; |
|
| 160 | + | or w32 %11 %9 %10; |
|
| 161 | + | store w32 %11 %8 0; |
|
| 162 | + | ret; |
|
| 163 | + | @guard#trap4 |
|
| 164 | + | ebreak; |
|
| 165 | + | unreachable; |
|
| 166 | + | } |
|
| 167 | + | ||
| 168 | + | fn w64 $"regions.compiler.bitset::clear"(w64 %0, w32 %1) { |
|
| 169 | + | @entry0 |
|
| 170 | + | load w32 %2 %0 16; |
|
| 171 | + | br.ult w32 %1 %2 @merge2 @then1; |
|
| 172 | + | @then1 |
|
| 173 | + | ret undefined; |
|
| 174 | + | @merge2 |
|
| 175 | + | udiv w32 %3 %1 32; |
|
| 176 | + | urem w32 %4 %1 32; |
|
| 177 | + | load w32 %5 %0 8; |
|
| 178 | + | br.ult w32 %3 %5 @guard#pass3 @guard#trap4; |
|
| 179 | + | @guard#pass3 |
|
| 180 | + | load w64 %6 %0 0; |
|
| 181 | + | mul w64 %7 %3 4; |
|
| 182 | + | add w64 %8 %6 %7; |
|
| 183 | + | load w32 %9 %8 0; |
|
| 184 | + | shl w32 %10 1 %4; |
|
| 185 | + | not w32 %11 %10; |
|
| 186 | + | and w32 %12 %9 %11; |
|
| 187 | + | store w32 %12 %8 0; |
|
| 188 | + | ret; |
|
| 189 | + | @guard#trap4 |
|
| 190 | + | ebreak; |
|
| 191 | + | unreachable; |
|
| 192 | + | } |
|
| 193 | + | ||
| 194 | + | fn w8 $"regions.compiler.bitset::contains"(w64 %0, w32 %1) { |
|
| 195 | + | @entry0 |
|
| 196 | + | load w32 %2 %0 16; |
|
| 197 | + | br.ult w32 %1 %2 @merge2 @then1; |
|
| 198 | + | @then1 |
|
| 199 | + | ret 0; |
|
| 200 | + | @merge2 |
|
| 201 | + | udiv w32 %3 %1 32; |
|
| 202 | + | urem w32 %4 %1 32; |
|
| 203 | + | load w32 %5 %0 8; |
|
| 204 | + | br.ult w32 %3 %5 @guard#pass3 @guard#trap4; |
|
| 205 | + | @guard#pass3 |
|
| 206 | + | load w64 %6 %0 0; |
|
| 207 | + | mul w64 %7 %3 4; |
|
| 208 | + | add w64 %8 %6 %7; |
|
| 209 | + | load w32 %9 %8 0; |
|
| 210 | + | shl w32 %10 1 %4; |
|
| 211 | + | and w32 %11 %9 %10; |
|
| 212 | + | ne w32 %12 %11 0; |
|
| 213 | + | ret %12; |
|
| 214 | + | @guard#trap4 |
|
| 215 | + | ebreak; |
|
| 216 | + | unreachable; |
|
| 217 | + | } |
|
| 218 | + | ||
| 219 | + | fn w32 $"regions.compiler.bitset::count"(w64 %0) { |
|
| 220 | + | @entry0 |
|
| 221 | + | load w32 %1 %0 8; |
|
| 222 | + | jmp @loop1(0, %0, 0); |
|
| 223 | + | @loop1(w32 %2, w64 %3, w32 %9) |
|
| 224 | + | br.ult w32 %2 %1 @body2 @merge3; |
|
| 225 | + | @body2 |
|
| 226 | + | load w32 %4 %3 8; |
|
| 227 | + | br.ult w32 %2 %4 @guard#pass4 @guard#trap5; |
|
| 228 | + | @merge3 |
|
| 229 | + | ret %9; |
|
| 230 | + | @guard#pass4 |
|
| 231 | + | load w64 %5 %3 0; |
|
| 232 | + | mul w64 %6 %2 4; |
|
| 233 | + | add w64 %7 %5 %6; |
|
| 234 | + | load w32 %8 %7 0; |
|
| 235 | + | br.ne w32 %8 0 @then6 @merge7(%9); |
|
| 236 | + | @guard#trap5 |
|
| 237 | + | ebreak; |
|
| 238 | + | unreachable; |
|
| 239 | + | @then6 |
|
| 240 | + | call w32 %10 $"regions.compiler.bitset::popCount"(%8); |
|
| 241 | + | add w32 %11 %9 %10; |
|
| 242 | + | jmp @merge7(%11); |
|
| 243 | + | @merge7(w32 %15) |
|
| 244 | + | add w32 %13 %2 1; |
|
| 245 | + | jmp @loop1(%13, %3, %15); |
|
| 246 | + | } |
|
| 247 | + | ||
| 248 | + | fn w32 $"regions.compiler.bitset::popCount"(w32 %0) { |
|
| 249 | + | @entry0 |
|
| 250 | + | ushr w32 %1 %0 1; |
|
| 251 | + | and w32 %2 %1 1431655765; |
|
| 252 | + | sub w32 %3 %0 %2; |
|
| 253 | + | and w32 %4 %3 858993459; |
|
| 254 | + | ushr w32 %5 %3 2; |
|
| 255 | + | and w32 %6 %5 858993459; |
|
| 256 | + | add w32 %7 %4 %6; |
|
| 257 | + | ushr w32 %8 %7 4; |
|
| 258 | + | add w32 %9 %7 %8; |
|
| 259 | + | and w32 %10 %9 252645135; |
|
| 260 | + | ushr w32 %11 %10 8; |
|
| 261 | + | add w32 %12 %10 %11; |
|
| 262 | + | ushr w32 %13 %12 16; |
|
| 263 | + | add w32 %14 %12 %13; |
|
| 264 | + | and w32 %15 %14 63; |
|
| 265 | + | ret %15; |
|
| 266 | + | } |
|
| 267 | + | ||
| 268 | + | fn w64 $"regions.compiler.bitset::union_"(w64 %0, w64 %1) { |
|
| 269 | + | @entry0 |
|
| 270 | + | load w32 %2 %0 8; |
|
| 271 | + | load w32 %3 %1 8; |
|
| 272 | + | call w32 %4 $"regions.compiler.bitset::min"(%2, %3); |
|
| 273 | + | jmp @loop1(0, %0, %1); |
|
| 274 | + | @loop1(w32 %5, w64 %6, w64 %12) |
|
| 275 | + | br.ult w32 %5 %4 @body2 @merge3; |
|
| 276 | + | @body2 |
|
| 277 | + | load w32 %7 %6 8; |
|
| 278 | + | br.ult w32 %5 %7 @guard#pass4 @guard#trap5; |
|
| 279 | + | @merge3 |
|
| 280 | + | ret; |
|
| 281 | + | @guard#pass4 |
|
| 282 | + | load w64 %8 %6 0; |
|
| 283 | + | mul w64 %9 %5 4; |
|
| 284 | + | add w64 %10 %8 %9; |
|
| 285 | + | load w32 %11 %10 0; |
|
| 286 | + | load w32 %13 %12 8; |
|
| 287 | + | br.ult w32 %5 %13 @guard#pass6 @guard#trap7; |
|
| 288 | + | @guard#trap5 |
|
| 289 | + | ebreak; |
|
| 290 | + | unreachable; |
|
| 291 | + | @guard#pass6 |
|
| 292 | + | load w64 %14 %12 0; |
|
| 293 | + | mul w64 %15 %5 4; |
|
| 294 | + | add w64 %16 %14 %15; |
|
| 295 | + | load w32 %17 %16 0; |
|
| 296 | + | or w32 %18 %11 %17; |
|
| 297 | + | store w32 %18 %10 0; |
|
| 298 | + | add w32 %19 %5 1; |
|
| 299 | + | jmp @loop1(%19, %6, %12); |
|
| 300 | + | @guard#trap7 |
|
| 301 | + | ebreak; |
|
| 302 | + | unreachable; |
|
| 303 | + | } |
|
| 304 | + | ||
| 305 | + | fn w64 $"regions.compiler.bitset::subtract"(w64 %0, w64 %1) { |
|
| 306 | + | @entry0 |
|
| 307 | + | load w32 %2 %0 8; |
|
| 308 | + | load w32 %3 %1 8; |
|
| 309 | + | call w32 %4 $"regions.compiler.bitset::min"(%2, %3); |
|
| 310 | + | jmp @loop1(0, %0, %1); |
|
| 311 | + | @loop1(w32 %5, w64 %6, w64 %12) |
|
| 312 | + | br.ult w32 %5 %4 @body2 @merge3; |
|
| 313 | + | @body2 |
|
| 314 | + | load w32 %7 %6 8; |
|
| 315 | + | br.ult w32 %5 %7 @guard#pass4 @guard#trap5; |
|
| 316 | + | @merge3 |
|
| 317 | + | ret; |
|
| 318 | + | @guard#pass4 |
|
| 319 | + | load w64 %8 %6 0; |
|
| 320 | + | mul w64 %9 %5 4; |
|
| 321 | + | add w64 %10 %8 %9; |
|
| 322 | + | load w32 %11 %10 0; |
|
| 323 | + | load w32 %13 %12 8; |
|
| 324 | + | br.ult w32 %5 %13 @guard#pass6 @guard#trap7; |
|
| 325 | + | @guard#trap5 |
|
| 326 | + | ebreak; |
|
| 327 | + | unreachable; |
|
| 328 | + | @guard#pass6 |
|
| 329 | + | load w64 %14 %12 0; |
|
| 330 | + | mul w64 %15 %5 4; |
|
| 331 | + | add w64 %16 %14 %15; |
|
| 332 | + | load w32 %17 %16 0; |
|
| 333 | + | not w32 %18 %17; |
|
| 334 | + | and w32 %19 %11 %18; |
|
| 335 | + | store w32 %19 %10 0; |
|
| 336 | + | add w32 %20 %5 1; |
|
| 337 | + | jmp @loop1(%20, %6, %12); |
|
| 338 | + | @guard#trap7 |
|
| 339 | + | ebreak; |
|
| 340 | + | unreachable; |
|
| 341 | + | } |
|
| 342 | + | ||
| 343 | + | fn w8 $"regions.compiler.bitset::eq"(w64 %0, w64 %1) { |
|
| 344 | + | @entry0 |
|
| 345 | + | load w32 %2 %0 8; |
|
| 346 | + | load w32 %3 %1 8; |
|
| 347 | + | call w32 %4 $"regions.compiler.bitset::min"(%2, %3); |
|
| 348 | + | jmp @loop1(0, %0, %1); |
|
| 349 | + | @loop1(w32 %5, w64 %6, w64 %12) |
|
| 350 | + | br.ult w32 %5 %4 @body2 @merge3; |
|
| 351 | + | @body2 |
|
| 352 | + | load w32 %7 %6 8; |
|
| 353 | + | br.ult w32 %5 %7 @guard#pass6 @guard#trap7; |
|
| 354 | + | @merge3 |
|
| 355 | + | jmp @loop10(%4, %6); |
|
| 356 | + | @then4 |
|
| 357 | + | ret 0; |
|
| 358 | + | @merge5 |
|
| 359 | + | add w32 %18 %5 1; |
|
| 360 | + | jmp @loop1(%18, %6, %12); |
|
| 361 | + | @guard#pass6 |
|
| 362 | + | load w64 %8 %6 0; |
|
| 363 | + | mul w64 %9 %5 4; |
|
| 364 | + | add w64 %10 %8 %9; |
|
| 365 | + | load w32 %11 %10 0; |
|
| 366 | + | load w32 %13 %12 8; |
|
| 367 | + | br.ult w32 %5 %13 @guard#pass8 @guard#trap9; |
|
| 368 | + | @guard#trap7 |
|
| 369 | + | ebreak; |
|
| 370 | + | unreachable; |
|
| 371 | + | @guard#pass8 |
|
| 372 | + | load w64 %14 %12 0; |
|
| 373 | + | mul w64 %15 %5 4; |
|
| 374 | + | add w64 %16 %14 %15; |
|
| 375 | + | load w32 %17 %16 0; |
|
| 376 | + | br.ne w32 %11 %17 @then4 @merge5; |
|
| 377 | + | @guard#trap9 |
|
| 378 | + | ebreak; |
|
| 379 | + | unreachable; |
|
| 380 | + | @loop10(w32 %21, w64 %22) |
|
| 381 | + | br.ult w32 %21 %2 @body11 @merge12; |
|
| 382 | + | @body11 |
|
| 383 | + | load w32 %23 %22 8; |
|
| 384 | + | br.ult w32 %21 %23 @guard#pass15 @guard#trap16; |
|
| 385 | + | @merge12 |
|
| 386 | + | jmp @loop17(%4, %12); |
|
| 387 | + | @then13 |
|
| 388 | + | ret 0; |
|
| 389 | + | @merge14 |
|
| 390 | + | add w32 %28 %21 1; |
|
| 391 | + | jmp @loop10(%28, %22); |
|
| 392 | + | @guard#pass15 |
|
| 393 | + | load w64 %24 %22 0; |
|
| 394 | + | mul w64 %25 %21 4; |
|
| 395 | + | add w64 %26 %24 %25; |
|
| 396 | + | load w32 %27 %26 0; |
|
| 397 | + | br.ne w32 %27 0 @then13 @merge14; |
|
| 398 | + | @guard#trap16 |
|
| 399 | + | ebreak; |
|
| 400 | + | unreachable; |
|
| 401 | + | @loop17(w32 %32, w64 %33) |
|
| 402 | + | br.ult w32 %32 %3 @body18 @merge19; |
|
| 403 | + | @body18 |
|
| 404 | + | load w32 %34 %33 8; |
|
| 405 | + | br.ult w32 %32 %34 @guard#pass22 @guard#trap23; |
|
| 406 | + | @merge19 |
|
| 407 | + | ret 1; |
|
| 408 | + | @then20 |
|
| 409 | + | ret 0; |
|
| 410 | + | @merge21 |
|
| 411 | + | add w32 %39 %32 1; |
|
| 412 | + | jmp @loop17(%39, %33); |
|
| 413 | + | @guard#pass22 |
|
| 414 | + | load w64 %35 %33 0; |
|
| 415 | + | mul w64 %36 %32 4; |
|
| 416 | + | add w64 %37 %35 %36; |
|
| 417 | + | load w32 %38 %37 0; |
|
| 418 | + | br.ne w32 %38 0 @then20 @merge21; |
|
| 419 | + | @guard#trap23 |
|
| 420 | + | ebreak; |
|
| 421 | + | unreachable; |
|
| 422 | + | } |
|
| 423 | + | ||
| 424 | + | fn w64 $"regions.compiler.bitset::copy"(w64 %0, w64 %1) { |
|
| 425 | + | @entry0 |
|
| 426 | + | load w32 %2 %0 8; |
|
| 427 | + | load w32 %3 %1 8; |
|
| 428 | + | call w32 %4 $"regions.compiler.bitset::min"(%2, %3); |
|
| 429 | + | jmp @loop1(0, %1, %0); |
|
| 430 | + | @loop1(w32 %5, w64 %6, w64 %12) |
|
| 431 | + | br.ult w32 %5 %4 @body2 @merge3; |
|
| 432 | + | @body2 |
|
| 433 | + | load w32 %7 %6 8; |
|
| 434 | + | br.ult w32 %5 %7 @guard#pass4 @guard#trap5; |
|
| 435 | + | @merge3 |
|
| 436 | + | jmp @loop8(%4, %12); |
|
| 437 | + | @guard#pass4 |
|
| 438 | + | load w64 %8 %6 0; |
|
| 439 | + | mul w64 %9 %5 4; |
|
| 440 | + | add w64 %10 %8 %9; |
|
| 441 | + | load w32 %11 %10 0; |
|
| 442 | + | load w32 %13 %12 8; |
|
| 443 | + | br.ult w32 %5 %13 @guard#pass6 @guard#trap7; |
|
| 444 | + | @guard#trap5 |
|
| 445 | + | ebreak; |
|
| 446 | + | unreachable; |
|
| 447 | + | @guard#pass6 |
|
| 448 | + | load w64 %14 %12 0; |
|
| 449 | + | mul w64 %15 %5 4; |
|
| 450 | + | add w64 %16 %14 %15; |
|
| 451 | + | store w32 %11 %16 0; |
|
| 452 | + | add w32 %17 %5 1; |
|
| 453 | + | jmp @loop1(%17, %6, %12); |
|
| 454 | + | @guard#trap7 |
|
| 455 | + | ebreak; |
|
| 456 | + | unreachable; |
|
| 457 | + | @loop8(w32 %20, w64 %21) |
|
| 458 | + | br.ult w32 %20 %2 @body9 @merge10; |
|
| 459 | + | @body9 |
|
| 460 | + | load w32 %22 %21 8; |
|
| 461 | + | br.ult w32 %20 %22 @guard#pass11 @guard#trap12; |
|
| 462 | + | @merge10 |
|
| 463 | + | ret; |
|
| 464 | + | @guard#pass11 |
|
| 465 | + | load w64 %23 %21 0; |
|
| 466 | + | mul w64 %24 %20 4; |
|
| 467 | + | add w64 %25 %23 %24; |
|
| 468 | + | store w32 0 %25 0; |
|
| 469 | + | add w32 %26 %20 1; |
|
| 470 | + | jmp @loop8(%26, %21); |
|
| 471 | + | @guard#trap12 |
|
| 472 | + | ebreak; |
|
| 473 | + | unreachable; |
|
| 474 | + | } |
|
| 475 | + | ||
| 476 | + | fn w64 $"regions.compiler.bitset::clearAll"(w64 %0) { |
|
| 477 | + | @entry0 |
|
| 478 | + | load w32 %1 %0 8; |
|
| 479 | + | jmp @loop1(0, %0); |
|
| 480 | + | @loop1(w32 %2, w64 %3) |
|
| 481 | + | br.ult w32 %2 %1 @body2 @merge3; |
|
| 482 | + | @body2 |
|
| 483 | + | load w32 %4 %3 8; |
|
| 484 | + | br.ult w32 %2 %4 @guard#pass4 @guard#trap5; |
|
| 485 | + | @merge3 |
|
| 486 | + | ret; |
|
| 487 | + | @guard#pass4 |
|
| 488 | + | load w64 %5 %3 0; |
|
| 489 | + | mul w64 %6 %2 4; |
|
| 490 | + | add w64 %7 %5 %6; |
|
| 491 | + | store w32 0 %7 0; |
|
| 492 | + | add w32 %8 %2 1; |
|
| 493 | + | jmp @loop1(%8, %3); |
|
| 494 | + | @guard#trap5 |
|
| 495 | + | ebreak; |
|
| 496 | + | unreachable; |
|
| 497 | + | } |
|
| 498 | + | ||
| 499 | + | fn w64 $"regions.compiler.bitset::iter"(w64 %0) { |
|
| 500 | + | @entry0 |
|
| 501 | + | load w32 %1 %0 16; |
|
| 502 | + | br.ult w32 0 %1 @cond#then1 @cond#else2; |
|
| 503 | + | @cond#then1 |
|
| 504 | + | load w32 %3 %0 8; |
|
| 505 | + | br.ult w32 0 %3 @guard#pass4 @guard#trap5; |
|
| 506 | + | @cond#else2 |
|
| 507 | + | jmp @cond#merge3(0); |
|
| 508 | + | @cond#merge3(w32 %2) |
|
| 509 | + | reserve %6 8 4; |
|
| 510 | + | store w32 0 %6 0; |
|
| 511 | + | store w32 %2 %6 4; |
|
| 512 | + | reserve %7 8 8; |
|
| 513 | + | store w64 0 %7 0; |
|
| 514 | + | blit %7 %6 8; |
|
| 515 | + | load w64 %8 %7 0; |
|
| 516 | + | ret %8; |
|
| 517 | + | @guard#pass4 |
|
| 518 | + | load w64 %4 %0 0; |
|
| 519 | + | load w32 %5 %4 0; |
|
| 520 | + | jmp @cond#merge3(%5); |
|
| 521 | + | @guard#trap5 |
|
| 522 | + | ebreak; |
|
| 523 | + | unreachable; |
|
| 524 | + | } |
|
| 525 | + | ||
| 526 | + | fn w64 $"regions.compiler.bitset::iterNext"(w64 %0, w64 %1, w64 %2) { |
|
| 527 | + | @entry0 |
|
| 528 | + | load w32 %3 %2 8; |
|
| 529 | + | jmp @while1(%1, %3, %2); |
|
| 530 | + | @while1(w64 %4, w32 %9, w64 %11) |
|
| 531 | + | load w32 %5 %4 4; |
|
| 532 | + | br.eq w32 %5 0 @body2 @merge3; |
|
| 533 | + | @body2 |
|
| 534 | + | load w32 %6 %4 0; |
|
| 535 | + | add w32 %7 %6 1; |
|
| 536 | + | store w32 %7 %4 0; |
|
| 537 | + | load w32 %8 %4 0; |
|
| 538 | + | br.ult w32 %8 %9 @merge5 @then4; |
|
| 539 | + | @merge3 |
|
| 540 | + | load w32 %18 %4 4; |
|
| 541 | + | call w32 %19 $"regions.compiler.bitset::ctz"(%18); |
|
| 542 | + | load w32 %20 %4 0; |
|
| 543 | + | mul w32 %21 %20 32; |
|
| 544 | + | add w32 %22 %21 %19; |
|
| 545 | + | load w32 %23 %11 16; |
|
| 546 | + | br.ult w32 %22 %23 @merge9 @then8; |
|
| 547 | + | @then4 |
|
| 548 | + | reserve %10 8 4; |
|
| 549 | + | store w8 0 %10 0; |
|
| 550 | + | blit %0 %10 8; |
|
| 551 | + | ret %0; |
|
| 552 | + | @merge5 |
|
| 553 | + | load w32 %12 %4 0; |
|
| 554 | + | load w32 %13 %11 8; |
|
| 555 | + | br.ult w32 %12 %13 @guard#pass6 @guard#trap7; |
|
| 556 | + | @guard#pass6 |
|
| 557 | + | load w64 %14 %11 0; |
|
| 558 | + | mul w64 %15 %12 4; |
|
| 559 | + | add w64 %16 %14 %15; |
|
| 560 | + | load w32 %17 %16 0; |
|
| 561 | + | store w32 %17 %4 4; |
|
| 562 | + | jmp @while1(%4, %9, %11); |
|
| 563 | + | @guard#trap7 |
|
| 564 | + | ebreak; |
|
| 565 | + | unreachable; |
|
| 566 | + | @then8 |
|
| 567 | + | reserve %24 8 4; |
|
| 568 | + | store w8 0 %24 0; |
|
| 569 | + | blit %0 %24 8; |
|
| 570 | + | ret %0; |
|
| 571 | + | @merge9 |
|
| 572 | + | load w32 %25 %4 4; |
|
| 573 | + | load w32 %26 %4 4; |
|
| 574 | + | sub w32 %27 %26 1; |
|
| 575 | + | and w32 %28 %25 %27; |
|
| 576 | + | store w32 %28 %4 4; |
|
| 577 | + | reserve %29 8 4; |
|
| 578 | + | store w8 1 %29 0; |
|
| 579 | + | store w32 %22 %29 4; |
|
| 580 | + | blit %0 %29 8; |
|
| 581 | + | ret %0; |
|
| 582 | + | } |
|
| 583 | + | ||
| 584 | + | fn w32 $"regions.compiler.bitset::ctz"(w32 %0) { |
|
| 585 | + | @entry0 |
|
| 586 | + | not w32 %1 %0; |
|
| 587 | + | add w32 %2 %1 1; |
|
| 588 | + | and w32 %3 %0 %2; |
|
| 589 | + | copy %4 $"regions.compiler.bitset::regions.compiler.bitset::ctz$nominal$TABLE"; |
|
| 590 | + | mul w32 %5 %3 125613361; |
|
| 591 | + | ushr w32 %6 %5 27; |
|
| 592 | + | br.ult w32 %6 32 @guard#pass1 @guard#trap2; |
|
| 593 | + | @guard#pass1 |
|
| 594 | + | add w64 %7 %4 %6; |
|
| 595 | + | load w8 %8 %7 0; |
|
| 596 | + | zext w8 %9 %8; |
|
| 597 | + | ret %9; |
|
| 598 | + | @guard#trap2 |
|
| 599 | + | ebreak; |
|
| 600 | + | unreachable; |
|
| 601 | + | } |
|
| 602 | + | ||
| 603 | + | fn w32 $"regions.compiler.bitset::main"() { |
|
| 604 | + | @entry0 |
|
| 605 | + | copy %0 $"regions.compiler.bitset::regions.compiler.bitset::main$nominal$DATA"; |
|
| 606 | + | reserve %1 16 8; |
|
| 607 | + | store w64 %0 %1 0; |
|
| 608 | + | store w32 256 %1 8; |
|
| 609 | + | store w32 256 %1 12; |
|
| 610 | + | reserve %2 24 8; |
|
| 611 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 612 | + | reserve %4 16 8; |
|
| 613 | + | store w64 %3 %4 0; |
|
| 614 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 615 | + | reserve %5 32 8; |
|
| 616 | + | call w64 %6 $"regions.compiler.bitset::allocate"(%5, %4, 96); |
|
| 617 | + | load w64 %7 %6 0; |
|
| 618 | + | reserve %8 24 8; |
|
| 619 | + | br.ne w32 %7 0 @err2 @ok1; |
|
| 620 | + | @ok1 |
|
| 621 | + | add w64 %9 %6 8; |
|
| 622 | + | blit %8 %9 24; |
|
| 623 | + | jmp @merge3; |
|
| 624 | + | @err2 |
|
| 625 | + | unreachable; |
|
| 626 | + | @merge3 |
|
| 627 | + | reserve %10 32 8; |
|
| 628 | + | call w64 %11 $"regions.compiler.bitset::allocate"(%10, %4, 96); |
|
| 629 | + | load w64 %12 %11 0; |
|
| 630 | + | reserve %13 24 8; |
|
| 631 | + | br.ne w32 %12 0 @err5 @ok4; |
|
| 632 | + | @ok4 |
|
| 633 | + | add w64 %14 %11 8; |
|
| 634 | + | blit %13 %14 24; |
|
| 635 | + | jmp @merge6; |
|
| 636 | + | @err5 |
|
| 637 | + | unreachable; |
|
| 638 | + | @merge6 |
|
| 639 | + | call w64 $"regions.compiler.bitset::put"(%8, 1); |
|
| 640 | + | call w64 $"regions.compiler.bitset::put"(%8, 41); |
|
| 641 | + | call w64 $"regions.compiler.bitset::put"(%13, 41); |
|
| 642 | + | call w64 $"regions.compiler.bitset::put"(%13, 65); |
|
| 643 | + | call w64 $"regions.compiler.bitset::union_"(%8, %13); |
|
| 644 | + | call w32 %15 $"regions.compiler.bitset::count"(%8); |
|
| 645 | + | br.eq w32 %15 3 @assert.ok8 @assert.fail7; |
|
| 646 | + | @assert.fail7 |
|
| 647 | + | unreachable; |
|
| 648 | + | @assert.ok8 |
|
| 649 | + | call w64 $"regions.compiler.bitset::subtract"(%8, %13); |
|
| 650 | + | call w32 %17 $"regions.compiler.bitset::count"(%8); |
|
| 651 | + | br.eq w32 %17 1 @and#then11 @and#else12; |
|
| 652 | + | @assert.fail9 |
|
| 653 | + | unreachable; |
|
| 654 | + | @assert.ok10 |
|
| 655 | + | call w64 $"regions.compiler.bitset::copy"(%8, %13); |
|
| 656 | + | call w8 %21 $"regions.compiler.bitset::eq"(%8, %13); |
|
| 657 | + | br.ne w32 %21 0 @assert.ok15 @assert.fail14; |
|
| 658 | + | @and#then11 |
|
| 659 | + | call w8 %18 $"regions.compiler.bitset::contains"(%8, 1); |
|
| 660 | + | jmp @and#end13(%18); |
|
| 661 | + | @and#else12 |
|
| 662 | + | jmp @and#end13(0); |
|
| 663 | + | @and#end13(w8 %16) |
|
| 664 | + | br.ne w32 %16 0 @assert.ok10 @assert.fail9; |
|
| 665 | + | @assert.fail14 |
|
| 666 | + | unreachable; |
|
| 667 | + | @assert.ok15 |
|
| 668 | + | call w64 %22 $"regions.compiler.bitset::iter"(%8); |
|
| 669 | + | reserve %23 8 8; |
|
| 670 | + | store w64 %22 %23 0; |
|
| 671 | + | reserve %24 8 4; |
|
| 672 | + | call w64 %25 $"regions.compiler.bitset::iterNext"(%24, %23, %8); |
|
| 673 | + | reserve %26 8 4; |
|
| 674 | + | store w8 1 %26 0; |
|
| 675 | + | store w32 41 %26 4; |
|
| 676 | + | load w8 %27 %25 0; |
|
| 677 | + | load w8 %28 %26 0; |
|
| 678 | + | eq w8 %29 %27 %28; |
|
| 679 | + | eq w8 %30 %27 0; |
|
| 680 | + | load w32 %31 %25 4; |
|
| 681 | + | load w32 %32 %26 4; |
|
| 682 | + | eq w32 %33 %31 %32; |
|
| 683 | + | or w32 %34 %30 %33; |
|
| 684 | + | and w32 %35 %29 %34; |
|
| 685 | + | br.ne w32 %35 0 @assert.ok17 @assert.fail16; |
|
| 686 | + | @assert.fail16 |
|
| 687 | + | unreachable; |
|
| 688 | + | @assert.ok17 |
|
| 689 | + | call w64 $"regions.compiler.bitset::clear"(%8, 41); |
|
| 690 | + | reserve %36 8 4; |
|
| 691 | + | call w64 %37 $"regions.compiler.bitset::iterNext"(%36, %23, %8); |
|
| 692 | + | reserve %38 8 4; |
|
| 693 | + | store w8 1 %38 0; |
|
| 694 | + | store w32 65 %38 4; |
|
| 695 | + | load w8 %39 %37 0; |
|
| 696 | + | load w8 %40 %38 0; |
|
| 697 | + | eq w8 %41 %39 %40; |
|
| 698 | + | eq w8 %42 %39 0; |
|
| 699 | + | load w32 %43 %37 4; |
|
| 700 | + | load w32 %44 %38 4; |
|
| 701 | + | eq w32 %45 %43 %44; |
|
| 702 | + | or w32 %46 %42 %45; |
|
| 703 | + | and w32 %47 %41 %46; |
|
| 704 | + | br.ne w32 %47 0 @assert.ok19 @assert.fail18; |
|
| 705 | + | @assert.fail18 |
|
| 706 | + | unreachable; |
|
| 707 | + | @assert.ok19 |
|
| 708 | + | reserve %48 8 4; |
|
| 709 | + | call w64 %49 $"regions.compiler.bitset::iterNext"(%48, %23, %8); |
|
| 710 | + | load w8 %50 %49 0; |
|
| 711 | + | eq w8 %51 %50 0; |
|
| 712 | + | br.ne w32 %51 0 @assert.ok21 @assert.fail20; |
|
| 713 | + | @assert.fail20 |
|
| 714 | + | unreachable; |
|
| 715 | + | @assert.ok21 |
|
| 716 | + | call w64 $"regions.compiler.bitset::clearAll"(%8); |
|
| 717 | + | call w32 %52 $"regions.compiler.bitset::count"(%8); |
|
| 718 | + | br.eq w32 %52 0 @assert.ok23 @assert.fail22; |
|
| 719 | + | @assert.fail22 |
|
| 720 | + | unreachable; |
|
| 721 | + | @assert.ok23 |
|
| 722 | + | call w64 $"regions.compiler.bitset::put"(%8, 42); |
|
| 723 | + | call w64 $"regions.compiler.bitset::clear"(%13, 65); |
|
| 724 | + | call w32 %53 $"regions.compiler.bitset::count"(%13); |
|
| 725 | + | br.eq w32 %53 1 @assert.ok25 @assert.fail24; |
|
| 726 | + | @assert.fail24 |
|
| 727 | + | unreachable; |
|
| 728 | + | @assert.ok25 |
|
| 729 | + | call w64 %54 $"regions.compiler.bitset::iter"(%8); |
|
| 730 | + | reserve %55 8 8; |
|
| 731 | + | store w64 %54 %55 0; |
|
| 732 | + | reserve %56 8 4; |
|
| 733 | + | call w64 %57 $"regions.compiler.bitset::iterNext"(%56, %55, %8); |
|
| 734 | + | reserve %58 8 4; |
|
| 735 | + | blit %58 %57 8; |
|
| 736 | + | load w8 %59 %58 0; |
|
| 737 | + | br.ne w32 %59 0 @success26 @else27; |
|
| 738 | + | @success26 |
|
| 739 | + | load w32 %60 %58 4; |
|
| 740 | + | jmp @merge28; |
|
| 741 | + | @else27 |
|
| 742 | + | ret 0; |
|
| 743 | + | @merge28 |
|
| 744 | + | ret %60; |
|
| 745 | + | } |
test/tests/regions.compiler.regmap.rad
added
+45 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// Physical register number. |
|
| 7 | + | record Reg: Copy(u8); |
|
| 8 | + | ||
| 9 | + | /// Register mappings retained in session storage. |
|
| 10 | + | record RegMap: 'scratch { |
|
| 11 | + | /// Virtual register numbers. |
|
| 12 | + | virtRegs: &'scratch mut [u32], |
|
| 13 | + | /// Physical register numbers. |
|
| 14 | + | physRegs: &'scratch mut [Reg], |
|
| 15 | + | /// Number of initialized mappings. |
|
| 16 | + | n: u32, |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Transfer a register map while retaining its session storage. |
|
| 20 | + | fn transfer 'r (map: RegMap 'r) -> RegMap 'r { |
|
| 21 | + | return map; |
|
| 22 | + | } |
|
| 23 | + | ||
| 24 | + | @default unsafe fn main() -> u32 { |
|
| 25 | + | static DATA: [u8; 4096] = [0; 4096]; |
|
| 26 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 27 | + | use arena as registers in { |
|
| 28 | + | let virtual = try! registers.fill(0 as u32, 64); |
|
| 29 | + | let physical = try! registers.fill(Reg(0), 64); |
|
| 30 | + | let map: RegMap 'registers = RegMap { |
|
| 31 | + | virtRegs: virtual, physRegs: physical, n: 0, |
|
| 32 | + | }; |
|
| 33 | + | let mut moved = transfer(map); |
|
| 34 | + | set moved.virtRegs[0] = 40; |
|
| 35 | + | set moved.physRegs[0] = Reg(2); |
|
| 36 | + | set moved.n = 1; |
|
| 37 | + | let current: 'instruction = &mut moved where 'registers: 'instruction in { |
|
| 38 | + | set current.virtRegs[0] += *current.physRegs[0] as u32; |
|
| 39 | + | } |
|
| 40 | + | assert moved.n == 1; |
|
| 41 | + | assert moved.virtRegs[63] == 0; |
|
| 42 | + | assert *moved.physRegs[63] == 0; |
|
| 43 | + | return moved.virtRegs[0]; |
|
| 44 | + | } |
|
| 45 | + | } |
test/tests/regions.compiler.regmap.ril
added
+166 -0
| 1 | + | data mut $"regions.compiler.regmap::regions.compiler.regmap::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 4096; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w64 $"regions.compiler.regmap::transfer"(w64 %0, w64 %1) { |
|
| 6 | + | @entry0 |
|
| 7 | + | blit %0 %1 40; |
|
| 8 | + | ret %0; |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | fn w32 $"regions.compiler.regmap::main"() { |
|
| 12 | + | @entry0 |
|
| 13 | + | copy %0 $"regions.compiler.regmap::regions.compiler.regmap::main$nominal$DATA"; |
|
| 14 | + | reserve %1 16 8; |
|
| 15 | + | store w64 %0 %1 0; |
|
| 16 | + | store w32 4096 %1 8; |
|
| 17 | + | store w32 4096 %1 12; |
|
| 18 | + | reserve %2 24 8; |
|
| 19 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 20 | + | reserve %4 16 8; |
|
| 21 | + | store w64 %3 %4 0; |
|
| 22 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 23 | + | load w64 %5 %4 0; |
|
| 24 | + | load w64 %6 %4 8; |
|
| 25 | + | load w64 %7 %6 8; |
|
| 26 | + | zext w32 %8 0; |
|
| 27 | + | reserve %9 24 8; |
|
| 28 | + | call w64 %10 %7(%9, %5, 4, 4, 64); |
|
| 29 | + | load w64 %11 %10 0; |
|
| 30 | + | reserve %12 16 8; |
|
| 31 | + | br.ne w32 %11 0 @err2 @ok1; |
|
| 32 | + | @ok1 |
|
| 33 | + | load w64 %13 %10 8; |
|
| 34 | + | jmp @fill3(0); |
|
| 35 | + | @err2 |
|
| 36 | + | unreachable; |
|
| 37 | + | @fill3(w32 %14) |
|
| 38 | + | br.ult w32 %14 64 @fill4 @fill5; |
|
| 39 | + | @fill4 |
|
| 40 | + | mul w64 %15 %14 4; |
|
| 41 | + | add w64 %16 %13 %15; |
|
| 42 | + | store w32 %8 %16 0; |
|
| 43 | + | add w32 %17 %14 1; |
|
| 44 | + | jmp @fill3(%17); |
|
| 45 | + | @fill5 |
|
| 46 | + | add w64 %18 %10 8; |
|
| 47 | + | blit %12 %18 16; |
|
| 48 | + | jmp @merge6; |
|
| 49 | + | @merge6 |
|
| 50 | + | load w64 %20 %4 0; |
|
| 51 | + | load w64 %21 %4 8; |
|
| 52 | + | load w64 %22 %21 8; |
|
| 53 | + | reserve %23 1 1; |
|
| 54 | + | store w8 0 %23 0; |
|
| 55 | + | reserve %24 24 8; |
|
| 56 | + | call w64 %25 %22(%24, %20, 1, 1, 64); |
|
| 57 | + | load w64 %26 %25 0; |
|
| 58 | + | reserve %27 16 8; |
|
| 59 | + | br.ne w32 %26 0 @err8 @ok7; |
|
| 60 | + | @ok7 |
|
| 61 | + | load w64 %28 %25 8; |
|
| 62 | + | jmp @fill9(0); |
|
| 63 | + | @err8 |
|
| 64 | + | unreachable; |
|
| 65 | + | @fill9(w32 %29) |
|
| 66 | + | br.ult w32 %29 64 @fill10 @fill11; |
|
| 67 | + | @fill10 |
|
| 68 | + | add w64 %30 %28 %29; |
|
| 69 | + | blit %30 %23 1; |
|
| 70 | + | add w32 %31 %29 1; |
|
| 71 | + | jmp @fill9(%31); |
|
| 72 | + | @fill11 |
|
| 73 | + | add w64 %32 %25 8; |
|
| 74 | + | blit %27 %32 16; |
|
| 75 | + | jmp @merge12; |
|
| 76 | + | @merge12 |
|
| 77 | + | reserve %33 40 8; |
|
| 78 | + | blit %33 %12 16; |
|
| 79 | + | add w64 %35 %33 16; |
|
| 80 | + | blit %35 %27 16; |
|
| 81 | + | store w32 0 %33 32; |
|
| 82 | + | reserve %36 40 8; |
|
| 83 | + | call w64 %37 $"regions.compiler.regmap::transfer"(%36, %33); |
|
| 84 | + | load w32 %38 %37 8; |
|
| 85 | + | br.ult w32 0 %38 @guard#pass13 @guard#trap14; |
|
| 86 | + | @guard#pass13 |
|
| 87 | + | load w64 %39 %37 0; |
|
| 88 | + | store w32 40 %39 0; |
|
| 89 | + | reserve %40 1 1; |
|
| 90 | + | store w8 2 %40 0; |
|
| 91 | + | add w64 %41 %37 16; |
|
| 92 | + | load w32 %42 %41 8; |
|
| 93 | + | br.ult w32 0 %42 @guard#pass15 @guard#trap16; |
|
| 94 | + | @guard#trap14 |
|
| 95 | + | ebreak; |
|
| 96 | + | unreachable; |
|
| 97 | + | @guard#pass15 |
|
| 98 | + | load w64 %43 %41 0; |
|
| 99 | + | blit %43 %40 1; |
|
| 100 | + | store w32 1 %37 32; |
|
| 101 | + | load w32 %44 %37 8; |
|
| 102 | + | br.ult w32 0 %44 @guard#pass17 @guard#trap18; |
|
| 103 | + | @guard#trap16 |
|
| 104 | + | ebreak; |
|
| 105 | + | unreachable; |
|
| 106 | + | @guard#pass17 |
|
| 107 | + | load w64 %45 %37 0; |
|
| 108 | + | load w32 %46 %45 0; |
|
| 109 | + | add w64 %47 %37 16; |
|
| 110 | + | load w32 %48 %47 8; |
|
| 111 | + | br.ult w32 0 %48 @guard#pass19 @guard#trap20; |
|
| 112 | + | @guard#trap18 |
|
| 113 | + | ebreak; |
|
| 114 | + | unreachable; |
|
| 115 | + | @guard#pass19 |
|
| 116 | + | load w64 %49 %47 0; |
|
| 117 | + | load w8 %50 %49 0; |
|
| 118 | + | zext w8 %51 %50; |
|
| 119 | + | add w32 %52 %46 %51; |
|
| 120 | + | store w32 %52 %45 0; |
|
| 121 | + | load w32 %53 %37 32; |
|
| 122 | + | br.eq w32 %53 1 @assert.ok22 @assert.fail21; |
|
| 123 | + | @guard#trap20 |
|
| 124 | + | ebreak; |
|
| 125 | + | unreachable; |
|
| 126 | + | @assert.fail21 |
|
| 127 | + | unreachable; |
|
| 128 | + | @assert.ok22 |
|
| 129 | + | load w32 %54 %37 8; |
|
| 130 | + | br.ult w32 63 %54 @guard#pass25 @guard#trap26; |
|
| 131 | + | @assert.fail23 |
|
| 132 | + | unreachable; |
|
| 133 | + | @assert.ok24 |
|
| 134 | + | add w64 %59 %37 16; |
|
| 135 | + | load w32 %60 %59 8; |
|
| 136 | + | br.ult w32 63 %60 @guard#pass29 @guard#trap30; |
|
| 137 | + | @guard#pass25 |
|
| 138 | + | load w64 %55 %37 0; |
|
| 139 | + | mul w64 %56 63 4; |
|
| 140 | + | add w64 %57 %55 %56; |
|
| 141 | + | load w32 %58 %57 0; |
|
| 142 | + | br.eq w32 %58 0 @assert.ok24 @assert.fail23; |
|
| 143 | + | @guard#trap26 |
|
| 144 | + | ebreak; |
|
| 145 | + | unreachable; |
|
| 146 | + | @assert.fail27 |
|
| 147 | + | unreachable; |
|
| 148 | + | @assert.ok28 |
|
| 149 | + | load w32 %64 %37 8; |
|
| 150 | + | br.ult w32 0 %64 @guard#pass31 @guard#trap32; |
|
| 151 | + | @guard#pass29 |
|
| 152 | + | load w64 %61 %59 0; |
|
| 153 | + | add w64 %62 %61 63; |
|
| 154 | + | load w8 %63 %62 0; |
|
| 155 | + | br.eq w8 %63 0 @assert.ok28 @assert.fail27; |
|
| 156 | + | @guard#trap30 |
|
| 157 | + | ebreak; |
|
| 158 | + | unreachable; |
|
| 159 | + | @guard#pass31 |
|
| 160 | + | load w64 %65 %37 0; |
|
| 161 | + | load w32 %66 %65 0; |
|
| 162 | + | ret %66; |
|
| 163 | + | @guard#trap32 |
|
| 164 | + | ebreak; |
|
| 165 | + | unreachable; |
|
| 166 | + | } |
test/tests/regions.compiler.symbol.rad
added
+36 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// One symbol with shared identity and a mutable register index. |
|
| 7 | + | record Symbol: 'graph + Copy { |
|
| 8 | + | /// Source name in permanent storage. |
|
| 9 | + | name: *[u8], |
|
| 10 | + | /// Register index retained by the graph region. |
|
| 11 | + | index: &'graph cell u32, |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Update a symbol found through a shared table entry. |
|
| 15 | + | fn assign 'graph (symbol: &'graph Symbol 'graph, index: u32) { |
|
| 16 | + | set *symbol.index = index; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | @default fn main() -> u32 { |
|
| 20 | + | static DATA: [u8; 256] = [0; 256]; |
|
| 21 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 22 | + | use arena as graph in { |
|
| 23 | + | let index = try! graph.new(0 as u32); |
|
| 24 | + | let description: Symbol 'graph = Symbol { name: "value", index: index as &'graph cell u32 }; |
|
| 25 | + | let owned = try! graph.new(description); |
|
| 26 | + | let shared: &'graph Symbol 'graph = owned; |
|
| 27 | + | let byName = try! graph.fill(shared, 2); |
|
| 28 | + | let byId = try! graph.fill(shared, 2); |
|
| 29 | + | assert byName[0] == byId[1]; |
|
| 30 | + | assert byName[0].name.len == 5; |
|
| 31 | + | assign(byName[0], 41); |
|
| 32 | + | assert *byId[1].index == 41; |
|
| 33 | + | assign(byId[1], *byName[0].index + 1); |
|
| 34 | + | return *shared.index; |
|
| 35 | + | } |
|
| 36 | + | } |
test/tests/regions.compiler.symbol.ril
added
+212 -0
| 1 | + | data mut $"regions.compiler.symbol::regions.compiler.symbol::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 256; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data $"regions.compiler.symbol::main$literal$0" align 1 { |
|
| 6 | + | str "value"; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w64 $"regions.compiler.symbol::assign"(w64 %0, w32 %1) { |
|
| 10 | + | @entry0 |
|
| 11 | + | load w64 %2 %0 16; |
|
| 12 | + | store w32 %1 %2 0; |
|
| 13 | + | ret; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | fn w32 $"regions.compiler.symbol::main"() { |
|
| 17 | + | @entry0 |
|
| 18 | + | copy %0 $"regions.compiler.symbol::regions.compiler.symbol::main$nominal$DATA"; |
|
| 19 | + | reserve %1 16 8; |
|
| 20 | + | store w64 %0 %1 0; |
|
| 21 | + | store w32 256 %1 8; |
|
| 22 | + | store w32 256 %1 12; |
|
| 23 | + | reserve %2 24 8; |
|
| 24 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 25 | + | reserve %4 16 8; |
|
| 26 | + | store w64 %3 %4 0; |
|
| 27 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 28 | + | load w64 %5 %4 0; |
|
| 29 | + | load w64 %6 %4 8; |
|
| 30 | + | load w64 %7 %6 0; |
|
| 31 | + | zext w32 %8 0; |
|
| 32 | + | reserve %9 16 8; |
|
| 33 | + | call w64 %10 %7(%9, %5, 4, 4); |
|
| 34 | + | load w64 %11 %10 0; |
|
| 35 | + | reserve %12 8 8; |
|
| 36 | + | br.ne w32 %11 0 @err2 @ok1; |
|
| 37 | + | @ok1 |
|
| 38 | + | load w64 %13 %10 8; |
|
| 39 | + | store w32 %8 %13 0; |
|
| 40 | + | load w64 %14 %10 8; |
|
| 41 | + | store w64 %14 %12 0; |
|
| 42 | + | jmp @merge3; |
|
| 43 | + | @err2 |
|
| 44 | + | unreachable; |
|
| 45 | + | @merge3 |
|
| 46 | + | load w64 %15 %12 0; |
|
| 47 | + | reserve %16 24 8; |
|
| 48 | + | copy %17 $"regions.compiler.symbol::main$literal$0"; |
|
| 49 | + | reserve %18 16 8; |
|
| 50 | + | store w64 %17 %18 0; |
|
| 51 | + | store w32 5 %18 8; |
|
| 52 | + | store w32 5 %18 12; |
|
| 53 | + | blit %16 %18 16; |
|
| 54 | + | store w64 %15 %16 16; |
|
| 55 | + | load w64 %19 %4 0; |
|
| 56 | + | load w64 %20 %4 8; |
|
| 57 | + | load w64 %21 %20 0; |
|
| 58 | + | reserve %22 24 8; |
|
| 59 | + | blit %22 %16 24; |
|
| 60 | + | reserve %23 16 8; |
|
| 61 | + | call w64 %24 %21(%23, %19, 24, 8); |
|
| 62 | + | load w64 %25 %24 0; |
|
| 63 | + | reserve %26 8 8; |
|
| 64 | + | br.ne w32 %25 0 @err5 @ok4; |
|
| 65 | + | @ok4 |
|
| 66 | + | load w64 %27 %24 8; |
|
| 67 | + | blit %27 %22 24; |
|
| 68 | + | load w64 %28 %24 8; |
|
| 69 | + | store w64 %28 %26 0; |
|
| 70 | + | jmp @merge6; |
|
| 71 | + | @err5 |
|
| 72 | + | unreachable; |
|
| 73 | + | @merge6 |
|
| 74 | + | load w64 %29 %26 0; |
|
| 75 | + | load w64 %30 %4 0; |
|
| 76 | + | load w64 %31 %4 8; |
|
| 77 | + | load w64 %32 %31 8; |
|
| 78 | + | reserve %33 24 8; |
|
| 79 | + | call w64 %34 %32(%33, %30, 8, 8, 2); |
|
| 80 | + | load w64 %35 %34 0; |
|
| 81 | + | reserve %36 16 8; |
|
| 82 | + | br.ne w32 %35 0 @err8 @ok7; |
|
| 83 | + | @ok7 |
|
| 84 | + | load w64 %37 %34 8; |
|
| 85 | + | jmp @fill9(0); |
|
| 86 | + | @err8 |
|
| 87 | + | unreachable; |
|
| 88 | + | @fill9(w32 %38) |
|
| 89 | + | br.ult w32 %38 2 @fill10 @fill11; |
|
| 90 | + | @fill10 |
|
| 91 | + | mul w64 %39 %38 8; |
|
| 92 | + | add w64 %40 %37 %39; |
|
| 93 | + | store w64 %29 %40 0; |
|
| 94 | + | add w32 %41 %38 1; |
|
| 95 | + | jmp @fill9(%41); |
|
| 96 | + | @fill11 |
|
| 97 | + | add w64 %42 %34 8; |
|
| 98 | + | blit %36 %42 16; |
|
| 99 | + | jmp @merge12; |
|
| 100 | + | @merge12 |
|
| 101 | + | load w64 %44 %4 0; |
|
| 102 | + | load w64 %45 %4 8; |
|
| 103 | + | load w64 %46 %45 8; |
|
| 104 | + | reserve %48 24 8; |
|
| 105 | + | call w64 %49 %46(%48, %44, 8, 8, 2); |
|
| 106 | + | load w64 %50 %49 0; |
|
| 107 | + | reserve %51 16 8; |
|
| 108 | + | br.ne w32 %50 0 @err14 @ok13; |
|
| 109 | + | @ok13 |
|
| 110 | + | load w64 %52 %49 8; |
|
| 111 | + | jmp @fill15(0); |
|
| 112 | + | @err14 |
|
| 113 | + | unreachable; |
|
| 114 | + | @fill15(w32 %53) |
|
| 115 | + | br.ult w32 %53 2 @fill16 @fill17; |
|
| 116 | + | @fill16 |
|
| 117 | + | mul w64 %54 %53 8; |
|
| 118 | + | add w64 %55 %52 %54; |
|
| 119 | + | store w64 %29 %55 0; |
|
| 120 | + | add w32 %56 %53 1; |
|
| 121 | + | jmp @fill15(%56); |
|
| 122 | + | @fill17 |
|
| 123 | + | add w64 %57 %49 8; |
|
| 124 | + | blit %51 %57 16; |
|
| 125 | + | jmp @merge18; |
|
| 126 | + | @merge18 |
|
| 127 | + | load w32 %59 %36 8; |
|
| 128 | + | br.ult w32 0 %59 @guard#pass21 @guard#trap22; |
|
| 129 | + | @assert.fail19 |
|
| 130 | + | unreachable; |
|
| 131 | + | @assert.ok20 |
|
| 132 | + | load w32 %67 %36 8; |
|
| 133 | + | br.ult w32 0 %67 @guard#pass27 @guard#trap28; |
|
| 134 | + | @guard#pass21 |
|
| 135 | + | load w64 %60 %36 0; |
|
| 136 | + | load w64 %61 %60 0; |
|
| 137 | + | load w32 %62 %51 8; |
|
| 138 | + | br.ult w32 1 %62 @guard#pass23 @guard#trap24; |
|
| 139 | + | @guard#trap22 |
|
| 140 | + | ebreak; |
|
| 141 | + | unreachable; |
|
| 142 | + | @guard#pass23 |
|
| 143 | + | load w64 %63 %51 0; |
|
| 144 | + | mul w64 %64 1 8; |
|
| 145 | + | add w64 %65 %63 %64; |
|
| 146 | + | load w64 %66 %65 0; |
|
| 147 | + | br.eq w64 %61 %66 @assert.ok20 @assert.fail19; |
|
| 148 | + | @guard#trap24 |
|
| 149 | + | ebreak; |
|
| 150 | + | unreachable; |
|
| 151 | + | @assert.fail25 |
|
| 152 | + | unreachable; |
|
| 153 | + | @assert.ok26 |
|
| 154 | + | load w32 %71 %36 8; |
|
| 155 | + | br.ult w32 0 %71 @guard#pass29 @guard#trap30; |
|
| 156 | + | @guard#pass27 |
|
| 157 | + | load w64 %68 %36 0; |
|
| 158 | + | load w64 %69 %68 0; |
|
| 159 | + | load w32 %70 %69 8; |
|
| 160 | + | br.eq w32 %70 5 @assert.ok26 @assert.fail25; |
|
| 161 | + | @guard#trap28 |
|
| 162 | + | ebreak; |
|
| 163 | + | unreachable; |
|
| 164 | + | @guard#pass29 |
|
| 165 | + | load w64 %72 %36 0; |
|
| 166 | + | load w64 %73 %72 0; |
|
| 167 | + | call w64 $"regions.compiler.symbol::assign"(%73, 41); |
|
| 168 | + | load w32 %74 %51 8; |
|
| 169 | + | br.ult w32 1 %74 @guard#pass33 @guard#trap34; |
|
| 170 | + | @guard#trap30 |
|
| 171 | + | ebreak; |
|
| 172 | + | unreachable; |
|
| 173 | + | @assert.fail31 |
|
| 174 | + | unreachable; |
|
| 175 | + | @assert.ok32 |
|
| 176 | + | load w32 %81 %51 8; |
|
| 177 | + | br.ult w32 1 %81 @guard#pass35 @guard#trap36; |
|
| 178 | + | @guard#pass33 |
|
| 179 | + | load w64 %75 %51 0; |
|
| 180 | + | mul w64 %76 1 8; |
|
| 181 | + | add w64 %77 %75 %76; |
|
| 182 | + | load w64 %78 %77 0; |
|
| 183 | + | load w64 %79 %78 16; |
|
| 184 | + | load w32 %80 %79 0; |
|
| 185 | + | br.eq w32 %80 41 @assert.ok32 @assert.fail31; |
|
| 186 | + | @guard#trap34 |
|
| 187 | + | ebreak; |
|
| 188 | + | unreachable; |
|
| 189 | + | @guard#pass35 |
|
| 190 | + | load w64 %82 %51 0; |
|
| 191 | + | mul w64 %83 1 8; |
|
| 192 | + | add w64 %84 %82 %83; |
|
| 193 | + | load w64 %85 %84 0; |
|
| 194 | + | load w32 %86 %36 8; |
|
| 195 | + | br.ult w32 0 %86 @guard#pass37 @guard#trap38; |
|
| 196 | + | @guard#trap36 |
|
| 197 | + | ebreak; |
|
| 198 | + | unreachable; |
|
| 199 | + | @guard#pass37 |
|
| 200 | + | load w64 %87 %36 0; |
|
| 201 | + | load w64 %88 %87 0; |
|
| 202 | + | load w64 %89 %88 16; |
|
| 203 | + | load w32 %90 %89 0; |
|
| 204 | + | add w32 %91 %90 1; |
|
| 205 | + | call w64 $"regions.compiler.symbol::assign"(%85, %91); |
|
| 206 | + | load w64 %93 %29 16; |
|
| 207 | + | load w32 %94 %93 0; |
|
| 208 | + | ret %94; |
|
| 209 | + | @guard#trap38 |
|
| 210 | + | ebreak; |
|
| 211 | + | unreachable; |
|
| 212 | + | } |
test/tests/regions.compiler.writer.rad
added
+46 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// Instruction buffer with one exclusive writer. |
|
| 7 | + | record Writer: 'output { |
|
| 8 | + | /// Instruction storage retained by the output region. |
|
| 9 | + | code: &'output mut [u32], |
|
| 10 | + | /// Number of initialized output words. |
|
| 11 | + | len: u32, |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Append one instruction within the fixed output capacity. |
|
| 15 | + | fn emit 'output (writer: &mut Writer 'output, instruction: u32) { |
|
| 16 | + | assert writer.len < writer.code.len, "emit: code buffer full"; |
|
| 17 | + | set writer.code[writer.len] = instruction; |
|
| 18 | + | set writer.len += 1; |
|
| 19 | + | } |
|
| 20 | + | ||
| 21 | + | /// Patch an instruction already present in the output. |
|
| 22 | + | fn patch 'output (writer: &mut Writer 'output, offset: u32, instruction: u32) { |
|
| 23 | + | assert offset < writer.len; |
|
| 24 | + | set writer.code[offset] = instruction; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | /// Publish initialized output and consume the writer's exclusive access. |
|
| 28 | + | fn finish 'output (writer: Writer 'output) -> &'output [u32] { |
|
| 29 | + | return &writer.code[..writer.len]; |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | @default fn main() -> u32 { |
|
| 33 | + | static DATA: [u8; 128] = [0; 128]; |
|
| 34 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 35 | + | use arena as output in { |
|
| 36 | + | let code = try! output.fill(0 as u32, 16); |
|
| 37 | + | let mut writer: Writer 'output = Writer { code, len: 0 }; |
|
| 38 | + | emit(&mut writer, 11); |
|
| 39 | + | emit(&mut writer, 20); |
|
| 40 | + | emit(&mut writer, 12); |
|
| 41 | + | patch(&mut writer, 1, 19); |
|
| 42 | + | let finished = finish(writer); |
|
| 43 | + | assert finished.len == 3; |
|
| 44 | + | return finished[0] + finished[1] + finished[2]; |
|
| 45 | + | } |
|
| 46 | + | } |
test/tests/regions.compiler.writer.ril
added
+152 -0
| 1 | + | data mut $"regions.compiler.writer::regions.compiler.writer::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 128; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w64 $"regions.compiler.writer::emit"(w64 %0, w32 %1) { |
|
| 6 | + | @entry0 |
|
| 7 | + | load w32 %2 %0 16; |
|
| 8 | + | load w32 %3 %0 8; |
|
| 9 | + | br.ult w32 %2 %3 @assert.ok2 @assert.fail1; |
|
| 10 | + | @assert.fail1 |
|
| 11 | + | unreachable; |
|
| 12 | + | @assert.ok2 |
|
| 13 | + | load w32 %4 %0 16; |
|
| 14 | + | load w32 %5 %0 8; |
|
| 15 | + | br.ult w32 %4 %5 @guard#pass3 @guard#trap4; |
|
| 16 | + | @guard#pass3 |
|
| 17 | + | load w64 %6 %0 0; |
|
| 18 | + | mul w64 %7 %4 4; |
|
| 19 | + | add w64 %8 %6 %7; |
|
| 20 | + | store w32 %1 %8 0; |
|
| 21 | + | load w32 %9 %0 16; |
|
| 22 | + | add w32 %10 %9 1; |
|
| 23 | + | store w32 %10 %0 16; |
|
| 24 | + | ret; |
|
| 25 | + | @guard#trap4 |
|
| 26 | + | ebreak; |
|
| 27 | + | unreachable; |
|
| 28 | + | } |
|
| 29 | + | ||
| 30 | + | fn w64 $"regions.compiler.writer::patch"(w64 %0, w32 %1, w32 %2) { |
|
| 31 | + | @entry0 |
|
| 32 | + | load w32 %3 %0 16; |
|
| 33 | + | br.ult w32 %1 %3 @assert.ok2 @assert.fail1; |
|
| 34 | + | @assert.fail1 |
|
| 35 | + | unreachable; |
|
| 36 | + | @assert.ok2 |
|
| 37 | + | load w32 %4 %0 8; |
|
| 38 | + | br.ult w32 %1 %4 @guard#pass3 @guard#trap4; |
|
| 39 | + | @guard#pass3 |
|
| 40 | + | load w64 %5 %0 0; |
|
| 41 | + | mul w64 %6 %1 4; |
|
| 42 | + | add w64 %7 %5 %6; |
|
| 43 | + | store w32 %2 %7 0; |
|
| 44 | + | ret; |
|
| 45 | + | @guard#trap4 |
|
| 46 | + | ebreak; |
|
| 47 | + | unreachable; |
|
| 48 | + | } |
|
| 49 | + | ||
| 50 | + | fn w64 $"regions.compiler.writer::finish"(w64 %0, w64 %1) { |
|
| 51 | + | @entry0 |
|
| 52 | + | load w64 %2 %1 0; |
|
| 53 | + | load w32 %3 %1 8; |
|
| 54 | + | load w32 %4 %1 16; |
|
| 55 | + | br.ult w32 %3 %4 @guard#trap1 @guard#pass2; |
|
| 56 | + | @guard#trap1 |
|
| 57 | + | ebreak; |
|
| 58 | + | unreachable; |
|
| 59 | + | @guard#pass2 |
|
| 60 | + | reserve %5 16 8; |
|
| 61 | + | store w64 %2 %5 0; |
|
| 62 | + | store w32 %4 %5 8; |
|
| 63 | + | store w32 %4 %5 12; |
|
| 64 | + | blit %0 %5 16; |
|
| 65 | + | ret %0; |
|
| 66 | + | } |
|
| 67 | + | ||
| 68 | + | fn w32 $"regions.compiler.writer::main"() { |
|
| 69 | + | @entry0 |
|
| 70 | + | copy %0 $"regions.compiler.writer::regions.compiler.writer::main$nominal$DATA"; |
|
| 71 | + | reserve %1 16 8; |
|
| 72 | + | store w64 %0 %1 0; |
|
| 73 | + | store w32 128 %1 8; |
|
| 74 | + | store w32 128 %1 12; |
|
| 75 | + | reserve %2 24 8; |
|
| 76 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 77 | + | reserve %4 16 8; |
|
| 78 | + | store w64 %3 %4 0; |
|
| 79 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 80 | + | load w64 %5 %4 0; |
|
| 81 | + | load w64 %6 %4 8; |
|
| 82 | + | load w64 %7 %6 8; |
|
| 83 | + | zext w32 %8 0; |
|
| 84 | + | reserve %9 24 8; |
|
| 85 | + | call w64 %10 %7(%9, %5, 4, 4, 16); |
|
| 86 | + | load w64 %11 %10 0; |
|
| 87 | + | reserve %12 16 8; |
|
| 88 | + | br.ne w32 %11 0 @err2 @ok1; |
|
| 89 | + | @ok1 |
|
| 90 | + | load w64 %13 %10 8; |
|
| 91 | + | jmp @fill3(0); |
|
| 92 | + | @err2 |
|
| 93 | + | unreachable; |
|
| 94 | + | @fill3(w32 %14) |
|
| 95 | + | br.ult w32 %14 16 @fill4 @fill5; |
|
| 96 | + | @fill4 |
|
| 97 | + | mul w64 %15 %14 4; |
|
| 98 | + | add w64 %16 %13 %15; |
|
| 99 | + | store w32 %8 %16 0; |
|
| 100 | + | add w32 %17 %14 1; |
|
| 101 | + | jmp @fill3(%17); |
|
| 102 | + | @fill5 |
|
| 103 | + | add w64 %18 %10 8; |
|
| 104 | + | blit %12 %18 16; |
|
| 105 | + | jmp @merge6; |
|
| 106 | + | @merge6 |
|
| 107 | + | reserve %19 24 8; |
|
| 108 | + | blit %19 %12 16; |
|
| 109 | + | store w32 0 %19 16; |
|
| 110 | + | call w64 $"regions.compiler.writer::emit"(%19, 11); |
|
| 111 | + | call w64 $"regions.compiler.writer::emit"(%19, 20); |
|
| 112 | + | call w64 $"regions.compiler.writer::emit"(%19, 12); |
|
| 113 | + | call w64 $"regions.compiler.writer::patch"(%19, 1, 19); |
|
| 114 | + | reserve %20 16 8; |
|
| 115 | + | call w64 %21 $"regions.compiler.writer::finish"(%20, %19); |
|
| 116 | + | load w32 %22 %21 8; |
|
| 117 | + | br.eq w32 %22 3 @assert.ok8 @assert.fail7; |
|
| 118 | + | @assert.fail7 |
|
| 119 | + | unreachable; |
|
| 120 | + | @assert.ok8 |
|
| 121 | + | load w32 %23 %21 8; |
|
| 122 | + | br.ult w32 0 %23 @guard#pass9 @guard#trap10; |
|
| 123 | + | @guard#pass9 |
|
| 124 | + | load w64 %24 %21 0; |
|
| 125 | + | load w32 %25 %24 0; |
|
| 126 | + | load w32 %26 %21 8; |
|
| 127 | + | br.ult w32 1 %26 @guard#pass11 @guard#trap12; |
|
| 128 | + | @guard#trap10 |
|
| 129 | + | ebreak; |
|
| 130 | + | unreachable; |
|
| 131 | + | @guard#pass11 |
|
| 132 | + | load w64 %27 %21 0; |
|
| 133 | + | mul w64 %28 1 4; |
|
| 134 | + | add w64 %29 %27 %28; |
|
| 135 | + | load w32 %30 %29 0; |
|
| 136 | + | add w32 %31 %25 %30; |
|
| 137 | + | load w32 %32 %21 8; |
|
| 138 | + | br.ult w32 2 %32 @guard#pass13 @guard#trap14; |
|
| 139 | + | @guard#trap12 |
|
| 140 | + | ebreak; |
|
| 141 | + | unreachable; |
|
| 142 | + | @guard#pass13 |
|
| 143 | + | load w64 %33 %21 0; |
|
| 144 | + | mul w64 %34 2 4; |
|
| 145 | + | add w64 %35 %33 %34; |
|
| 146 | + | load w32 %36 %35 0; |
|
| 147 | + | add w32 %37 %31 %36; |
|
| 148 | + | ret %37; |
|
| 149 | + | @guard#trap14 |
|
| 150 | + | ebreak; |
|
| 151 | + | unreachable; |
|
| 152 | + | } |
test/tests/regions.constant.optional.rad
added
+16 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Value with a regional name alternative. |
|
| 4 | + | union Value: 'r + Copy { Imm(i64), Name(&'r [u8]) } |
|
| 5 | + | /// Instruction with an optional regional payload. |
|
| 6 | + | union Instruction: 'r + Copy { Ret { value: ?Value 'r } } |
|
| 7 | + | @default fn main() -> u32 { |
|
| 8 | + | let name = "test"; |
|
| 9 | + | let input: 'r = &name[..] in { |
|
| 10 | + | let instructions = &[Instruction 'r::Ret { value: Value 'r::Imm(42) }]; |
|
| 11 | + | let case Instruction 'r::Ret { value } = instructions[0] else panic; |
|
| 12 | + | let present = value else panic; |
|
| 13 | + | let case Value 'r::Imm(number) = present else panic; |
|
| 14 | + | return number as u32; |
|
| 15 | + | } |
|
| 16 | + | } |
test/tests/regions.constant.optional.ril
added
+73 -0
| 1 | + | data $main$literal$0 align 1 { |
|
| 2 | + | str "test"; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data $main$literal$1 align 8 { |
|
| 6 | + | w8 0; |
|
| 7 | + | undef * 7; |
|
| 8 | + | w8 1; |
|
| 9 | + | undef * 7; |
|
| 10 | + | w8 0; |
|
| 11 | + | undef * 7; |
|
| 12 | + | w64 42; |
|
| 13 | + | undef * 8; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | fn w32 $main() { |
|
| 17 | + | @entry0 |
|
| 18 | + | copy %0 $main$literal$0; |
|
| 19 | + | reserve %1 16 8; |
|
| 20 | + | store w64 %0 %1 0; |
|
| 21 | + | store w32 4 %1 8; |
|
| 22 | + | store w32 4 %1 12; |
|
| 23 | + | load w64 %2 %1 0; |
|
| 24 | + | load w32 %3 %1 8; |
|
| 25 | + | reserve %4 16 8; |
|
| 26 | + | store w64 %2 %4 0; |
|
| 27 | + | store w32 %3 %4 8; |
|
| 28 | + | store w32 %3 %4 12; |
|
| 29 | + | copy %5 $main$literal$1; |
|
| 30 | + | reserve %6 16 8; |
|
| 31 | + | store w64 %5 %6 0; |
|
| 32 | + | store w32 1 %6 8; |
|
| 33 | + | store w32 1 %6 12; |
|
| 34 | + | load w32 %7 %6 8; |
|
| 35 | + | br.ult w32 0 %7 @guard#pass1 @guard#trap2; |
|
| 36 | + | @guard#pass1 |
|
| 37 | + | load w64 %8 %6 0; |
|
| 38 | + | reserve %9 40 8; |
|
| 39 | + | blit %9 %8 40; |
|
| 40 | + | load w8 %10 %9 0; |
|
| 41 | + | br.eq w8 %10 0 @success3 @else4; |
|
| 42 | + | @guard#trap2 |
|
| 43 | + | ebreak; |
|
| 44 | + | unreachable; |
|
| 45 | + | @success3 |
|
| 46 | + | add w64 %11 %9 8; |
|
| 47 | + | jmp @merge5; |
|
| 48 | + | @else4 |
|
| 49 | + | unreachable; |
|
| 50 | + | @merge5 |
|
| 51 | + | reserve %12 32 8; |
|
| 52 | + | blit %12 %11 32; |
|
| 53 | + | load w8 %13 %12 0; |
|
| 54 | + | br.ne w32 %13 0 @success6 @else7; |
|
| 55 | + | @success6 |
|
| 56 | + | add w64 %14 %12 8; |
|
| 57 | + | jmp @merge8; |
|
| 58 | + | @else7 |
|
| 59 | + | unreachable; |
|
| 60 | + | @merge8 |
|
| 61 | + | reserve %15 24 8; |
|
| 62 | + | blit %15 %14 24; |
|
| 63 | + | load w8 %16 %15 0; |
|
| 64 | + | br.eq w8 %16 0 @success9 @else10; |
|
| 65 | + | @success9 |
|
| 66 | + | sload w64 %17 %15 8; |
|
| 67 | + | jmp @merge11; |
|
| 68 | + | @else10 |
|
| 69 | + | unreachable; |
|
| 70 | + | @merge11 |
|
| 71 | + | zext w32 %18 %17; |
|
| 72 | + | ret %18; |
|
| 73 | + | } |
test/tests/regions.copy.binding.rad
added
+64 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// A shared reference that can be replaced without moving its target. |
|
| 4 | + | record Holder: 'r { |
|
| 5 | + | /// Current target within the declared region. |
|
| 6 | + | current: &'r u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Replace a stored reference and read the previous target. |
|
| 10 | + | fn replace 'r (self: &mut Holder 'r, next: &'r u32) -> u32 { |
|
| 11 | + | let previous = self.current; |
|
| 12 | + | set self.current = next; |
|
| 13 | + | return *previous; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | /// Rebind a copied reference within its declared region. |
|
| 17 | + | fn follow 'r (first: &'r u32, second: &'r u32) -> u32 { |
|
| 18 | + | let mut cursor = first; |
|
| 19 | + | set cursor = second; |
|
| 20 | + | return *cursor; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | /// Rebind a shared slice and read its new target. |
|
| 24 | + | fn followSlice 'r (first: &'r [u32], second: &'r [u32]) -> u32 { |
|
| 25 | + | let mut cursor = first; |
|
| 26 | + | assert cursor[0] == 20; |
|
| 27 | + | set cursor = second; |
|
| 28 | + | return cursor[0]; |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | /// Write through two successive cell references. |
|
| 32 | + | fn followCell 'r (first: &'r cell u32, second: &'r cell u32) { |
|
| 33 | + | let mut cursor = first; |
|
| 34 | + | set *cursor = 20; |
|
| 35 | + | set cursor = second; |
|
| 36 | + | set *cursor = 22; |
|
| 37 | + | } |
|
| 38 | + | ||
| 39 | + | @default fn main() -> u32 { |
|
| 40 | + | let first: u32 = 20; |
|
| 41 | + | let second: u32 = 22; |
|
| 42 | + | let mut result: u32 = 0; |
|
| 43 | + | let a: 'values = &first, b = &second in { |
|
| 44 | + | let mut holder = Holder 'values { current: a }; |
|
| 45 | + | set result = replace(&mut holder, b) + follow(a, holder.current); |
|
| 46 | + | } |
|
| 47 | + | let xs: [u32; 1] = [20]; |
|
| 48 | + | let ys: [u32; 1] = [22]; |
|
| 49 | + | let a: 'slices = &xs[..], b = &ys[..] in { |
|
| 50 | + | assert followSlice(a, b) == 22; |
|
| 51 | + | } |
|
| 52 | + | let mut x: u32 = 0; |
|
| 53 | + | let mut y: u32 = 0; |
|
| 54 | + | let a: 'cells = &mut x, b = &mut y in { |
|
| 55 | + | let firstCell = a as &'cells cell u32; |
|
| 56 | + | let secondCell = b as &'cells cell u32; |
|
| 57 | + | followCell(firstCell, secondCell); |
|
| 58 | + | assert *firstCell == 20; |
|
| 59 | + | assert *secondCell == 22; |
|
| 60 | + | } |
|
| 61 | + | assert x == 20; |
|
| 62 | + | assert y == 22; |
|
| 63 | + | return result; |
|
| 64 | + | } |
test/tests/regions.copy.binding.ril
added
+107 -0
| 1 | + | fn w32 $replace(w64 %0, w64 %1) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w64 %2 %0 0; |
|
| 4 | + | store w64 %1 %0 0; |
|
| 5 | + | load w32 %3 %2 0; |
|
| 6 | + | ret %3; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w32 $follow(w64 %0, w64 %1) { |
|
| 10 | + | @entry0 |
|
| 11 | + | load w32 %2 %1 0; |
|
| 12 | + | ret %2; |
|
| 13 | + | } |
|
| 14 | + | ||
| 15 | + | fn w32 $followSlice(w64 %0, w64 %1) { |
|
| 16 | + | @entry0 |
|
| 17 | + | reserve %2 16 8; |
|
| 18 | + | blit %2 %0 16; |
|
| 19 | + | load w32 %3 %2 8; |
|
| 20 | + | br.ult w32 0 %3 @guard#pass3 @guard#trap4; |
|
| 21 | + | @assert.fail1 |
|
| 22 | + | unreachable; |
|
| 23 | + | @assert.ok2 |
|
| 24 | + | blit %2 %1 16; |
|
| 25 | + | load w32 %6 %2 8; |
|
| 26 | + | br.ult w32 0 %6 @guard#pass5 @guard#trap6; |
|
| 27 | + | @guard#pass3 |
|
| 28 | + | load w64 %4 %2 0; |
|
| 29 | + | load w32 %5 %4 0; |
|
| 30 | + | br.eq w32 %5 20 @assert.ok2 @assert.fail1; |
|
| 31 | + | @guard#trap4 |
|
| 32 | + | ebreak; |
|
| 33 | + | unreachable; |
|
| 34 | + | @guard#pass5 |
|
| 35 | + | load w64 %7 %2 0; |
|
| 36 | + | load w32 %8 %7 0; |
|
| 37 | + | ret %8; |
|
| 38 | + | @guard#trap6 |
|
| 39 | + | ebreak; |
|
| 40 | + | unreachable; |
|
| 41 | + | } |
|
| 42 | + | ||
| 43 | + | fn w64 $followCell(w64 %0, w64 %1) { |
|
| 44 | + | @entry0 |
|
| 45 | + | store w32 20 %0 0; |
|
| 46 | + | store w32 22 %1 0; |
|
| 47 | + | ret; |
|
| 48 | + | } |
|
| 49 | + | ||
| 50 | + | fn w32 $main() { |
|
| 51 | + | @entry0 |
|
| 52 | + | reserve %0 4 4; |
|
| 53 | + | store w32 20 %0 0; |
|
| 54 | + | reserve %1 4 4; |
|
| 55 | + | store w32 22 %1 0; |
|
| 56 | + | reserve %2 8 8; |
|
| 57 | + | store w64 %0 %2 0; |
|
| 58 | + | call w32 %3 $replace(%2, %1); |
|
| 59 | + | load w64 %4 %2 0; |
|
| 60 | + | call w32 %5 $follow(%0, %4); |
|
| 61 | + | add w32 %6 %3 %5; |
|
| 62 | + | reserve %7 4 4; |
|
| 63 | + | store w32 20 %7 0; |
|
| 64 | + | reserve %8 4 4; |
|
| 65 | + | store w32 22 %8 0; |
|
| 66 | + | reserve %9 16 8; |
|
| 67 | + | store w64 %7 %9 0; |
|
| 68 | + | store w32 1 %9 8; |
|
| 69 | + | store w32 1 %9 12; |
|
| 70 | + | reserve %10 16 8; |
|
| 71 | + | store w64 %8 %10 0; |
|
| 72 | + | store w32 1 %10 8; |
|
| 73 | + | store w32 1 %10 12; |
|
| 74 | + | reserve %11 16 8; |
|
| 75 | + | blit %11 %9 16; |
|
| 76 | + | call w32 %12 $followSlice(%11, %10); |
|
| 77 | + | br.eq w32 %12 22 @assert.ok2 @assert.fail1; |
|
| 78 | + | @assert.fail1 |
|
| 79 | + | unreachable; |
|
| 80 | + | @assert.ok2 |
|
| 81 | + | reserve %13 4 4; |
|
| 82 | + | store w32 0 %13 0; |
|
| 83 | + | reserve %14 4 4; |
|
| 84 | + | store w32 0 %14 0; |
|
| 85 | + | call w64 $followCell(%13, %14); |
|
| 86 | + | load w32 %15 %13 0; |
|
| 87 | + | br.eq w32 %15 20 @assert.ok4 @assert.fail3; |
|
| 88 | + | @assert.fail3 |
|
| 89 | + | unreachable; |
|
| 90 | + | @assert.ok4 |
|
| 91 | + | load w32 %16 %14 0; |
|
| 92 | + | br.eq w32 %16 22 @assert.ok6 @assert.fail5; |
|
| 93 | + | @assert.fail5 |
|
| 94 | + | unreachable; |
|
| 95 | + | @assert.ok6 |
|
| 96 | + | load w32 %17 %13 0; |
|
| 97 | + | br.eq w32 %17 20 @assert.ok8 @assert.fail7; |
|
| 98 | + | @assert.fail7 |
|
| 99 | + | unreachable; |
|
| 100 | + | @assert.ok8 |
|
| 101 | + | load w32 %18 %14 0; |
|
| 102 | + | br.eq w32 %18 22 @assert.ok10 @assert.fail9; |
|
| 103 | + | @assert.fail9 |
|
| 104 | + | unreachable; |
|
| 105 | + | @assert.ok10 |
|
| 106 | + | ret %6; |
|
| 107 | + | } |
test/tests/regions.loans.control.rad
added
+76 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record Pair { left: u32, right: u32 } |
|
| 4 | + | ||
| 5 | + | fn split 'r (p: &'r mut Pair) -> u32 { |
|
| 6 | + | let a = &mut p.left; |
|
| 7 | + | let b = &mut p.right; |
|
| 8 | + | set *a += 1; |
|
| 9 | + | set *b += 1; |
|
| 10 | + | return *a + *b; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn branch 'r (p: &'r mut Pair, condition: bool) -> u32 { |
|
| 14 | + | if condition { |
|
| 15 | + | let q = &mut p.left; |
|
| 16 | + | set *q = 7; |
|
| 17 | + | } else { |
|
| 18 | + | set p.left = 8; |
|
| 19 | + | } |
|
| 20 | + | return p.right; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | fn returnedBranch 'r (p: &'r mut u32, condition: bool) -> u32 { |
|
| 24 | + | if condition { |
|
| 25 | + | let q = &mut *p; |
|
| 26 | + | return *q; |
|
| 27 | + | } |
|
| 28 | + | return *p; |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | fn readLoop 'r (p: &'r u32) -> u32 { |
|
| 32 | + | let mut sum: u32 = 0; |
|
| 33 | + | for i in 0..3 { |
|
| 34 | + | let q = &*p; |
|
| 35 | + | set sum += *q; |
|
| 36 | + | } |
|
| 37 | + | let mut count: u32 = 0; |
|
| 38 | + | while count < 2 { |
|
| 39 | + | let q = &*p; |
|
| 40 | + | assert *q > 0; |
|
| 41 | + | set count += 1; |
|
| 42 | + | } |
|
| 43 | + | let mut next: ?u32 = 1; |
|
| 44 | + | while let n = next { |
|
| 45 | + | let q = &*p; |
|
| 46 | + | assert *q > 0; |
|
| 47 | + | set next = nil; |
|
| 48 | + | } |
|
| 49 | + | return sum; |
|
| 50 | + | } |
|
| 51 | + | ||
| 52 | + | fn breakChild 'r (p: &'r mut u32) { |
|
| 53 | + | loop { |
|
| 54 | + | let q: 'iteration = &mut *p where 'r: 'iteration in { |
|
| 55 | + | let value = &mut *q; |
|
| 56 | + | set *value += 1; |
|
| 57 | + | break; |
|
| 58 | + | } |
|
| 59 | + | } |
|
| 60 | + | set *p += 1; |
|
| 61 | + | } |
|
| 62 | + | ||
| 63 | + | @default fn main() -> u32 { |
|
| 64 | + | let mut pair = Pair { left: 20, right: 20 }; |
|
| 65 | + | let p: 'split = &mut pair in { assert split(p) == 42; } |
|
| 66 | + | let mut other = Pair { left: 0, right: 9 }; |
|
| 67 | + | let p: 'first = &mut other in { assert branch(p, true) == 9; } |
|
| 68 | + | let p: 'second = &mut other in { assert branch(p, false) == 9; } |
|
| 69 | + | let p: 'shared = &pair.left in { assert readLoop(p) == 63; } |
|
| 70 | + | let mut value: u32 = 0; |
|
| 71 | + | let p: 'break = &mut value in { breakChild(p); } |
|
| 72 | + | assert value == 2; |
|
| 73 | + | let p: 'returned = &mut value in { assert returnedBranch(p, true) == 2; } |
|
| 74 | + | let p: 'continued = &mut value in { assert returnedBranch(p, false) == 2; } |
|
| 75 | + | return pair.left + pair.right; |
|
| 76 | + | } |
test/tests/regions.loans.control.ril
added
+153 -0
| 1 | + | fn w32 $split(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | add w64 %1 %0 4; |
|
| 4 | + | load w32 %2 %0 0; |
|
| 5 | + | add w32 %3 %2 1; |
|
| 6 | + | store w32 %3 %0 0; |
|
| 7 | + | load w32 %4 %1 0; |
|
| 8 | + | add w32 %5 %4 1; |
|
| 9 | + | store w32 %5 %1 0; |
|
| 10 | + | load w32 %6 %0 0; |
|
| 11 | + | load w32 %7 %1 0; |
|
| 12 | + | add w32 %8 %6 %7; |
|
| 13 | + | ret %8; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | fn w32 $branch(w64 %0, w8 %1) { |
|
| 17 | + | @entry0 |
|
| 18 | + | br.ne w32 %1 0 @then1 @else2; |
|
| 19 | + | @then1 |
|
| 20 | + | store w32 7 %0 0; |
|
| 21 | + | jmp @merge3; |
|
| 22 | + | @else2 |
|
| 23 | + | store w32 8 %0 0; |
|
| 24 | + | jmp @merge3; |
|
| 25 | + | @merge3 |
|
| 26 | + | load w32 %3 %0 4; |
|
| 27 | + | ret %3; |
|
| 28 | + | } |
|
| 29 | + | ||
| 30 | + | fn w32 $returnedBranch(w64 %0, w8 %1) { |
|
| 31 | + | @entry0 |
|
| 32 | + | br.ne w32 %1 0 @then1 @merge2; |
|
| 33 | + | @then1 |
|
| 34 | + | load w32 %2 %0 0; |
|
| 35 | + | ret %2; |
|
| 36 | + | @merge2 |
|
| 37 | + | load w32 %3 %0 0; |
|
| 38 | + | ret %3; |
|
| 39 | + | } |
|
| 40 | + | ||
| 41 | + | fn w32 $readLoop(w64 %0) { |
|
| 42 | + | @entry0 |
|
| 43 | + | jmp @loop1(0, %0, 0); |
|
| 44 | + | @loop1(w64 %1, w64 %2, w32 %3) |
|
| 45 | + | br.slt w64 %1 3 @body2 @merge3; |
|
| 46 | + | @body2 |
|
| 47 | + | load w32 %4 %2 0; |
|
| 48 | + | add w32 %5 %3 %4; |
|
| 49 | + | add w64 %6 %1 1; |
|
| 50 | + | jmp @loop1(%6, %2, %5); |
|
| 51 | + | @merge3 |
|
| 52 | + | jmp @while4(0, %2); |
|
| 53 | + | @while4(w32 %7, w64 %8) |
|
| 54 | + | br.ult w32 %7 2 @body5 @merge6; |
|
| 55 | + | @body5 |
|
| 56 | + | load w32 %9 %8 0; |
|
| 57 | + | br.ult w32 0 %9 @assert.ok8 @assert.fail7; |
|
| 58 | + | @merge6 |
|
| 59 | + | reserve %11 8 4; |
|
| 60 | + | store w8 1 %11 0; |
|
| 61 | + | store w32 1 %11 4; |
|
| 62 | + | jmp @while9(%11, %8); |
|
| 63 | + | @assert.fail7 |
|
| 64 | + | unreachable; |
|
| 65 | + | @assert.ok8 |
|
| 66 | + | add w32 %10 %7 1; |
|
| 67 | + | jmp @while4(%10, %8); |
|
| 68 | + | @while9(w64 %12, w64 %16) |
|
| 69 | + | reserve %13 8 4; |
|
| 70 | + | blit %13 %12 8; |
|
| 71 | + | load w8 %14 %13 0; |
|
| 72 | + | br.ne w32 %14 0 @body10 @merge11; |
|
| 73 | + | @body10 |
|
| 74 | + | load w32 %15 %13 4; |
|
| 75 | + | load w32 %17 %16 0; |
|
| 76 | + | br.ult w32 0 %17 @assert.ok13 @assert.fail12; |
|
| 77 | + | @merge11 |
|
| 78 | + | ret %3; |
|
| 79 | + | @assert.fail12 |
|
| 80 | + | unreachable; |
|
| 81 | + | @assert.ok13 |
|
| 82 | + | reserve %18 8 4; |
|
| 83 | + | store w8 0 %18 0; |
|
| 84 | + | blit %12 %18 8; |
|
| 85 | + | jmp @while9(%12, %16); |
|
| 86 | + | } |
|
| 87 | + | ||
| 88 | + | fn w64 $breakChild(w64 %0) { |
|
| 89 | + | @entry0 |
|
| 90 | + | jmp @loop1(%0); |
|
| 91 | + | @loop1(w64 %1) |
|
| 92 | + | load w32 %2 %1 0; |
|
| 93 | + | add w32 %3 %2 1; |
|
| 94 | + | store w32 %3 %1 0; |
|
| 95 | + | jmp @merge2; |
|
| 96 | + | @merge2 |
|
| 97 | + | load w32 %4 %1 0; |
|
| 98 | + | add w32 %5 %4 1; |
|
| 99 | + | store w32 %5 %1 0; |
|
| 100 | + | ret; |
|
| 101 | + | } |
|
| 102 | + | ||
| 103 | + | fn w32 $main() { |
|
| 104 | + | @entry0 |
|
| 105 | + | reserve %0 8 4; |
|
| 106 | + | store w32 20 %0 0; |
|
| 107 | + | store w32 20 %0 4; |
|
| 108 | + | call w32 %1 $split(%0); |
|
| 109 | + | br.eq w32 %1 42 @assert.ok2 @assert.fail1; |
|
| 110 | + | @assert.fail1 |
|
| 111 | + | unreachable; |
|
| 112 | + | @assert.ok2 |
|
| 113 | + | reserve %2 8 4; |
|
| 114 | + | store w32 0 %2 0; |
|
| 115 | + | store w32 9 %2 4; |
|
| 116 | + | call w32 %3 $branch(%2, 1); |
|
| 117 | + | br.eq w32 %3 9 @assert.ok4 @assert.fail3; |
|
| 118 | + | @assert.fail3 |
|
| 119 | + | unreachable; |
|
| 120 | + | @assert.ok4 |
|
| 121 | + | call w32 %4 $branch(%2, 0); |
|
| 122 | + | br.eq w32 %4 9 @assert.ok6 @assert.fail5; |
|
| 123 | + | @assert.fail5 |
|
| 124 | + | unreachable; |
|
| 125 | + | @assert.ok6 |
|
| 126 | + | call w32 %5 $readLoop(%0); |
|
| 127 | + | br.eq w32 %5 63 @assert.ok8 @assert.fail7; |
|
| 128 | + | @assert.fail7 |
|
| 129 | + | unreachable; |
|
| 130 | + | @assert.ok8 |
|
| 131 | + | reserve %6 4 4; |
|
| 132 | + | store w32 0 %6 0; |
|
| 133 | + | call w64 $breakChild(%6); |
|
| 134 | + | load w32 %7 %6 0; |
|
| 135 | + | br.eq w32 %7 2 @assert.ok10 @assert.fail9; |
|
| 136 | + | @assert.fail9 |
|
| 137 | + | unreachable; |
|
| 138 | + | @assert.ok10 |
|
| 139 | + | call w32 %8 $returnedBranch(%6, 1); |
|
| 140 | + | br.eq w32 %8 2 @assert.ok12 @assert.fail11; |
|
| 141 | + | @assert.fail11 |
|
| 142 | + | unreachable; |
|
| 143 | + | @assert.ok12 |
|
| 144 | + | call w32 %9 $returnedBranch(%6, 0); |
|
| 145 | + | br.eq w32 %9 2 @assert.ok14 @assert.fail13; |
|
| 146 | + | @assert.fail13 |
|
| 147 | + | unreachable; |
|
| 148 | + | @assert.ok14 |
|
| 149 | + | load w32 %10 %0 0; |
|
| 150 | + | load w32 %11 %0 4; |
|
| 151 | + | add w32 %12 %10 %11; |
|
| 152 | + | ret %12; |
|
| 153 | + | } |
test/tests/regions.methods.rad
added
+56 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Value tied to one lexical region. |
|
| 4 | + | record View: 'r + Copy { |
|
| 5 | + | /// Borrowed value. |
|
| 6 | + | value: &'r u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Return the value retained by a regional receiver. |
|
| 10 | + | fn (view: &View 'r) get 'r () -> &'r u32 { |
|
| 11 | + | return view.value; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Select a value with a call-specific region. |
|
| 15 | + | trait Pick { |
|
| 16 | + | /// Return the selected value. |
|
| 17 | + | fn (&Pick) pick 'r (value: &'r u32) -> &'r u32; |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | /// Stateless selector. |
|
| 21 | + | record Picker: Copy {} |
|
| 22 | + | ||
| 23 | + | instance Pick for Picker { |
|
| 24 | + | /// Return the selected value. |
|
| 25 | + | fn (picker: &Picker) pick 'r (value: &'r u32) -> &'r u32 { |
|
| 26 | + | return value; |
|
| 27 | + | } |
|
| 28 | + | } |
|
| 29 | + | ||
| 30 | + | /// Read a stored value. |
|
| 31 | + | trait Read { |
|
| 32 | + | /// Return the stored value. |
|
| 33 | + | fn (&Read) read() -> u32; |
|
| 34 | + | } |
|
| 35 | + | ||
| 36 | + | instance Read for View 'r { |
|
| 37 | + | /// Return the regional value. |
|
| 38 | + | fn (view: &View 'r) read() -> u32 { |
|
| 39 | + | return *view.value; |
|
| 40 | + | } |
|
| 41 | + | } |
|
| 42 | + | ||
| 43 | + | @default unsafe fn main() -> u32 { |
|
| 44 | + | let value: u32 = 42; |
|
| 45 | + | let borrowed: 'value = &value in { |
|
| 46 | + | let view = View 'value { value: borrowed }; |
|
| 47 | + | assert *view.get() == 42; |
|
| 48 | + | ||
| 49 | + | let picker = Picker {}; |
|
| 50 | + | let pick: *unsafe opaque Pick = &picker; |
|
| 51 | + | assert *pick.pick(borrowed) == 42; |
|
| 52 | + | ||
| 53 | + | let read: *unsafe opaque Read = &view; |
|
| 54 | + | return read.read(); |
|
| 55 | + | } |
|
| 56 | + | } |
test/tests/regions.nominal.rad
added
+47 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record Count: 'r + Copy { value: u32 } |
|
| 4 | + | record Pair: 'r + Copy (u32, u32); |
|
| 5 | + | record Node: 'r + Copy { value: u32, next: ?*Node 'r } |
|
| 6 | + | union Item: 'r + Copy { Value(u32), Link { node: ?*Node 'r }, Empty } |
|
| 7 | + | ||
| 8 | + | fn create 'r (value: u32) -> Count 'r { return Count { value }; } |
|
| 9 | + | fn empty 'r () -> Item 'r { return Item::Empty; } |
|
| 10 | + | fn read 'r (count: Count 'r) -> u32 { return count.value; } |
|
| 11 | + | fn sum 'r (pair: Pair 'r) -> u32 { |
|
| 12 | + | let case Pair(a, b) = pair else panic; |
|
| 13 | + | return a + b; |
|
| 14 | + | } |
|
| 15 | + | fn itemValue 'r (item: Item 'r) -> u32 { |
|
| 16 | + | match item { |
|
| 17 | + | case Item::Value(value) => return value, |
|
| 18 | + | case Item::Link { node } => { |
|
| 19 | + | if let n = node { |
|
| 20 | + | return n.value; |
|
| 21 | + | } |
|
| 22 | + | return 0; |
|
| 23 | + | } |
|
| 24 | + | case Item::Empty => return 0, |
|
| 25 | + | } |
|
| 26 | + | } |
|
| 27 | + | fn load 'r 'b (node: &'b Node 'r) -> u32 { return node.value; } |
|
| 28 | + | ||
| 29 | + | @default fn main() -> u32 { |
|
| 30 | + | let x: u32 = 0; |
|
| 31 | + | let p: 'first = &x in { |
|
| 32 | + | let count = create 'first (20); |
|
| 33 | + | let pair: Pair 'first = Pair(1, 1); |
|
| 34 | + | let node = Node 'first { value: 20, next: nil }; |
|
| 35 | + | let item: Item 'first = Item::Value(read(count)); |
|
| 36 | + | let none = empty 'first (); |
|
| 37 | + | let link = Item 'first::Link { node: nil }; |
|
| 38 | + | assert itemValue(none) == 0; |
|
| 39 | + | assert itemValue(link) == 0; |
|
| 40 | + | let n: 'second = &node in { |
|
| 41 | + | assert load(n) == 20; |
|
| 42 | + | let other = Count 'second { value: 22 }; |
|
| 43 | + | assert read(other) == 22; |
|
| 44 | + | } |
|
| 45 | + | return itemValue(item) + sum(pair) + node.value; |
|
| 46 | + | } |
|
| 47 | + | } |
test/tests/regions.nominal.ril
added
+132 -0
| 1 | + | fn w64 $create(w32 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %1 4 4; |
|
| 4 | + | store w32 %0 %1 0; |
|
| 5 | + | reserve %2 8 8; |
|
| 6 | + | store w64 0 %2 0; |
|
| 7 | + | blit %2 %1 4; |
|
| 8 | + | load w64 %3 %2 0; |
|
| 9 | + | ret %3; |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | fn w64 $empty(w64 %0) { |
|
| 13 | + | @entry0 |
|
| 14 | + | reserve %1 16 8; |
|
| 15 | + | store w8 2 %1 0; |
|
| 16 | + | blit %0 %1 16; |
|
| 17 | + | ret %0; |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | fn w32 $read(w64 %0) { |
|
| 21 | + | @entry0 |
|
| 22 | + | load w32 %1 %0 0; |
|
| 23 | + | ret %1; |
|
| 24 | + | } |
|
| 25 | + | ||
| 26 | + | fn w32 $sum(w64 %0) { |
|
| 27 | + | @entry0 |
|
| 28 | + | reserve %1 8 4; |
|
| 29 | + | blit %1 %0 8; |
|
| 30 | + | jmp @success1; |
|
| 31 | + | @success1 |
|
| 32 | + | load w32 %2 %1 0; |
|
| 33 | + | load w32 %3 %1 4; |
|
| 34 | + | jmp @merge3; |
|
| 35 | + | @else2 |
|
| 36 | + | unreachable; |
|
| 37 | + | @merge3 |
|
| 38 | + | add w32 %4 %2 %3; |
|
| 39 | + | ret %4; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | fn w32 $itemValue(w64 %0) { |
|
| 43 | + | @entry0 |
|
| 44 | + | reserve %1 16 8; |
|
| 45 | + | blit %1 %0 16; |
|
| 46 | + | jmp @arm1; |
|
| 47 | + | @arm1 |
|
| 48 | + | load w8 %2 %1 0; |
|
| 49 | + | br.eq w8 %2 0 @case2 @arm3; |
|
| 50 | + | @case2 |
|
| 51 | + | load w32 %3 %1 8; |
|
| 52 | + | ret %3; |
|
| 53 | + | @arm3 |
|
| 54 | + | load w8 %4 %1 0; |
|
| 55 | + | br.eq w8 %4 1 @case4 @arm5; |
|
| 56 | + | @case4 |
|
| 57 | + | add w64 %5 %1 8; |
|
| 58 | + | load w64 %6 %5 0; |
|
| 59 | + | br.ne w32 %6 0 @then6 @else7; |
|
| 60 | + | @arm5 |
|
| 61 | + | jmp @case9; |
|
| 62 | + | @then6 |
|
| 63 | + | load w32 %7 %6 0; |
|
| 64 | + | ret %7; |
|
| 65 | + | @else7 |
|
| 66 | + | jmp @merge8; |
|
| 67 | + | @merge8 |
|
| 68 | + | ret 0; |
|
| 69 | + | @case9 |
|
| 70 | + | ret 0; |
|
| 71 | + | } |
|
| 72 | + | ||
| 73 | + | fn w32 $load(w64 %0) { |
|
| 74 | + | @entry0 |
|
| 75 | + | load w32 %1 %0 0; |
|
| 76 | + | ret %1; |
|
| 77 | + | } |
|
| 78 | + | ||
| 79 | + | fn w32 $main() { |
|
| 80 | + | @entry0 |
|
| 81 | + | reserve %0 4 4; |
|
| 82 | + | store w32 0 %0 0; |
|
| 83 | + | call w64 %1 $create(20); |
|
| 84 | + | reserve %2 8 8; |
|
| 85 | + | store w64 %1 %2 0; |
|
| 86 | + | reserve %3 8 4; |
|
| 87 | + | store w32 1 %3 0; |
|
| 88 | + | store w32 1 %3 4; |
|
| 89 | + | reserve %4 16 8; |
|
| 90 | + | store w32 20 %4 0; |
|
| 91 | + | store w64 0 %4 8; |
|
| 92 | + | reserve %5 4 4; |
|
| 93 | + | call w32 %6 $read(%2); |
|
| 94 | + | store w32 %6 %5 0; |
|
| 95 | + | reserve %7 16 8; |
|
| 96 | + | store w8 0 %7 0; |
|
| 97 | + | add w64 %8 %7 8; |
|
| 98 | + | blit %8 %5 4; |
|
| 99 | + | reserve %9 16 8; |
|
| 100 | + | call w64 %10 $empty(%9); |
|
| 101 | + | reserve %11 16 8; |
|
| 102 | + | store w8 1 %11 0; |
|
| 103 | + | store w64 0 %11 8; |
|
| 104 | + | call w32 %12 $itemValue(%10); |
|
| 105 | + | br.eq w32 %12 0 @assert.ok2 @assert.fail1; |
|
| 106 | + | @assert.fail1 |
|
| 107 | + | unreachable; |
|
| 108 | + | @assert.ok2 |
|
| 109 | + | call w32 %13 $itemValue(%11); |
|
| 110 | + | br.eq w32 %13 0 @assert.ok4 @assert.fail3; |
|
| 111 | + | @assert.fail3 |
|
| 112 | + | unreachable; |
|
| 113 | + | @assert.ok4 |
|
| 114 | + | call w32 %14 $load(%4); |
|
| 115 | + | br.eq w32 %14 20 @assert.ok6 @assert.fail5; |
|
| 116 | + | @assert.fail5 |
|
| 117 | + | unreachable; |
|
| 118 | + | @assert.ok6 |
|
| 119 | + | reserve %15 4 4; |
|
| 120 | + | store w32 22 %15 0; |
|
| 121 | + | call w32 %16 $read(%15); |
|
| 122 | + | br.eq w32 %16 22 @assert.ok8 @assert.fail7; |
|
| 123 | + | @assert.fail7 |
|
| 124 | + | unreachable; |
|
| 125 | + | @assert.ok8 |
|
| 126 | + | call w32 %17 $itemValue(%7); |
|
| 127 | + | call w32 %18 $sum(%3); |
|
| 128 | + | add w32 %19 %17 %18; |
|
| 129 | + | load w32 %20 %4 0; |
|
| 130 | + | add w32 %21 %19 %20; |
|
| 131 | + | ret %21; |
|
| 132 | + | } |
test/tests/regions.owner.freeze.rad
added
+15 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// A uniquely owned value. |
|
| 4 | + | record Owner { |
|
| 5 | + | /// Storage controlled by this owner. |
|
| 6 | + | value: *mut u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | @default fn main() -> u32 { |
|
| 10 | + | static VALUE: u32 = 42; |
|
| 11 | + | let owner = Owner { value: &mut VALUE }; |
|
| 12 | + | let case Owner { value } = owner else panic; |
|
| 13 | + | let shared: *u32 = value; |
|
| 14 | + | return *shared; |
|
| 15 | + | } |
test/tests/regions.owner.freeze.ril
added
+21 -0
| 1 | + | data mut $main$nominal$VALUE align 4 { |
|
| 2 | + | w32 42; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w32 $main() { |
|
| 6 | + | @entry0 |
|
| 7 | + | reserve %0 8 8; |
|
| 8 | + | copy %1 $main$nominal$VALUE; |
|
| 9 | + | store w64 %1 %0 0; |
|
| 10 | + | reserve %2 8 8; |
|
| 11 | + | blit %2 %0 8; |
|
| 12 | + | jmp @success1; |
|
| 13 | + | @success1 |
|
| 14 | + | load w64 %3 %2 0; |
|
| 15 | + | jmp @merge3; |
|
| 16 | + | @else2 |
|
| 17 | + | unreachable; |
|
| 18 | + | @merge3 |
|
| 19 | + | load w32 %4 %3 0; |
|
| 20 | + | ret %4; |
|
| 21 | + | } |
test/tests/regions.owner.lifetime.rad
added
+42 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// An exclusive owner of regional storage. |
|
| 4 | + | record Owner: 'r { |
|
| 5 | + | /// Value controlled by the owner. |
|
| 6 | + | value: &'r mut u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// A copied shared reference to regional storage. |
|
| 10 | + | record Shared: 'r + Copy { |
|
| 11 | + | /// Value that remains valid independently of this container. |
|
| 12 | + | value: &'r u32, |
|
| 13 | + | } |
|
| 14 | + | ||
| 15 | + | /// Reborrow an exclusive field for the owner's borrow region. |
|
| 16 | + | fn readOwner 'r 's (owner: &'s Owner 'r) -> &'s u32 where 'r: 's { |
|
| 17 | + | return &*owner.value; |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | /// Retain the region of a copyable shared field. |
|
| 21 | + | fn readShared 'r 's (shared: &'s Shared 'r) -> &'r u32 where 'r: 's { |
|
| 22 | + | return &*shared.value; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | @default fn main() -> u32 { |
|
| 26 | + | let mut value: u32 = 41; |
|
| 27 | + | let reference: 'value = &mut value in { |
|
| 28 | + | let owner = Owner 'value { value: reference }; |
|
| 29 | + | let view: 'read = &owner where 'value: 'read in { |
|
| 30 | + | let first = readOwner(view); |
|
| 31 | + | assert *first == 41; |
|
| 32 | + | } |
|
| 33 | + | set *owner.value = 42; |
|
| 34 | + | let shared = Shared 'value { value: &*owner.value }; |
|
| 35 | + | let mut retained: ?&'value u32 = nil; |
|
| 36 | + | let view: 'copy = &shared where 'value: 'copy in { |
|
| 37 | + | set retained = readShared(view); |
|
| 38 | + | } |
|
| 39 | + | let answer = retained else panic; |
|
| 40 | + | return *answer; |
|
| 41 | + | } |
|
| 42 | + | } |
test/tests/regions.owner.lifetime.ril
added
+39 -0
| 1 | + | fn w64 $readOwner(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w64 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w64 $readShared(w64 %0) { |
|
| 8 | + | @entry0 |
|
| 9 | + | load w64 %1 %0 0; |
|
| 10 | + | ret %1; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $main() { |
|
| 14 | + | @entry0 |
|
| 15 | + | reserve %0 4 4; |
|
| 16 | + | store w32 41 %0 0; |
|
| 17 | + | reserve %1 8 8; |
|
| 18 | + | store w64 %0 %1 0; |
|
| 19 | + | call w64 %2 $readOwner(%1); |
|
| 20 | + | load w32 %3 %2 0; |
|
| 21 | + | br.eq w32 %3 41 @assert.ok2 @assert.fail1; |
|
| 22 | + | @assert.fail1 |
|
| 23 | + | unreachable; |
|
| 24 | + | @assert.ok2 |
|
| 25 | + | load w64 %4 %1 0; |
|
| 26 | + | store w32 42 %4 0; |
|
| 27 | + | reserve %5 8 8; |
|
| 28 | + | load w64 %6 %1 0; |
|
| 29 | + | store w64 %6 %5 0; |
|
| 30 | + | call w64 %7 $readShared(%5); |
|
| 31 | + | br.ne w32 %7 0 @success3 @else4; |
|
| 32 | + | @success3 |
|
| 33 | + | jmp @merge5; |
|
| 34 | + | @else4 |
|
| 35 | + | unreachable; |
|
| 36 | + | @merge5 |
|
| 37 | + | load w32 %8 %7 0; |
|
| 38 | + | ret %8; |
|
| 39 | + | } |
test/tests/regions.ownership.move.rad
added
+3 -0
| 1 | + | // Regional exclusive references retain affine ownership and arithmetic checks. |
|
| 2 | + | ||
| 3 | + | fn f 'r (p: &'r mut u8) { let q: &'r mut u8 = p; set *q = 3; } |
test/tests/regions.ownership.move.ril
added
+5 -0
| 1 | + | fn w64 $f(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | store w8 3 %0 0; |
|
| 4 | + | ret; |
|
| 5 | + | } |
test/tests/regions.parameters.rad
added
+5 -0
| 1 | + | //! Region-qualified pointer and slice parameter lowering. |
|
| 2 | + | ||
| 3 | + | fn load 'r (p: &'r u32) -> u32 { return *p; } |
|
| 4 | + | fn store 'r (p: &'r mut u32, value: u32) { set *p = value; } |
|
| 5 | + | fn element 'r (p: &'r [u32], i: u32) -> u32 { return p[i]; } |
test/tests/regions.parameters.ril
added
+26 -0
| 1 | + | fn w32 $load(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 0; |
|
| 4 | + | ret %1; |
|
| 5 | + | } |
|
| 6 | + | ||
| 7 | + | fn w64 $store(w64 %0, w32 %1) { |
|
| 8 | + | @entry0 |
|
| 9 | + | store w32 %1 %0 0; |
|
| 10 | + | ret; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $element(w64 %0, w32 %1) { |
|
| 14 | + | @entry0 |
|
| 15 | + | load w32 %2 %0 8; |
|
| 16 | + | br.ult w32 %1 %2 @guard#pass1 @guard#trap2; |
|
| 17 | + | @guard#pass1 |
|
| 18 | + | load w64 %3 %0 0; |
|
| 19 | + | mul w64 %4 %1 4; |
|
| 20 | + | add w64 %5 %3 %4; |
|
| 21 | + | load w32 %6 %5 0; |
|
| 22 | + | ret %6; |
|
| 23 | + | @guard#trap2 |
|
| 24 | + | ebreak; |
|
| 25 | + | unreachable; |
|
| 26 | + | } |
test/tests/regions.session.allocate.rad
added
+73 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | record Pair: Copy { a: u32, b: u32 } |
|
| 7 | + | record Empty: Copy {} |
|
| 8 | + | record Entry { value: u32 } |
|
| 9 | + | ||
| 10 | + | fn create 'r (session: &Session 'r, value: u32) -> &'r mut u32 throws (alloc::AllocError) { |
|
| 11 | + | return try session.new(value); |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | fn initializer(state: &mut u32) -> u32 throws (alloc::AllocError) { |
|
| 15 | + | set *state = 42; |
|
| 16 | + | throw alloc::AllocError::OutOfMemory; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | fn failedInitializer 'r (session: &Session 'r, state: &mut u32) -> &'r mut u32 throws (alloc::AllocError) { |
|
| 20 | + | return try session.new(try initializer(state)); |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | fn failures(arena: &mut alloc::Arena) { |
|
| 24 | + | let before = alloc::used(arena); |
|
| 25 | + | let mut state: u32 = 0; |
|
| 26 | + | use *arena as failed in { |
|
| 27 | + | try failedInitializer(&failed, &mut state) catch error as alloc::AllocError { |
|
| 28 | + | assert state == 42; |
|
| 29 | + | }; |
|
| 30 | + | let overflow = try? failed.fill(1 as u64, 4294967295); |
|
| 31 | + | if let unexpected = overflow { |
|
| 32 | + | panic; |
|
| 33 | + | } |
|
| 34 | + | try failed.fill(1 as u32, 256) catch error as alloc::AllocError { |
|
| 35 | + | assert state == 42; |
|
| 36 | + | }; |
|
| 37 | + | } |
|
| 38 | + | assert alloc::used(arena) == before; |
|
| 39 | + | assert state == 42; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | @default fn main() -> u32 { |
|
| 43 | + | static DATA: [u8; 256] = [0; 256]; |
|
| 44 | + | let mut arena = alloc::new(&mut DATA[1..]); |
|
| 45 | + | failures(&mut arena); |
|
| 46 | + | use arena as objects in { |
|
| 47 | + | let entry = try! objects.new(Entry { value: 7 }); |
|
| 48 | + | assert entry.value == 7; |
|
| 49 | + | let name = try! objects.new("value"); |
|
| 50 | + | assert name.len == 5; |
|
| 51 | + | let first = try! create(&objects, 20); |
|
| 52 | + | let second = try! objects.new(Pair { a: 11, b: 11 }); |
|
| 53 | + | let filled = try! objects.fill(Pair { a: 1, b: 2 }, 3); |
|
| 54 | + | let copied = try! objects.copy(&filled[..]); |
|
| 55 | + | set filled[0].a = 9; |
|
| 56 | + | assert copied[0].a == 1; |
|
| 57 | + | assert copied[2].b == 2; |
|
| 58 | + | let copiedAgain = try! objects.copy(&filled[..] if true else &copied[..]); |
|
| 59 | + | assert copiedAgain[0].a == 9; |
|
| 60 | + | set filled[1].a = 5; |
|
| 61 | + | assert copiedAgain[1].a == 1; |
|
| 62 | + | let pointer = try! objects.new(first); |
|
| 63 | + | assert **pointer == 20; |
|
| 64 | + | let zero = try! objects.fill(Empty {}, 0); |
|
| 65 | + | assert zero.len == 0; |
|
| 66 | + | let empty = try! objects.new(Empty {}); |
|
| 67 | + | let many = try! objects.fill(Empty {}, 2); |
|
| 68 | + | assert many.len == 2; |
|
| 69 | + | assert **pointer == 20; |
|
| 70 | + | assert second.a + second.b == 22; |
|
| 71 | + | return **pointer + second.a + second.b; |
|
| 72 | + | } |
|
| 73 | + | } |
test/tests/regions.session.allocate.ril
added
+641 -0
| 1 | + | data mut $"regions.session.allocate::regions.session.allocate::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 256; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data $"regions.session.allocate::main$literal$0" align 1 { |
|
| 6 | + | str "value"; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w64 $"regions.session.allocate::create"(w64 %0, w64 %1, w32 %2) { |
|
| 10 | + | @entry0 |
|
| 11 | + | load w64 %3 %1 0; |
|
| 12 | + | load w64 %4 %1 8; |
|
| 13 | + | load w64 %5 %4 0; |
|
| 14 | + | reserve %6 16 8; |
|
| 15 | + | call w64 %7 %5(%6, %3, 4, 4); |
|
| 16 | + | load w64 %8 %7 0; |
|
| 17 | + | reserve %9 8 8; |
|
| 18 | + | br.ne w32 %8 0 @err2 @ok1; |
|
| 19 | + | @ok1 |
|
| 20 | + | load w64 %10 %7 8; |
|
| 21 | + | store w32 %2 %10 0; |
|
| 22 | + | load w64 %11 %7 8; |
|
| 23 | + | store w64 %11 %9 0; |
|
| 24 | + | jmp @merge3; |
|
| 25 | + | @err2 |
|
| 26 | + | reserve %12 16 8; |
|
| 27 | + | store w64 %8 %12 0; |
|
| 28 | + | add w64 %13 %7 8; |
|
| 29 | + | add w64 %14 %12 8; |
|
| 30 | + | blit %14 %13 1; |
|
| 31 | + | blit %0 %12 16; |
|
| 32 | + | ret %0; |
|
| 33 | + | @merge3 |
|
| 34 | + | load w64 %15 %9 0; |
|
| 35 | + | reserve %16 16 8; |
|
| 36 | + | store w64 0 %16 0; |
|
| 37 | + | store w64 %15 %16 8; |
|
| 38 | + | blit %0 %16 16; |
|
| 39 | + | ret %0; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | fn w64 $"regions.session.allocate::initializer"(w64 %0, w64 %1) { |
|
| 43 | + | @entry0 |
|
| 44 | + | store w32 42 %1 0; |
|
| 45 | + | reserve %2 12 8; |
|
| 46 | + | store w64 1 %2 0; |
|
| 47 | + | store w8 0 %2 8; |
|
| 48 | + | blit %0 %2 12; |
|
| 49 | + | ret %0; |
|
| 50 | + | } |
|
| 51 | + | ||
| 52 | + | fn w64 $"regions.session.allocate::failedInitializer"(w64 %0, w64 %1, w64 %2) { |
|
| 53 | + | @entry0 |
|
| 54 | + | load w64 %3 %1 0; |
|
| 55 | + | load w64 %4 %1 8; |
|
| 56 | + | load w64 %5 %4 0; |
|
| 57 | + | reserve %6 12 8; |
|
| 58 | + | call w64 %7 $"regions.session.allocate::initializer"(%6, %2); |
|
| 59 | + | load w64 %8 %7 0; |
|
| 60 | + | reserve %9 4 4; |
|
| 61 | + | br.ne w32 %8 0 @err2 @ok1; |
|
| 62 | + | @ok1 |
|
| 63 | + | load w32 %10 %7 8; |
|
| 64 | + | store w32 %10 %9 0; |
|
| 65 | + | jmp @merge3; |
|
| 66 | + | @err2 |
|
| 67 | + | reserve %11 16 8; |
|
| 68 | + | store w64 %8 %11 0; |
|
| 69 | + | add w64 %12 %7 8; |
|
| 70 | + | add w64 %13 %11 8; |
|
| 71 | + | blit %13 %12 1; |
|
| 72 | + | blit %0 %11 16; |
|
| 73 | + | ret %0; |
|
| 74 | + | @merge3 |
|
| 75 | + | load w32 %14 %9 0; |
|
| 76 | + | reserve %15 16 8; |
|
| 77 | + | call w64 %16 %5(%15, %3, 4, 4); |
|
| 78 | + | load w64 %17 %16 0; |
|
| 79 | + | reserve %18 8 8; |
|
| 80 | + | br.ne w32 %17 0 @err5 @ok4; |
|
| 81 | + | @ok4 |
|
| 82 | + | load w64 %19 %16 8; |
|
| 83 | + | store w32 %14 %19 0; |
|
| 84 | + | load w64 %20 %16 8; |
|
| 85 | + | store w64 %20 %18 0; |
|
| 86 | + | jmp @merge6; |
|
| 87 | + | @err5 |
|
| 88 | + | reserve %21 16 8; |
|
| 89 | + | store w64 %17 %21 0; |
|
| 90 | + | add w64 %22 %16 8; |
|
| 91 | + | add w64 %23 %21 8; |
|
| 92 | + | blit %23 %22 1; |
|
| 93 | + | blit %0 %21 16; |
|
| 94 | + | ret %0; |
|
| 95 | + | @merge6 |
|
| 96 | + | load w64 %24 %18 0; |
|
| 97 | + | reserve %25 16 8; |
|
| 98 | + | store w64 0 %25 0; |
|
| 99 | + | store w64 %24 %25 8; |
|
| 100 | + | blit %0 %25 16; |
|
| 101 | + | ret %0; |
|
| 102 | + | } |
|
| 103 | + | ||
| 104 | + | fn w64 $"regions.session.allocate::failures"(w64 %0) { |
|
| 105 | + | @entry0 |
|
| 106 | + | call w32 %1 $"std::lang::alloc::used"(%0); |
|
| 107 | + | reserve %2 4 4; |
|
| 108 | + | store w32 0 %2 0; |
|
| 109 | + | reserve %3 16 8; |
|
| 110 | + | store w64 %0 %3 0; |
|
| 111 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %3 8; |
|
| 112 | + | reserve %4 16 8; |
|
| 113 | + | call w64 %5 $"regions.session.allocate::failedInitializer"(%4, %3, %2); |
|
| 114 | + | load w64 %6 %5 0; |
|
| 115 | + | reserve %7 8 8; |
|
| 116 | + | br.ne w32 %6 0 @err2 @ok1; |
|
| 117 | + | @ok1 |
|
| 118 | + | load w64 %8 %5 8; |
|
| 119 | + | store w64 %8 %7 0; |
|
| 120 | + | jmp @merge3; |
|
| 121 | + | @err2 |
|
| 122 | + | switch %6 (1 @catch4) @unreachable5; |
|
| 123 | + | @merge3 |
|
| 124 | + | load w64 %11 %7 0; |
|
| 125 | + | load w64 %13 %3 0; |
|
| 126 | + | load w64 %14 %3 8; |
|
| 127 | + | load w64 %15 %14 8; |
|
| 128 | + | reserve %16 24 8; |
|
| 129 | + | call w64 %17 %15(%16, %13, 8, 8, 4294967295); |
|
| 130 | + | load w64 %18 %17 0; |
|
| 131 | + | reserve %19 16 8; |
|
| 132 | + | br.ne w32 %18 0 @err9 @ok8; |
|
| 133 | + | @catch4 |
|
| 134 | + | load w8 %9 %5 8; |
|
| 135 | + | load w32 %10 %2 0; |
|
| 136 | + | br.eq w32 %10 42 @assert.ok7 @assert.fail6; |
|
| 137 | + | @unreachable5 |
|
| 138 | + | unreachable; |
|
| 139 | + | @assert.fail6 |
|
| 140 | + | unreachable; |
|
| 141 | + | @assert.ok7 |
|
| 142 | + | jmp @merge3; |
|
| 143 | + | @ok8 |
|
| 144 | + | load w64 %20 %17 8; |
|
| 145 | + | jmp @fill10(0); |
|
| 146 | + | @err9 |
|
| 147 | + | reserve %26 16 8; |
|
| 148 | + | store w64 0 %26 0; |
|
| 149 | + | store w32 0 %26 8; |
|
| 150 | + | store w32 0 %26 12; |
|
| 151 | + | blit %19 %26 16; |
|
| 152 | + | jmp @merge13; |
|
| 153 | + | @fill10(w32 %21) |
|
| 154 | + | br.ult w32 %21 4294967295 @fill11 @fill12; |
|
| 155 | + | @fill11 |
|
| 156 | + | mul w64 %22 %21 8; |
|
| 157 | + | add w64 %23 %20 %22; |
|
| 158 | + | store w64 1 %23 0; |
|
| 159 | + | add w32 %24 %21 1; |
|
| 160 | + | jmp @fill10(%24); |
|
| 161 | + | @fill12 |
|
| 162 | + | add w64 %25 %17 8; |
|
| 163 | + | blit %19 %25 16; |
|
| 164 | + | jmp @merge13; |
|
| 165 | + | @merge13 |
|
| 166 | + | reserve %27 16 8; |
|
| 167 | + | blit %27 %19 16; |
|
| 168 | + | load w64 %28 %27 0; |
|
| 169 | + | br.ne w32 %28 0 @then14 @else15; |
|
| 170 | + | @then14 |
|
| 171 | + | unreachable; |
|
| 172 | + | @else15 |
|
| 173 | + | jmp @merge16; |
|
| 174 | + | @merge16 |
|
| 175 | + | load w64 %31 %3 0; |
|
| 176 | + | load w64 %32 %3 8; |
|
| 177 | + | load w64 %33 %32 8; |
|
| 178 | + | zext w32 %34 1; |
|
| 179 | + | reserve %35 24 8; |
|
| 180 | + | call w64 %36 %33(%35, %31, 4, 4, 256); |
|
| 181 | + | load w64 %37 %36 0; |
|
| 182 | + | reserve %38 16 8; |
|
| 183 | + | br.ne w32 %37 0 @err18 @ok17; |
|
| 184 | + | @ok17 |
|
| 185 | + | load w64 %39 %36 8; |
|
| 186 | + | jmp @fill19(0); |
|
| 187 | + | @err18 |
|
| 188 | + | switch %37 (1 @catch23) @unreachable24; |
|
| 189 | + | @fill19(w32 %40) |
|
| 190 | + | br.ult w32 %40 256 @fill20 @fill21; |
|
| 191 | + | @fill20 |
|
| 192 | + | mul w64 %41 %40 4; |
|
| 193 | + | add w64 %42 %39 %41; |
|
| 194 | + | store w32 %34 %42 0; |
|
| 195 | + | add w32 %43 %40 1; |
|
| 196 | + | jmp @fill19(%43); |
|
| 197 | + | @fill21 |
|
| 198 | + | add w64 %44 %36 8; |
|
| 199 | + | blit %38 %44 16; |
|
| 200 | + | jmp @merge22; |
|
| 201 | + | @merge22 |
|
| 202 | + | call w32 %55 $"std::lang::alloc::used"(%0); |
|
| 203 | + | br.eq w32 %55 %1 @assert.ok28 @assert.fail27; |
|
| 204 | + | @catch23 |
|
| 205 | + | load w8 %45 %36 8; |
|
| 206 | + | load w32 %49 %2 0; |
|
| 207 | + | br.eq w32 %49 42 @assert.ok26 @assert.fail25; |
|
| 208 | + | @unreachable24 |
|
| 209 | + | unreachable; |
|
| 210 | + | @assert.fail25 |
|
| 211 | + | unreachable; |
|
| 212 | + | @assert.ok26 |
|
| 213 | + | jmp @merge22; |
|
| 214 | + | @assert.fail27 |
|
| 215 | + | unreachable; |
|
| 216 | + | @assert.ok28 |
|
| 217 | + | load w32 %63 %2 0; |
|
| 218 | + | br.eq w32 %63 42 @assert.ok30 @assert.fail29; |
|
| 219 | + | @assert.fail29 |
|
| 220 | + | unreachable; |
|
| 221 | + | @assert.ok30 |
|
| 222 | + | ret; |
|
| 223 | + | } |
|
| 224 | + | ||
| 225 | + | fn w32 $"regions.session.allocate::main"() { |
|
| 226 | + | @entry0 |
|
| 227 | + | copy %0 $"regions.session.allocate::regions.session.allocate::main$nominal$DATA"; |
|
| 228 | + | add w64 %1 %0 1; |
|
| 229 | + | sub w32 %2 256 1; |
|
| 230 | + | reserve %3 16 8; |
|
| 231 | + | store w64 %1 %3 0; |
|
| 232 | + | store w32 %2 %3 8; |
|
| 233 | + | store w32 %2 %3 12; |
|
| 234 | + | reserve %4 24 8; |
|
| 235 | + | call w64 %5 $"std::lang::alloc::new"(%4, %3); |
|
| 236 | + | call w64 $"regions.session.allocate::failures"(%5); |
|
| 237 | + | reserve %6 16 8; |
|
| 238 | + | store w64 %5 %6 0; |
|
| 239 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %6 8; |
|
| 240 | + | load w64 %7 %6 0; |
|
| 241 | + | load w64 %8 %6 8; |
|
| 242 | + | load w64 %9 %8 0; |
|
| 243 | + | reserve %10 4 4; |
|
| 244 | + | store w32 7 %10 0; |
|
| 245 | + | reserve %11 16 8; |
|
| 246 | + | call w64 %12 %9(%11, %7, 4, 4); |
|
| 247 | + | load w64 %13 %12 0; |
|
| 248 | + | reserve %14 8 8; |
|
| 249 | + | br.ne w32 %13 0 @err2 @ok1; |
|
| 250 | + | @ok1 |
|
| 251 | + | load w64 %15 %12 8; |
|
| 252 | + | blit %15 %10 4; |
|
| 253 | + | load w64 %16 %12 8; |
|
| 254 | + | store w64 %16 %14 0; |
|
| 255 | + | jmp @merge3; |
|
| 256 | + | @err2 |
|
| 257 | + | unreachable; |
|
| 258 | + | @merge3 |
|
| 259 | + | load w64 %17 %14 0; |
|
| 260 | + | load w32 %18 %17 0; |
|
| 261 | + | br.eq w32 %18 7 @assert.ok5 @assert.fail4; |
|
| 262 | + | @assert.fail4 |
|
| 263 | + | unreachable; |
|
| 264 | + | @assert.ok5 |
|
| 265 | + | load w64 %19 %6 0; |
|
| 266 | + | load w64 %20 %6 8; |
|
| 267 | + | load w64 %21 %20 0; |
|
| 268 | + | copy %22 $"regions.session.allocate::main$literal$0"; |
|
| 269 | + | reserve %23 16 8; |
|
| 270 | + | store w64 %22 %23 0; |
|
| 271 | + | store w32 5 %23 8; |
|
| 272 | + | store w32 5 %23 12; |
|
| 273 | + | reserve %24 16 8; |
|
| 274 | + | call w64 %25 %21(%24, %19, 16, 8); |
|
| 275 | + | load w64 %26 %25 0; |
|
| 276 | + | reserve %27 8 8; |
|
| 277 | + | br.ne w32 %26 0 @err7 @ok6; |
|
| 278 | + | @ok6 |
|
| 279 | + | load w64 %28 %25 8; |
|
| 280 | + | blit %28 %23 16; |
|
| 281 | + | load w64 %29 %25 8; |
|
| 282 | + | store w64 %29 %27 0; |
|
| 283 | + | jmp @merge8; |
|
| 284 | + | @err7 |
|
| 285 | + | unreachable; |
|
| 286 | + | @merge8 |
|
| 287 | + | load w64 %30 %27 0; |
|
| 288 | + | load w32 %31 %30 8; |
|
| 289 | + | br.eq w32 %31 5 @assert.ok10 @assert.fail9; |
|
| 290 | + | @assert.fail9 |
|
| 291 | + | unreachable; |
|
| 292 | + | @assert.ok10 |
|
| 293 | + | reserve %32 16 8; |
|
| 294 | + | call w64 %33 $"regions.session.allocate::create"(%32, %6, 20); |
|
| 295 | + | load w64 %34 %33 0; |
|
| 296 | + | reserve %35 8 8; |
|
| 297 | + | br.ne w32 %34 0 @err12 @ok11; |
|
| 298 | + | @ok11 |
|
| 299 | + | load w64 %36 %33 8; |
|
| 300 | + | store w64 %36 %35 0; |
|
| 301 | + | jmp @merge13; |
|
| 302 | + | @err12 |
|
| 303 | + | unreachable; |
|
| 304 | + | @merge13 |
|
| 305 | + | load w64 %37 %35 0; |
|
| 306 | + | load w64 %38 %6 0; |
|
| 307 | + | load w64 %39 %6 8; |
|
| 308 | + | load w64 %40 %39 0; |
|
| 309 | + | reserve %41 8 4; |
|
| 310 | + | store w32 11 %41 0; |
|
| 311 | + | store w32 11 %41 4; |
|
| 312 | + | reserve %42 16 8; |
|
| 313 | + | call w64 %43 %40(%42, %38, 8, 4); |
|
| 314 | + | load w64 %44 %43 0; |
|
| 315 | + | reserve %45 8 8; |
|
| 316 | + | br.ne w32 %44 0 @err15 @ok14; |
|
| 317 | + | @ok14 |
|
| 318 | + | load w64 %46 %43 8; |
|
| 319 | + | blit %46 %41 8; |
|
| 320 | + | load w64 %47 %43 8; |
|
| 321 | + | store w64 %47 %45 0; |
|
| 322 | + | jmp @merge16; |
|
| 323 | + | @err15 |
|
| 324 | + | unreachable; |
|
| 325 | + | @merge16 |
|
| 326 | + | load w64 %48 %45 0; |
|
| 327 | + | load w64 %49 %6 0; |
|
| 328 | + | load w64 %50 %6 8; |
|
| 329 | + | load w64 %51 %50 8; |
|
| 330 | + | reserve %52 8 4; |
|
| 331 | + | store w32 1 %52 0; |
|
| 332 | + | store w32 2 %52 4; |
|
| 333 | + | reserve %53 24 8; |
|
| 334 | + | call w64 %54 %51(%53, %49, 8, 4, 3); |
|
| 335 | + | load w64 %55 %54 0; |
|
| 336 | + | reserve %56 16 8; |
|
| 337 | + | br.ne w32 %55 0 @err18 @ok17; |
|
| 338 | + | @ok17 |
|
| 339 | + | load w64 %57 %54 8; |
|
| 340 | + | jmp @fill19(0); |
|
| 341 | + | @err18 |
|
| 342 | + | unreachable; |
|
| 343 | + | @fill19(w32 %58) |
|
| 344 | + | br.ult w32 %58 3 @fill20 @fill21; |
|
| 345 | + | @fill20 |
|
| 346 | + | mul w64 %59 %58 8; |
|
| 347 | + | add w64 %60 %57 %59; |
|
| 348 | + | blit %60 %52 8; |
|
| 349 | + | add w32 %61 %58 1; |
|
| 350 | + | jmp @fill19(%61); |
|
| 351 | + | @fill21 |
|
| 352 | + | add w64 %62 %54 8; |
|
| 353 | + | blit %56 %62 16; |
|
| 354 | + | jmp @merge22; |
|
| 355 | + | @merge22 |
|
| 356 | + | load w64 %64 %6 0; |
|
| 357 | + | load w64 %65 %6 8; |
|
| 358 | + | load w64 %66 %65 8; |
|
| 359 | + | load w64 %67 %56 0; |
|
| 360 | + | load w32 %68 %56 8; |
|
| 361 | + | reserve %69 16 8; |
|
| 362 | + | store w64 %67 %69 0; |
|
| 363 | + | store w32 %68 %69 8; |
|
| 364 | + | store w32 %68 %69 12; |
|
| 365 | + | load w32 %70 %69 8; |
|
| 366 | + | reserve %71 24 8; |
|
| 367 | + | call w64 %72 %66(%71, %64, 8, 4, %70); |
|
| 368 | + | load w64 %73 %72 0; |
|
| 369 | + | reserve %74 16 8; |
|
| 370 | + | br.ne w32 %73 0 @err24 @ok23; |
|
| 371 | + | @ok23 |
|
| 372 | + | load w64 %75 %72 8; |
|
| 373 | + | load w64 %76 %69 0; |
|
| 374 | + | mul w32 %77 %70 8; |
|
| 375 | + | jmp @allocate.copy25(0); |
|
| 376 | + | @err24 |
|
| 377 | + | unreachable; |
|
| 378 | + | @allocate.copy25(w32 %78) |
|
| 379 | + | br.ult w32 %78 %77 @allocate.copy26 @allocate.copy27; |
|
| 380 | + | @allocate.copy26 |
|
| 381 | + | add w64 %79 %76 %78; |
|
| 382 | + | load w8 %80 %79 0; |
|
| 383 | + | add w64 %81 %75 %78; |
|
| 384 | + | store w8 %80 %81 0; |
|
| 385 | + | add w32 %82 %78 1; |
|
| 386 | + | jmp @allocate.copy25(%82); |
|
| 387 | + | @allocate.copy27 |
|
| 388 | + | add w64 %83 %72 8; |
|
| 389 | + | blit %74 %83 16; |
|
| 390 | + | jmp @merge28; |
|
| 391 | + | @merge28 |
|
| 392 | + | load w32 %85 %56 8; |
|
| 393 | + | br.ult w32 0 %85 @guard#pass29 @guard#trap30; |
|
| 394 | + | @guard#pass29 |
|
| 395 | + | load w64 %86 %56 0; |
|
| 396 | + | store w32 9 %86 0; |
|
| 397 | + | load w32 %87 %74 8; |
|
| 398 | + | br.ult w32 0 %87 @guard#pass33 @guard#trap34; |
|
| 399 | + | @guard#trap30 |
|
| 400 | + | ebreak; |
|
| 401 | + | unreachable; |
|
| 402 | + | @assert.fail31 |
|
| 403 | + | unreachable; |
|
| 404 | + | @assert.ok32 |
|
| 405 | + | load w32 %90 %74 8; |
|
| 406 | + | br.ult w32 2 %90 @guard#pass37 @guard#trap38; |
|
| 407 | + | @guard#pass33 |
|
| 408 | + | load w64 %88 %74 0; |
|
| 409 | + | load w32 %89 %88 0; |
|
| 410 | + | br.eq w32 %89 1 @assert.ok32 @assert.fail31; |
|
| 411 | + | @guard#trap34 |
|
| 412 | + | ebreak; |
|
| 413 | + | unreachable; |
|
| 414 | + | @assert.fail35 |
|
| 415 | + | unreachable; |
|
| 416 | + | @assert.ok36 |
|
| 417 | + | load w64 %96 %6 0; |
|
| 418 | + | load w64 %97 %6 8; |
|
| 419 | + | load w64 %98 %97 8; |
|
| 420 | + | reserve %99 16 8; |
|
| 421 | + | copy %100 1; |
|
| 422 | + | br.ne w32 %100 0 @cond#then39 @cond#else40; |
|
| 423 | + | @guard#pass37 |
|
| 424 | + | load w64 %91 %74 0; |
|
| 425 | + | mul w64 %92 2 8; |
|
| 426 | + | add w64 %93 %91 %92; |
|
| 427 | + | load w32 %94 %93 4; |
|
| 428 | + | br.eq w32 %94 2 @assert.ok36 @assert.fail35; |
|
| 429 | + | @guard#trap38 |
|
| 430 | + | ebreak; |
|
| 431 | + | unreachable; |
|
| 432 | + | @cond#then39 |
|
| 433 | + | load w64 %101 %56 0; |
|
| 434 | + | load w32 %102 %56 8; |
|
| 435 | + | reserve %103 16 8; |
|
| 436 | + | store w64 %101 %103 0; |
|
| 437 | + | store w32 %102 %103 8; |
|
| 438 | + | store w32 %102 %103 12; |
|
| 439 | + | blit %99 %103 16; |
|
| 440 | + | jmp @cond#merge41; |
|
| 441 | + | @cond#else40 |
|
| 442 | + | load w64 %104 %74 0; |
|
| 443 | + | load w32 %105 %74 8; |
|
| 444 | + | reserve %106 16 8; |
|
| 445 | + | store w64 %104 %106 0; |
|
| 446 | + | store w32 %105 %106 8; |
|
| 447 | + | store w32 %105 %106 12; |
|
| 448 | + | blit %99 %106 16; |
|
| 449 | + | jmp @cond#merge41; |
|
| 450 | + | @cond#merge41 |
|
| 451 | + | load w32 %107 %99 8; |
|
| 452 | + | reserve %108 24 8; |
|
| 453 | + | call w64 %109 %98(%108, %96, 8, 4, %107); |
|
| 454 | + | load w64 %110 %109 0; |
|
| 455 | + | reserve %111 16 8; |
|
| 456 | + | br.ne w32 %110 0 @err43 @ok42; |
|
| 457 | + | @ok42 |
|
| 458 | + | load w64 %112 %109 8; |
|
| 459 | + | load w64 %113 %99 0; |
|
| 460 | + | mul w32 %114 %107 8; |
|
| 461 | + | jmp @allocate.copy44(0); |
|
| 462 | + | @err43 |
|
| 463 | + | unreachable; |
|
| 464 | + | @allocate.copy44(w32 %115) |
|
| 465 | + | br.ult w32 %115 %114 @allocate.copy45 @allocate.copy46; |
|
| 466 | + | @allocate.copy45 |
|
| 467 | + | add w64 %116 %113 %115; |
|
| 468 | + | load w8 %117 %116 0; |
|
| 469 | + | add w64 %118 %112 %115; |
|
| 470 | + | store w8 %117 %118 0; |
|
| 471 | + | add w32 %119 %115 1; |
|
| 472 | + | jmp @allocate.copy44(%119); |
|
| 473 | + | @allocate.copy46 |
|
| 474 | + | add w64 %120 %109 8; |
|
| 475 | + | blit %111 %120 16; |
|
| 476 | + | jmp @merge47; |
|
| 477 | + | @merge47 |
|
| 478 | + | load w32 %121 %111 8; |
|
| 479 | + | br.ult w32 0 %121 @guard#pass50 @guard#trap51; |
|
| 480 | + | @assert.fail48 |
|
| 481 | + | unreachable; |
|
| 482 | + | @assert.ok49 |
|
| 483 | + | load w32 %126 %56 8; |
|
| 484 | + | br.ult w32 1 %126 @guard#pass52 @guard#trap53; |
|
| 485 | + | @guard#pass50 |
|
| 486 | + | load w64 %122 %111 0; |
|
| 487 | + | load w32 %123 %122 0; |
|
| 488 | + | br.eq w32 %123 9 @assert.ok49 @assert.fail48; |
|
| 489 | + | @guard#trap51 |
|
| 490 | + | ebreak; |
|
| 491 | + | unreachable; |
|
| 492 | + | @guard#pass52 |
|
| 493 | + | load w64 %127 %56 0; |
|
| 494 | + | mul w64 %128 1 8; |
|
| 495 | + | add w64 %129 %127 %128; |
|
| 496 | + | store w32 5 %129 0; |
|
| 497 | + | load w32 %130 %111 8; |
|
| 498 | + | br.ult w32 1 %130 @guard#pass56 @guard#trap57; |
|
| 499 | + | @guard#trap53 |
|
| 500 | + | ebreak; |
|
| 501 | + | unreachable; |
|
| 502 | + | @assert.fail54 |
|
| 503 | + | unreachable; |
|
| 504 | + | @assert.ok55 |
|
| 505 | + | load w64 %137 %6 0; |
|
| 506 | + | load w64 %138 %6 8; |
|
| 507 | + | load w64 %139 %138 0; |
|
| 508 | + | reserve %144 16 8; |
|
| 509 | + | call w64 %145 %139(%144, %137, 8, 8); |
|
| 510 | + | load w64 %146 %145 0; |
|
| 511 | + | reserve %147 8 8; |
|
| 512 | + | br.ne w32 %146 0 @err59 @ok58; |
|
| 513 | + | @guard#pass56 |
|
| 514 | + | load w64 %131 %111 0; |
|
| 515 | + | mul w64 %132 1 8; |
|
| 516 | + | add w64 %133 %131 %132; |
|
| 517 | + | load w32 %134 %133 0; |
|
| 518 | + | br.eq w32 %134 1 @assert.ok55 @assert.fail54; |
|
| 519 | + | @guard#trap57 |
|
| 520 | + | ebreak; |
|
| 521 | + | unreachable; |
|
| 522 | + | @ok58 |
|
| 523 | + | load w64 %148 %145 8; |
|
| 524 | + | store w64 %37 %148 0; |
|
| 525 | + | load w64 %149 %145 8; |
|
| 526 | + | store w64 %149 %147 0; |
|
| 527 | + | jmp @merge60; |
|
| 528 | + | @err59 |
|
| 529 | + | unreachable; |
|
| 530 | + | @merge60 |
|
| 531 | + | load w64 %150 %147 0; |
|
| 532 | + | load w64 %151 %150 0; |
|
| 533 | + | load w32 %152 %151 0; |
|
| 534 | + | br.eq w32 %152 20 @assert.ok62 @assert.fail61; |
|
| 535 | + | @assert.fail61 |
|
| 536 | + | unreachable; |
|
| 537 | + | @assert.ok62 |
|
| 538 | + | load w64 %153 %6 0; |
|
| 539 | + | load w64 %154 %6 8; |
|
| 540 | + | load w64 %155 %154 8; |
|
| 541 | + | reserve %156 0 1; |
|
| 542 | + | reserve %157 24 8; |
|
| 543 | + | call w64 %158 %155(%157, %153, 1, 1, 0); |
|
| 544 | + | load w64 %159 %158 0; |
|
| 545 | + | reserve %160 16 8; |
|
| 546 | + | br.ne w32 %159 0 @err64 @ok63; |
|
| 547 | + | @ok63 |
|
| 548 | + | load w64 %161 %158 8; |
|
| 549 | + | jmp @fill65(0); |
|
| 550 | + | @err64 |
|
| 551 | + | unreachable; |
|
| 552 | + | @fill65(w32 %162) |
|
| 553 | + | br.ult w32 %162 0 @fill66 @fill67; |
|
| 554 | + | @fill66 |
|
| 555 | + | mul w64 %163 %162 0; |
|
| 556 | + | add w64 %164 %161 %163; |
|
| 557 | + | blit %164 %156 0; |
|
| 558 | + | add w32 %165 %162 1; |
|
| 559 | + | jmp @fill65(%165); |
|
| 560 | + | @fill67 |
|
| 561 | + | add w64 %166 %158 8; |
|
| 562 | + | blit %160 %166 16; |
|
| 563 | + | jmp @merge68; |
|
| 564 | + | @merge68 |
|
| 565 | + | load w32 %167 %160 8; |
|
| 566 | + | br.eq w32 %167 0 @assert.ok70 @assert.fail69; |
|
| 567 | + | @assert.fail69 |
|
| 568 | + | unreachable; |
|
| 569 | + | @assert.ok70 |
|
| 570 | + | load w64 %169 %6 0; |
|
| 571 | + | load w64 %170 %6 8; |
|
| 572 | + | load w64 %171 %170 0; |
|
| 573 | + | reserve %172 0 1; |
|
| 574 | + | reserve %173 16 8; |
|
| 575 | + | call w64 %174 %171(%173, %169, 1, 1); |
|
| 576 | + | load w64 %175 %174 0; |
|
| 577 | + | reserve %176 8 8; |
|
| 578 | + | br.ne w32 %175 0 @err72 @ok71; |
|
| 579 | + | @ok71 |
|
| 580 | + | load w64 %177 %174 8; |
|
| 581 | + | blit %177 %172 0; |
|
| 582 | + | load w64 %178 %174 8; |
|
| 583 | + | store w64 %178 %176 0; |
|
| 584 | + | jmp @merge73; |
|
| 585 | + | @err72 |
|
| 586 | + | unreachable; |
|
| 587 | + | @merge73 |
|
| 588 | + | load w64 %179 %176 0; |
|
| 589 | + | load w64 %180 %6 0; |
|
| 590 | + | load w64 %181 %6 8; |
|
| 591 | + | load w64 %182 %181 8; |
|
| 592 | + | reserve %183 0 1; |
|
| 593 | + | reserve %184 24 8; |
|
| 594 | + | call w64 %185 %182(%184, %180, 1, 1, 2); |
|
| 595 | + | load w64 %186 %185 0; |
|
| 596 | + | reserve %187 16 8; |
|
| 597 | + | br.ne w32 %186 0 @err75 @ok74; |
|
| 598 | + | @ok74 |
|
| 599 | + | load w64 %188 %185 8; |
|
| 600 | + | jmp @fill76(0); |
|
| 601 | + | @err75 |
|
| 602 | + | unreachable; |
|
| 603 | + | @fill76(w32 %189) |
|
| 604 | + | br.ult w32 %189 2 @fill77 @fill78; |
|
| 605 | + | @fill77 |
|
| 606 | + | mul w64 %190 %189 0; |
|
| 607 | + | add w64 %191 %188 %190; |
|
| 608 | + | blit %191 %183 0; |
|
| 609 | + | add w32 %192 %189 1; |
|
| 610 | + | jmp @fill76(%192); |
|
| 611 | + | @fill78 |
|
| 612 | + | add w64 %193 %185 8; |
|
| 613 | + | blit %187 %193 16; |
|
| 614 | + | jmp @merge79; |
|
| 615 | + | @merge79 |
|
| 616 | + | load w32 %194 %187 8; |
|
| 617 | + | br.eq w32 %194 2 @assert.ok81 @assert.fail80; |
|
| 618 | + | @assert.fail80 |
|
| 619 | + | unreachable; |
|
| 620 | + | @assert.ok81 |
|
| 621 | + | load w64 %197 %150 0; |
|
| 622 | + | load w32 %198 %197 0; |
|
| 623 | + | br.eq w32 %198 20 @assert.ok83 @assert.fail82; |
|
| 624 | + | @assert.fail82 |
|
| 625 | + | unreachable; |
|
| 626 | + | @assert.ok83 |
|
| 627 | + | load w32 %205 %48 0; |
|
| 628 | + | load w32 %206 %48 4; |
|
| 629 | + | add w32 %207 %205 %206; |
|
| 630 | + | br.eq w32 %207 22 @assert.ok85 @assert.fail84; |
|
| 631 | + | @assert.fail84 |
|
| 632 | + | unreachable; |
|
| 633 | + | @assert.ok85 |
|
| 634 | + | load w64 %208 %150 0; |
|
| 635 | + | load w32 %209 %208 0; |
|
| 636 | + | load w32 %210 %48 0; |
|
| 637 | + | add w32 %211 %209 %210; |
|
| 638 | + | load w32 %212 %48 4; |
|
| 639 | + | add w32 %213 %211 %212; |
|
| 640 | + | ret %213; |
|
| 641 | + | } |
test/tests/regions.session.allocator.rad
added
+39 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// Allocation session provider that delegates to an arena. |
|
| 7 | + | record Allocator: 'r { |
|
| 8 | + | /// Arena that owns the reserved storage. |
|
| 9 | + | arena: &'r mut alloc::Arena, |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | instance alloc::Alloc for Allocator 'r { |
|
| 13 | + | /// Reserve one object in the delegated arena. |
|
| 14 | + | unsafe fn (self: &mut Allocator 'r) reserve(size: u32, alignment: u32) -> *unsafe mut opaque throws (alloc::AllocError) { |
|
| 15 | + | return try alloc::allocRaw(self.arena, size, alignment); |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | /// Reserve a slice in the delegated arena. |
|
| 19 | + | unsafe fn (self: &mut Allocator 'r) reserveSlice(size: u32, alignment: u32, count: u32) -> *unsafe mut [opaque] throws (alloc::AllocError) { |
|
| 20 | + | return try alloc::allocRawSlice(self.arena, size, alignment, count); |
|
| 21 | + | } |
|
| 22 | + | } |
|
| 23 | + | ||
| 24 | + | /// Allocate through a regional allocation trait implementation. |
|
| 25 | + | fn allocate 'r (arena: &'r mut alloc::Arena) -> u32 { |
|
| 26 | + | let mut allocator = Allocator 'r { arena }; |
|
| 27 | + | use allocator as objects in { |
|
| 28 | + | let value = try! objects.new(42 as u32); |
|
| 29 | + | return *value; |
|
| 30 | + | } |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | @default fn main() -> u32 { |
|
| 34 | + | static DATA: [u8; 64] = [0; 64]; |
|
| 35 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 36 | + | let storage: 'storage = &mut arena in { |
|
| 37 | + | return allocate(storage); |
|
| 38 | + | } |
|
| 39 | + | } |
test/tests/regions.session.context.rad
added
+78 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | /// Immutable node in one allocation region. |
|
| 7 | + | record Node: 'r + Copy { |
|
| 8 | + | value: u32, |
|
| 9 | + | next: ?&'r Node 'r, |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | /// Graph builder that owns its allocation interface. |
|
| 13 | + | record Context: 'r { |
|
| 14 | + | storage: Session 'r, |
|
| 15 | + | head: ?&'r Node 'r, |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | /// Construct a graph builder from its allocation interface. |
|
| 19 | + | fn context 'r (storage: Session 'r) -> Context 'r { |
|
| 20 | + | return Context 'r { storage, head: nil }; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | /// Move a graph builder with all of its existing node references. |
|
| 24 | + | fn transfer 'r (value: Context 'r) -> Context 'r { |
|
| 25 | + | return value; |
|
| 26 | + | } |
|
| 27 | + | ||
| 28 | + | /// Prepend one initialized node to the graph. |
|
| 29 | + | fn prepend 'r (self: &mut Context 'r, value: u32) { |
|
| 30 | + | let node = try! self.storage.new(Node 'r { value, next: self.head }); |
|
| 31 | + | set self.head = node; |
|
| 32 | + | } |
|
| 33 | + | ||
| 34 | + | /// Sum the immutable nodes retained by the graph builder. |
|
| 35 | + | fn sum 'r (self: &Context 'r) -> u32 { |
|
| 36 | + | let mut cursor = self.head; |
|
| 37 | + | let mut result: u32 = 0; |
|
| 38 | + | while let node = cursor { |
|
| 39 | + | set result += node.value; |
|
| 40 | + | set cursor = node.next; |
|
| 41 | + | } |
|
| 42 | + | return result; |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | /// Retain copied references after replacing their optional containers. |
|
| 46 | + | fn checkCopiedPatterns 'r (self: &Context 'r) { |
|
| 47 | + | let mut current = self.head; |
|
| 48 | + | if let node = current { |
|
| 49 | + | set current = nil; |
|
| 50 | + | assert node.value == 22; |
|
| 51 | + | } |
|
| 52 | + | set current = self.head; |
|
| 53 | + | match current { |
|
| 54 | + | case nil => { |
|
| 55 | + | }, |
|
| 56 | + | node => { |
|
| 57 | + | set current = nil; |
|
| 58 | + | assert node.value == 22; |
|
| 59 | + | }, |
|
| 60 | + | } |
|
| 61 | + | assert current == nil; |
|
| 62 | + | } |
|
| 63 | + | ||
| 64 | + | @default unsafe fn main() -> u32 { |
|
| 65 | + | static DATA: [u8; 1024] = [0; 1024]; |
|
| 66 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 67 | + | let mut result: u32 = 0; |
|
| 68 | + | use arena as graph in { |
|
| 69 | + | let mut first = context(graph); |
|
| 70 | + | prepend(&mut first, 20); |
|
| 71 | + | let mut moved = transfer(first); |
|
| 72 | + | prepend(&mut moved, 22); |
|
| 73 | + | checkCopiedPatterns(&moved); |
|
| 74 | + | set result = sum(&moved); |
|
| 75 | + | } |
|
| 76 | + | alloc::reset(&mut arena); |
|
| 77 | + | return result; |
|
| 78 | + | } |
test/tests/regions.session.context.ril
added
+122 -0
| 1 | + | data mut $"regions.session.context::regions.session.context::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 1024; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w64 $"regions.session.context::context"(w64 %0, w64 %1) { |
|
| 6 | + | @entry0 |
|
| 7 | + | reserve %2 24 8; |
|
| 8 | + | blit %2 %1 16; |
|
| 9 | + | store w64 0 %2 16; |
|
| 10 | + | blit %0 %2 24; |
|
| 11 | + | ret %0; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | fn w64 $"regions.session.context::transfer"(w64 %0, w64 %1) { |
|
| 15 | + | @entry0 |
|
| 16 | + | blit %0 %1 24; |
|
| 17 | + | ret %0; |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | fn w64 $"regions.session.context::prepend"(w64 %0, w32 %1) { |
|
| 21 | + | @entry0 |
|
| 22 | + | load w64 %2 %0 0; |
|
| 23 | + | load w64 %3 %0 8; |
|
| 24 | + | load w64 %4 %3 0; |
|
| 25 | + | reserve %5 16 8; |
|
| 26 | + | store w32 %1 %5 0; |
|
| 27 | + | load w64 %6 %0 16; |
|
| 28 | + | store w64 %6 %5 8; |
|
| 29 | + | reserve %7 16 8; |
|
| 30 | + | call w64 %8 %4(%7, %2, 16, 8); |
|
| 31 | + | load w64 %9 %8 0; |
|
| 32 | + | reserve %10 8 8; |
|
| 33 | + | br.ne w32 %9 0 @err2 @ok1; |
|
| 34 | + | @ok1 |
|
| 35 | + | load w64 %11 %8 8; |
|
| 36 | + | blit %11 %5 16; |
|
| 37 | + | load w64 %12 %8 8; |
|
| 38 | + | store w64 %12 %10 0; |
|
| 39 | + | jmp @merge3; |
|
| 40 | + | @err2 |
|
| 41 | + | unreachable; |
|
| 42 | + | @merge3 |
|
| 43 | + | load w64 %13 %10 0; |
|
| 44 | + | store w64 %13 %0 16; |
|
| 45 | + | ret; |
|
| 46 | + | } |
|
| 47 | + | ||
| 48 | + | fn w32 $"regions.session.context::sum"(w64 %0) { |
|
| 49 | + | @entry0 |
|
| 50 | + | load w64 %1 %0 16; |
|
| 51 | + | jmp @while1(%1, 0); |
|
| 52 | + | @while1(w64 %2, w32 %3) |
|
| 53 | + | br.ne w32 %2 0 @body2 @merge3; |
|
| 54 | + | @body2 |
|
| 55 | + | load w32 %4 %2 0; |
|
| 56 | + | add w32 %5 %3 %4; |
|
| 57 | + | load w64 %6 %2 8; |
|
| 58 | + | jmp @while1(%6, %5); |
|
| 59 | + | @merge3 |
|
| 60 | + | ret %3; |
|
| 61 | + | } |
|
| 62 | + | ||
| 63 | + | fn w64 $"regions.session.context::checkCopiedPatterns"(w64 %0) { |
|
| 64 | + | @entry0 |
|
| 65 | + | load w64 %1 %0 16; |
|
| 66 | + | br.ne w32 %1 0 @then1 @else2; |
|
| 67 | + | @then1 |
|
| 68 | + | load w32 %2 %1 0; |
|
| 69 | + | br.eq w32 %2 22 @assert.ok4 @assert.fail3; |
|
| 70 | + | @else2 |
|
| 71 | + | jmp @merge5; |
|
| 72 | + | @assert.fail3 |
|
| 73 | + | unreachable; |
|
| 74 | + | @assert.ok4 |
|
| 75 | + | jmp @merge5; |
|
| 76 | + | @merge5 |
|
| 77 | + | load w64 %4 %0 16; |
|
| 78 | + | jmp @arm6; |
|
| 79 | + | @arm6 |
|
| 80 | + | br.eq w64 %4 0 @case7 @arm8; |
|
| 81 | + | @case7 |
|
| 82 | + | jmp @merge9(%4); |
|
| 83 | + | @arm8 |
|
| 84 | + | jmp @case10; |
|
| 85 | + | @merge9(w64 %6) |
|
| 86 | + | br.eq w64 %6 0 @assert.ok15 @assert.fail14; |
|
| 87 | + | @case10 |
|
| 88 | + | load w32 %5 %4 0; |
|
| 89 | + | br.eq w32 %5 22 @assert.ok13 @assert.fail12; |
|
| 90 | + | @assert.fail12 |
|
| 91 | + | unreachable; |
|
| 92 | + | @assert.ok13 |
|
| 93 | + | jmp @merge9(0); |
|
| 94 | + | @assert.fail14 |
|
| 95 | + | unreachable; |
|
| 96 | + | @assert.ok15 |
|
| 97 | + | ret; |
|
| 98 | + | } |
|
| 99 | + | ||
| 100 | + | fn w32 $"regions.session.context::main"() { |
|
| 101 | + | @entry0 |
|
| 102 | + | copy %0 $"regions.session.context::regions.session.context::main$nominal$DATA"; |
|
| 103 | + | reserve %1 16 8; |
|
| 104 | + | store w64 %0 %1 0; |
|
| 105 | + | store w32 1024 %1 8; |
|
| 106 | + | store w32 1024 %1 12; |
|
| 107 | + | reserve %2 24 8; |
|
| 108 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 109 | + | reserve %4 16 8; |
|
| 110 | + | store w64 %3 %4 0; |
|
| 111 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 112 | + | reserve %5 24 8; |
|
| 113 | + | call w64 %6 $"regions.session.context::context"(%5, %4); |
|
| 114 | + | call w64 $"regions.session.context::prepend"(%6, 20); |
|
| 115 | + | reserve %7 24 8; |
|
| 116 | + | call w64 %8 $"regions.session.context::transfer"(%7, %6); |
|
| 117 | + | call w64 $"regions.session.context::prepend"(%8, 22); |
|
| 118 | + | call w64 $"regions.session.context::checkCopiedPatterns"(%8); |
|
| 119 | + | call w32 %9 $"regions.session.context::sum"(%8); |
|
| 120 | + | call w64 $"std::lang::alloc::reset"(%3); |
|
| 121 | + | ret %9; |
|
| 122 | + | } |
test/tests/regions.session.scope.rad
added
+29 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | use std::lang::alloc; |
|
| 5 | + | ||
| 6 | + | fn observe 'r (session: &Session 'r) -> u32 { return 42; } |
|
| 7 | + | fn relay 'r (session: Session 'r) -> Session 'r { return session; } |
|
| 8 | + | ||
| 9 | + | @default fn main() -> u32 { |
|
| 10 | + | static DATA: [u8; 64] = [0; 64]; |
|
| 11 | + | let mut arena = alloc::new(&mut DATA[..]); |
|
| 12 | + | use arena as objects in { |
|
| 13 | + | assert observe(&objects) == 42; |
|
| 14 | + | let moved = relay(objects); |
|
| 15 | + | assert observe(&moved) == 42; |
|
| 16 | + | } |
|
| 17 | + | alloc::reset(&mut arena); |
|
| 18 | + | for i in 0..2 { |
|
| 19 | + | use arena as iteration in { |
|
| 20 | + | assert observe(&iteration) == 42; |
|
| 21 | + | if i == 0 { |
|
| 22 | + | continue; |
|
| 23 | + | } |
|
| 24 | + | break; |
|
| 25 | + | } |
|
| 26 | + | } |
|
| 27 | + | alloc::reset(&mut arena); |
|
| 28 | + | return 42; |
|
| 29 | + | } |
test/tests/regions.session.scope.ril
added
+64 -0
| 1 | + | data mut $"regions.session.scope::regions.session.scope::main$nominal$DATA" align 1 { |
|
| 2 | + | w8 0 * 64; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | fn w32 $"regions.session.scope::observe"(w64 %0) { |
|
| 6 | + | @entry0 |
|
| 7 | + | ret 42; |
|
| 8 | + | } |
|
| 9 | + | ||
| 10 | + | fn w64 $"regions.session.scope::relay"(w64 %0, w64 %1) { |
|
| 11 | + | @entry0 |
|
| 12 | + | blit %0 %1 16; |
|
| 13 | + | ret %0; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | fn w32 $"regions.session.scope::main"() { |
|
| 17 | + | @entry0 |
|
| 18 | + | copy %0 $"regions.session.scope::regions.session.scope::main$nominal$DATA"; |
|
| 19 | + | reserve %1 16 8; |
|
| 20 | + | store w64 %0 %1 0; |
|
| 21 | + | store w32 64 %1 8; |
|
| 22 | + | store w32 64 %1 12; |
|
| 23 | + | reserve %2 24 8; |
|
| 24 | + | call w64 %3 $"std::lang::alloc::new"(%2, %1); |
|
| 25 | + | reserve %4 16 8; |
|
| 26 | + | store w64 %3 %4 0; |
|
| 27 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %4 8; |
|
| 28 | + | call w32 %5 $"regions.session.scope::observe"(%4); |
|
| 29 | + | br.eq w32 %5 42 @assert.ok2 @assert.fail1; |
|
| 30 | + | @assert.fail1 |
|
| 31 | + | unreachable; |
|
| 32 | + | @assert.ok2 |
|
| 33 | + | reserve %6 16 8; |
|
| 34 | + | call w64 %7 $"regions.session.scope::relay"(%6, %4); |
|
| 35 | + | call w32 %8 $"regions.session.scope::observe"(%7); |
|
| 36 | + | br.eq w32 %8 42 @assert.ok4 @assert.fail3; |
|
| 37 | + | @assert.fail3 |
|
| 38 | + | unreachable; |
|
| 39 | + | @assert.ok4 |
|
| 40 | + | call w64 $"std::lang::alloc::reset"(%3); |
|
| 41 | + | jmp @loop5(0, %3); |
|
| 42 | + | @loop5(w64 %9, w64 %10) |
|
| 43 | + | br.slt w64 %9 2 @body6 @merge7; |
|
| 44 | + | @body6 |
|
| 45 | + | reserve %11 16 8; |
|
| 46 | + | store w64 %10 %11 0; |
|
| 47 | + | store w64 $"std::lang::alloc::vtable::Arena::Alloc" %11 8; |
|
| 48 | + | call w32 %12 $"regions.session.scope::observe"(%11); |
|
| 49 | + | br.eq w32 %12 42 @assert.ok9 @assert.fail8; |
|
| 50 | + | @merge7 |
|
| 51 | + | call w64 $"std::lang::alloc::reset"(%10); |
|
| 52 | + | ret 42; |
|
| 53 | + | @assert.fail8 |
|
| 54 | + | unreachable; |
|
| 55 | + | @assert.ok9 |
|
| 56 | + | br.eq w64 %9 0 @then10 @merge11; |
|
| 57 | + | @then10 |
|
| 58 | + | jmp @step12; |
|
| 59 | + | @merge11 |
|
| 60 | + | jmp @merge7; |
|
| 61 | + | @step12 |
|
| 62 | + | add w64 %13 %9 1; |
|
| 63 | + | jmp @loop5(%13, %10); |
|
| 64 | + | } |
test/tests/regions.shared.owner.rad
added
+39 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// An owner of an exclusive slice. |
|
| 4 | + | record Holder: 'r { |
|
| 5 | + | /// Slice whose elements can be read through a shared holder. |
|
| 6 | + | items: &'r mut [u32], |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Read through a shared borrow of an exclusive owner. |
|
| 10 | + | fn sum 'r (holder: &Holder 'r) -> u32 { |
|
| 11 | + | return holder.items[0] + holder.items[1]; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Update an element through an exclusive borrow of its owner. |
|
| 15 | + | fn update 'r (holder: &mut Holder 'r, value: u32) { |
|
| 16 | + | set holder.items[0] = value; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Reborrow an exclusive slice while retaining its owner. |
|
| 20 | + | fn updateSlice(items: &mut [u32], value: u32) { |
|
| 21 | + | set items[1] = value; |
|
| 22 | + | } |
|
| 23 | + | ||
| 24 | + | /// Use a stored exclusive handle through exclusive aggregate access. |
|
| 25 | + | fn updateSecond 'r (holder: &mut Holder 'r, value: u32) { |
|
| 26 | + | updateSlice(holder.items, value); |
|
| 27 | + | } |
|
| 28 | + | ||
| 29 | + | @default fn main() -> u32 { |
|
| 30 | + | let mut values: [u32; 2] = [20, 22]; |
|
| 31 | + | let items: 'items = &mut values[..] in { |
|
| 32 | + | let mut holder = Holder 'items { items }; |
|
| 33 | + | assert sum(&holder) == 42; |
|
| 34 | + | update(&mut holder, 19); |
|
| 35 | + | assert sum(&holder) == 41; |
|
| 36 | + | updateSecond(&mut holder, 23); |
|
| 37 | + | return sum(&holder); |
|
| 38 | + | } |
|
| 39 | + | } |
test/tests/regions.shared.owner.ril
added
+86 -0
| 1 | + | fn w32 $sum(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | load w32 %1 %0 8; |
|
| 4 | + | br.ult w32 0 %1 @guard#pass1 @guard#trap2; |
|
| 5 | + | @guard#pass1 |
|
| 6 | + | load w64 %2 %0 0; |
|
| 7 | + | load w32 %3 %2 0; |
|
| 8 | + | load w32 %4 %0 8; |
|
| 9 | + | br.ult w32 1 %4 @guard#pass3 @guard#trap4; |
|
| 10 | + | @guard#trap2 |
|
| 11 | + | ebreak; |
|
| 12 | + | unreachable; |
|
| 13 | + | @guard#pass3 |
|
| 14 | + | load w64 %5 %0 0; |
|
| 15 | + | mul w64 %6 1 4; |
|
| 16 | + | add w64 %7 %5 %6; |
|
| 17 | + | load w32 %8 %7 0; |
|
| 18 | + | add w32 %9 %3 %8; |
|
| 19 | + | ret %9; |
|
| 20 | + | @guard#trap4 |
|
| 21 | + | ebreak; |
|
| 22 | + | unreachable; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | fn w64 $update(w64 %0, w32 %1) { |
|
| 26 | + | @entry0 |
|
| 27 | + | load w32 %2 %0 8; |
|
| 28 | + | br.ult w32 0 %2 @guard#pass1 @guard#trap2; |
|
| 29 | + | @guard#pass1 |
|
| 30 | + | load w64 %3 %0 0; |
|
| 31 | + | store w32 %1 %3 0; |
|
| 32 | + | ret; |
|
| 33 | + | @guard#trap2 |
|
| 34 | + | ebreak; |
|
| 35 | + | unreachable; |
|
| 36 | + | } |
|
| 37 | + | ||
| 38 | + | fn w64 $updateSlice(w64 %0, w32 %1) { |
|
| 39 | + | @entry0 |
|
| 40 | + | load w32 %2 %0 8; |
|
| 41 | + | br.ult w32 1 %2 @guard#pass1 @guard#trap2; |
|
| 42 | + | @guard#pass1 |
|
| 43 | + | load w64 %3 %0 0; |
|
| 44 | + | mul w64 %4 1 4; |
|
| 45 | + | add w64 %5 %3 %4; |
|
| 46 | + | store w32 %1 %5 0; |
|
| 47 | + | ret; |
|
| 48 | + | @guard#trap2 |
|
| 49 | + | ebreak; |
|
| 50 | + | unreachable; |
|
| 51 | + | } |
|
| 52 | + | ||
| 53 | + | fn w64 $updateSecond(w64 %0, w32 %1) { |
|
| 54 | + | @entry0 |
|
| 55 | + | reserve %2 16 8; |
|
| 56 | + | blit %2 %0 16; |
|
| 57 | + | call w64 $updateSlice(%2, %1); |
|
| 58 | + | ret; |
|
| 59 | + | } |
|
| 60 | + | ||
| 61 | + | fn w32 $main() { |
|
| 62 | + | @entry0 |
|
| 63 | + | reserve %0 8 4; |
|
| 64 | + | store w32 20 %0 0; |
|
| 65 | + | store w32 22 %0 4; |
|
| 66 | + | reserve %1 16 8; |
|
| 67 | + | store w64 %0 %1 0; |
|
| 68 | + | store w32 2 %1 8; |
|
| 69 | + | store w32 2 %1 12; |
|
| 70 | + | reserve %2 16 8; |
|
| 71 | + | blit %2 %1 16; |
|
| 72 | + | call w32 %3 $sum(%2); |
|
| 73 | + | br.eq w32 %3 42 @assert.ok2 @assert.fail1; |
|
| 74 | + | @assert.fail1 |
|
| 75 | + | unreachable; |
|
| 76 | + | @assert.ok2 |
|
| 77 | + | call w64 $update(%2, 19); |
|
| 78 | + | call w32 %4 $sum(%2); |
|
| 79 | + | br.eq w32 %4 41 @assert.ok4 @assert.fail3; |
|
| 80 | + | @assert.fail3 |
|
| 81 | + | unreachable; |
|
| 82 | + | @assert.ok4 |
|
| 83 | + | call w64 $updateSecond(%2, 23); |
|
| 84 | + | call w32 %5 $sum(%2); |
|
| 85 | + | ret %5; |
|
| 86 | + | } |
test/tests/regions.storage.rad
added
+75 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | record Reader: 'r + Copy { value: &'r u32 } |
|
| 4 | + | record Writer: 'r { value: &'r mut u32 } |
|
| 5 | + | union View: 'r + Copy { Item { value: &'r u32 }, Empty } |
|
| 6 | + | record Error: 'r + Copy { value: &'r u32 } |
|
| 7 | + | union Other: Copy { Failed } |
|
| 8 | + | ||
| 9 | + | fn reader 'r (p: &'r u32) -> Reader 'r { return Reader { value: p }; } |
|
| 10 | + | fn writer 'r (p: &'r mut u32) -> Writer 'r { return Writer { value: p }; } |
|
| 11 | + | fn unwrap 'r (w: Writer 'r) -> &'r mut u32 { |
|
| 12 | + | let case Writer { value } = w else panic; |
|
| 13 | + | return value; |
|
| 14 | + | } |
|
| 15 | + | fn project 'r (p: &'r u32) -> &'r u32 { return &*p; } |
|
| 16 | + | fn read 'r (r: Reader 'r) -> &'r u32 { return r.value; } |
|
| 17 | + | fn view 'r (v: View 'r) -> u32 { |
|
| 18 | + | match v { |
|
| 19 | + | case View::Item { value } => return *value, |
|
| 20 | + | case View::Empty => return 0, |
|
| 21 | + | } |
|
| 22 | + | } |
|
| 23 | + | fn fail 'r (p: &'r u32, other: bool) throws (Error 'r, Other) { |
|
| 24 | + | if other { |
|
| 25 | + | throw Other::Failed; |
|
| 26 | + | } |
|
| 27 | + | throw Error 'r { value: p }; |
|
| 28 | + | } |
|
| 29 | + | fn catchValue 'r (p: &'r u32, other: bool) -> u32 { |
|
| 30 | + | try fail(p, other) catch e as Error 'r { |
|
| 31 | + | return *e.value; |
|
| 32 | + | } catch e as Other { |
|
| 33 | + | return 2; |
|
| 34 | + | }; |
|
| 35 | + | return 0; |
|
| 36 | + | } |
|
| 37 | + | ||
| 38 | + | fn store 'long 'short (dst: &'short mut ?&'long u32, p: &'long u32) where 'long: 'short { |
|
| 39 | + | set *dst = p; |
|
| 40 | + | } |
|
| 41 | + | fn fill 'long 'short (dst: &'short mut [&'long u32], p: &'long u32) where 'long: 'short { |
|
| 42 | + | set dst[..] = p; |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | @default fn main() -> u32 { |
|
| 46 | + | let mut value: u32 = 40; |
|
| 47 | + | let p: 'write = &mut value in { |
|
| 48 | + | let owner = writer(p); |
|
| 49 | + | let q = unwrap(owner); |
|
| 50 | + | set *q += 2; |
|
| 51 | + | } |
|
| 52 | + | let p: 'freeze = &mut value in { |
|
| 53 | + | let q = project(p); |
|
| 54 | + | assert *q == 42; |
|
| 55 | + | } |
|
| 56 | + | let p: 'read = &value in { |
|
| 57 | + | let mut slot: ?&'read u32 = nil; |
|
| 58 | + | let dst: 'slot = &mut slot in { store(dst, p); } |
|
| 59 | + | let saved = slot else panic; |
|
| 60 | + | assert *saved == 42; |
|
| 61 | + | let mut pointers: [&'read u32; 2] = [p, p]; |
|
| 62 | + | let dst: 'items = &mut pointers[..] in { fill(dst, p); } |
|
| 63 | + | assert *pointers[1] == 42; |
|
| 64 | + | let r = reader(project(p)); |
|
| 65 | + | let values: [Reader 'read; 2] = [r, r]; |
|
| 66 | + | let some: ?Reader 'read = values[0]; |
|
| 67 | + | let got = some else panic; |
|
| 68 | + | assert *read(got) == 42; |
|
| 69 | + | let v: View 'read = View::Item { value: p }; |
|
| 70 | + | assert view(v) == 42; |
|
| 71 | + | assert catchValue(p, false) == 42; |
|
| 72 | + | assert catchValue(p, true) == 2; |
|
| 73 | + | } |
|
| 74 | + | return value; |
|
| 75 | + | } |
test/tests/regions.storage.ril
added
+228 -0
| 1 | + | fn w64 $reader(w64 %0) { |
|
| 2 | + | @entry0 |
|
| 3 | + | reserve %1 8 8; |
|
| 4 | + | store w64 %0 %1 0; |
|
| 5 | + | load w64 %2 %1 0; |
|
| 6 | + | ret %2; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | fn w64 $writer(w64 %0) { |
|
| 10 | + | @entry0 |
|
| 11 | + | reserve %1 8 8; |
|
| 12 | + | store w64 %0 %1 0; |
|
| 13 | + | load w64 %2 %1 0; |
|
| 14 | + | ret %2; |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | fn w64 $unwrap(w64 %0) { |
|
| 18 | + | @entry0 |
|
| 19 | + | reserve %1 8 8; |
|
| 20 | + | blit %1 %0 8; |
|
| 21 | + | jmp @success1; |
|
| 22 | + | @success1 |
|
| 23 | + | load w64 %2 %1 0; |
|
| 24 | + | jmp @merge3; |
|
| 25 | + | @else2 |
|
| 26 | + | unreachable; |
|
| 27 | + | @merge3 |
|
| 28 | + | ret %2; |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | fn w64 $project(w64 %0) { |
|
| 32 | + | @entry0 |
|
| 33 | + | ret %0; |
|
| 34 | + | } |
|
| 35 | + | ||
| 36 | + | fn w64 $read(w64 %0) { |
|
| 37 | + | @entry0 |
|
| 38 | + | load w64 %1 %0 0; |
|
| 39 | + | ret %1; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | fn w32 $view(w64 %0) { |
|
| 43 | + | @entry0 |
|
| 44 | + | reserve %1 16 8; |
|
| 45 | + | blit %1 %0 16; |
|
| 46 | + | jmp @arm1; |
|
| 47 | + | @arm1 |
|
| 48 | + | load w8 %2 %1 0; |
|
| 49 | + | br.eq w8 %2 0 @case2 @arm3; |
|
| 50 | + | @case2 |
|
| 51 | + | add w64 %3 %1 8; |
|
| 52 | + | load w64 %4 %3 0; |
|
| 53 | + | load w32 %5 %4 0; |
|
| 54 | + | ret %5; |
|
| 55 | + | @arm3 |
|
| 56 | + | jmp @case4; |
|
| 57 | + | @case4 |
|
| 58 | + | ret 0; |
|
| 59 | + | } |
|
| 60 | + | ||
| 61 | + | fn w64 $fail(w64 %0, w64 %1, w8 %2) { |
|
| 62 | + | @entry0 |
|
| 63 | + | br.ne w32 %2 0 @then1 @merge2; |
|
| 64 | + | @then1 |
|
| 65 | + | reserve %3 16 8; |
|
| 66 | + | store w64 1 %3 0; |
|
| 67 | + | store w8 0 %3 8; |
|
| 68 | + | blit %0 %3 16; |
|
| 69 | + | ret %0; |
|
| 70 | + | @merge2 |
|
| 71 | + | reserve %4 8 8; |
|
| 72 | + | store w64 %1 %4 0; |
|
| 73 | + | reserve %5 16 8; |
|
| 74 | + | store w64 2 %5 0; |
|
| 75 | + | add w64 %6 %5 8; |
|
| 76 | + | blit %6 %4 8; |
|
| 77 | + | blit %0 %5 16; |
|
| 78 | + | ret %0; |
|
| 79 | + | } |
|
| 80 | + | ||
| 81 | + | fn w32 $catchValue(w64 %0, w8 %1) { |
|
| 82 | + | @entry0 |
|
| 83 | + | reserve %2 16 8; |
|
| 84 | + | call w64 %3 $fail(%2, %0, %1); |
|
| 85 | + | load w64 %4 %3 0; |
|
| 86 | + | br.ne w32 %4 0 @err2 @ok1; |
|
| 87 | + | @ok1 |
|
| 88 | + | jmp @merge3; |
|
| 89 | + | @err2 |
|
| 90 | + | switch %4 (2 @catch4) (1 @catch5) @unreachable6; |
|
| 91 | + | @merge3 |
|
| 92 | + | ret 0; |
|
| 93 | + | @catch4 |
|
| 94 | + | add w64 %5 %3 8; |
|
| 95 | + | load w64 %6 %5 0; |
|
| 96 | + | load w32 %7 %6 0; |
|
| 97 | + | ret %7; |
|
| 98 | + | @catch5 |
|
| 99 | + | load w8 %8 %3 8; |
|
| 100 | + | ret 2; |
|
| 101 | + | @unreachable6 |
|
| 102 | + | unreachable; |
|
| 103 | + | } |
|
| 104 | + | ||
| 105 | + | fn w64 $store(w64 %0, w64 %1) { |
|
| 106 | + | @entry0 |
|
| 107 | + | store w64 %1 %0 0; |
|
| 108 | + | ret; |
|
| 109 | + | } |
|
| 110 | + | ||
| 111 | + | fn w64 $fill(w64 %0, w64 %1) { |
|
| 112 | + | @entry0 |
|
| 113 | + | load w64 %2 %0 0; |
|
| 114 | + | load w32 %3 %0 8; |
|
| 115 | + | jmp @fill1(0); |
|
| 116 | + | @fill1(w32 %4) |
|
| 117 | + | br.ult w32 %4 %3 @fill2 @fill3; |
|
| 118 | + | @fill2 |
|
| 119 | + | mul w64 %5 %4 8; |
|
| 120 | + | add w64 %6 %2 %5; |
|
| 121 | + | store w64 %1 %6 0; |
|
| 122 | + | add w32 %7 %4 1; |
|
| 123 | + | jmp @fill1(%7); |
|
| 124 | + | @fill3 |
|
| 125 | + | ret; |
|
| 126 | + | } |
|
| 127 | + | ||
| 128 | + | fn w32 $main() { |
|
| 129 | + | @entry0 |
|
| 130 | + | reserve %0 4 4; |
|
| 131 | + | store w32 40 %0 0; |
|
| 132 | + | call w64 %1 $writer(%0); |
|
| 133 | + | reserve %2 8 8; |
|
| 134 | + | store w64 %1 %2 0; |
|
| 135 | + | call w64 %3 $unwrap(%2); |
|
| 136 | + | load w32 %4 %3 0; |
|
| 137 | + | add w32 %5 %4 2; |
|
| 138 | + | store w32 %5 %3 0; |
|
| 139 | + | call w64 %6 $project(%0); |
|
| 140 | + | load w32 %7 %6 0; |
|
| 141 | + | br.eq w32 %7 42 @assert.ok2 @assert.fail1; |
|
| 142 | + | @assert.fail1 |
|
| 143 | + | unreachable; |
|
| 144 | + | @assert.ok2 |
|
| 145 | + | reserve %8 8 8; |
|
| 146 | + | store w64 0 %8 0; |
|
| 147 | + | call w64 $store(%8, %0); |
|
| 148 | + | load w64 %9 %8 0; |
|
| 149 | + | br.ne w32 %9 0 @success3 @else4; |
|
| 150 | + | @success3 |
|
| 151 | + | jmp @merge5; |
|
| 152 | + | @else4 |
|
| 153 | + | unreachable; |
|
| 154 | + | @merge5 |
|
| 155 | + | load w32 %10 %9 0; |
|
| 156 | + | br.eq w32 %10 42 @assert.ok7 @assert.fail6; |
|
| 157 | + | @assert.fail6 |
|
| 158 | + | unreachable; |
|
| 159 | + | @assert.ok7 |
|
| 160 | + | reserve %11 16 8; |
|
| 161 | + | store w64 %0 %11 0; |
|
| 162 | + | store w64 %0 %11 8; |
|
| 163 | + | reserve %12 16 8; |
|
| 164 | + | store w64 %11 %12 0; |
|
| 165 | + | store w32 2 %12 8; |
|
| 166 | + | store w32 2 %12 12; |
|
| 167 | + | reserve %13 16 8; |
|
| 168 | + | blit %13 %12 16; |
|
| 169 | + | call w64 $fill(%13, %0); |
|
| 170 | + | mul w64 %14 1 8; |
|
| 171 | + | add w64 %15 %11 %14; |
|
| 172 | + | load w64 %16 %15 0; |
|
| 173 | + | load w32 %17 %16 0; |
|
| 174 | + | br.eq w32 %17 42 @assert.ok9 @assert.fail8; |
|
| 175 | + | @assert.fail8 |
|
| 176 | + | unreachable; |
|
| 177 | + | @assert.ok9 |
|
| 178 | + | call w64 %18 $project(%0); |
|
| 179 | + | call w64 %19 $reader(%18); |
|
| 180 | + | reserve %20 8 8; |
|
| 181 | + | store w64 %19 %20 0; |
|
| 182 | + | reserve %21 16 8; |
|
| 183 | + | blit %21 %20 8; |
|
| 184 | + | add w64 %22 %21 8; |
|
| 185 | + | blit %22 %20 8; |
|
| 186 | + | reserve %23 16 8; |
|
| 187 | + | store w8 1 %23 0; |
|
| 188 | + | add w64 %24 %23 8; |
|
| 189 | + | blit %24 %21 8; |
|
| 190 | + | reserve %25 16 8; |
|
| 191 | + | blit %25 %23 16; |
|
| 192 | + | reserve %26 16 8; |
|
| 193 | + | blit %26 %25 16; |
|
| 194 | + | load w8 %27 %26 0; |
|
| 195 | + | br.ne w32 %27 0 @success10 @else11; |
|
| 196 | + | @success10 |
|
| 197 | + | add w64 %28 %26 8; |
|
| 198 | + | jmp @merge12; |
|
| 199 | + | @else11 |
|
| 200 | + | unreachable; |
|
| 201 | + | @merge12 |
|
| 202 | + | call w64 %29 $read(%28); |
|
| 203 | + | load w32 %30 %29 0; |
|
| 204 | + | br.eq w32 %30 42 @assert.ok14 @assert.fail13; |
|
| 205 | + | @assert.fail13 |
|
| 206 | + | unreachable; |
|
| 207 | + | @assert.ok14 |
|
| 208 | + | reserve %31 16 8; |
|
| 209 | + | store w8 0 %31 0; |
|
| 210 | + | store w64 %0 %31 8; |
|
| 211 | + | call w32 %32 $view(%31); |
|
| 212 | + | br.eq w32 %32 42 @assert.ok16 @assert.fail15; |
|
| 213 | + | @assert.fail15 |
|
| 214 | + | unreachable; |
|
| 215 | + | @assert.ok16 |
|
| 216 | + | call w32 %33 $catchValue(%0, 0); |
|
| 217 | + | br.eq w32 %33 42 @assert.ok18 @assert.fail17; |
|
| 218 | + | @assert.fail17 |
|
| 219 | + | unreachable; |
|
| 220 | + | @assert.ok18 |
|
| 221 | + | call w32 %34 $catchValue(%0, 1); |
|
| 222 | + | br.eq w32 %34 2 @assert.ok20 @assert.fail19; |
|
| 223 | + | @assert.fail19 |
|
| 224 | + | unreachable; |
|
| 225 | + | @assert.ok20 |
|
| 226 | + | load w32 %35 %0 0; |
|
| 227 | + | ret %35; |
|
| 228 | + | } |
test/tests/static.local.names.rad
added
+25 -0
| 1 | + | //! returns: 42 |
|
| 2 | + | ||
| 3 | + | /// Increment the first function's persistent counter. |
|
| 4 | + | fn left() -> i32 { |
|
| 5 | + | static VALUE: i32 = 9; |
|
| 6 | + | constant STEP: i32 = 1; |
|
| 7 | + | set VALUE += STEP; |
|
| 8 | + | return VALUE; |
|
| 9 | + | } |
|
| 10 | + | ||
| 11 | + | /// Increment the second function's persistent counter. |
|
| 12 | + | fn right() -> i32 { |
|
| 13 | + | static VALUE: i32 = 30; |
|
| 14 | + | set VALUE += 1; |
|
| 15 | + | return VALUE; |
|
| 16 | + | } |
|
| 17 | + | ||
| 18 | + | @default fn main() -> i32 { |
|
| 19 | + | assert left() == 10; |
|
| 20 | + | let first = left(); |
|
| 21 | + | let second = right(); |
|
| 22 | + | assert first == 11; |
|
| 23 | + | assert second == 31; |
|
| 24 | + | return first + second; |
|
| 25 | + | } |
test/tests/static.local.names.ril
added
+56 -0
| 1 | + | data mut $left$nominal$VALUE align 4 { |
|
| 2 | + | w32 9; |
|
| 3 | + | } |
|
| 4 | + | ||
| 5 | + | data $left$nominal$STEP align 4 { |
|
| 6 | + | w32 1; |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | data mut $right$nominal$VALUE align 4 { |
|
| 10 | + | w32 30; |
|
| 11 | + | } |
|
| 12 | + | ||
| 13 | + | fn w32 $left() { |
|
| 14 | + | @entry0 |
|
| 15 | + | copy %0 $left$nominal$VALUE; |
|
| 16 | + | sload w32 %1 %0 0; |
|
| 17 | + | add w32 %2 %1 1; |
|
| 18 | + | copy %3 $left$nominal$VALUE; |
|
| 19 | + | store w32 %2 %3 0; |
|
| 20 | + | copy %4 $left$nominal$VALUE; |
|
| 21 | + | sload w32 %5 %4 0; |
|
| 22 | + | ret %5; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | fn w32 $right() { |
|
| 26 | + | @entry0 |
|
| 27 | + | copy %0 $right$nominal$VALUE; |
|
| 28 | + | sload w32 %1 %0 0; |
|
| 29 | + | add w32 %2 %1 1; |
|
| 30 | + | copy %3 $right$nominal$VALUE; |
|
| 31 | + | store w32 %2 %3 0; |
|
| 32 | + | copy %4 $right$nominal$VALUE; |
|
| 33 | + | sload w32 %5 %4 0; |
|
| 34 | + | ret %5; |
|
| 35 | + | } |
|
| 36 | + | ||
| 37 | + | fn w32 $main() { |
|
| 38 | + | @entry0 |
|
| 39 | + | call w32 %0 $left(); |
|
| 40 | + | br.eq w32 %0 10 @assert.ok2 @assert.fail1; |
|
| 41 | + | @assert.fail1 |
|
| 42 | + | unreachable; |
|
| 43 | + | @assert.ok2 |
|
| 44 | + | call w32 %1 $left(); |
|
| 45 | + | call w32 %2 $right(); |
|
| 46 | + | br.eq w32 %1 11 @assert.ok4 @assert.fail3; |
|
| 47 | + | @assert.fail3 |
|
| 48 | + | unreachable; |
|
| 49 | + | @assert.ok4 |
|
| 50 | + | br.eq w32 %2 31 @assert.ok6 @assert.fail5; |
|
| 51 | + | @assert.fail5 |
|
| 52 | + | unreachable; |
|
| 53 | + | @assert.ok6 |
|
| 54 | + | add w32 %3 %1 %2; |
|
| 55 | + | ret %3; |
|
| 56 | + | } |
test/tests/static.optional.nil.rad
added
+24 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! Static nil values occupy their complete scalar, pointer, and aggregate layouts. |
|
| 3 | + | ||
| 4 | + | /// Payload with alignment and padding requirements. |
|
| 5 | + | record Payload: Copy { base: u64, count: u32 } |
|
| 6 | + | /// Adjacent fields must remain intact around a nil aggregate. |
|
| 7 | + | record Container: Copy { first: u64, item: ?Payload, last: u64 } |
|
| 8 | + | ||
| 9 | + | static VALUE: ?Payload = nil; |
|
| 10 | + | static NUMBER: ?u64 = nil; |
|
| 11 | + | static POINTER: ?*u64 = nil; |
|
| 12 | + | static ITEMS: [?Payload; 2] = [nil; 2]; |
|
| 13 | + | static BOX: Container = Container { first: 0x1122334455667788, item: nil, last: 0x8877665544332211 }; |
|
| 14 | + | ||
| 15 | + | /// Check complete nil layouts and subsequent mutable initialization. |
|
| 16 | + | @default fn main() -> i32 { |
|
| 17 | + | assert VALUE == nil and NUMBER == nil and POINTER == nil; |
|
| 18 | + | assert ITEMS[0] == nil and ITEMS[1] == nil; |
|
| 19 | + | assert BOX.item == nil and BOX.first == 0x1122334455667788 and BOX.last == 0x8877665544332211; |
|
| 20 | + | set VALUE = Payload { base: 42, count: 7 }; |
|
| 21 | + | let value = VALUE else panic "missing initialized payload"; |
|
| 22 | + | assert value.base == 42 and value.count == 7; |
|
| 23 | + | return 0; |
|
| 24 | + | } |