mono_lock_free_array_nth (struct MonoLockFreeArray * arr, int index)
{
  _Bool D.5232;
  long int D.5233;
  long int D.5234;
  struct MonoLockFreeArrayChunk * D.5237;
  struct MonoLockFreeArrayChunk * * D.5240;
  void * D.5241;
  _Bool D.5244;
  long int D.5245;
  long int D.5246;
  struct MonoLockFreeArrayChunk * * D.5251;
  void * D.5252;
  _Bool D.5255;
  long int D.5256;
  long int D.5257;
  int D.5260;
  void * D.5261;
  long unsigned int D.5262;
  long unsigned int D.5263;
  long unsigned int D.5264;
  struct Chunk * chunk;

  D.5232 = index < 0;
  D.5233 = (long int) D.5232;
  D.5234 = __builtin_expect (D.5233, 0);
  if (D.5234 != 0) goto <D.5235>; else goto <D.5236>;
  <D.5235>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 57, "index >= 0");
  <D.5236>:
  D.5237 = arr->chunk_list;
  if (D.5237 == 0B) goto <D.5238>; else goto <D.5239>;
  <D.5238>:
  chunk = alloc_chunk (arr);
  mono_memory_write_barrier ();
  D.5240 = &arr->chunk_list;
  D.5241 = InterlockedCompareExchangePointer (D.5240, chunk, 0B);
  if (D.5241 != 0B) goto <D.5242>; else goto <D.5243>;
  <D.5242>:
  free_chunk (chunk);
  <D.5243>:
  <D.5239>:
  chunk = arr->chunk_list;
  D.5244 = chunk == 0B;
  D.5245 = (long int) D.5244;
  D.5246 = __builtin_expect (D.5245, 0);
  if (D.5246 != 0) goto <D.5247>; else goto <D.5248>;
  <D.5247>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 67, "chunk");
  <D.5248>:
  goto <D.5174>;
  <D.5173>:
  {
    struct Chunk * next;

    next = chunk->next;
    if (next == 0B) goto <D.5249>; else goto <D.5250>;
    <D.5249>:
    next = alloc_chunk (arr);
    mono_memory_write_barrier ();
    D.5251 = &chunk->next;
    D.5252 = InterlockedCompareExchangePointer (D.5251, next, 0B);
    if (D.5252 != 0B) goto <D.5253>; else goto <D.5254>;
    <D.5253>:
    free_chunk (next);
    next = chunk->next;
    D.5255 = next == 0B;
    D.5256 = (long int) D.5255;
    D.5257 = __builtin_expect (D.5256, 0);
    if (D.5257 != 0) goto <D.5258>; else goto <D.5259>;
    <D.5258>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 77, "next");
    <D.5259>:
    <D.5254>:
    <D.5250>:
    D.5260 = chunk->num_entries;
    index = index - D.5260;
    chunk = next;
  }
  <D.5174>:
  D.5260 = chunk->num_entries;
  if (D.5260 <= index) goto <D.5173>; else goto <D.5175>;
  <D.5175>:
  D.5262 = (long unsigned int) index;
  D.5263 = arr->entry_size;
  D.5264 = D.5262 * D.5263;
  D.5261 = &chunk->entries[D.5264];
  return D.5261;
}


alloc_chunk (struct MonoLockFreeArray * arr)
{
  long unsigned int D.5266;
  long unsigned int D.5267;
  long unsigned int D.5268;
  long unsigned int D.5269;
  long unsigned int D.5270;
  _Bool D.5271;
  long int D.5272;
  long int D.5273;
  struct Chunk * D.5276;
  int size;
  int num_entries;
  struct Chunk * chunk;

  size = mono_pagesize ();
  D.5266 = (long unsigned int) size;
  D.5267 = D.5266 + 18446744073709551600;
  D.5268 = arr->entry_size;
  D.5269 = D.5267 / D.5268;
  num_entries = (int) D.5269;
  D.5270 = (long unsigned int) size;
  chunk = mono_valloc (0B, D.5270, 3);
  D.5271 = chunk == 0B;
  D.5272 = (long int) D.5271;
  D.5273 = __builtin_expect (D.5272, 0);
  if (D.5273 != 0) goto <D.5274>; else goto <D.5275>;
  <D.5274>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-array-queue.c", 41, "chunk");
  <D.5275>:
  chunk->num_entries = num_entries;
  D.5276 = chunk;
  return D.5276;
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


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

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


free_chunk (struct Chunk * chunk)
{
  int D.5283;
  long unsigned int D.5284;

  D.5283 = mono_pagesize ();
  D.5284 = (long unsigned int) D.5283;
  mono_vfree (chunk, D.5284);
}


mono_lock_free_array_iterate (struct MonoLockFreeArray * arr, void * (*MonoLockFreeArrayIterateFunc) (int, void *, void *) func, void * user_data)
{
  long unsigned int D.5285;
  long unsigned int D.5286;
  long unsigned int D.5287;
  char * D.5288;
  void * D.5291;
  int D.5292;
  struct Chunk * chunk;

  chunk = arr->chunk_list;
  goto <D.5188>;
  <D.5187>:
  {
    int i;

    i = 0;
    goto <D.5185>;
    <D.5184>:
    {
      void * result;

      D.5285 = (long unsigned int) i;
      D.5286 = arr->entry_size;
      D.5287 = D.5285 * D.5286;
      D.5288 = &chunk->entries[D.5287];
      result = func (i, D.5288, user_data);
      if (result != 0B) goto <D.5289>; else goto <D.5290>;
      <D.5289>:
      D.5291 = result;
      return D.5291;
      <D.5290>:
    }
    i = i + 1;
    <D.5185>:
    D.5292 = chunk->num_entries;
    if (D.5292 > i) goto <D.5184>; else goto <D.5186>;
    <D.5186>:
  }
  chunk = chunk->next;
  <D.5188>:
  if (chunk != 0B) goto <D.5187>; else goto <D.5189>;
  <D.5189>:
  D.5291 = 0B;
  return D.5291;
}


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

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

    next = chunk->next;
    free_chunk (chunk);
    chunk = next;
  }
  <D.5196>:
  if (chunk != 0B) goto <D.5195>; else goto <D.5197>;
  <D.5197>:
}


mono_lock_free_array_queue_push (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gint32 * D.5294;
  int D.5295;
  struct MonoLockFreeArray * D.5296;
  gint32 * D.5297;
  int D.5298;
  long unsigned int D.5299;
  long unsigned int D.5300;
  void *[0:] * D.5301;
  int D.5303;
  int D.5304;
  int index;
  int num_used;
  struct Entry * entry;

  <D.5214>:
  D.5294 = &q->num_used_entries;
  D.5295 = InterlockedIncrement (D.5294);
  index = D.5295 + -1;
  D.5296 = &q->array;
  entry = mono_lock_free_array_nth (D.5296, index);
  D.5297 = &entry->state;
  D.5298 = InterlockedCompareExchange (D.5297, 2, 0);
  if (D.5298 != 0) goto <D.5214>; else goto <D.5215>;
  <D.5215>:
  mono_memory_write_barrier ();
  D.5299 = q->array.entry_size;
  D.5300 = D.5299 + 18446744073709551608;
  D.5301 = &entry->data;
  memcpy (D.5301, entry_data_ptr, D.5300);
  mono_memory_write_barrier ();
  entry->state = 1;
  mono_memory_barrier ();
  <D.5217>:
  num_used = q->num_used_entries;
  if (num_used > index) goto <D.5216>; else goto <D.5302>;
  <D.5302>:
  D.5303 = index + 1;
  D.5294 = &q->num_used_entries;
  D.5304 = InterlockedCompareExchange (D.5294, D.5303, num_used);
  if (D.5304 != num_used) goto <D.5217>; else goto <D.5216>;
  <D.5216>:
  mono_memory_write_barrier ();
}


InterlockedIncrement (volatile gint32 * val)
{
  gint32 D.5305;
  unsigned int D.5306;

  D.5306 = __sync_add_and_fetch_4 (val, 1);
  D.5305 = (gint32) D.5306;
  return D.5305;
}


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

  D.5309 = __builtin_object_size (__dest, 0);
  D.5308 = __builtin___memcpy_chk (__dest, __src, __len, D.5309);
  return D.5308;
}


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

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


mono_lock_free_array_queue_pop (struct MonoLockFreeArrayQueue * q, void * entry_data_ptr)
{
  gboolean D.5318;
  int D.5319;
  gint32 * D.5320;
  int D.5321;
  struct MonoLockFreeArray * D.5322;
  gint32 * D.5323;
  int D.5324;
  long unsigned int D.5325;
  long unsigned int D.5326;
  void *[0:] * D.5327;
  int index;
  struct Entry * entry;

  <D.5226>:
  <D.5224>:
  index = q->num_used_entries;
  if (index == 0) goto <D.5316>; else goto <D.5317>;
  <D.5316>:
  D.5318 = 0;
  return D.5318;
  <D.5317>:
  D.5319 = index + -1;
  D.5320 = &q->num_used_entries;
  D.5321 = InterlockedCompareExchange (D.5320, D.5319, index);
  if (D.5321 != index) goto <D.5224>; else goto <D.5225>;
  <D.5225>:
  D.5319 = index + -1;
  D.5322 = &q->array;
  entry = mono_lock_free_array_nth (D.5322, D.5319);
  D.5323 = &entry->state;
  D.5324 = InterlockedCompareExchange (D.5323, 2, 1);
  if (D.5324 != 1) goto <D.5226>; else goto <D.5227>;
  <D.5227>:
  mono_memory_barrier ();
  D.5325 = q->array.entry_size;
  D.5326 = D.5325 + 18446744073709551608;
  D.5327 = &entry->data;
  memcpy (entry_data_ptr, D.5327, D.5326);
  mono_memory_barrier ();
  entry->state = 0;
  mono_memory_write_barrier ();
  D.5318 = 1;
  return D.5318;
}


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

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


