mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.7505;
  long int D.7506;
  long int D.7507;
  struct MonoLockFreeArrayChunk * D.7510;
  struct MonoLockFreeArrayChunk * * D.7513;
  void * D.7514;
  _Bool D.7517;
  long int D.7518;
  long int D.7519;
  struct MonoLockFreeArrayChunk * * D.7524;
  void * D.7525;
  _Bool D.7528;
  long int D.7529;
  long int D.7530;
  int D.7533;
  void * D.7534;
  unsigned int D.7535;
  unsigned int index.0;
  unsigned int D.7537;
  struct Chunk * chunk;

  D.7505 = index < 0;
  D.7506 = (long int) D.7505;
  D.7507 = __builtin_expect (D.7506, 0);
  if (D.7507 != 0) goto <D.7508>; else goto <D.7509>;
  <D.7508>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.7509>:
  D.7510 = arr->chunk_list;
  if (D.7510 == 0B) goto <D.7511>; else goto <D.7512>;
  <D.7511>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.7513 = &arr->chunk_list;
  D.7514 = InterlockedCompareExchangePointer (D.7513, chunk, 0B);
  if (D.7514 != 0B) goto <D.7515>; else goto <D.7516>;
  <D.7515>:
  free_chunk (chunk);
  <D.7516>:
  <D.7512>:
  chunk = arr->chunk_list;
  D.7517 = chunk == 0B;
  D.7518 = (long int) D.7517;
  D.7519 = __builtin_expect (D.7518, 0);
  if (D.7519 != 0) goto <D.7520>; else goto <D.7521>;
  <D.7520>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.7521>:
  goto <D.7445>;
  <D.7444>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.7522>; else goto <D.7523>;
    <D.7522>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.7524 = &chunk->next;
    D.7525 = InterlockedCompareExchangePointer (D.7524, next, 0B);
    if (D.7525 != 0B) goto <D.7526>; else goto <D.7527>;
    <D.7526>:
    free_chunk (next);
    next = chunk->next;
    D.7528 = next == 0B;
    D.7529 = (long int) D.7528;
    D.7530 = __builtin_expect (D.7529, 0);
    if (D.7530 != 0) goto <D.7531>; else goto <D.7532>;
    <D.7531>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.7532>:
    <D.7527>:
    <D.7523>:
    D.7533 = chunk->num_entries;
    index = index - D.7533;
    chunk = next;
  }
  <D.7445>:
  D.7533 = chunk->num_entries;
  if (D.7533 <= index) goto <D.7444>; else goto <D.7446>;
  <D.7446>:
  D.7535 = arr->entry_size;
  index.0 = (unsigned int) index;
  D.7537 = D.7535 * index.0;
  D.7534 = &chunk->entries[D.7537];
  return D.7534;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  unsigned int size.1;
  unsigned int D.7540;
  unsigned int D.7541;
  unsigned int D.7542;
  unsigned int size.2;
  _Bool D.7544;
  long int D.7545;
  long int D.7546;
  struct Chunk * D.7549;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  size.1 = (unsigned int) size;
  D.7540 = size.1 + 4294967288;
  D.7541 = arr->entry_size;
  D.7542 = D.7540 / D.7541;
  num_entries = (int) D.7542;
  size.2 = (unsigned int) size;
  chunk = mono_valloc (0B, size.2, 3);
  D.7544 = chunk == 0B;
  D.7545 = (long int) D.7544;
  D.7546 = __builtin_expect (D.7545, 0);
  if (D.7546 != 0) goto <D.7547>; else goto <D.7548>;
  <D.7547>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.7548>:
  chunk->num_entries = num_entries;
  D.7549 = chunk;
  return D.7549;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


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

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


free_chunk (struct Chunk * chunk)
{
  int D.7556;
  unsigned int D.7557;

  D.7556 = mono_pagesize ();
  D.7557 = (unsigned int) D.7556;
  mono_vfree (chunk, D.7557);
}


mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  unsigned int D.7558;
  unsigned int i.5;
  unsigned int D.7560;
  char * D.7561;
  void * D.7564;
  int D.7565;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.7459>;
  <D.7458>:
  {
    int i;

    i = 0;
    goto <D.7456>;
    <D.7455>:
    {
      void * result;

      D.7558 = arr->entry_size;
      i.5 = (unsigned int) i;
      D.7560 = D.7558 * i.5;
      D.7561 = &chunk->entries[D.7560];
      result = func (i, D.7561, user_data);
      if (result != 0B) goto <D.7562>; else goto <D.7563>;
      <D.7562>:
      D.7564 = result;
      return D.7564;
      <D.7563>:
    }
    i = i + 1;
    <D.7456>:
    D.7565 = chunk->num_entries;
    if (D.7565 > i) goto <D.7455>; else goto <D.7457>;
    <D.7457>:
  }
  chunk = chunk->next;
  <D.7459>:
  if (chunk != 0B) goto <D.7458>; else goto <D.7460>;
  <D.7460>:
  D.7564 = 0B;
  return D.7564;
}


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

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

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.7467>:
  if (chunk != 0B) goto <D.7466>; else goto <D.7468>;
  <D.7468>:
}


mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.7567;
  int D.7568;
  struct MonoLockFreeArray * D.7569;
  gint32 * D.7570;
  int D.7571;
  void *[0:] * D.7572;
  unsigned int D.7573;
  unsigned int D.7574;
  int D.7576;
  int D.7577;
  int index;
  int num_used;
  struct Entry * entry;

  <D.7485>:
  D.7567 = &q->num_used_entries;
  D.7568 = InterlockedIncrement (D.7567);
  index = D.7568 + -1;
  D.7569 = &q->array;
  entry = mono_lock_free_array_nth (D.7569, index);
  D.7570 = &entry->state;
  D.7571 = InterlockedCompareExchange (D.7570, 2, 0);
  if (D.7571 != 0) goto <D.7485>; else goto <D.7486>;
  <D.7486>:
  mono_memory_write_barrier ();
  D.7572 = &entry->data;
  D.7573 = q->array.entry_size;
  D.7574 = D.7573 + 4294967292;
  memcpy (D.7572, entry_data_ptr, D.7574);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.7488>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.7487>; else goto <D.7575>;
  <D.7575>:
  D.7567 = &q->num_used_entries;
  D.7576 = index + 1;
  D.7577 = InterlockedCompareExchange (D.7567, D.7576, num_used);
  if (D.7577 != num_used) goto <D.7488>; else goto <D.7487>;
  <D.7487>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.7578;
  unsigned int D.7579;

  D.7579 = __sync_add_and_fetch_4 (val, 1);
  D.7578 = (gint32) D.7579;
  return D.7578;
}


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

  D.7582 = __builtin_object_size (__dest, 0);
  D.7581 = __builtin___memcpy_chk (__dest, __src, __len, D.7582);
  return D.7581;
}


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

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


mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.7591;
  gint32 * D.7592;
  int D.7593;
  int D.7594;
  struct MonoLockFreeArray * D.7595;
  gint32 * D.7596;
  int D.7597;
  void *[0:] * D.7598;
  unsigned int D.7599;
  unsigned int D.7600;
  int index;
  struct Entry * entry;

  <D.7497>:
  <D.7495>:
  index = q->num_used_entries;
  if (index == 0) goto <D.7589>; else goto <D.7590>;
  <D.7589>:
  D.7591 = 0;
  return D.7591;
  <D.7590>:
  D.7592 = &q->num_used_entries;
  D.7593 = index + -1;
  D.7594 = InterlockedCompareExchange (D.7592, D.7593, index);
  if (D.7594 != index) goto <D.7495>; else goto <D.7496>;
  <D.7496>:
  D.7595 = &q->array;
  D.7593 = index + -1;
  entry = mono_lock_free_array_nth (D.7595, D.7593);
  D.7596 = &entry->state;
  D.7597 = InterlockedCompareExchange (D.7596, 2, 1);
  if (D.7597 != 1) goto <D.7497>; else goto <D.7498>;
  <D.7498>:
  mono_memory_barrier ();
  D.7598 = &entry->data;
  D.7599 = q->array.entry_size;
  D.7600 = D.7599 + 4294967292;
  memcpy (entry_data_ptr, D.7598, D.7600);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.7591 = 1;
  return D.7591;
}


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

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


