summaryrefslogtreecommitdiff
path: root/test/mono
diff options
context:
space:
mode:
Diffstat (limited to 'test/mono')
-rw-r--r--test/mono/.gitignore1
-rw-r--r--test/mono/addsubexist.sail75
-rw-r--r--test/mono/fnreduce.sail69
-rw-r--r--test/mono/test.ml1
-rwxr-xr-xtest/mono/test.sh44
-rw-r--r--test/mono/tests4
-rw-r--r--test/mono/union-exist.sail33
-rw-r--r--test/mono/varmatch.sail19
-rw-r--r--test/mono/vector.sail21
9 files changed, 267 insertions, 0 deletions
diff --git a/test/mono/.gitignore b/test/mono/.gitignore
new file mode 100644
index 00000000..2dd3daa3
--- /dev/null
+++ b/test/mono/.gitignore
@@ -0,0 +1 @@
+test-out \ No newline at end of file
diff --git a/test/mono/addsubexist.sail b/test/mono/addsubexist.sail
new file mode 100644
index 00000000..f59f596e
--- /dev/null
+++ b/test/mono/addsubexist.sail
@@ -0,0 +1,75 @@
+(* Adapted from hand-written ARM model *)
+
+default Order dec
+typedef boolean = bit
+typedef reg_size = bit[5]
+typedef reg_index = [|31|]
+
+val reg_size -> reg_index effect pure UInt_reg
+val unit -> unit effect pure (* probably not pure *) ReservedValue
+function forall Nat 'N. bit['N] NOT((bit['N]) x) = ~(x)
+val forall Nat 'M, Nat 'N. bit['M] -> bit['N] effect pure ZeroExtend
+val forall Nat 'N. (bit['N], bit['N], bit) -> (bit['N],bit[4]) effect pure AddWithCarry
+val forall Nat 'N, 'N IN {8,16,32,64}. (*broken? implicit<'N>*)unit -> bit['N] effect {rreg} rSP
+val forall Nat 'N, 'N IN {8,16,32,64}. ((*ditto implicit<'N>,*)reg_index) -> bit['N] effect {rreg}rX
+val (unit, bit[4]) -> unit effect {wreg} wPSTATE_NZCV
+val forall Nat 'N, 'N IN {32,64}. (unit, bit['N]) -> unit effect {rreg,wreg} wSP
+val forall Nat 'N, 'N IN {32,64}. (reg_index,bit['N]) -> unit effect {wreg} wX
+
+typedef ast = const union
+{
+ (exist 'R, 'R in {32,64}. (reg_index,reg_index,[:'R:],boolean,boolean,bit['R])) AddSubImmediate;
+}
+
+val ast -> unit effect {rreg,wreg(*,rmem,barr,eamem,wmv,escape*)} execute
+scattered function unit execute
+
+val bit[32] -> option<(ast)> effect pure decodeAddSubtractImmediate
+
+(* ADD/ADDS (immediate) *)
+(* SUB/SUBS (immediate) *)
+function option<(ast)> effect pure decodeAddSubtractImmediate ([sf]:[op]:[S]:0b10001:(bit[2]) shift:(bit[12]) imm12:(reg_size) Rn:(reg_size) Rd) =
+{
+ (reg_index) d := UInt_reg(Rd);
+ (reg_index) n := UInt_reg(Rn);
+ let (exist 'R, 'R in {32,64}. [:'R:]) 'datasize = if sf then 64 else 32 in {
+ (boolean) sub_op := op;
+ (boolean) setflags := S;
+ (bit['datasize]) imm := 0; (* ARM: uninitialized *)
+
+ switch shift {
+ case 0b00 -> imm := ZeroExtend(imm12)
+ case 0b01 -> imm := ZeroExtend(imm12 : (0b0 ^^ 12))
+ case [bitone,_] -> ReservedValue()
+ };
+
+ Some(AddSubImmediate( (d,n,datasize,sub_op,setflags,imm) ));
+}}
+
+function clause execute (AddSubImmediate('datasize)) = {
+switch datasize {
+case (d,n,datasize,sub_op,setflags,imm) ->
+{
+ (bit['datasize]) operand1 := if n == 31 then rSP() else rX(n);
+ (bit['datasize]) operand2 := imm;
+ (bit) carry_in := bitzero; (* ARM: uninitialized *)
+
+ if sub_op then {
+ operand2 := NOT(operand2);
+ carry_in := bitone;
+ }
+ else
+ carry_in := bitzero;
+
+ let (result,nzcv) = (AddWithCarry(operand1, operand2, carry_in)) in {
+
+ if setflags then
+ wPSTATE_NZCV() := nzcv;
+
+ if (d == 31 & ~(setflags)) then
+ wSP() := result
+ else
+ wX(d) := result;
+ }
+}}}
+end execute
diff --git a/test/mono/fnreduce.sail b/test/mono/fnreduce.sail
new file mode 100644
index 00000000..f39fb87d
--- /dev/null
+++ b/test/mono/fnreduce.sail
@@ -0,0 +1,69 @@
+(* Test constant propagation part of monomorphisation involving
+ functions. We should reduce a function application when the
+ arguments are suitable values, the function is pure and the result
+ is a value.
+ *)
+
+typedef AnEnum = enumerate { One; Two; Three }
+
+typedef EnumlikeUnion = const union { First; Second }
+
+typedef ProperUnion = const union {
+ (AnEnum) Stuff;
+ (EnumlikeUnion) Nonsense;
+}
+
+function AnEnum canReduce ((AnEnum) x) = {
+ switch (x) {
+ case One -> Two
+ case x -> x
+ }
+}
+
+function nat cannotReduce ((AnEnum) x) = {
+ let (nat) y = switch (x) { case One -> 1 case _ -> 5 } in
+ 2 + y
+}
+
+function AnEnum effect {rreg} fakeUnpure ((AnEnum) x) = {
+ switch (x) {
+ case One -> Two
+ case x -> x
+ }
+}
+
+function EnumlikeUnion canReduceUnion ((AnEnum) x) = {
+ switch (x) {
+ case One -> First
+ case _ -> Second
+ }
+}
+
+function ProperUnion canReduceUnion2 ((AnEnum) x) = {
+ switch (x) {
+ case One -> Nonsense(First)
+ case y -> Stuff(y)
+ }
+}
+
+(* FIXME LATER: once effect handling is in place we should get an error
+ because this isn't pure *)
+
+val AnEnum -> (AnEnum,nat,AnEnum,EnumlikeUnion,ProperUnion) effect pure test
+
+function test (x) = {
+ let a = canReduce(x) in
+ let b = cannotReduce(x) in
+ let c = fakeUnpure(x) in
+ let d = canReduceUnion(x) in
+ let e = canReduceUnion2(x) in
+ (a,b,c,d,e)
+}
+
+val unit -> bool effect pure run
+
+function run () = {
+ test(One) == (Two,3,Two,First,Nonsense(First)) &
+ test(Two) == (Two,7,Two,Second,Stuff(Two)) &
+ test(Three) == (Three,7,Three,Second,Stuff(Three))
+}
diff --git a/test/mono/test.ml b/test/mono/test.ml
new file mode 100644
index 00000000..f99abfb8
--- /dev/null
+++ b/test/mono/test.ml
@@ -0,0 +1 @@
+if Testout_embed_sequential.run() then print_endline "OK" else print_endline "Failed";;
diff --git a/test/mono/test.sh b/test/mono/test.sh
new file mode 100755
index 00000000..2a5aa80b
--- /dev/null
+++ b/test/mono/test.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SAILDIR="$DIR/../.."
+LEMDIR="$DIR/../../../lem"
+OUTDIR="$DIR/test-out"
+ZARITH="$LEMDIR/ocaml-lib/dependencies/zarith"
+
+if [ ! -d "$OUTDIR" ]; then
+ mkdir -- "$OUTDIR"
+fi
+cd "$OUTDIR"
+
+TESTONLY="$1"
+if [ -n "$TESTONLY" ]; then shift; fi
+
+LOG="$DIR/log"
+date > "$LOG"
+
+exec 3< "$DIR/tests"
+set +e
+
+while read -u 3 TEST ARGS; do
+ if [ -z "$TESTONLY" -o "$TEST" = "$TESTONLY" ]; then
+# echo "$TEST ocaml"
+# rm -f -- "$OUTDIR"/*
+# "$SAILDIR/sail" -ocaml "$SAILDIR/lib/prelude.sail" "$SAILDIR/lib/prelude_wrappers.sail" "$DIR/$TEST" -o "$OUTDIR/testout" $ARGS
+# cp -- "$SAILDIR"/src/gen_lib/sail_values.ml .
+# cp -- "$DIR"/test.ml .
+# ocamlc -I "$ZARITH" "$ZARITH/zarith.cma" -dllpath "$ZARITH" -I "$LEMDIR/ocaml-lib" "$LEMDIR/ocaml-lib/extract.cma" -I "$SAILDIR/src/_build/lem_interp" "$SAILDIR/src/_build/lem_interp/extract.cma" sail_values.ml testout.ml test.ml -o test
+# ./test
+
+ echo "$TEST lem - ocaml" | tee -a -- "$LOG"
+ rm -f -- "$OUTDIR"/*
+ "$SAILDIR/sail" -lem -lem_sequential -lem_mwords "$SAILDIR/lib/prelude.sail" "$SAILDIR/lib/prelude_wrappers.sail" "$DIR/$TEST".sail -o "$OUTDIR/testout" $ARGS $@ &>> "$LOG" && \
+ "$LEMDIR/bin/lem" -ocaml -lib "$SAILDIR/src/lem_interp" "$SAILDIR/src/gen_lib/sail_values.lem" "$SAILDIR/src/gen_lib/sail_operators_mwords.lem" "$SAILDIR/src/gen_lib/state.lem" testout_embed_types_sequential.lem testout_embed_sequential.lem -outdir "$OUTDIR" &>> "$LOG" && \
+ cp -- "$DIR"/test.ml "$OUTDIR" && \
+ ocamlc -I "$ZARITH" "$ZARITH/zarith.cma" -dllpath "$ZARITH" -I "$LEMDIR/ocaml-lib" "$LEMDIR/ocaml-lib/extract.cma" -I "$SAILDIR/src/_build/lem_interp" "$SAILDIR/src/_build/lem_interp/extract.cma" sail_values.ml sail_operators_mwords.ml state.ml testout_embed_types_sequential.ml testout_embed_sequential.ml test.ml -o test &>> "$LOG" && \
+ ./test |& tee -a -- "$LOG" || \
+ (echo "Failed:"; echo; tail -- "$LOG"; echo; echo)
+ fi
+done
diff --git a/test/mono/tests b/test/mono/tests
new file mode 100644
index 00000000..0825c686
--- /dev/null
+++ b/test/mono/tests
@@ -0,0 +1,4 @@
+fnreduce -mono-split fnreduce.sail:43:x
+varmatch -mono-split varmatch.sail:7:x
+vector -mono-split vector.sail:7:sel
+union-exist -mono-split union-exist.sail:9:v
diff --git a/test/mono/union-exist.sail b/test/mono/union-exist.sail
new file mode 100644
index 00000000..74ab429a
--- /dev/null
+++ b/test/mono/union-exist.sail
@@ -0,0 +1,33 @@
+default Order dec
+
+typedef myunion = const union {
+ (exist 'n, 'n in {8,16}. ([:'n:],bit['n])) MyConstr;
+}
+
+val bit[2] -> myunion effect pure make
+
+function make(v) =
+ (* Can't mention these below without running into exp/nexp parsing conflict! *)
+ let eight = 8 in let sixteen = 16 in
+ switch v {
+ case 0b00 -> MyConstr( ( eight, 0x12) )
+ case 0b01 -> MyConstr( (sixteen,0x1234) )
+ case 0b10 -> MyConstr( ( eight, 0x56) )
+ case 0b11 -> MyConstr( (sixteen,0x5678) )
+ }
+
+val myunion -> bit[32] effect pure use
+
+function use(MyConstr('n)) = {
+ switch n {
+ case (n,v) -> extz(v)
+ }
+}
+val unit -> bool effect pure run
+
+function run () = {
+ use(make(0b00)) == 0x00000012 &
+ use(make(0b01)) == 0x00001234 &
+ use(make(0b10)) == 0x00000056 &
+ use(make(0b11)) == 0x00005678
+}
diff --git a/test/mono/varmatch.sail b/test/mono/varmatch.sail
new file mode 100644
index 00000000..7d2b9b73
--- /dev/null
+++ b/test/mono/varmatch.sail
@@ -0,0 +1,19 @@
+(* Check that when we case split on a variable that the constant propagation
+ handles the default case correctly. *)
+
+typedef AnEnum = enumerate { One; Two; Three }
+
+function AnEnum foo((AnEnum) x) = {
+ switch (x) {
+ case One -> Two
+ case y -> y
+ }
+}
+
+val unit -> bool effect pure run
+
+function run () = {
+ foo(One) == Two &
+ foo(Two) == Two &
+ foo(Three) == Three
+}
diff --git a/test/mono/vector.sail b/test/mono/vector.sail
new file mode 100644
index 00000000..03f36da5
--- /dev/null
+++ b/test/mono/vector.sail
@@ -0,0 +1,21 @@
+(* Check case splitting on a vector *)
+
+default Order dec
+
+val bit[32] -> nat effect pure test
+
+function nat test((bit[2]) sel : (bit[30]) _) = {
+ switch (sel) {
+ case 0b00 -> 5
+ case 0b10 -> 1
+ case _ -> 0
+ }
+}
+
+val unit -> bool effect pure run
+
+function run () = {
+ test(0x0f353533) == 5 &
+ test(0x84534656) == 1 &
+ test(0xf3463903) == 0
+}