Beispiel #1
0
static void add_method(reachable_method_stack_t** s,
  reachable_type_t* t, const char* name, ast_t* typeargs)
{
  reachable_method_name_t* n = reach_method_name(t, name);

  if(n == NULL)
  {
    n = POOL_ALLOC(reachable_method_name_t);
    n->name = name;
    reachable_methods_init(&n->r_methods, 0);
    reachable_method_names_put(&t->methods, n);
  }

  add_rmethod(s, t, n, typeargs);

  // Add to subtypes if we're an interface or trait.
  ast_t* def = (ast_t*)ast_data(t->type);

  switch(ast_id(def))
  {
    case TK_INTERFACE:
    case TK_TRAIT:
    {
      size_t i = HASHMAP_BEGIN;
      reachable_type_t* t2;

      while((t2 = reachable_type_cache_next(&t->subtypes, &i)) != NULL)
        add_method(s, t2, name, typeargs);

      break;
    }

    default: {}
  }
}
Beispiel #2
0
reach_method_t* reach_method(reach_type_t* t, token_id cap,
  const char* name, ast_t* typeargs)
{
  reach_method_name_t* n = reach_method_name(t, name);

  if(n == NULL)
    return NULL;

  if((n->id == TK_FUN) && ((n->cap == TK_BOX) || (n->cap == TK_TAG)))
  {
    switch(cap)
    {
      case TK_ISO:
      case TK_TRN:
        cap = TK_REF;
        break;

      case TK_REF:
      case TK_VAL:
      case TK_BOX:
        break;

      default:
        cap = n->cap;
    }
  } else {
    cap = n->cap;
  }

  name = genname_fun(cap, n->name, typeargs);
  return reach_rmethod(n, name);
}
Beispiel #3
0
static bool need_primitive_call(compile_t* c, const char* method)
{
  size_t i = HASHMAP_BEGIN;
  reachable_type_t* t;

  while((t = reachable_types_next(c->reachable, &i)) != NULL)
  {
    if(ast_id(t->type) == TK_TUPLETYPE)
      continue;

    ast_t* def = (ast_t*)ast_data(t->type);

    if(ast_id(def) != TK_PRIMITIVE)
      continue;

    reachable_method_name_t* n = reach_method_name(t, method);

    if(n == NULL)
      continue;

    return true;
  }

  return false;
}
Beispiel #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;
      }
    }
  }
}
Beispiel #5
0
reachable_method_t* reach_method(reachable_type_t* t, const char* name,
  ast_t* typeargs)
{
  reachable_method_name_t* n = reach_method_name(t, name);

  if(n == NULL)
    return NULL;

  return reach_method_instance(n, typeargs);
}
Beispiel #6
0
static void set_method_external_nominal(reach_type_t* t, const char* name)
{
  reach_method_name_t* n = reach_method_name(t, name);
  if(n != NULL)
  {
    size_t i = HASHMAP_BEGIN;
    reach_method_t* m;
    while((m = reach_methods_next(&n->r_methods, &i)) != NULL)
    {
      LLVMSetFunctionCallConv(m->func, LLVMCCallConv);
      LLVMSetLinkage(m->func, LLVMExternalLinkage);
    }
  }
}
Beispiel #7
0
static void primitive_call(compile_t* c, const char* method, LLVMValueRef arg)
{
  size_t count = 1;

  if(arg != NULL)
    count++;

  size_t i = HASHMAP_BEGIN;
  reachable_type_t* t;

  while((t = reachable_types_next(c->reachable, &i)) != NULL)
  {
    if(ast_id(t->type) == TK_TUPLETYPE)
      continue;

    ast_t* def = (ast_t*)ast_data(t->type);

    if(ast_id(def) != TK_PRIMITIVE)
      continue;

    reachable_method_name_t* n = reach_method_name(t, method);

    if(n == NULL)
      continue;

    gentype_t g;

    if(!gentype(c, t->type, &g))
    {
      assert(0);
      return;
    }

    LLVMValueRef fun = genfun_proto(c, &g, method, NULL);
    assert(fun != NULL);

    LLVMValueRef args[2];
    args[0] = g.instance;
    args[1] = arg;

    codegen_call(c, fun, args, count);
  }
}
Beispiel #8
0
static reach_method_name_t* add_method_name(reach_type_t* t, const char* name)
{
  reach_method_name_t* n = reach_method_name(t, name);

  if(n == NULL)
  {
    n = POOL_ALLOC(reach_method_name_t);
    n->name = name;
    reach_methods_init(&n->r_methods, 0);
    reach_mangled_init(&n->r_mangled, 0);
    reach_method_names_put(&t->methods, n);

    ast_t* fun = lookup(NULL, NULL, t->ast, name);
    n->id = ast_id(fun);
    n->cap = ast_id(ast_child(fun));
    ast_free_unattached(fun);
  }

  return n;
}
Beispiel #9
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);
    }
  }
}
Beispiel #10
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 #11
0
static uint32_t vtable_index(compile_t* c, const char* type_name,
  const char* name, ast_t* typeargs)
{
  reachable_type_t* t = reach_type(c->reachable, type_name);

  if(t == NULL)
    return -1;

  reachable_method_name_t* n = reach_method_name(t, name);

  if(n == NULL)
    return -1;

  if(typeargs != NULL)
    name = genname_fun(NULL, name, typeargs);

  reachable_method_t* m = reach_method(n, name);

  if(m == NULL)
    return -1;

  assert(m->vtable_index != (uint32_t)-1);
  return m->vtable_index;
}