mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
Update skeleton
This commit is contained in:
10
README.md
10
README.md
@@ -17,11 +17,13 @@ cargo build --release # release build
|
||||
|
||||
```sh
|
||||
cargo run -- -h # print options
|
||||
cargo run -- -p examples/fibonacci.c # parse
|
||||
cargo run -- -i examples/fibonacci.c # irgen
|
||||
cargo run -- examples/fibonacci.c # compile
|
||||
cargo run -- -p examples/c/fibonacci.c # parse
|
||||
cargo run -- -i examples/c/fibonacci.c # irgen
|
||||
cargo run -- examples/c/fibonacci.c # compile
|
||||
|
||||
cargo run --release -- examples/fibonacci.c # compile with release build
|
||||
cargo run -- --irrun examples/c/fibonacci.c # interprets the IR
|
||||
|
||||
cargo run --release -- examples/c/fibonacci.c # compile with release build
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ fn compile_ir(
|
||||
SimplifyCfg::default().optimize(input);
|
||||
}
|
||||
|
||||
if matches.is_present("mem2erg") {
|
||||
if matches.is_present("mem2reg") {
|
||||
Mem2reg::default().optimize(input);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,12 @@ fn compile_ir(
|
||||
return;
|
||||
}
|
||||
|
||||
if matches.is_present("irrun") {
|
||||
let result = ir::interp(input, Vec::new()).unwrap();
|
||||
println!("[result] {:?}", result);
|
||||
return;
|
||||
}
|
||||
|
||||
let asm = ok_or_exit!(Asmgen::default().translate(input), 1);
|
||||
write(&asm, output).unwrap();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ name: kecc
|
||||
args:
|
||||
- parse:
|
||||
long: parse
|
||||
help: Parses the input file
|
||||
help: Parses the input C file
|
||||
- print:
|
||||
short: p
|
||||
long: print
|
||||
@@ -17,6 +17,9 @@ args:
|
||||
- irprint:
|
||||
long: irprint
|
||||
help: Prints the input IR AST
|
||||
- irrun:
|
||||
long: irrun
|
||||
help: Executes the input file
|
||||
- optimize:
|
||||
short: O
|
||||
long: optimize
|
||||
|
||||
5
examples/asm/simple.c
Normal file
5
examples/asm/simple.c
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int x = 1;
|
||||
return 1;
|
||||
}
|
||||
16
examples/ir/alignof.ir
Normal file
16
examples/ir/alignof.ir
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:u64 = typecast 4:i32 to u64
|
||||
%b0:i1:u1 = cmp eq 4:u64 %b0:i0:u64
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
101
examples/ir/array.ir
Normal file
101
examples/ir/array.ir
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:[5 x i32]:a
|
||||
%l1:i32:len
|
||||
%l2:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 5:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
%b2:i1:i32 = load %l1:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b3:i1:i32 = load %l2:*i32
|
||||
%b3:i2:i64 = typecast %b3:i1:i32 to i64
|
||||
%b3:i3:i64 = mul %b3:i2:i64 4:i64
|
||||
%b3:i4:*i32 = getelementptr %b3:i0 offset %b3:i3
|
||||
%b3:i5:i32 = load %l2:*i32
|
||||
%b3:i6:unit = store %b3:i5:i32 %b3:i4:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l2:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:*i32 = getelementptr %l0 offset 0
|
||||
%b5:i2:i32 = call @sum(%b5:i0:i32, %b5:i1:*i32)
|
||||
%b5:i3:u1 = cmp eq %b5:i2:i32 10:i32
|
||||
%b5:i4:i32 = typecast %b5:i3:u1 to i32
|
||||
ret %b5:i4:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
|
||||
fun i32 @sum {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:len
|
||||
%l1:*i32:p
|
||||
%l2:i32:result
|
||||
%l3:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:*i32 %l1:**i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:i32 = load %l0:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:*i32 = load %l1:**i32
|
||||
%b3:i2:i32 = load %l3:*i32
|
||||
%b3:i3:i64 = typecast %b3:i2:i32 to i64
|
||||
%b3:i4:i64 = mul %b3:i3:i64 4:i64
|
||||
%b3:i5:*i32 = getelementptr %b3:i1 offset %b3:i4
|
||||
%b3:i6:i32 = load %b3:i5:*i32
|
||||
%b3:i7:i32 = add %b3:i0:i32 %b3:i6:i32
|
||||
%b3:i8:unit = store %b3:i7:i32 %l2:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l2:*i32
|
||||
ret %b5:i0:i32
|
||||
|
||||
block b6:
|
||||
ret undef:i32
|
||||
}
|
||||
107
examples/ir/array2.ir
Normal file
107
examples/ir/array2.ir
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
fun unit @init {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:row
|
||||
%l1:i32:col
|
||||
%l2:*[5 x i32]:a
|
||||
%l3:i32:i
|
||||
%l4:i32:j
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:*[5 x i32] %l2:**[5 x i32]
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:i32 = load %l0:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
j b6()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
ret unit:unit
|
||||
|
||||
block b6:
|
||||
%b6:i0:unit = store 0:i32 %l4:*i32
|
||||
j b7()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l4:*i32
|
||||
%b7:i1:i32 = load %l1:*i32
|
||||
%b7:i2:u1 = cmp lt %b7:i0:i32 %b7:i1:i32
|
||||
br %b7:i2:u1, b8(), b10()
|
||||
|
||||
block b8:
|
||||
%b8:i0:*[5 x i32] = load %l2:**[5 x i32]
|
||||
%b8:i1:i32 = load %l3:*i32
|
||||
%b8:i2:i64 = typecast %b8:i1:i32 to i64
|
||||
%b8:i3:i64 = mul %b8:i2:i64 20:i64
|
||||
%b8:i4:*[5 x i32] = getelementptr %b8:i0 offset %b8:i3
|
||||
%b8:i5:*i32 = getelementptr %b8:i4 offset 0
|
||||
%b8:i6:i32 = load %l4:*i32
|
||||
%b8:i7:i64 = typecast %b8:i6:i32 to i64
|
||||
%b8:i8:i64 = mul %b8:i7:i64 4:i64
|
||||
%b8:i9:*i32 = getelementptr %b8:i5 offset %b8:i8
|
||||
%b8:i10:i32 = load %l3:*i32
|
||||
%b8:i11:i32 = load %l4:*i32
|
||||
%b8:i12:i32 = mul %b8:i10:i32 %b8:i11:i32
|
||||
%b8:i13:unit = store %b8:i12:i32 %b8:i9:*i32
|
||||
j b9()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l4:*i32
|
||||
%b9:i1:i32 = add %b9:i0:i32 1:i32
|
||||
%b9:i2:unit = store %b9:i1:i32 %l4:*i32
|
||||
j b7()
|
||||
|
||||
block b10:
|
||||
j b4()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:[4 x [5 x i32]]:a
|
||||
%l1:i32:row
|
||||
%l2:i32:col
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 4:i32 %l1:*i32
|
||||
%b0:i1:unit = store 5:i32 %l2:*i32
|
||||
%b0:i2:i32 = load %l1:*i32
|
||||
%b0:i3:i32 = load %l2:*i32
|
||||
%b0:i4:*[5 x i32] = getelementptr %l0 offset 0
|
||||
%b0:i5:unit = call @init(%b0:i2:i32, %b0:i3:i32, %b0:i4:*[5 x i32])
|
||||
%b0:i6:*[5 x i32] = getelementptr %l0 offset 0
|
||||
%b0:i7:i64 = typecast 2:i32 to i64
|
||||
%b0:i8:i64 = mul %b0:i7:i64 20:i64
|
||||
%b0:i9:*[5 x i32] = getelementptr %b0:i6 offset %b0:i8
|
||||
%b0:i10:*i32 = getelementptr %b0:i9 offset 0
|
||||
%b0:i11:i64 = typecast 3:i32 to i64
|
||||
%b0:i12:i64 = mul %b0:i11:i64 4:i64
|
||||
%b0:i13:*i32 = getelementptr %b0:i10 offset %b0:i12
|
||||
%b0:i14:i32 = load %b0:i13:*i32
|
||||
%b0:i15:u1 = cmp eq %b0:i14:i32 6:i32
|
||||
%b0:i16:i32 = typecast %b0:i15:u1 to i32
|
||||
ret %b0:i16:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
65
examples/ir/array3.ir
Normal file
65
examples/ir/array3.ir
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
fun *i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:*i32:a
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:*i32 %l0:**i32
|
||||
%b0:i1:*i32 = load %l0:**i32
|
||||
ret %b0:i1:*i32
|
||||
|
||||
block b1:
|
||||
ret undef:*i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:[10 x i32]:a
|
||||
%l1:i32:i
|
||||
|
||||
block b0:
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l1:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l1:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 10:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b3:i1:*i32 = call @foo(%b3:i0:*i32)
|
||||
%b3:i2:i32 = load %l1:*i32
|
||||
%b3:i3:i64 = typecast %b3:i2:i32 to i64
|
||||
%b3:i4:i64 = mul %b3:i3:i64 4:i64
|
||||
%b3:i5:*i32 = getelementptr %b3:i1 offset %b3:i4
|
||||
%b3:i6:i32 = load %l1:*i32
|
||||
%b3:i7:unit = store %b3:i6:i32 %b3:i5:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l1:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b5:i1:i64 = typecast 5:i32 to i64
|
||||
%b5:i2:i64 = mul %b5:i1:i64 4:i64
|
||||
%b5:i3:*i32 = getelementptr %b5:i0 offset %b5:i2
|
||||
%b5:i4:i32 = load %b5:i3:*i32
|
||||
%b5:i5:u1 = cmp eq %b5:i4:i32 5:i32
|
||||
%b5:i6:i32 = typecast %b5:i5:u1 to i32
|
||||
ret %b5:i6:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
51
examples/ir/array4.ir
Normal file
51
examples/ir/array4.ir
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:[10 x i32]:a
|
||||
%l1:*i32:p
|
||||
%l2:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b0:i1:unit = store %b0:i0:*i32 %l1:**i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 10:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:*i32 = load %l1:**i32
|
||||
%b3:i1:i64 = mul 1:i64 4:i64
|
||||
%b3:i2:*i32 = getelementptr %b3:i0 offset %b3:i1
|
||||
%b3:i3:unit = store %b3:i2:*i32 %l1:**i32
|
||||
%b3:i4:i32 = load %l2:*i32
|
||||
%b3:i5:unit = store %b3:i4:i32 %b3:i0:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l2:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b5:i1:i64 = typecast 5:i32 to i64
|
||||
%b5:i2:i64 = mul %b5:i1:i64 4:i64
|
||||
%b5:i3:*i32 = getelementptr %b5:i0 offset %b5:i2
|
||||
%b5:i4:i32 = load %b5:i3:*i32
|
||||
%b5:i5:u1 = cmp eq %b5:i4:i32 5:i32
|
||||
%b5:i6:i32 = typecast %b5:i5:u1 to i32
|
||||
ret %b5:i6:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
77
examples/ir/array5.ir
Normal file
77
examples/ir/array5.ir
Normal file
@@ -0,0 +1,77 @@
|
||||
var [5 x i32] @g_a = {1, 2, 3}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:init
|
||||
%l1:[5 x i32]:a
|
||||
%l2:i32:sum
|
||||
%l3:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 1:i32 %l0:*i32
|
||||
%b0:i1:*i32 = getelementptr %l1 offset 0
|
||||
%b0:i2:i64 = mul 0:i64 4:i64
|
||||
%b0:i3:*i32 = getelementptr %b0:i1 offset %b0:i2
|
||||
%b0:i4:i32 = load %l0:*i32
|
||||
%b0:i5:unit = store %b0:i4:i32 %b0:i3:*i32
|
||||
%b0:i6:i64 = mul 1:i64 4:i64
|
||||
%b0:i7:*i32 = getelementptr %b0:i1 offset %b0:i6
|
||||
%b0:i8:unit = store 2:i32 %b0:i7:*i32
|
||||
%b0:i9:i64 = mul 2:i64 4:i64
|
||||
%b0:i10:*i32 = getelementptr %b0:i1 offset %b0:i9
|
||||
%b0:i11:unit = store 3:i32 %b0:i10:*i32
|
||||
%b0:i12:i64 = mul 3:i64 4:i64
|
||||
%b0:i13:*i32 = getelementptr %b0:i1 offset %b0:i12
|
||||
%b0:i14:unit = store 4:i32 %b0:i13:*i32
|
||||
%b0:i15:i64 = mul 4:i64 4:i64
|
||||
%b0:i16:*i32 = getelementptr %b0:i1 offset %b0:i15
|
||||
%b0:i17:i32 = minus 5:i32
|
||||
%b0:i18:unit = store %b0:i17:i32 %b0:i16:*i32
|
||||
%b0:i19:unit = store 0:i32 %l2:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 5:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:*i32 = getelementptr %l1 offset 0
|
||||
%b3:i2:i32 = load %l3:*i32
|
||||
%b3:i3:i64 = typecast %b3:i2:i32 to i64
|
||||
%b3:i4:i64 = mul %b3:i3:i64 4:i64
|
||||
%b3:i5:*i32 = getelementptr %b3:i1 offset %b3:i4
|
||||
%b3:i6:i32 = load %b3:i5:*i32
|
||||
%b3:i7:i32 = add %b3:i0:i32 %b3:i6:i32
|
||||
%b3:i8:unit = store %b3:i7:i32 %l2:*i32
|
||||
%b3:i9:i32 = load %l2:*i32
|
||||
%b3:i10:*i32 = getelementptr @g_a offset 0
|
||||
%b3:i11:i32 = load %l3:*i32
|
||||
%b3:i12:i64 = typecast %b3:i11:i32 to i64
|
||||
%b3:i13:i64 = mul %b3:i12:i64 4:i64
|
||||
%b3:i14:*i32 = getelementptr %b3:i10 offset %b3:i13
|
||||
%b3:i15:i32 = load %b3:i14:*i32
|
||||
%b3:i16:i32 = add %b3:i9:i32 %b3:i15:i32
|
||||
%b3:i17:unit = store %b3:i16:i32 %l2:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l2:*i32
|
||||
ret %b5:i0:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
66
examples/ir/bar.ir
Normal file
66
examples/ir/bar.ir
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
fun i32 @bar {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
%l1:i32:y
|
||||
%l2:i32:z
|
||||
%l3:i32:arith_mean
|
||||
%l4:i32:ugly_mean
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:i32 %l2:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:i32 = load %l1:*i32
|
||||
%b0:i5:i32 = add %b0:i3:i32 %b0:i4:i32
|
||||
%b0:i6:i32 = load %l2:*i32
|
||||
%b0:i7:i32 = add %b0:i5:i32 %b0:i6:i32
|
||||
%b0:i8:i32 = div %b0:i7:i32 3:i32
|
||||
%b0:i9:unit = store %b0:i8:i32 %l3:*i32
|
||||
%b0:i10:i32 = load %l0:*i32
|
||||
%b0:i11:i32 = load %l1:*i32
|
||||
%b0:i12:i32 = add %b0:i10:i32 %b0:i11:i32
|
||||
%b0:i13:i32 = div %b0:i12:i32 2:i32
|
||||
%b0:i14:i32 = mul %b0:i13:i32 2:i32
|
||||
%b0:i15:i32 = load %l2:*i32
|
||||
%b0:i16:i32 = add %b0:i14:i32 %b0:i15:i32
|
||||
%b0:i17:i32 = div %b0:i16:i32 3:i32
|
||||
%b0:i18:unit = store %b0:i17:i32 %l4:*i32
|
||||
%b0:i19:i32 = load %l0:*i32
|
||||
%b0:i20:i32 = load %l1:*i32
|
||||
%b0:i21:u1 = cmp eq %b0:i19:i32 %b0:i20:i32
|
||||
br %b0:i21:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
ret %b2:i0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
j b3()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret 1:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
150
examples/ir/bitwise.ir
Normal file
150
examples/ir/bitwise.ir
Normal file
@@ -0,0 +1,150 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:u8:a
|
||||
%l1:u8:b
|
||||
%l2:u8:c
|
||||
%l3:u8:d
|
||||
%l4:u8:e
|
||||
%l5:u8:f
|
||||
%l6:u8:g
|
||||
%l7:u8:h
|
||||
%l8:u8:i
|
||||
%l9:u1:t0
|
||||
%l10:u1:t1
|
||||
%l11:u1:t2
|
||||
%l12:u1:t3
|
||||
%l13:u1:t4
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = minus 1:i32
|
||||
%b0:i1:u8 = typecast %b0:i0:i32 to u8
|
||||
%b0:i2:unit = store %b0:i1:u8 %l0:*u8
|
||||
%b0:i3:i32 = minus 128:i32
|
||||
%b0:i4:u8 = typecast %b0:i3:i32 to u8
|
||||
%b0:i5:unit = store %b0:i4:u8 %l1:*u8
|
||||
%b0:i6:u8 = typecast 127:i32 to u8
|
||||
%b0:i7:unit = store %b0:i6:u8 %l2:*u8
|
||||
%b0:i8:u8 = load %l1:*u8
|
||||
%b0:i9:u8 = load %l0:*u8
|
||||
%b0:i10:i32 = typecast %b0:i8:u8 to i32
|
||||
%b0:i11:i32 = typecast %b0:i9:u8 to i32
|
||||
%b0:i12:i32 = or %b0:i10:i32 %b0:i11:i32
|
||||
%b0:i13:u8 = typecast %b0:i12:i32 to u8
|
||||
%b0:i14:unit = store %b0:i13:u8 %l3:*u8
|
||||
%b0:i15:u8 = load %l1:*u8
|
||||
%b0:i16:u8 = load %l0:*u8
|
||||
%b0:i17:i32 = typecast %b0:i15:u8 to i32
|
||||
%b0:i18:i32 = typecast %b0:i16:u8 to i32
|
||||
%b0:i19:i32 = and %b0:i17:i32 %b0:i18:i32
|
||||
%b0:i20:u8 = typecast %b0:i19:i32 to u8
|
||||
%b0:i21:unit = store %b0:i20:u8 %l4:*u8
|
||||
%b0:i22:u8 = load %l1:*u8
|
||||
%b0:i23:u8 = load %l2:*u8
|
||||
%b0:i24:i32 = typecast %b0:i22:u8 to i32
|
||||
%b0:i25:i32 = typecast %b0:i23:u8 to i32
|
||||
%b0:i26:i32 = and %b0:i24:i32 %b0:i25:i32
|
||||
%b0:i27:u8 = typecast %b0:i26:i32 to u8
|
||||
%b0:i28:unit = store %b0:i27:u8 %l5:*u8
|
||||
%b0:i29:u8 = load %l1:*u8
|
||||
%b0:i30:u8 = load %l2:*u8
|
||||
%b0:i31:i32 = typecast %b0:i29:u8 to i32
|
||||
%b0:i32:i32 = typecast %b0:i30:u8 to i32
|
||||
%b0:i33:i32 = or %b0:i31:i32 %b0:i32:i32
|
||||
%b0:i34:u8 = typecast %b0:i33:i32 to u8
|
||||
%b0:i35:unit = store %b0:i34:u8 %l6:*u8
|
||||
%b0:i36:i32 = minus 1:i32
|
||||
%b0:i37:i32 = minus 1:i32
|
||||
%b0:i38:i32 = xor %b0:i36:i32 %b0:i37:i32
|
||||
%b0:i39:u8 = typecast %b0:i38:i32 to u8
|
||||
%b0:i40:unit = store %b0:i39:u8 %l7:*u8
|
||||
%b0:i41:i32 = minus 1:i32
|
||||
%b0:i42:i32 = xor %b0:i41:i32 0:i32
|
||||
%b0:i43:u8 = typecast %b0:i42:i32 to u8
|
||||
%b0:i44:unit = store %b0:i43:u8 %l8:*u8
|
||||
%b0:i45:u8 = load %l3:*u8
|
||||
%b0:i46:i32 = typecast %b0:i45:u8 to i32
|
||||
%b0:i47:u1 = cmp eq %b0:i46:i32 255:i32
|
||||
br %b0:i47:u1, b13(), b14()
|
||||
|
||||
block b1:
|
||||
%b1:i0:u8 = load %l8:*u8
|
||||
%b1:i1:i32 = typecast %b1:i0:u8 to i32
|
||||
%b1:i2:u1 = cmp eq %b1:i1:i32 255:i32
|
||||
%b1:i3:unit = store %b1:i2:u1 %l13:*u1
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:unit = store 0:u1 %l13:*u1
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:u1 = load %l13:*u1
|
||||
%b3:i1:i32 = typecast %b3:i0:u1 to i32
|
||||
ret %b3:i1:i32
|
||||
|
||||
block b4:
|
||||
%b4:i0:u8 = load %l7:*u8
|
||||
%b4:i1:i32 = typecast %b4:i0:u8 to i32
|
||||
%b4:i2:u1 = cmp eq %b4:i1:i32 0:i32
|
||||
%b4:i3:unit = store %b4:i2:u1 %l12:*u1
|
||||
j b6()
|
||||
|
||||
block b5:
|
||||
%b5:i0:unit = store 0:u1 %l12:*u1
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:u1 = load %l12:*u1
|
||||
br %b6:i0:u1, b1(), b2()
|
||||
|
||||
block b7:
|
||||
%b7:i0:u8 = load %l6:*u8
|
||||
%b7:i1:i32 = typecast %b7:i0:u8 to i32
|
||||
%b7:i2:u1 = cmp eq %b7:i1:i32 255:i32
|
||||
%b7:i3:unit = store %b7:i2:u1 %l11:*u1
|
||||
j b9()
|
||||
|
||||
block b8:
|
||||
%b8:i0:unit = store 0:u1 %l11:*u1
|
||||
j b9()
|
||||
|
||||
block b9:
|
||||
%b9:i0:u1 = load %l11:*u1
|
||||
br %b9:i0:u1, b4(), b5()
|
||||
|
||||
block b10:
|
||||
%b10:i0:u8 = load %l5:*u8
|
||||
%b10:i1:i32 = typecast %b10:i0:u8 to i32
|
||||
%b10:i2:u1 = cmp eq %b10:i1:i32 0:i32
|
||||
%b10:i3:unit = store %b10:i2:u1 %l10:*u1
|
||||
j b12()
|
||||
|
||||
block b11:
|
||||
%b11:i0:unit = store 0:u1 %l10:*u1
|
||||
j b12()
|
||||
|
||||
block b12:
|
||||
%b12:i0:u1 = load %l10:*u1
|
||||
br %b12:i0:u1, b7(), b8()
|
||||
|
||||
block b13:
|
||||
%b13:i0:u8 = load %l4:*u8
|
||||
%b13:i1:i32 = typecast %b13:i0:u8 to i32
|
||||
%b13:i2:u1 = cmp eq %b13:i1:i32 128:i32
|
||||
%b13:i3:unit = store %b13:i2:u1 %l9:*u1
|
||||
j b15()
|
||||
|
||||
block b14:
|
||||
%b14:i0:unit = store 0:u1 %l9:*u1
|
||||
j b15()
|
||||
|
||||
block b15:
|
||||
%b15:i0:u1 = load %l9:*u1
|
||||
br %b15:i0:u1, b10(), b11()
|
||||
|
||||
block b16:
|
||||
ret 0:i32
|
||||
}
|
||||
106
examples/ir/cmp.ir
Normal file
106
examples/ir/cmp.ir
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
fun i32 @char_greater_than {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i8:i
|
||||
%l1:u8:j
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i8 %l0:*i8
|
||||
%b0:i1:unit = store %b0:p1:u8 %l1:*u8
|
||||
%b0:i2:i8 = load %l0:*i8
|
||||
%b0:i3:u8 = load %l1:*u8
|
||||
%b0:i4:i32 = typecast %b0:i2:i8 to i32
|
||||
%b0:i5:i32 = typecast %b0:i3:u8 to i32
|
||||
%b0:i6:u1 = cmp gt %b0:i4:i32 %b0:i5:i32
|
||||
br %b0:i6:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
ret 1:i32
|
||||
|
||||
block b2:
|
||||
ret 0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
j b3()
|
||||
}
|
||||
|
||||
fun i32 @int_greater_than {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:u32:j
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:u32 %l1:*u32
|
||||
%b0:i2:i32 = load %l0:*i32
|
||||
%b0:i3:u32 = load %l1:*u32
|
||||
%b0:i4:u32 = typecast %b0:i2:i32 to u32
|
||||
%b0:i5:u1 = cmp gt %b0:i4:u32 %b0:i3:u32
|
||||
br %b0:i5:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
ret 1:i32
|
||||
|
||||
block b2:
|
||||
ret 0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
j b3()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:r1
|
||||
%l1:i32:r2
|
||||
%l2:u1:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = minus 1:i32
|
||||
%b0:i1:u32 = typecast 1:i32 to u32
|
||||
%b0:i2:i32 = call @int_greater_than(%b0:i0:i32, %b0:i1:u32)
|
||||
%b0:i3:unit = store %b0:i2:i32 %l0:*i32
|
||||
%b0:i4:i32 = minus 1:i32
|
||||
%b0:i5:i8 = typecast %b0:i4:i32 to i8
|
||||
%b0:i6:u8 = typecast 1:i32 to u8
|
||||
%b0:i7:i32 = call @char_greater_than(%b0:i5:i8, %b0:i6:u8)
|
||||
%b0:i8:unit = store %b0:i7:i32 %l1:*i32
|
||||
%b0:i9:i32 = load %l0:*i32
|
||||
%b0:i10:u1 = cmp eq %b0:i9:i32 1:i32
|
||||
br %b0:i10:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
%b1:i1:u1 = cmp eq %b1:i0:i32 0:i32
|
||||
%b1:i2:unit = store %b1:i1:u1 %l2:*u1
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:unit = store 0:u1 %l2:*u1
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:u1 = load %l2:*u1
|
||||
%b3:i1:i32 = typecast %b3:i0:u1 to i32
|
||||
ret %b3:i1:i32
|
||||
|
||||
block b4:
|
||||
ret 0:i32
|
||||
}
|
||||
24
examples/ir/comma.ir
Normal file
24
examples/ir/comma.ir
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:y
|
||||
%l1:i32:x
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 2:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:i32 = add %b0:i1:i32 2:i32
|
||||
%b0:i3:unit = store %b0:i2:i32 %l0:*i32
|
||||
%b0:i4:i32 = load %l0:*i32
|
||||
%b0:i5:i32 = add %b0:i4:i32 3:i32
|
||||
%b0:i6:unit = store %b0:i5:i32 %l1:*i32
|
||||
%b0:i7:i32 = load %l1:*i32
|
||||
%b0:i8:u1 = cmp eq %b0:i7:i32 7:i32
|
||||
%b0:i9:i32 = typecast %b0:i8:u1 to i32
|
||||
ret %b0:i9:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
29202
examples/ir/complete_cond.ir
Normal file
29202
examples/ir/complete_cond.ir
Normal file
File diff suppressed because it is too large
Load Diff
34
examples/ir/cond.ir
Normal file
34
examples/ir/cond.ir
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:y
|
||||
%l1:i32:x
|
||||
%l2:i32:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 1:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:i32 = load %l1:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:u1 = cmp eq %b0:i2:i32 %b0:i3:i32
|
||||
br %b0:i4:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 2:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:unit = store 5:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:u1 = cmp eq %b3:i0:i32 5:i32
|
||||
%b3:i2:i32 = typecast %b3:i1:u1 to i32
|
||||
ret %b3:i2:i32
|
||||
|
||||
block b4:
|
||||
ret 0:i32
|
||||
}
|
||||
121
examples/ir/cond_and_loop.ir
Normal file
121
examples/ir/cond_and_loop.ir
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:i32:p
|
||||
%l2:i32:q
|
||||
%l3:i32:r
|
||||
%l4:i32:t0
|
||||
%l5:i32:t1
|
||||
%l6:i32:t2
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 2:i32 %l1:*i32
|
||||
%b0:i1:unit = store 5:i32 %l2:*i32
|
||||
%b0:i2:u1 = cmp ne 0:i32 0:i32
|
||||
br %b0:i2:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
%b1:i1:i32 = load %l2:*i32
|
||||
%b1:i2:u1 = cmp gt %b1:i0:i32 %b1:i1:i32
|
||||
br %b1:i2:u1, b4(), b5()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l1:*i32
|
||||
%b2:i1:i32 = load %l2:*i32
|
||||
%b2:i2:i32 = add %b2:i0:i32 %b2:i1:i32
|
||||
%b2:i3:unit = store %b2:i2:i32 %l5:*i32
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l5:*i32
|
||||
%b3:i1:unit = store %b3:i0:i32 %l3:*i32
|
||||
j b7()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:i32 = sub %b4:i0:i32 2:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l1:*i32
|
||||
%b4:i3:unit = store %b4:i1:i32 %l4:*i32
|
||||
j b6()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:i32 = add %b5:i0:i32 2:i32
|
||||
%b5:i2:unit = store %b5:i1:i32 %l1:*i32
|
||||
%b5:i3:unit = store %b5:i1:i32 %l4:*i32
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l4:*i32
|
||||
%b6:i1:unit = store %b6:i0:i32 %l5:*i32
|
||||
j b3()
|
||||
|
||||
block b7:
|
||||
%b7:i0:unit = store 0:i32 %l0:*i32
|
||||
j b8()
|
||||
|
||||
block b8:
|
||||
%b8:i0:i32 = load %l0:*i32
|
||||
%b8:i1:u1 = cmp lt %b8:i0:i32 11:i32
|
||||
br %b8:i1:u1, b9(), b11()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l0:*i32
|
||||
%b9:i1:i32 = mod %b9:i0:i32 2:i32
|
||||
%b9:i2:u1 = cmp ne %b9:i1:i32 0:i32
|
||||
br %b9:i2:u1, b12(), b13()
|
||||
|
||||
block b10:
|
||||
%b10:i0:i32 = load %l0:*i32
|
||||
%b10:i1:i32 = mod %b10:i0:i32 2:i32
|
||||
%b10:i2:u1 = cmp ne %b10:i1:i32 0:i32
|
||||
br %b10:i2:u1, b15(), b16()
|
||||
|
||||
block b11:
|
||||
%b11:i0:i32 = load %l1:*i32
|
||||
%b11:i1:u1 = cmp eq %b11:i0:i32 34:i32
|
||||
%b11:i2:i32 = typecast %b11:i1:u1 to i32
|
||||
ret %b11:i2:i32
|
||||
|
||||
block b12:
|
||||
%b12:i0:i32 = load %l1:*i32
|
||||
%b12:i1:i32 = load %l2:*i32
|
||||
%b12:i2:i32 = add %b12:i0:i32 %b12:i1:i32
|
||||
%b12:i3:unit = store %b12:i2:i32 %l1:*i32
|
||||
j b14()
|
||||
|
||||
block b13:
|
||||
%b13:i0:i32 = load %l1:*i32
|
||||
%b13:i1:i32 = load %l3:*i32
|
||||
%b13:i2:i32 = add %b13:i0:i32 %b13:i1:i32
|
||||
%b13:i3:unit = store %b13:i2:i32 %l1:*i32
|
||||
j b14()
|
||||
|
||||
block b14:
|
||||
j b10()
|
||||
|
||||
block b15:
|
||||
%b15:i0:i32 = load %l0:*i32
|
||||
%b15:i1:i32 = add %b15:i0:i32 2:i32
|
||||
%b15:i2:unit = store %b15:i1:i32 %l0:*i32
|
||||
%b15:i3:unit = store %b15:i1:i32 %l6:*i32
|
||||
j b17()
|
||||
|
||||
block b16:
|
||||
%b16:i0:i32 = load %l0:*i32
|
||||
%b16:i1:i32 = add %b16:i0:i32 1:i32
|
||||
%b16:i2:unit = store %b16:i1:i32 %l0:*i32
|
||||
%b16:i3:unit = store %b16:i1:i32 %l6:*i32
|
||||
j b17()
|
||||
|
||||
block b17:
|
||||
%b17:i0:i32 = load %l6:*i32
|
||||
j b8()
|
||||
|
||||
block b18:
|
||||
ret 0:i32
|
||||
}
|
||||
52
examples/ir/fib2.ir
Normal file
52
examples/ir/fib2.ir
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:u1 = cmp lt %b0:i1:i32 2:i32
|
||||
br %b0:i2:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l0:*i32
|
||||
%b3:i1:i32 = sub %b3:i0:i32 2:i32
|
||||
%b3:i2:i32 = call @fibonacci(%b3:i1:i32)
|
||||
%b3:i3:i32 = load %l0:*i32
|
||||
%b3:i4:i32 = sub %b3:i3:i32 1:i32
|
||||
%b3:i5:i32 = call @fibonacci(%b3:i4:i32)
|
||||
%b3:i6:i32 = add %b3:i2:i32 %b3:i5:i32
|
||||
ret %b3:i6:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @fibonacci(9:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 34:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
84
examples/ir/fib3.ir
Normal file
84
examples/ir/fib3.ir
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
%l1:i32:i
|
||||
%l2:i32:t1
|
||||
%l3:i32:t2
|
||||
%l4:i32:next_term
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
%b0:i3:unit = store 1:i32 %l3:*i32
|
||||
%b0:i4:unit = store 0:i32 %l4:*i32
|
||||
%b0:i5:i32 = load %l0:*i32
|
||||
%b0:i6:u1 = cmp lt %b0:i5:i32 2:i32
|
||||
br %b0:i6:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
j b5()
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
%b5:i0:unit = store 1:i32 %l1:*i32
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l1:*i32
|
||||
%b6:i1:i32 = load %l0:*i32
|
||||
%b6:i2:u1 = cmp lt %b6:i0:i32 %b6:i1:i32
|
||||
br %b6:i2:u1, b7(), b9()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l2:*i32
|
||||
%b7:i1:i32 = load %l3:*i32
|
||||
%b7:i2:i32 = add %b7:i0:i32 %b7:i1:i32
|
||||
%b7:i3:unit = store %b7:i2:i32 %l4:*i32
|
||||
%b7:i4:i32 = load %l3:*i32
|
||||
%b7:i5:unit = store %b7:i4:i32 %l2:*i32
|
||||
%b7:i6:i32 = load %l4:*i32
|
||||
%b7:i7:unit = store %b7:i6:i32 %l3:*i32
|
||||
j b8()
|
||||
|
||||
block b8:
|
||||
%b8:i0:i32 = load %l1:*i32
|
||||
%b8:i1:i32 = add %b8:i0:i32 1:i32
|
||||
%b8:i2:unit = store %b8:i1:i32 %l1:*i32
|
||||
j b6()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l3:*i32
|
||||
ret %b9:i0:i32
|
||||
|
||||
block b10:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @fibonacci(9:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 34:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
78
examples/ir/fib4.ir
Normal file
78
examples/ir/fib4.ir
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
%l1:i32:i
|
||||
%l2:i32:t1
|
||||
%l3:i32:t2
|
||||
%l4:i32:next_term
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
%b0:i3:unit = store 1:i32 %l3:*i32
|
||||
%b0:i4:unit = store 0:i32 %l4:*i32
|
||||
%b0:i5:i32 = load %l0:*i32
|
||||
%b0:i6:u1 = cmp lt %b0:i5:i32 2:i32
|
||||
br %b0:i6:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:unit = store 1:i32 %l1:*i32
|
||||
j b5()
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:i32 = load %l0:*i32
|
||||
%b5:i2:u1 = cmp lt %b5:i0:i32 %b5:i1:i32
|
||||
br %b5:i2:u1, b6(), b7()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l2:*i32
|
||||
%b6:i1:i32 = load %l3:*i32
|
||||
%b6:i2:i32 = add %b6:i0:i32 %b6:i1:i32
|
||||
%b6:i3:unit = store %b6:i2:i32 %l4:*i32
|
||||
%b6:i4:i32 = load %l3:*i32
|
||||
%b6:i5:unit = store %b6:i4:i32 %l2:*i32
|
||||
%b6:i6:i32 = load %l4:*i32
|
||||
%b6:i7:unit = store %b6:i6:i32 %l3:*i32
|
||||
%b6:i8:i32 = load %l1:*i32
|
||||
%b6:i9:i32 = add %b6:i8:i32 1:i32
|
||||
%b6:i10:unit = store %b6:i9:i32 %l1:*i32
|
||||
j b5()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l3:*i32
|
||||
ret %b7:i0:i32
|
||||
|
||||
block b8:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @fibonacci(9:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 34:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
78
examples/ir/fib5.ir
Normal file
78
examples/ir/fib5.ir
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
%l1:i32:i
|
||||
%l2:i32:t1
|
||||
%l3:i32:t2
|
||||
%l4:i32:next_term
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
%b0:i3:unit = store 1:i32 %l3:*i32
|
||||
%b0:i4:unit = store 0:i32 %l4:*i32
|
||||
%b0:i5:i32 = load %l0:*i32
|
||||
%b0:i6:u1 = cmp lt %b0:i5:i32 2:i32
|
||||
br %b0:i6:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:unit = store 1:i32 %l1:*i32
|
||||
j b5()
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l2:*i32
|
||||
%b5:i1:i32 = load %l3:*i32
|
||||
%b5:i2:i32 = add %b5:i0:i32 %b5:i1:i32
|
||||
%b5:i3:unit = store %b5:i2:i32 %l4:*i32
|
||||
%b5:i4:i32 = load %l3:*i32
|
||||
%b5:i5:unit = store %b5:i4:i32 %l2:*i32
|
||||
%b5:i6:i32 = load %l4:*i32
|
||||
%b5:i7:unit = store %b5:i6:i32 %l3:*i32
|
||||
%b5:i8:i32 = load %l1:*i32
|
||||
%b5:i9:i32 = add %b5:i8:i32 1:i32
|
||||
%b5:i10:unit = store %b5:i9:i32 %l1:*i32
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l1:*i32
|
||||
%b6:i1:i32 = load %l0:*i32
|
||||
%b6:i2:u1 = cmp lt %b6:i0:i32 %b6:i1:i32
|
||||
br %b6:i2:u1, b5(), b7()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l3:*i32
|
||||
ret %b7:i0:i32
|
||||
|
||||
block b8:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @fibonacci(9:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 34:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
52
examples/ir/fibonacci.ir
Normal file
52
examples/ir/fibonacci.ir
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:u1 = cmp lt %b0:i1:i32 2:i32
|
||||
br %b0:i2:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l0:*i32
|
||||
%b3:i1:i32 = sub %b3:i0:i32 2:i32
|
||||
%b3:i2:i32 = call @fibonacci(%b3:i1:i32)
|
||||
%b3:i3:i32 = load %l0:*i32
|
||||
%b3:i4:i32 = sub %b3:i3:i32 1:i32
|
||||
%b3:i5:i32 = call @fibonacci(%b3:i4:i32)
|
||||
%b3:i6:i32 = add %b3:i2:i32 %b3:i5:i32
|
||||
ret %b3:i6:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @fibonacci(9:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 34:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
211
examples/ir/float.ir
Normal file
211
examples/ir/float.ir
Normal file
@@ -0,0 +1,211 @@
|
||||
|
||||
fun f64 @average {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:len
|
||||
%l1:*i32:a
|
||||
%l2:i32:sum
|
||||
%l3:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:*i32 %l1:**i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:i32 = load %l0:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:*i32 = load %l1:**i32
|
||||
%b3:i2:i32 = load %l3:*i32
|
||||
%b3:i3:i64 = typecast %b3:i2:i32 to i64
|
||||
%b3:i4:i64 = mul %b3:i3:i64 4:i64
|
||||
%b3:i5:*i32 = getelementptr %b3:i1 offset %b3:i4
|
||||
%b3:i6:i32 = load %b3:i5:*i32
|
||||
%b3:i7:i32 = add %b3:i0:i32 %b3:i6:i32
|
||||
%b3:i8:unit = store %b3:i7:i32 %l2:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l2:*i32
|
||||
%b5:i1:f64 = typecast %b5:i0:i32 to f64
|
||||
%b5:i2:i32 = load %l0:*i32
|
||||
%b5:i3:f64 = typecast %b5:i2:i32 to f64
|
||||
%b5:i4:f64 = div %b5:i1:f64 %b5:i3:f64
|
||||
ret %b5:i4:f64
|
||||
|
||||
block b6:
|
||||
ret undef:f64
|
||||
}
|
||||
|
||||
fun f64 @custom_abs {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:f64:a
|
||||
%l1:f64:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:f64 %l0:*f64
|
||||
%b0:i1:f64 = load %l0:*f64
|
||||
%b0:i2:f64 = typecast 0:i32 to f64
|
||||
%b0:i3:u1 = cmp lt %b0:i1:f64 %b0:i2:f64
|
||||
br %b0:i3:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:f64 = load %l0:*f64
|
||||
%b1:i1:f64 = minus %b1:i0:f64
|
||||
%b1:i2:unit = store %b1:i1:f64 %l1:*f64
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:f64 = load %l0:*f64
|
||||
%b2:i1:unit = store %b2:i0:f64 %l1:*f64
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:f64 = load %l1:*f64
|
||||
ret %b3:i0:f64
|
||||
|
||||
block b4:
|
||||
ret undef:f64
|
||||
}
|
||||
|
||||
fun f64 @custom_max {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:f64:a
|
||||
%l1:f64:b
|
||||
%l2:f64:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:f64 %l0:*f64
|
||||
%b0:i1:unit = store %b0:p1:f64 %l1:*f64
|
||||
%b0:i2:f64 = load %l0:*f64
|
||||
%b0:i3:f64 = load %l1:*f64
|
||||
%b0:i4:u1 = cmp gt %b0:i2:f64 %b0:i3:f64
|
||||
br %b0:i4:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:f64 = load %l0:*f64
|
||||
%b1:i1:unit = store %b1:i0:f64 %l2:*f64
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:f64 = load %l1:*f64
|
||||
%b2:i1:unit = store %b2:i0:f64 %l2:*f64
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:f64 = load %l2:*f64
|
||||
ret %b3:i0:f64
|
||||
|
||||
block b4:
|
||||
ret undef:f64
|
||||
}
|
||||
|
||||
fun i32 @is_close {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:f64:a
|
||||
%l1:f64:b
|
||||
%l2:f64:rel_tol
|
||||
%l3:f64:abs_tol
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:f64 %l0:*f64
|
||||
%b0:i1:unit = store %b0:p1:f64 %l1:*f64
|
||||
%b0:i2:unit = store %b0:p2:f64 %l2:*f64
|
||||
%b0:i3:unit = store %b0:p3:f64 %l3:*f64
|
||||
%b0:i4:f64 = load %l0:*f64
|
||||
%b0:i5:f64 = load %l1:*f64
|
||||
%b0:i6:f64 = sub %b0:i4:f64 %b0:i5:f64
|
||||
%b0:i7:f64 = call @custom_abs(%b0:i6:f64)
|
||||
%b0:i8:f64 = load %l2:*f64
|
||||
%b0:i9:f64 = load %l0:*f64
|
||||
%b0:i10:f64 = call @custom_abs(%b0:i9:f64)
|
||||
%b0:i11:f64 = load %l1:*f64
|
||||
%b0:i12:f64 = call @custom_abs(%b0:i11:f64)
|
||||
%b0:i13:f64 = call @custom_max(%b0:i10:f64, %b0:i12:f64)
|
||||
%b0:i14:f64 = mul %b0:i8:f64 %b0:i13:f64
|
||||
%b0:i15:f64 = load %l3:*f64
|
||||
%b0:i16:f64 = call @custom_max(%b0:i14:f64, %b0:i15:f64)
|
||||
%b0:i17:u1 = cmp le %b0:i7:f64 %b0:i16:f64
|
||||
%b0:i18:i32 = typecast %b0:i17:u1 to i32
|
||||
ret %b0:i18:i32
|
||||
|
||||
block b1:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:[10 x i32]:a
|
||||
%l1:i32:len
|
||||
%l2:i32:i
|
||||
%l3:f32:avg
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 10:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
%b2:i1:i32 = load %l1:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:*i32 = getelementptr %l0 offset 0
|
||||
%b3:i1:i32 = load %l2:*i32
|
||||
%b3:i2:i64 = typecast %b3:i1:i32 to i64
|
||||
%b3:i3:i64 = mul %b3:i2:i64 4:i64
|
||||
%b3:i4:*i32 = getelementptr %b3:i0 offset %b3:i3
|
||||
%b3:i5:i32 = load %l2:*i32
|
||||
%b3:i6:unit = store %b3:i5:i32 %b3:i4:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l2:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l2:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:*i32 = getelementptr %l0 offset 0
|
||||
%b5:i2:f64 = call @average(%b5:i0:i32, %b5:i1:*i32)
|
||||
%b5:i3:f32 = typecast %b5:i2:f64 to f32
|
||||
%b5:i4:unit = store %b5:i3:f32 %l3:*f32
|
||||
%b5:i5:f32 = load %l3:*f32
|
||||
%b5:i6:f64 = typecast %b5:i5:f32 to f64
|
||||
%b5:i7:i32 = call @is_close(%b5:i6:f64, 4.5:f64, 0.000000001:f64, 0.1:f64)
|
||||
ret %b5:i7:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
16243
examples/ir/float2.ir
Normal file
16243
examples/ir/float2.ir
Normal file
File diff suppressed because it is too large
Load Diff
53
examples/ir/foo.ir
Normal file
53
examples/ir/foo.ir
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
%l1:i32:y
|
||||
%l2:i32:z
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:i32 %l2:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:i32 = load %l1:*i32
|
||||
%b0:i5:u1 = cmp eq %b0:i3:i32 %b0:i4:i32
|
||||
br %b0:i5:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
ret %b2:i0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
j b3()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = minus 1:i32
|
||||
%b0:i1:i32 = call @foo(0:i32, 1:i32, %b0:i0:i32)
|
||||
%b0:i2:i32 = minus 1:i32
|
||||
%b0:i3:u1 = cmp eq %b0:i1:i32 %b0:i2:i32
|
||||
%b0:i4:i32 = typecast %b0:i3:u1 to i32
|
||||
ret %b0:i4:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
40
examples/ir/foo2.ir
Normal file
40
examples/ir/foo2.ir
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:i32:i
|
||||
%l2:i32:i
|
||||
%l3:i32:k
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l1:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l1:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 10:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:unit = store 0:i32 %l2:*i32
|
||||
%b3:i1:unit = store 0:i32 %l3:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l1:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
ret 1:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
42
examples/ir/foo3.ir
Normal file
42
examples/ir/foo3.ir
Normal file
@@ -0,0 +1,42 @@
|
||||
var i32 @g = 10
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:i32:j
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:i32 = load %l0:*i32
|
||||
%b0:i3:i32 = load %l1:*i32
|
||||
%b0:i4:i32 = add %b0:i2:i32 %b0:i3:i32
|
||||
%b0:i5:i32 = load @g:*i32
|
||||
%b0:i6:i32 = add %b0:i4:i32 %b0:i5:i32
|
||||
ret %b0:i6:i32
|
||||
|
||||
block b1:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = load @g:*i32
|
||||
%b0:i1:unit = store %b0:i0:i32 %l0:*i32
|
||||
%b0:i2:i32 = load %l0:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:i32 = call @foo(%b0:i2:i32, %b0:i3:i32)
|
||||
%b0:i5:u1 = cmp eq %b0:i4:i32 30:i32
|
||||
%b0:i6:i32 = typecast %b0:i5:u1 to i32
|
||||
ret %b0:i6:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
67
examples/ir/foo4.ir
Normal file
67
examples/ir/foo4.ir
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:i32:j
|
||||
%l2:i32:k
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:i32 %l2:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:i32 = load %l1:*i32
|
||||
%b0:i5:i32 = add %b0:i3:i32 %b0:i4:i32
|
||||
%b0:i6:i32 = load %l2:*i32
|
||||
%b0:i7:i32 = add %b0:i5:i32 %b0:i6:i32
|
||||
ret %b0:i7:i32
|
||||
|
||||
block b1:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun *i32 (i32, i32, i32) @foo2 {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret @foo:*i32 (i32, i32, i32)
|
||||
|
||||
block b1:
|
||||
ret undef:*i32 (i32, i32, i32)
|
||||
}
|
||||
|
||||
fun **i32 (i32, i32, i32) () @foo3 {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret @foo2:**i32 (i32, i32, i32) ()
|
||||
|
||||
block b1:
|
||||
ret undef:**i32 (i32, i32, i32) ()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:**i32 (i32, i32, i32) () = call @foo3()
|
||||
%b0:i1:*i32 (i32, i32, i32) = call %b0:i0()
|
||||
%b0:i2:i32 = call %b0:i1(2:i32, 2:i32, 2:i32)
|
||||
%b0:i3:u1 = cmp eq %b0:i2:i32 6:i32
|
||||
%b0:i4:i32 = typecast %b0:i3:u1 to i32
|
||||
ret %b0:i4:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
86
examples/ir/for_continue_break.ir
Normal file
86
examples/ir/for_continue_break.ir
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:sum
|
||||
%l1:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l1:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l1:*i32
|
||||
%b3:i1:u1 = cmp eq %b3:i0:i32 5:i32
|
||||
br %b3:i1:u1, b6(), b7()
|
||||
|
||||
block b4:
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l0:*i32
|
||||
ret %b5:i0:i32
|
||||
|
||||
block b6:
|
||||
j b5()
|
||||
|
||||
block b7:
|
||||
j b8()
|
||||
|
||||
block b8:
|
||||
%b8:i0:i32 = load %l1:*i32
|
||||
%b8:i1:u1 = cmp eq %b8:i0:i32 3:i32
|
||||
br %b8:i1:u1, b10(), b11()
|
||||
|
||||
block b9:
|
||||
j b8()
|
||||
|
||||
block b10:
|
||||
%b10:i0:i32 = load %l1:*i32
|
||||
%b10:i1:i32 = add %b10:i0:i32 1:i32
|
||||
%b10:i2:unit = store %b10:i1:i32 %l1:*i32
|
||||
j b4()
|
||||
|
||||
block b11:
|
||||
j b12()
|
||||
|
||||
block b12:
|
||||
%b12:i0:i32 = load %l0:*i32
|
||||
%b12:i1:i32 = load %l1:*i32
|
||||
%b12:i2:i32 = add %b12:i0:i32 %b12:i1:i32
|
||||
%b12:i3:unit = store %b12:i2:i32 %l0:*i32
|
||||
%b12:i4:i32 = load %l1:*i32
|
||||
%b12:i5:i32 = add %b12:i4:i32 1:i32
|
||||
%b12:i6:unit = store %b12:i5:i32 %l1:*i32
|
||||
j b4()
|
||||
|
||||
block b13:
|
||||
j b12()
|
||||
|
||||
block b14:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @foo()
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 7:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
103
examples/ir/gcd.ir
Normal file
103
examples/ir/gcd.ir
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
fun i32 @gcd {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:a
|
||||
%l1:i32:b
|
||||
%l2:i32:t0
|
||||
%l3:i32:t1
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:i32 = load %l0:*i32
|
||||
%b0:i3:u1 = cmp gt %b0:i2:i32 0:i32
|
||||
br %b0:i3:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
%b1:i1:unit = store %b1:i0:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l0:*i32
|
||||
%b2:i1:i32 = minus %b2:i0:i32
|
||||
%b2:i2:unit = store %b2:i1:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:unit = store %b3:i0:i32 %l0:*i32
|
||||
%b3:i2:i32 = load %l1:*i32
|
||||
%b3:i3:u1 = cmp gt %b3:i2:i32 0:i32
|
||||
br %b3:i3:u1, b4(), b5()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:unit = store %b4:i0:i32 %l3:*i32
|
||||
j b6()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:i32 = minus %b5:i0:i32
|
||||
%b5:i2:unit = store %b5:i1:i32 %l3:*i32
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l3:*i32
|
||||
%b6:i1:unit = store %b6:i0:i32 %l1:*i32
|
||||
j b7()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l0:*i32
|
||||
%b7:i1:i32 = load %l1:*i32
|
||||
%b7:i2:u1 = cmp ne %b7:i0:i32 %b7:i1:i32
|
||||
br %b7:i2:u1, b8(), b9()
|
||||
|
||||
block b8:
|
||||
%b8:i0:i32 = load %l0:*i32
|
||||
%b8:i1:i32 = load %l1:*i32
|
||||
%b8:i2:u1 = cmp gt %b8:i0:i32 %b8:i1:i32
|
||||
br %b8:i2:u1, b10(), b11()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l0:*i32
|
||||
ret %b9:i0:i32
|
||||
|
||||
block b10:
|
||||
%b10:i0:i32 = load %l0:*i32
|
||||
%b10:i1:i32 = load %l1:*i32
|
||||
%b10:i2:i32 = sub %b10:i0:i32 %b10:i1:i32
|
||||
%b10:i3:unit = store %b10:i2:i32 %l0:*i32
|
||||
j b12()
|
||||
|
||||
block b11:
|
||||
%b11:i0:i32 = load %l1:*i32
|
||||
%b11:i1:i32 = load %l0:*i32
|
||||
%b11:i2:i32 = sub %b11:i0:i32 %b11:i1:i32
|
||||
%b11:i3:unit = store %b11:i2:i32 %l1:*i32
|
||||
j b12()
|
||||
|
||||
block b12:
|
||||
j b7()
|
||||
|
||||
block b13:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @gcd(18:i32, 21:i32)
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 3:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
25
examples/ir/integer_literal.ir
Normal file
25
examples/ir/integer_literal.ir
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i16:temp
|
||||
%l1:u32:temp2
|
||||
|
||||
block b0:
|
||||
%b0:i0:i16 = typecast 0:i32 to i16
|
||||
%b0:i1:unit = store %b0:i0:i16 %l0:*i16
|
||||
%b0:i2:unit = store 4294967163:u32 %l1:*u32
|
||||
%b0:i3:i16 = load %l0:*i16
|
||||
%b0:i4:u32 = load %l1:*u32
|
||||
%b0:i5:u32 = typecast %b0:i3:i16 to u32
|
||||
%b0:i6:u32 = xor %b0:i5:u32 %b0:i4:u32
|
||||
%b0:i7:i8 = typecast %b0:i6:u32 to i8
|
||||
%b0:i8:i32 = typecast %b0:i7:i8 to i32
|
||||
%b0:i9:u1 = cmp eq %b0:i8:i32 123:i32
|
||||
%b0:i10:i32 = typecast %b0:i9:u1 to i32
|
||||
ret %b0:i10:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
18
examples/ir/integer_literal2.ir
Normal file
18
examples/ir/integer_literal2.ir
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:temp
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:u32 = typecast %b0:i1:i32 to u32
|
||||
%b0:i3:u1 = cmp lt %b0:i2:u32 4294967295:u32
|
||||
%b0:i4:i32 = typecast %b0:i3:u1 to i32
|
||||
ret %b0:i4:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
96
examples/ir/logical_op.ir
Normal file
96
examples/ir/logical_op.ir
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:a
|
||||
%l1:i32:b
|
||||
%l2:i32:c
|
||||
%l3:i32:d
|
||||
%l4:u1:t0
|
||||
%l5:u1:t1
|
||||
%l6:u1:t2
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:unit = store 0:i32 %l2:*i32
|
||||
%b0:i3:unit = store 0:i32 %l3:*i32
|
||||
%b0:i4:unit = store 1:i32 %l0:*i32
|
||||
%b0:i5:u1 = cmp ne 1:i32 0:i32
|
||||
br %b0:i5:u1, b4(), b5()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
%b1:i1:i32 = add %b1:i0:i32 1:i32
|
||||
%b1:i2:unit = store %b1:i1:i32 %l1:*i32
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:unit = store 1:i32 %l2:*i32
|
||||
%b3:i1:u1 = cmp ne 1:i32 0:i32
|
||||
br %b3:i1:u1, b10(), b11()
|
||||
|
||||
block b4:
|
||||
%b4:i0:unit = store 1:u1 %l4:*u1
|
||||
j b6()
|
||||
|
||||
block b5:
|
||||
%b5:i0:unit = store 1:i32 %l1:*i32
|
||||
%b5:i1:u1 = cmp ne 1:i32 0:i32
|
||||
%b5:i2:unit = store %b5:i1:u1 %l4:*u1
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:u1 = load %l4:*u1
|
||||
br %b6:i0:u1, b1(), b2()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l3:*i32
|
||||
%b7:i1:i32 = add %b7:i0:i32 1:i32
|
||||
%b7:i2:unit = store %b7:i1:i32 %l3:*i32
|
||||
j b9()
|
||||
|
||||
block b8:
|
||||
j b9()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l1:*i32
|
||||
%b9:i1:u1 = cmp eq %b9:i0:i32 1:i32
|
||||
br %b9:i1:u1, b13(), b14()
|
||||
|
||||
block b10:
|
||||
%b10:i0:unit = store 1:i32 %l3:*i32
|
||||
%b10:i1:u1 = cmp ne 1:i32 0:i32
|
||||
%b10:i2:unit = store %b10:i1:u1 %l5:*u1
|
||||
j b12()
|
||||
|
||||
block b11:
|
||||
%b11:i0:unit = store 0:u1 %l5:*u1
|
||||
j b12()
|
||||
|
||||
block b12:
|
||||
%b12:i0:u1 = load %l5:*u1
|
||||
br %b12:i0:u1, b7(), b8()
|
||||
|
||||
block b13:
|
||||
%b13:i0:i32 = load %l3:*i32
|
||||
%b13:i1:u1 = cmp eq %b13:i0:i32 2:i32
|
||||
%b13:i2:unit = store %b13:i1:u1 %l6:*u1
|
||||
j b15()
|
||||
|
||||
block b14:
|
||||
%b14:i0:unit = store 0:u1 %l6:*u1
|
||||
j b15()
|
||||
|
||||
block b15:
|
||||
%b15:i0:u1 = load %l6:*u1
|
||||
%b15:i1:i32 = typecast %b15:i0:u1 to i32
|
||||
ret %b15:i1:i32
|
||||
|
||||
block b16:
|
||||
ret 0:i32
|
||||
}
|
||||
32
examples/ir/minus_constant.ir
Normal file
32
examples/ir/minus_constant.ir
Normal file
@@ -0,0 +1,32 @@
|
||||
var i32 @a = -(1)
|
||||
var i64 @b = -(1l)
|
||||
var f32 @c = -(1.5f)
|
||||
var f64 @d = -(1.5)
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = load @a:*i32
|
||||
%b0:i1:i64 = load @b:*i64
|
||||
%b0:i2:i64 = typecast %b0:i0:i32 to i64
|
||||
%b0:i3:i64 = add %b0:i2:i64 %b0:i1:i64
|
||||
%b0:i4:f32 = load @c:*f32
|
||||
%b0:i5:i32 = typecast %b0:i4:f32 to i32
|
||||
%b0:i6:i64 = typecast %b0:i5:i32 to i64
|
||||
%b0:i7:i64 = add %b0:i3:i64 %b0:i6:i64
|
||||
%b0:i8:f64 = load @d:*f64
|
||||
%b0:i9:i64 = typecast %b0:i8:f64 to i64
|
||||
%b0:i10:i64 = add %b0:i7:i64 %b0:i9:i64
|
||||
%b0:i11:i32 = minus 4:i32
|
||||
%b0:i12:i64 = typecast %b0:i11:i32 to i64
|
||||
%b0:i13:u1 = cmp eq %b0:i10:i64 %b0:i12:i64
|
||||
%b0:i14:i32 = typecast %b0:i13:u1 to i32
|
||||
ret %b0:i14:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
53
examples/ir/negate.ir
Normal file
53
examples/ir/negate.ir
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
%l1:i32:y
|
||||
%l2:i32:z
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:i32 %l2:*i32
|
||||
%b0:i3:i32 = load %l0:*i32
|
||||
%b0:i4:i32 = load %l1:*i32
|
||||
%b0:i5:u1 = cmp eq %b0:i3:i32 %b0:i4:i32
|
||||
%b0:i6:u1 = negate %b0:i5:u1
|
||||
br %b0:i6:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
ret %b1:i0:i32
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l2:*i32
|
||||
ret %b2:i0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b3()
|
||||
|
||||
block b5:
|
||||
j b3()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = minus 1:i32
|
||||
%b0:i1:i32 = call @foo(0:i32, 1:i32, %b0:i0:i32)
|
||||
%b0:i2:u1 = cmp eq %b0:i1:i32 1:i32
|
||||
%b0:i3:i32 = typecast %b0:i2:u1 to i32
|
||||
ret %b0:i3:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
68
examples/ir/pointer.ir
Normal file
68
examples/ir/pointer.ir
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
fun *i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:*i32:a
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:*i32 %l0:**i32
|
||||
%b0:i1:*i32 = load %l0:**i32
|
||||
ret %b0:i1:*i32
|
||||
|
||||
block b1:
|
||||
ret undef:*i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:a
|
||||
%l1:*i32:p
|
||||
%l2:**i32:p2
|
||||
%l3:*i32:p3
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 1:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:unit = store %l0:*i32 %l1:**i32
|
||||
%b0:i3:*i32 = load %l1:**i32
|
||||
%b0:i4:*i32 = load %l1:**i32
|
||||
%b0:i5:*i32 = load %l1:**i32
|
||||
%b0:i6:unit = store %l1:**i32 %l2:***i32
|
||||
%b0:i7:*i32 = load %l1:**i32
|
||||
%b0:i8:*i32 = load %l1:**i32
|
||||
%b0:i9:unit = store %b0:i8:*i32 %l3:**i32
|
||||
%b0:i10:**i32 = load %l2:***i32
|
||||
%b0:i11:*i32 = load %b0:i10:**i32
|
||||
%b0:i12:*i32 = call @foo(%b0:i11:*i32)
|
||||
%b0:i13:i32 = load %b0:i12:*i32
|
||||
%b0:i14:**i32 = load %l2:***i32
|
||||
%b0:i15:*i32 = load %b0:i14:**i32
|
||||
%b0:i16:*i32 = call @foo(%b0:i15:*i32)
|
||||
%b0:i17:**i32 = load %l2:***i32
|
||||
%b0:i18:*i32 = load %b0:i17:**i32
|
||||
%b0:i19:*i32 = call @foo(%b0:i18:*i32)
|
||||
%b0:i20:i32 = load %b0:i19:*i32
|
||||
%b0:i21:**i32 = load %l2:***i32
|
||||
%b0:i22:*i32 = load %b0:i21:**i32
|
||||
%b0:i23:*i32 = call @foo(%b0:i22:*i32)
|
||||
%b0:i24:i32 = load %b0:i23:*i32
|
||||
%b0:i25:i32 = add %b0:i24:i32 1:i32
|
||||
%b0:i26:unit = store %b0:i25:i32 %b0:i16:*i32
|
||||
%b0:i27:*i32 = load %l3:**i32
|
||||
%b0:i28:*i32 = call @foo(%b0:i27:*i32)
|
||||
%b0:i29:*i32 = load %l3:**i32
|
||||
%b0:i30:*i32 = call @foo(%b0:i29:*i32)
|
||||
%b0:i31:i32 = load %b0:i30:*i32
|
||||
%b0:i32:i32 = add %b0:i31:i32 1:i32
|
||||
%b0:i33:unit = store %b0:i32:i32 %b0:i28:*i32
|
||||
%b0:i34:i32 = load %l0:*i32
|
||||
%b0:i35:u1 = cmp eq %b0:i34:i32 3:i32
|
||||
%b0:i36:i32 = typecast %b0:i35:u1 to i32
|
||||
ret %b0:i36:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
24
examples/ir/return_void.ir
Normal file
24
examples/ir/return_void.ir
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
fun unit @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret unit:unit
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = call @foo()
|
||||
ret 1:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
49
examples/ir/shift.ir
Normal file
49
examples/ir/shift.ir
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i8:a
|
||||
%l1:i8:b
|
||||
%l2:u8:c
|
||||
%l3:u1:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:i8 = typecast 127:i32 to i8
|
||||
%b0:i1:unit = store %b0:i0:i8 %l0:*i8
|
||||
%b0:i2:i8 = load %l0:*i8
|
||||
%b0:i3:i32 = typecast %b0:i2:i8 to i32
|
||||
%b0:i4:i32 = shl %b0:i3:i32 1:i32
|
||||
%b0:i5:i8 = typecast %b0:i4:i32 to i8
|
||||
%b0:i6:unit = store %b0:i5:i8 %l1:*i8
|
||||
%b0:i7:i8 = load %l1:*i8
|
||||
%b0:i8:u8 = typecast %b0:i7:i8 to u8
|
||||
%b0:i9:i32 = typecast %b0:i8:u8 to i32
|
||||
%b0:i10:i32 = shr %b0:i9:i32 1:i32
|
||||
%b0:i11:u8 = typecast %b0:i10:i32 to u8
|
||||
%b0:i12:unit = store %b0:i11:u8 %l2:*u8
|
||||
%b0:i13:i8 = load %l1:*i8
|
||||
%b0:i14:i32 = minus 2:i32
|
||||
%b0:i15:i32 = typecast %b0:i13:i8 to i32
|
||||
%b0:i16:u1 = cmp eq %b0:i15:i32 %b0:i14:i32
|
||||
br %b0:i16:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:u8 = load %l2:*u8
|
||||
%b1:i1:i32 = typecast %b1:i0:u8 to i32
|
||||
%b1:i2:u1 = cmp eq %b1:i1:i32 127:i32
|
||||
%b1:i3:unit = store %b1:i2:u1 %l3:*u1
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:unit = store 0:u1 %l3:*u1
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:u1 = load %l3:*u1
|
||||
%b3:i1:i32 = typecast %b3:i0:u1 to i32
|
||||
ret %b3:i1:i32
|
||||
|
||||
block b4:
|
||||
ret 0:i32
|
||||
}
|
||||
14
examples/ir/simple.ir
Normal file
14
examples/ir/simple.ir
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 1:i32 %l0:*i32
|
||||
ret 1:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
69
examples/ir/simple_cond.ir
Normal file
69
examples/ir/simple_cond.ir
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
fun i32 @f {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:i32 = add %b0:i1:i32 8:i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:x
|
||||
%l1:i32:y
|
||||
%l2:i32:t0
|
||||
%l3:i32:t1
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:i32 = add %b0:i1:i32 1:i32
|
||||
%b0:i3:unit = store %b0:i2:i32 %l0:*i32
|
||||
%b0:i4:u1 = cmp eq %b0:i1:i32 1:i32
|
||||
br %b0:i4:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 1:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:unit = store 2:i32 %l2:*i32
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l2:*i32
|
||||
%b3:i1:unit = store %b3:i0:i32 %l1:*i32
|
||||
%b3:i2:i32 = load %l0:*i32
|
||||
%b3:i3:i32 = load %l1:*i32
|
||||
%b3:i4:u1 = cmp lt %b3:i2:i32 %b3:i3:i32
|
||||
br %b3:i4:u1, b4(), b5()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l0:*i32
|
||||
%b4:i1:unit = store %b4:i0:i32 %l3:*i32
|
||||
j b6()
|
||||
|
||||
block b5:
|
||||
%b5:i0:unit = store 2:i32 %l3:*i32
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l3:*i32
|
||||
%b6:i1:i32 = call @f(%b6:i0:i32)
|
||||
%b6:i2:u1 = cmp eq %b6:i1:i32 9:i32
|
||||
%b6:i3:i32 = typecast %b6:i2:u1 to i32
|
||||
ret %b6:i3:i32
|
||||
|
||||
block b7:
|
||||
ret 0:i32
|
||||
}
|
||||
43
examples/ir/simple_for.ir
Normal file
43
examples/ir/simple_for.ir
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:i
|
||||
%l1:i32:sum
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l0:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l0:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 11:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l1:*i32
|
||||
%b3:i1:i32 = load %l0:*i32
|
||||
%b3:i2:i32 = add %b3:i0:i32 %b3:i1:i32
|
||||
%b3:i3:unit = store %b3:i2:i32 %l1:*i32
|
||||
j b4()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l0:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l0:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l1:*i32
|
||||
%b5:i1:u1 = cmp eq %b5:i0:i32 55:i32
|
||||
%b5:i2:i32 = typecast %b5:i1:u1 to i32
|
||||
ret %b5:i2:i32
|
||||
|
||||
block b6:
|
||||
ret 0:i32
|
||||
}
|
||||
48
examples/ir/simple_if.ir
Normal file
48
examples/ir/simple_if.ir
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:u1 = cmp lt %b0:i1:i32 2:i32
|
||||
br %b0:i2:u1, b1(), b2()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
%b1:i1:i32 = add %b1:i0:i32 2:i32
|
||||
%b1:i2:unit = store %b1:i1:i32 %l0:*i32
|
||||
j b3()
|
||||
|
||||
block b2:
|
||||
j b3()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l0:*i32
|
||||
%b3:i1:i32 = sub %b3:i0:i32 2:i32
|
||||
%b3:i2:i32 = call @fibonacci(%b3:i1:i32)
|
||||
%b3:i3:i32 = load %l0:*i32
|
||||
%b3:i4:i32 = sub %b3:i3:i32 1:i32
|
||||
%b3:i5:i32 = call @fibonacci(%b3:i4:i32)
|
||||
%b3:i6:i32 = add %b3:i2:i32 %b3:i5:i32
|
||||
ret %b3:i6:i32
|
||||
|
||||
block b4:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret 1:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
16
examples/ir/sizeof.ir
Normal file
16
examples/ir/sizeof.ir
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:u64 = typecast 4:i32 to u64
|
||||
%b0:i1:u1 = cmp eq 4:u64 %b0:i0:u64
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
114
examples/ir/struct.ir
Normal file
114
examples/ir/struct.ir
Normal file
@@ -0,0 +1,114 @@
|
||||
struct %t1 : { i8, struct %t0, f64 }
|
||||
struct %t0 : { [4 x [5 x i32]] }
|
||||
|
||||
fun unit @init {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:row
|
||||
%l1:i32:col
|
||||
%l2:*[5 x i32]:arr
|
||||
%l3:i32:i
|
||||
%l4:i32:j
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
%b0:i1:unit = store %b0:p1:i32 %l1:*i32
|
||||
%b0:i2:unit = store %b0:p2:*[5 x i32] %l2:**[5 x i32]
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:i32 = load %l0:*i32
|
||||
%b2:i2:u1 = cmp lt %b2:i0:i32 %b2:i1:i32
|
||||
br %b2:i2:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
j b6()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
ret unit:unit
|
||||
|
||||
block b6:
|
||||
%b6:i0:unit = store 0:i32 %l4:*i32
|
||||
j b7()
|
||||
|
||||
block b7:
|
||||
%b7:i0:i32 = load %l4:*i32
|
||||
%b7:i1:i32 = load %l1:*i32
|
||||
%b7:i2:u1 = cmp lt %b7:i0:i32 %b7:i1:i32
|
||||
br %b7:i2:u1, b8(), b10()
|
||||
|
||||
block b8:
|
||||
%b8:i0:*[5 x i32] = load %l2:**[5 x i32]
|
||||
%b8:i1:i32 = load %l3:*i32
|
||||
%b8:i2:i64 = typecast %b8:i1:i32 to i64
|
||||
%b8:i3:i64 = mul %b8:i2:i64 20:i64
|
||||
%b8:i4:*[5 x i32] = getelementptr %b8:i0 offset %b8:i3
|
||||
%b8:i5:*i32 = getelementptr %b8:i4 offset 0
|
||||
%b8:i6:i32 = load %l4:*i32
|
||||
%b8:i7:i64 = typecast %b8:i6:i32 to i64
|
||||
%b8:i8:i64 = mul %b8:i7:i64 4:i64
|
||||
%b8:i9:*i32 = getelementptr %b8:i5 offset %b8:i8
|
||||
%b8:i10:i32 = load %l3:*i32
|
||||
%b8:i11:i32 = load %l4:*i32
|
||||
%b8:i12:i32 = mul %b8:i10:i32 %b8:i11:i32
|
||||
%b8:i13:unit = store %b8:i12:i32 %b8:i9:*i32
|
||||
j b9()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l4:*i32
|
||||
%b9:i1:i32 = add %b9:i0:i32 1:i32
|
||||
%b9:i2:unit = store %b9:i1:i32 %l4:*i32
|
||||
j b7()
|
||||
|
||||
block b10:
|
||||
j b4()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0: struct %t1:temp
|
||||
%l1:i32:row
|
||||
%l2:i32:col
|
||||
%l3: struct %t1:temp2
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 4:i32 %l1:*i32
|
||||
%b0:i1:unit = store 5:i32 %l2:*i32
|
||||
%b0:i2:i32 = load %l1:*i32
|
||||
%b0:i3:i32 = load %l2:*i32
|
||||
%b0:i4:*[4 x [5 x i32]] = getelementptr %l0 offset 4
|
||||
%b0:i5:*[5 x i32] = getelementptr %b0:i4 offset 0
|
||||
%b0:i6:unit = call @init(%b0:i2:i32, %b0:i3:i32, %b0:i5:*[5 x i32])
|
||||
%b0:i7: struct %t1 = load %l0:* struct %t1
|
||||
%b0:i8:unit = store %b0:i7: struct %t1 %l3:* struct %t1
|
||||
%b0:i9:*[4 x [5 x i32]] = getelementptr %l3 offset 4
|
||||
%b0:i10:*[5 x i32] = getelementptr %b0:i9 offset 0
|
||||
%b0:i11:i64 = typecast 2:i32 to i64
|
||||
%b0:i12:i64 = mul %b0:i11:i64 20:i64
|
||||
%b0:i13:*[5 x i32] = getelementptr %b0:i10 offset %b0:i12
|
||||
%b0:i14:*i32 = getelementptr %b0:i13 offset 0
|
||||
%b0:i15:i64 = typecast 3:i32 to i64
|
||||
%b0:i16:i64 = mul %b0:i15:i64 4:i64
|
||||
%b0:i17:*i32 = getelementptr %b0:i14 offset %b0:i16
|
||||
%b0:i18:i32 = load %b0:i17:*i32
|
||||
%b0:i19:u1 = cmp eq %b0:i18:i32 6:i32
|
||||
%b0:i20:i32 = typecast %b0:i19:u1 to i32
|
||||
ret %b0:i20:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
59
examples/ir/struct2.ir
Normal file
59
examples/ir/struct2.ir
Normal file
@@ -0,0 +1,59 @@
|
||||
struct %t1 : { i8, struct %t0, i64 }
|
||||
struct %t0 : { [4 x i32] }
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:const struct %t1:temp
|
||||
%l1: struct %t1:temp2
|
||||
%l2:i32:sum
|
||||
|
||||
block b0:
|
||||
%b0:i0:*i8 = getelementptr %l0 offset 0
|
||||
%b0:i1:i8 = typecast 1:i32 to i8
|
||||
%b0:i2:unit = store %b0:i1:i8 %b0:i0:*i8
|
||||
%b0:i3:* struct %t0 = getelementptr %l0 offset 4
|
||||
%b0:i4:*[4 x i32] = getelementptr %b0:i3 offset 0
|
||||
%b0:i5:*i32 = getelementptr %b0:i4 offset 0
|
||||
%b0:i6:i64 = mul 0:i64 4:i64
|
||||
%b0:i7:*i32 = getelementptr %b0:i5 offset %b0:i6
|
||||
%b0:i8:unit = store 2:i32 %b0:i7:*i32
|
||||
%b0:i9:i64 = mul 1:i64 4:i64
|
||||
%b0:i10:*i32 = getelementptr %b0:i5 offset %b0:i9
|
||||
%b0:i11:unit = store 3:i32 %b0:i10:*i32
|
||||
%b0:i12:i64 = mul 2:i64 4:i64
|
||||
%b0:i13:*i32 = getelementptr %b0:i5 offset %b0:i12
|
||||
%b0:i14:unit = store 4:i32 %b0:i13:*i32
|
||||
%b0:i15:i64 = mul 3:i64 4:i64
|
||||
%b0:i16:*i32 = getelementptr %b0:i5 offset %b0:i15
|
||||
%b0:i17:unit = store 5:i32 %b0:i16:*i32
|
||||
%b0:i18:*i64 = getelementptr %l0 offset 24
|
||||
%b0:i19:i64 = typecast 6:i32 to i64
|
||||
%b0:i20:unit = store %b0:i19:i64 %b0:i18:*i64
|
||||
%b0:i21: struct %t1 = load %l0:*const struct %t1
|
||||
%b0:i22:unit = store %b0:i21: struct %t1 %l1:* struct %t1
|
||||
%b0:i23:*i8 = getelementptr %l1 offset 0
|
||||
%b0:i24:i8 = load %b0:i23:*i8
|
||||
%b0:i25:*[4 x i32] = getelementptr %l1 offset 4
|
||||
%b0:i26:*i32 = getelementptr %b0:i25 offset 0
|
||||
%b0:i27:i64 = typecast 2:i32 to i64
|
||||
%b0:i28:i64 = mul %b0:i27:i64 4:i64
|
||||
%b0:i29:*i32 = getelementptr %b0:i26 offset %b0:i28
|
||||
%b0:i30:i32 = load %b0:i29:*i32
|
||||
%b0:i31:i32 = typecast %b0:i24:i8 to i32
|
||||
%b0:i32:i32 = add %b0:i31:i32 %b0:i30:i32
|
||||
%b0:i33:*i64 = getelementptr %l1 offset 24
|
||||
%b0:i34:i64 = load %b0:i33:*i64
|
||||
%b0:i35:i64 = typecast %b0:i32:i32 to i64
|
||||
%b0:i36:i64 = add %b0:i35:i64 %b0:i34:i64
|
||||
%b0:i37:i32 = typecast %b0:i36:i64 to i32
|
||||
%b0:i38:unit = store %b0:i37:i32 %l2:*i32
|
||||
%b0:i39:i32 = load %l2:*i32
|
||||
%b0:i40:u1 = cmp eq %b0:i39:i32 11:i32
|
||||
%b0:i41:i32 = typecast %b0:i40:u1 to i32
|
||||
ret %b0:i41:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
44
examples/ir/switch.ir
Normal file
44
examples/ir/switch.ir
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:a
|
||||
%l1:i32:b
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 1:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
%b0:i2:i32 = load %l0:*i32
|
||||
switch %b0:i2:i32 default b4() [
|
||||
0:i32 b2()
|
||||
1:i32 b3()
|
||||
]
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
%b1:i1:u1 = cmp eq %b1:i0:i32 2:i32
|
||||
%b1:i2:i32 = typecast %b1:i1:u1 to i32
|
||||
ret %b1:i2:i32
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l1:*i32
|
||||
%b2:i1:i32 = add %b2:i0:i32 1:i32
|
||||
%b2:i2:unit = store %b2:i1:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l1:*i32
|
||||
%b3:i1:i32 = add %b3:i0:i32 2:i32
|
||||
%b3:i2:unit = store %b3:i1:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 3:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b5:
|
||||
ret 0:i32
|
||||
}
|
||||
41
examples/ir/temp.ir
Normal file
41
examples/ir/temp.ir
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
fun i32 @fibonacci {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:n
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store %b0:p0:i32 %l0:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l0:*i32
|
||||
%b1:i1:i32 = load %l0:*i32
|
||||
%b1:i2:i32 = add %b1:i0:i32 %b1:i1:i32
|
||||
%b1:i3:u1 = cmp ne %b1:i2:i32 0:i32
|
||||
br %b1:i3:u1, b2(), b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l0:*i32
|
||||
ret %b2:i0:i32
|
||||
|
||||
block b3:
|
||||
ret undef:i32
|
||||
|
||||
block b4:
|
||||
j b1()
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
ret 1:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
118
examples/ir/temp2.ir
Normal file
118
examples/ir/temp2.ir
Normal file
@@ -0,0 +1,118 @@
|
||||
struct color : { i32, i8 }
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:temp
|
||||
%l1: struct color:c
|
||||
%l2:* struct color:cp
|
||||
%l3:i32:i
|
||||
%l4:i32:j
|
||||
%l5:u1:t0
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:u64 = typecast %b0:i1:i32 to u64
|
||||
%b0:i3:u64 = add %b0:i2:u64 1:u64
|
||||
%b0:i4:i32 = typecast %b0:i3:u64 to i32
|
||||
%b0:i5:unit = store %b0:i4:i32 %l0:*i32
|
||||
%b0:i6:i32 = load %l0:*i32
|
||||
%b0:i7:u64 = typecast %b0:i6:i32 to u64
|
||||
%b0:i8:u64 = add %b0:i7:u64 1:u64
|
||||
%b0:i9:i32 = typecast %b0:i8:u64 to i32
|
||||
%b0:i10:unit = store %b0:i9:i32 %l0:*i32
|
||||
%b0:i11:*i32 = getelementptr %l1 offset 0
|
||||
%b0:i12:unit = store 1:i32 %b0:i11:*i32
|
||||
%b0:i13:*i8 = getelementptr %l1 offset 4
|
||||
%b0:i14:i8 = typecast 2:i32 to i8
|
||||
%b0:i15:unit = store %b0:i14:i8 %b0:i13:*i8
|
||||
%b0:i16:i32 = load %l0:*i32
|
||||
%b0:i17:*i8 = getelementptr %l1 offset 4
|
||||
%b0:i18:i8 = load %b0:i17:*i8
|
||||
%b0:i19:i32 = typecast %b0:i18:i8 to i32
|
||||
%b0:i20:i32 = add %b0:i16:i32 %b0:i19:i32
|
||||
%b0:i21:unit = store %b0:i20:i32 %l0:*i32
|
||||
%b0:i22: struct color = load %l1:* struct color
|
||||
%b0:i23:unit = store %l1:* struct color %l2:** struct color
|
||||
%b0:i24:i32 = load %l0:*i32
|
||||
%b0:i25:* struct color = load %l2:** struct color
|
||||
%b0:i26:*i8 = getelementptr %b0:i25 offset 4
|
||||
%b0:i27:i8 = load %b0:i26:*i8
|
||||
%b0:i28:i32 = typecast %b0:i27:i8 to i32
|
||||
%b0:i29:i32 = add %b0:i24:i32 %b0:i28:i32
|
||||
%b0:i30:unit = store %b0:i29:i32 %l0:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:unit = store 0:i32 %l3:*i32
|
||||
%b1:i1:unit = store 0:i32 %l4:*i32
|
||||
j b2()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l3:*i32
|
||||
%b2:i1:u1 = cmp lt %b2:i0:i32 10:i32
|
||||
br %b2:i1:u1, b3(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l3:*i32
|
||||
%b3:i1:u1 = cmp eq %b3:i0:i32 2:i32
|
||||
br %b3:i1:u1, b9(), b10()
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l3:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l3:*i32
|
||||
j b2()
|
||||
|
||||
block b5:
|
||||
%b5:i0:i32 = load %l0:*i32
|
||||
switch %b5:i0:i32 default b15() [
|
||||
1:i32 b14()
|
||||
]
|
||||
|
||||
block b6:
|
||||
j b5()
|
||||
|
||||
block b7:
|
||||
j b8()
|
||||
|
||||
block b8:
|
||||
%b8:i0:i32 = load %l0:*i32
|
||||
%b8:i1:i32 = load %l3:*i32
|
||||
%b8:i2:i32 = add %b8:i0:i32 %b8:i1:i32
|
||||
%b8:i3:unit = store %b8:i2:i32 %l0:*i32
|
||||
j b4()
|
||||
|
||||
block b9:
|
||||
%b9:i0:i32 = load %l4:*i32
|
||||
%b9:i1:u1 = cmp eq %b9:i0:i32 0:i32
|
||||
%b9:i2:unit = store %b9:i1:u1 %l5:*u1
|
||||
j b11()
|
||||
|
||||
block b10:
|
||||
%b10:i0:unit = store 0:u1 %l5:*u1
|
||||
j b11()
|
||||
|
||||
block b11:
|
||||
%b11:i0:u1 = load %l5:*u1
|
||||
br %b11:i0:u1, b6(), b7()
|
||||
|
||||
block b12:
|
||||
j b8()
|
||||
|
||||
block b13:
|
||||
%b13:i0:i32 = load %l0:*i32
|
||||
ret %b13:i0:i32
|
||||
|
||||
block b14:
|
||||
%b14:i0:unit = store 0:i32 %l0:*i32
|
||||
j b13()
|
||||
|
||||
block b15:
|
||||
j b13()
|
||||
|
||||
block b16:
|
||||
ret 0:i32
|
||||
}
|
||||
52
examples/ir/test.ir
Normal file
52
examples/ir/test.ir
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i64:l
|
||||
%l1:i64:l2
|
||||
%l2:i64:l3
|
||||
%l3:i16:s
|
||||
%l4:i16:s2
|
||||
%l5:i32:i
|
||||
%l6:i8:c
|
||||
|
||||
block b0:
|
||||
%b0:i0:i64 = typecast 1:i32 to i64
|
||||
%b0:i1:unit = store %b0:i0:i64 %l0:*i64
|
||||
%b0:i2:i64 = typecast 2:i32 to i64
|
||||
%b0:i3:unit = store %b0:i2:i64 %l1:*i64
|
||||
%b0:i4:i64 = typecast 3:i32 to i64
|
||||
%b0:i5:unit = store %b0:i4:i64 %l2:*i64
|
||||
%b0:i6:i16 = typecast 4:i32 to i16
|
||||
%b0:i7:unit = store %b0:i6:i16 %l3:*i16
|
||||
%b0:i8:i16 = typecast 5:i32 to i16
|
||||
%b0:i9:unit = store %b0:i8:i16 %l4:*i16
|
||||
%b0:i10:unit = store 6:i32 %l5:*i32
|
||||
%b0:i11:i8 = typecast 7:i32 to i8
|
||||
%b0:i12:unit = store %b0:i11:i8 %l6:*i8
|
||||
%b0:i13:i64 = load %l0:*i64
|
||||
%b0:i14:i64 = load %l1:*i64
|
||||
%b0:i15:i64 = add %b0:i13:i64 %b0:i14:i64
|
||||
%b0:i16:i64 = load %l2:*i64
|
||||
%b0:i17:i64 = add %b0:i15:i64 %b0:i16:i64
|
||||
%b0:i18:i16 = load %l3:*i16
|
||||
%b0:i19:i64 = typecast %b0:i18:i16 to i64
|
||||
%b0:i20:i64 = add %b0:i17:i64 %b0:i19:i64
|
||||
%b0:i21:i16 = load %l4:*i16
|
||||
%b0:i22:i64 = typecast %b0:i21:i16 to i64
|
||||
%b0:i23:i64 = add %b0:i20:i64 %b0:i22:i64
|
||||
%b0:i24:i32 = load %l5:*i32
|
||||
%b0:i25:i64 = typecast %b0:i24:i32 to i64
|
||||
%b0:i26:i64 = add %b0:i23:i64 %b0:i25:i64
|
||||
%b0:i27:i8 = load %l6:*i8
|
||||
%b0:i28:i64 = typecast %b0:i27:i8 to i64
|
||||
%b0:i29:i64 = add %b0:i26:i64 %b0:i28:i64
|
||||
%b0:i30:i64 = typecast 28:i32 to i64
|
||||
%b0:i31:u1 = cmp eq %b0:i29:i64 %b0:i30:i64
|
||||
%b0:i32:i32 = typecast %b0:i31:u1 to i32
|
||||
ret %b0:i32:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
19
examples/ir/typecast.ir
Normal file
19
examples/ir/typecast.ir
Normal file
@@ -0,0 +1,19 @@
|
||||
var i8 @temp = 0x00l
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i8 = typecast 61238:i64 to i8
|
||||
%b0:i1:unit = store %b0:i0:i8 @temp:*i8
|
||||
%b0:i2:i64 = typecast %b0:i0:i8 to i64
|
||||
%b0:i3:u1 = cmp ge %b0:i2:i64 2:i64
|
||||
%b0:i4:i32 = typecast %b0:i3:u1 to i32
|
||||
ret %b0:i4:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
21
examples/ir/typedef.ir
Normal file
21
examples/ir/typedef.ir
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:a
|
||||
%l1:*const i32:b
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:i32 = load %l0:*i32
|
||||
%b0:i2:unit = store %l0:*i32 %l1:**const i32
|
||||
%b0:i3:*i32 = load %l1:**const i32
|
||||
%b0:i4:unit = store 1:i32 %b0:i3:*i32
|
||||
%b0:i5:*i32 = load %l1:**const i32
|
||||
%b0:i6:i32 = load %b0:i5:*i32
|
||||
ret %b0:i6:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
21
examples/ir/unary.ir
Normal file
21
examples/ir/unary.ir
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:u8:temp
|
||||
|
||||
block b0:
|
||||
%b0:i0:u8 = typecast 0:i64 to u8
|
||||
%b0:i1:unit = store %b0:i0:u8 %l0:*u8
|
||||
%b0:i2:u8 = load %l0:*u8
|
||||
%b0:i3:u8 = sub %b0:i2:u8 1:u8
|
||||
%b0:i4:unit = store %b0:i3:u8 %l0:*u8
|
||||
%b0:i5:i32 = typecast %b0:i3:u8 to i32
|
||||
%b0:i6:u1 = cmp gt 1:i32 %b0:i5:i32
|
||||
%b0:i7:i32 = typecast %b0:i6:u1 to i32
|
||||
ret %b0:i7:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
82
examples/ir/while_continue_break.ir
Normal file
82
examples/ir/while_continue_break.ir
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
fun i32 @foo {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
%l0:i32:sum
|
||||
%l1:i32:i
|
||||
|
||||
block b0:
|
||||
%b0:i0:unit = store 0:i32 %l0:*i32
|
||||
%b0:i1:unit = store 0:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b1:
|
||||
%b1:i0:i32 = load %l1:*i32
|
||||
%b1:i1:u1 = cmp lt %b1:i0:i32 10:i32
|
||||
br %b1:i1:u1, b2(), b3()
|
||||
|
||||
block b2:
|
||||
%b2:i0:i32 = load %l1:*i32
|
||||
%b2:i1:u1 = cmp eq %b2:i0:i32 3:i32
|
||||
br %b2:i1:u1, b4(), b5()
|
||||
|
||||
block b3:
|
||||
%b3:i0:i32 = load %l0:*i32
|
||||
ret %b3:i0:i32
|
||||
|
||||
block b4:
|
||||
%b4:i0:i32 = load %l1:*i32
|
||||
%b4:i1:i32 = add %b4:i0:i32 1:i32
|
||||
%b4:i2:unit = store %b4:i1:i32 %l1:*i32
|
||||
j b1()
|
||||
|
||||
block b5:
|
||||
j b6()
|
||||
|
||||
block b6:
|
||||
%b6:i0:i32 = load %l0:*i32
|
||||
%b6:i1:i32 = load %l1:*i32
|
||||
%b6:i2:i32 = add %b6:i0:i32 %b6:i1:i32
|
||||
%b6:i3:unit = store %b6:i2:i32 %l0:*i32
|
||||
%b6:i4:i32 = load %l1:*i32
|
||||
%b6:i5:i32 = add %b6:i4:i32 1:i32
|
||||
%b6:i6:unit = store %b6:i5:i32 %l1:*i32
|
||||
%b6:i7:i32 = load %l1:*i32
|
||||
%b6:i8:u1 = cmp eq %b6:i7:i32 5:i32
|
||||
br %b6:i8:u1, b8(), b9()
|
||||
|
||||
block b7:
|
||||
j b6()
|
||||
|
||||
block b8:
|
||||
j b3()
|
||||
|
||||
block b9:
|
||||
j b10()
|
||||
|
||||
block b10:
|
||||
j b1()
|
||||
|
||||
block b11:
|
||||
j b10()
|
||||
|
||||
block b12:
|
||||
ret undef:i32
|
||||
}
|
||||
|
||||
fun i32 @main {
|
||||
init:
|
||||
bid: b0
|
||||
allocations:
|
||||
|
||||
|
||||
block b0:
|
||||
%b0:i0:i32 = call @foo()
|
||||
%b0:i1:u1 = cmp eq %b0:i0:i32 7:i32
|
||||
%b0:i2:i32 = typecast %b0:i1:u1 to i32
|
||||
ret %b0:i2:i32
|
||||
|
||||
block b1:
|
||||
ret 0:i32
|
||||
}
|
||||
257
src/asm/mod.rs
257
src/asm/mod.rs
@@ -1,4 +1,259 @@
|
||||
mod write_asm;
|
||||
|
||||
use crate::ir;
|
||||
|
||||
use core::convert::TryFrom;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct TODO {}
|
||||
|
||||
/// TODO
|
||||
pub struct Asm {}
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Asm {
|
||||
pub unit: TranslationUnit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct TranslationUnit {
|
||||
pub functions: Vec<Section<Function>>,
|
||||
pub variables: Vec<Section<Variable>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Section<T> {
|
||||
/// Section Headers provice size, offset, type, alignment and flags of the sections
|
||||
/// https://github.com/rv8-io/rv8-io.github.io/blob/master/asm.md#section-header
|
||||
pub header: Vec<Directive>,
|
||||
pub body: T,
|
||||
}
|
||||
|
||||
/// An object file is made up of multiple sections, with each section corresponding to
|
||||
/// distinct types of executable code or data.
|
||||
/// https://github.com/rv8-io/rv8-io.github.io/blob/master/asm.md#sections
|
||||
impl<T> Section<T> {
|
||||
pub fn new(header: Vec<Directive>, body: T) -> Self {
|
||||
Self { header, body }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Function {
|
||||
pub blocks: Vec<Block>,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn new(blocks: Vec<Block>) -> Self {
|
||||
Self { blocks }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Variable {
|
||||
todo: TODO,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Block {
|
||||
pub label: Option<Label>,
|
||||
pub instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn new(label: Option<Label>, instructions: Vec<Instruction>) -> Self {
|
||||
Self {
|
||||
label,
|
||||
instructions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The assembler implements a number of directives that control the assembly of instructions
|
||||
/// into an object file.
|
||||
/// https://github.com/rv8-io/rv8-io.github.io/blob/master/asm.md#assembler-directives
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Directive {
|
||||
/// .globl symbol
|
||||
Globl(Label),
|
||||
/// .type symbol, symbol_type
|
||||
Type(Label, SymbolType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SymbolType {
|
||||
Function,
|
||||
Object,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Instruction {
|
||||
/// R-type instruction format
|
||||
/// https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf (11p, 104p)
|
||||
RType {
|
||||
instr: RType,
|
||||
rd: Register,
|
||||
rs1: Register,
|
||||
rs2: Register,
|
||||
},
|
||||
/// I-type instruction format
|
||||
/// https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf (11p, 104p)
|
||||
IType {
|
||||
instr: IType,
|
||||
rd: Register,
|
||||
rs1: Register,
|
||||
imm: isize,
|
||||
},
|
||||
/// S-type instruction format
|
||||
/// https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf (11p, 104p)
|
||||
SType {
|
||||
instr: SType,
|
||||
rs1: Register,
|
||||
rs2: Register,
|
||||
imm: isize,
|
||||
},
|
||||
Pseudo(Pseudo),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum RType {
|
||||
Add(Option<DataSize>),
|
||||
Mul(Option<DataSize>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum IType {
|
||||
Load(DataSize),
|
||||
Addi(Option<DataSize>),
|
||||
}
|
||||
|
||||
impl IType {
|
||||
pub const LW: Self = Self::Load(DataSize::Word);
|
||||
pub const LD: Self = Self::Load(DataSize::Double);
|
||||
pub const ADDI: Self = Self::Addi(None);
|
||||
|
||||
pub fn load(dtype: ir::Dtype) -> Self {
|
||||
let data_align =
|
||||
DataSize::try_from(dtype).expect("`data_align` must be derived from `dtype`");
|
||||
Self::Load(data_align)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SType {
|
||||
Store(DataSize),
|
||||
}
|
||||
|
||||
impl SType {
|
||||
pub const SW: Self = Self::Store(DataSize::Word);
|
||||
pub const SD: Self = Self::Store(DataSize::Double);
|
||||
|
||||
pub fn store(dtype: ir::Dtype) -> Self {
|
||||
let data_align =
|
||||
DataSize::try_from(dtype).expect("`data_align` must be derived from `dtype`");
|
||||
Self::Store(data_align)
|
||||
}
|
||||
}
|
||||
|
||||
/// The assembler implements a number of convenience psuedo-instructions that are formed from
|
||||
/// instructions in the base ISA, but have implicit arguments or in some case reversed arguments,
|
||||
/// that result in distinct semantics.
|
||||
/// https://github.com/rv8-io/rv8-io.github.io/blob/master/asm.md#assembler-pseudo-instructions
|
||||
/// https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf (110p)
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Pseudo {
|
||||
/// li rd, immediate
|
||||
Li { rd: Register, imm: isize },
|
||||
/// mv rd, rs
|
||||
Mv { rs: Register, rd: Register },
|
||||
/// sext.w rd, rs
|
||||
SextW { rs: Register, rd: Register },
|
||||
/// j offset
|
||||
J { offset: Label },
|
||||
/// jr rs
|
||||
Jr { rs: Register },
|
||||
/// ret
|
||||
Ret,
|
||||
/// call offset
|
||||
Call { offset: Label },
|
||||
}
|
||||
|
||||
/// `Label` is used as branch, unconditional jump targets and symbol offsets.
|
||||
/// https://github.com/rv8-io/rv8-io.github.io/blob/master/asm.md#labels
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Label(pub String);
|
||||
|
||||
impl Label {
|
||||
pub fn new(name: &str, block_id: ir::BlockId) -> Self {
|
||||
let id = block_id.0;
|
||||
Self(format!(".{}_L{}", name, id))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DataSize {
|
||||
Byte,
|
||||
Half,
|
||||
Word,
|
||||
Double,
|
||||
}
|
||||
|
||||
impl TryFrom<ir::Dtype> for DataSize {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(dtype: ir::Dtype) -> Result<Self, Self::Error> {
|
||||
let width = match dtype {
|
||||
ir::Dtype::Int { width, .. } => width,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
let size = (width - 1) / ir::Dtype::BITS_OF_BYTE + 1;
|
||||
let align = match size {
|
||||
ir::Dtype::SIZE_OF_CHAR => Self::Byte,
|
||||
ir::Dtype::SIZE_OF_SHORT => Self::Half,
|
||||
ir::Dtype::SIZE_OF_INT => Self::Word,
|
||||
ir::Dtype::SIZE_OF_LONG => Self::Double,
|
||||
_ => panic!("there is no other possible case"),
|
||||
};
|
||||
|
||||
Ok(align)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add calling convention information (caller/callee-save registers)
|
||||
/// ABI name for RISC-V integer and floating-point register
|
||||
/// https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf (109p)
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
|
||||
pub enum Register {
|
||||
Zero,
|
||||
Ra,
|
||||
Sp,
|
||||
Gp,
|
||||
Tp,
|
||||
/// E.g., t0
|
||||
Temp(usize),
|
||||
/// E.g., s0
|
||||
Saved(usize),
|
||||
/// E.g., a0
|
||||
Arg(usize),
|
||||
}
|
||||
|
||||
impl Register {
|
||||
// TODO: add all possible registers in the future
|
||||
pub const S0: Self = Self::Saved(0);
|
||||
pub const A0: Self = Self::Arg(0);
|
||||
pub const A5: Self = Self::Arg(5);
|
||||
|
||||
pub fn temp(id: usize) -> Self {
|
||||
assert!(id <= 6);
|
||||
Self::Temp(id)
|
||||
}
|
||||
|
||||
pub fn saved(id: usize) -> Self {
|
||||
assert!(id <= 11);
|
||||
Self::Saved(id)
|
||||
}
|
||||
|
||||
pub fn arg(id: usize) -> Self {
|
||||
assert!(id <= 7);
|
||||
Self::Arg(id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,213 @@
|
||||
use std::io::{Result, Write};
|
||||
|
||||
use crate::asm::Asm;
|
||||
use crate::write_base::WriteLine;
|
||||
use crate::asm::*;
|
||||
use crate::write_base::*;
|
||||
|
||||
const INDENT: usize = 4;
|
||||
|
||||
impl WriteLine for Asm {
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
self.unit.write_line(indent, write)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteLine for TranslationUnit {
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
for function in &self.functions {
|
||||
function.write_line(indent, write)?;
|
||||
}
|
||||
|
||||
for variable in &self.variables {
|
||||
variable.write_line(indent, write)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: WriteLine> WriteLine for Section<T> {
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
for directive in &self.header {
|
||||
write_indent(indent + INDENT, write)?;
|
||||
writeln!(write, "{}", directive.write_string())?;
|
||||
}
|
||||
self.body.write_line(indent, write)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteLine for Function {
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
for block in &self.blocks {
|
||||
block.write_line(indent, write)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteLine for Variable {
|
||||
fn write_line(&self, _indent: usize, _write: &mut dyn Write) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteLine for Block {
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
if let Some(label) = &self.label {
|
||||
writeln!(write, "{}:", label.0)?;
|
||||
}
|
||||
|
||||
for instruction in &self.instructions {
|
||||
write_indent(indent + INDENT, write)?;
|
||||
writeln!(write, "{}", instruction.write_string())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for Directive {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Globl(label) => format!(".globl\t{}", label.0),
|
||||
Self::Type(symbol, symbol_type) => {
|
||||
format!(".type\t{}, {}", symbol.0, symbol_type.write_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for SymbolType {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Function => "@function",
|
||||
Self::Object => "@object",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for Instruction {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::RType {
|
||||
instr,
|
||||
rd,
|
||||
rs1,
|
||||
rs2,
|
||||
} => format!(
|
||||
"{}\t{},{},{}",
|
||||
instr.write_string(),
|
||||
rd.write_string(),
|
||||
rs1.write_string(),
|
||||
rs2.write_string()
|
||||
),
|
||||
Self::IType {
|
||||
instr,
|
||||
rd,
|
||||
rs1,
|
||||
imm,
|
||||
} => {
|
||||
if let IType::Load(_) = instr {
|
||||
format!(
|
||||
"{}\t{},{}({})",
|
||||
instr.write_string(),
|
||||
rd.write_string(),
|
||||
imm,
|
||||
rs1.write_string()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"{}\t{},{},{}",
|
||||
instr.write_string(),
|
||||
rd.write_string(),
|
||||
rs1.write_string(),
|
||||
imm
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::SType {
|
||||
instr,
|
||||
rs1,
|
||||
rs2,
|
||||
imm,
|
||||
} => format!(
|
||||
"{}\t{},{}({})",
|
||||
instr.write_string(),
|
||||
rs2.write_string(),
|
||||
imm,
|
||||
rs1.write_string()
|
||||
),
|
||||
Self::Pseudo(pseudo) => pseudo.write_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for RType {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Add(data_size) => format!("add{}", data_size.write_string()),
|
||||
Self::Mul(data_size) => format!("mul{}", data_size.write_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for IType {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Load(data_size) => format!("l{}", data_size.write_string()),
|
||||
Self::Addi(data_size) => format!("addi{}", data_size.write_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for SType {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Store(data_size) => format!("s{}", data_size.write_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for Pseudo {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Li { rd, imm } => format!("li\t{},{}", rd.write_string(), imm),
|
||||
Self::Mv { rs, rd } => format!("mv\t{},{}", rd.write_string(), rs.write_string()),
|
||||
Self::SextW { .. } => todo!(),
|
||||
Self::J { offset } => format!("j\t{}", offset.0),
|
||||
Self::Jr { rs } => format!("jr\t{}", rs.write_string()),
|
||||
Self::Ret => "ret".to_string(),
|
||||
Self::Call { offset } => format!("call\t{}", offset.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for DataSize {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Byte => "b",
|
||||
Self::Half => "h",
|
||||
Self::Word => "w",
|
||||
Self::Double => "d",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteString for Register {
|
||||
fn write_string(&self) -> String {
|
||||
match self {
|
||||
Self::Zero => "zero".to_string(),
|
||||
Self::Ra => "ra".to_string(),
|
||||
Self::Sp => "sp".to_string(),
|
||||
Self::Gp => "gp".to_string(),
|
||||
Self::Tp => "tp".to_string(),
|
||||
Self::Temp(id) => format!("t{}", id),
|
||||
Self::Saved(id) => format!("s{}", id),
|
||||
Self::Arg(id) => format!("a{}", id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,512 @@
|
||||
use crate::asm::Asm;
|
||||
use crate::asm;
|
||||
use crate::ir;
|
||||
use crate::ir::HasDtype;
|
||||
use crate::Translate;
|
||||
|
||||
use core::ops::Deref;
|
||||
use std::collections::HashMap;
|
||||
|
||||
struct StackInfo {
|
||||
/// Function name for generating the block labels
|
||||
name: String,
|
||||
/// Minimum stack size required to execute function
|
||||
stack_size: usize,
|
||||
/// Stack offsets of registers
|
||||
stack_offsets_registers: HashMap<ir::RegisterId, usize>,
|
||||
/// Stack offset for previous `ra` value
|
||||
stack_offset_ra: usize,
|
||||
/// Stack offset for previous `s0` value
|
||||
stack_offset_s0: usize,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Asmgen {}
|
||||
|
||||
impl Translate<ir::TranslationUnit> for Asmgen {
|
||||
type Target = Asm;
|
||||
type Target = asm::Asm;
|
||||
type Error = ();
|
||||
|
||||
fn translate(&mut self, _source: &ir::TranslationUnit) -> Result<Self::Target, Self::Error> {
|
||||
todo!()
|
||||
fn translate(&mut self, source: &ir::TranslationUnit) -> Result<Self::Target, Self::Error> {
|
||||
let mut functions = Vec::new();
|
||||
let mut _variables = Vec::new();
|
||||
for (name, decl) in &source.decls {
|
||||
match decl {
|
||||
ir::Declaration::Variable { .. } => todo!(),
|
||||
ir::Declaration::Function {
|
||||
signature,
|
||||
definition,
|
||||
} => {
|
||||
let definition = definition
|
||||
.as_ref()
|
||||
.expect("function must have its definition");
|
||||
let function = self.translate_function(
|
||||
name.clone(),
|
||||
signature,
|
||||
definition,
|
||||
&source.structs,
|
||||
)?;
|
||||
functions.push(function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(asm::Asm {
|
||||
unit: asm::TranslationUnit {
|
||||
functions,
|
||||
variables: _variables,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Asmgen {
|
||||
const STACK_ALIGNMENT: usize = 16;
|
||||
const SIZE_OF_S_ZERO: usize = 8;
|
||||
const SIZE_OF_RETURN_ADDRESS: usize = 8;
|
||||
|
||||
fn translate_function(
|
||||
&self,
|
||||
name: String,
|
||||
_signature: &ir::FunctionSignature,
|
||||
definition: &ir::FunctionDefinition,
|
||||
structs: &HashMap<String, Option<ir::Dtype>>,
|
||||
) -> Result<asm::Section<asm::Function>, ()> {
|
||||
// TODO: need to map function parameters and memory address
|
||||
// Map `RegisterId` and its memory address. The memory address is represented
|
||||
// by a distance from the stack pointer.
|
||||
let mut stack_offsets_registers = HashMap::new();
|
||||
|
||||
// Allocate memory for return address and s0(frame pointer).
|
||||
let mut required_size = Self::SIZE_OF_RETURN_ADDRESS + Self::SIZE_OF_S_ZERO;
|
||||
|
||||
// Allocate memory for local variables.
|
||||
for (i, alloc) in definition.allocations.iter().enumerate() {
|
||||
required_size += alloc.deref().size_align_of(structs).unwrap().0;
|
||||
let rid = ir::RegisterId::local(i);
|
||||
assert_eq!(stack_offsets_registers.insert(rid, required_size), None);
|
||||
}
|
||||
|
||||
// Allocate memory for saved registers.
|
||||
let required_size = definition
|
||||
.blocks
|
||||
.iter()
|
||||
.fold(required_size, |size, (bid, block)| {
|
||||
block
|
||||
.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(size, |size, (i, instr)| {
|
||||
let size = size + instr.deref().dtype().size_align_of(structs).unwrap().0;
|
||||
let rid = ir::RegisterId::temp(*bid, i);
|
||||
assert_eq!(stack_offsets_registers.insert(rid, size), None);
|
||||
size
|
||||
})
|
||||
});
|
||||
|
||||
// TODO: Allocate memory for next function args
|
||||
|
||||
let stack_size = ((required_size - 1) / Self::STACK_ALIGNMENT + 1) * Self::STACK_ALIGNMENT;
|
||||
let stack_offset_ra = stack_size - Self::SIZE_OF_RETURN_ADDRESS;
|
||||
let stack_offset_s0 = stack_offset_ra - Self::SIZE_OF_S_ZERO;
|
||||
let stack_info = StackInfo {
|
||||
name,
|
||||
stack_size,
|
||||
stack_offsets_registers,
|
||||
stack_offset_ra,
|
||||
stack_offset_s0,
|
||||
};
|
||||
|
||||
let mut function_section = asm::Section::new(Vec::new(), asm::Function::new(Vec::new()));
|
||||
|
||||
self.translate_section_header(&stack_info, &mut function_section)?;
|
||||
self.translate_init_block(&stack_info, &mut function_section)?;
|
||||
definition
|
||||
.blocks
|
||||
.iter()
|
||||
.map(|(bid, block)| {
|
||||
self.translate_block(&stack_info, *bid, block, &mut function_section)
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
self.translate_final_block(&stack_info, &mut function_section)?;
|
||||
|
||||
Ok(function_section)
|
||||
}
|
||||
|
||||
fn translate_section_header(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
function_section: &mut asm::Section<asm::Function>,
|
||||
) -> Result<(), ()> {
|
||||
// .globl func_name
|
||||
function_section
|
||||
.header
|
||||
.push(asm::Directive::Globl(asm::Label(stack_info.name.clone())));
|
||||
// .type func_name, @function
|
||||
function_section.header.push(asm::Directive::Type(
|
||||
asm::Label(stack_info.name.clone()),
|
||||
asm::SymbolType::Function,
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_init_block(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
function_section: &mut asm::Section<asm::Function>,
|
||||
) -> Result<(), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
// addi sp, sp, -stack_size
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: asm::IType::ADDI,
|
||||
rd: asm::Register::Sp,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: -(stack_info.stack_size as isize),
|
||||
});
|
||||
// sd ra, stack_offset_ra(sp)
|
||||
instrs.push(asm::Instruction::SType {
|
||||
instr: asm::SType::SD,
|
||||
rs2: asm::Register::Ra,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_offset_ra as isize,
|
||||
});
|
||||
// sd s0, stack_offset_s0(sp)
|
||||
instrs.push(asm::Instruction::SType {
|
||||
instr: asm::SType::SD,
|
||||
rs2: asm::Register::S0,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_offset_s0 as isize,
|
||||
});
|
||||
// addi s0, sp, stack_size
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: asm::IType::ADDI,
|
||||
rd: asm::Register::S0,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_size as isize,
|
||||
});
|
||||
|
||||
let enter_block = asm::Block::new(Some(asm::Label(stack_info.name.clone())), instrs);
|
||||
function_section.body.blocks.push(enter_block);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_final_block(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
function_section: &mut asm::Section<asm::Function>,
|
||||
) -> Result<(), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
// ld ra, stack_offset_ra(sp)
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: asm::IType::LD,
|
||||
rd: asm::Register::Ra,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_offset_ra as isize,
|
||||
});
|
||||
// ld s0, stack_offset_s0(sp)
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: asm::IType::LD,
|
||||
rd: asm::Register::S0,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_offset_s0 as isize,
|
||||
});
|
||||
// addi sp, sp, stack_size
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: asm::IType::ADDI,
|
||||
rd: asm::Register::Sp,
|
||||
rs1: asm::Register::Sp,
|
||||
imm: stack_info.stack_size as isize,
|
||||
});
|
||||
// jr ra
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::Jr {
|
||||
rs: asm::Register::Ra,
|
||||
}));
|
||||
|
||||
let exit_label = asm::Label(format!(".{}_END", stack_info.name));
|
||||
let exit_block = asm::Block::new(Some(exit_label), instrs);
|
||||
function_section.body.blocks.push(exit_block);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_block(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
bid: ir::BlockId,
|
||||
block: &ir::Block,
|
||||
function_section: &mut asm::Section<asm::Function>,
|
||||
) -> Result<(), ()> {
|
||||
let instrs_for_phinodes = block
|
||||
.phinodes
|
||||
.iter()
|
||||
.map(|p| self.translate_phinode(stack_info, p.deref()))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
let instrs_for_instructions = block
|
||||
.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(iid, instr)| {
|
||||
let dest_rid = ir::RegisterId::temp(bid, iid);
|
||||
self.translate_instruction(stack_info, dest_rid, instr.deref())
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
let instrs_for_block_exit = self.translate_block_exit(stack_info, &block.exit)?;
|
||||
|
||||
let instrs = vec![
|
||||
instrs_for_phinodes,
|
||||
instrs_for_instructions,
|
||||
instrs_for_block_exit,
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let label = asm::Label::new(&stack_info.name, bid);
|
||||
let block = asm::Block::new(Some(label), instrs);
|
||||
function_section.body.blocks.push(block);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_phinode(
|
||||
&self,
|
||||
_stack_info: &StackInfo,
|
||||
_phinode: &ir::Dtype,
|
||||
) -> Result<Vec<asm::Instruction>, ()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn translate_instruction(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
dest_rid: ir::RegisterId,
|
||||
instruction: &ir::Instruction,
|
||||
) -> Result<Vec<asm::Instruction>, ()> {
|
||||
let (mut instrs, rd) = match instruction {
|
||||
ir::Instruction::Store { ptr, value } => {
|
||||
let instrs = self.translate_store(stack_info, ptr, value)?;
|
||||
return Ok(instrs);
|
||||
}
|
||||
ir::Instruction::Load { ptr } => self.translate_load(stack_info, ptr)?,
|
||||
ir::Instruction::Call { callee, args, .. } => self.translate_call(callee, args)?,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
// Store `rd` into memory
|
||||
let dtype = instruction.dtype();
|
||||
let dist_s0_to_ptr = stack_info
|
||||
.stack_offsets_registers
|
||||
.get(&dest_rid)
|
||||
.expect("address matched with `rid` must exist");
|
||||
let store_instr = asm::SType::store(dtype);
|
||||
|
||||
instrs.push(asm::Instruction::SType {
|
||||
instr: store_instr,
|
||||
rs2: rd,
|
||||
rs1: asm::Register::S0,
|
||||
imm: -(*dist_s0_to_ptr as isize),
|
||||
});
|
||||
|
||||
Ok(instrs)
|
||||
}
|
||||
|
||||
fn translate_store(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
ptr: &ir::Operand,
|
||||
value: &ir::Operand,
|
||||
) -> Result<Vec<asm::Instruction>, ()> {
|
||||
let (instrs_for_value, reg_of_value) = self.translate_operand(stack_info, value)?;
|
||||
|
||||
let mut instrs = Vec::new();
|
||||
let (rid, dtype) = ptr.get_register().expect("`ptr` must be register");
|
||||
let dist_s0_to_ptr = stack_info
|
||||
.stack_offsets_registers
|
||||
.get(rid)
|
||||
.expect("address matched with `rid` must exist");
|
||||
let inner_dtype = dtype
|
||||
.get_pointer_inner()
|
||||
.expect("`dtype` must be pointer type");
|
||||
let store_instr = asm::SType::store(inner_dtype.clone());
|
||||
|
||||
instrs.push(asm::Instruction::SType {
|
||||
instr: store_instr,
|
||||
rs2: reg_of_value,
|
||||
rs1: asm::Register::S0,
|
||||
imm: -(*dist_s0_to_ptr as isize),
|
||||
});
|
||||
|
||||
let instrs = vec![instrs_for_value, instrs]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
Ok(instrs)
|
||||
}
|
||||
|
||||
fn translate_load(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
ptr: &ir::Operand,
|
||||
) -> Result<(Vec<asm::Instruction>, asm::Register), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
|
||||
let (rid, dtype) = ptr.get_register().expect("`ptr` must be register");
|
||||
let dist_s0_to_ptr = stack_info
|
||||
.stack_offsets_registers
|
||||
.get(rid)
|
||||
.expect("address matched with `rid` must exist");
|
||||
let inner_dtype = dtype
|
||||
.get_pointer_inner()
|
||||
.expect("`dtype` must be pointer type");
|
||||
let load_instr = asm::IType::load(inner_dtype.clone());
|
||||
|
||||
// TODO: select register which is not occupied
|
||||
let rd = asm::Register::A5;
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: load_instr,
|
||||
rd,
|
||||
rs1: asm::Register::S0,
|
||||
imm: -(*dist_s0_to_ptr as isize),
|
||||
});
|
||||
|
||||
Ok((instrs, rd))
|
||||
}
|
||||
|
||||
fn translate_call(
|
||||
&self,
|
||||
callee: &ir::Operand,
|
||||
_args: &[ir::Operand],
|
||||
) -> Result<(Vec<asm::Instruction>, asm::Register), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
|
||||
// TODO: translate pass the args
|
||||
|
||||
match callee {
|
||||
ir::Operand::Constant(constant) => {
|
||||
if let ir::Constant::GlobalVariable { name, dtype } = constant {
|
||||
assert!(dtype.get_function_inner().is_some());
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
|
||||
offset: asm::Label(name.clone()),
|
||||
}));
|
||||
} else {
|
||||
panic!("`callee` must be `GlobalVariable`")
|
||||
}
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
// TODO: select register which is not occupied
|
||||
let rd = asm::Register::A5;
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||
rs: asm::Register::A0,
|
||||
rd,
|
||||
}));
|
||||
|
||||
Ok((instrs, rd))
|
||||
}
|
||||
|
||||
fn translate_block_exit(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
block_exit: &ir::BlockExit,
|
||||
) -> Result<Vec<asm::Instruction>, ()> {
|
||||
match block_exit {
|
||||
ir::BlockExit::Return { value } => self.translate_return(stack_info, value),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_return(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
value: &ir::Operand,
|
||||
) -> Result<Vec<asm::Instruction>, ()> {
|
||||
let (instrs_for_value, rs) = self.translate_operand(stack_info, value)?;
|
||||
|
||||
let mut instrs = Vec::new();
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||
rs,
|
||||
rd: asm::Register::A0,
|
||||
}));
|
||||
// Jump to exit block
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
||||
offset: asm::Label(format!(".{}_END", stack_info.name)),
|
||||
}));
|
||||
|
||||
let instrs = vec![instrs_for_value, instrs]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
Ok(instrs)
|
||||
}
|
||||
|
||||
fn translate_operand(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
operand: &ir::Operand,
|
||||
) -> Result<(Vec<asm::Instruction>, asm::Register), ()> {
|
||||
match operand {
|
||||
ir::Operand::Constant(constant) => self.translate_constant(stack_info, constant),
|
||||
ir::Operand::Register { rid, dtype } => self.translate_register(stack_info, rid, dtype),
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_constant(
|
||||
&self,
|
||||
_stack_info: &StackInfo,
|
||||
constant: &ir::Constant,
|
||||
) -> Result<(Vec<asm::Instruction>, asm::Register), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
|
||||
match constant {
|
||||
// TODO: consider width and signed option in the future
|
||||
ir::Constant::Int { value, .. } => {
|
||||
// TODO: select register which is not occupied
|
||||
let rd = asm::Register::A5;
|
||||
instrs.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||
rd,
|
||||
imm: *value as isize,
|
||||
}));
|
||||
Ok((instrs, rd))
|
||||
}
|
||||
ir::Constant::Undef { .. } => {
|
||||
// TODO: select register which is not occupied
|
||||
Ok((instrs, asm::Register::A5))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_register(
|
||||
&self,
|
||||
stack_info: &StackInfo,
|
||||
rid: &ir::RegisterId,
|
||||
dtype: &ir::Dtype,
|
||||
) -> Result<(Vec<asm::Instruction>, asm::Register), ()> {
|
||||
let mut instrs = Vec::new();
|
||||
|
||||
let dist_s0_to_ptr = stack_info
|
||||
.stack_offsets_registers
|
||||
.get(rid)
|
||||
.expect("address matched with `rid` must exist");
|
||||
let load_instr = asm::IType::load(dtype.clone());
|
||||
|
||||
// TODO: select register which is not occupied
|
||||
let rd = asm::Register::A5;
|
||||
instrs.push(asm::Instruction::IType {
|
||||
instr: load_instr,
|
||||
rd,
|
||||
rs1: asm::Register::S0,
|
||||
imm: -(*dist_s0_to_ptr as isize),
|
||||
});
|
||||
|
||||
Ok((instrs, rd))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,6 +573,15 @@ impl Dtype {
|
||||
);
|
||||
|
||||
let fields = fields.unwrap();
|
||||
if fields.is_empty() {
|
||||
return Ok(Self::Struct {
|
||||
name,
|
||||
fields: Some(fields),
|
||||
is_const,
|
||||
size_align_offsets: Some((0, 1, Vec::new())),
|
||||
});
|
||||
}
|
||||
|
||||
let align_of = fields
|
||||
.iter()
|
||||
.map(|f| f.deref().size_align_of(structs))
|
||||
@@ -709,6 +718,7 @@ impl Dtype {
|
||||
Self::Unit { .. } => todo!(),
|
||||
Self::Int { .. } => true,
|
||||
Self::Float { .. } => true,
|
||||
Self::Pointer { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,13 +644,28 @@ mod calculator {
|
||||
|
||||
calculate_float_binary_operator_expression(op, lhs, rhs, lhs_w)
|
||||
}
|
||||
(Value::Pointer { bid, .. }, Value::Pointer { bid: other_bid, .. }) => match op {
|
||||
(
|
||||
Value::Pointer { bid, offset, .. },
|
||||
Value::Pointer {
|
||||
bid: other_bid,
|
||||
offset: other_offset,
|
||||
..
|
||||
},
|
||||
) => match op {
|
||||
ast::BinaryOperator::Equals => {
|
||||
let result = if bid == other_bid { 1 } else { 0 };
|
||||
let result = if bid == other_bid && offset == other_offset {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Ok(Value::int(result, 1, false))
|
||||
}
|
||||
ast::BinaryOperator::NotEquals => {
|
||||
let result = if bid != other_bid { 1 } else { 0 };
|
||||
let result = if !(bid == other_bid && offset == other_offset) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Ok(Value::int(result, 1, false))
|
||||
}
|
||||
_ => todo!(
|
||||
|
||||
Reference in New Issue
Block a user