fspl/generator/control-flow_test.go

653 lines
17 KiB
Go

package generator
import "testing"
func TestBranchAssign (test *testing.T) {
testString (test,
`define void @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
%1 = alloca i64
br i1 true, label %2, label %4
2:
store i64 5, ptr %1
br label %3
3:
ret void
4:
store i64 6, ptr %1
br label %3
}
`,
`
[main] = {
x:Int
if true then {
x = 5
} else {
x = 6
}
}
`)
}
func TestBranchAssignNoFalse (test *testing.T) {
testString (test,
`define void @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
%1 = alloca i64
br i1 true, label %2, label %3
2:
store i64 5, ptr %1
br label %3
3:
ret void
}
`,
`
[main] = {
x:Int
if true then {
x = 5
}
}
`)
}
func TestBranchResult (test *testing.T) {
testString (test,
`define void @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
%1 = alloca i64
br i1 true, label %2, label %5
2:
br label %3
3:
%4 = phi i64 [ 5, %2 ], [ 6, %5 ]
store i64 %4, ptr %1
ret void
5:
br label %3
}
`,
`
[main] = {
x:Int = if true then 5 else 6
}
`)
}
func TestLoopSimple (test *testing.T) {
testString (test,
`define void @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
br label %1
1:
br label %1
2:
ret void
}
`,
`
[main] = {
loop {
}
}
`)
}
func TestLoopResult (test *testing.T) {
testString (test,
`define void @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
%1 = alloca i64
br label %2
2:
br label %3
3:
%4 = phi i64 [ 5, %2 ]
store i64 %4, ptr %1
ret void
}
`,
`
[main] = {
x:Int = loop {
[break 5]
}
}
`)
}
func TestLoopBranchResult (test *testing.T) {
testString (test,
`define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::main"() {
0:
%1 = alloca i64
store i64 6, ptr %1
br label %2
2:
%3 = load i64, ptr %1
%4 = icmp slt i64 %3, 3
br i1 %4, label %7, label %10
5:
%6 = phi i64 [ %8, %7 ]
ret i64 %6
7:
%8 = load i64, ptr %1
br label %5
9:
br label %2
10:
%11 = load i64, ptr %1
%12 = sub i64 %11, 1
store i64 %12, ptr %1
br label %9
}
`,
`
[main]:Int = {
y:Int = 6
loop {
if [< y 3]
then [break y]
else {
y = [-- y]
}
}
}
`)
}
func TestMatch (test *testing.T) {
testString (test,
`%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::matchToInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
0:
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
%2 = alloca i64
%3 = alloca double
%4 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
%5 = load i64, ptr %4
switch i64 %5, label %6 [
i64 7620767046192759206, label %8
i64 9186060094042213285, label %12
]
6:
%7 = phi i64 [ %11, %8 ], [ %16, %12 ], [ zeroinitializer, %0 ]
ret i64 %7
8:
%9 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%10 = load i64, ptr %9
store i64 %10, ptr %2
%11 = load i64, ptr %2
br label %6
12:
%13 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%14 = load double, ptr %13
store double %14, ptr %3
%15 = load double, ptr %3
%16 = fptosi double %15 to i64
br label %6
}
`,
`
U: (| Int F64)
[matchToInt u:U]:Int = match u
| u:Int u
| u:F64 [~Int u]
`)
}
func TestMatchReturn (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
define %"AAAAAAAAAAAAAAAAAAAAAA==::Bool" @"0zNZN147MN2wzMAQ6NS2dQ==::isInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
0:
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
%2 = alloca i64
%3 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
%4 = load i64, ptr %3
switch i64 %4, label %5 [
i64 7620767046192759206, label %6
]
5:
ret i1 false
6:
%7 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%8 = load i64, ptr %7
store i64 %8, ptr %2
ret i1 true
}
`,
`
U: (| Int F64)
[isInt u:U]:Bool = {
match u | u:Int [return true]
false
}
`)
}
func TestMatchReturnValueUsed (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
define %"AAAAAAAAAAAAAAAAAAAAAA==::Bool" @"0zNZN147MN2wzMAQ6NS2dQ==::isInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
0:
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
%2 = alloca i64
%3 = alloca double
%4 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
%5 = load i64, ptr %4
switch i64 %5, label %6 [
i64 7620767046192759206, label %8
i64 9186060094042213285, label %11
]
6:
%7 = phi i1 [ false, %11 ], [ zeroinitializer, %0 ]
ret i1 %7
8:
%9 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%10 = load i64, ptr %9
store i64 %10, ptr %2
ret i1 true
11:
%12 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%13 = load double, ptr %12
store double %13, ptr %3
br label %6
}
`,
`
U: (| Int F64)
[isInt u:U]:Bool = match u
| u:Int [return true]
| u:F64 false
`)
}
func TestMatchUnionUnderComplete (test *testing.T) {
testString (test,
`%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64
%"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" }
define void @"0zNZN147MN2wzMAQ6NS2dQ==::matchToInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
0:
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
%2 = alloca i64
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
%4 = alloca [3 x i8]
%5 = alloca double
%6 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
%7 = alloca [3 x i8]
%8 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
%9 = load i64, ptr %8
switch i64 %9, label %10 [
i64 7620767046192759206, label %11
i64 9186060094042213285, label %20
]
10:
ret void
11:
%12 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%13 = load i64, ptr %12
store i64 %13, ptr %2
%14 = getelementptr [3 x i8], ptr %4, i32 0, i32 0
store i8 73, ptr %14
%15 = getelementptr [3 x i8], ptr %4, i32 0, i32 1
store i8 110, ptr %15
%16 = getelementptr [3 x i8], ptr %4, i32 0, i32 2
store i8 116, ptr %16
%17 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 0
store ptr %4, ptr %17
%18 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %18
%19 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %19)
br label %10
20:
%21 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%22 = load double, ptr %21
store double %22, ptr %5
%23 = getelementptr [3 x i8], ptr %7, i32 0, i32 0
store i8 70, ptr %23
%24 = getelementptr [3 x i8], ptr %7, i32 0, i32 1
store i8 54, ptr %24
%25 = getelementptr [3 x i8], ptr %7, i32 0, i32 2
store i8 52, ptr %25
%26 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 0
store ptr %7, ptr %26
%27 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %27
%28 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %28)
br label %10
}
declare void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str)
`,
`
U: (| Int F64 UInt)
[print str:String]
[matchToInt u:U] = match u
| u:Int [print 'Int']
| u:F64 [print 'F64']
`)
}
func TestMatchDefault (test *testing.T) {
testString (test,
`%"0zNZN147MN2wzMAQ6NS2dQ==::U" = type { i64, i64 }
%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64
%"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" }
define void @"0zNZN147MN2wzMAQ6NS2dQ==::matchToInt"(%"0zNZN147MN2wzMAQ6NS2dQ==::U" %u) {
0:
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::U"
store %"0zNZN147MN2wzMAQ6NS2dQ==::U" %u, ptr %1
%2 = alloca i64
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
%4 = alloca [3 x i8]
%5 = alloca double
%6 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
%7 = alloca [3 x i8]
%8 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
%9 = alloca [3 x i8]
%10 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 0
%11 = load i64, ptr %10
switch i64 %11, label %31 [
i64 7620767046192759206, label %13
i64 9186060094042213285, label %22
]
12:
ret void
13:
%14 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%15 = load i64, ptr %14
store i64 %15, ptr %2
%16 = getelementptr [3 x i8], ptr %4, i32 0, i32 0
store i8 73, ptr %16
%17 = getelementptr [3 x i8], ptr %4, i32 0, i32 1
store i8 110, ptr %17
%18 = getelementptr [3 x i8], ptr %4, i32 0, i32 2
store i8 116, ptr %18
%19 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 0
store ptr %4, ptr %19
%20 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %20
%21 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %21)
br label %12
22:
%23 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::U", ptr %1, i32 0, i32 1
%24 = load double, ptr %23
store double %24, ptr %5
%25 = getelementptr [3 x i8], ptr %7, i32 0, i32 0
store i8 70, ptr %25
%26 = getelementptr [3 x i8], ptr %7, i32 0, i32 1
store i8 54, ptr %26
%27 = getelementptr [3 x i8], ptr %7, i32 0, i32 2
store i8 52, ptr %27
%28 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 0
store ptr %7, ptr %28
%29 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6, i32 0, i32 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %29
%30 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %6
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %30)
br label %12
31:
%32 = getelementptr [3 x i8], ptr %9, i32 0, i32 0
store i8 105, ptr %32
%33 = getelementptr [3 x i8], ptr %9, i32 0, i32 1
store i8 100, ptr %33
%34 = getelementptr [3 x i8], ptr %9, i32 0, i32 2
store i8 107, ptr %34
%35 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8, i32 0, i32 0
store ptr %9, ptr %35
%36 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8, i32 0, i32 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 3, ptr %36
%37 = load %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %8
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %37)
br label %12
}
declare void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str)
`,
`
U: (| Int F64 UInt)
[print str:String]
[matchToInt u:U] = match u
| u:Int [print 'Int']
| u:F64 [print 'F64']
* [print 'idk']
`)
}
func TestSwitchReturn (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
define %"AAAAAAAAAAAAAAAAAAAAAA==::Bool" @"0zNZN147MN2wzMAQ6NS2dQ==::is5"(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = load i64, ptr %1
switch i64 %2, label %3 [
i64 5, label %4
]
3:
ret i1 false
4:
ret i1 true
}
`,
`
[is5 x:Int]:Bool = {
switch x | 5 [return true]
false
}
`)
}
func TestSwitchReturnValueUsed (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
define %"AAAAAAAAAAAAAAAAAAAAAA==::Bool" @"0zNZN147MN2wzMAQ6NS2dQ==::is5"(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = load i64, ptr %1
switch i64 %2, label %6 [
i64 5, label %5
]
3:
%4 = phi i1 [ false, %6 ]
ret i1 %4
5:
ret i1 true
6:
br label %3
}
`,
`
[is5 x:Int]:Bool = switch x
| 5 [return true]
* false
`)
}
func TestIfElseReturnValueUsed (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Bool" = type i1
define %"AAAAAAAAAAAAAAAAAAAAAA==::Bool" @"0zNZN147MN2wzMAQ6NS2dQ==::is5"(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = load i64, ptr %1
%3 = icmp eq i64 %2, 5
br i1 %3, label %4, label %7
4:
br label %5
5:
%6 = phi i1 [ true, %4 ]
ret i1 %6
7:
ret i1 false
}
`,
`
[is5 x:Int]:Bool = if [= x 5]
then true
else [return false]
`)
}
func TestIfElseBreakValueUsed (test *testing.T) {
testString (test,
`define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::f"(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = alloca i64
br label %3
3:
%4 = load i64, ptr %1
%5 = icmp eq i64 %4, 5
br i1 %5, label %8, label %11
6:
%7 = phi i64 [ 0, %8 ]
ret i64 %7
8:
br label %6
9:
%10 = phi i64 [ %12, %11 ]
store i64 %10, ptr %2
br label %3
11:
%12 = load i64, ptr %1
br label %9
}
`,
`
[f x:Int]: Int = loop {
y:Int = if [= x 5]
then [break 0]
else x
}
`)
}
func TestFor (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64
%"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" }
%"AAAAAAAAAAAAAAAAAAAAAA==::Byte" = type i8
define void @"0zNZN147MN2wzMAQ6NS2dQ==::f"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str) {
0:
%1 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
store %"AAAAAAAAAAAAAAAAAAAAAA==::String" %str, ptr %1
%2 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Index"
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Byte"
br label %4
4:
%5 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 1
%6 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %5
%7 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%8 = icmp ult %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %7, %6
br i1 %8, label %9, label %18
9:
%10 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 0
%11 = load ptr, ptr %10
%12 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%13 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %11, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %12
%14 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %13
store %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %14, ptr %3
%15 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %3
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %15)
%16 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%17 = add %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %16, 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %17, ptr %2
br label %4
18:
ret void
}
declare void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %x)
define void @"0zNZN147MN2wzMAQ6NS2dQ==::g"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str) {
0:
%1 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
store %"AAAAAAAAAAAAAAAAAAAAAA==::String" %str, ptr %1
%2 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Index"
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" zeroinitializer, ptr %2
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Byte"
br label %4
4:
%5 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 1
%6 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %5
%7 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%8 = icmp ult %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %7, %6
br i1 %8, label %9, label %18
9:
%10 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 0
%11 = load ptr, ptr %10
%12 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%13 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %11, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %12
%14 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %13
store %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %14, ptr %3
%15 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %3
call void @"0zNZN147MN2wzMAQ6NS2dQ==::print"(%"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %15)
%16 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%17 = add %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %16, 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %17, ptr %2
br label %4
18:
ret void
}
`,
`
[print x:Byte]
[f str:String] = for c:Byte in str { [print c] }
[g str:String] = for i:Index c:Byte in str [print c]
`)}
func TestForBreak (test *testing.T) {
testString (test,
`%"AAAAAAAAAAAAAAAAAAAAAA==::Byte" = type i8
%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64
%"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" }
define %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" @"0zNZN147MN2wzMAQ6NS2dQ==::f"(%"AAAAAAAAAAAAAAAAAAAAAA==::String" %str) {
0:
%1 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::String"
store %"AAAAAAAAAAAAAAAAAAAAAA==::String" %str, ptr %1
%2 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Index"
%3 = alloca %"AAAAAAAAAAAAAAAAAAAAAA==::Byte"
br label %4
4:
%5 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 1
%6 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %5
%7 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%8 = icmp ult %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %7, %6
br i1 %8, label %9, label %18
9:
%10 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %1, i32 0, i32 0
%11 = load ptr, ptr %10
%12 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%13 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %11, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %12
%14 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %13
store %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %14, ptr %3
%15 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Byte", ptr %3
%16 = load %"AAAAAAAAAAAAAAAAAAAAAA==::Index", ptr %2
%17 = add %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %16, 1
store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" %17, ptr %2
br label %18
18:
%19 = phi %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" [ %15, %9 ], [ zeroinitializer, %4 ]
ret %"AAAAAAAAAAAAAAAAAAAAAA==::Byte" %19
}
`,
`
[f str:String]:Byte = for c:Byte in str [break c]
`)}