Exemple #1
0
int subtype_kind_overlap(reach_type_t* left, reach_type_t* right)
{
  int subtypes = SUBTYPE_KIND_NONE;

  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub_left;

  while((sub_left = reach_type_cache_next(&left->subtypes, &i)) != NULL)
  {
    if(!sub_left->can_be_boxed)
    {
      subtypes |= SUBTYPE_KIND_UNBOXED;
      if(subtypes == SUBTYPE_KIND_ALL)
        return subtypes;

      continue;
    }

    if(sub_left->underlying != TK_TUPLETYPE)
    {
      reach_type_t k;
      k.name = sub_left->name;
      size_t j = HASHMAP_UNKNOWN;
      reach_type_t* sub_right = reach_type_cache_get(&right->subtypes, &k, &j);

      if(sub_right != NULL)
      {
        pony_assert(sub_left == sub_right);

        if(sub_left->underlying == TK_PRIMITIVE)
          subtypes |= SUBTYPE_KIND_NUMERIC;

        if(subtypes == SUBTYPE_KIND_ALL)
          return subtypes;
      }
    } else if((subtypes & SUBTYPE_KIND_TUPLE) == 0) {
      size_t cardinality = ast_childcount(sub_left->ast_cap);
      size_t j = HASHMAP_UNKNOWN;
      reach_type_t* sub_right;

      while((sub_right = reach_type_cache_next(&right->subtypes, &j)) != NULL)
      {
        if((sub_right->underlying == TK_TUPLETYPE) &&
          (ast_childcount(sub_right->ast_cap) == cardinality))
        {
          subtypes |= SUBTYPE_KIND_TUPLE;

          if(subtypes == SUBTYPE_KIND_ALL)
            return subtypes;

          break;
        }
      }
    }
  }

  return subtypes;
}
Exemple #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);
    }
  }
}
Exemple #3
0
int subtype_kind(reach_type_t* type)
{
  int subtypes = SUBTYPE_KIND_NONE;

  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub;

  while((sub = reach_type_cache_next(&type->subtypes, &i)) != NULL)
  {
    if(sub->can_be_boxed)
    {
      if(type->underlying == TK_PRIMITIVE)
        subtypes |= SUBTYPE_KIND_NUMERIC;
      else
        subtypes |= SUBTYPE_KIND_TUPLE;
    } else {
      subtypes |= SUBTYPE_KIND_UNBOXED;
    }

    if(subtypes == SUBTYPE_KIND_ALL)
      return subtypes;
  }

  return subtypes;
}
Exemple #4
0
static void set_method_external_interface(reach_type_t* t, const char* name,
  uint32_t vtable_index)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub;

  while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL)
  {
    reach_method_name_t* n = reach_method_name(sub, name);

    if(n == NULL)
      continue;

    size_t j = HASHMAP_BEGIN;
    reach_method_t* m;

    while((m = reach_mangled_next(&n->r_mangled, &j)) != NULL)
    {
      if(m->vtable_index == vtable_index)
      {
        compile_method_t* c_m = (compile_method_t*)m->c_method;
        LLVMSetFunctionCallConv(c_m->func, LLVMCCallConv);
        LLVMSetLinkage(c_m->func, LLVMExternalLinkage);
        break;
      }
    }
  }
}
Exemple #5
0
static void add_rmethod_to_subtypes(reach_t* r, reach_type_t* t,
  reach_method_name_t* n, reach_method_t* m, pass_opt_t* opt)
{
  switch(ast_id(t->ast))
  {
    case TK_NOMINAL:
    {
      ast_t* def = (ast_t*)ast_data(t->ast);

      switch(ast_id(def))
      {
        case TK_INTERFACE:
        case TK_TRAIT:
        {
          // Add to subtypes if we're an interface or trait.
          size_t i = HASHMAP_BEGIN;
          reach_type_t* t2;

          while((t2 = reach_type_cache_next(&t->subtypes, &i)) != NULL)
            add_rmethod_to_subtype(r, t2, n, m, opt);

          break;
        }

        default: {}
      }
      return;
    }

    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      ast_t* child = ast_child(t->ast);

      while(child != NULL)
      {
        ast_t* find = lookup_try(NULL, NULL, child, n->name);

        if(find != NULL)
        {
          reach_type_t* t2 = add_type(r, child, opt);
          add_rmethod_to_subtype(r, t2, n, m, opt);
          ast_free_unattached(find);
        }

        child = ast_sibling(child);
      }
      return;
    }

    default: {}
  }

  assert(0);
}
Exemple #6
0
static int boxed_subtypes_overlap(reach_t* reach, ast_t* left_type,
  ast_t* right_type)
{
  reach_type_t* r_left = reach_type(reach, left_type);
  reach_type_t* r_right = reach_type(reach, right_type);

  int subtypes = BOXED_SUBTYPES_NONE;

  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub_left;

  while((sub_left = reach_type_cache_next(&r_left->subtypes, &i)) != NULL)
  {
    if(!sub_left->can_be_boxed)
    {
      subtypes |= BOXED_SUBTYPES_UNBOXED;
      if(subtypes == BOXED_SUBTYPES_ALL)
        return subtypes;

      continue;
    }

    size_t j = HASHMAP_BEGIN;
    reach_type_t* sub_right;

    while((sub_right = reach_type_cache_next(&r_right->subtypes, &j)) != NULL)
    {
      if(sub_left == sub_right)
      {
        if(sub_left->underlying == TK_PRIMITIVE)
          subtypes |= BOXED_SUBTYPES_NUMERIC;
        else
          subtypes |= BOXED_SUBTYPES_TUPLE;

        if(subtypes == BOXED_SUBTYPES_ALL)
          return subtypes;
      }
    }
  }

  return subtypes;
}
Exemple #7
0
static uint32_t trait_count(reach_type_t* t, uint32_t** list,
  size_t* list_size)
{
  switch(t->underlying)
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
    {
      uint32_t count = (uint32_t)reach_type_cache_size(&t->subtypes);

      if(count == 0)
        return 0;

      // Sort the trait identifiers.
      size_t tid_size = count * sizeof(uint32_t);
      uint32_t* tid = (uint32_t*)ponyint_pool_alloc_size(tid_size);

      size_t i = HASHMAP_BEGIN;
      size_t index = 0;
      reach_type_t* provide;

      while((provide = reach_type_cache_next(&t->subtypes, &i)) != NULL)
        tid[index++] = provide->type_id;

      qsort(tid, index, sizeof(uint32_t), cmp_uint32);
      count = (uint32_t)unique_uint32(tid, index);

      if(list != NULL)
      {
        *list = tid;
        *list_size = tid_size;
      } else {
        ponyint_pool_free_size(tid_size, tid);
      }

      return count;
    }

    default: {}
  }

  return 0;
}
Exemple #8
0
static void set_method_external_interface(reach_type_t* t, const char* name)
{
  set_method_external_nominal(t, name);

  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub;
  while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL)
  {
    reach_method_name_t* n = reach_method_name(sub, name);
    if(n == NULL)
      continue;
    size_t j = HASHMAP_BEGIN;
    reach_method_t* m;
    while((m = reach_methods_next(&n->r_methods, &j)) != NULL)
    {
      LLVMSetFunctionCallConv(m->func, LLVMCCallConv);
      LLVMSetLinkage(m->func, LLVMExternalLinkage);
    }
  }
}
Exemple #9
0
static bool can_inline_message_send(reach_type_t* t, reach_method_t* m,
  const char* method_name)
{
  switch(t->underlying)
  {
    case TK_CLASS:
    case TK_STRUCT:
    case TK_PRIMITIVE:
      return false;

    case TK_ACTOR:
      return true;

    default: {}
  }

  size_t i = HASHMAP_BEGIN;
  reach_type_t* sub;
  while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL)
  {
    reach_method_t* m_sub = reach_method(sub, m->cap, method_name, m->typeargs);

    if(m_sub == NULL)
      continue;

    switch(sub->underlying)
    {
      case TK_CLASS:
      case TK_PRIMITIVE:
        return false;

      case TK_ACTOR:
        if(ast_id(m_sub->r_fun) == TK_FUN)
          return false;
        break;

      default: {}
    }

    pony_assert(m->param_count == m_sub->param_count);
    for(size_t i = 0; i < m->param_count; i++)
    {
      // If the param is a boxable type for us and an unboxable type for one of
      // our subtypes, that subtype will take that param as boxed through an
      // interface. In order to correctly box the value the actual function to
      // call must be resolved through name mangling, therefore we can't inline
      // the message send.
      reach_type_t* param = m->params[i].type;
      reach_type_t* sub_param = m_sub->params[i].type;
      if(param->can_be_boxed)
      {
        if(!sub_param->can_be_boxed)
          return false;

        if(param->underlying == TK_TUPLETYPE)
        {
          ast_t* child = ast_child(param->ast);
          while(child != NULL)
          {
            if(contains_boxable(child))
              return false;
          }
        }
      }
    }
  }

  return true;
}