Add foreach_r tests

This commit is contained in:
Dmitry Atamanov
2022-08-16 19:33:00 +05:00
committed by Christoffer Lerno
parent 9a3e7fd34b
commit 15586b3076
20 changed files with 1417 additions and 189 deletions

View File

@@ -1,6 +1,6 @@
// #target: macos-x64
module foo;
module test;
struct Foo
{
int[] x;
@@ -31,10 +31,10 @@ fn void main()
extern fn int printf(char *fmt, ...);
/* #expect: foo.ll
/* #expect: test.ll
; Function Attrs: nounwind
define void @foo_main() #0 {
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
@@ -81,4 +81,14 @@ loop.body2: ; preds = %loop.body
loop.exit: ; preds = %loop.body2, %loop.cond
ret void
}
}
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, i8** %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,72 @@
// #target: macos-x64
module test;
fn void test()
{
int[3] x;
int g = 0;
foreach_r (z : x)
{
if (z > 0) break;
if (z == 1) continue;
g += z;
}
}
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_test() #0 {
entry:
%x = alloca [3 x i32], align 4
%g = alloca i32, align 4
%.anon = alloca i64, align 8
%z = alloca i32, align 4
%0 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 0
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 1
store i32 0, i32* %1, align 4
%2 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 2
store i32 0, i32* %2, align 4
store i32 0, i32* %g, align 4
store i64 3, i64* %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %if.exit3, %if.then2, %entry
%3 = load i64, i64* %.anon, align 8
%gt = icmp ugt i64 %3, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%4 = load i64, i64* %.anon, align 8
%sub = sub i64 %4, 1
store i64 %sub, i64* %.anon, align 8
%5 = load i64, i64* %.anon, align 8
%6 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 %5
%7 = load i32, i32* %6, align 4
store i32 %7, i32* %z, align 4
%8 = load i32, i32* %z, align 4
%gt1 = icmp sgt i32 %8, 0
br i1 %gt1, label %if.then, label %if.exit
if.then: ; preds = %loop.body
br label %loop.exit
if.exit: ; preds = %loop.body
%9 = load i32, i32* %z, align 4
%eq = icmp eq i32 %9, 1
br i1 %eq, label %if.then2, label %if.exit3
if.then2: ; preds = %if.exit
br label %loop.cond
if.exit3: ; preds = %if.exit
%10 = load i32, i32* %g, align 4
%11 = load i32, i32* %z, align 4
%add = add i32 %10, %11
store i32 %add, i32* %g, align 4
br label %loop.cond
loop.exit: ; preds = %if.then, %loop.cond
ret void
}

View File

@@ -0,0 +1,353 @@
// #target: macos-x64
module test;
extern fn void printf(char*, ...);
fn void main()
{
float[3] foo = { 2, 4.5, 8 };
float[<3>] foo2 = { 2, 4.5, 8 };
foreach_r (a : foo)
{
printf("Value: %f\n", a);
}
foreach_r (float* &a : foo)
{
*a *= 2;
printf("Value: %f\n", *a);
}
foreach_r (void* &a : foo)
{
printf("Value: %f\n", *((float*)(a)));
}
foreach_r (i, a : foo)
{
printf("Value[%d]: %f\n", i, a);
}
foreach_r (char i, double a : foo)
{
printf("Value2[%d]: %f\n", i, a);
}
foreach_r (double a : foo)
{
printf("Value3: %f\n", a);
}
foreach_r (a : foo2)
{
printf("Value: %f\n", a);
}
foreach_r (i, a : foo2)
{
printf("Value[%d]: %f\n", i, a);
}
foreach_r (char i, double a : foo2)
{
printf("Value2[%d]: %f\n", i, a);
}
foreach_r (double a : foo2)
{
printf("Value3: %f\n", a);
}
}
/* #expect: test.ll
@.__const = private unnamed_addr constant [3 x float] [float 2.000000e+00, float 4.500000e+00, float 8.000000e+00], align 4
@.str = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.1 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.2 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.3 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1
@.str.4 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1
@.str.5 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1
@.str.6 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.7 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1
@.str.8 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1
@.str.9 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%foo = alloca [3 x float], align 4
%foo2 = alloca <3 x float>, align 16
%.anon = alloca i64, align 8
%a = alloca float, align 4
%.anon1 = alloca i64, align 8
%a6 = alloca float*, align 8
%.anon9 = alloca i64, align 8
%a14 = alloca i8*, align 8
%.anon18 = alloca i64, align 8
%i = alloca i64, align 8
%a23 = alloca float, align 4
%.anon26 = alloca i64, align 8
%i31 = alloca i8, align 1
%a32 = alloca double, align 8
%.anon35 = alloca i64, align 8
%a40 = alloca double, align 8
%.anon43 = alloca i64, align 8
%a48 = alloca float, align 4
%.anon51 = alloca i64, align 8
%i56 = alloca i64, align 8
%a57 = alloca float, align 4
%.anon60 = alloca i64, align 8
%i65 = alloca i8, align 1
%a67 = alloca double, align 8
%.anon71 = alloca i64, align 8
%a76 = alloca double, align 8
%0 = bitcast [3 x float]* %foo to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x float]* @.__const to i8*), i32 12, i1 false)
store <3 x float> <float 2.000000e+00, float 4.500000e+00, float 8.000000e+00>, <3 x float>* %foo2, align 16
store i64 3, i64* %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %loop.body, %entry
%1 = load i64, i64* %.anon, align 8
%gt = icmp ugt i64 %1, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%2 = load i64, i64* %.anon, align 8
%sub = sub i64 %2, 1
store i64 %sub, i64* %.anon, align 8
%3 = load i64, i64* %.anon, align 8
%4 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %3
%5 = load float, float* %4, align 4
store float %5, float* %a, align 4
%6 = load float, float* %a, align 4
%fpfpext = fpext float %6 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), double %fpfpext)
br label %loop.cond
loop.exit: ; preds = %loop.cond
store i64 3, i64* %.anon1, align 8
br label %loop.cond2
loop.cond2: ; preds = %loop.body4, %loop.exit
%7 = load i64, i64* %.anon1, align 8
%gt3 = icmp ugt i64 %7, 0
br i1 %gt3, label %loop.body4, label %loop.exit8
loop.body4: ; preds = %loop.cond2
%8 = load i64, i64* %.anon1, align 8
%sub5 = sub i64 %8, 1
store i64 %sub5, i64* %.anon1, align 8
%9 = load i64, i64* %.anon1, align 8
%10 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %9
store float* %10, float** %a6, align 8
%11 = load float*, float** %a6, align 8
%12 = load float, float* %11, align 8
%fmul = fmul float %12, 2.000000e+00
store float %fmul, float* %11, align 8
%13 = load float*, float** %a6, align 8
%14 = load float, float* %13, align 8
%fpfpext7 = fpext float %14 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), double %fpfpext7)
br label %loop.cond2
loop.exit8: ; preds = %loop.cond2
store i64 3, i64* %.anon9, align 8
br label %loop.cond10
loop.cond10: ; preds = %loop.body12, %loop.exit8
%15 = load i64, i64* %.anon9, align 8
%gt11 = icmp ugt i64 %15, 0
br i1 %gt11, label %loop.body12, label %loop.exit17
loop.body12: ; preds = %loop.cond10
%16 = load i64, i64* %.anon9, align 8
%sub13 = sub i64 %16, 1
store i64 %sub13, i64* %.anon9, align 8
%17 = load i64, i64* %.anon9, align 8
%18 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %17
%ptrptr = bitcast float* %18 to i8*
store i8* %ptrptr, i8** %a14, align 8
%19 = load i8*, i8** %a14, align 8
%ptrptr15 = bitcast i8* %19 to float*
%20 = load float, float* %ptrptr15, align 8
%fpfpext16 = fpext float %20 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), double %fpfpext16)
br label %loop.cond10
loop.exit17: ; preds = %loop.cond10
store i64 3, i64* %.anon18, align 8
br label %loop.cond19
loop.cond19: ; preds = %loop.body21, %loop.exit17
%21 = load i64, i64* %.anon18, align 8
%gt20 = icmp ugt i64 %21, 0
br i1 %gt20, label %loop.body21, label %loop.exit25
loop.body21: ; preds = %loop.cond19
%22 = load i64, i64* %.anon18, align 8
%sub22 = sub i64 %22, 1
store i64 %sub22, i64* %.anon18, align 8
%23 = load i64, i64* %.anon18, align 8
store i64 %23, i64* %i, align 8
%24 = load i64, i64* %.anon18, align 8
%25 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %24
%26 = load float, float* %25, align 4
store float %26, float* %a23, align 4
%27 = load i64, i64* %i, align 8
%28 = load float, float* %a23, align 4
%fpfpext24 = fpext float %28 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i32 0, i32 0), i64 %27, double %fpfpext24)
br label %loop.cond19
loop.exit25: ; preds = %loop.cond19
store i64 3, i64* %.anon26, align 8
br label %loop.cond27
loop.cond27: ; preds = %loop.body29, %loop.exit25
%29 = load i64, i64* %.anon26, align 8
%gt28 = icmp ugt i64 %29, 0
br i1 %gt28, label %loop.body29, label %loop.exit34
loop.body29: ; preds = %loop.cond27
%30 = load i64, i64* %.anon26, align 8
%sub30 = sub i64 %30, 1
store i64 %sub30, i64* %.anon26, align 8
%31 = load i64, i64* %.anon26, align 8
%ztrunc = trunc i64 %31 to i8
store i8 %ztrunc, i8* %i31, align 1
%32 = load i64, i64* %.anon26, align 8
%33 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %32
%34 = load float, float* %33, align 4
%fpfpext33 = fpext float %34 to double
store double %fpfpext33, double* %a32, align 8
%35 = load i8, i8* %i31, align 1
%uisiext = zext i8 %35 to i32
%36 = load double, double* %a32, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.4, i32 0, i32 0), i32 %uisiext, double %36)
br label %loop.cond27
loop.exit34: ; preds = %loop.cond27
store i64 3, i64* %.anon35, align 8
br label %loop.cond36
loop.cond36: ; preds = %loop.body38, %loop.exit34
%37 = load i64, i64* %.anon35, align 8
%gt37 = icmp ugt i64 %37, 0
br i1 %gt37, label %loop.body38, label %loop.exit42
loop.body38: ; preds = %loop.cond36
%38 = load i64, i64* %.anon35, align 8
%sub39 = sub i64 %38, 1
store i64 %sub39, i64* %.anon35, align 8
%39 = load i64, i64* %.anon35, align 8
%40 = getelementptr inbounds [3 x float], [3 x float]* %foo, i64 0, i64 %39
%41 = load float, float* %40, align 4
%fpfpext41 = fpext float %41 to double
store double %fpfpext41, double* %a40, align 8
%42 = load double, double* %a40, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.5, i32 0, i32 0), double %42)
br label %loop.cond36
loop.exit42: ; preds = %loop.cond36
store i64 3, i64* %.anon43, align 8
br label %loop.cond44
loop.cond44: ; preds = %loop.body46, %loop.exit42
%43 = load i64, i64* %.anon43, align 8
%gt45 = icmp ugt i64 %43, 0
br i1 %gt45, label %loop.body46, label %loop.exit50
loop.body46: ; preds = %loop.cond44
%44 = load i64, i64* %.anon43, align 8
%sub47 = sub i64 %44, 1
store i64 %sub47, i64* %.anon43, align 8
%45 = load <3 x float>, <3 x float>* %foo2, align 16
%46 = load i64, i64* %.anon43, align 8
%47 = extractelement <3 x float> %45, i64 %46
store float %47, float* %a48, align 4
%48 = load float, float* %a48, align 4
%fpfpext49 = fpext float %48 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.6, i32 0, i32 0), double %fpfpext49)
br label %loop.cond44
loop.exit50: ; preds = %loop.cond44
store i64 3, i64* %.anon51, align 8
br label %loop.cond52
loop.cond52: ; preds = %loop.body54, %loop.exit50
%49 = load i64, i64* %.anon51, align 8
%gt53 = icmp ugt i64 %49, 0
br i1 %gt53, label %loop.body54, label %loop.exit59
loop.body54: ; preds = %loop.cond52
%50 = load i64, i64* %.anon51, align 8
%sub55 = sub i64 %50, 1
store i64 %sub55, i64* %.anon51, align 8
%51 = load i64, i64* %.anon51, align 8
store i64 %51, i64* %i56, align 8
%52 = load <3 x float>, <3 x float>* %foo2, align 16
%53 = load i64, i64* %.anon51, align 8
%54 = extractelement <3 x float> %52, i64 %53
store float %54, float* %a57, align 4
%55 = load i64, i64* %i56, align 8
%56 = load float, float* %a57, align 4
%fpfpext58 = fpext float %56 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.7, i32 0, i32 0), i64 %55, double %fpfpext58)
br label %loop.cond52
loop.exit59: ; preds = %loop.cond52
store i64 3, i64* %.anon60, align 8
br label %loop.cond61
loop.cond61: ; preds = %loop.body63, %loop.exit59
%57 = load i64, i64* %.anon60, align 8
%gt62 = icmp ugt i64 %57, 0
br i1 %gt62, label %loop.body63, label %loop.exit70
loop.body63: ; preds = %loop.cond61
%58 = load i64, i64* %.anon60, align 8
%sub64 = sub i64 %58, 1
store i64 %sub64, i64* %.anon60, align 8
%59 = load i64, i64* %.anon60, align 8
%ztrunc66 = trunc i64 %59 to i8
store i8 %ztrunc66, i8* %i65, align 1
%60 = load <3 x float>, <3 x float>* %foo2, align 16
%61 = load i64, i64* %.anon60, align 8
%62 = extractelement <3 x float> %60, i64 %61
%fpfpext68 = fpext float %62 to double
store double %fpfpext68, double* %a67, align 8
%63 = load i8, i8* %i65, align 1
%uisiext69 = zext i8 %63 to i32
%64 = load double, double* %a67, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.8, i32 0, i32 0), i32 %uisiext69, double %64)
br label %loop.cond61
loop.exit70: ; preds = %loop.cond61
store i64 3, i64* %.anon71, align 8
br label %loop.cond72
loop.cond72: ; preds = %loop.body74, %loop.exit70
%65 = load i64, i64* %.anon71, align 8
%gt73 = icmp ugt i64 %65, 0
br i1 %gt73, label %loop.body74, label %loop.exit78
loop.body74: ; preds = %loop.cond72
%66 = load i64, i64* %.anon71, align 8
%sub75 = sub i64 %66, 1
store i64 %sub75, i64* %.anon71, align 8
%67 = load <3 x float>, <3 x float>* %foo2, align 16
%68 = load i64, i64* %.anon71, align 8
%69 = extractelement <3 x float> %67, i64 %68
%fpfpext77 = fpext float %69 to double
store double %fpfpext77, double* %a76, align 8
%70 = load double, double* %a76, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.9, i32 0, i32 0), double %70)
br label %loop.cond72
loop.exit78: ; preds = %loop.cond72
ret void
}
; Function Attrs: nounwind
define i32 @main(i32 %0, i8** %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,94 @@
// #target: macos-x64
module test;
struct Foo
{
int[] x;
}
macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat)
{
return foo.x[index];
}
macro usize Foo.@operator_len(Foo &foo) @operator(len)
{
return foo.x.len;
}
fn void main()
{
int[*] i = { 1, 3, 10 };
Foo x = { &i };
foreach_r FOO: (int f : x) {
printf("%d\n", f);
while (1)
{
break FOO;
}
}
}
extern fn int printf(char *fmt, ...);
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
%.anon = alloca i64, align 8
%f = alloca i32, align 4
%index = alloca i64, align 8
%0 = bitcast [3 x i32]* %i to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%2 = bitcast [3 x i32]* %i to i32*
%3 = insertvalue %"int[]" undef, i32* %2, 0
%4 = insertvalue %"int[]" %3, i64 3, 1
store %"int[]" %4, %"int[]"* %1, align 8
%5 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%6 = getelementptr inbounds %"int[]", %"int[]"* %5, i32 0, i32 1
%7 = load i64, i64* %6, align 8
store i64 %7, i64* %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %entry
%8 = load i64, i64* %.anon, align 8
%gt = icmp ugt i64 %8, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%9 = load i64, i64* %.anon, align 8
%sub = sub i64 %9, 1
store i64 %sub, i64* %.anon, align 8
%10 = load i64, i64* %.anon, align 8
store i64 %10, i64* %index, align 8
%11 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%12 = getelementptr inbounds %"int[]", %"int[]"* %11, i32 0, i32 0
%13 = load i32*, i32** %12, align 8
%14 = load i64, i64* %index, align 8
%ptroffset = getelementptr inbounds i32, i32* %13, i64 %14
%15 = load i32, i32* %ptroffset, align 4
store i32 %15, i32* %f, align 4
%16 = load i32, i32* %f, align 4
%17 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %16)
br label %loop.body1
loop.body1: ; preds = %loop.body
br label %loop.exit
loop.exit: ; preds = %loop.body1, %loop.cond
ret void
}
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, i8** %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,15 @@
fn void test1()
{
int x;
foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int'
}
define Test1 = distinct int;
fn void test2()
{
Test1 x;
foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'Test1'
}

View File

@@ -0,0 +1,93 @@
// #target: macos-x64
module test;
struct Foo
{
int[] x;
}
macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat)
{
return foo.x[index];
}
macro usize Foo.@operator_len(Foo &foo) @operator(len)
{
return foo.x.len;
}
fn void main()
{
int[*] i = { 1, 3, 10 };
Foo x = { &i };
foreach_r FOO: (int f : x) {
printf("%d\n", f);
while (1)
{
break FOO;
}
}
}
extern fn int printf(char *fmt, ...);
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
%.anon = alloca i64, align 8
%f = alloca i32, align 4
%index = alloca i64, align 8
%0 = bitcast [3 x i32]* %i to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%2 = bitcast [3 x i32]* %i to i32*
%3 = insertvalue %"int[]" undef, i32* %2, 0
%4 = insertvalue %"int[]" %3, i64 3, 1
store %"int[]" %4, %"int[]"* %1, align 8
%5 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%6 = getelementptr inbounds %"int[]", %"int[]"* %5, i32 0, i32 1
%7 = load i64, i64* %6, align 8
store i64 %7, i64* %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %entry
%8 = load i64, i64* %.anon, align 8
%gt = icmp ugt i64 %8, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%9 = load i64, i64* %.anon, align 8
%sub = sub i64 %9, 1
store i64 %sub, i64* %.anon, align 8
%10 = load i64, i64* %.anon, align 8
store i64 %10, i64* %index, align 8
%11 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%12 = getelementptr inbounds %"int[]", %"int[]"* %11, i32 0, i32 0
%13 = load i32*, i32** %12, align 8
%14 = load i64, i64* %index, align 8
%ptroffset = getelementptr inbounds i32, i32* %13, i64 %14
%15 = load i32, i32* %ptroffset, align 4
store i32 %15, i32* %f, align 4
%16 = load i32, i32* %f, align 4
%17 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %16)
br label %loop.body1
loop.body1: ; preds = %loop.body
br label %loop.exit
loop.exit: ; preds = %loop.body1, %loop.cond
ret void
}
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, i8** %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,54 @@
module test;
extern fn void foo();
int[3] z;
fn void test1()
{
int x;
foreach_r (a : x) // #error: It's not possible to enumerate an expression of type 'int'.
{
foo();
}
}
fn void test2()
{
foreach_r (a : z) foo();
foreach_r (i, a : z) foo();
foreach_r (double i, a : z); // #error: Index must be an integer type, 'double' is not valid.
}
fn void test3()
{
foreach_r (&a : z) foo();
foreach_r (&i, &a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'?
}
fn void test4()
{
foreach_r (&a : z) foo();
foreach_r (&i, a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'?
}
fn void test5()
{
foreach_r (int! y : z) foo(); // #error: The variable may not be a failable.
}
fn void test6()
{
foreach_r (int! i, y : z) foo(); // #error: The index may not be a failable.
}
fn void test7()
{
foreach_r (int a : { 1, 2, 3 }) foo();
foreach_r (a : { 1, 2, 3 }) foo(); // #error: Add the type of your variable here if you want to iterate over
}
fn void test8()
{
foreach_r (int a : { z }) foo(); // #error: 'int[3]' into 'int'
}

View File

@@ -0,0 +1,5 @@
fn void test9()
{
foreach_r (int a : { [2] = 1 }) foo();
foreach_r (int a : { [2] = 2, 1 }) foo(); // #error: Normal initialization cannot be mixed with designated initialization.
}

View File

@@ -1,94 +0,0 @@
// #target: macos-x64
module test;
import std::io;
fn void main()
{
int[*] x = { 1, 5, 10 };
int[] y = &x;
foreach_r (int i, val : y)
{
io::printfln("%d: %d", i, val);
}
}
/* #expect: test.ll
entry:
%x = alloca [3 x i32], align 4
%y = alloca %"int[]", align 8
%.anon = alloca i64, align 8
%i = alloca i32, align 4
%val = alloca i32, align 4
%retparam = alloca i64, align 8
%taddr = alloca %"char[]", align 8
%vararg = alloca %"variant[]", align 8
%varargslots = alloca [2 x %variant], align 16
%0 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = bitcast [3 x i32]* %x to i32*
%2 = insertvalue %"int[]" undef, i32* %1, 0
%3 = insertvalue %"int[]" %2, i64 3, 1
store %"int[]" %3, %"int[]"* %y, align 8
%4 = getelementptr inbounds %"int[]", %"int[]"* %y, i32 0, i32 1
%5 = load i64, i64* %4, align 8
store i64 %5, i64* %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %voiderr, %entry
%6 = load i64, i64* %.anon, align 8
%gt = icmp ugt i64 %6, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%7 = load i64, i64* %.anon, align 8
%sub = sub i64 %7, 1
store i64 %sub, i64* %.anon, align 8
%8 = load i64, i64* %.anon, align 8
%uisitrunc = trunc i64 %8 to i32
store i32 %uisitrunc, i32* %i, align 4
%9 = getelementptr inbounds %"int[]", %"int[]"* %y, i32 0, i32 0
%10 = load i32*, i32** %9, align 8
%11 = load i64, i64* %.anon, align 8
%ptroffset = getelementptr inbounds i32, i32* %10, i64 %11
%12 = load i32, i32* %ptroffset, align 4
store i32 %12, i32* %val, align 4
store %"char[]" { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i64 6 }, %"char[]"* %taddr, align 8
%13 = bitcast %"char[]"* %taddr to { i8*, i64 }*
%14 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %13, i32 0, i32 0
%lo = load i8*, i8** %14, align 8
%15 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %13, i32 0, i32 1
%hi = load i64, i64* %15, align 8
%16 = bitcast i32* %i to i8*
%17 = insertvalue %variant undef, i8* %16, 0
%18 = insertvalue %variant %17, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1
%19 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 0
store %variant %18, %variant* %19, align 16
%20 = bitcast i32* %val to i8*
%21 = insertvalue %variant undef, i8* %20, 0
%22 = insertvalue %variant %21, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1
%23 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 1
store %variant %22, %variant* %23, align 16
%24 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1
store i64 2, i64* %24, align 8
%25 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0
%26 = bitcast [2 x %variant]* %varargslots to %variant*
store %variant* %26, %variant** %25, align 8
%27 = bitcast %"variant[]"* %vararg to { i8*, i64 }*
%28 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %27, i32 0, i32 0
%lo1 = load i8*, i8** %28, align 8
%29 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %27, i32 0, i32 1
%hi2 = load i64, i64* %29, align 8
%30 = call i64 @std_io_printfln(i64* %retparam, i8* %lo, i64 %hi, i8* %lo1, i64 %hi2)
%not_err = icmp eq i64 %30, 0
br i1 %not_err, label %after_check, label %voiderr
after_check: ; preds = %loop.body
br label %voiderr
voiderr: ; preds = %after_check, %loop.body
br label %loop.cond
loop.exit: ; preds = %loop.cond
ret void
}

View File

@@ -0,0 +1,12 @@
module test;
fn void test()
{
int[3]! x;
int g;
foreach_r (z : x) // #error: The expression may not be failable.
{
g += z;
x[0] = 1;
}
}

View File

@@ -1,6 +1,6 @@
// #target: macos-x64
module foo;
module test;
struct Foo
{
int[] x;
@@ -31,10 +31,10 @@ fn void main()
extern fn int printf(char *fmt, ...);
/* #expect: foo.ll
/* #expect: test.ll
; Function Attrs: nounwind
define void @foo_main() #0 {
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
@@ -79,4 +79,14 @@ loop.body2: ; preds = %loop.body
loop.exit: ; preds = %loop.body2, %loop.cond
ret void
}
}
; Function Attrs: nounwind
declare i32 @printf(ptr, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, ptr %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,72 @@
// #target: macos-x64
module test;
fn void test()
{
int[3] x;
int g = 0;
foreach_r (z : x)
{
if (z > 0) break;
if (z == 1) continue;
g += z;
}
}
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_test() #0 {
entry:
%x = alloca [3 x i32], align 4
%g = alloca i32, align 4
%.anon = alloca i64, align 8
%z = alloca i32, align 4
%0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 0
store i32 0, ptr %0, align 4
%1 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1
store i32 0, ptr %1, align 4
%2 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 2
store i32 0, ptr %2, align 4
store i32 0, ptr %g, align 4
store i64 3, ptr %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %if.exit3, %if.then2, %entry
%3 = load i64, ptr %.anon, align 8
%gt = icmp ugt i64 %3, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%4 = load i64, ptr %.anon, align 8
%sub = sub i64 %4, 1
store i64 %sub, ptr %.anon, align 8
%5 = load i64, ptr %.anon, align 8
%6 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 %5
%7 = load i32, ptr %6, align 4
store i32 %7, ptr %z, align 4
%8 = load i32, ptr %z, align 4
%gt1 = icmp sgt i32 %8, 0
br i1 %gt1, label %if.then, label %if.exit
if.then: ; preds = %loop.body
br label %loop.exit
if.exit: ; preds = %loop.body
%9 = load i32, ptr %z, align 4
%eq = icmp eq i32 %9, 1
br i1 %eq, label %if.then2, label %if.exit3
if.then2: ; preds = %if.exit
br label %loop.cond
if.exit3: ; preds = %if.exit
%10 = load i32, ptr %g, align 4
%11 = load i32, ptr %z, align 4
%add = add i32 %10, %11
store i32 %add, ptr %g, align 4
br label %loop.cond
loop.exit: ; preds = %if.then, %loop.cond
ret void
}

View File

@@ -0,0 +1,350 @@
// #target: macos-x64
module test;
extern fn void printf(char*, ...);
fn void main()
{
float[3] foo = { 2, 4.5, 8 };
float[<3>] foo2 = { 2, 4.5, 8 };
foreach_r (a : foo)
{
printf("Value: %f\n", a);
}
foreach_r (float* &a : foo)
{
*a *= 2;
printf("Value: %f\n", *a);
}
foreach_r (void* &a : foo)
{
printf("Value: %f\n", *((float*)(a)));
}
foreach_r (i, a : foo)
{
printf("Value[%d]: %f\n", i, a);
}
foreach_r (char i, double a : foo)
{
printf("Value2[%d]: %f\n", i, a);
}
foreach_r (double a : foo)
{
printf("Value3: %f\n", a);
}
foreach_r (a : foo2)
{
printf("Value: %f\n", a);
}
foreach_r (i, a : foo2)
{
printf("Value[%d]: %f\n", i, a);
}
foreach_r (char i, double a : foo2)
{
printf("Value2[%d]: %f\n", i, a);
}
foreach_r (double a : foo2)
{
printf("Value3: %f\n", a);
}
}
/* #expect: test.ll
@.__const = private unnamed_addr constant [3 x float] [float 2.000000e+00, float 4.500000e+00, float 8.000000e+00], align 4
@.str = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.1 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.2 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.3 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1
@.str.4 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1
@.str.5 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1
@.str.6 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1
@.str.7 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1
@.str.8 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1
@.str.9 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1
; Function Attrs: nounwind
declare void @printf(ptr, ...) #0
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%foo = alloca [3 x float], align 4
%foo2 = alloca <3 x float>, align 16
%.anon = alloca i64, align 8
%a = alloca float, align 4
%.anon1 = alloca i64, align 8
%a6 = alloca ptr, align 8
%.anon9 = alloca i64, align 8
%a14 = alloca ptr, align 8
%.anon17 = alloca i64, align 8
%i = alloca i64, align 8
%a22 = alloca float, align 4
%.anon25 = alloca i64, align 8
%i30 = alloca i8, align 1
%a31 = alloca double, align 8
%.anon34 = alloca i64, align 8
%a39 = alloca double, align 8
%.anon42 = alloca i64, align 8
%a47 = alloca float, align 4
%.anon50 = alloca i64, align 8
%i55 = alloca i64, align 8
%a56 = alloca float, align 4
%.anon59 = alloca i64, align 8
%i64 = alloca i8, align 1
%a66 = alloca double, align 8
%.anon70 = alloca i64, align 8
%a75 = alloca double, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 @.__const, i32 12, i1 false)
store <3 x float> <float 2.000000e+00, float 4.500000e+00, float 8.000000e+00>, ptr %foo2, align 16
store i64 3, ptr %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %loop.body, %entry
%0 = load i64, ptr %.anon, align 8
%gt = icmp ugt i64 %0, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%1 = load i64, ptr %.anon, align 8
%sub = sub i64 %1, 1
store i64 %sub, ptr %.anon, align 8
%2 = load i64, ptr %.anon, align 8
%3 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %2
%4 = load float, ptr %3, align 4
store float %4, ptr %a, align 4
%5 = load float, ptr %a, align 4
%fpfpext = fpext float %5 to double
call void (ptr, ...) @printf(ptr @.str, double %fpfpext)
br label %loop.cond
loop.exit: ; preds = %loop.cond
store i64 3, ptr %.anon1, align 8
br label %loop.cond2
loop.cond2: ; preds = %loop.body4, %loop.exit
%6 = load i64, ptr %.anon1, align 8
%gt3 = icmp ugt i64 %6, 0
br i1 %gt3, label %loop.body4, label %loop.exit8
loop.body4: ; preds = %loop.cond2
%7 = load i64, ptr %.anon1, align 8
%sub5 = sub i64 %7, 1
store i64 %sub5, ptr %.anon1, align 8
%8 = load i64, ptr %.anon1, align 8
%9 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %8
store ptr %9, ptr %a6, align 8
%10 = load ptr, ptr %a6, align 8
%11 = load float, ptr %10, align 8
%fmul = fmul float %11, 2.000000e+00
store float %fmul, ptr %10, align 8
%12 = load ptr, ptr %a6, align 8
%13 = load float, ptr %12, align 8
%fpfpext7 = fpext float %13 to double
call void (ptr, ...) @printf(ptr @.str.1, double %fpfpext7)
br label %loop.cond2
loop.exit8: ; preds = %loop.cond2
store i64 3, ptr %.anon9, align 8
br label %loop.cond10
loop.cond10: ; preds = %loop.body12, %loop.exit8
%14 = load i64, ptr %.anon9, align 8
%gt11 = icmp ugt i64 %14, 0
br i1 %gt11, label %loop.body12, label %loop.exit16
loop.body12: ; preds = %loop.cond10
%15 = load i64, ptr %.anon9, align 8
%sub13 = sub i64 %15, 1
store i64 %sub13, ptr %.anon9, align 8
%16 = load i64, ptr %.anon9, align 8
%17 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %16
store ptr %17, ptr %a14, align 8
%18 = load ptr, ptr %a14, align 8
%19 = load float, ptr %18, align 8
%fpfpext15 = fpext float %19 to double
call void (ptr, ...) @printf(ptr @.str.2, double %fpfpext15)
br label %loop.cond10
loop.exit16: ; preds = %loop.cond10
store i64 3, ptr %.anon17, align 8
br label %loop.cond18
loop.cond18: ; preds = %loop.body20, %loop.exit16
%20 = load i64, ptr %.anon17, align 8
%gt19 = icmp ugt i64 %20, 0
br i1 %gt19, label %loop.body20, label %loop.exit24
loop.body20: ; preds = %loop.cond18
%21 = load i64, ptr %.anon17, align 8
%sub21 = sub i64 %21, 1
store i64 %sub21, ptr %.anon17, align 8
%22 = load i64, ptr %.anon17, align 8
store i64 %22, ptr %i, align 8
%23 = load i64, ptr %.anon17, align 8
%24 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %23
%25 = load float, ptr %24, align 4
store float %25, ptr %a22, align 4
%26 = load i64, ptr %i, align 8
%27 = load float, ptr %a22, align 4
%fpfpext23 = fpext float %27 to double
call void (ptr, ...) @printf(ptr @.str.3, i64 %26, double %fpfpext23)
br label %loop.cond18
loop.exit24: ; preds = %loop.cond18
store i64 3, ptr %.anon25, align 8
br label %loop.cond26
loop.cond26: ; preds = %loop.body28, %loop.exit24
%28 = load i64, ptr %.anon25, align 8
%gt27 = icmp ugt i64 %28, 0
br i1 %gt27, label %loop.body28, label %loop.exit33
loop.body28: ; preds = %loop.cond26
%29 = load i64, ptr %.anon25, align 8
%sub29 = sub i64 %29, 1
store i64 %sub29, ptr %.anon25, align 8
%30 = load i64, ptr %.anon25, align 8
%ztrunc = trunc i64 %30 to i8
store i8 %ztrunc, ptr %i30, align 1
%31 = load i64, ptr %.anon25, align 8
%32 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %31
%33 = load float, ptr %32, align 4
%fpfpext32 = fpext float %33 to double
store double %fpfpext32, ptr %a31, align 8
%34 = load i8, ptr %i30, align 1
%uisiext = zext i8 %34 to i32
%35 = load double, ptr %a31, align 8
call void (ptr, ...) @printf(ptr @.str.4, i32 %uisiext, double %35)
br label %loop.cond26
loop.exit33: ; preds = %loop.cond26
store i64 3, ptr %.anon34, align 8
br label %loop.cond35
loop.cond35: ; preds = %loop.body37, %loop.exit33
%36 = load i64, ptr %.anon34, align 8
%gt36 = icmp ugt i64 %36, 0
br i1 %gt36, label %loop.body37, label %loop.exit41
loop.body37: ; preds = %loop.cond35
%37 = load i64, ptr %.anon34, align 8
%sub38 = sub i64 %37, 1
store i64 %sub38, ptr %.anon34, align 8
%38 = load i64, ptr %.anon34, align 8
%39 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %38
%40 = load float, ptr %39, align 4
%fpfpext40 = fpext float %40 to double
store double %fpfpext40, ptr %a39, align 8
%41 = load double, ptr %a39, align 8
call void (ptr, ...) @printf(ptr @.str.5, double %41)
br label %loop.cond35
loop.exit41: ; preds = %loop.cond35
store i64 3, ptr %.anon42, align 8
br label %loop.cond43
loop.cond43: ; preds = %loop.body45, %loop.exit41
%42 = load i64, ptr %.anon42, align 8
%gt44 = icmp ugt i64 %42, 0
br i1 %gt44, label %loop.body45, label %loop.exit49
loop.body45: ; preds = %loop.cond43
%43 = load i64, ptr %.anon42, align 8
%sub46 = sub i64 %43, 1
store i64 %sub46, ptr %.anon42, align 8
%44 = load <3 x float>, ptr %foo2, align 16
%45 = load i64, ptr %.anon42, align 8
%46 = extractelement <3 x float> %44, i64 %45
store float %46, ptr %a47, align 4
%47 = load float, ptr %a47, align 4
%fpfpext48 = fpext float %47 to double
call void (ptr, ...) @printf(ptr @.str.6, double %fpfpext48)
br label %loop.cond43
loop.exit49: ; preds = %loop.cond43
store i64 3, ptr %.anon50, align 8
br label %loop.cond51
loop.cond51: ; preds = %loop.body53, %loop.exit49
%48 = load i64, ptr %.anon50, align 8
%gt52 = icmp ugt i64 %48, 0
br i1 %gt52, label %loop.body53, label %loop.exit58
loop.body53: ; preds = %loop.cond51
%49 = load i64, ptr %.anon50, align 8
%sub54 = sub i64 %49, 1
store i64 %sub54, ptr %.anon50, align 8
%50 = load i64, ptr %.anon50, align 8
store i64 %50, ptr %i55, align 8
%51 = load <3 x float>, ptr %foo2, align 16
%52 = load i64, ptr %.anon50, align 8
%53 = extractelement <3 x float> %51, i64 %52
store float %53, ptr %a56, align 4
%54 = load i64, ptr %i55, align 8
%55 = load float, ptr %a56, align 4
%fpfpext57 = fpext float %55 to double
call void (ptr, ...) @printf(ptr @.str.7, i64 %54, double %fpfpext57)
br label %loop.cond51
loop.exit58: ; preds = %loop.cond51
store i64 3, ptr %.anon59, align 8
br label %loop.cond60
loop.cond60: ; preds = %loop.body62, %loop.exit58
%56 = load i64, ptr %.anon59, align 8
%gt61 = icmp ugt i64 %56, 0
br i1 %gt61, label %loop.body62, label %loop.exit69
loop.body62: ; preds = %loop.cond60
%57 = load i64, ptr %.anon59, align 8
%sub63 = sub i64 %57, 1
store i64 %sub63, ptr %.anon59, align 8
%58 = load i64, ptr %.anon59, align 8
%ztrunc65 = trunc i64 %58 to i8
store i8 %ztrunc65, ptr %i64, align 1
%59 = load <3 x float>, ptr %foo2, align 16
%60 = load i64, ptr %.anon59, align 8
%61 = extractelement <3 x float> %59, i64 %60
%fpfpext67 = fpext float %61 to double
store double %fpfpext67, ptr %a66, align 8
%62 = load i8, ptr %i64, align 1
%uisiext68 = zext i8 %62 to i32
%63 = load double, ptr %a66, align 8
call void (ptr, ...) @printf(ptr @.str.8, i32 %uisiext68, double %63)
br label %loop.cond60
loop.exit69: ; preds = %loop.cond60
store i64 3, ptr %.anon70, align 8
br label %loop.cond71
loop.cond71: ; preds = %loop.body73, %loop.exit69
%64 = load i64, ptr %.anon70, align 8
%gt72 = icmp ugt i64 %64, 0
br i1 %gt72, label %loop.body73, label %loop.exit77
loop.body73: ; preds = %loop.cond71
%65 = load i64, ptr %.anon70, align 8
%sub74 = sub i64 %65, 1
store i64 %sub74, ptr %.anon70, align 8
%66 = load <3 x float>, ptr %foo2, align 16
%67 = load i64, ptr %.anon70, align 8
%68 = extractelement <3 x float> %66, i64 %67
%fpfpext76 = fpext float %68 to double
store double %fpfpext76, ptr %a75, align 8
%69 = load double, ptr %a75, align 8
call void (ptr, ...) @printf(ptr @.str.9, double %69)
br label %loop.cond71
loop.exit77: ; preds = %loop.cond71
ret void
}
; Function Attrs: nounwind
define i32 @main(i32 %0, ptr %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,92 @@
// #target: macos-x64
module test;
struct Foo
{
int[] x;
}
macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat)
{
return foo.x[index];
}
macro usize Foo.@operator_len(Foo &foo) @operator(len)
{
return foo.x.len;
}
fn void main()
{
int[*] i = { 1, 3, 10 };
Foo x = { &i };
foreach_r FOO: (int f : x) {
printf("%d\n", f);
while (1)
{
break FOO;
}
}
}
extern fn int printf(char *fmt, ...);
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
%.anon = alloca i64, align 8
%f = alloca i32, align 4
%index = alloca i64, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %i, ptr align 4 @.__const, i32 12, i1 false)
%0 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%1 = insertvalue %"int[]" undef, ptr %i, 0
%2 = insertvalue %"int[]" %1, i64 3, 1
store %"int[]" %2, ptr %0, align 8
%3 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%4 = getelementptr inbounds %"int[]", ptr %3, i32 0, i32 1
%5 = load i64, ptr %4, align 8
store i64 %5, ptr %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %entry
%6 = load i64, ptr %.anon, align 8
%gt = icmp ugt i64 %6, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%7 = load i64, ptr %.anon, align 8
%sub = sub i64 %7, 1
store i64 %sub, ptr %.anon, align 8
%8 = load i64, ptr %.anon, align 8
store i64 %8, ptr %index, align 8
%9 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%10 = getelementptr inbounds %"int[]", ptr %9, i32 0, i32 0
%11 = load ptr, ptr %10, align 8
%12 = load i64, ptr %index, align 8
%ptroffset = getelementptr inbounds i32, ptr %11, i64 %12
%13 = load i32, ptr %ptroffset, align 4
store i32 %13, ptr %f, align 4
%14 = load i32, ptr %f, align 4
%15 = call i32 (ptr, ...) @printf(ptr @.str, i32 %14)
br label %loop.body1
loop.body1: ; preds = %loop.body
br label %loop.exit
loop.exit: ; preds = %loop.body1, %loop.cond
ret void
}
; Function Attrs: nounwind
declare i32 @printf(ptr, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, ptr %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,15 @@
fn void test1()
{
int x;
foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int'
}
define Test1 = distinct int;
fn void test2()
{
Test1 x;
foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'Test1'
}

View File

@@ -0,0 +1,91 @@
// #target: macos-x64
module test;
struct Foo
{
int[] x;
}
macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat)
{
return foo.x[index];
}
macro usize Foo.@operator_len(Foo &foo) @operator(len)
{
return foo.x.len;
}
fn void main()
{
int[*] i = { 1, 3, 10 };
Foo x = { &i };
foreach_r FOO: (int f : x) {
printf("%d\n", f);
while (1)
{
break FOO;
}
}
}
extern fn int printf(char *fmt, ...);
/* #expect: test.ll
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
%.anon = alloca i64, align 8
%f = alloca i32, align 4
%index = alloca i64, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %i, ptr align 4 @.__const, i32 12, i1 false)
%0 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%1 = insertvalue %"int[]" undef, ptr %i, 0
%2 = insertvalue %"int[]" %1, i64 3, 1
store %"int[]" %2, ptr %0, align 8
%3 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%4 = getelementptr inbounds %"int[]", ptr %3, i32 0, i32 1
%5 = load i64, ptr %4, align 8
store i64 %5, ptr %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %entry
%6 = load i64, ptr %.anon, align 8
%gt = icmp ugt i64 %6, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%7 = load i64, ptr %.anon, align 8
%sub = sub i64 %7, 1
store i64 %sub, ptr %.anon, align 8
%8 = load i64, ptr %.anon, align 8
store i64 %8, ptr %index, align 8
%9 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
%10 = getelementptr inbounds %"int[]", ptr %9, i32 0, i32 0
%11 = load ptr, ptr %10, align 8
%12 = load i64, ptr %index, align 8
%ptroffset = getelementptr inbounds i32, ptr %11, i64 %12
%13 = load i32, ptr %ptroffset, align 4
store i32 %13, ptr %f, align 4
%14 = load i32, ptr %f, align 4
%15 = call i32 (ptr, ...) @printf(ptr @.str, i32 %14)
br label %loop.body1
loop.body1: ; preds = %loop.body
br label %loop.exit
loop.exit: ; preds = %loop.body1, %loop.cond
ret void
}
; Function Attrs: nounwind
declare i32 @printf(ptr, ...) #0
; Function Attrs: nounwind
define i32 @main(i32 %0, ptr %1) #0 {
entry:
call void @test_main()
ret i32 0
}

View File

@@ -0,0 +1,54 @@
module test;
extern fn void foo();
int[3] z;
fn void test1()
{
int x;
foreach_r (a : x) // #error: It's not possible to enumerate an expression of type 'int'.
{
foo();
}
}
fn void test2()
{
foreach_r (a : z) foo();
foreach_r (i, a : z) foo();
foreach_r (double i, a : z); // #error: Index must be an integer type, 'double' is not valid.
}
fn void test3()
{
foreach_r (&a : z) foo();
foreach_r (&i, &a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'?
}
fn void test4()
{
foreach_r (&a : z) foo();
foreach_r (&i, a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'?
}
fn void test5()
{
foreach_r (int! y : z) foo(); // #error: The variable may not be a failable.
}
fn void test6()
{
foreach_r (int! i, y : z) foo(); // #error: The index may not be a failable.
}
fn void test7()
{
foreach_r (int a : { 1, 2, 3 }) foo();
foreach_r (a : { 1, 2, 3 }) foo(); // #error: Add the type of your variable here if you want to iterate over
}
fn void test8()
{
foreach_r (int a : { z }) foo(); // #error: 'int[3]' into 'int'
}

View File

@@ -0,0 +1,5 @@
fn void test9()
{
foreach_r (int a : { [2] = 1 }) foo();
foreach_r (int a : { [2] = 2, 1 }) foo(); // #error: Normal initialization cannot be mixed with designated initialization.
}

View File

@@ -1,87 +0,0 @@
// #target: macos-x64
module test;
import std::io;
fn void main()
{
int[*] x = { 1, 5, 10 };
int[] y = &x;
foreach_r (int i, val : y)
{
io::printfln("%d: %d", i, val);
}
}
/* #expect: test.ll
entry:
%x = alloca [3 x i32], align 4
%y = alloca %"int[]", align 8
%.anon = alloca i64, align 8
%i = alloca i32, align 4
%val = alloca i32, align 4
%retparam = alloca i64, align 8
%taddr = alloca %"char[]", align 8
%vararg = alloca %"variant[]", align 8
%varargslots = alloca [2 x %variant], align 16
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false)
%0 = insertvalue %"int[]" undef, ptr %x, 0
%1 = insertvalue %"int[]" %0, i64 3, 1
store %"int[]" %1, ptr %y, align 8
%2 = getelementptr inbounds %"int[]", ptr %y, i32 0, i32 1
%3 = load i64, ptr %2, align 8
store i64 %3, ptr %.anon, align 8
br label %loop.cond
loop.cond: ; preds = %voiderr, %entry
%4 = load i64, ptr %.anon, align 8
%gt = icmp ugt i64 %4, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%5 = load i64, ptr %.anon, align 8
%sub = sub i64 %5, 1
store i64 %sub, ptr %.anon, align 8
%6 = load i64, ptr %.anon, align 8
%uisitrunc = trunc i64 %6 to i32
store i32 %uisitrunc, ptr %i, align 4
%7 = getelementptr inbounds %"int[]", ptr %y, i32 0, i32 0
%8 = load ptr, ptr %7, align 8
%9 = load i64, ptr %.anon, align 8
%ptroffset = getelementptr inbounds i32, ptr %8, i64 %9
%10 = load i32, ptr %ptroffset, align 4
store i32 %10, ptr %val, align 4
store %"char[]" { ptr @.str, i64 6 }, ptr %taddr, align 8
%11 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0
%lo = load ptr, ptr %11, align 8
%12 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1
%hi = load i64, ptr %12, align 8
%13 = insertvalue %variant undef, ptr %i, 0
%14 = insertvalue %variant %13, i64 ptrtoint (ptr @"ct$int" to i64), 1
%15 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 0
store %variant %14, ptr %15, align 16
%16 = insertvalue %variant undef, ptr %val, 0
%17 = insertvalue %variant %16, i64 ptrtoint (ptr @"ct$int" to i64), 1
%18 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 1
store %variant %17, ptr %18, align 16
%19 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1
store i64 2, ptr %19, align 8
%20 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0
store ptr %varargslots, ptr %20, align 8
%21 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0
%lo1 = load ptr, ptr %21, align 8
%22 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1
%hi2 = load i64, ptr %22, align 8
%23 = call i64 @std_io_printfln(ptr %retparam, ptr %lo, i64 %hi, ptr %lo1, i64 %hi2)
%not_err = icmp eq i64 %23, 0
br i1 %not_err, label %after_check, label %voiderr
after_check: ; preds = %loop.body
br label %voiderr
voiderr: ; preds = %after_check, %loop.body
br label %loop.cond
loop.exit: ; preds = %loop.cond
ret void
}

View File

@@ -0,0 +1,12 @@
module test;
fn void test()
{
int[3]! x;
int g;
foreach_r (z : x) // #error: The expression may not be failable.
{
g += z;
x[0] = 1;
}
}