__attribute__((visibility ("hidden")))
sgen_card_table_get_card_data (guint8 * data_dest, mword address, mword cards)
{
  gboolean D.18138;
  mword * start;
  mword * dest;
  mword * end;
  mword mask;

  start = sgen_card_table_get_shadow_card_address (address);
  dest = data_dest;
  end = data_dest + cards;
  mask = 0;
  goto <D.17978>;
  <D.17977>:
  {
    mword v;

    v = *start;
    *dest = v;
    mask = mask | v;
  }
  dest = dest + 8;
  start = start + 8;
  <D.17978>:
  if (dest < end) goto <D.17977>; else goto <D.17979>;
  <D.17979>:
  D.18138 = (gboolean) mask;
  return D.18138;
}


sgen_card_table_get_shadow_card_address (mword address)
{
  guint8 * D.18140;
  guint8 * sgen_shadow_cardtable.0;
  long unsigned int D.18142;
  sizetype D.18143;

  sgen_shadow_cardtable.0 = sgen_shadow_cardtable;
  D.18142 = address >> 9;
  D.18143 = D.18142 & 8388607;
  D.18140 = sgen_shadow_cardtable.0 + D.18143;
  return D.18140;
}


__attribute__((visibility ("hidden")))
sgen_card_table_align_pointer (void * ptr)
{
  void * D.18145;
  long unsigned int ptr.1;
  long unsigned int D.18147;

  ptr.1 = (long unsigned int) ptr;
  D.18147 = ptr.1 & 18446744073709551104;
  D.18145 = (void *) D.18147;
  return D.18145;
}


__attribute__((visibility ("hidden")))
sgen_card_table_mark_range (mword address, mword size)
{
  guint8 * D.18149;
  long unsigned int D.18150;

  D.18149 = sgen_card_table_get_card_address (address);
  D.18150 = cards_in_range (address, size);
  memset (D.18149, 1, D.18150);
}


sgen_card_table_get_card_address (mword address)
{
  guint8 * D.18151;
  guint8 * sgen_cardtable.2;
  long unsigned int D.18153;
  sizetype D.18154;

  sgen_cardtable.2 = sgen_cardtable;
  D.18153 = address >> 9;
  D.18154 = D.18153 & 8388607;
  D.18151 = sgen_cardtable.2 + D.18154;
  return D.18151;
}


cards_in_range (mword address, mword size)
{
  mword iftmp.3;
  long unsigned int D.18160;
  mword D.18161;
  long unsigned int D.18162;
  long unsigned int D.18163;
  long unsigned int D.18164;
  mword end;

  if (size != 0) goto <D.18157>; else goto <D.18158>;
  <D.18157>:
  iftmp.3 = size;
  goto <D.18159>;
  <D.18158>:
  iftmp.3 = 1;
  <D.18159>:
  D.18160 = iftmp.3 + address;
  end = D.18160 + 18446744073709551615;
  D.18162 = end >> 9;
  D.18163 = address >> 9;
  D.18164 = D.18162 - D.18163;
  D.18161 = D.18164 + 1;
  return D.18161;
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__, __nothrow__, __leaf__))
memset (void * __dest, int __ch, size_t __len)
{
  void * D.18166;
  long unsigned int D.18167;

  D.18167 = __builtin_object_size (__dest, 0);
  D.18166 = __builtin___memset_chk (__dest, __ch, __len, D.18167);
  return D.18166;
}


__attribute__((visibility ("hidden")))
sgen_card_table_update_mod_union (guint8 * dest, char * obj, mword obj_size, size_t * out_num_cards)
{
  long unsigned int obj.4;
  long unsigned int D.18170;
  long unsigned int D.18171;
  guint8 * D.18172;
  _Bool D.18173;
  guint8 * sgen_cardtable.5;
  long int edge_card.6;
  long int start_card.7;
  long int D.18179;
  guint8 * D.18180;
  long int D.18181;
  long int D.18182;
  long int end_card.8;
  long int sgen_cardtable.9;
  long int D.18187;
  long int D.18188;
  long unsigned int D.18189;
  _Bool D.18190;
  long int D.18191;
  long int D.18192;
  long int D.18196;
  guint8 * D.18201;
  guint8 * result;
  guint8 * start_card;
  guint8 * end_card;
  gboolean init;
  size_t num_cards;

  result = dest;
  obj.4 = (long unsigned int) obj;
  start_card = sgen_card_table_get_card_address (obj.4);
  obj.4 = (long unsigned int) obj;
  D.18170 = obj.4 + obj_size;
  D.18171 = D.18170 + 18446744073709551615;
  D.18172 = sgen_card_table_get_card_address (D.18171);
  end_card = D.18172 + 1;
  D.18173 = dest == 0B;
  init = (gboolean) D.18173;
  if (end_card < start_card) goto <D.18174>; else goto <D.18175>;
  <D.18174>:
  {
    guint8 * edge_card;
    size_t num_cards_to_edge;

    sgen_cardtable.5 = sgen_cardtable;
    edge_card = sgen_cardtable.5 + 8388608;
    edge_card.6 = (long int) edge_card;
    start_card.7 = (long int) start_card;
    D.18179 = edge_card.6 - start_card.7;
    num_cards_to_edge = (size_t) D.18179;
    D.18180 = end_card + 8388608;
    D.18181 = (long int) D.18180;
    start_card.7 = (long int) start_card;
    D.18182 = D.18181 - start_card.7;
    num_cards = (size_t) D.18182;
    if (init != 0) goto <D.18183>; else goto <D.18184>;
    <D.18183>:
    dest = alloc_mod_union (num_cards);
    result = dest;
    <D.18184>:
    update_mod_union (dest, init, start_card, edge_card);
    edge_card.6 = (long int) edge_card;
    start_card.7 = (long int) start_card;
    D.18179 = edge_card.6 - start_card.7;
    end_card.8 = (long int) end_card;
    sgen_cardtable.5 = sgen_cardtable;
    sgen_cardtable.9 = (long int) sgen_cardtable.5;
    D.18187 = end_card.8 - sgen_cardtable.9;
    D.18188 = D.18179 + D.18187;
    D.18189 = (long unsigned int) D.18188;
    D.18190 = D.18189 != num_cards;
    D.18191 = (long int) D.18190;
    D.18192 = __builtin_expect (D.18191, 0);
    if (D.18192 != 0) goto <D.18193>; else goto <D.18194>;
    <D.18193>:
    monoeg_g_log (0B, 4, "wrong number of cards");
    <D.18034>:
    goto <D.18034>;
    <D.18194>:
    dest = dest + num_cards_to_edge;
    start_card = sgen_cardtable;
  }
  goto <D.18195>;
  <D.18175>:
  end_card.8 = (long int) end_card;
  start_card.7 = (long int) start_card;
  D.18196 = end_card.8 - start_card.7;
  num_cards = (size_t) D.18196;
  if (init != 0) goto <D.18197>; else goto <D.18198>;
  <D.18197>:
  dest = alloc_mod_union (num_cards);
  result = dest;
  <D.18198>:
  <D.18195>:
  update_mod_union (dest, init, start_card, end_card);
  if (out_num_cards != 0B) goto <D.18199>; else goto <D.18200>;
  <D.18199>:
  *out_num_cards = num_cards;
  <D.18200>:
  D.18201 = result;
  return D.18201;
}


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

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


update_mod_union (guint8 * dest, gboolean init, guint8 * start_card, guint8 * end_card)
{
  long int end_card.10;
  long int start_card.11;
  long int D.18207;
  sizetype D.18211;
  guint8 * D.18212;
  unsigned char D.18213;
  guint8 * D.18214;
  unsigned char D.18215;
  unsigned char D.18216;
  long unsigned int D.18217;
  size_t num_cards;

  end_card.10 = (long int) end_card;
  start_card.11 = (long int) start_card;
  D.18207 = end_card.10 - start_card.11;
  num_cards = (size_t) D.18207;
  if (init != 0) goto <D.18208>; else goto <D.18209>;
  <D.18208>:
  memcpy (dest, start_card, num_cards);
  goto <D.18210>;
  <D.18209>:
  {
    int i;

    i = 0;
    goto <D.18016>;
    <D.18015>:
    D.18211 = (sizetype) i;
    D.18212 = dest + D.18211;
    D.18211 = (sizetype) i;
    D.18212 = dest + D.18211;
    D.18213 = *D.18212;
    D.18211 = (sizetype) i;
    D.18214 = start_card + D.18211;
    D.18215 = *D.18214;
    D.18216 = D.18213 | D.18215;
    *D.18212 = D.18216;
    i = i + 1;
    <D.18016>:
    D.18217 = (long unsigned int) i;
    if (D.18217 < num_cards) goto <D.18015>; else goto <D.18017>;
    <D.18017>:
  }
  <D.18210>:
}


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

  D.18219 = __builtin_object_size (__dest, 0);
  D.18218 = __builtin___memcpy_chk (__dest, __src, __len, D.18219);
  return D.18218;
}


__attribute__((visibility ("hidden")))
mono_gc_get_card_table (int * shift_bits, void * * mask)
{
  guint8 * sgen_cardtable.12;
  guint8 * D.18224;

  sgen_cardtable.12 = sgen_cardtable;
  if (sgen_cardtable.12 == 0B) goto <D.18222>; else goto <D.18223>;
  <D.18222>:
  D.18224 = 0B;
  return D.18224;
  <D.18223>:
  *shift_bits = 9;
  *mask = 8388607B;
  D.18224 = sgen_cardtable;
  return D.18224;
}


__attribute__((visibility ("hidden")))
mono_gc_card_table_nursery_check ()
{
  gboolean D.18226;
  int D.18227;
  _Bool D.18228;

  D.18227 = major_collector.is_concurrent;
  D.18228 = D.18227 == 0;
  D.18226 = (gboolean) D.18228;
  return D.18226;
}


__attribute__((visibility ("hidden")))
sgen_cardtable_scan_object (char * obj, mword block_obj_size, guint8 * cards, gboolean mod_union, struct SgenGrayQueue * queue)
{
  long unsigned int D.18230;
  long unsigned int D.18231;
  void * D.18232;
  long unsigned int D.18233;
  int D.18234;
  unsigned char D.18237;
  unsigned int D.18240;
  struct MonoClass * D.18241;
  void * D.18242;
  long unsigned int obj.13;
  guint8 * sgen_shadow_cardtable.14;
  guint8 * D.18250;
  long int card_data_end.15;
  long int D.18254;
  long int D.18255;
  sizetype D.18256;
  long int card_data.16;
  long int card_base.17;
  long int D.18259;
  unsigned int D.18260;
  unsigned int extra_idx.18;
  unsigned int D.18262;
  int D.18263;
  sizetype D.18264;
  double[0:] * D.18267;
  long int start.19;
  char * D.18272;
  long int D.18273;
  long int D.18274;
  long int D.18275;
  long int D.18276;
  double[0:] * D.18277;
  int D.18278;
  sizetype D.18279;
  long unsigned int D.18280;
  long unsigned int D.18281;
  struct SgenObjectOperations * D.18284;
  sizetype D.18285;
  struct SgenObjectOperations * D.18287;
  int D.18292;
  _Bool D.18293;
  long int D.18294;
  long int D.18295;
  int D.18296;
  _Bool D.18297;
  long int D.18298;
  long int D.18299;
  guint8 * D.18302;
  int D.18308;
  struct SgenObjectOperations * D.18311;
  void (*<T2d43>) (char *, struct SgenGrayQueue *) D.18312;
  int D.18314;
  struct SgenObjectOperations * D.18317;
  void (*<T2d43>) (char *, struct SgenGrayQueue *) D.18318;
  struct MonoVTable * vt;
  struct MonoClass * klass;
  void LOOP_HEAD = <<< error >>>;

  D.18230 = MEM[(mword *)obj];
  D.18231 = D.18230 & 18446744073709551612;
  vt = (struct MonoVTable *) D.18231;
  klass = vt->klass;
  D.18232 = vt->gc_descr;
  D.18233 = (long unsigned int) D.18232;
  D.18234 = sgen_gc_descr_has_references (D.18233);
  if (D.18234 == 0) goto <D.18235>; else goto <D.18236>;
  <D.18235>:
  return;
  <D.18236>:
  D.18237 = vt->rank;
  if (D.18237 != 0) goto <D.18238>; else goto <D.18239>;
  <D.18238>:
  {
    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;
    guint8 * overflow_scan_end;

    obj_start = sgen_card_table_align_pointer (obj);
    D.18240 = sgen_par_object_get_size (vt, obj);
    obj_size = (mword) D.18240;
    obj_end = obj + obj_size;
    extra_idx = 0;
    arr = obj;
    D.18241 = klass->element_class;
    D.18242 = D.18241->gc_descr;
    desc = (mword) D.18242;
    elem_size = mono_array_element_size (klass);
    overflow_scan_end = 0B;
    if (cards != 0B) goto <D.18243>; else goto <D.18244>;
    <D.18243>:
    card_data = cards;
    goto <D.18245>;
    <D.18244>:
    obj.13 = (long unsigned int) obj;
    card_data = sgen_card_table_get_shadow_card_address (obj.13);
    <D.18245>:
    card_base = card_data;
    obj.13 = (long unsigned int) obj;
    card_count = cards_in_range (obj.13, obj_size);
    card_data_end = card_data + card_count;
    if (cards == 0B) goto <D.18247>; else goto <D.18248>;
    <D.18247>:
    sgen_shadow_cardtable.14 = sgen_shadow_cardtable;
    D.18250 = sgen_shadow_cardtable.14 + 8388608;
    if (D.18250 <= card_data_end) goto <D.18251>; else goto <D.18252>;
    <D.18251>:
    sgen_shadow_cardtable.14 = sgen_shadow_cardtable;
    card_data_end.15 = (long int) card_data_end;
    sgen_shadow_cardtable.14 = sgen_shadow_cardtable;
    D.18250 = sgen_shadow_cardtable.14 + 8388608;
    D.18254 = (long int) D.18250;
    D.18255 = card_data_end.15 - D.18254;
    D.18256 = (sizetype) D.18255;
    overflow_scan_end = sgen_shadow_cardtable.14 + D.18256;
    sgen_shadow_cardtable.14 = sgen_shadow_cardtable;
    card_data_end = sgen_shadow_cardtable.14 + 8388608;
    <D.18252>:
    <D.18248>:
    LOOP_HEAD:
    card_data = find_next_card (card_data, card_data_end);
    goto <D.18129>;
    <D.18128>:
    {
      int index;
      int idx;
      char * start;
      char * card_end;
      char * first_elem;
      char * elem;

      card_data.16 = (long int) card_data;
      card_base.17 = (long int) card_base;
      D.18259 = card_data.16 - card_base.17;
      D.18260 = (unsigned int) D.18259;
      extra_idx.18 = (unsigned int) extra_idx;
      D.18262 = D.18260 + extra_idx.18;
      idx = (int) D.18262;
      D.18263 = idx * 512;
      D.18264 = (sizetype) D.18263;
      start = obj_start + D.18264;
      card_end = start + 512;
      if (cards == 0B) goto <D.18265>; else goto <D.18266>;
      <D.18265>:
      sgen_card_table_prepare_card_for_scanning (card_data);
      <D.18266>:
      card_end = MIN_EXPR <obj_end, card_end>;
      D.18267 = &arr->vector;
      if (D.18267 >= start) goto <D.18268>; else goto <D.18269>;
      <D.18268>:
      index = 0;
      goto <D.18270>;
      <D.18269>:
      start.19 = (long int) start;
      D.18272 = obj + 32;
      D.18273 = (long int) D.18272;
      D.18274 = start.19 - D.18273;
      D.18275 = (long int) elem_size;
      D.18276 = D.18274 / D.18275;
      index = (int) D.18276;
      <D.18270>:
      D.18277 = &MEM[(struct MonoArray *)obj].vector;
      D.18278 = elem_size * index;
      D.18279 = (sizetype) D.18278;
      first_elem = D.18277 + D.18279;
      elem = first_elem;
      D.18241 = klass->element_class;
      D.18280 = BIT_FIELD_REF <*D.18241, 64, 256>;
      D.18281 = D.18280 & 1152921504606846976;
      if (D.18281 != 0) goto <D.18282>; else goto <D.18283>;
      <D.18282>:
      {
        void (*ScanVTypeFunc) (char *, mword, struct SgenGrayQueue *) scan_vtype_func;

        D.18284 = sgen_get_current_object_ops ();
        scan_vtype_func = D.18284->scan_vtype;
        goto <D.18120>;
        <D.18119>:
        scan_vtype_func (elem, desc, queue);
        D.18285 = (sizetype) elem_size;
        elem = elem + D.18285;
        <D.18120>:
        if (elem < card_end) goto <D.18119>; else goto <D.18121>;
        <D.18121>:
      }
      goto <D.18286>;
      <D.18283>:
      {
        void (*CopyOrMarkObjectFunc) (void * *, struct SgenGrayQueue *) copy_func;

        D.18287 = sgen_get_current_object_ops ();
        copy_func = D.18287->copy_or_mark_object;
        goto <D.18126>;
        <D.18125>:
        {
          void * new;
          void * old;

          old = MEM[(void * *)elem];
          if (mod_union != 0) goto <D.18291>; else goto <D.18288>;
          <D.18291>:
          if (old != 0B) goto <D.18289>; else goto <D.18288>;
          <D.18288>:
          D.18292 = sgen_ptr_in_nursery (old);
          D.18293 = D.18292 != 0;
          D.18294 = (long int) D.18293;
          D.18295 = __builtin_expect (D.18294, 0);
          if (D.18295 != 0) goto <D.18289>; else goto <D.18290>;
          <D.18289>:
          copy_func (elem, queue);
          new = MEM[(void * *)elem];
          D.18296 = sgen_ptr_in_nursery (new);
          D.18297 = D.18296 != 0;
          D.18298 = (long int) D.18297;
          D.18299 = __builtin_expect (D.18298, 0);
          if (D.18299 != 0) goto <D.18300>; else goto <D.18301>;
          <D.18300>:
          sgen_add_to_global_remset (elem, new);
          <D.18301>:
          <D.18290>:
        }
        elem = elem + 8;
        <D.18126>:
        if (elem < card_end) goto <D.18125>; else goto <D.18127>;
        <D.18127>:
      }
      <D.18286>:
    }
    D.18302 = card_data + 1;
    card_data = find_next_card (D.18302, card_data_end);
    <D.18129>:
    if (card_data < card_data_end) goto <D.18128>; else goto <D.18130>;
    <D.18130>:
    if (overflow_scan_end != 0B) goto <D.18303>; else goto <D.18304>;
    <D.18303>:
    card_data.16 = (long int) card_data;
    card_base.17 = (long int) card_base;
    D.18259 = card_data.16 - card_base.17;
    extra_idx = (int) D.18259;
    card_data = sgen_shadow_cardtable;
    card_base = card_data;
    card_data_end = overflow_scan_end;
    overflow_scan_end = 0B;
    goto LOOP_HEAD;
    <D.18304>:
  }
  goto <D.18305>;
  <D.18239>:
  if (cards != 0B) goto <D.18306>; else goto <D.18307>;
  <D.18306>:
  obj.13 = (long unsigned int) obj;
  D.18308 = sgen_card_table_is_range_marked (cards, obj.13, block_obj_size);
  if (D.18308 != 0) goto <D.18309>; else goto <D.18310>;
  <D.18309>:
  D.18311 = sgen_get_current_object_ops ();
  D.18312 = D.18311->scan_object;
  D.18312 (obj, queue);
  <D.18310>:
  goto <D.18313>;
  <D.18307>:
  obj.13 = (long unsigned int) obj;
  D.18314 = sgen_card_table_region_begin_scanning (obj.13, block_obj_size);
  if (D.18314 != 0) goto <D.18315>; else goto <D.18316>;
  <D.18315>:
  D.18317 = sgen_get_current_object_ops ();
  D.18318 = D.18317->scan_object;
  D.18318 (obj, queue);
  <D.18316>:
  <D.18313>:
  <D.18305>:
}


sgen_gc_descr_has_references (mword desc)
{
  long unsigned int D.18320;
  gboolean D.18323;
  long unsigned int D.18324;
  long unsigned int D.18327;

  D.18320 = desc & 4294901767;
  if (D.18320 == 1) goto <D.18321>; else goto <D.18322>;
  <D.18321>:
  D.18323 = 0;
  return D.18323;
  <D.18322>:
  D.18324 = desc & 49159;
  if (D.18324 == 4) goto <D.18325>; else goto <D.18326>;
  <D.18325>:
  D.18323 = 0;
  return D.18323;
  <D.18326>:
  D.18327 = desc & 7;
  if (D.18327 == 7) goto <D.18328>; else goto <D.18329>;
  <D.18328>:
  D.18323 = 0;
  return D.18323;
  <D.18329>:
  D.18323 = 1;
  return D.18323;
}


sgen_par_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  void * D.18331;
  long unsigned int D.18332;
  guint D.18337;
  int D.18338;
  int D.18339;
  unsigned int D.18340;
  long unsigned int D.18343;
  int D.18344;
  unsigned int D.18345;
  unsigned int element_size.20;
  unsigned int D.18347;
  long unsigned int D.18348;
  long unsigned int D.18349;
  struct MonoClass * D.18352;
  unsigned char D.18353;
  long unsigned int D.18354;
  long unsigned int D.18355;
  mword descr;
  mword type;

  D.18331 = vtable->gc_descr;
  descr = (mword) D.18331;
  type = descr & 7;
  D.18332 = type + 18446744073709551615;
  if (D.18332 <= 1) goto <D.18333>; else goto <D.18334>;
  <D.18333>:
  {
    mword size;

    size = descr & 65528;
    if (size == 0) goto <D.18335>; else goto <D.18336>;
    <D.18335>:
    D.18338 = MEM[(struct MonoString *)o].length;
    D.18339 = D.18338 * 2;
    D.18340 = (unsigned int) D.18339;
    D.18337 = D.18340 + 26;
    return D.18337;
    <D.18336>:
    D.18337 = (guint) size;
    return D.18337;
  }
  <D.18334>:
  if (type == 4) goto <D.18341>; else goto <D.18342>;
  <D.18341>:
  {
    int element_size;
    struct MonoArray * array;
    size_t size;

    D.18343 = descr >> 3;
    D.18344 = (int) D.18343;
    element_size = D.18344 & 1023;
    array = o;
    D.18345 = array->max_length;
    element_size.20 = (unsigned int) element_size;
    D.18347 = D.18345 * element_size.20;
    D.18348 = (long unsigned int) D.18347;
    size = D.18348 + 32;
    D.18349 = descr & 8192;
    if (D.18349 != 0) goto <D.18350>; else goto <D.18351>;
    <D.18350>:
    size = size + 3;
    size = size & 18446744073709551612;
    D.18352 = vtable->klass;
    D.18353 = D.18352->rank;
    D.18354 = (long unsigned int) D.18353;
    D.18355 = D.18354 * 8;
    size = D.18355 + size;
    <D.18351>:
    D.18337 = (guint) size;
    return D.18337;
  }
  <D.18342>:
  D.18337 = slow_object_get_size (vtable, o);
  return D.18337;
}


slow_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  struct MonoClass * D.18357;
  guint D.18360;
  int D.18361;
  int D.18362;
  unsigned int D.18363;
  unsigned char D.18364;
  int D.18367;
  unsigned int D.18368;
  unsigned int D.18369;
  unsigned int D.18370;
  long unsigned int D.18371;
  struct MonoArrayBounds * D.18372;
  _Bool D.18373;
  long int D.18374;
  long int D.18375;
  long unsigned int D.18378;
  long unsigned int D.18379;
  int D.18380;
  struct MonoClass * klass;

  klass = vtable->klass;
  D.18357 = mono_defaults.string_class;
  if (D.18357 == klass) goto <D.18358>; else goto <D.18359>;
  <D.18358>:
  D.18361 = MEM[(struct MonoString *)o].length;
  D.18362 = D.18361 * 2;
  D.18363 = (unsigned int) D.18362;
  D.18360 = D.18363 + 26;
  return D.18360;
  <D.18359>:
  D.18364 = klass->rank;
  if (D.18364 != 0) goto <D.18365>; else goto <D.18366>;
  <D.18365>:
  {
    struct MonoArray * array;
    size_t size;

    array = o;
    D.18367 = klass->sizes.element_size;
    D.18368 = (unsigned int) D.18367;
    D.18369 = array->max_length;
    D.18370 = D.18368 * D.18369;
    D.18371 = (long unsigned int) D.18370;
    size = D.18371 + 32;
    D.18372 = array->bounds;
    D.18373 = D.18372 != 0B;
    D.18374 = (long int) D.18373;
    D.18375 = __builtin_expect (D.18374, 0);
    if (D.18375 != 0) goto <D.18376>; else goto <D.18377>;
    <D.18376>:
    size = size + 3;
    size = size & 18446744073709551612;
    D.18364 = klass->rank;
    D.18378 = (long unsigned int) D.18364;
    D.18379 = D.18378 * 8;
    size = D.18379 + size;
    <D.18377>:
    D.18360 = (guint) size;
    return D.18360;
  }
  <D.18366>:
  D.18380 = klass->instance_size;
  D.18360 = (guint) D.18380;
  return D.18360;
}


sgen_card_table_prepare_card_for_scanning (guint8 * card)
{

}


__attribute__((always_inline))
sgen_ptr_in_nursery (void * p)
{
  gboolean D.18382;
  int sgen_nursery_bits.21;
  int D.18384;
  int D.18385;
  long unsigned int D.18386;
  long unsigned int p.22;
  long unsigned int D.18388;
  char * sgen_nursery_start.23;
  long unsigned int sgen_nursery_start.24;
  _Bool D.18391;

  sgen_nursery_bits.21 = sgen_nursery_bits;
  D.18384 = 1 << sgen_nursery_bits.21;
  D.18385 = -D.18384;
  D.18386 = (long unsigned int) D.18385;
  p.22 = (long unsigned int) p;
  D.18388 = D.18386 & p.22;
  sgen_nursery_start.23 = sgen_nursery_start;
  sgen_nursery_start.24 = (long unsigned int) sgen_nursery_start.23;
  D.18391 = D.18388 == sgen_nursery_start.24;
  D.18382 = (gboolean) D.18391;
  return D.18382;
}


find_next_card (guint8 * card_data, guint8 * end)
{
  unsigned char D.18393;
  guint8 * D.18396;
  long unsigned int card_data.25;
  long unsigned int D.18398;
  long unsigned int end.26;
  long unsigned int D.18403;
  int D.18406;
  sizetype D.18407;
  mword * cards;
  mword * cards_end;
  mword card;

  goto <D.18082>;
  <D.18081>:
  D.18393 = *card_data;
  if (D.18393 != 0) goto <D.18394>; else goto <D.18395>;
  <D.18394>:
  D.18396 = card_data;
  return D.18396;
  <D.18395>:
  card_data = card_data + 1;
  <D.18082>:
  card_data.25 = (long unsigned int) card_data;
  D.18398 = card_data.25 & 7;
  if (D.18398 != 0) goto <D.18399>; else goto <D.18083>;
  <D.18399>:
  if (card_data < end) goto <D.18081>; else goto <D.18083>;
  <D.18083>:
  if (card_data == end) goto <D.18400>; else goto <D.18401>;
  <D.18400>:
  D.18396 = end;
  return D.18396;
  <D.18401>:
  cards = card_data;
  end.26 = (long unsigned int) end;
  D.18403 = end.26 & 18446744073709551608;
  cards_end = (mword *) D.18403;
  goto <D.18085>;
  <D.18084>:
  card = *cards;
  if (card != 0) goto <D.18404>; else goto <D.18405>;
  <D.18404>:
  D.18406 = find_card_offset (card);
  D.18407 = (sizetype) D.18406;
  D.18396 = cards + D.18407;
  return D.18396;
  <D.18405>:
  cards = cards + 8;
  <D.18085>:
  if (cards < cards_end) goto <D.18084>; else goto <D.18086>;
  <D.18086>:
  card_data = cards_end;
  goto <D.18088>;
  <D.18087>:
  D.18393 = *card_data;
  if (D.18393 != 0) goto <D.18408>; else goto <D.18409>;
  <D.18408>:
  D.18396 = card_data;
  return D.18396;
  <D.18409>:
  card_data = card_data + 1;
  <D.18088>:
  if (card_data < end) goto <D.18087>; else goto <D.18089>;
  <D.18089>:
  D.18396 = end;
  return D.18396;
}


find_card_offset (mword card)
{
  int D.18411;
  unsigned int D.18412;
  unsigned int D.18413;
  unsigned int D.18414;
  unsigned int D.18415;
  unsigned int D.18416;
  unsigned int D.18417;
  unsigned int D.18418;
  unsigned int D.18419;
  unsigned int D.18420;
  unsigned int D.18421;
  long unsigned int D.18422;
  long unsigned int D.18423;
  long unsigned int D.18424;
  unsigned int D.18425;
  unsigned int D.18426;
  unsigned int D.18427;
  unsigned int D.18428;
  unsigned int D.18429;
  unsigned int D.18430;
  unsigned int D.18431;
  unsigned int D.18432;
  unsigned int D.18433;
  unsigned int D.18434;
  long unsigned int D.18435;
  long unsigned int D.18436;
  long long int D.18437;
  int D.18438;
  int D.18439;

  D.18412 = (unsigned int) card;
  D.18413 = D.18412 << 24;
  D.18412 = (unsigned int) card;
  D.18414 = D.18412 >> 8;
  D.18415 = D.18414 & 65280;
  D.18416 = D.18413 | D.18415;
  D.18412 = (unsigned int) card;
  D.18417 = D.18412 << 8;
  D.18418 = D.18417 & 16711680;
  D.18419 = D.18416 | D.18418;
  D.18412 = (unsigned int) card;
  D.18420 = D.18412 >> 24;
  D.18421 = D.18419 | D.18420;
  D.18422 = (long unsigned int) D.18421;
  D.18423 = D.18422 << 32;
  D.18424 = card >> 32;
  D.18425 = (unsigned int) D.18424;
  D.18426 = D.18425 << 24;
  D.18424 = card >> 32;
  D.18425 = (unsigned int) D.18424;
  D.18427 = D.18425 >> 8;
  D.18428 = D.18427 & 65280;
  D.18429 = D.18426 | D.18428;
  D.18424 = card >> 32;
  D.18425 = (unsigned int) D.18424;
  D.18430 = D.18425 << 8;
  D.18431 = D.18430 & 16711680;
  D.18432 = D.18429 | D.18431;
  D.18424 = card >> 32;
  D.18425 = (unsigned int) D.18424;
  D.18433 = D.18425 >> 24;
  D.18434 = D.18432 | D.18433;
  D.18435 = (long unsigned int) D.18434;
  D.18436 = D.18423 | D.18435;
  D.18437 = (long long int) D.18436;
  D.18438 = __builtin_ffsll (D.18437);
  D.18439 = D.18438 + -1;
  D.18411 = D.18439 / 8;
  return D.18411;
}


sgen_card_table_is_range_marked (guint8 * cards, mword address, mword size)
{
  long unsigned int D.18441;
  guint8 * cards.27;
  unsigned char D.18443;
  gboolean D.18446;
  guint8 * end;

  D.18441 = cards_in_range (address, size);
  end = cards + D.18441;
  goto <D.17994>;
  <D.17993>:
  cards.27 = cards;
  cards = cards.27 + 1;
  D.18443 = *cards.27;
  if (D.18443 != 0) goto <D.18444>; else goto <D.18445>;
  <D.18444>:
  D.18446 = 1;
  return D.18446;
  <D.18445>:
  <D.17994>:
  if (cards != end) goto <D.17993>; else goto <D.17995>;
  <D.17995>:
  D.18446 = 0;
  return D.18446;
}


sgen_card_table_region_begin_scanning (mword start, mword end)
{
  int D.18448;
  gboolean D.18451;

  goto <D.17965>;
  <D.17964>:
  D.18448 = sgen_card_table_card_begin_scanning (start);
  if (D.18448 != 0) goto <D.18449>; else goto <D.18450>;
  <D.18449>:
  D.18451 = 1;
  return D.18451;
  <D.18450>:
  start = start + 512;
  <D.17965>:
  if (start <= end) goto <D.17964>; else goto <D.17966>;
  <D.17966>:
  D.18451 = 0;
  return D.18451;
}


sgen_card_table_card_begin_scanning (mword address)
{
  gboolean D.18453;
  guint8 * D.18454;
  unsigned char D.18455;
  _Bool D.18456;

  D.18454 = sgen_card_table_get_shadow_card_address (address);
  D.18455 = *D.18454;
  D.18456 = D.18455 != 0;
  D.18453 = (gboolean) D.18456;
  return D.18453;
}


__attribute__((visibility ("hidden")))
sgen_card_table_init (struct SgenRemeberedSet * remset)
{
  void * D.18458;
  void * D.18459;
  struct SgenMajorCollector * D.18460;
  int D.18461;

  D.18458 = sgen_alloc_os_memory (8388608, 2, "card table");
  sgen_cardtable = D.18458;
  D.18459 = sgen_alloc_os_memory (8388608, 2, "shadow card table");
  sgen_shadow_cardtable = D.18459;
  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.18460 = sgen_get_major_collector ();
  D.18461 = D.18460->is_concurrent;
  need_mod_union = D.18461;
}


sgen_card_table_find_address_with_cards (char * cards_start, guint8 * cards, char * addr)
{
  gboolean D.18462;
  long int addr.28;
  long int cards_start.29;
  long int D.18465;
  long int D.18466;
  sizetype D.18467;
  guint8 * D.18468;
  unsigned char D.18469;

  cards_start = sgen_card_table_align_pointer (cards_start);
  addr.28 = (long int) addr;
  cards_start.29 = (long int) cards_start;
  D.18465 = addr.28 - cards_start.29;
  D.18466 = D.18465 >> 9;
  D.18467 = (sizetype) D.18466;
  D.18468 = cards + D.18467;
  D.18469 = *D.18468;
  D.18462 = (gboolean) D.18469;
  return D.18462;
}


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

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


sgen_card_table_address_is_marked (mword address)
{
  gboolean D.18474;
  guint8 * D.18475;
  unsigned char D.18476;
  _Bool D.18477;

  D.18475 = sgen_card_table_get_card_address (address);
  D.18476 = *D.18475;
  D.18477 = D.18476 != 0;
  D.18474 = (gboolean) D.18477;
  return D.18474;
}


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)
{
  guint8 * D.18479;
  guint8 * sgen_cardtable.31;
  guint8 * D.18481;
  long int D.18484;
  long int addr.32;
  long int D.18486;
  long unsigned int D.18487;
  guint8 * addr;
  size_t bytes;

  addr = sgen_card_table_get_card_address (start);
  bytes = cards_in_range (start, size);
  D.18479 = addr + bytes;
  sgen_cardtable.31 = sgen_cardtable;
  D.18481 = sgen_cardtable.31 + 8388608;
  if (D.18479 > D.18481) goto <D.18482>; else goto <D.18483>;
  <D.18482>:
  {
    size_t first_chunk;

    sgen_cardtable.31 = sgen_cardtable;
    D.18481 = sgen_cardtable.31 + 8388608;
    D.18484 = (long int) D.18481;
    addr.32 = (long int) addr;
    D.18486 = D.18484 - addr.32;
    first_chunk = (size_t) D.18486;
    memset (addr, 0, first_chunk);
    sgen_cardtable.31 = sgen_cardtable;
    D.18487 = bytes - first_chunk;
    memset (sgen_cardtable.31, 0, D.18487);
  }
  goto <D.18488>;
  <D.18483>:
  memset (addr, 0, bytes);
  <D.18488>:
}


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 int D.18489;
  long int D.18490;
  int D.18491;
  long long int D.18492;
  long long int major_card_scan_time.33;
  long long int last_major_scan_time.34;
  long long int D.18495;
  long int D.18496;
  long int D.18497;
  int D.18498;
  long long int D.18499;
  long long int los_card_scan_time.35;
  long long int last_los_scan_time.36;
  long long int D.18502;
  gint64 atv;
  gint64 btv;

  sgen_card_tables_collect_stats (1);
  sgen_major_collector_iterate_live_block_ranges (move_cards_to_shadow_table);
  sgen_los_iterate_live_block_ranges (move_cards_to_shadow_table);
  sgen_card_table_prepare_for_major_collection ();
  atv = mono_100ns_ticks ();
  sgen_major_collector_scan_card_table (queue);
  btv = mono_100ns_ticks ();
  D.18489 = btv - atv;
  D.18490 = D.18489 / 10;
  D.18491 = (int) D.18490;
  D.18492 = (long long int) D.18491;
  last_major_scan_time = D.18492;
  major_card_scan_time.33 = major_card_scan_time;
  last_major_scan_time.34 = last_major_scan_time;
  D.18495 = major_card_scan_time.33 + last_major_scan_time.34;
  major_card_scan_time = D.18495;
  sgen_los_scan_card_table (0, queue);
  atv = mono_100ns_ticks ();
  D.18496 = atv - btv;
  D.18497 = D.18496 / 10;
  D.18498 = (int) D.18497;
  D.18499 = (long long int) D.18498;
  last_los_scan_time = D.18499;
  los_card_scan_time.35 = los_card_scan_time;
  last_los_scan_time.36 = last_los_scan_time;
  D.18502 = los_card_scan_time.35 + last_los_scan_time.36;
  los_card_scan_time = D.18502;
}


move_cards_to_shadow_table (mword start, mword size)
{
  guint8 * D.18503;
  guint8 * sgen_shadow_cardtable.37;
  guint8 * D.18505;
  long int D.18508;
  long int to.38;
  long int D.18510;
  long unsigned int D.18511;
  guint8 * sgen_cardtable.39;
  guint8 * from;
  guint8 * to;
  size_t bytes;

  from = sgen_card_table_get_card_address (start);
  to = sgen_card_table_get_shadow_card_address (start);
  bytes = cards_in_range (start, size);
  D.18503 = to + bytes;
  sgen_shadow_cardtable.37 = sgen_shadow_cardtable;
  D.18505 = sgen_shadow_cardtable.37 + 8388608;
  if (D.18503 > D.18505) goto <D.18506>; else goto <D.18507>;
  <D.18506>:
  {
    size_t first_chunk;
    size_t second_chunk;

    sgen_shadow_cardtable.37 = sgen_shadow_cardtable;
    D.18505 = sgen_shadow_cardtable.37 + 8388608;
    D.18508 = (long int) D.18505;
    to.38 = (long int) to;
    D.18510 = D.18508 - to.38;
    first_chunk = (size_t) D.18510;
    D.18511 = MIN_EXPR <bytes, 8388608>;
    second_chunk = D.18511 - first_chunk;
    memcpy (to, from, first_chunk);
    sgen_shadow_cardtable.37 = sgen_shadow_cardtable;
    sgen_cardtable.39 = sgen_cardtable;
    memcpy (sgen_shadow_cardtable.37, sgen_cardtable.39, second_chunk);
  }
  goto <D.18513>;
  <D.18507>:
  memcpy (to, from, bytes);
  <D.18513>:
}


sgen_card_table_record_pointer (void * address)
{
  long unsigned int address.40;
  guint8 * D.18515;

  address.40 = (long unsigned int) address;
  D.18515 = sgen_card_table_get_card_address (address.40);
  *D.18515 = 1;
}


sgen_card_table_wbarrier_generic_nostore (void * ptr)
{
  long unsigned int ptr.41;

  ptr.41 = (long unsigned int) ptr;
  sgen_card_table_mark_address (ptr.41);
}


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

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


sgen_card_table_wbarrier_object_copy (struct MonoObject * obj, struct MonoObject * src)
{
  struct MonoVTable * D.18518;
  struct MonoClass * D.18519;
  struct SgenThreadInfo * sgen_thread_info.42;
  void * D.18521;
  const void * D.18522;
  long unsigned int D.18523;
  long unsigned int D.18524;
  long unsigned int obj.43;
  long unsigned int D.18526;
  int size;

  D.18518 = obj->vtable;
  D.18519 = D.18518->klass;
  size = D.18519->instance_size;
  sgen_thread_info.42 = sgen_thread_info;
  sgen_thread_info.42->in_critical_region = 1;
  D.18521 = obj + 16;
  D.18522 = src + 16;
  D.18523 = (long unsigned int) size;
  D.18524 = D.18523 + 18446744073709551600;
  mono_gc_memmove_aligned (D.18521, D.18522, D.18524);
  obj.43 = (long unsigned int) obj;
  D.18526 = (long unsigned int) size;
  sgen_card_table_mark_range (obj.43, D.18526);
  sgen_thread_info.42 = sgen_thread_info;
  sgen_thread_info.42->in_critical_region = 0;
}


sgen_card_table_wbarrier_value_copy (void * dest, void * src, int count, struct MonoClass * klass)
{
  int D.18527;
  long unsigned int D.18528;
  struct SgenThreadInfo * sgen_thread_info.44;
  long unsigned int dest.45;
  size_t element_size;
  size_t size;

  D.18527 = mono_class_value_size (klass, 0B);
  element_size = (size_t) D.18527;
  D.18528 = (long unsigned int) count;
  size = D.18528 * element_size;
  sgen_thread_info.44 = sgen_thread_info;
  sgen_thread_info.44->in_critical_region = 1;
  mono_gc_memmove_atomic (dest, src, size);
  dest.45 = (long unsigned int) dest;
  sgen_card_table_mark_range (dest.45, size);
  sgen_thread_info.44 = sgen_thread_info;
  sgen_thread_info.44->in_critical_region = 0;
}


sgen_card_table_wbarrier_arrayref_copy (void * dest_ptr, void * src_ptr, int count)
{
  long unsigned int D.18534;
  long unsigned int D.18535;
  void * * D.18536;
  sizetype D.18538;
  int need_mod_union.46;
  int D.18543;
  long unsigned int dest.47;
  int D.18548;
  void * * dest;
  void * * src;

  dest = dest_ptr;
  src = src_ptr;
  if (src < dest) goto <D.18533>; else goto <D.18531>;
  <D.18533>:
  D.18534 = (long unsigned int) count;
  D.18535 = D.18534 * 8;
  D.18536 = src + D.18535;
  if (D.18536 > dest) goto <D.18537>; else goto <D.18531>;
  <D.18537>:
  {
    void * * start;

    start = dest;
    D.18534 = (long unsigned int) count;
    D.18535 = D.18534 * 8;
    D.18538 = D.18535 + 18446744073709551608;
    dest = dest + D.18538;
    D.18534 = (long unsigned int) count;
    D.18535 = D.18534 * 8;
    D.18538 = D.18535 + 18446744073709551608;
    src = src + D.18538;
    goto <D.17936>;
    <D.17935>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.46 = need_mod_union;
      if (need_mod_union.46 != 0) goto <D.18539>; else goto <D.18542>;
      <D.18542>:
      D.18543 = sgen_ptr_in_nursery (value);
      if (D.18543 != 0) goto <D.18539>; else goto <D.18540>;
      <D.18539>:
      dest.47 = (long unsigned int) dest;
      sgen_card_table_mark_address (dest.47);
      <D.18540>:
      sgen_dummy_use (value);
    }
    src = src + 18446744073709551608;
    dest = dest + 18446744073709551608;
    <D.17936>:
    if (dest >= start) goto <D.17935>; else goto <D.17937>;
    <D.17937>:
  }
  goto <D.18532>;
  <D.18531>:
  {
    void * * end;

    D.18534 = (long unsigned int) count;
    D.18535 = D.18534 * 8;
    end = dest + D.18535;
    goto <D.17941>;
    <D.17940>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.46 = need_mod_union;
      if (need_mod_union.46 != 0) goto <D.18545>; else goto <D.18547>;
      <D.18547>:
      D.18548 = sgen_ptr_in_nursery (value);
      if (D.18548 != 0) goto <D.18545>; else goto <D.18546>;
      <D.18545>:
      dest.47 = (long unsigned int) dest;
      sgen_card_table_mark_address (dest.47);
      <D.18546>:
      sgen_dummy_use (value);
    }
    src = src + 8;
    dest = dest + 8;
    <D.17941>:
    if (dest < end) goto <D.17940>; else goto <D.17942>;
    <D.17942>:
  }
  <D.18532>:
}


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.48;
  int D.18553;
  long unsigned int slot_ptr.49;

  MEM[(void * *)slot_ptr] = value;
  need_mod_union.48 = need_mod_union;
  if (need_mod_union.48 != 0) goto <D.18549>; else goto <D.18552>;
  <D.18552>:
  D.18553 = sgen_ptr_in_nursery (value);
  if (D.18553 != 0) goto <D.18549>; else goto <D.18550>;
  <D.18549>:
  slot_ptr.49 = (long unsigned int) slot_ptr;
  sgen_card_table_mark_address (slot_ptr.49);
  <D.18550>:
  sgen_dummy_use (value);
}


sgen_card_table_wbarrier_set_field (struct MonoObject * obj, void * field_ptr, struct MonoObject * value)
{
  int need_mod_union.50;
  int D.18559;
  long unsigned int field_ptr.51;

  MEM[(void * *)field_ptr] = value;
  need_mod_union.50 = need_mod_union;
  if (need_mod_union.50 != 0) goto <D.18555>; else goto <D.18558>;
  <D.18558>:
  D.18559 = sgen_ptr_in_nursery (value);
  if (D.18559 != 0) goto <D.18555>; else goto <D.18556>;
  <D.18555>:
  field_ptr.51 = (long unsigned int) field_ptr;
  sgen_card_table_mark_address (field_ptr.51);
  <D.18556>:
  sgen_dummy_use (value);
}


