Exemple #1
0
/**
 * 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;
}
Exemple #2
0
bool gentypes(compile_t* c)
{
  reach_type_t* t;
  size_t i;

  genprim_builtins(c);

  if(c->opt->verbosity >= VERBOSITY_INFO)
    fprintf(stderr, " Data prototypes\n");

  i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(!make_opaque_struct(c, t))
      return false;

    gendesc_type(c, t);
    make_debug_info(c, t);
    make_box_type(c, t);
    make_dispatch(c, t);
    gentrace_prototype(c, t);
  }

  gendesc_table(c);

  if(c->opt->verbosity >= VERBOSITY_INFO)
    fprintf(stderr, " Data types\n");

  i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(!make_struct(c, t))
      return false;

    make_global_instance(c, t);
  }

  if(c->opt->verbosity >= VERBOSITY_INFO)
    fprintf(stderr, " Function prototypes\n");

  i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    // The ABI size for machine words and tuples is the boxed size.
    if(t->structure != NULL)
      t->abi_size = (size_t)LLVMABISizeOfType(c->target_data, t->structure);

    make_debug_final(c, t);
    make_pointer_methods(c, t);

    if(!genfun_method_sigs(c, t))
      return false;
  }

  if(c->opt->verbosity >= VERBOSITY_INFO)
    fprintf(stderr, " Functions\n");

  i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(!genfun_method_bodies(c, t))
      return false;
  }

  if(c->opt->verbosity >= VERBOSITY_INFO)
    fprintf(stderr, " Descriptors\n");

  i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(!make_trace(c, t))
      return false;

    if(!genserialise(c, t))
      return false;

    gendesc_init(c, t);
  }

  return true;
}
Exemple #3
0
static bool make_nominal(compile_t* c, ast_t* ast, gentype_t* g, bool prelim)
{
  assert(ast_id(ast) == TK_NOMINAL);
  ast_t* def = (ast_t*)ast_data(ast);
  token_id id = ast_id(def);

  // For traits, just return a raw object pointer.
  switch(id)
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      g->underlying = id;
      g->use_type = c->object_ptr;
      dwarf_trait(&c->dwarf, g);
      return true;

    default: {}
  }

  // If we already exist or we're preliminary, we're done.
  if(setup_name(c, ast, g, prelim))
    return true;

  if(g->primitive == NULL)
  {
    // Not a primitive type. Generate all the fields and a trace function.
    setup_type_fields(g);

    // Forward declare debug symbols for this nominal, if needed.
    // At this point, this can only be TK_STRUCT, TK_CLASS, TK_PRIMITIVE, or
    // TK_ACTOR ast nodes. TK_TYPE has been translated to any of the former
    // during reification.
    dwarf_forward(&c->dwarf, g);

    bool ok = make_struct(c, g);

    if(!g->done)
      ok = ok && make_trace(c, g) && make_components(c, g);

    if(!ok)
    {
      free_fields(g);
      return false;
    }

    // Finalise symbols for composite type.
    if(!g->done)
      dwarf_composite(&c->dwarf, g);
  } else {
    // Emit debug symbols for a basic type (U8, U16, U32...)
    dwarf_basic(&c->dwarf, g);

    // Create a box type.
    make_box_type(c, g);
  }

  if(!g->done)
  {
    // Generate a dispatch function if necessary.
    make_dispatch(c, g);

    // Create a unique global instance if we need one.
    make_global_instance(c, g);

    // Generate all the methods.
    if(!genfun_methods(c, g))
    {
      free_fields(g);
      return false;
    }

    if(g->underlying != TK_STRUCT)
      gendesc_init(c, g);

    // Finish off the dispatch function.
    if(g->underlying == TK_ACTOR)
    {
      codegen_startfun(c, g->dispatch_fn, false);
      codegen_finishfun(c);
    }

    // Finish the dwarf frame.
    dwarf_finish(&c->dwarf);
  }

  free_fields(g);
  g->done = true;
  return true;
}
Exemple #4
0
bool gentypes(compile_t* c)
{
  reachable_type_t* t;
  size_t i;

  genprim_builtins(c);

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Data prototypes\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_opaque_struct(c, t))
      return false;

    gendesc_type(c, t);
    make_debug_info(c, t);
    make_box_type(c, t);
    make_dispatch(c, t);
    gentrace_prototype(c, t);
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Data types\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_struct(c, t))
      return false;

    make_global_instance(c, t);
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Function prototypes\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    make_debug_final(c, t);
    make_pointer_methods(c, t);

    if(!genfun_method_sigs(c, t))
      return false;
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Functions\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!genfun_method_bodies(c, t))
      return false;
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Descriptors\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_trace(c, t))
      return false;

    gendesc_init(c, t);
  }

  return true;
}