// #target: macos-x64
module test;
import std;

struct St12
{
    int a @align(16);
}
fn St12 f12_0() { while (1) {} }
fn void f12_1(St12 a0) {}

struct St13_0 { long[3] f0; }
struct St13_1 { long[2] f0; }
fn St13_0 f13(int a, int b, int c, int d,
                 St13_1 e, int f) { while (1) {} }

fn void f14(int a, int b, int c, int d, int e, int f, ichar x) {}

fn void f15(int a, int b, int c, int d, int e, int f, void *x) {}

fn void f16(float a, float b, float c, float d, float e, float f, float g, float h,
         float x) {}

struct Fl18_s0 { int f0; }
fn void fl18(int a, Fl18_s0 f18_arg1) { while (1) {} }

struct St20 @align(32) {
  int x;
  int y;
}
fn void f20(St20 x) {}

struct StringRef
{
  int x;
  char* ptr;
}
fn char *f21(StringRef s) { return s.x+s.ptr; }

struct St22s @align(16)
{ ulong[2] x; }
fn void f22(St22s x, St22s y) { }



struct St23S {
  short f0;
  uint f1;
  int f2;
}


fn void f23(int a, St23S b) {
}

struct St24s { int a; int b; }

fn St23S f24(St23S *x, St24s *p2)
{
  return *x;

}

fn float[<4>] f25(float[<4>] x) {
  return x+x;
}

struct Foo26 {
  int *x;
  float *y;
}

fn Foo26 f26(Foo26 *p) {
  return *p;
}


struct V4f32wrapper {
  float[<4>] v;
}

fn V4f32wrapper f27(V4f32wrapper x) {
  return x;
}

// PR22563 - We should unwrap simple structs and arrays to pass
// and return them in the appropriate vector registers if possible.

alias V8f32 = float[<8>];
struct V8f32wrapper {
  V8f32 v;
}

fn V8f32wrapper f27a(V8f32wrapper x) {
  return x;
}

struct V8f32wrapper_wrapper {
  V8f32[1] v;
}

fn V8f32wrapper_wrapper f27b(V8f32wrapper_wrapper x) {
  return x;
}

struct F28c {
  double x;
  int y;
}
fn void f28(F28c c) {
}

struct Inner
{
    double x;
    int y;
}
struct F29a
{
  Inner[1] c;
}

fn void f29a(F29a a) {
}

struct St0 {
    char[8] f0; char f2; char f3; char f4; }
fn void f30(St0 p_4) {
}

struct F31foo { float a, b, c; }
fn float f31(F31foo x) {
  return x.c;
}

alias V1i64 = ulong[<1>];

fn V1i64 f34(V1i64 arg) { return arg; }


alias V1i64_2 = uint[<2>];
fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; }

alias V2i32 = float[<2>];
fn V2i32 f36(V2i32 arg) { return arg; }


/* #expect: test.ll

define i32 @test.f12_0()
define void @test.f12_1(i32 %0)
define void @test.f13(ptr noalias sret(%St13_0) align 8 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr byval(%St13_1) align 8 %5, i32 %6) #0 {
define void @test.f14(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 signext %6) #0 {
define void @test.f15(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, ptr %6)
define void @test.f16(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, float %8)
define void @test.fl18(i32 %0, i32 %1)
define void @test.f20(ptr byval(%St20) align 32 %0)
define ptr @test.f21(i32 %0, ptr %1)
define void @test.f22(i64 %0, i64 %1, i64 %2, i64 %3)
entry:
  %x = alloca %St22s, align 16
  %y = alloca %St22s, align 16
define void @test.f23(i32 %0, i64 %1, i32 %2)
define { i64, i32 } @test.f24(ptr %0, ptr %1)
define <4 x float> @test.f25(<4 x float> %0) #0 {
entry:
  %fadd = fadd <4 x float> %0, %0
  ret <4 x float> %fadd
}
define { ptr, ptr } @test.f26(ptr %0)
define <4 x float> @test.f27(<4 x float> %0)
define <8 x float> @test.f27a(<8 x float> %0)
define <8 x float> @test.f27b(<8 x float> %0)
define void @test.f28(double %0, i32 %1)
define void @test.f29a(double %0, i32 %1)
define void @test.f30(i64 %0, i24 %1)
define float @test.f31(<2 x float> %0, float %1)
define double @test.f34(double %0)
define double @test.f35(double %0)
define double @test.f36(double %0)