#line 1597 "/home/travis/build/felix-lang/felix/src/packages/gc.fdoc"
  class Rtti {
  
    The type of the collector.
    type collector_t = "::flx::gc::generic::collector_t*";
  
    The type of an RTTI record.
    type gc_shape_t = "::flx::gc::generic::gc_shape_t*";
    fun isNULL: gc_shape_t -> bool = "$1==0";
    typedef gc_shape_flags_t = uint;
      val gc_flags_default = 0;
      val gc_flags_immobile = 1;
      val gc_flags_persistent = 2;
      val gc_flags_conservative = 4;
  
    The type of a finalisation function.
    typedef gc_finaliser_t = collector_t * address --> void;
    typedef gc_encoder_t = address --> string;
    typedef gc_decoder_t = address * +char * size --> size;
  
    Iterator to find the next shape after a given one.
    fun next_shape: gc_shape_t -> gc_shape_t = "$1->next_shape";
  
    The C++ name of the Felix type.
    fun cname: gc_shape_t -> +char = "$1->cname";
  
    The static number of elements in an array type.
    Note this is not the size of a varray!
    fun number_of_elements: gc_shape_t -> size = "$1->count";
  
    Number of bytes in one element.
    fun bytes_per_element: gc_shape_t -> size = "$1->amt";
  
    The finaliser function.
    fun finaliser: gc_shape_t -> gc_finaliser_t  = "$1->finaliser";
  
    The encoder function.
    fun encoder : gc_shape_t -> gc_encoder_t = "$1->encoder";
  
    The decoder function.
    fun decoder: gc_shape_t -> gc_decoder_t = "$1->decoder";
  
    Check for offset data
    fun uses_offset_table : gc_shape_t -> bool = "$1->scanner == ::flx::gc::generic::scan_by_offsets";
  
    The number of pointers in the base type.
    If the type is an array that's the element type.
    fun _unsafe_n_offsets: gc_shape_t -> size = "((::flx::gc::generic::offset_data_t const *)($1->private_data))->n_offsets";
  
    fun n_offsets (shape: gc_shape_t) : size =>
      if uses_offset_table shape then _unsafe_n_offsets shape else 0uz
    ;
  
    Pointer to the offset table.
    fun _unsafe_offsets: gc_shape_t -> +size = "const_cast< ::std::size_t *>(((::flx::gc::generic::offset_data_t const *)($1->private_data))->offsets)";
  
    fun offsets (shape: gc_shape_t) : +size =>
      if uses_offset_table shape then _unsafe_offsets shape else C_hack::cast[+size] 0
    ;
  
    Flags.
    fun flags: gc_shape_t -> gc_shape_flags_t = "$1->flags";
  
    Global head of the compiled shape list.
    This is actually the first type, since they're linked together.
    fun shape_list_head : unit -> gc_shape_t = "PTF shape_list_head";
  
    C++ type_info for the type.
    type type_info = "::std::type_info" requires header "#include <typeinfo>";
  
    C++ source name of the type.
    fun name : type_info -> string = "::std::string($1.name())";
  
    C++ Type_info of a type.
    const typeid[T]: type_info = "typeid(?1)";
  
    // PLATFORM DEPENDENT, REQUIRES cxxabi.h.
    // Only sure to work for gcc.
    private proc _gxx_demangle: string * &string = """{
      int status;
      char *tmp=abi::__cxa_demangle($1.c_str(), 0,0, &status);
      string s= string(tmp);
      std::free(tmp);
      *$2= s;
      }
    """ requires header "#include <cxxabi.h>";
  
    For gcc only, the C++ name a mangled name represents.
    fun gxx_demangle(s:string) :string =
    {
      var r: string;
      _gxx_demangle(s, &r);
      return r;
    }
  
    proc _link_shape[T]: &gc_shape_t = """
      ::flx::gc::generic::gc_shape_t *p = (gc_shape_t*)malloc(sizeof(gc_shape_t));
      p->next_shape = PTF shape_list_head;
      PTF shape_list_head = p;
      p->cname = typeid(?1).name();
      p->count = 1;
      p->amt = sizeof(?1);
      p->finaliser = ::flx::gc::generic::std_finaliser<?1>;
      p->n_offsets = 0;
      p->offsets = 0;
      p->flags = ::flx::gc::generic::gc_flags_default;
      *$1 = p;
      """ requires property "needs_gc";
  
    Put a new shape record into the global list.
    This routine constructs a new shape record on the heap.
    It fills in some of the data based on the type.
    It links the new record into the shape list.
    Then it stores the shape at the user specified address.
    Since the shape is represented in Felix by a pointer,
    subsequent modifications carry through to the linked shape object.
    This routine is only useful for adding a shape record for a statically
    known type: that's useful because not all statically known types get
    shape records: the compiler only generates them if the shape is
    required because an object of that type is allocated on the heap.
    gen link_shape[T]()= { var p: gc_shape_t; _link_shape[T] (&p); return p; }
  }