コード例 #1
0
ファイル: gendesc.c プロジェクト: DevL/ponyc
LLVMTypeRef gendesc_type(compile_t* c, gentype_t* g)
{
  const char* desc_name;
  uint32_t traits = 0;
  uint32_t fields = 0;
  uint32_t vtable_size = 0;

  if(g != NULL)
  {
    // TODO: wrong trait count
    desc_name = g->desc_name;
    traits = trait_count(c, g, NULL, NULL);

    if(g->underlying == TK_TUPLETYPE)
    {
      fields = g->field_count;
    } else {
      vtable_size = genfun_vtable_size(c, g);
    }
  } else {
    desc_name = genname_descriptor(NULL);
  }

  LLVMTypeRef type = LLVMGetTypeByName(c->module, desc_name);

  if(type == NULL)
  {
    type = LLVMStructCreateNamed(c->context, desc_name);
  } else if(!LLVMIsOpaqueStruct(type)) {
    return type;
  }

  LLVMTypeRef params[DESC_LENGTH];

  params[DESC_ID] = c->i32;
  params[DESC_SIZE] = c->i32;
  params[DESC_TRAIT_COUNT] = c->i32;
  params[DESC_FIELD_COUNT] = c->i32;
  params[DESC_FIELD_OFFSET] = c->i32;
  params[DESC_TRACE] = c->trace_fn;
  params[DESC_SERIALISE] = c->trace_fn;
  params[DESC_DESERIALISE] = c->trace_fn;
  params[DESC_DISPATCH] = c->dispatch_fn;
  params[DESC_FINALISE] = c->final_fn;
  params[DESC_EVENT_NOTIFY] = c->i32;
  params[DESC_TRAITS] = LLVMPointerType(LLVMArrayType(c->i32, traits), 0);
  params[DESC_FIELDS] = LLVMPointerType(
    LLVMArrayType(c->field_descriptor, fields), 0);
  params[DESC_VTABLE] = LLVMArrayType(c->void_ptr, vtable_size);

  LLVMStructSetBody(type, params, DESC_LENGTH, false);
  return type;
}
コード例 #2
0
ファイル: gentype.c プロジェクト: nunb/ponyc
static void make_box_type(compile_t* c, gentype_t* g)
{
  if(g->primitive == NULL)
    return;

  if(g->structure == NULL)
  {
    const char* box_name = genname_box(g->type_name);
    g->structure = LLVMGetTypeByName(c->module, box_name);

    if(g->structure == NULL)
      g->structure = LLVMStructCreateNamed(c->context, box_name);
  }

  if(LLVMIsOpaqueStruct(g->structure))
  {
    LLVMTypeRef elements[2];
    elements[0] = LLVMPointerType(g->desc_type, 0);
    elements[1] = g->primitive;
    LLVMStructSetBody(g->structure, elements, 2, false);
  }

  g->structure_ptr = LLVMPointerType(g->structure, 0);
}
コード例 #3
0
ファイル: gentype.c プロジェクト: nunb/ponyc
/**
 * Return true if the type already exists or if we are only being asked to
 * generate a preliminary type, false otherwise.
 */
static bool setup_name(compile_t* c, ast_t* ast, gentype_t* g, bool prelim)
{
  if(ast_id(ast) == TK_NOMINAL)
  {
    ast_t* def = (ast_t*)ast_data(ast);
    g->underlying = ast_id(def);

    // Find the primitive type, if there is one.
    AST_GET_CHILDREN(ast, pkg, id);
    const char* package = ast_name(pkg);
    const char* name = ast_name(id);

    if(package == c->str_builtin)
    {
      if(name == c->str_Bool)
        g->primitive = c->i1;
      else if(name == c->str_I8)
        g->primitive = c->i8;
      else if(name == c->str_U8)
        g->primitive = c->i8;
      else if(name == c->str_I16)
        g->primitive = c->i16;
      else if(name == c->str_U16)
        g->primitive = c->i16;
      else if(name == c->str_I32)
        g->primitive = c->i32;
      else if(name == c->str_U32)
        g->primitive = c->i32;
      else if(name == c->str_I64)
        g->primitive = c->i64;
      else if(name == c->str_U64)
        g->primitive = c->i64;
      else if(name == c->str_I128)
        g->primitive = c->i128;
      else if(name == c->str_U128)
        g->primitive = c->i128;
#if defined(PLATFORM_IS_ILP32)
      else if(name == c->str_ILong)
        g->primitive = c->i32;
      else if(name == c->str_ULong)
        g->primitive = c->i32;
      else if(name == c->str_ISize)
        g->primitive = c->i32;
      else if(name == c->str_USize)
        g->primitive = c->i32;
#elif defined(PLATFORM_IS_LP64)
      else if(name == c->str_ILong)
        g->primitive = c->i64;
      else if(name == c->str_ULong)
        g->primitive = c->i64;
      else if(name == c->str_ISize)
        g->primitive = c->i64;
      else if(name == c->str_USize)
        g->primitive = c->i64;
#elif defined(PLATFORM_IS_LLP64)
      else if(name == c->str_ILong)
        g->primitive = c->i32;
      else if(name == c->str_ULong)
        g->primitive = c->i32;
      else if(name == c->str_ISize)
        g->primitive = c->i64;
      else if(name == c->str_USize)
        g->primitive = c->i64;
#endif
      else if(name == c->str_F32)
        g->primitive = c->f32;
      else if(name == c->str_F64)
        g->primitive = c->f64;
      else if(name == c->str_Pointer)
        return genprim_pointer(c, g, prelim);
      else if(name == c->str_Maybe)
        return genprim_maybe(c, g, prelim);
      else if(name == c->str_Platform)
        return true;
    }
  } else {
    g->underlying = TK_TUPLETYPE;
  }

  // Find or create the structure type.
  g->structure = LLVMGetTypeByName(c->module, g->type_name);

  if(g->structure == NULL)
    g->structure = LLVMStructCreateNamed(c->context, g->type_name);

  bool opaque = LLVMIsOpaqueStruct(g->structure) != 0;

  if(g->underlying == TK_TUPLETYPE)
  {
    // This is actually our primitive type.
    g->primitive = g->structure;
    g->structure = NULL;
  } else {
    g->structure_ptr = LLVMPointerType(g->structure, 0);
  }

  // Fill in our global descriptor.
  make_global_descriptor(c, g);

  if(g->primitive != NULL)
  {
    // We're primitive, so use the primitive type.
    g->use_type = g->primitive;
  } else {
    // We're not primitive, so use a pointer to our structure.
    g->use_type = g->structure_ptr;
  }

  if(!opaque)
  {
    // Fill in our global instance if the type is not opaque.
    make_global_instance(c, g);

    // Fill in a box type if we need one.
    make_box_type(c, g);

    return true;
  }

  return prelim;
}
コード例 #4
0
ファイル: gentype.c プロジェクト: nunb/ponyc
static bool make_struct(compile_t* c, gentype_t* g)
{
  LLVMTypeRef type;
  int extra = 0;

  if(g->underlying != TK_TUPLETYPE)
  {
    type = g->structure;

    if(g->underlying != TK_STRUCT)
      extra++;
  } else {
    type = g->primitive;
  }

  if(g->underlying == TK_ACTOR)
    extra++;

  size_t buf_size = (g->field_count + extra) * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size);

  // Create the type descriptor as element 0.
  if(extra > 0)
    elements[0] = LLVMPointerType(g->desc_type, 0);

  // Create the actor pad as element 1.
  if(g->underlying == TK_ACTOR)
    elements[1] = c->actor_pad;

  // Get a preliminary type for each field and set the struct body. This is
  // needed in case a struct for the type being generated here is required when
  // generating a field.
  for(int i = 0; i < g->field_count; i++)
  {
    gentype_t field_g;
    bool ok;

    if((g->field_keys != NULL) && (g->field_keys[i] == TK_EMBED))
    {
      ok = gentype(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.structure;
    } else {
      ok = gentype_prelim(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.use_type;
    }

    if(!ok)
    {
      pool_free_size(buf_size, elements);
      return false;
    }
  }

  // An embedded field may have caused the current type to be fully generated
  // at this point. If so, finish gracefully.
  if(!LLVMIsOpaqueStruct(type))
  {
    g->done = true;
    return true;
  }

  LLVMStructSetBody(type, elements, g->field_count + extra, false);

  // Create a box type for tuples.
  if(g->underlying == TK_TUPLETYPE)
    make_box_type(c, g);

  pool_free_size(buf_size, elements);
  return true;
}