// #target: macos-aarch64
module the_generic <THE_CONST, Type>;
struct Abc
{ int a; }

module the_generic <THE_CONST, Type>;

struct TheStruct
{
	Type[THE_CONST] el;
}

fn Type TheStruct.foo2(&self)
{
	return self.el[0];
}

struct TheStruct2
{
	union
	{
		struct
		{
			Type a, b;
		}
	}
}
Type foo = THE_CONST;

Type bar @local;

Type* baz = &bar;

fn Type square(Type t) => t * THE_CONST;

module test;
import the_generic;

<* @require Type.sizeof < 5 *>
fn Type square(Type t) <Type> => t * 3;
fn Type bob(Type2 t) <Type2> => feok * 3;

fn int main()
{
	TheStruct{5, double} s;
	TheStruct{5, int} s2;
	s.el[4] = 1.2;
	double y = s.foo2();
	double y22 = s2.foo2();
	int x = the_generic::foo{4, int};
	int* b = the_generic::baz{4, int};
	x = the_generic::square{3, int}(x);
	x = square{int}(x);
	return x;
}

/* #expect: the_generic.ll

@"the_generic.foo$5$double$" = weak local_unnamed_addr global double 5.000000e+00, align 8
@"the_generic.baz$5$double$" = weak local_unnamed_addr global ptr @"the_generic.bar$5$double$
@"the_generic.foo$5$int$" = weak local_unnamed_addr global i32 5, align 4
@"the_generic.baz$5$int$" = weak local_unnamed_addr global ptr @"the_generic.bar$5$int$
@"the_generic.foo$4$int$" = weak local_unnamed_addr global i32 4, align 4
@"the_generic.baz$4$int$" = weak local_unnamed_addr global ptr @"the_generic.bar$4$int$
@"the_generic.foo$3$int$" = weak local_unnamed_addr global i32 3, align 4
@"the_generic.baz$3$int$" = weak local_unnamed_addr global ptr @"the_generic.bar$3$int$

define weak double @"the_generic.TheStruct$5$double$.foo2"(ptr %0) #0 {
entry:
  %1 = load double, ptr %0, align 8
  ret double %1
}

define weak i32 @"the_generic.TheStruct$5$int$.foo2"(ptr %0) #0 {
entry:
  %1 = load i32, ptr %0, align 4
  ret i32 %1
}

define weak i32 @"the_generic.TheStruct$4$int$.foo2"(ptr %0) #0 {
entry:
  %1 = load i32, ptr %0, align 4
  ret i32 %1
}

define weak i32 @"the_generic.TheStruct$3$int$.foo2"(ptr %0) #0 {
entry:
  %1 = load i32, ptr %0, align 4
  ret i32 %1
}

define weak double @"the_generic.square$5$double$"(double %0) #0 {
entry:
  %fmul = fmul double %0, 5.000000e+00
  ret double %fmul
}

define weak i32 @"the_generic.square$5$int$"(i32 %0) #0 {
entry:
  %mul = mul i32 %0, 5
  ret i32 %mul
}

define weak i32 @"the_generic.square$4$int$"(i32 %0) #0 {
entry:
  %mul = mul i32 %0, 4
  ret i32 %mul
}

define weak i32 @"the_generic.square$3$int$"(i32 %0) #0 {
entry:
  %mul = mul i32 %0, 3
  ret i32 %mul
}

// #expect: test.ll

%"TheStruct{5, double}" = type { [5 x double] }
%"TheStruct{5, int}" = type { [5 x i32] }

@"the_generic.foo$4$int$" = extern_weak global i32, align 4
@"the_generic.baz$4$int$" = extern_weak global ptr, align 8

define i32 @main() #0 {
entry:
  %s = alloca %"TheStruct{5, double}", align 8
  %s2 = alloca %"TheStruct{5, int}", align 4
  %y = alloca double, align 8
  %y22 = alloca double, align 8
  %x = alloca i32, align 4
  %b = alloca ptr, align 8
  call void @llvm.memset.p0.i64(ptr align 8 %s, i8 0, i64 40, i1 false)
  call void @llvm.memset.p0.i64(ptr align 4 %s2, i8 0, i64 20, i1 false)
  %ptradd = getelementptr inbounds i8, ptr %s, i64 32
  store double 1.200000e+00, ptr %ptradd, align 8
  %0 = call double @"the_generic.TheStruct$5$double$.foo2"(ptr %s)
  store double %0, ptr %y, align 8
  %1 = call i32 @"the_generic.TheStruct$5$int$.foo2"(ptr %s2)
  %sifp = sitofp i32 %1 to double
  store double %sifp, ptr %y22, align 8
  %2 = load i32, ptr @"the_generic.foo$4$int$", align 4
  store i32 %2, ptr %x, align 4
  %3 = load ptr, ptr @"the_generic.baz$4$int$", align 8
  store ptr %3, ptr %b, align 8
  %4 = load i32, ptr %x, align 4
  %5 = call i32 @"the_generic.square$3$int$"(i32 %4)
  store i32 %5, ptr %x, align 4
  %6 = load i32, ptr %x, align 4
  %7 = call i32 @"test.square$int$"(i32 %6)
  store i32 %7, ptr %x, align 4
  %8 = load i32, ptr %x, align 4
  ret i32 %8
}

define weak i32 @"test.square$int$"(i32 %0) #0 {
entry:
  %mul = mul i32 %0, 3
  ret i32 %mul
}

declare void @llvm.memset.p0.i64(ptr

declare extern_weak double @"the_generic.TheStruct$5$double$.foo2"(ptr) #0

declare extern_weak i32 @"the_generic.TheStruct$5$int$.foo2"(ptr) #0

declare extern_weak i32 @"the_generic.square$3$int$"(i32) #0
