Esempio n. 1
0
static void genfun_dwarf(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs, ast_t* fun)
{
  if(!codegen_hassource(c))
    return;

  // Get the function.
  const char* funname = genname_fun(g->type_name, name, typeargs);
  LLVMValueRef func = LLVMGetNamedFunction(c->module, funname);
  assert(func != NULL);

  // Count the parameters, including the receiver.
  ast_t* params = ast_childidx(fun, 3);
  size_t count = ast_childcount(params) + 1;

  size_t buf_size = (count + 1) * sizeof(const char*);
  const char** pnames = (const char**)pool_alloc_size(buf_size);
  count = 0;

  // Return value type name and receiver type name.
  pnames[count++] = genname_type(ast_childidx(fun, 4));
  pnames[count++] = g->type_name;

  // Get a type name for each parameter.
  ast_t* param = ast_child(params);

  while(param != NULL)
  {
    ast_t* ptype = ast_childidx(param, 1);
    pnames[count++] = genname_type(ptype);
    param = ast_sibling(param);
  }

  // Dwarf the method type
  dwarf_method(&c->dwarf, fun, name, funname, pnames, count, func);

  // Dwarf the receiver pointer.
  LLVMBasicBlockRef entry = LLVMGetEntryBasicBlock(codegen_fun(c));
  LLVMValueRef argument = codegen_getlocal(c, stringtab("this"));

  dwarf_this(&c->dwarf, fun, g->type_name, entry, argument);

  // Dwarf locals for parameters
  param = ast_child(params);
  size_t index = 1;

  while(param != NULL)
  {
    argument = codegen_getlocal(c, ast_name(ast_child(param)));
    dwarf_parameter(&c->dwarf, param, pnames[index + 1], entry, argument,
      index);
    param = ast_sibling(param);
    index++;
  }

  pool_free_size(buf_size, pnames);
}
Esempio n. 2
0
File: gentype.c Progetto: nunb/ponyc
bool gentype(compile_t* c, ast_t* ast, gentype_t* g)
{
  memset(g, 0, sizeof(gentype_t));

  if(ast == NULL)
    return false;

  if(contains_dontcare(ast))
    return true;

  g->ast = ast;
  g->type_name = genname_type(ast);
  g->desc_name = genname_descriptor(g->type_name);

  switch(ast_id(ast))
  {
    case TK_NOMINAL:
      return make_nominal(c, ast, g, false);

    case TK_TUPLETYPE:
      return make_tuple(c, ast, g);

    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
      // Just a raw object pointer.
      g->underlying = ast_id(ast);
      g->use_type = c->object_ptr;
      return true;

    default: {}
  }

  assert(0);
  return false;
}
Esempio n. 3
0
File: gentype.c Progetto: nunb/ponyc
static bool trace_fields(compile_t* c, gentype_t* g, LLVMValueRef ctx,
  LLVMValueRef object, int extra)
{
  bool need_trace = false;

  for(int i = 0; i < g->field_count; i++)
  {
    LLVMValueRef field = LLVMBuildStructGEP(c->builder, object, i + extra, "");

    if(g->field_keys[i] != TK_EMBED)
    {
      // Call the trace function indirectly depending on rcaps.
      LLVMValueRef value = LLVMBuildLoad(c->builder, field, "");
      need_trace |= gentrace(c, ctx, value, g->fields[i]);
    } else {
      // Call the trace function directly without marking the field.
      const char* fun = genname_trace(genname_type(g->fields[i]));
      LLVMValueRef trace_fn = LLVMGetNamedFunction(c->module, fun);

      if(trace_fn != NULL)
      {
        LLVMValueRef args[2];
        args[0] = ctx;
        args[1] = LLVMBuildBitCast(c->builder, field, c->object_ptr, "");

        LLVMBuildCall(c->builder, trace_fn, args, 2, "");
        need_trace = true;
      }
    }
  }

  return need_trace;
}
Esempio n. 4
0
File: genfun.c Progetto: fydot/ponyc
uint32_t genfun_vtable_index(compile_t* c, gentype_t* g, const char* name,
  ast_t* typeargs)
{
  switch(ast_id(g->ast))
  {
    case TK_NOMINAL:
      return vtable_index(c, g->type_name, name, typeargs);

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

      while(child != NULL)
      {
        const char* type_name = genname_type(child);
        uint32_t index = vtable_index(c, type_name, name, typeargs);

        if(index != (uint32_t)-1)
          return index;

        child = ast_sibling(child);
      }

      return -1;
    }

    default: {}
  }

  return -1;
}
Esempio n. 5
0
File: reach.c Progetto: DevL/ponyc
static reachable_type_t* add_tuple(reachable_method_stack_t** s,
  reachable_types_t* r, uint32_t* next_type_id, ast_t* type)
{
  if(contains_dontcare(type))
    return NULL;

  const char* type_name = genname_type(type);
  reachable_type_t* t = reach_type(r, type_name);

  if(t != NULL)
    return t;

  t = add_reachable_type(r, type, type_name);
  t->type_id = ++(*next_type_id);

  ast_t* child = ast_child(type);

  while(child != NULL)
  {
    add_type(s, r, next_type_id, child);
    child = ast_sibling(child);
  }

  return t;
}
Esempio n. 6
0
File: reach.c Progetto: DevL/ponyc
static reachable_type_t* add_nominal(reachable_method_stack_t** s,
  reachable_types_t* r, uint32_t* next_type_id, ast_t* type)
{
  const char* type_name = genname_type(type);
  reachable_type_t* t = reach_type(r, type_name);

  if(t != NULL)
    return t;

  t = add_reachable_type(r, type, type_name);

  AST_GET_CHILDREN(type, pkg, id, typeparams);
  ast_t* typeparam = ast_child(typeparams);

  while(typeparam != NULL)
  {
    add_type(s, r, next_type_id, typeparam);
    typeparam = ast_sibling(typeparam);
  }

  ast_t* def = (ast_t*)ast_data(type);

  switch(ast_id(def))
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      add_types_to_trait(s, r, t);
      break;

    case TK_PRIMITIVE:
      add_traits_to_type(s, r, t);
      add_special(s, t, type, "_init");
      add_special(s, t, type, "_final");
      break;

    case TK_STRUCT:
    case TK_CLASS:
      add_traits_to_type(s, r, t);
      add_special(s, t, type, "_final");
      add_fields(s, r, next_type_id, type);
      break;

    case TK_ACTOR:
      add_traits_to_type(s, r, t);
      add_special(s, t, type, "_event_notify");
      add_special(s, t, type, "_final");
      add_fields(s, r, next_type_id, type);
      break;

    default: {}
  }

  if(t->type_id == 0)
    t->type_id = ++(*next_type_id);

  return t;
}
Esempio n. 7
0
LLVMValueRef gendesc_istrait(compile_t* c, LLVMValueRef desc, ast_t* type)
{
  // Get the trait identifier.
  reachable_type_t* t = reach_type(c->reachable, genname_type(type));
  assert(t != NULL);
  LLVMValueRef trait_id = LLVMConstInt(c->i32, t->type_id, false);

  // Read the count and the trait list from the descriptor.
  LLVMValueRef count = desc_field(c, desc, DESC_TRAIT_COUNT);
  LLVMValueRef list = desc_field(c, desc, DESC_TRAITS);

  LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef cond_block = codegen_block(c, "cond");
  LLVMBasicBlockRef body_block = codegen_block(c, "body");
  LLVMBasicBlockRef post_block = codegen_block(c, "post");
  LLVMBuildBr(c->builder, cond_block);

  // While the index is less than the count, check an ID.
  LLVMPositionBuilderAtEnd(c->builder, cond_block);
  LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i32, "");
  LLVMValueRef zero = LLVMConstInt(c->i32, 0, false);
  LLVMAddIncoming(phi, &zero, &entry_block, 1);

  LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, count, "");
  LLVMBuildCondBr(c->builder, test, body_block, post_block);

  // The phi node is the index. Get ID and compare it.
  LLVMPositionBuilderAtEnd(c->builder, body_block);

  LLVMValueRef gep[2];
  gep[0] = LLVMConstInt(c->i32, 0, false);
  gep[1] = phi;

  LLVMValueRef id_ptr = LLVMBuildGEP(c->builder, list, gep, 2, "");
  LLVMValueRef id = LLVMBuildLoad(c->builder, id_ptr, "");
  LLVMValueRef test_id = LLVMBuildICmp(c->builder, LLVMIntEQ, id, trait_id,
    "");

  // Add one to the phi node.
  LLVMValueRef one = LLVMConstInt(c->i32, 1, false);
  LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, "");
  LLVMAddIncoming(phi, &inc, &body_block, 1);

  // Either to the post block or back to the condition.
  LLVMBuildCondBr(c->builder, test_id, post_block, cond_block);

  LLVMPositionBuilderAtEnd(c->builder, post_block);
  LLVMValueRef result = LLVMBuildPhi(c->builder, c->i1, "");
  LLVMAddIncoming(result, &test, &cond_block, 1);
  LLVMAddIncoming(result, &test_id, &body_block, 1);

  return result;
}
Esempio n. 8
0
static reachable_type_t* add_reachable_type(reachable_types_t* r, ast_t* type)
{
  reachable_type_t* t = POOL_ALLOC(reachable_type_t);
  memset(t, 0, sizeof(reachable_type_t));

  t->name = genname_type(type);
  t->ast = set_cap_and_ephemeral(type, TK_REF, TK_NONE);
  reachable_method_names_init(&t->methods, 0);
  reachable_type_cache_init(&t->subtypes, 0);
  reachable_types_put(r, t);

  return t;
}
Esempio n. 9
0
static void print_base_type(compile_t* c, printbuf_t* buf, ast_t* type)
{
  if(ast_id(type) == TK_NOMINAL)
  {
    const char* name = genname_type(type);
    const char* c_name = c_type_name(c, name);

    if(c_name != NULL)
      printbuf(buf, c_name);
    else
      printbuf(buf, "%s*", name);
  } else {
    printbuf(buf, "void*");
  }
}
Esempio n. 10
0
File: gentype.c Progetto: nunb/ponyc
bool gentype_prelim(compile_t* c, ast_t* ast, gentype_t* g)
{
  if(ast_id(ast) == TK_NOMINAL)
  {
    memset(g, 0, sizeof(gentype_t));

    g->ast = ast;
    g->type_name = genname_type(ast);
    g->desc_name = genname_descriptor(g->type_name);

    return make_nominal(c, ast, g, true);
  }

  return gentype(c, ast, g);
}
Esempio n. 11
0
static void typeargs_append(char* name, ast_t* typeargs, bool function)
{
  if(typeargs == NULL)
    return;

  if(function)
    strcat(name, "_");

  ast_t* typearg = ast_child(typeargs);

  while(typearg != NULL)
  {
    name_append(name, genname_type(typearg));
    typearg = ast_sibling(typearg);
  }
}
Esempio n. 12
0
static size_t typeargs_len(ast_t* typeargs)
{
  if(typeargs == NULL)
    return 0;

  ast_t* typearg = ast_child(typeargs);
  size_t len = 0;

  while(typearg != NULL)
  {
    const char* argname = genname_type(typearg);
    len += strlen(argname) + 1;
    typearg = ast_sibling(typearg);
  }

  return len;
}
Esempio n. 13
0
static bool trace_tuple(compile_t* c, LLVMValueRef ctx, LLVMValueRef value,
  ast_t* type)
{
  // Invoke the trace function directly. Do not trace the address of the tuple.
  const char* type_name = genname_type(type);
  const char* trace_name = genname_tracetuple(type_name);
  LLVMValueRef trace_fn = LLVMGetNamedFunction(c->module, trace_name);

  // There will be no trace function if the tuple doesn't need tracing.
  if(trace_fn == NULL)
    return false;

  LLVMValueRef args[2];
  args[0] = ctx;
  args[1] = value;

  LLVMBuildCall(c->builder, trace_fn, args, 2, "");
  return true;
}
Esempio n. 14
0
reach_type_t* reach_type(reach_t* r, ast_t* type)
{
  reach_type_t k;
  k.name = genname_type(type);
  return reach_types_get(&r->types, &k);
}
Esempio n. 15
0
reachable_type_t* reach_type(reachable_types_t* r, ast_t* type)
{
  reachable_type_t k;
  k.name = genname_type(type);
  return reachable_types_get(r, &k);
}
Esempio n. 16
0
LLVMValueRef gendesc_typeid(compile_t* c, ast_t* type)
{
  return make_type_id(c, genname_type(type));
}