// #target: macos-x64 module foo; struct Foo { int[3] a; } extern fn void printf(char*, ...); macro int* Foo.@operator_element_at_ref(&f, int a) @operator(&[]) { return &f.a[a]; } macro int Foo.@operator_len(&f) @operator(len) { return 3; } macro int Foo.@operator_element_at(&f, int a) @operator([]) { return f.a[a]; } fn int[5] getFields() { printf("getFields\n"); return (int[5]) { 3, 5, 2, 10, 111}; } fn Foo *call(Foo* f) { printf("Call made\n"); return f; } fn void main() { Foo x = { { 1, 5, 7} }; printf("%d %d %d\n", x[0], x[1], x[2]); foreach (i, int y : *call(&x)) { printf("Hello %d: %d\n", i, y); } foreach (i, int* &y : x) { *y += 1; printf("Hello %d: %d\n", i, *y); } foreach (i, int y : x) { printf("After one %d: %d\n", i, y); } foreach (i, int y : &x) { printf("By pointer %d: %d\n", i, y); } foreach (i, int y : x) { printf("Adding %d: %d\n", i, y); i++; } foreach(i, y : (int[5]) { 1, 2, 10, 111, 123 } ) { printf("Adding %d: %d\n", i, y); i++; } foreach(i, y : getFields() ) { printf("Pull value %d: %d\n", i, y); } foreach(i, y : &&getFields()) { printf("Pull value tempptr %d: %d\n", i, y); } printf("%d %d\n", x[0], x[1]); int* y = &x[1]; *y += 1; printf("%d %d\n", x[0], x[1]); } /* #expect: foo.ll %Foo = type { [3 x i32] } @"$ct.foo.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 12, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @.str = private unnamed_addr constant [11 x i8] c"getFields\0A\00", align 1 @.__const = private unnamed_addr constant [5 x i32] [i32 3, i32 5, i32 2, i32 10, i32 111], align 16 @.str.1 = private unnamed_addr constant [11 x i8] c"Call made\0A\00", align 1 @.__const.2 = private unnamed_addr constant %Foo { [3 x i32] [i32 1, i32 5, i32 7] }, align 4 @.str.3 = private unnamed_addr constant [10 x i8] c"%d %d %d\0A\00", align 1 @.str.4 = private unnamed_addr constant [14 x i8] c"Hello %d: %d\0A\00", align 1 @.str.5 = private unnamed_addr constant [14 x i8] c"Hello %d: %d\0A\00", align 1 @.str.6 = private unnamed_addr constant [18 x i8] c"After one %d: %d\0A\00", align 1 @.str.7 = private unnamed_addr constant [19 x i8] c"By pointer %d: %d\0A\00", align 1 @.str.8 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 @.__const.9 = private unnamed_addr constant [5 x i32] [i32 1, i32 2, i32 10, i32 111, i32 123], align 16 @.str.10 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 @.str.11 = private unnamed_addr constant [19 x i8] c"Pull value %d: %d\0A\00", align 1 @.str.12 = private unnamed_addr constant [27 x i8] c"Pull value tempptr %d: %d\0A\00", align 1 @.str.13 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 @.str.14 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 ; Function Attrs: declare void @printf(ptr, ...) #0 ; Function Attrs: define void @foo.getFields(ptr noalias sret([5 x i32]) align 4 %0) #0 { entry: %literal = alloca [5 x i32], align 16 call void (ptr, ...) @printf(ptr @.str) call void @llvm.memcpy.p0.p0.i32(ptr align 16 %literal, ptr align 16 @.__const, i32 20, i1 false) call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 16 %literal, i32 20, i1 false) ret void } ; Function Attrs: define ptr @foo.call(ptr %0) #0 { entry: call void (ptr, ...) @printf(ptr @.str.1) ret ptr %0 } ; Function Attrs: define void @foo.main() #0 { entry: %x = alloca %Foo, align 4 %.anon = alloca i32, align 4 %i = alloca i32, align 4 %y = alloca i32, align 4 %a = alloca i32, align 4 %.anon7 = alloca i32, align 4 %i11 = alloca i32, align 4 %y12 = alloca ptr, align 8 %a13 = alloca i32, align 4 %.anon20 = alloca i32, align 4 %i24 = alloca i32, align 4 %y25 = alloca i32, align 4 %a26 = alloca i32, align 4 %.anon33 = alloca i32, align 4 %i37 = alloca i32, align 4 %y38 = alloca i32, align 4 %a39 = alloca i32, align 4 %.anon46 = alloca i32, align 4 %i50 = alloca i32, align 4 %y51 = alloca i32, align 4 %a52 = alloca i32, align 4 %.anon59 = alloca [5 x i32], align 16 %.anon60 = alloca i64, align 8 %i63 = alloca i64, align 8 %y64 = alloca i32, align 4 %.anon68 = alloca [5 x i32], align 16 %.anon69 = alloca i64, align 8 %i73 = alloca i64, align 8 %y74 = alloca i32, align 4 %sretparam = alloca [5 x i32], align 4 %.anon78 = alloca i64, align 8 %i82 = alloca i64, align 8 %y83 = alloca i32, align 4 %y90 = alloca ptr, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const.2, i32 12, i1 false) %neq = icmp ne ptr %x, null call void @llvm.assume(i1 %neq) %neq1 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq1) %ptradd = getelementptr inbounds i8, ptr %x, i64 4 %neq2 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq2) %ptradd3 = getelementptr inbounds i8, ptr %x, i64 8 %0 = load i32, ptr %x, align 4 %1 = load i32, ptr %ptradd, align 4 %2 = load i32, ptr %ptradd3, align 4 call void (ptr, ...) @printf(ptr @.str.3, i32 %0, i32 %1, i32 %2) %3 = call ptr @foo.call(ptr %x) %neq4 = icmp ne ptr %3, null call void @llvm.assume(i1 %neq4) store i32 0, ptr %.anon, align 4 br label %loop.cond loop.cond: ; preds = %loop.body, %entry %4 = load i32, ptr %.anon, align 4 %lt = icmp slt i32 %4, 3 br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond %5 = load i32, ptr %.anon, align 4 store i32 %5, ptr %i, align 4 %6 = load i32, ptr %.anon, align 4 store i32 %6, ptr %a, align 4 %neq5 = icmp ne ptr %3, null call void @llvm.assume(i1 %neq5) %7 = load i32, ptr %a, align 4 %sext = sext i32 %7 to i64 %ptroffset = getelementptr inbounds [4 x i8], ptr %3, i64 %sext %8 = load i32, ptr %ptroffset, align 4 store i32 %8, ptr %y, align 4 %9 = load i32, ptr %i, align 4 %10 = load i32, ptr %y, align 4 call void (ptr, ...) @printf(ptr @.str.4, i32 %9, i32 %10) %11 = load i32, ptr %.anon, align 4 %addnsw = add nsw i32 %11, 1 store i32 %addnsw, ptr %.anon, align 4 br label %loop.cond loop.exit: ; preds = %loop.cond %neq6 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq6) store i32 0, ptr %.anon7, align 4 br label %loop.cond8 loop.cond8: ; preds = %loop.body10, %loop.exit %12 = load i32, ptr %.anon7, align 4 %lt9 = icmp slt i32 %12, 3 br i1 %lt9, label %loop.body10, label %loop.exit18 loop.body10: ; preds = %loop.cond8 %13 = load i32, ptr %.anon7, align 4 store i32 %13, ptr %i11, align 4 %14 = load i32, ptr %.anon7, align 4 store i32 %14, ptr %a13, align 4 %neq14 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq14) %15 = load i32, ptr %a13, align 4 %sext15 = sext i32 %15 to i64 %ptroffset16 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext15 store ptr %ptroffset16, ptr %y12, align 8 %16 = load ptr, ptr %y12, align 8 %17 = load i32, ptr %16, align 4 %add = add i32 %17, 1 store i32 %add, ptr %16, align 4 %18 = load ptr, ptr %y12, align 8 %19 = load i32, ptr %i11, align 4 %20 = load i32, ptr %18, align 4 call void (ptr, ...) @printf(ptr @.str.5, i32 %19, i32 %20) %21 = load i32, ptr %.anon7, align 4 %addnsw17 = add nsw i32 %21, 1 store i32 %addnsw17, ptr %.anon7, align 4 br label %loop.cond8 loop.exit18: ; preds = %loop.cond8 %neq19 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq19) store i32 0, ptr %.anon20, align 4 br label %loop.cond21 loop.cond21: ; preds = %loop.body23, %loop.exit18 %22 = load i32, ptr %.anon20, align 4 %lt22 = icmp slt i32 %22, 3 br i1 %lt22, label %loop.body23, label %loop.exit31 loop.body23: ; preds = %loop.cond21 %23 = load i32, ptr %.anon20, align 4 store i32 %23, ptr %i24, align 4 %24 = load i32, ptr %.anon20, align 4 store i32 %24, ptr %a26, align 4 %neq27 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq27) %25 = load i32, ptr %a26, align 4 %sext28 = sext i32 %25 to i64 %ptroffset29 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext28 %26 = load i32, ptr %ptroffset29, align 4 store i32 %26, ptr %y25, align 4 %27 = load i32, ptr %i24, align 4 %28 = load i32, ptr %y25, align 4 call void (ptr, ...) @printf(ptr @.str.6, i32 %27, i32 %28) %29 = load i32, ptr %.anon20, align 4 %addnsw30 = add nsw i32 %29, 1 store i32 %addnsw30, ptr %.anon20, align 4 br label %loop.cond21 loop.exit31: ; preds = %loop.cond21 %neq32 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq32) store i32 0, ptr %.anon33, align 4 br label %loop.cond34 loop.cond34: ; preds = %loop.body36, %loop.exit31 %30 = load i32, ptr %.anon33, align 4 %lt35 = icmp slt i32 %30, 3 br i1 %lt35, label %loop.body36, label %loop.exit44 loop.body36: ; preds = %loop.cond34 %31 = load i32, ptr %.anon33, align 4 store i32 %31, ptr %i37, align 4 %32 = load i32, ptr %.anon33, align 4 store i32 %32, ptr %a39, align 4 %neq40 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq40) %33 = load i32, ptr %a39, align 4 %sext41 = sext i32 %33 to i64 %ptroffset42 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext41 %34 = load i32, ptr %ptroffset42, align 4 store i32 %34, ptr %y38, align 4 %35 = load i32, ptr %i37, align 4 %36 = load i32, ptr %y38, align 4 call void (ptr, ...) @printf(ptr @.str.7, i32 %35, i32 %36) %37 = load i32, ptr %.anon33, align 4 %addnsw43 = add nsw i32 %37, 1 store i32 %addnsw43, ptr %.anon33, align 4 br label %loop.cond34 loop.exit44: ; preds = %loop.cond34 %neq45 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq45) store i32 0, ptr %.anon46, align 4 br label %loop.cond47 loop.cond47: ; preds = %loop.body49, %loop.exit44 %38 = load i32, ptr %.anon46, align 4 %lt48 = icmp slt i32 %38, 3 br i1 %lt48, label %loop.body49, label %loop.exit58 loop.body49: ; preds = %loop.cond47 %39 = load i32, ptr %.anon46, align 4 store i32 %39, ptr %i50, align 4 %40 = load i32, ptr %.anon46, align 4 store i32 %40, ptr %a52, align 4 %neq53 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq53) %41 = load i32, ptr %a52, align 4 %sext54 = sext i32 %41 to i64 %ptroffset55 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext54 %42 = load i32, ptr %ptroffset55, align 4 store i32 %42, ptr %y51, align 4 %43 = load i32, ptr %i50, align 4 %44 = load i32, ptr %y51, align 4 call void (ptr, ...) @printf(ptr @.str.8, i32 %43, i32 %44) %45 = load i32, ptr %i50, align 4 %add56 = add i32 %45, 1 store i32 %add56, ptr %i50, align 4 %46 = load i32, ptr %.anon46, align 4 %addnsw57 = add nsw i32 %46, 1 store i32 %addnsw57, ptr %.anon46, align 4 br label %loop.cond47 loop.exit58: ; preds = %loop.cond47 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %.anon59, ptr align 16 @.__const.9, i32 20, i1 false) store i64 0, ptr %.anon60, align 8 br label %loop.cond61 loop.cond61: ; preds = %loop.body62, %loop.exit58 %47 = load i64, ptr %.anon60, align 8 %gt = icmp ugt i64 5, %47 br i1 %gt, label %loop.body62, label %loop.exit67 loop.body62: ; preds = %loop.cond61 %48 = load i64, ptr %.anon60, align 8 store i64 %48, ptr %i63, align 8 %49 = load i64, ptr %.anon60, align 8 %ptroffset65 = getelementptr inbounds [4 x i8], ptr %.anon59, i64 %49 %50 = load i32, ptr %ptroffset65, align 4 store i32 %50, ptr %y64, align 4 %51 = load i64, ptr %i63, align 8 %52 = load i32, ptr %y64, align 4 call void (ptr, ...) @printf(ptr @.str.10, i64 %51, i32 %52) %53 = load i64, ptr %i63, align 8 %add66 = add i64 %53, 1 store i64 %add66, ptr %i63, align 8 %54 = load i64, ptr %.anon60, align 8 %addnuw = add nuw i64 %54, 1 store i64 %addnuw, ptr %.anon60, align 8 br label %loop.cond61 loop.exit67: ; preds = %loop.cond61 call void @foo.getFields(ptr sret([5 x i32]) align 4 %.anon68) store i64 0, ptr %.anon69, align 8 br label %loop.cond70 loop.cond70: ; preds = %loop.body72, %loop.exit67 %55 = load i64, ptr %.anon69, align 8 %gt71 = icmp ugt i64 5, %55 br i1 %gt71, label %loop.body72, label %loop.exit77 loop.body72: ; preds = %loop.cond70 %56 = load i64, ptr %.anon69, align 8 store i64 %56, ptr %i73, align 8 %57 = load i64, ptr %.anon69, align 8 %ptroffset75 = getelementptr inbounds [4 x i8], ptr %.anon68, i64 %57 %58 = load i32, ptr %ptroffset75, align 4 store i32 %58, ptr %y74, align 4 %59 = load i64, ptr %i73, align 8 %60 = load i32, ptr %y74, align 4 call void (ptr, ...) @printf(ptr @.str.11, i64 %59, i32 %60) %61 = load i64, ptr %.anon69, align 8 %addnuw76 = add nuw i64 %61, 1 store i64 %addnuw76, ptr %.anon69, align 8 br label %loop.cond70 loop.exit77: ; preds = %loop.cond70 call void @foo.getFields(ptr sret([5 x i32]) align 4 %sretparam) store i64 0, ptr %.anon78, align 8 br label %loop.cond79 loop.cond79: ; preds = %loop.body81, %loop.exit77 %62 = load i64, ptr %.anon78, align 8 %gt80 = icmp ugt i64 5, %62 br i1 %gt80, label %loop.body81, label %loop.exit86 loop.body81: ; preds = %loop.cond79 %63 = load i64, ptr %.anon78, align 8 store i64 %63, ptr %i82, align 8 %64 = load i64, ptr %.anon78, align 8 %ptroffset84 = getelementptr inbounds [4 x i8], ptr %sretparam, i64 %64 %65 = load i32, ptr %ptroffset84, align 4 store i32 %65, ptr %y83, align 4 %66 = load i64, ptr %i82, align 8 %67 = load i32, ptr %y83, align 4 call void (ptr, ...) @printf(ptr @.str.12, i64 %66, i32 %67) %68 = load i64, ptr %.anon78, align 8 %addnuw85 = add nuw i64 %68, 1 store i64 %addnuw85, ptr %.anon78, align 8 br label %loop.cond79 loop.exit86: ; preds = %loop.cond79 %neq87 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq87) %neq88 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq88) %ptradd89 = getelementptr inbounds i8, ptr %x, i64 4 %69 = load i32, ptr %x, align 4 %70 = load i32, ptr %ptradd89, align 4 call void (ptr, ...) @printf(ptr @.str.13, i32 %69, i32 %70) %neq91 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq91) %ptradd92 = getelementptr inbounds i8, ptr %x, i64 4 store ptr %ptradd92, ptr %y90, align 8 %71 = load ptr, ptr %y90, align 8 %72 = load i32, ptr %71, align 4 %add93 = add i32 %72, 1 store i32 %add93, ptr %71, align 4 %neq94 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq94) %neq95 = icmp ne ptr %x, null call void @llvm.assume(i1 %neq95) %ptradd96 = getelementptr inbounds i8, ptr %x, i64 4 %73 = load i32, ptr %x, align 4 %74 = load i32, ptr %ptradd96, align 4 call void (ptr, ...) @printf(ptr @.str.14, i32 %73, i32 %74) ret void }