sgen_card_table_get_card_data (guint8 * data_dest, mword address, mword cards)
{
  gboolean D.17614;
  mword * start;
  mword * dest;
  mword * end;
  mword mask;

  start = sgen_card_table_get_card_address (address);
  dest = data_dest;
  end = data_dest + cards;
  mask = 0;
  goto <D.17471>;
  <D.17470>:
  {
    mword v;

    v = *start;
    *dest = v;
    mask = mask | v;
    *start = 0;
  }
  dest = dest + 4;
  start = start + 4;
  <D.17471>:
  if (dest < end) goto <D.17470>; else goto <D.17472>;
  <D.17472>:
  D.17614 = (gboolean) mask;
  return D.17614;
}


sgen_card_table_get_card_address (mword address)
{
  guint8 * D.17616;
  guint8 * sgen_cardtable.0;
  unsigned int D.17618;

  sgen_cardtable.0 = sgen_cardtable;
  D.17618 = address >> 9;
  D.17616 = sgen_cardtable.0 + D.17618;
  return D.17616;
}


sgen_card_table_align_pointer (void * ptr)
{
  void * D.17620;
  unsigned int ptr.1;
  unsigned int D.17622;

  ptr.1 = (unsigned int) ptr;
  D.17622 = ptr.1 & 4294966784;
  D.17620 = (void *) D.17622;
  return D.17620;
}


sgen_card_table_mark_range (mword address, mword size)
{
  unsigned int D.17624;
  guint8 * D.17625;

  D.17624 = cards_in_range (address, size);
  D.17625 = sgen_card_table_get_card_address (address);
  memset (D.17625, 1, D.17624);
}


cards_in_range (mword address, mword size)
{
  mword iftmp.2;
  unsigned int D.17630;
  mword D.17631;
  unsigned int D.17632;
  unsigned int D.17633;
  unsigned int D.17634;
  mword end;

  if (size != 0) goto <D.17627>; else goto <D.17628>;
  <D.17627>:
  iftmp.2 = size;
  goto <D.17629>;
  <D.17628>:
  iftmp.2 = 1;
  <D.17629>:
  D.17630 = iftmp.2 + address;
  end = D.17630 + 4294967295;
  D.17632 = end >> 9;
  D.17633 = address >> 9;
  D.17634 = D.17632 - D.17633;
  D.17631 = D.17634 + 1;
  return D.17631;
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.17638;
  int D.17643;
  void * D.17645;
  unsigned int D.17646;

  D.17638 = __builtin_constant_p (__len);
  if (D.17638 != 0) goto <D.17639>; else goto <D.17640>;
  <D.17639>:
  if (__len == 0) goto <D.17641>; else goto <D.17642>;
  <D.17641>:
  D.17643 = __builtin_constant_p (__ch);
  if (D.17643 == 0) goto <D.17636>; else goto <D.17644>;
  <D.17644>:
  if (__ch != 0) goto <D.17636>; else goto <D.17637>;
  <D.17636>:
  __warn_memset_zero_len ();
  D.17645 = __dest;
  return D.17645;
  <D.17637>:
  <D.17642>:
  <D.17640>:
  D.17646 = __builtin_object_size (__dest, 0);
  D.17645 = __builtin___memset_chk (__dest, __ch, __len, D.17646);
  return D.17645;
}


sgen_card_table_update_mod_union (guint8 * dest, char * obj, mword obj_size, size_t * out_num_cards)
{
  unsigned int obj.3;
  unsigned int D.17649;
  unsigned int D.17650;
  guint8 * D.17651;
  _Bool D.17652;
  int end_card.4;
  int start_card.5;
  int D.17655;
  guint8 * D.17660;
  guint8 * result;
  guint8 * start_card;
  guint8 * end_card;
  gboolean init;
  size_t num_cards;

  result = dest;
  obj.3 = (unsigned int) obj;
  start_card = sgen_card_table_get_card_address (obj.3);
  obj.3 = (unsigned int) obj;
  D.17649 = obj.3 + obj_size;
  D.17650 = D.17649 + 4294967295;
  D.17651 = sgen_card_table_get_card_address (D.17650);
  end_card = D.17651 + 1;
  D.17652 = dest == 0B;
  init = (gboolean) D.17652;
  end_card.4 = (int) end_card;
  start_card.5 = (int) start_card;
  D.17655 = end_card.4 - start_card.5;
  num_cards = (size_t) D.17655;
  if (init != 0) goto <D.17656>; else goto <D.17657>;
  <D.17656>:
  dest = alloc_mod_union (num_cards);
  result = dest;
  <D.17657>:
  update_mod_union (dest, init, start_card, end_card);
  if (out_num_cards != 0B) goto <D.17658>; else goto <D.17659>;
  <D.17658>:
  *out_num_cards = num_cards;
  <D.17659>:
  D.17660 = result;
  return D.17660;
}


alloc_mod_union (size_t num_cards)
{
  guint8 * D.17662;

  D.17662 = sgen_alloc_internal_dynamic (num_cards, 28, 1);
  return D.17662;
}


update_mod_union (guint8 * dest, gboolean init, guint8 * start_card, guint8 * end_card)
{
  int end_card.6;
  int start_card.7;
  int D.17666;
  sizetype i.8;
  guint8 * D.17671;
  unsigned char D.17672;
  guint8 * D.17673;
  unsigned char D.17674;
  unsigned char D.17675;
  unsigned int i.9;
  size_t num_cards;

  end_card.6 = (int) end_card;
  start_card.7 = (int) start_card;
  D.17666 = end_card.6 - start_card.7;
  num_cards = (size_t) D.17666;
  if (init != 0) goto <D.17667>; else goto <D.17668>;
  <D.17667>:
  memcpy (dest, start_card, num_cards);
  goto <D.17669>;
  <D.17668>:
  {
    int i;

    i = 0;
    goto <D.17509>;
    <D.17508>:
    i.8 = (sizetype) i;
    D.17671 = dest + i.8;
    i.8 = (sizetype) i;
    D.17671 = dest + i.8;
    D.17672 = *D.17671;
    i.8 = (sizetype) i;
    D.17673 = start_card + i.8;
    D.17674 = *D.17673;
    D.17675 = D.17672 | D.17674;
    *D.17671 = D.17675;
    i = i + 1;
    <D.17509>:
    i.9 = (unsigned int) i;
    if (i.9 < num_cards) goto <D.17508>; else goto <D.17510>;
    <D.17510>:
  }
  <D.17669>:
}


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

  D.17678 = __builtin_object_size (__dest, 0);
  D.17677 = __builtin___memcpy_chk (__dest, __src, __len, D.17678);
  return D.17677;
}


mono_gc_get_card_table (int * shift_bits, void * * mask)
{
  guint8 * sgen_cardtable.10;
  guint8 * D.17683;

  sgen_cardtable.10 = sgen_cardtable;
  if (sgen_cardtable.10 == 0B) goto <D.17681>; else goto <D.17682>;
  <D.17681>:
  D.17683 = 0B;
  return D.17683;
  <D.17682>:
  *shift_bits = 9;
  *mask = 0B;
  D.17683 = sgen_cardtable;
  return D.17683;
}


mono_gc_card_table_nursery_check ()
{
  gboolean D.17685;
  int D.17686;
  _Bool D.17687;

  D.17686 = major_collector.is_concurrent;
  D.17687 = D.17686 == 0;
  D.17685 = (gboolean) D.17687;
  return D.17685;
}


sgen_cardtable_scan_object (char * obj, mword block_obj_size, guint8 * cards, gboolean mod_union, struct SgenGrayQueue * queue)
{
  unsigned int D.17689;
  unsigned int D.17690;
  void * D.17691;
  unsigned int D.17692;
  int D.17693;
  unsigned char D.17696;
  struct MonoClass * D.17699;
  void * D.17700;
  unsigned int obj.11;
  int card_data.12;
  int card_base.13;
  int D.17707;
  int D.17708;
  sizetype D.17709;
  double[0:] * D.17712;
  int start.14;
  char * D.17717;
  int D.17718;
  int D.17719;
  double[0:] * D.17720;
  int D.17721;
  sizetype D.17722;
  unsigned char D.17723;
  unsigned char D.17724;
  struct SgenObjectOperations * D.17727;
  sizetype elem_size.15;
  struct SgenObjectOperations * D.17730;
  _Bool D.17733;
  _Bool D.17734;
  _Bool D.17735;
  int D.17737;
  _Bool D.17738;
  long int D.17739;
  long int D.17740;
  int D.17741;
  _Bool D.17742;
  long int D.17743;
  long int D.17744;
  guint8 * D.17747;
  int D.17751;
  struct SgenObjectOperations * D.17754;
  void (*<T2b53>) (char *, struct SgenGrayQueue *) D.17755;
  int D.17757;
  struct SgenObjectOperations * D.17760;
  void (*<T2b53>) (char *, struct SgenGrayQueue *) D.17761;
  struct MonoVTable * vt;
  struct MonoClass * klass;

  D.17689 = MEM[(mword *)obj];
  D.17690 = D.17689 & 4294967292;
  vt = (struct MonoVTable *) D.17690;
  klass = vt->klass;
  D.17691 = vt->gc_descr;
  D.17692 = (unsigned int) D.17691;
  D.17693 = sgen_gc_descr_has_references (D.17692);
  if (D.17693 == 0) goto <D.17694>; else goto <D.17695>;
  <D.17694>:
  return;
  <D.17695>:
  D.17696 = vt->rank;
  if (D.17696 != 0) goto <D.17697>; else goto <D.17698>;
  <D.17697>:
  {
    guint8 * card_data;
    guint8 * card_base;
    guint8 * card_data_end;
    char * obj_start;
    mword obj_size;
    char * obj_end;
    size_t card_count;
    int extra_idx;
    struct MonoArray * arr;
    mword desc;
    int elem_size;

    obj_start = sgen_card_table_align_pointer (obj);
    obj_size = sgen_par_object_get_size (vt, obj);
    obj_end = obj + obj_size;
    extra_idx = 0;
    arr = obj;
    D.17699 = klass->element_class;
    D.17700 = D.17699->gc_descr;
    desc = (mword) D.17700;
    elem_size = mono_array_element_size (klass);
    if (cards != 0B) goto <D.17701>; else goto <D.17702>;
    <D.17701>:
    card_data = cards;
    goto <D.17703>;
    <D.17702>:
    obj.11 = (unsigned int) obj;
    card_data = sgen_card_table_get_card_address (obj.11);
    <D.17703>:
    card_base = card_data;
    obj.11 = (unsigned int) obj;
    card_count = cards_in_range (obj.11, obj_size);
    card_data_end = card_data + card_count;
    card_data = find_next_card (card_data, card_data_end);
    goto <D.17605>;
    <D.17604>:
    {
      int index;
      int idx;
      char * start;
      char * card_end;
      char * first_elem;
      char * elem;

      card_data.12 = (int) card_data;
      card_base.13 = (int) card_base;
      D.17707 = card_data.12 - card_base.13;
      idx = D.17707 + extra_idx;
      D.17708 = idx * 512;
      D.17709 = (sizetype) D.17708;
      start = obj_start + D.17709;
      card_end = start + 512;
      if (cards == 0B) goto <D.17710>; else goto <D.17711>;
      <D.17710>:
      sgen_card_table_prepare_card_for_scanning (card_data);
      <D.17711>:
      card_end = MIN_EXPR <obj_end, card_end>;
      D.17712 = &arr->vector;
      if (D.17712 >= start) goto <D.17713>; else goto <D.17714>;
      <D.17713>:
      index = 0;
      goto <D.17715>;
      <D.17714>:
      start.14 = (int) start;
      D.17717 = obj + 16;
      D.17718 = (int) D.17717;
      D.17719 = start.14 - D.17718;
      index = D.17719 / elem_size;
      <D.17715>:
      D.17720 = &MEM[(struct MonoArray *)obj].vector;
      D.17721 = elem_size * index;
      D.17722 = (sizetype) D.17721;
      first_elem = D.17720 + D.17722;
      elem = first_elem;
      D.17699 = klass->element_class;
      D.17723 = BIT_FIELD_REF <*D.17699, 8, 160>;
      D.17724 = D.17723 & 8;
      if (D.17724 != 0) goto <D.17725>; else goto <D.17726>;
      <D.17725>:
      {
        void (*ScanVTypeFunc) (char *, mword, struct SgenGrayQueue *) scan_vtype_func;

        D.17727 = sgen_get_current_object_ops ();
        scan_vtype_func = D.17727->scan_vtype;
        goto <D.17596>;
        <D.17595>:
        scan_vtype_func (elem, desc, queue);
        elem_size.15 = (sizetype) elem_size;
        elem = elem + elem_size.15;
        <D.17596>:
        if (elem < card_end) goto <D.17595>; else goto <D.17597>;
        <D.17597>:
      }
      goto <D.17729>;
      <D.17726>:
      {
        void (*CopyOrMarkObjectFunc) (void * *, struct SgenGrayQueue *) copy_func;

        D.17730 = sgen_get_current_object_ops ();
        copy_func = D.17730->copy_or_mark_object;
        goto <D.17602>;
        <D.17601>:
        {
          void * new;
          void * old;

          old = MEM[(void * *)elem];
          D.17733 = mod_union != 0;
          D.17734 = old != 0B;
          D.17735 = D.17733 & D.17734;
          if (D.17735 != 0) goto <D.17731>; else goto <D.17736>;
          <D.17736>:
          D.17737 = sgen_ptr_in_nursery (old);
          D.17738 = D.17737 != 0;
          D.17739 = (long int) D.17738;
          D.17740 = __builtin_expect (D.17739, 0);
          if (D.17740 != 0) goto <D.17731>; else goto <D.17732>;
          <D.17731>:
          copy_func (elem, queue);
          new = MEM[(void * *)elem];
          D.17741 = sgen_ptr_in_nursery (new);
          D.17742 = D.17741 != 0;
          D.17743 = (long int) D.17742;
          D.17744 = __builtin_expect (D.17743, 0);
          if (D.17744 != 0) goto <D.17745>; else goto <D.17746>;
          <D.17745>:
          sgen_add_to_global_remset (elem, new);
          <D.17746>:
          <D.17732>:
        }
        elem = elem + 4;
        <D.17602>:
        if (elem < card_end) goto <D.17601>; else goto <D.17603>;
        <D.17603>:
      }
      <D.17729>:
    }
    D.17747 = card_data + 1;
    card_data = find_next_card (D.17747, card_data_end);
    <D.17605>:
    if (card_data < card_data_end) goto <D.17604>; else goto <D.17606>;
    <D.17606>:
  }
  goto <D.17748>;
  <D.17698>:
  if (cards != 0B) goto <D.17749>; else goto <D.17750>;
  <D.17749>:
  obj.11 = (unsigned int) obj;
  D.17751 = sgen_card_table_is_range_marked (cards, obj.11, block_obj_size);
  if (D.17751 != 0) goto <D.17752>; else goto <D.17753>;
  <D.17752>:
  D.17754 = sgen_get_current_object_ops ();
  D.17755 = D.17754->scan_object;
  D.17755 (obj, queue);
  <D.17753>:
  goto <D.17756>;
  <D.17750>:
  obj.11 = (unsigned int) obj;
  D.17757 = sgen_card_table_region_begin_scanning (obj.11, block_obj_size);
  if (D.17757 != 0) goto <D.17758>; else goto <D.17759>;
  <D.17758>:
  D.17760 = sgen_get_current_object_ops ();
  D.17761 = D.17760->scan_object;
  D.17761 (obj, queue);
  <D.17759>:
  <D.17756>:
  <D.17748>:
}


sgen_gc_descr_has_references (mword desc)
{
  unsigned int D.17763;
  gboolean D.17766;
  unsigned int D.17767;
  unsigned int D.17770;

  D.17763 = desc & 4294901767;
  if (D.17763 == 1) goto <D.17764>; else goto <D.17765>;
  <D.17764>:
  D.17766 = 0;
  return D.17766;
  <D.17765>:
  D.17767 = desc & 49159;
  if (D.17767 == 4) goto <D.17768>; else goto <D.17769>;
  <D.17768>:
  D.17766 = 0;
  return D.17766;
  <D.17769>:
  D.17770 = desc & 7;
  if (D.17770 == 7) goto <D.17771>; else goto <D.17772>;
  <D.17771>:
  D.17766 = 0;
  return D.17766;
  <D.17772>:
  D.17766 = 1;
  return D.17766;
}


sgen_par_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  void * D.17774;
  unsigned int D.17775;
  guint D.17780;
  int D.17781;
  int D.17782;
  unsigned int D.17783;
  unsigned int D.17786;
  int D.17787;
  unsigned int D.17788;
  unsigned int element_size.16;
  unsigned int D.17790;
  unsigned int D.17791;
  struct MonoClass * D.17794;
  unsigned char D.17795;
  unsigned int D.17796;
  unsigned int D.17797;
  mword descr;
  mword type;

  D.17774 = vtable->gc_descr;
  descr = (mword) D.17774;
  type = descr & 7;
  D.17775 = type + 4294967295;
  if (D.17775 <= 1) goto <D.17776>; else goto <D.17777>;
  <D.17776>:
  {
    mword size;

    size = descr & 65528;
    if (size == 0) goto <D.17778>; else goto <D.17779>;
    <D.17778>:
    D.17781 = MEM[(struct MonoString *)o].length;
    D.17782 = D.17781 * 2;
    D.17783 = (unsigned int) D.17782;
    D.17780 = D.17783 + 14;
    return D.17780;
    <D.17779>:
    D.17780 = size;
    return D.17780;
  }
  <D.17777>:
  if (type == 4) goto <D.17784>; else goto <D.17785>;
  <D.17784>:
  {
    int element_size;
    struct MonoArray * array;
    size_t size;

    D.17786 = descr >> 3;
    D.17787 = (int) D.17786;
    element_size = D.17787 & 1023;
    array = o;
    D.17788 = array->max_length;
    element_size.16 = (unsigned int) element_size;
    D.17790 = D.17788 * element_size.16;
    size = D.17790 + 16;
    D.17791 = descr & 8192;
    if (D.17791 != 0) goto <D.17792>; else goto <D.17793>;
    <D.17792>:
    size = size + 3;
    size = size & 4294967292;
    D.17794 = vtable->klass;
    D.17795 = D.17794->rank;
    D.17796 = (unsigned int) D.17795;
    D.17797 = D.17796 * 8;
    size = D.17797 + size;
    <D.17793>:
    D.17780 = size;
    return D.17780;
  }
  <D.17785>:
  D.17780 = slow_object_get_size (vtable, o);
  return D.17780;
}


slow_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  struct MonoClass * D.17799;
  guint D.17802;
  int D.17803;
  int D.17804;
  unsigned int D.17805;
  unsigned char D.17806;
  int D.17809;
  unsigned int D.17810;
  unsigned int D.17811;
  unsigned int D.17812;
  struct MonoArrayBounds * D.17813;
  _Bool D.17814;
  long int D.17815;
  long int D.17816;
  unsigned int D.17819;
  unsigned int D.17820;
  int D.17821;
  struct MonoClass * klass;

  klass = vtable->klass;
  D.17799 = mono_defaults.string_class;
  if (D.17799 == klass) goto <D.17800>; else goto <D.17801>;
  <D.17800>:
  D.17803 = MEM[(struct MonoString *)o].length;
  D.17804 = D.17803 * 2;
  D.17805 = (unsigned int) D.17804;
  D.17802 = D.17805 + 14;
  return D.17802;
  <D.17801>:
  D.17806 = klass->rank;
  if (D.17806 != 0) goto <D.17807>; else goto <D.17808>;
  <D.17807>:
  {
    struct MonoArray * array;
    size_t size;

    array = o;
    D.17809 = klass->sizes.element_size;
    D.17810 = (unsigned int) D.17809;
    D.17811 = array->max_length;
    D.17812 = D.17810 * D.17811;
    size = D.17812 + 16;
    D.17813 = array->bounds;
    D.17814 = D.17813 != 0B;
    D.17815 = (long int) D.17814;
    D.17816 = __builtin_expect (D.17815, 0);
    if (D.17816 != 0) goto <D.17817>; else goto <D.17818>;
    <D.17817>:
    size = size + 3;
    size = size & 4294967292;
    D.17806 = klass->rank;
    D.17819 = (unsigned int) D.17806;
    D.17820 = D.17819 * 8;
    size = D.17820 + size;
    <D.17818>:
    D.17802 = size;
    return D.17802;
  }
  <D.17808>:
  D.17821 = klass->instance_size;
  D.17802 = (guint) D.17821;
  return D.17802;
}


sgen_card_table_prepare_card_for_scanning (guint8 * card)
{
  *card = 0;
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.17823;
  int sgen_nursery_bits.17;
  int D.17825;
  int D.17826;
  unsigned int D.17827;
  unsigned int p.18;
  unsigned int D.17829;
  char * sgen_nursery_start.19;
  unsigned int sgen_nursery_start.20;
  _Bool D.17832;

  sgen_nursery_bits.17 = sgen_nursery_bits;
  D.17825 = 1 << sgen_nursery_bits.17;
  D.17826 = -D.17825;
  D.17827 = (unsigned int) D.17826;
  p.18 = (unsigned int) p;
  D.17829 = D.17827 & p.18;
  sgen_nursery_start.19 = sgen_nursery_start;
  sgen_nursery_start.20 = (unsigned int) sgen_nursery_start.19;
  D.17832 = D.17829 == sgen_nursery_start.20;
  D.17823 = (gboolean) D.17832;
  return D.17823;
}


find_next_card (guint8 * card_data, guint8 * end)
{
  unsigned char D.17834;
  guint8 * D.17837;
  unsigned int card_data.21;
  unsigned int D.17839;
  unsigned int end.22;
  unsigned int D.17844;
  int D.17847;
  sizetype D.17848;
  mword * cards;
  mword * cards_end;
  mword card;

  goto <D.17560>;
  <D.17559>:
  D.17834 = *card_data;
  if (D.17834 != 0) goto <D.17835>; else goto <D.17836>;
  <D.17835>:
  D.17837 = card_data;
  return D.17837;
  <D.17836>:
  card_data = card_data + 1;
  <D.17560>:
  card_data.21 = (unsigned int) card_data;
  D.17839 = card_data.21 & 3;
  if (D.17839 != 0) goto <D.17840>; else goto <D.17561>;
  <D.17840>:
  if (card_data < end) goto <D.17559>; else goto <D.17561>;
  <D.17561>:
  if (card_data == end) goto <D.17841>; else goto <D.17842>;
  <D.17841>:
  D.17837 = end;
  return D.17837;
  <D.17842>:
  cards = card_data;
  end.22 = (unsigned int) end;
  D.17844 = end.22 & 4294967292;
  cards_end = (mword *) D.17844;
  goto <D.17563>;
  <D.17562>:
  card = *cards;
  if (card != 0) goto <D.17845>; else goto <D.17846>;
  <D.17845>:
  D.17847 = find_card_offset (card);
  D.17848 = (sizetype) D.17847;
  D.17837 = cards + D.17848;
  return D.17837;
  <D.17846>:
  cards = cards + 4;
  <D.17563>:
  if (cards < cards_end) goto <D.17562>; else goto <D.17564>;
  <D.17564>:
  card_data = cards_end;
  goto <D.17566>;
  <D.17565>:
  D.17834 = *card_data;
  if (D.17834 != 0) goto <D.17849>; else goto <D.17850>;
  <D.17849>:
  D.17837 = card_data;
  return D.17837;
  <D.17850>:
  card_data = card_data + 1;
  <D.17566>:
  if (card_data < end) goto <D.17565>; else goto <D.17567>;
  <D.17567>:
  D.17837 = end;
  return D.17837;
}


find_card_offset (mword card)
{
  int D.17852;
  int card.23;
  int D.17854;
  int D.17855;

  card.23 = (int) card;
  D.17854 = __builtin_ffs (card.23);
  D.17855 = D.17854 + -1;
  D.17852 = D.17855 / 8;
  return D.17852;
}


sgen_card_table_is_range_marked (guint8 * cards, mword address, mword size)
{
  unsigned int D.17857;
  guint8 * cards.24;
  unsigned char D.17859;
  gboolean D.17862;
  guint8 * end;

  D.17857 = cards_in_range (address, size);
  end = cards + D.17857;
  goto <D.17487>;
  <D.17486>:
  cards.24 = cards;
  cards = cards.24 + 1;
  D.17859 = *cards.24;
  if (D.17859 != 0) goto <D.17860>; else goto <D.17861>;
  <D.17860>:
  D.17862 = 1;
  return D.17862;
  <D.17861>:
  <D.17487>:
  if (cards != end) goto <D.17486>; else goto <D.17488>;
  <D.17488>:
  D.17862 = 0;
  return D.17862;
}


sgen_card_table_region_begin_scanning (mword start, mword size)
{
  unsigned int D.17864;
  guint8 * card.25;
  unsigned char D.17866;
  unsigned int D.17869;
  guint8 * D.17870;
  gboolean D.17871;
  gboolean res;
  guint8 * card;
  guint8 * end;

  res = 0;
  card = sgen_card_table_get_card_address (start);
  D.17864 = cards_in_range (start, size);
  end = card + D.17864;
  goto <D.17459>;
  <D.17458>:
  card.25 = card;
  card = card.25 + 1;
  D.17866 = *card.25;
  if (D.17866 != 0) goto <D.17867>; else goto <D.17868>;
  <D.17867>:
  res = 1;
  goto <D.17457>;
  <D.17868>:
  <D.17459>:
  if (card != end) goto <D.17458>; else goto <D.17457>;
  <D.17457>:
  D.17869 = size >> 9;
  D.17870 = sgen_card_table_get_card_address (start);
  memset (D.17870, 0, D.17869);
  D.17871 = res;
  return D.17871;
}


sgen_card_table_init (struct SgenRemeberedSet * remset)
{
  void * sgen_cardtable.26;
  struct SgenMajorCollector * D.17874;
  int need_mod_union.27;

  sgen_cardtable.26 = sgen_alloc_os_memory (8388608, 2, "card table");
  sgen_cardtable = sgen_cardtable.26;
  mono_counters_register ("cardtable major scan time", 519, &major_card_scan_time);
  mono_counters_register ("cardtable los scan time", 519, &los_card_scan_time);
  remset->wbarrier_set_field = sgen_card_table_wbarrier_set_field;
  remset->wbarrier_set_arrayref = sgen_card_table_wbarrier_set_arrayref;
  remset->wbarrier_arrayref_copy = sgen_card_table_wbarrier_arrayref_copy;
  remset->wbarrier_value_copy = sgen_card_table_wbarrier_value_copy;
  remset->wbarrier_object_copy = sgen_card_table_wbarrier_object_copy;
  remset->wbarrier_generic_nostore = sgen_card_table_wbarrier_generic_nostore;
  remset->record_pointer = sgen_card_table_record_pointer;
  remset->finish_scan_remsets = sgen_card_table_finish_scan_remsets;
  remset->finish_minor_collection = sgen_card_table_finish_minor_collection;
  remset->prepare_for_major_collection = sgen_card_table_prepare_for_major_collection;
  remset->find_address = sgen_card_table_find_address;
  remset->find_address_with_cards = sgen_card_table_find_address_with_cards;
  D.17874 = sgen_get_major_collector ();
  need_mod_union.27 = D.17874->is_concurrent;
  need_mod_union = need_mod_union.27;
}


sgen_card_table_find_address_with_cards (char * cards_start, guint8 * cards, char * addr)
{
  gboolean D.17876;
  int addr.28;
  int cards_start.29;
  int D.17879;
  int D.17880;
  sizetype D.17881;
  guint8 * D.17882;
  unsigned char D.17883;

  cards_start = sgen_card_table_align_pointer (cards_start);
  addr.28 = (int) addr;
  cards_start.29 = (int) cards_start;
  D.17879 = addr.28 - cards_start.29;
  D.17880 = D.17879 >> 9;
  D.17881 = (sizetype) D.17880;
  D.17882 = cards + D.17881;
  D.17883 = *D.17882;
  D.17876 = (gboolean) D.17883;
  return D.17876;
}


sgen_card_table_find_address (char * addr)
{
  gboolean D.17885;
  unsigned int addr.30;

  addr.30 = (unsigned int) addr;
  D.17885 = sgen_card_table_address_is_marked (addr.30);
  return D.17885;
}


sgen_card_table_address_is_marked (mword address)
{
  gboolean D.17888;
  guint8 * D.17889;
  unsigned char D.17890;
  _Bool D.17891;

  D.17889 = sgen_card_table_get_card_address (address);
  D.17890 = *D.17889;
  D.17891 = D.17890 != 0;
  D.17888 = (gboolean) D.17891;
  return D.17888;
}


sgen_card_table_prepare_for_major_collection ()
{
  sgen_major_collector_iterate_live_block_ranges (clear_cards);
  sgen_los_iterate_live_block_ranges (clear_cards);
}


clear_cards (mword start, mword size)
{
  unsigned int D.17893;
  guint8 * D.17894;

  D.17893 = cards_in_range (start, size);
  D.17894 = sgen_card_table_get_card_address (start);
  memset (D.17894, 0, D.17893);
}


sgen_card_table_finish_minor_collection ()
{
  sgen_card_tables_collect_stats (0);
}


sgen_card_tables_collect_stats (gboolean begin)
{

}


sgen_card_table_finish_scan_remsets (void * start_nursery, void * end_nursery, struct SgenGrayQueue * queue)
{
  long long int D.17895;
  long long int D.17896;
  int D.17897;
  long long int last_major_scan_time.31;
  long long int major_card_scan_time.32;
  long long int last_major_scan_time.33;
  long long int major_card_scan_time.34;
  long long int D.17902;
  long long int D.17903;
  int D.17904;
  long long int last_los_scan_time.35;
  long long int los_card_scan_time.36;
  long long int last_los_scan_time.37;
  long long int los_card_scan_time.38;
  gint64 atv;
  gint64 btv;

  sgen_card_tables_collect_stats (1);
  atv = mono_100ns_ticks ();
  sgen_major_collector_scan_card_table (queue);
  btv = mono_100ns_ticks ();
  D.17895 = btv - atv;
  D.17896 = D.17895 / 10;
  D.17897 = (int) D.17896;
  last_major_scan_time.31 = (long long int) D.17897;
  last_major_scan_time = last_major_scan_time.31;
  major_card_scan_time.32 = major_card_scan_time;
  last_major_scan_time.33 = last_major_scan_time;
  major_card_scan_time.34 = major_card_scan_time.32 + last_major_scan_time.33;
  major_card_scan_time = major_card_scan_time.34;
  sgen_los_scan_card_table (0, queue);
  atv = mono_100ns_ticks ();
  D.17902 = atv - btv;
  D.17903 = D.17902 / 10;
  D.17904 = (int) D.17903;
  last_los_scan_time.35 = (long long int) D.17904;
  last_los_scan_time = last_los_scan_time.35;
  los_card_scan_time.36 = los_card_scan_time;
  last_los_scan_time.37 = last_los_scan_time;
  los_card_scan_time.38 = los_card_scan_time.36 + last_los_scan_time.37;
  los_card_scan_time = los_card_scan_time.38;
}


sgen_card_table_record_pointer (void * address)
{
  unsigned int address.39;
  guint8 * D.17910;

  address.39 = (unsigned int) address;
  D.17910 = sgen_card_table_get_card_address (address.39);
  *D.17910 = 1;
}


sgen_card_table_wbarrier_generic_nostore (void * ptr)
{
  unsigned int ptr.40;

  ptr.40 = (unsigned int) ptr;
  sgen_card_table_mark_address (ptr.40);
}


sgen_card_table_mark_address (mword address)
{
  guint8 * D.17912;

  D.17912 = sgen_card_table_get_card_address (address);
  *D.17912 = 1;
}


sgen_card_table_wbarrier_object_copy (struct MonoObject * obj, struct MonoObject * src)
{
  struct MonoVTable * D.17913;
  struct MonoClass * D.17914;
  struct SgenThreadInfo * sgen_thread_info.41;
  unsigned int size.42;
  unsigned int D.17917;
  const void * D.17918;
  void * D.17919;
  unsigned int size.43;
  unsigned int obj.44;
  int size;

  D.17913 = obj->vtable;
  D.17914 = D.17913->klass;
  size = D.17914->instance_size;
  sgen_thread_info.41 = sgen_thread_info;
  sgen_thread_info.41->in_critical_region = 1;
  mono_memory_barrier ();
  size.42 = (unsigned int) size;
  D.17917 = size.42 + 4294967288;
  D.17918 = src + 8;
  D.17919 = obj + 8;
  mono_gc_memmove_aligned (D.17919, D.17918, D.17917);
  size.43 = (unsigned int) size;
  obj.44 = (unsigned int) obj;
  sgen_card_table_mark_range (obj.44, size.43);
  sgen_thread_info.41 = sgen_thread_info;
  sgen_thread_info.41->in_critical_region = 0;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


sgen_card_table_wbarrier_value_copy (void * dest, void * src, int count, struct MonoClass * klass)
{
  int D.17922;
  unsigned int count.45;
  struct SgenThreadInfo * sgen_thread_info.46;
  unsigned int dest.47;
  size_t element_size;
  size_t size;

  D.17922 = mono_class_value_size (klass, 0B);
  element_size = (size_t) D.17922;
  count.45 = (unsigned int) count;
  size = count.45 * element_size;
  sgen_thread_info.46 = sgen_thread_info;
  sgen_thread_info.46->in_critical_region = 1;
  mono_memory_barrier ();
  mono_gc_memmove_atomic (dest, src, size);
  dest.47 = (unsigned int) dest;
  sgen_card_table_mark_range (dest.47, size);
  sgen_thread_info.46 = sgen_thread_info;
  sgen_thread_info.46->in_critical_region = 0;
}


sgen_card_table_wbarrier_arrayref_copy (void * dest_ptr, void * src_ptr, int count)
{
  unsigned int count.48;
  unsigned int D.17930;
  void * * D.17931;
  sizetype count.49;
  sizetype D.17934;
  sizetype D.17935;
  int need_mod_union.50;
  int D.17940;
  unsigned int dest.51;
  int D.17945;
  void * * dest;
  void * * src;

  dest = dest_ptr;
  src = src_ptr;
  if (src < dest) goto <D.17928>; else goto <D.17926>;
  <D.17928>:
  count.48 = (unsigned int) count;
  D.17930 = count.48 * 4;
  D.17931 = src + D.17930;
  if (D.17931 > dest) goto <D.17932>; else goto <D.17926>;
  <D.17932>:
  {
    void * * start;

    start = dest;
    count.49 = (sizetype) count;
    D.17934 = count.49 + 1073741823;
    D.17935 = D.17934 * 4;
    dest = dest + D.17935;
    count.49 = (sizetype) count;
    D.17934 = count.49 + 1073741823;
    D.17935 = D.17934 * 4;
    src = src + D.17935;
    goto <D.17427>;
    <D.17426>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.50 = need_mod_union;
      if (need_mod_union.50 != 0) goto <D.17936>; else goto <D.17939>;
      <D.17939>:
      D.17940 = sgen_ptr_in_nursery (value);
      if (D.17940 != 0) goto <D.17936>; else goto <D.17937>;
      <D.17936>:
      dest.51 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.51);
      <D.17937>:
      sgen_dummy_use (value);
    }
    src = src + 4294967292;
    dest = dest + 4294967292;
    <D.17427>:
    if (dest >= start) goto <D.17426>; else goto <D.17428>;
    <D.17428>:
  }
  goto <D.17927>;
  <D.17926>:
  {
    void * * end;

    count.48 = (unsigned int) count;
    D.17930 = count.48 * 4;
    end = dest + D.17930;
    goto <D.17432>;
    <D.17431>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.50 = need_mod_union;
      if (need_mod_union.50 != 0) goto <D.17942>; else goto <D.17944>;
      <D.17944>:
      D.17945 = sgen_ptr_in_nursery (value);
      if (D.17945 != 0) goto <D.17942>; else goto <D.17943>;
      <D.17942>:
      dest.51 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.51);
      <D.17943>:
      sgen_dummy_use (value);
    }
    src = src + 4;
    dest = dest + 4;
    <D.17432>:
    if (dest < end) goto <D.17431>; else goto <D.17433>;
    <D.17433>:
  }
  <D.17927>:
}


sgen_dummy_use (void * v)
{
  __asm__ __volatile__("" : "=r" v : "r" v);
}


sgen_card_table_wbarrier_set_arrayref (struct MonoArray * arr, void * slot_ptr, struct MonoObject * value)
{
  int need_mod_union.52;
  int D.17950;
  unsigned int slot_ptr.53;

  MEM[(void * *)slot_ptr] = value;
  need_mod_union.52 = need_mod_union;
  if (need_mod_union.52 != 0) goto <D.17946>; else goto <D.17949>;
  <D.17949>:
  D.17950 = sgen_ptr_in_nursery (value);
  if (D.17950 != 0) goto <D.17946>; else goto <D.17947>;
  <D.17946>:
  slot_ptr.53 = (unsigned int) slot_ptr;
  sgen_card_table_mark_address (slot_ptr.53);
  <D.17947>:
  sgen_dummy_use (value);
}


sgen_card_table_wbarrier_set_field (struct MonoObject * obj, void * field_ptr, struct MonoObject * value)
{
  int need_mod_union.54;
  int D.17956;
  unsigned int field_ptr.55;

  MEM[(void * *)field_ptr] = value;
  need_mod_union.54 = need_mod_union;
  if (need_mod_union.54 != 0) goto <D.17952>; else goto <D.17955>;
  <D.17955>:
  D.17956 = sgen_ptr_in_nursery (value);
  if (D.17956 != 0) goto <D.17952>; else goto <D.17953>;
  <D.17952>:
  field_ptr.55 = (unsigned int) field_ptr;
  sgen_card_table_mark_address (field_ptr.55);
  <D.17953>:
  sgen_dummy_use (value);
}


