// #target: linux-riscv32
module test;

struct Tiny {
  char a, b, c, d;
}

struct Small {
  int a;
  int* b;
}

struct Small_aligned
{
  long a;
}

struct Large {
  int a, b, c, d;
}

// Scalars passed on the stack should not have signext/zeroext attributes
// (they are anyext).

fn int f_scalar_stack_1(int a, long b, float c, double d, float128 e,
                     char f, ichar g, char h) {
  return g + h;
}

// Ensure that scalars passed on the stack are still determined correctly in
// the presence of large return values that consume a register due to the need
// to pass a pointer.

fn Large f_scalar_stack_2(float a, long b, double c, float128 d,
                              char e, ichar f, char g) {
  return {(int)a, e, f, g};
}

// Aggregates and >=XLen scalars passed on the stack should be lowered just as
// they would be if passed via registers.

fn void f_scalar_stack_3(double a, long b, double c, long d, int e,
                      long f, float g, double h, float128 i) {}

fn void f_agg_stack(double a, long b, double c, long d, Tiny e,
                 Small f, Small_aligned g, Large h) {}

/* #expect: test.ll


define i32 @test.f_scalar_stack_1(i32 %0, i64 %1, float %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
entry:
  %sext = sext i8 %6 to i32
  %zext = zext i8 %7 to i32
  %add = add i32 %sext, %zext
  ret i32 %add
}

; Function Attrs:
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, float %1, i64 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
entry:
  %literal = alloca %Large, align 4
  %fpsi = fptosi float %1 to i32
  store i32 %fpsi, ptr %literal, align 4
  %ptradd = getelementptr inbounds i8, ptr %literal, i32 4
  %zext = zext i8 %5 to i32
  store i32 %zext, ptr %ptradd, align 4
  %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8
  %sext = sext i8 %6 to i32
  store i32 %sext, ptr %ptradd1, align 4
  %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12
  %zext3 = zext i8 %7 to i32
  store i32 %zext3, ptr %ptradd2, align 4
  call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false)
  ret void
}

; Function Attrs:
define void @test.f_scalar_stack_3(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, float %6, double %7, fp128 %8) #0 {
entry:
  ret void
}

; Function Attrs:
define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 {
entry:
  %e = alloca %Tiny, align 1
  %f = alloca %Small, align 4
  %g = alloca %Small_aligned, align 8
  store i32 %4, ptr %e, align 1
  store [2 x i32] %5, ptr %f, align 4
  store i64 %6, ptr %g, align 8
  ret void
}
