mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.4882;
  long int D.4883;
  long int D.4884;
  struct MonoLockFreeArrayChunk * D.4887;
  struct MonoLockFreeArrayChunk * * D.4890;
  void * D.4891;
  _Bool D.4894;
  long int D.4895;
  long int D.4896;
  struct MonoLockFreeArrayChunk * * D.4901;
  void * D.4902;
  _Bool D.4905;
  long int D.4906;
  long int D.4907;
  int D.4910;
  void * D.4911;
  unsigned int D.4912;
  unsigned int index.0;
  unsigned int D.4914;
  struct Chunk * chunk;

  D.4882 = index < 0;
  D.4883 = (long int) D.4882;
  D.4884 = __builtin_expect (D.4883, 0);
  if (D.4884 != 0) goto <D.4885>; else goto <D.4886>;
  <D.4885>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.4886>:
  D.4887 = arr->chunk_list;
  if (D.4887 == 0B) goto <D.4888>; else goto <D.4889>;
  <D.4888>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.4890 = &arr->chunk_list;
  D.4891 = InterlockedCompareExchangePointer (D.4890, chunk, 0B);
  if (D.4891 != 0B) goto <D.4892>; else goto <D.4893>;
  <D.4892>:
  free_chunk (chunk);
  <D.4893>:
  <D.4889>:
  chunk = arr->chunk_list;
  D.4894 = chunk == 0B;
  D.4895 = (long int) D.4894;
  D.4896 = __builtin_expect (D.4895, 0);
  if (D.4896 != 0) goto <D.4897>; else goto <D.4898>;
  <D.4897>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.4898>:
  goto <D.4824>;
  <D.4823>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.4899>; else goto <D.4900>;
    <D.4899>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.4901 = &chunk->next;
    D.4902 = InterlockedCompareExchangePointer (D.4901, next, 0B);
    if (D.4902 != 0B) goto <D.4903>; else goto <D.4904>;
    <D.4903>:
    free_chunk (next);
    next = chunk->next;
    D.4905 = next == 0B;
    D.4906 = (long int) D.4905;
    D.4907 = __builtin_expect (D.4906, 0);
    if (D.4907 != 0) goto <D.4908>; else goto <D.4909>;
    <D.4908>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.4909>:
    <D.4904>:
    <D.4900>:
    D.4910 = chunk->num_entries;
    index = index - D.4910;
    chunk = next;
  }
  <D.4824>:
  D.4910 = chunk->num_entries;
  if (D.4910 <= index) goto <D.4823>; else goto <D.4825>;
  <D.4825>:
  D.4912 = arr->entry_size;
  index.0 = (unsigned int) index;
  D.4914 = D.4912 * index.0;
  D.4911 = &chunk->entries[D.4914];
  return D.4911;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  unsigned int size.1;
  unsigned int D.4917;
  unsigned int D.4918;
  unsigned int D.4919;
  unsigned int size.2;
  _Bool D.4921;
  long int D.4922;
  long int D.4923;
  struct Chunk * D.4926;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  size.1 = (unsigned int) size;
  D.4917 = size.1 + 4294967288;
  D.4918 = arr->entry_size;
  D.4919 = D.4917 / D.4918;
  num_entries = (int) D.4919;
  size.2 = (unsigned int) size;
  chunk = mono_valloc (0B, size.2, 3);
  D.4921 = chunk == 0B;
  D.4922 = (long int) D.4921;
  D.4923 = __builtin_expect (D.4922, 0);
  if (D.4923 != 0) goto <D.4924>; else goto <D.4925>;
  <D.4924>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.4925>:
  chunk->num_entries = num_entries;
  D.4926 = chunk;
  return D.4926;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.4928;
  unsigned int exch.3;
  unsigned int comp.4;
  unsigned int D.4931;

  exch.3 = (unsigned int) exch;
  comp.4 = (unsigned int) comp;
  D.4931 = __sync_val_compare_and_swap_4 (dest, comp.4, exch.3);
  D.4928 = (void *) D.4931;
  return D.4928;
}


free_chunk (struct Chunk * chunk)
{
  int D.4933;
  unsigned int D.4934;

  D.4933 = mono_pagesize ();
  D.4934 = (unsigned int) D.4933;
  mono_vfree (chunk, D.4934);
}


mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  unsigned int D.4935;
  unsigned int i.5;
  unsigned int D.4937;
  char * D.4938;
  void * D.4941;
  int D.4942;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.4838>;
  <D.4837>:
  {
    int i;

    i = 0;
    goto <D.4835>;
    <D.4834>:
    {
      void * result;

      D.4935 = arr->entry_size;
      i.5 = (unsigned int) i;
      D.4937 = D.4935 * i.5;
      D.4938 = &chunk->entries[D.4937];
      result = func (i, D.4938, user_data);
      if (result != 0B) goto <D.4939>; else goto <D.4940>;
      <D.4939>:
      D.4941 = result;
      return D.4941;
      <D.4940>:
    }
    i = i + 1;
    <D.4835>:
    D.4942 = chunk->num_entries;
    if (D.4942 > i) goto <D.4834>; else goto <D.4836>;
    <D.4836>:
  }
  chunk = chunk->next;
  <D.4838>:
  if (chunk != 0B) goto <D.4837>; else goto <D.4839>;
  <D.4839>:
  D.4941 = 0B;
  return D.4941;
}


mono_lock_free_array_cleanup (struct MonoLockFreeArray * arr)
{
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  arr->chunk_list = 0B;
  goto <D.4846>;
  <D.4845>:
  {
    struct Chunk * next;

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.4846>:
  if (chunk != 0B) goto <D.4845>; else goto <D.4847>;
  <D.4847>:
}


mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.4944;
  int D.4945;
  struct MonoLockFreeArray * D.4946;
  gint32 * D.4947;
  int D.4948;
  unsigned int D.4949;
  unsigned int D.4950;
  void *[0:] * D.4951;
  int D.4953;
  int D.4954;
  int index;
  int num_used;
  struct Entry * entry;

  <D.4864>:
  D.4944 = &q->num_used_entries;
  D.4945 = InterlockedIncrement (D.4944);
  index = D.4945 + -1;
  D.4946 = &q->array;
  entry = mono_lock_free_array_nth (D.4946, index);
  D.4947 = &entry->state;
  D.4948 = InterlockedCompareExchange (D.4947, 2, 0);
  if (D.4948 != 0) goto <D.4864>; else goto <D.4865>;
  <D.4865>:
  mono_memory_write_barrier ();
  D.4949 = q->array.entry_size;
  D.4950 = D.4949 + 4294967292;
  D.4951 = &entry->data;
  memcpy (D.4951, entry_data_ptr, D.4950);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.4867>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.4866>; else goto <D.4952>;
  <D.4952>:
  D.4953 = index + 1;
  D.4944 = &q->num_used_entries;
  D.4954 = InterlockedCompareExchange (D.4944, D.4953, num_used);
  if (D.4954 != num_used) goto <D.4867>; else goto <D.4866>;
  <D.4866>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.4955;
  unsigned int D.4956;

  D.4956 = __sync_add_and_fetch_4 (val, 1);
  D.4955 = (gint32) D.4956;
  return D.4955;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.4958;
  unsigned int D.4959;

  D.4959 = __builtin_object_size (__dest, 0);
  D.4958 = __builtin___memcpy_chk (__dest, __src, __len, D.4959);
  return D.4958;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.4961;
  unsigned int exch.6;
  unsigned int comp.7;
  unsigned int D.4964;

  exch.6 = (unsigned int) exch;
  comp.7 = (unsigned int) comp;
  D.4964 = __sync_val_compare_and_swap_4 (dest, comp.7, exch.6);
  D.4961 = (gint32) D.4964;
  return D.4961;
}


mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.4968;
  int D.4969;
  gint32 * D.4970;
  int D.4971;
  struct MonoLockFreeArray * D.4972;
  gint32 * D.4973;
  int D.4974;
  unsigned int D.4975;
  unsigned int D.4976;
  void *[0:] * D.4977;
  int index;
  struct Entry * entry;

  <D.4876>:
  <D.4874>:
  index = q->num_used_entries;
  if (index == 0) goto <D.4966>; else goto <D.4967>;
  <D.4966>:
  D.4968 = 0;
  return D.4968;
  <D.4967>:
  D.4969 = index + -1;
  D.4970 = &q->num_used_entries;
  D.4971 = InterlockedCompareExchange (D.4970, D.4969, index);
  if (D.4971 != index) goto <D.4874>; else goto <D.4875>;
  <D.4875>:
  D.4969 = index + -1;
  D.4972 = &q->array;
  entry = mono_lock_free_array_nth (D.4972, D.4969);
  D.4973 = &entry->state;
  D.4974 = InterlockedCompareExchange (D.4973, 2, 1);
  if (D.4974 != 1) goto <D.4876>; else goto <D.4877>;
  <D.4877>:
  mono_memory_barrier ();
  D.4975 = q->array.entry_size;
  D.4976 = D.4975 + 4294967292;
  D.4977 = &entry->data;
  memcpy (entry_data_ptr, D.4977, D.4976);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.4968 = 1;
  return D.4968;
}


mono_lock_free_array_queue_cleanup (struct MonoLockFreeArrayQueue * q)
{
  struct MonoLockFreeArray * D.4979;

  D.4979 = &q->array;
  mono_lock_free_array_cleanup (D.4979);
  q->num_used_entries = 0;
}


