mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.4916;
  long int D.4917;
  long int D.4918;
  struct MonoLockFreeArrayChunk * D.4921;
  struct MonoLockFreeArrayChunk * * D.4924;
  void * D.4925;
  _Bool D.4928;
  long int D.4929;
  long int D.4930;
  struct MonoLockFreeArrayChunk * * D.4935;
  void * D.4936;
  _Bool D.4939;
  long int D.4940;
  long int D.4941;
  int D.4944;
  void * D.4945;
  unsigned int D.4946;
  unsigned int index.0;
  unsigned int D.4948;
  struct Chunk * chunk;

  D.4916 = index < 0;
  D.4917 = (long int) D.4916;
  D.4918 = __builtin_expect (D.4917, 0);
  if (D.4918 != 0) goto <D.4919>; else goto <D.4920>;
  <D.4919>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.4920>:
  D.4921 = arr->chunk_list;
  if (D.4921 == 0B) goto <D.4922>; else goto <D.4923>;
  <D.4922>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.4924 = &arr->chunk_list;
  D.4925 = InterlockedCompareExchangePointer (D.4924, chunk, 0B);
  if (D.4925 != 0B) goto <D.4926>; else goto <D.4927>;
  <D.4926>:
  free_chunk (chunk);
  <D.4927>:
  <D.4923>:
  chunk = arr->chunk_list;
  D.4928 = chunk == 0B;
  D.4929 = (long int) D.4928;
  D.4930 = __builtin_expect (D.4929, 0);
  if (D.4930 != 0) goto <D.4931>; else goto <D.4932>;
  <D.4931>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.4932>:
  goto <D.4858>;
  <D.4857>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.4933>; else goto <D.4934>;
    <D.4933>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.4935 = &chunk->next;
    D.4936 = InterlockedCompareExchangePointer (D.4935, next, 0B);
    if (D.4936 != 0B) goto <D.4937>; else goto <D.4938>;
    <D.4937>:
    free_chunk (next);
    next = chunk->next;
    D.4939 = next == 0B;
    D.4940 = (long int) D.4939;
    D.4941 = __builtin_expect (D.4940, 0);
    if (D.4941 != 0) goto <D.4942>; else goto <D.4943>;
    <D.4942>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.4943>:
    <D.4938>:
    <D.4934>:
    D.4944 = chunk->num_entries;
    index = index - D.4944;
    chunk = next;
  }
  <D.4858>:
  D.4944 = chunk->num_entries;
  if (D.4944 <= index) goto <D.4857>; else goto <D.4859>;
  <D.4859>:
  D.4946 = arr->entry_size;
  index.0 = (unsigned int) index;
  D.4948 = D.4946 * index.0;
  D.4945 = &chunk->entries[D.4948];
  return D.4945;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  unsigned int size.1;
  unsigned int D.4951;
  unsigned int D.4952;
  unsigned int D.4953;
  unsigned int size.2;
  _Bool D.4955;
  long int D.4956;
  long int D.4957;
  struct Chunk * D.4960;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  size.1 = (unsigned int) size;
  D.4951 = size.1 + 4294967288;
  D.4952 = arr->entry_size;
  D.4953 = D.4951 / D.4952;
  num_entries = (int) D.4953;
  size.2 = (unsigned int) size;
  chunk = mono_valloc (0B, size.2, 3);
  D.4955 = chunk == 0B;
  D.4956 = (long int) D.4955;
  D.4957 = __builtin_expect (D.4956, 0);
  if (D.4957 != 0) goto <D.4958>; else goto <D.4959>;
  <D.4958>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.4959>:
  chunk->num_entries = num_entries;
  D.4960 = chunk;
  return D.4960;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


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

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


free_chunk (struct Chunk * chunk)
{
  int D.4967;
  unsigned int D.4968;

  D.4967 = mono_pagesize ();
  D.4968 = (unsigned int) D.4967;
  mono_vfree (chunk, D.4968);
}


mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  unsigned int D.4969;
  unsigned int i.5;
  unsigned int D.4971;
  char * D.4972;
  void * D.4975;
  int D.4976;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.4872>;
  <D.4871>:
  {
    int i;

    i = 0;
    goto <D.4869>;
    <D.4868>:
    {
      void * result;

      D.4969 = arr->entry_size;
      i.5 = (unsigned int) i;
      D.4971 = D.4969 * i.5;
      D.4972 = &chunk->entries[D.4971];
      result = func (i, D.4972, user_data);
      if (result != 0B) goto <D.4973>; else goto <D.4974>;
      <D.4973>:
      D.4975 = result;
      return D.4975;
      <D.4974>:
    }
    i = i + 1;
    <D.4869>:
    D.4976 = chunk->num_entries;
    if (D.4976 > i) goto <D.4868>; else goto <D.4870>;
    <D.4870>:
  }
  chunk = chunk->next;
  <D.4872>:
  if (chunk != 0B) goto <D.4871>; else goto <D.4873>;
  <D.4873>:
  D.4975 = 0B;
  return D.4975;
}


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

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

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.4880>:
  if (chunk != 0B) goto <D.4879>; else goto <D.4881>;
  <D.4881>:
}


mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.4978;
  int D.4979;
  struct MonoLockFreeArray * D.4980;
  gint32 * D.4981;
  int D.4982;
  void *[0:] * D.4983;
  unsigned int D.4984;
  unsigned int D.4985;
  int D.4987;
  int D.4988;
  int index;
  int num_used;
  struct Entry * entry;

  <D.4898>:
  D.4978 = &q->num_used_entries;
  D.4979 = InterlockedIncrement (D.4978);
  index = D.4979 + -1;
  D.4980 = &q->array;
  entry = mono_lock_free_array_nth (D.4980, index);
  D.4981 = &entry->state;
  D.4982 = InterlockedCompareExchange (D.4981, 2, 0);
  if (D.4982 != 0) goto <D.4898>; else goto <D.4899>;
  <D.4899>:
  mono_memory_write_barrier ();
  D.4983 = &entry->data;
  D.4984 = q->array.entry_size;
  D.4985 = D.4984 + 4294967292;
  memcpy (D.4983, entry_data_ptr, D.4985);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.4901>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.4900>; else goto <D.4986>;
  <D.4986>:
  D.4978 = &q->num_used_entries;
  D.4987 = index + 1;
  D.4988 = InterlockedCompareExchange (D.4978, D.4987, num_used);
  if (D.4988 != num_used) goto <D.4901>; else goto <D.4900>;
  <D.4900>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.4989;
  unsigned int D.4990;

  D.4990 = __sync_add_and_fetch_4 (val, 1);
  D.4989 = (gint32) D.4990;
  return D.4989;
}


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

  D.4993 = __builtin_object_size (__dest, 0);
  D.4992 = __builtin___memcpy_chk (__dest, __src, __len, D.4993);
  return D.4992;
}


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

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


mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.5002;
  gint32 * D.5003;
  int D.5004;
  int D.5005;
  struct MonoLockFreeArray * D.5006;
  gint32 * D.5007;
  int D.5008;
  void *[0:] * D.5009;
  unsigned int D.5010;
  unsigned int D.5011;
  int index;
  struct Entry * entry;

  <D.4910>:
  <D.4908>:
  index = q->num_used_entries;
  if (index == 0) goto <D.5000>; else goto <D.5001>;
  <D.5000>:
  D.5002 = 0;
  return D.5002;
  <D.5001>:
  D.5003 = &q->num_used_entries;
  D.5004 = index + -1;
  D.5005 = InterlockedCompareExchange (D.5003, D.5004, index);
  if (D.5005 != index) goto <D.4908>; else goto <D.4909>;
  <D.4909>:
  D.5006 = &q->array;
  D.5004 = index + -1;
  entry = mono_lock_free_array_nth (D.5006, D.5004);
  D.5007 = &entry->state;
  D.5008 = InterlockedCompareExchange (D.5007, 2, 1);
  if (D.5008 != 1) goto <D.4910>; else goto <D.4911>;
  <D.4911>:
  mono_memory_barrier ();
  D.5009 = &entry->data;
  D.5010 = q->array.entry_size;
  D.5011 = D.5010 + 4294967292;
  memcpy (entry_data_ptr, D.5009, D.5011);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.5002 = 1;
  return D.5002;
}


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

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


