__attribute__((visibility ("hidden")))
mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.5399;
  long int D.5400;
  long int D.5401;
  struct MonoLockFreeArrayChunk * D.5404;
  struct MonoLockFreeArrayChunk * * D.5407;
  void * D.5408;
  _Bool D.5411;
  long int D.5412;
  long int D.5413;
  struct MonoLockFreeArrayChunk * * D.5418;
  void * D.5419;
  _Bool D.5422;
  long int D.5423;
  long int D.5424;
  int D.5427;
  void * D.5428;
  char[0:] * D.5429;
  long unsigned int D.5430;
  long unsigned int D.5431;
  long unsigned int D.5432;
  struct Chunk * chunk;

  D.5399 = index < 0;
  D.5400 = (long int) D.5399;
  D.5401 = __builtin_expect (D.5400, 0);
  if (D.5401 != 0) goto <D.5402>; else goto <D.5403>;
  <D.5402>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.5403>:
  D.5404 = arr->chunk_list;
  if (D.5404 == 0B) goto <D.5405>; else goto <D.5406>;
  <D.5405>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.5407 = &arr->chunk_list;
  D.5408 = InterlockedCompareExchangePointer (D.5407, chunk, 0B);
  if (D.5408 != 0B) goto <D.5409>; else goto <D.5410>;
  <D.5409>:
  free_chunk (chunk);
  <D.5410>:
  <D.5406>:
  chunk = arr->chunk_list;
  D.5411 = chunk == 0B;
  D.5412 = (long int) D.5411;
  D.5413 = __builtin_expect (D.5412, 0);
  if (D.5413 != 0) goto <D.5414>; else goto <D.5415>;
  <D.5414>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.5415>:
  goto <D.5341>;
  <D.5340>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.5416>; else goto <D.5417>;
    <D.5416>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.5418 = &chunk->next;
    D.5419 = InterlockedCompareExchangePointer (D.5418, next, 0B);
    if (D.5419 != 0B) goto <D.5420>; else goto <D.5421>;
    <D.5420>:
    free_chunk (next);
    next = chunk->next;
    D.5422 = next == 0B;
    D.5423 = (long int) D.5422;
    D.5424 = __builtin_expect (D.5423, 0);
    if (D.5424 != 0) goto <D.5425>; else goto <D.5426>;
    <D.5425>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.5426>:
    <D.5421>:
    <D.5417>:
    D.5427 = chunk->num_entries;
    index = index - D.5427;
    chunk = next;
  }
  <D.5341>:
  D.5427 = chunk->num_entries;
  if (D.5427 <= index) goto <D.5340>; else goto <D.5342>;
  <D.5342>:
  D.5429 = &chunk->entries;
  D.5430 = (long unsigned int) index;
  D.5431 = arr->entry_size;
  D.5432 = D.5430 * D.5431;
  D.5428 = D.5429 + D.5432;
  return D.5428;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  long unsigned int D.5434;
  long unsigned int D.5435;
  long unsigned int D.5436;
  long unsigned int D.5437;
  long unsigned int D.5438;
  _Bool D.5439;
  long int D.5440;
  long int D.5441;
  struct Chunk * D.5444;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  D.5434 = (long unsigned int) size;
  D.5435 = D.5434 + 18446744073709551600;
  D.5436 = arr->entry_size;
  D.5437 = D.5435 / D.5436;
  num_entries = (int) D.5437;
  D.5438 = (long unsigned int) size;
  chunk = mono_valloc (0B, D.5438, 3);
  D.5439 = chunk == 0B;
  D.5440 = (long int) D.5439;
  D.5441 = __builtin_expect (D.5440, 0);
  if (D.5441 != 0) goto <D.5442>; else goto <D.5443>;
  <D.5442>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.5443>:
  chunk->num_entries = num_entries;
  D.5444 = chunk;
  return D.5444;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


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

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


free_chunk (struct Chunk * chunk)
{
  int D.5451;
  long unsigned int D.5452;

  D.5451 = mono_pagesize ();
  D.5452 = (long unsigned int) D.5451;
  mono_vfree (chunk, D.5452);
}


__attribute__((visibility ("hidden")))
mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  char[0:] * D.5453;
  long unsigned int D.5454;
  long unsigned int D.5455;
  long unsigned int D.5456;
  void * D.5457;
  void * D.5460;
  int D.5461;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.5355>;
  <D.5354>:
  {
    int i;

    i = 0;
    goto <D.5352>;
    <D.5351>:
    {
      void * result;

      D.5453 = &chunk->entries;
      D.5454 = (long unsigned int) i;
      D.5455 = arr->entry_size;
      D.5456 = D.5454 * D.5455;
      D.5457 = D.5453 + D.5456;
      result = func (i, D.5457, user_data);
      if (result != 0B) goto <D.5458>; else goto <D.5459>;
      <D.5458>:
      D.5460 = result;
      return D.5460;
      <D.5459>:
    }
    i = i + 1;
    <D.5352>:
    D.5461 = chunk->num_entries;
    if (D.5461 > i) goto <D.5351>; else goto <D.5353>;
    <D.5353>:
  }
  chunk = chunk->next;
  <D.5355>:
  if (chunk != 0B) goto <D.5354>; else goto <D.5356>;
  <D.5356>:
  D.5460 = 0B;
  return D.5460;
}


__attribute__((visibility ("hidden")))
mono_lock_free_array_cleanup (struct MonoLockFreeArray * arr)
{
  struct Chunk * chunk;

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

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.5363>:
  if (chunk != 0B) goto <D.5362>; else goto <D.5364>;
  <D.5364>:
}


__attribute__((visibility ("hidden")))
mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.5463;
  int D.5464;
  struct MonoLockFreeArray * D.5465;
  gint32 * D.5466;
  int D.5467;
  void *[0:] * D.5468;
  long unsigned int D.5469;
  long unsigned int D.5470;
  int D.5472;
  int D.5473;
  int index;
  int num_used;
  struct Entry * entry;

  <D.5381>:
  D.5463 = &q->num_used_entries;
  D.5464 = InterlockedIncrement (D.5463);
  index = D.5464 + -1;
  D.5465 = &q->array;
  entry = mono_lock_free_array_nth (D.5465, index);
  D.5466 = &entry->state;
  D.5467 = InterlockedCompareExchange (D.5466, 2, 0);
  if (D.5467 != 0) goto <D.5381>; else goto <D.5382>;
  <D.5382>:
  mono_memory_write_barrier ();
  D.5468 = &entry->data;
  D.5469 = q->array.entry_size;
  D.5470 = D.5469 + 18446744073709551608;
  memcpy (D.5468, entry_data_ptr, D.5470);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.5384>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.5383>; else goto <D.5471>;
  <D.5471>:
  D.5463 = &q->num_used_entries;
  D.5472 = index + 1;
  D.5473 = InterlockedCompareExchange (D.5463, D.5472, num_used);
  if (D.5473 != num_used) goto <D.5384>; else goto <D.5383>;
  <D.5383>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.5474;
  unsigned int D.5475;

  D.5475 = __sync_add_and_fetch_4 (val, 1);
  D.5474 = (gint32) D.5475;
  return D.5474;
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__, __nothrow__, __leaf__))
memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.5477;
  long unsigned int D.5478;

  D.5478 = __builtin_object_size (__dest, 0);
  D.5477 = __builtin___memcpy_chk (__dest, __src, __len, D.5478);
  return D.5477;
}


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

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


__attribute__((visibility ("hidden")))
mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.5487;
  gint32 * D.5488;
  int D.5489;
  int D.5490;
  struct MonoLockFreeArray * D.5491;
  gint32 * D.5492;
  int D.5493;
  void *[0:] * D.5494;
  long unsigned int D.5495;
  long unsigned int D.5496;
  int index;
  struct Entry * entry;

  <D.5393>:
  <D.5391>:
  index = q->num_used_entries;
  if (index == 0) goto <D.5485>; else goto <D.5486>;
  <D.5485>:
  D.5487 = 0;
  return D.5487;
  <D.5486>:
  D.5488 = &q->num_used_entries;
  D.5489 = index + -1;
  D.5490 = InterlockedCompareExchange (D.5488, D.5489, index);
  if (D.5490 != index) goto <D.5391>; else goto <D.5392>;
  <D.5392>:
  D.5491 = &q->array;
  D.5489 = index + -1;
  entry = mono_lock_free_array_nth (D.5491, D.5489);
  D.5492 = &entry->state;
  D.5493 = InterlockedCompareExchange (D.5492, 2, 1);
  if (D.5493 != 1) goto <D.5393>; else goto <D.5394>;
  <D.5394>:
  mono_memory_barrier ();
  D.5494 = &entry->data;
  D.5495 = q->array.entry_size;
  D.5496 = D.5495 + 18446744073709551608;
  memcpy (entry_data_ptr, D.5494, D.5496);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.5487 = 1;
  return D.5487;
}


__attribute__((visibility ("hidden")))
mono_lock_free_array_queue_cleanup (struct MonoLockFreeArrayQueue * q)
{
  struct MonoLockFreeArray * D.5498;

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


