Esempio n. 1
0
static void name_param(compile_t* c, reachable_type_t* t,
  reachable_method_t* m, LLVMValueRef func, const char* name, unsigned index,
  size_t line, size_t pos)
{
  LLVMValueRef value = LLVMGetParam(func, index);
  LLVMSetValueName(value, name);

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

  LLVMMetadataRef info;

  if(index == 0)
  {
    info = LLVMDIBuilderCreateArtificialVariable(c->di,
      m->di_method, name, index + 1, m->di_file, (unsigned)ast_line(m->r_fun),
      t->di_type);
  } else {
    info = LLVMDIBuilderCreateParameterVariable(c->di,
      m->di_method, name, index + 1, m->di_file, (unsigned)ast_line(m->r_fun),
      t->di_type);
  }

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

  LLVMDIBuilderInsertDeclare(c->di, alloc, info, expr,
    (unsigned)line, (unsigned)pos, m->di_method,
    LLVMGetInsertBlock(c->builder));
}
Esempio n. 2
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;
}
Esempio n. 3
0
/**
 * Make sure the definition of something occurs before its use. This is for
 * both fields and local variable.
 */
static bool def_before_use(ast_t* def, ast_t* use, const char* name)
{
  if((ast_line(def) > ast_line(use)) ||
     ((ast_line(def) == ast_line(use)) &&
      (ast_pos(def) > ast_pos(use))))
  {
    ast_error(use, "declaration of '%s' appears after use", name);
    ast_error(def, "declaration of '%s' appears here", name);
    return false;
  }

  return true;
}
Esempio n. 4
0
/**
 * Make sure the definition of something occurs before its use. This is for
 * both fields and local variable.
 */
bool def_before_use(pass_opt_t* opt, ast_t* def, ast_t* use, const char* name)
{
  if((ast_line(def) > ast_line(use)) ||
     ((ast_line(def) == ast_line(use)) &&
      (ast_pos(def) > ast_pos(use))))
  {
    ast_error(opt->check.errors, use,
      "declaration of '%s' appears after use", name);
    ast_error_continue(opt->check.errors, def,
      "declaration of '%s' appears here", name);
    return false;
  }

  return true;
}
Esempio n. 5
0
static void name_params(compile_t* c, reachable_type_t* t,
  reachable_method_t* m, ast_t* params, LLVMValueRef func)
{
  // Name the receiver 'this'.
  name_param(c, t, m, func, c->str_this, 0, ast_line(params), ast_pos(params));

  // Name each parameter.
  ast_t* param = ast_child(params);

  for(size_t i = 0; i < m->param_count; i++)
  {
    name_param(c, m->params[i], m, func, ast_name(ast_child(param)),
      (unsigned)i + 1, ast_line(param), ast_pos(param));
    param = ast_sibling(param);
  }
}
Esempio n. 6
0
static bool names_typealias(pass_opt_t* opt, ast_t** astp, ast_t* def)
{
  ast_t* ast = *astp;
  AST_GET_CHILDREN(ast, pkg, id, typeargs, cap, eph);

  // Make sure the alias is resolved,
  AST_GET_CHILDREN(def, alias_id, typeparams, def_cap, provides);
  ast_t* alias = ast_child(provides);

  if(!names_resolvealias(opt, def, &alias))
    return false;

  // Reify the alias.
  ast_t* r_alias = reify(typeparams, alias, typeparams, typeargs);

  if(r_alias == NULL)
    return false;

  // Apply our cap and ephemeral to the result.
  if(!names_applycap(r_alias, cap, eph))
  {
    ast_free_unattached(r_alias);
    return false;
  }

  // Maintain the position info of the original reference to aid error
  // reporting.
  ast_setpos(r_alias, ast_line(ast), ast_pos(ast));

  // Replace this with the alias.
  ast_replace(astp, r_alias);
  return true;
}
Esempio n. 7
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;
}
Esempio n. 8
0
void codegen_debugloc(compile_t* c, ast_t* ast)
{
  if(ast != NULL)
  {
    LLVMSetCurrentDebugLocation2(c->builder,
      (unsigned)ast_line(ast), (unsigned)ast_pos(ast), c->frame->di_scope);
  } else {
    LLVMSetCurrentDebugLocation2(c->builder, 0, 0, NULL);
  }
}
Esempio n. 9
0
static void make_debug_prototype(compile_t* c, reach_type_t* t)
{
  t->di_type = LLVMDIBuilderCreateReplaceableStruct(c->di,
    t->name, c->di_unit, t->di_file, (unsigned)ast_line(t->ast));

  if(t->underlying != TK_TUPLETYPE)
  {
    t->di_type_embed = t->di_type;
    t->di_type = LLVMDIBuilderCreatePointerType(c->di, t->di_type_embed, 0, 0);
  }
}
Esempio n. 10
0
File: dwarf.c Progetto: ozra/ponyc
void dwarf_method(dwarf_t* dwarf, ast_t* fun, const char* name,
  const char* mangled, const char** params, size_t count, LLVMValueRef ir)
{
  dwarf_meta_t meta;
  memset(&meta, 0, sizeof(dwarf_meta_t));

  source_t* source = ast_source(fun);
  ast_t* seq = ast_childidx(fun, 6);

  meta.file = source->file;
  meta.name = name;
  meta.mangled = mangled;
  meta.params = params;
  meta.line = ast_line(fun);
  meta.pos = ast_pos(fun);
  meta.offset = ast_line(seq);
  meta.size = count;

  symbols_method(dwarf->symbols, &meta, ir);
}
Esempio n. 11
0
static LLVMMetadataRef make_debug_field(compile_t* c, reach_type_t* t,
  uint32_t i)
{
  const char* name;
  char buf[32];
  unsigned flags = 0;
  uint64_t offset = 0;
  ast_t* ast;

  if(t->underlying != TK_TUPLETYPE)
  {
    ast_t* def = (ast_t*)ast_data(t->ast);
    ast_t* members = ast_childidx(def, 4);
    ast = ast_childidx(members, i);
    name = ast_name(ast_child(ast));

    if(is_name_private(name))
      flags |= DW_FLAG_Private;

    uint32_t extra = 0;

    if(t->underlying != TK_STRUCT)
      extra++;

    if(t->underlying == TK_ACTOR)
      extra++;

    offset = LLVMOffsetOfElement(c->target_data, t->structure, i + extra);
  } else {
    snprintf(buf, 32, "_%d", i + 1);
    name = buf;
    ast = t->ast;
    offset = LLVMOffsetOfElement(c->target_data, t->primitive, i);
  }

  LLVMTypeRef type;
  LLVMMetadataRef di_type;

  if(t->fields[i].embed)
  {
    type = t->fields[i].type->structure;
    di_type = t->fields[i].type->di_type_embed;
  } else {
    type = t->fields[i].type->use_type;
    di_type = t->fields[i].type->di_type;
  }

  uint64_t size = LLVMABISizeOfType(c->target_data, type);
  uint64_t align = LLVMABIAlignmentOfType(c->target_data, type);

  return LLVMDIBuilderCreateMemberType(c->di, c->di_unit, name, t->di_file,
    (unsigned)ast_line(ast), 8 * size, 8 * align, 8 * offset, flags, di_type);
}
Esempio n. 12
0
File: dwarf.c Progetto: ozra/ponyc
void dwarf_lexicalscope(dwarf_t* dwarf, ast_t* ast)
{
  dwarf_meta_t meta;
  memset(&meta, 0, sizeof(dwarf_meta_t));

  symbols_push_frame(dwarf->symbols, NULL);
  source_t* source = ast_source(ast);

  meta.file = source->file;
  meta.line = ast_line(ast);
  meta.pos = ast_pos(ast);

  symbols_lexicalscope(dwarf->symbols, &meta);
}
Esempio n. 13
0
static void setup_dwarf(dwarf_t* dwarf, dwarf_meta_t* meta, gentype_t* g,
  bool opaque, bool field)
{
  memset(meta, 0, sizeof(dwarf_meta_t));

  ast_t* ast = g->ast;
  LLVMTypeRef type = g->primitive;

  if(is_machine_word(ast))
  {
    if(is_float(ast))
      meta->flags |= DWARF_FLOAT;
    else if(is_signed(dwarf->opt, ast))
      meta->flags |= DWARF_SIGNED;
    else if(is_bool(ast))
      meta->flags |= DWARF_BOOLEAN;
  }
  else if(is_pointer(ast) || is_maybe(ast) || !is_concrete(ast) ||
    (is_constructable(ast) && field))
  {
    type = g->use_type;
  }
  else if(is_constructable(ast))
  {
    type = g->structure;
  }

  bool defined_type = g->underlying != TK_TUPLETYPE &&
    g->underlying != TK_UNIONTYPE && g->underlying != TK_ISECTTYPE;

  source_t* source;

  if(defined_type)
    ast = (ast_t*)ast_data(ast);

  source = ast_source(ast);
  meta->file = source->file;
  meta->name = g->type_name;
  meta->line = ast_line(ast);
  meta->pos = ast_pos(ast);

  if(!opaque)
  {
    meta->size = LLVMABISizeOfType(dwarf->target_data, type) << 3;
    meta->align = LLVMABIAlignmentOfType(dwarf->target_data, type) << 3;
  }
}
Esempio n. 14
0
static void make_debug_fields(compile_t* c, reach_type_t* t)
{
  LLVMMetadataRef fields = NULL;

  if(t->field_count > 0)
  {
    size_t buf_size = t->field_count * sizeof(LLVMMetadataRef);
    LLVMMetadataRef* data = (LLVMMetadataRef*)ponyint_pool_alloc_size(
      buf_size);

    for(uint32_t i = 0; i < t->field_count; i++)
      data[i] = make_debug_field(c, t, i);

    fields = LLVMDIBuilderGetOrCreateArray(c->di, data, t->field_count);
    ponyint_pool_free_size(buf_size, data);
  }

  LLVMTypeRef type;

  if(t->underlying != TK_TUPLETYPE)
    type = t->structure;
  else
    type = t->primitive;

  uint64_t size = 0;
  uint64_t align = 0;

  if(type != NULL)
  {
    size = LLVMABISizeOfType(c->target_data, type);
    align = LLVMABIAlignmentOfType(c->target_data, type);
  }

  LLVMMetadataRef di_type = LLVMDIBuilderCreateStructType(c->di, c->di_unit,
    t->name, t->di_file, (unsigned) ast_line(t->ast), 8 * size, 8 * align,
    fields);

  if(t->underlying != TK_TUPLETYPE)
  {
    LLVMMetadataReplaceAllUsesWith(t->di_type_embed, di_type);
    t->di_type_embed = di_type;
  } else {
    LLVMMetadataReplaceAllUsesWith(t->di_type, di_type);
    t->di_type = di_type;
  }
}
Esempio n. 15
0
void codegen_pushscope(compile_t* c, ast_t* ast)
{
  compile_frame_t* frame = push_frame(c);

  frame->fun = frame->prev->fun;
  frame->break_target = frame->prev->break_target;
  frame->continue_target = frame->prev->continue_target;
  frame->invoke_target = frame->prev->invoke_target;
  frame->di_file = frame->prev->di_file;

  if(frame->prev->di_scope != NULL)
  {
    frame->di_scope = LLVMDIBuilderCreateLexicalBlock(c->di,
      frame->prev->di_scope, frame->di_file,
      (unsigned)ast_line(ast), (unsigned)ast_pos(ast));
  }
}
Esempio n. 16
0
File: dwarf.c Progetto: ozra/ponyc
void dwarf_location(dwarf_t* dwarf, ast_t* ast)
{
  if(dwarf->has_source && (ast != NULL))
  {
    size_t line = ast_line(ast);
    size_t pos = ast_pos(ast);

    if(!ast_debug(ast))
      symbols_reset(dwarf->symbols, true);
    else
      symbols_location(dwarf->symbols, line, pos);
  }
  else if(dwarf->symbols != NULL)
  {
    symbols_reset(dwarf->symbols, true);
  }
}
Esempio n. 17
0
File: dwarf.c Progetto: ozra/ponyc
static void meta_local(dwarf_meta_t* meta, ast_t* ast, const char* name,
  const char* type, LLVMBasicBlockRef entry, LLVMValueRef storage,
  size_t offset, bool constant)
{
  memset(meta, 0, sizeof(dwarf_meta_t));

  source_t* source = ast_source(ast);

  meta->file = source->file;
  meta->name = name;
  meta->mangled = type;
  meta->line = ast_line(ast);
  meta->pos = ast_pos(ast);
  meta->offset = offset + 1;
  meta->entry = entry;
  meta->storage = storage;

  if(constant)
    meta->flags = DWARF_CONSTANT;
}
Esempio n. 18
0
// Check the number of configs we have to process and print a warning if it's a
// lot.
static void check_config_count(buildflagset_t* config, ast_t* location)
{
  pony_assert(config != NULL);
  pony_assert(location != NULL);

  double config_count = buildflagset_configcount(config);

  if(config_count > 10000)
  {
    source_t* source = ast_source(location);
    const char* file = NULL;

    if(source != NULL)
      file = source->file;

    if(file == NULL)
      file = "";

    printf("Processing %g configs at %s:" __zu ", this may take some time\n",
      config_count, file, ast_line(location));
  }
}
Esempio n. 19
0
static void make_function_debug(compile_t* c, reachable_type_t* t,
  reachable_method_t* m, LLVMValueRef func)
{
  AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error,
    body);

  // Count the parameters, including the receiver and the result.
  size_t count = m->param_count + 2;
  size_t md_size = count * sizeof(reachable_type_t*);
  LLVMMetadataRef* md = (LLVMMetadataRef*)ponyint_pool_alloc_size(md_size);

  md[0] = m->result->di_type;
  md[1] = t->di_type;

  for(size_t i = 0; i < m->param_count; i++)
    md[i + 2] = m->params[i]->di_type;

  m->di_file = t->di_file;

  LLVMMetadataRef type_array = LLVMDIBuilderGetOrCreateTypeArray(c->di,
    md, count);

  LLVMMetadataRef subroutine = LLVMDIBuilderCreateSubroutineType(c->di,
    m->di_file, type_array);

  LLVMMetadataRef scope;

  if(t->di_type_embed != NULL)
    scope = t->di_type_embed;
  else
    scope = t->di_type;

  m->di_method = LLVMDIBuilderCreateMethod(c->di, scope, ast_name(id),
    m->full_name, m->di_file, (unsigned)ast_line(m->r_fun), subroutine, func,
    c->opt->release);

  ponyint_pool_free_size(md_size, md);
}
Esempio n. 20
0
static void add_fields(reach_t* r, reach_type_t* t, pass_opt_t* opt)
{
  ast_t* def = (ast_t*)ast_data(t->ast);
  ast_t* typeargs = ast_childidx(t->ast, 2);
  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* members = ast_childidx(def, 4);
  ast_t* member = ast_child(members);

  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
      {
        t->field_count++;
        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }

  if(t->field_count == 0)
    return;

  t->fields = (reach_field_t*)calloc(t->field_count, sizeof(reach_field_t));
  member = ast_child(members);
  size_t index = 0;

  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
      {
        ast_t* r_member = lookup(NULL, NULL, t->ast,
          ast_name(ast_child(member)));
        assert(r_member != NULL);

        AST_GET_CHILDREN(r_member, name, type, init);

        t->fields[index].embed = ast_id(member) == TK_EMBED;
        t->fields[index].ast = reify(ast_type(member), typeparams, typeargs,
          opt, true);
        ast_setpos(t->fields[index].ast, NULL, ast_line(name), ast_pos(name));
        t->fields[index].type = add_type(r, type, opt);

        if(r_member != member)
          ast_free_unattached(r_member);

        index++;
        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }
}
Esempio n. 21
0
File: gentype.c Progetto: nunb/ponyc
static void setup_type_fields(gentype_t* g)
{
  assert(ast_id(g->ast) == TK_NOMINAL);

  g->field_count = 0;
  g->fields = NULL;
  g->field_keys = NULL;

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

  if(ast_id(def) == TK_PRIMITIVE)
    return;

  ast_t* typeargs = ast_childidx(g->ast, 2);
  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* members = ast_childidx(def, 4);
  ast_t* member = ast_child(members);

  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
      {
        g->field_count++;
        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }

  if(g->field_count == 0)
    return;

  g->fields = (ast_t**)calloc(g->field_count, sizeof(ast_t*));
  g->field_keys = (token_id*)calloc(g->field_count, sizeof(token_id));

  member = ast_child(members);
  size_t index = 0;

  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
      {
        AST_GET_CHILDREN(member, name, type, init);
        g->fields[index] = reify(ast_type(member), typeparams, typeargs);

        // TODO: Are we sure the AST source file is correct?
        ast_setpos(g->fields[index], NULL, ast_line(name), ast_pos(name));
        g->field_keys[index] = ast_id(member);
        index++;
        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }
}