Beispiel #1
1
void gendesc_table(compile_t* c)
{
  uint32_t len = c->reach->next_type_id;
  size_t size = len * sizeof(LLVMValueRef);
  LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size);

  reach_type_t* t;
  size_t i = HASHMAP_BEGIN;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    LLVMValueRef desc;

    if(t->desc != NULL)
      desc = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr, "");
    else
      desc = LLVMConstNull(c->descriptor_ptr);

    args[t->type_id] = desc;
  }

  LLVMTypeRef type = LLVMArrayType(c->descriptor_ptr, len);
  LLVMValueRef table = LLVMAddGlobal(c->module, type, "__DescTable");
  LLVMValueRef value = LLVMConstArray(c->descriptor_ptr, args, len);
  LLVMSetInitializer(table, value);
  LLVMSetGlobalConstant(table, true);

  LLVMValueRef table_size = LLVMAddGlobal(c->module, c->intptr,
    "__DescTableSize");
  LLVMSetInitializer(table_size, LLVMConstInt(c->intptr, len, false));
  LLVMSetGlobalConstant(table_size, true);

  ponyint_pool_free_size(size, args);
}
Beispiel #2
0
void reach_dump(reach_t* r)
{
  printf("REACH\n");

  size_t i = HASHMAP_BEGIN;
  reach_type_t* t;

  while((t = reach_types_next(&r->types, &i)) != NULL)
  {
    printf("  %d: %s, %s\n", t->type_id, t->name, t->mangle);
    size_t j = HASHMAP_BEGIN;
    reach_method_name_t* n;

    printf("    size: " __zu "\n", t->abi_size);
    printf("    vtable: %d\n", t->vtable_size);

    while((n = reach_method_names_next(&t->methods, &j)) != NULL)
    {
      size_t k = HASHMAP_BEGIN;
      reach_method_t* m;

      while((m = reach_mangled_next(&n->r_mangled, &k)) != NULL)
        printf("      %d: %s\n", m->vtable_index, m->mangled_name);
    }

    j = HASHMAP_BEGIN;
    reach_type_t* t2;

    while((t2 = reach_type_cache_next(&t->subtypes, &j)) != NULL)
    {
      printf("    %s\n", t2->name);
    }
  }
}
Beispiel #3
0
static void add_traits_to_type(reach_t* r, reach_type_t* t,
  pass_opt_t* opt)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t2;

  while((t2 = reach_types_next(&r->types, &i)) != NULL)
  {
    if(ast_id(t2->ast) != TK_NOMINAL)
      continue;

    ast_t* def = (ast_t*)ast_data(t2->ast);

    switch(ast_id(def))
    {
      case TK_INTERFACE:
      case TK_TRAIT:
        if(is_subtype(t->ast, t2->ast, NULL, opt))
        {
          reach_type_cache_put(&t->subtypes, t2);
          reach_type_cache_put(&t2->subtypes, t);
          add_methods_to_type(r, t2, t, opt);
        }
        break;

      default: {}
    }
  }
}
Beispiel #4
0
static void print_types(compile_t* c, FILE* fp, printbuf_t* buf)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    // Print the docstring if we have one.
    ast_t* def = (ast_t*)ast_data(t->ast);

    if (def != NULL)
    {
      ast_t* docstring = ast_childidx(def, 6);

      if(ast_id(docstring) == TK_STRING)
        fprintf(fp, "/*\n%s*/\n", ast_name(docstring));
    }

    if(!is_pointer(t->ast) && !is_maybe(t->ast) && !is_machine_word(t->ast))
    {
      // Forward declare an opaque type.
      fprintf(fp, "typedef struct %s %s;\n\n", t->name, t->name);

      // Function signature for the allocator.
      printbuf(buf,
        "/* Allocate a %s without initialising it. */\n%s* %s_Alloc();\n\n",
        t->name,
        t->name,
        t->name
        );
    }

    print_methods(c, t, buf);
  }
}
Beispiel #5
0
LLVMValueRef gen_numeric_size_table(compile_t* c)
{
  uint32_t len = c->reach->numeric_type_count;
  if(len == 0)
    return NULL;

  size_t size = len * sizeof(LLVMValueRef);
  LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size);

  uint32_t count = 0;
  reach_type_t* t;
  size_t i = HASHMAP_BEGIN;

  while(count < len)
  {
    t = reach_types_next(&c->reach->types, &i);
    pony_assert(t != NULL);

    if(t->is_trait || (t->underlying == TK_STRUCT))
      continue;

    uint32_t type_id = t->type_id;
    if((type_id % 4) == 0)
    {
      size_t type_size = (size_t)LLVMABISizeOfType(c->target_data, t->use_type);
      args[type_id >> 2] = LLVMConstInt(c->i32, type_size, false);
      count++;
    }
  }
Beispiel #6
0
static bool need_primitive_call(compile_t* c, const char* method)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(t->underlying != TK_PRIMITIVE)
      continue;

    reach_method_name_t* n = reach_method_name(t, method);

    if(n == NULL)
      continue;

    return true;
  }

  return false;
}
Beispiel #7
0
static void add_types_to_trait(reach_t* r, reach_type_t* t,
  pass_opt_t* opt)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t2;

  ast_t* def = (ast_t*)ast_data(t->ast);
  bool interface = ast_id(def) == TK_INTERFACE;

  while((t2 = reach_types_next(&r->types, &i)) != NULL)
  {
    if(ast_id(t2->ast) != TK_NOMINAL)
      continue;

    ast_t* def2 = (ast_t*)ast_data(t2->ast);

    switch(ast_id(def2))
    {
      case TK_INTERFACE:
      {
        // Use the same typeid.
        if(interface && is_eqtype(t->ast, t2->ast, NULL, opt))
          t->type_id = t2->type_id;
        break;
      }

      case TK_PRIMITIVE:
      case TK_CLASS:
      case TK_ACTOR:
        if(is_subtype(t2->ast, t->ast, NULL, opt))
        {
          reach_type_cache_put(&t->subtypes, t2);
          reach_type_cache_put(&t2->subtypes, t);
          add_methods_to_type(r, t, t2, opt);
        }
        break;

      default: {}
    }
  }
}
Beispiel #8
0
static void primitive_call(compile_t* c, const char* method)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t;

  while((t = reach_types_next(&c->reach->types, &i)) != NULL)
  {
    if(t->underlying != TK_PRIMITIVE)
      continue;

    reach_method_t* m = reach_method(t, TK_NONE, method, NULL);

    if(m == NULL)
      continue;

    LLVMValueRef value = codegen_call(c, m->func, &t->instance, 1);

    if(c->str__final == method)
      LLVMSetInstructionCallConv(value, LLVMCCallConv);
  }
}
Beispiel #9
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;
}