// #target: macos-x64
module test;
extern fn int printf(char *, ...);
extern fn int foo();

fn int main2() {
  while (foo()) {
     switch (foo()) {
     case 0:
     case 1:
     case 2:
     case 3:
       printf("3");
       nextcase;
     case 4: printf("4"); nextcase;
     case 5:
     case 6:
     default:
     }
   }
   return 0;
}

fn double test(uint x)
{
  double[30] student_t={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 ,
                               2.447 , 2.365 , 2.306 , 2.262 , 2.228 ,
                               2.201 , 2.179 , 2.160 , 2.145 , 2.131 ,
                               2.120 , 2.110 , 2.101 , 2.093 , 2.086 ,
                               2.080 , 2.074 , 2.069 , 2.064 , 2.060 ,
                               2.056 , 2.052 , 2.048 , 2.045 };
  return student_t[x];
}

struct St {
  int i;
  short s1, s2;
}

extern fn St func_returning_struct();

fn void loop() {
  func_returning_struct();
}

struct FooSt {
  char p;
  short q;
  char r;
  int x;
  short y, z;
  int q2;
}

extern fn int testF(FooSt x, float);
extern fn int testE(char,short,char,int,int,float);
fn void test3(FooSt *x) {
  x.q = 1;
}

fn void test2(FooSt y) {
  testE(y.p, y.q, y.r, y.x, y.y, 0.1f);
  testF(y, 0.1f);
  test2(y);
  test3(&y);
}

/* #expect: test.ll


define i32 @test.main2() #0 {
entry:
  %switch = alloca i32, align 4
  br label %loop.cond

loop.cond:                                        ; preds = %switch.exit, %entry
  %0 = call i32 @foo()
  %i2b = icmp ne i32 %0, 0
  br i1 %i2b, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %1 = call i32 @foo()
  store i32 %1, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %loop.body
  %2 = load i32, ptr %switch, align 4
  switch i32 %2, label %switch.exit [
    i32 0, label %switch.case
    i32 1, label %switch.case
    i32 2, label %switch.case
    i32 3, label %switch.case
    i32 4, label %switch.case1
    i32 5, label %switch.exit
    i32 6, label %switch.exit
  ]

switch.case:                                      ; preds = %switch.entry, %switch.entry, %switch.entry, %switch.entry
  %3 = call i32 (ptr, ...) @printf(ptr @.str)
  br label %switch.case1

switch.case1:                                     ; preds = %switch.entry, %switch.case
  %4 = call i32 (ptr, ...) @printf(ptr @.str.1)
  br label %switch.exit

switch.exit:                                      ; preds = %switch.entry, %switch.entry, %switch.case1, %switch.entry
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  ret i32 0
}

; Function Attrs:
define double @test.test(i32 %0) #0 {
entry:
  %student_t = alloca [30 x double], align 16
  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %student_t, ptr align 16 @.__const, i32 240, i1 false)
  %zext = zext i32 %0 to i64
  %ptroffset = getelementptr inbounds [8 x i8], ptr %student_t, i64 %zext
  %1 = load double, ptr %ptroffset, align 8
  ret double %1
}

define void @test.loop() #0 {
entry:
  %result = alloca %St, align 4
  %0 = call i64 @func_returning_struct()
  store i64 %0, ptr %result, align 4
  ret void
}

; Function Attrs:
declare i32 @testF(ptr byval(%FooSt) align 8, float) #0

; Function Attrs:
declare i32 @testE(i8 zeroext, i16 signext, i8 zeroext, i32, i32, float) #0

; Function Attrs:
define void @test.test3(ptr %0) #0 {
entry:
  %ptradd = getelementptr inbounds i8, ptr %0, i64 2
  store i16 1, ptr %ptradd, align 2
  ret void
}

; Function Attrs:
define void @test.test2(ptr byval(%FooSt) align 8 %0) #0 {
entry:
  %indirectarg = alloca %FooSt, align 8
  %indirectarg4 = alloca %FooSt, align 8
  %ptradd = getelementptr inbounds i8, ptr %0, i64 2
  %ptradd1 = getelementptr inbounds i8, ptr %0, i64 4
  %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8
  %ptradd3 = getelementptr inbounds i8, ptr %0, i64 12
  %1 = load i16, ptr %ptradd3, align 4
  %sext = sext i16 %1 to i32
  %2 = load i8, ptr %0, align 4
  %3 = load i16, ptr %ptradd, align 2
  %4 = load i8, ptr %ptradd1, align 4
  %5 = load i32, ptr %ptradd2, align 4
  %6 = call i32 @testE(i8 zeroext %2, i16 signext %3, i8 zeroext %4, i32 %5, i32 %sext, float 0x3FB99999A0000000)
  call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 4 %0, i32 20, i1 false)
  %7 = call i32 @testF(ptr byval(%FooSt) align 8 %indirectarg, float 0x3FB99999A0000000)
  call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg4, ptr align 4 %0, i32 20, i1 false)
  call void @test.test2(ptr byval(%FooSt) align 8 %indirectarg4)
  call void @test.test3(ptr %0)
  ret void
}
