#include <metal_stdlib>
using namespace metal;

template<typename T, size_t N>
struct tint_array {
  const constant T& operator[](size_t i) const constant { return elements[i]; }
  device T& operator[](size_t i) device { return elements[i]; }
  const device T& operator[](size_t i) const device { return elements[i]; }
  thread T& operator[](size_t i) thread { return elements[i]; }
  const thread T& operator[](size_t i) const thread { return elements[i]; }
  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
  T elements[N];
};

struct S {
  tint_array<int4, 4> arr;
};

struct tint_module_vars_struct {
  thread tint_array<int4, 4>* src_private;
  threadgroup tint_array<int4, 4>* src_workgroup;
  const constant S* src_uniform;
  device S* src_storage;
  thread tint_array<int4, 4>* dst;
  thread tint_array<tint_array<tint_array<int, 2>, 3>, 4>* dst_nested;
};

struct tint_symbol_2 {
  tint_array<int4, 4> tint_symbol_1;
};

tint_array<int4, 4> ret_arr() {
  return tint_array<int4, 4>{};
}

S ret_struct_arr() {
  return S{};
}

void foo(tint_array<int4, 4> src_param, tint_module_vars_struct tint_module_vars) {
  tint_array<int4, 4> src_function = {};
  (*tint_module_vars.dst) = tint_array<int4, 4>{int4(1), int4(2), int4(3), int4(3)};
  (*tint_module_vars.dst) = src_param;
  (*tint_module_vars.dst) = ret_arr();
  tint_array<int4, 4> const src_let = tint_array<int4, 4>{};
  (*tint_module_vars.dst) = src_let;
  (*tint_module_vars.dst) = src_function;
  (*tint_module_vars.dst) = (*tint_module_vars.src_private);
  (*tint_module_vars.dst) = (*tint_module_vars.src_workgroup);
  (*tint_module_vars.dst) = ret_struct_arr().arr;
  (*tint_module_vars.dst) = (*tint_module_vars.src_uniform).arr;
  (*tint_module_vars.dst) = (*tint_module_vars.src_storage).arr;
  tint_array<tint_array<tint_array<int, 2>, 3>, 4> src_nested = {};
  (*tint_module_vars.dst_nested) = src_nested;
}

void tint_symbol_inner(uint tint_local_index, tint_module_vars_struct tint_module_vars) {
  {
    uint v = 0u;
    v = tint_local_index;
    while(true) {
      uint const v_1 = v;
      if ((v_1 >= 4u)) {
        break;
      }
      (*tint_module_vars.src_workgroup)[v_1] = int4(0);
      {
        v = (v_1 + 1u);
      }
      continue;
    }
  }
  threadgroup_barrier(mem_flags::mem_threadgroup);
  tint_array<int4, 4> const a = tint_array<int4, 4>{};
  foo(a, tint_module_vars);
}

kernel void tint_symbol(uint tint_local_index [[thread_index_in_threadgroup]], threadgroup tint_symbol_2* v_2 [[threadgroup(0)]], const constant S* src_uniform [[buffer(0)]], device S* src_storage [[buffer(1)]]) {
  thread tint_array<int4, 4> src_private = {};
  thread tint_array<int4, 4> dst = {};
  thread tint_array<tint_array<tint_array<int, 2>, 3>, 4> dst_nested = {};
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.src_private=(&src_private), .src_workgroup=(&(*v_2).tint_symbol_1), .src_uniform=src_uniform, .src_storage=src_storage, .dst=(&dst), .dst_nested=(&dst_nested)};
  tint_symbol_inner(tint_local_index, tint_module_vars);
}
