示例#1
0
文件: reach.c 项目: jersey99/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;

  reachable_type_t* t = reach_type(r, type);

  if(t != NULL)
    return t;

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

  t->field_count = (uint32_t)ast_childcount(t->ast);
  t->fields = (reachable_field_t*)calloc(t->field_count,
    sizeof(reachable_field_t));
  size_t index = 0;

  ast_t* child = ast_child(type);

  while(child != NULL)
  {
    t->fields[index].ast = ast_dup(child);
    t->fields[index].type = add_type(s, r, next_type_id, child);;
    index++;

    child = ast_sibling(child);
  }

  return t;
}
示例#2
0
LLVMValueRef gen_string(compile_t* c, ast_t* ast)
{
  ast_t* type = ast_type(ast);
  const char* name = ast_name(ast);
  size_t len = ast_name_len(ast);

  LLVMValueRef args[4];
  args[0] = LLVMConstInt(c->i32, 0, false);
  args[1] = LLVMConstInt(c->i32, 0, false);

  LLVMValueRef str = LLVMConstStringInContext(c->context, name, (int)len,
    false);
  LLVMValueRef g_str = LLVMAddGlobal(c->module, LLVMTypeOf(str), "");
  LLVMSetLinkage(g_str, LLVMPrivateLinkage);
  LLVMSetInitializer(g_str, str);
  LLVMSetGlobalConstant(g_str, true);
  LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2);

  reach_type_t* t = reach_type(c->reach, type);

  args[0] = t->desc;
  args[1] = LLVMConstInt(c->intptr, len, false);
  args[2] = LLVMConstInt(c->intptr, len + 1, false);
  args[3] = str_ptr;

  LLVMValueRef inst = LLVMConstNamedStruct(t->structure, args, 4);
  LLVMValueRef g_inst = LLVMAddGlobal(c->module, t->structure, "");
  LLVMSetInitializer(g_inst, inst);
  LLVMSetGlobalConstant(g_inst, true);
  LLVMSetLinkage(g_inst, LLVMPrivateLinkage);

  return g_inst;
}
示例#3
0
文件: gendesc.c 项目: Andrea/ponyc
void gendesc_init(compile_t* c, gentype_t* g)
{
  // Initialise the global descriptor.
  uint32_t size = (uint32_t)LLVMABISizeOfType(c->target_data, g->structure);

  // Generate a separate type ID for every type.
  LLVMValueRef args[DESC_LENGTH];
  reachable_type_t* t = reach_type(c->reachable, g->type_name);

  args[DESC_ID] = LLVMConstInt(c->i32, t->type_id, false);
  args[DESC_SIZE] = LLVMConstInt(c->i32, size, false);
  args[DESC_TRAIT_COUNT] = make_trait_count(c, g);
  args[DESC_FIELD_COUNT] = make_field_count(c, g);
  args[DESC_TRACE] = make_function_ptr(c, genname_trace(g->type_name),
    c->trace_fn);
  args[DESC_SERIALISE] = make_function_ptr(c, genname_serialise(g->type_name),
    c->trace_fn);
  args[DESC_DESERIALISE] = make_function_ptr(c,
    genname_deserialise(g->type_name), c->trace_fn);
  args[DESC_DISPATCH] = make_function_ptr(c, genname_dispatch(g->type_name),
    c->dispatch_fn);
  args[DESC_FINALISE] = make_function_ptr(c, genname_finalise(g->type_name),
    c->final_fn);
  args[DESC_EVENT_NOTIFY] = LLVMConstInt(c->i32,
    genfun_vtable_index(c, g, stringtab("_event_notify"), NULL), false);
  args[DESC_TRAITS] = make_trait_list(c, g);
  args[DESC_FIELDS] = make_field_list(c, g);
  args[DESC_VTABLE] = make_vtable(c, g);

  LLVMValueRef desc = LLVMConstNamedStruct(g->desc_type, args, DESC_LENGTH);
  LLVMSetInitializer(g->desc, desc);
  LLVMSetGlobalConstant(g->desc, true);
}
示例#4
0
LLVMValueRef gen_float(compile_t* c, ast_t* ast)
{
  ast_t* type = ast_type(ast);
  reach_type_t* t = reach_type(c->reach, type);

  return LLVMConstReal(t->primitive, ast_float(ast));
}
示例#5
0
文件: reach.c 项目: 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;
}
示例#6
0
文件: genprim.c 项目: locksfree/ponyc
static void donotoptimise_apply(compile_t* c, reach_type_t* t,
  reach_method_t* m)
{
  const char* strtab_name = m->name;
  m->intrinsic = true;

  ast_t* typearg = ast_child(m->typeargs);
  reach_type_t* t_elem = reach_type(c->reach, typearg);
  LLVMTypeRef params[2];
  params[0] = t->use_type;
  params[1] = t_elem->use_type;

  start_function(c, m, m->result->use_type, params, 2);

  LLVMValueRef obj = LLVMGetParam(m->func, 1);
  LLVMTypeRef void_fn = LLVMFunctionType(c->void_type, &t_elem->use_type, 1,
    false);
  LLVMValueRef asmstr = LLVMConstInlineAsm(void_fn, "", "imr,~{memory}", true,
    false);
  LLVMBuildCall(c->builder, asmstr, &obj, 1, "");

  LLVMBuildRet(c->builder, m->result->instance);
  codegen_finishfun(c);

  BOX_FUNCTION();
}
示例#7
0
文件: gendesc.c 项目: Andrea/ponyc
static LLVMValueRef make_vtable(compile_t* c, gentype_t* g)
{
  uint32_t vtable_size = genfun_vtable_size(c, g);

  if(vtable_size == 0)
    return LLVMConstArray(c->void_ptr, NULL, 0);

  size_t buf_size = vtable_size * sizeof(LLVMValueRef);
  LLVMValueRef* vtable = (LLVMValueRef*)pool_alloc_size(buf_size);
  memset(vtable, 0, buf_size);

  reachable_type_t* t = reach_type(c->reachable, g->type_name);

  size_t i = HASHMAP_BEGIN;
  reachable_method_name_t* n;

  while((n = reachable_method_names_next(&t->methods, &i)) != NULL)
  {
    size_t j = HASHMAP_BEGIN;
    reachable_method_t* m;

    while((m = reachable_methods_next(&n->r_methods, &j)) != NULL)
    {
      const char* fullname = genname_fun(t->name, n->name, m->typeargs);
      token_id t = ast_id(m->r_fun);

      switch(t)
      {
        case TK_NEW:
        case TK_BE:
          if(g->underlying == TK_ACTOR)
            fullname = genname_be(fullname);
          break;

        default: {}
      }

      uint32_t index = m->vtable_index;
      assert(index != (uint32_t)-1);
      assert(vtable[index] == NULL);

      if(g->primitive != NULL)
        vtable[index] = make_unbox_function(c, g, fullname, t);
      else
        vtable[index] = make_function_ptr(c, fullname, c->void_ptr);
    }
  }

  for(uint32_t i = 0; i < vtable_size; i++)
  {
    if(vtable[i] == NULL)
      vtable[i] = LLVMConstNull(c->void_ptr);
  }

  LLVMValueRef r = LLVMConstArray(c->void_ptr, vtable, vtable_size);
  pool_free_size(buf_size, vtable);
  return r;
}
示例#8
0
文件: reach.c 项目: 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;
}
示例#9
0
LLVMValueRef gen_funptr(compile_t* c, ast_t* ast)
{
  pony_assert((ast_id(ast) == TK_FUNREF) || (ast_id(ast) == TK_BEREF));
  AST_GET_CHILDREN(ast, receiver, method);
  ast_t* typeargs = NULL;

  // Dig through function qualification.
  switch(ast_id(receiver))
  {
    case TK_BEREF:
    case TK_FUNREF:
      typeargs = method;
      AST_GET_CHILDREN_NO_DECL(receiver, receiver, method);
      break;

    default: {}
  }

  // Generate the receiver.
  LLVMValueRef value = gen_expr(c, receiver);

  // Get the receiver type.
  ast_t* type = ast_type(receiver);
  reach_type_t* t = reach_type(c->reach, type);
  pony_assert(t != NULL);

  const char* name = ast_name(method);
  token_id cap = cap_dispatch(type);
  reach_method_t* m = reach_method(t, cap, name, typeargs);
  LLVMValueRef funptr = dispatch_function(c, t, m, value);

  if(c->linkage != LLVMExternalLinkage)
  {
    // We must reset the function linkage and calling convention since we're
    // passing a function pointer to a FFI call.
    switch(t->underlying)
    {
      case TK_PRIMITIVE:
      case TK_STRUCT:
      case TK_CLASS:
      case TK_ACTOR:
        set_method_external_nominal(t, name);
        break;
      case TK_UNIONTYPE:
      case TK_ISECTTYPE:
      case TK_INTERFACE:
      case TK_TRAIT:
        set_method_external_interface(t, name);
        break;
      default:
        pony_assert(0);
        break;
    }
  }

  return funptr;
}
示例#10
0
文件: genfun.c 项目: fydot/ponyc
uint32_t genfun_vtable_size(compile_t* c, gentype_t* g)
{
  reachable_type_t* t = reach_type(c->reachable, g->type_name);

  if(t == NULL)
    return 0;

  return t->vtable_size;
}
示例#11
0
LLVMValueRef gen_tuple(compile_t* c, ast_t* ast)
{
  ast_t* child = ast_child(ast);

  if(ast_sibling(child) == NULL)
    return gen_expr(c, child);

  deferred_reification_t* reify = c->frame->reify;

  ast_t* type = deferred_reify(reify, ast_type(ast), c->opt);

  // If we contain '_', we have no usable value.
  if(contains_dontcare(type))
  {
    ast_free_unattached(type);
    return GEN_NOTNEEDED;
  }

  reach_type_t* t = reach_type(c->reach, type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;
  int count = LLVMCountStructElementTypes(c_t->primitive);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  LLVMGetStructElementTypes(c_t->primitive, elements);

  LLVMValueRef tuple = LLVMGetUndef(c_t->primitive);
  int i = 0;

  while(child != NULL)
  {
    LLVMValueRef value = gen_expr(c, child);

    if(value == NULL)
    {
      ponyint_pool_free_size(buf_size, elements);
      return NULL;
    }

    // We'll have an undefined element if one of our source elements is a
    // variable declaration. This is ok, since the tuple value will never be
    // used.
    if(value == GEN_NOVALUE || value == GEN_NOTNEEDED)
    {
      ponyint_pool_free_size(buf_size, elements);
      return value;
    }

    ast_t* child_type = deferred_reify(reify, ast_type(child), c->opt);
    value = gen_assign_cast(c, elements[i], value, child_type);
    ast_free_unattached(child_type);
    tuple = LLVMBuildInsertValue(c->builder, tuple, value, i++, "");
    child = ast_sibling(child);
  }

  ponyint_pool_free_size(buf_size, elements);
  return tuple;
}
示例#12
0
LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast)
{
  ast_t* id = ast_child(ast);
  const char* name = ast_name(id);

  // If this local has already been generated, don't create another copy. This
  // can happen when the same ast node is generated more than once, such as
  // the condition block of a while expression.
  LLVMValueRef value = codegen_getlocal(c, name);

  if(value != NULL)
    return GEN_NOVALUE;

  ast_t* type = deferred_reify(c->frame->reify, ast_type(id), c->opt);
  reach_type_t* t = reach_type(c->reach, type);
  ast_free_unattached(type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;

  // All alloca should happen in the entry block of a function.
  LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(codegen_fun(c));
  LLVMValueRef inst = LLVMGetFirstInstruction(entry_block);

  if(inst != NULL)
    LLVMPositionBuilderBefore(c->builder, inst);
  else
    LLVMPositionBuilderAtEnd(c->builder, entry_block);

  LLVMValueRef alloc = LLVMBuildAlloca(c->builder, c_t->mem_type, name);

  // Store the alloca to use when we reference this local.
  codegen_setlocal(c, name, alloc);

  LLVMMetadataRef file = codegen_difile(c);
  LLVMMetadataRef scope = codegen_discope(c);

#if PONY_LLVM >= 700
  uint32_t align_bytes = LLVMABIAlignmentOfType(c->target_data, c_t->mem_type);

  LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope,
    name, strlen(name), file, (unsigned)ast_line(ast), c_t->di_type,
    true, LLVMDIFlagZero, align_bytes * 8);
#else
  LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope, name,
    file, (unsigned)ast_line(ast), c_t->di_type);
#endif

  LLVMMetadataRef expr = LLVMDIBuilderCreateExpression(c->di, NULL, 0);

  LLVMDIBuilderInsertDeclare(c->di, alloc, info, expr,
    (unsigned)ast_line(ast), (unsigned)ast_pos(ast), scope,
    LLVMGetInsertBlock(c->builder));

  // Put the builder back where it was.
  LLVMPositionBuilderAtEnd(c->builder, this_block);
  return GEN_NOTNEEDED;
}
示例#13
0
LLVMValueRef gen_float(compile_t* c, ast_t* ast)
{
  ast_t* type = deferred_reify(c->frame->reify, ast_type(ast), c->opt);
  reach_type_t* t = reach_type(c->reach, type);
  ast_free_unattached(type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;

  return LLVMConstReal(c_t->primitive, ast_float(ast));
}
示例#14
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;
}
示例#15
0
void genprim_maybe_methods(compile_t* c, reach_type_t* t)
{
  ast_t* typeargs = ast_childidx(t->ast, 2);
  ast_t* typearg = ast_child(typeargs);
  reach_type_t* t_elem = reach_type(c->reach, typearg);

  maybe_create(c, t, t_elem);
  maybe_none(c, t);
  maybe_apply(c, t, t_elem);
  maybe_is_none(c, t);
}
示例#16
0
文件: gendesc.c 项目: npruehs/ponyc
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type)
{
  reach_type_t* t = reach_type(c->reach, type);

  if(t == NULL)
    return GEN_NOVALUE;

  LLVMValueRef dptr = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr,
    "");
  return LLVMBuildICmp(c->builder, LLVMIntEQ, desc, dptr, "");
}
示例#17
0
文件: gendesc.c 项目: awaidmann/ponyc
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type)
{
  reach_type_t* t = reach_type(c->reach, type);

  if(t == NULL)
    return GEN_NOVALUE;

  LLVMValueRef left = LLVMBuildPtrToInt(c->builder, desc, c->intptr, "");
  LLVMValueRef right = LLVMConstPtrToInt(t->desc, c->intptr);
  return LLVMBuildICmp(c->builder, LLVMIntEQ, left, right, "");
}
示例#18
0
文件: gendesc.c 项目: npruehs/ponyc
LLVMValueRef gendesc_istrait(compile_t* c, LLVMValueRef desc, ast_t* type)
{
  // Get the trait identifier.
  reach_type_t* t = reach_type(c->reach, 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 = LLVMBuildInBoundsGEP(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;
}
示例#19
0
static void trace_known(compile_t* c, LLVMValueRef ctx, LLVMValueRef object,
  ast_t* type, int mutability)
{
  reach_type_t* t = reach_type(c->reach, type);

  LLVMValueRef args[4];
  args[0] = ctx;
  args[1] = LLVMBuildBitCast(c->builder, object, c->object_ptr, "");
  args[2] = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr, "");
  args[3] = LLVMConstInt(c->i32, mutability, false);

  gencall_runtime(c, "pony_traceknown", args, 4, "");
}
示例#20
0
LLVMValueRef gen_localload(compile_t* c, ast_t* ast)
{
  LLVMValueRef local_ptr = gen_localptr(c, ast);

  if(local_ptr == NULL)
    return NULL;

  ast_t* type = deferred_reify(c->frame->reify, ast_type(ast), c->opt);
  reach_type_t* t = reach_type(c->reach, type);
  ast_free_unattached(type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;

  LLVMValueRef value = LLVMBuildLoad(c->builder, local_ptr, "");
  return gen_assign_cast(c, c_t->use_type, value, t->ast_cap);
}
示例#21
0
文件: gendesc.c 项目: Andrea/ponyc
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g)
{
  // The list is an array of integers.
  uint32_t count = trait_count(c, g);

  // If we have no traits, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0));

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

  reachable_type_t* t = reach_type(c->reachable, g->type_name);
  assert(t != NULL);

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

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

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

  // Create a constant array of trait identifiers.
  size_t list_size = index * sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(list_size);

  for(i = 0; i < index; i++)
    list[i] = LLVMConstInt(c->i32, tid[i], false);

  count = (uint32_t)index;
  LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count);

  // Create a global to hold the array.
  const char* name = genname_traitlist(g->type_name);
  LLVMTypeRef type = LLVMArrayType(c->i32, count);
  LLVMValueRef global = LLVMAddGlobal(c->module, type, name);
  LLVMSetGlobalConstant(global, true);
  LLVMSetLinkage(global, LLVMInternalLinkage);
  LLVMSetInitializer(global, trait_array);

  pool_free_size(tid_size, tid);
  pool_free_size(list_size, list);
  return global;
}
示例#22
0
static void trace_array_elements(compile_t* c, reach_type_t* t,
  LLVMValueRef ctx, LLVMValueRef object, LLVMValueRef pointer)
{
  // Get the type argument for the array. This will be used to generate the
  // per-element trace call.
  ast_t* typeargs = ast_childidx(t->ast, 2);
  ast_t* typearg = ast_child(typeargs);

  if(!gentrace_needed(typearg))
    return;

  reach_type_t* t_elem = reach_type(c->reach, typearg);
  pointer = LLVMBuildBitCast(c->builder, pointer,
    LLVMPointerType(t_elem->use_type, 0), "");

  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");

  // Read the size.
  LLVMValueRef size = field_value(c, object, 1);
  LLVMBuildBr(c->builder, cond_block);

  // While the index is less than the size, trace an element. The initial
  // index when coming from the entry block is zero.
  LLVMPositionBuilderAtEnd(c->builder, cond_block);
  LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, "");
  LLVMValueRef zero = LLVMConstInt(c->intptr, 0, false);
  LLVMAddIncoming(phi, &zero, &entry_block, 1);
  LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, size, "");
  LLVMBuildCondBr(c->builder, test, body_block, post_block);

  // The phi node is the index. Get the element and trace it.
  LLVMPositionBuilderAtEnd(c->builder, body_block);
  LLVMValueRef elem_ptr = LLVMBuildGEP(c->builder, pointer, &phi, 1, "elem");
  LLVMValueRef elem = LLVMBuildLoad(c->builder, elem_ptr, "");
  gentrace(c, ctx, elem, typearg);

  // Add one to the phi node and branch back to the cond block.
  LLVMValueRef one = LLVMConstInt(c->intptr, 1, false);
  LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, "");
  body_block = LLVMGetInsertBlock(c->builder);
  LLVMAddIncoming(phi, &inc, &body_block, 1);
  LLVMBuildBr(c->builder, cond_block);

  LLVMPositionBuilderAtEnd(c->builder, post_block);
}
示例#23
0
文件: genfun.c 项目: fydot/ponyc
bool genfun_methods(compile_t* c, gentype_t* g)
{
  reachable_type_t* t = reach_type(c->reachable, g->type_name);

  size_t i = HASHMAP_BEGIN;
  reachable_method_name_t* n;

  while((n = reachable_method_names_next(&t->methods, &i)) != NULL)
  {
    size_t j = HASHMAP_BEGIN;
    reachable_method_t* m;
    LLVMValueRef fun;

    while((m = reachable_methods_next(&n->r_methods, &j)) != NULL)
    {
      switch(ast_id(m->r_fun))
      {
        case TK_NEW:
          if(g->underlying == TK_ACTOR)
            fun = genfun_newbe(c, g, n->name, m->typeargs);
          else
            fun = genfun_new(c, g, n->name, m->typeargs);
          break;

        case TK_BE:
          fun = genfun_be(c, g, n->name, m->typeargs);
          break;

        case TK_FUN:
          fun = genfun_fun(c, g, n->name, m->typeargs);
          break;

        default:
          fun = NULL;
          break;
      }

      if(fun == NULL)
        return false;
    }
  }

  if(!genfun_allocator(c, g))
    return false;

  return true;
}
示例#24
0
LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast)
{
  ast_t* id = ast_child(ast);
  ast_t* type = ast_type(id);
  const char* name = ast_name(id);

  // If this local has already been generated, don't create another copy. This
  // can happen when the same ast node is generated more than once, such as
  // the condition block of a while expression.
  LLVMValueRef value = codegen_getlocal(c, name);

  if(value != NULL)
    return GEN_NOVALUE;

  reach_type_t* t = reach_type(c->reach, type);

  // All alloca should happen in the entry block of a function.
  LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(codegen_fun(c));
  LLVMValueRef inst = LLVMGetFirstInstruction(entry_block);

  if(inst != NULL)
    LLVMPositionBuilderBefore(c->builder, inst);
  else
    LLVMPositionBuilderAtEnd(c->builder, entry_block);

  LLVMValueRef alloc = LLVMBuildAlloca(c->builder, t->use_type, name);

  // Store the alloca to use when we reference this local.
  codegen_setlocal(c, name, alloc);

  LLVMMetadataRef file = codegen_difile(c);
  LLVMMetadataRef scope = codegen_discope(c);

  LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope, name,
    file, (unsigned)ast_line(ast), t->di_type);

  LLVMMetadataRef expr = LLVMDIBuilderCreateExpression(c->di, NULL, 0);

  LLVMDIBuilderInsertDeclare(c->di, alloc, info, expr,
    (unsigned)ast_line(ast), (unsigned)ast_pos(ast), scope,
    LLVMGetInsertBlock(c->builder));

  // Put the builder back where it was.
  LLVMPositionBuilderAtEnd(c->builder, this_block);
  return GEN_NOVALUE;
}
示例#25
0
文件: gendesc.c 项目: DevL/ponyc
static uint32_t trait_count(compile_t* c, gentype_t* g,
  uint32_t** list, size_t* list_size)
{
  switch(g->underlying)
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
    {
      reachable_type_t* t = reach_type(c->reachable, g->type_name);
      assert(t != NULL);
      uint32_t count = (uint32_t)reachable_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*)pool_alloc_size(tid_size);

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

      while((provide = reachable_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 {
        pool_free_size(tid_size, tid);
      }

      return count;
    }

    default: {}
  }

  return 0;
}
示例#26
0
文件: gendesc.c 项目: dleonard0/ponyc
static uint32_t trait_count(compile_t* c, gentype_t* g)
{
  switch(g->underlying)
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
    {
      reachable_type_t* t = reach_type(c->reachable, g->type_name);
      assert(t != NULL);

      return (uint32_t)reachable_type_cache_size(&t->subtypes);
    }

    default: {}
  }

  return 0;
}
示例#27
0
void genprim_pointer_methods(compile_t* c, reach_type_t* t)
{
  ast_t* typeargs = ast_childidx(t->ast, 2);
  ast_t* typearg = ast_child(typeargs);
  reach_type_t* t_elem = reach_type(c->reach, typearg);

  pointer_create(c, t);
  pointer_alloc(c, t, t_elem);

  pointer_realloc(c, t, t_elem);
  pointer_unsafe(c, t);
  pointer_apply(c, t, t_elem);
  pointer_update(c, t, t_elem);
  pointer_offset(c, t, t_elem);
  pointer_insert(c, t, t_elem);
  pointer_delete(c, t, t_elem);
  pointer_copy_to(c, t, t_elem);
  pointer_usize(c, t);
}
示例#28
0
static bool check_value(compile_t* c, ast_t* pattern, ast_t* param_type,
  LLVMValueRef value, LLVMBasicBlockRef next_block)
{
  reach_type_t* t = reach_type(c->reach, param_type);
  LLVMValueRef r_value = gen_assign_cast(c, t->use_type, value, param_type);

  if(r_value == NULL)
    return false;

  LLVMValueRef result = gen_pattern_eq(c, pattern, r_value);

  if(result == NULL)
    return false;

  LLVMBasicBlockRef continue_block = codegen_block(c, "pattern_continue");
  LLVMValueRef test = LLVMBuildTrunc(c->builder, result, c->i1, "");
  LLVMBuildCondBr(c->builder, test, continue_block, next_block);
  LLVMPositionBuilderAtEnd(c->builder, continue_block);
  return true;
}
示例#29
0
LLVMValueRef gen_int(compile_t* c, ast_t* ast)
{
  ast_t* type = ast_type(ast);
  reach_type_t* t = reach_type(c->reach, type);

  lexint_t* value = ast_int(ast);
  LLVMValueRef vlow = LLVMConstInt(c->i128, value->low, false);
  LLVMValueRef vhigh = LLVMConstInt(c->i128, value->high, false);
  LLVMValueRef shift = LLVMConstInt(c->i128, 64, false);
  vhigh = LLVMConstShl(vhigh, shift);
  vhigh = LLVMConstAdd(vhigh, vlow);

  if(t->primitive == c->i128)
    return vhigh;

  if((t->primitive == c->f32) || (t->primitive == c->f64))
    return LLVMConstUIToFP(vhigh, t->primitive);

  return LLVMConstTrunc(vhigh, t->primitive);
}
示例#30
0
LLVMValueRef gen_fieldload(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, left, right);

  LLVMValueRef field = gen_fieldptr(c, ast);

  if(field == NULL)
    return NULL;

  deferred_reification_t* reify = c->frame->reify;

  ast_t* type = deferred_reify(reify, ast_type(right), c->opt);
  reach_type_t* t = reach_type(c->reach, type);
  pony_assert(t != NULL);
  ast_free_unattached(type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;

  field = LLVMBuildLoad(c->builder, field, "");

  return gen_assign_cast(c, c_t->use_type, field, t->ast_cap);
}