mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.5746;
  long int D.5747;
  long int D.5748;
  struct MonoLockFreeArrayChunk * D.5751;
  struct MonoLockFreeArrayChunk * * D.5754;
  void * D.5755;
  _Bool D.5758;
  long int D.5759;
  long int D.5760;
  struct MonoLockFreeArrayChunk * * D.5765;
  void * D.5766;
  _Bool D.5769;
  long int D.5770;
  long int D.5771;
  int D.5774;
  void * D.5775;
  long unsigned int D.5776;
  long unsigned int D.5777;
  long unsigned int D.5778;
  struct Chunk * chunk;

  D.5746 = index < 0;
  D.5747 = (long int) D.5746;
  D.5748 = __builtin_expect (D.5747, 0);
  if (D.5748 != 0) goto <D.5749>; else goto <D.5750>;
  <D.5749>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.5750>:
  D.5751 = arr->chunk_list;
  if (D.5751 == 0B) goto <D.5752>; else goto <D.5753>;
  <D.5752>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.5754 = &arr->chunk_list;
  D.5755 = InterlockedCompareExchangePointer (D.5754, chunk, 0B);
  if (D.5755 != 0B) goto <D.5756>; else goto <D.5757>;
  <D.5756>:
  free_chunk (chunk);
  <D.5757>:
  <D.5753>:
  chunk = arr->chunk_list;
  D.5758 = chunk == 0B;
  D.5759 = (long int) D.5758;
  D.5760 = __builtin_expect (D.5759, 0);
  if (D.5760 != 0) goto <D.5761>; else goto <D.5762>;
  <D.5761>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.5762>:
  goto <D.5688>;
  <D.5687>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.5763>; else goto <D.5764>;
    <D.5763>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.5765 = &chunk->next;
    D.5766 = InterlockedCompareExchangePointer (D.5765, next, 0B);
    if (D.5766 != 0B) goto <D.5767>; else goto <D.5768>;
    <D.5767>:
    free_chunk (next);
    next = chunk->next;
    D.5769 = next == 0B;
    D.5770 = (long int) D.5769;
    D.5771 = __builtin_expect (D.5770, 0);
    if (D.5771 != 0) goto <D.5772>; else goto <D.5773>;
    <D.5772>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.5773>:
    <D.5768>:
    <D.5764>:
    D.5774 = chunk->num_entries;
    index = index - D.5774;
    chunk = next;
  }
  <D.5688>:
  D.5774 = chunk->num_entries;
  if (D.5774 <= index) goto <D.5687>; else goto <D.5689>;
  <D.5689>:
  D.5776 = (long unsigned int) index;
  D.5777 = arr->entry_size;
  D.5778 = D.5776 * D.5777;
  D.5775 = &chunk->entries[D.5778];
  return D.5775;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  long unsigned int D.5780;
  long unsigned int D.5781;
  long unsigned int D.5782;
  long unsigned int D.5783;
  long unsigned int D.5784;
  _Bool D.5785;
  long int D.5786;
  long int D.5787;
  struct Chunk * D.5790;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  D.5780 = (long unsigned int) size;
  D.5781 = D.5780 + 18446744073709551600;
  D.5782 = arr->entry_size;
  D.5783 = D.5781 / D.5782;
  num_entries = (int) D.5783;
  D.5784 = (long unsigned int) size;
  chunk = mono_valloc (0B, D.5784, 3);
  D.5785 = chunk == 0B;
  D.5786 = (long int) D.5785;
  D.5787 = __builtin_expect (D.5786, 0);
  if (D.5787 != 0) goto <D.5788>; else goto <D.5789>;
  <D.5788>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.5789>:
  chunk->num_entries = num_entries;
  D.5790 = chunk;
  return D.5790;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.5792;
  long unsigned int comp.0;
  long unsigned int exch.1;
  long unsigned int D.5795;

  comp.0 = (long unsigned int) comp;
  exch.1 = (long unsigned int) exch;
  D.5795 = __sync_val_compare_and_swap_8 (dest, comp.0, exch.1);
  D.5792 = (void *) D.5795;
  return D.5792;
}


free_chunk (struct Chunk * chunk)
{
  int D.5797;
  long unsigned int D.5798;

  D.5797 = mono_pagesize ();
  D.5798 = (long unsigned int) D.5797;
  mono_vfree (chunk, D.5798);
}


mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  long unsigned int D.5799;
  long unsigned int D.5800;
  long unsigned int D.5801;
  char * D.5802;
  void * D.5805;
  int D.5806;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.5702>;
  <D.5701>:
  {
    int i;

    i = 0;
    goto <D.5699>;
    <D.5698>:
    {
      void * result;

      D.5799 = (long unsigned int) i;
      D.5800 = arr->entry_size;
      D.5801 = D.5799 * D.5800;
      D.5802 = &chunk->entries[D.5801];
      result = func (i, D.5802, user_data);
      if (result != 0B) goto <D.5803>; else goto <D.5804>;
      <D.5803>:
      D.5805 = result;
      return D.5805;
      <D.5804>:
    }
    i = i + 1;
    <D.5699>:
    D.5806 = chunk->num_entries;
    if (D.5806 > i) goto <D.5698>; else goto <D.5700>;
    <D.5700>:
  }
  chunk = chunk->next;
  <D.5702>:
  if (chunk != 0B) goto <D.5701>; else goto <D.5703>;
  <D.5703>:
  D.5805 = 0B;
  return D.5805;
}


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

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

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.5710>:
  if (chunk != 0B) goto <D.5709>; else goto <D.5711>;
  <D.5711>:
}


mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.5808;
  int D.5809;
  struct MonoLockFreeArray * D.5810;
  gint32 * D.5811;
  int D.5812;
  void *[0:] * D.5813;
  long unsigned int D.5814;
  long unsigned int D.5815;
  int D.5817;
  int D.5818;
  int index;
  int num_used;
  struct Entry * entry;

  <D.5728>:
  D.5808 = &q->num_used_entries;
  D.5809 = InterlockedIncrement (D.5808);
  index = D.5809 + -1;
  D.5810 = &q->array;
  entry = mono_lock_free_array_nth (D.5810, index);
  D.5811 = &entry->state;
  D.5812 = InterlockedCompareExchange (D.5811, 2, 0);
  if (D.5812 != 0) goto <D.5728>; else goto <D.5729>;
  <D.5729>:
  mono_memory_write_barrier ();
  D.5813 = &entry->data;
  D.5814 = q->array.entry_size;
  D.5815 = D.5814 + 18446744073709551608;
  memcpy (D.5813, entry_data_ptr, D.5815);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.5731>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.5730>; else goto <D.5816>;
  <D.5816>:
  D.5808 = &q->num_used_entries;
  D.5817 = index + 1;
  D.5818 = InterlockedCompareExchange (D.5808, D.5817, num_used);
  if (D.5818 != num_used) goto <D.5731>; else goto <D.5730>;
  <D.5730>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.5819;
  unsigned int D.5820;

  D.5820 = __sync_add_and_fetch_4 (val, 1);
  D.5819 = (gint32) D.5820;
  return D.5819;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.5822;
  long unsigned int D.5823;

  D.5823 = __builtin_object_size (__dest, 0);
  D.5822 = __builtin___memcpy_chk (__dest, __src, __len, D.5823);
  return D.5822;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.5825;
  unsigned int comp.2;
  unsigned int exch.3;
  unsigned int D.5828;

  comp.2 = (unsigned int) comp;
  exch.3 = (unsigned int) exch;
  D.5828 = __sync_val_compare_and_swap_4 (dest, comp.2, exch.3);
  D.5825 = (gint32) D.5828;
  return D.5825;
}


mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.5832;
  gint32 * D.5833;
  int D.5834;
  int D.5835;
  struct MonoLockFreeArray * D.5836;
  gint32 * D.5837;
  int D.5838;
  void *[0:] * D.5839;
  long unsigned int D.5840;
  long unsigned int D.5841;
  int index;
  struct Entry * entry;

  <D.5740>:
  <D.5738>:
  index = q->num_used_entries;
  if (index == 0) goto <D.5830>; else goto <D.5831>;
  <D.5830>:
  D.5832 = 0;
  return D.5832;
  <D.5831>:
  D.5833 = &q->num_used_entries;
  D.5834 = index + -1;
  D.5835 = InterlockedCompareExchange (D.5833, D.5834, index);
  if (D.5835 != index) goto <D.5738>; else goto <D.5739>;
  <D.5739>:
  D.5836 = &q->array;
  D.5834 = index + -1;
  entry = mono_lock_free_array_nth (D.5836, D.5834);
  D.5837 = &entry->state;
  D.5838 = InterlockedCompareExchange (D.5837, 2, 1);
  if (D.5838 != 1) goto <D.5740>; else goto <D.5741>;
  <D.5741>:
  mono_memory_barrier ();
  D.5839 = &entry->data;
  D.5840 = q->array.entry_size;
  D.5841 = D.5840 + 18446744073709551608;
  memcpy (entry_data_ptr, D.5839, D.5841);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.5832 = 1;
  return D.5832;
}


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

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


