Exemplo n.º 1
0
Arquivo: genexe.c Projeto: volth/ponyc
bool genexe(compile_t* c, ast_t* program)
{
  // The first package is the main package. It has to have a Main actor.
  const char* main_actor = stringtab("Main");
  const char* env_class = stringtab("Env");

  ast_t* package = ast_child(program);
  ast_t* main_def = ast_get(package, main_actor, NULL);

  if(main_def == NULL)
  {
    errorf(NULL, "no Main actor found in package '%s'", c->filename);
    return false;
  }

  // Generate the Main actor and the Env class.
  ast_t* main_ast = type_builtin(c->opt, main_def, main_actor);
  ast_t* env_ast = type_builtin(c->opt, main_def, env_class);

  genprim_reachable_init(c, program);
  reach(c->reachable, main_ast, stringtab("create"), NULL);
  reach(c->reachable, env_ast, stringtab("_create"), NULL);
  paint(c->reachable);

  gentype_t main_g;
  gentype_t env_g;

  bool ok = gentype(c, main_ast, &main_g) && gentype(c, env_ast, &env_g);

  if(ok)
    gen_main(c, &main_g, &env_g);

  ast_free_unattached(main_ast);
  ast_free_unattached(env_ast);

  if(!ok)
    return false;

  if(!genopt(c))
    return false;

  const char* file_o = genobj(c);

  if(file_o == NULL)
    return false;

  if(c->opt->limit < PASS_ALL)
    return true;

  if(!link_exe(c, program, file_o))
    return false;

#ifdef PLATFORM_IS_WINDOWS
  _unlink(file_o);
#else
  unlink(file_o);
#endif

  return true;
}
Exemplo n.º 2
0
static LLVMTypeRef get_signature(compile_t* c, gentype_t* g, ast_t* fun)
{
  // Get a type for the result.
  ast_t* rtype = ast_childidx(fun, 4);
  gentype_t rtype_g;

  if(!gentype(c, rtype, &rtype_g))
  {
    ast_error(rtype, "couldn't generate result type");
    return 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 *sizeof(LLVMTypeRef);
  LLVMTypeRef* tparams = (LLVMTypeRef*)pool_alloc_size(buf_size);
  count = 0;

  // Get a type for the receiver.
  tparams[count++] = g->use_type;

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

  while(param != NULL)
  {
    ast_t* ptype = ast_childidx(param, 1);
    gentype_t ptype_g;

    if(!gentype(c, ptype, &ptype_g))
    {
      ast_error(ptype, "couldn't generate parameter type");
      pool_free_size(buf_size, tparams);
      return NULL;
    }

    tparams[count++] = ptype_g.use_type;
    param = ast_sibling(param);
  }

  LLVMTypeRef result = rtype_g.use_type;

  // Generate the function type.
  LLVMTypeRef r = LLVMFunctionType(result, tparams, (int)count, false);

  pool_free_size(buf_size, tparams);
  return r;
}
Exemplo n.º 3
0
LLVMValueRef gen_int(compile_t* c, ast_t* ast)
{
  ast_t* type = ast_type(ast);

  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  __uint128_t value = ast_int(ast);

  uint64_t low, high;
#if !defined(HAVE_STRUCT_INT128)
  low = (uint64_t)value;
  high = (uint64_t)(value >> 64);
#else
  low = value.low;
  high = value.high;
#endif

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

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

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

  return LLVMConstTrunc(vhigh, g.primitive);
}
Exemplo n.º 4
0
static bool dynamic_value_ptr(compile_t* c, LLVMValueRef ptr,
  LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block)
{
  // Get the type of the right-hand side of the pattern's eq() function.
  ast_t* param_type = eq_param_type(pattern);

  // Check the runtime type. We pass a pointer to the fields because we may
  // still need to match a tuple type inside a type expression.
  if(!check_type(c, ptr, desc, param_type, next_block))
    return false;

  // We now know that ptr points to something of type pattern_type, and that
  // it isn't a boxed primitive, as that would go through the other path, ie
  // dynamic_match_object(). We also know it isn't an unboxed tuple. We can
  // load from ptr with a type based on the static type of the pattern.
  gentype_t g;

  if(!gentype(c, param_type, &g))
    return false;

  LLVMTypeRef ptr_type = LLVMPointerType(g.use_type, 0);
  ptr = LLVMBuildIntToPtr(c->builder, ptr, ptr_type, "");
  LLVMValueRef value = LLVMBuildLoad(c->builder, ptr, "");

  return check_value(c, pattern, param_type, value, next_block);
}
Exemplo n.º 5
0
static bool check_value(compile_t* c, ast_t* pattern, ast_t* param_type,
  LLVMValueRef value, LLVMBasicBlockRef next_block)
{
  LLVMValueRef l_value = gen_expr(c, pattern);

  if(l_value == NULL)
    return false;

  gentype_t g;

  if(!gentype(c, param_type, &g))
    return false;

  LLVMValueRef r_value = gen_assign_cast(c, g.use_type, value, param_type);

  if(r_value == NULL)
    return false;

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

  if(test == NULL)
    return false;

  LLVMBasicBlockRef continue_block = codegen_block(c, "pattern_continue");
  LLVMBuildCondBr(c->builder, test, continue_block, next_block);
  LLVMPositionBuilderAtEnd(c->builder, continue_block);
  return true;
}
Exemplo n.º 6
0
LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast)
{
  ast_t* id = ast_child(ast);
  ast_t* type = ast_type(id);
  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

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

  const char* name = ast_name(id);
  LLVMValueRef l_value = LLVMBuildAlloca(c->builder, g.use_type, name);

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

  // Emit debug info for local variable declaration.
  dwarf_local(&c->dwarf, ast, g.type_name, entry_block, inst, l_value);

  // Put the builder back where it was.
  LLVMPositionBuilderAtEnd(c->builder, this_block);
  return GEN_NOVALUE;
}
Exemplo n.º 7
0
LLVMValueRef gen_funptr(compile_t* c, ast_t* ast)
{
  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 type.
  const char* method_name = ast_name(method);
  ast_t* type = ast_type(receiver);
  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  LLVMValueRef value = gen_expr(c, receiver);
  return dispatch_function(c, ast, &g, value, method_name, typeargs);
}
Exemplo n.º 8
0
static bool dynamic_capture_ptr(compile_t* c, LLVMValueRef ptr,
  LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block)
{
  // Here, ptr is a pointer to a tuple field. It could be a primitive, an
  // object, or a nested tuple.
  ast_t* pattern_type = ast_type(pattern);

  // Check the runtime type. We pass a pointer to the fields because we may
  // still need to match a tuple type inside a type expression.
  if(!check_type(c, ptr, desc, pattern_type, next_block))
    return false;

  // We now know that ptr points to something of type pattern_type, and that
  // it isn't a boxed primitive or tuple, as that would go through the other
  // path, ie dynamic_match_object(). We also know it isn't an unboxed tuple.
  // We can load from ptr with a type based on the static type of the pattern.
  gentype_t g;

  if(!gentype(c, pattern_type, &g))
    return false;

  LLVMTypeRef ptr_type = LLVMPointerType(g.use_type, 0);
  ptr = LLVMBuildIntToPtr(c->builder, ptr, ptr_type, "");
  LLVMValueRef value = LLVMBuildLoad(c->builder, ptr, "");

  return gen_assign_value(c, pattern, value, pattern_type) != NULL;
}
Exemplo n.º 9
0
static bool trace_known(compile_t* c, LLVMValueRef ctx, LLVMValueRef value,
  ast_t* type)
{
  gentype_t g;

  if(!gentype(c, type, &g))
    return false;

  // Get the trace function statically.
  const char* fun = genname_trace(g.type_name);
  LLVMValueRef trace_fn = LLVMGetNamedFunction(c->module, fun);

  // If this type has no trace function, don't try to recurse in the runtime.
  if(trace_fn != NULL)
  {
    // Cast the value to an object pointer.
    LLVMValueRef args[3];
    args[0] = ctx;
    args[1] = LLVMBuildBitCast(c->builder, value, c->object_ptr, "");
    args[2] = trace_fn;

    gencall_runtime(c, "pony_traceobject", args, 3, "");
  } else {
    // Cast the value to a void pointer.
    LLVMValueRef args[2];
    args[0] = ctx;
    args[1] = LLVMBuildBitCast(c->builder, value, c->void_ptr, "");
    gencall_runtime(c, "pony_trace", args, 2, "");
  }

  return true;
}
Exemplo n.º 10
0
LLVMValueRef gen_pattern_eq(compile_t* c, ast_t* pattern, LLVMValueRef r_value)
{
  // This is used for structural equality in pattern matching.
  ast_t* pattern_type = ast_type(pattern);
  AST_GET_CHILDREN(pattern_type, package, id);

  // Special case equality on primitive types.
  if(ast_name(package) == c->str_builtin)
  {
    const char* name = ast_name(id);

    if((name == c->str_Bool) ||
      (name == c->str_I8) ||
      (name == c->str_I16) ||
      (name == c->str_I32) ||
      (name == c->str_I64) ||
      (name == c->str_I128) ||
      (name == c->str_ILong) ||
      (name == c->str_ISize) ||
      (name == c->str_U8) ||
      (name == c->str_U16) ||
      (name == c->str_U32) ||
      (name == c->str_U64) ||
      (name == c->str_U128) ||
      (name == c->str_ULong) ||
      (name == c->str_USize) ||
      (name == c->str_F32) ||
      (name == c->str_F64)
      )
    {
      return gen_eq_rvalue(c, pattern, r_value);
    }
  }

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

  gentype_t g;

  if(!gentype(c, pattern_type, &g))
    return NULL;

  // Static or virtual dispatch.
  LLVMValueRef func = dispatch_function(c, pattern, &g, l_value,
    stringtab("eq"), NULL);

  if(func == NULL)
    return NULL;

  // Call the function. We know it isn't partial.
  LLVMValueRef args[2];
  args[0] = l_value;
  args[1] = r_value;

  // Emit debug location for calls to test for structural equality
  dwarf_location(&c->dwarf, pattern);

  return codegen_call(c, func, args, 2);
}
Exemplo n.º 11
0
void genp9(Node *file, char *out)
{
	Htab *globls, *strtab;
	Node *n, **blob;
	Func **fn;
	size_t nfn, nblob;
	size_t i;
	FILE *fd;

	/* ensure that all physical registers have a loc created before any
	 * other locs, so that locmap[Physreg] maps to the Loc for the physreg
	 * in question */
	for (i = 0; i < Nreg; i++)
		locphysreg(i);

	fn = NULL;
	nfn = 0;
	blob = NULL;
	nblob = 0;
	globls = mkht(varhash, vareq);
	initconsts(globls);

	/* We need to define all global variables before use */
	fillglobls(file->file.globls, globls);

	pushstab(file->file.globls);
	for (i = 0; i < file->file.nstmts; i++) {
		n = file->file.stmts[i];
		switch (n->type) {
		case Nuse: /* nothing to do */ 
		case Nimpl:
			break;
		case Ndecl:
			simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
			break;
		default:
			die("Bad node %s in toplevel", nodestr[n->type]);
			break;
		}
	}
	popstab();

	fd = fopen(out, "w");
	if (!fd)
		die("Couldn't open fd %s", out);

	strtab = mkht(strlithash, strliteq);
	for (i = 0; i < nblob; i++)
		genblob(fd, blob[i], globls, strtab);
	for (i = 0; i < nfn; i++)
		genfunc(fd, fn[i], globls, strtab);
	for (i = 0; i < ntypes; i++)
		if (types[i]->isreflect && !types[i]->isimport)
			gentype(fd, types[i]);
	fprintf(fd, "\n");
	genstrings(fd, strtab);

	fclose(fd);
}
Exemplo n.º 12
0
static LLVMValueRef make_field_list(compile_t* c, gentype_t* g)
{
  // The list is an array of field descriptors.
  int count;

  if(g->underlying == TK_TUPLETYPE)
    count = g->field_count;
  else
    count = 0;

  LLVMTypeRef type = LLVMArrayType(c->field_descriptor, count);

  // If we aren't a tuple, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(type, 0));

  // Create a constant array of field descriptors.
  size_t buf_size = count *sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(buf_size);

  for(int i = 0; i < count; i++)
  {
    gentype_t fg;

    if(!gentype(c, g->fields[i], &fg))
      return NULL;

    LLVMValueRef fdesc[2];
    fdesc[0] = LLVMConstInt(c->i32,
      LLVMOffsetOfElement(c->target_data, g->primitive, i), false);

    if(fg.desc != NULL)
    {
      // We are a concrete type.
      fdesc[1] = LLVMConstBitCast(fg.desc, c->descriptor_ptr);
    } else {
      // We aren't a concrete type.
      fdesc[1] = LLVMConstNull(c->descriptor_ptr);
    }

    list[i] = LLVMConstStructInContext(c->context, fdesc, 2, false);
  }

  LLVMValueRef field_array = LLVMConstArray(c->field_descriptor, list, count);

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

  pool_free_size(buf_size, list);
  return global;
}
Exemplo n.º 13
0
LLVMValueRef gen_float(compile_t* c, ast_t* ast)
{
  ast_t* type = ast_type(ast);

  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  return LLVMConstReal(g.primitive, ast_float(ast));
}
Exemplo n.º 14
0
Arquivo: gendesc.c Projeto: DevL/ponyc
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type)
{
  gentype_t g;

  if(!gentype(c, type, &g))
    return GEN_NOVALUE;

  LLVMValueRef left = LLVMBuildPtrToInt(c->builder, desc, c->intptr, "");
  LLVMValueRef right = LLVMConstPtrToInt(g.desc, c->intptr);
  return LLVMBuildICmp(c->builder, LLVMIntEQ, left, right, "");
}
Exemplo n.º 15
0
Arquivo: ga.c Projeto: haiy/XF_PRISM
void update_pop(population *S,mic_matrix M)
{
    int i=0;
    for(i=0;i<S->n;i++)
    {
        int **gtp=(int **)malloc(sizeof(int *));
        int num=gentype(S->m[i].chro,gtp,S->m[i].l);
        S->m[i].sig=cal_merit(*gtp,num,M);
        free(*gtp);
        free(gtp);
        gtp=NULL;
    }
}
Exemplo n.º 16
0
Arquivo: genfun.c Projeto: fydot/ponyc
static void name_param(compile_t* c, LLVMValueRef func, const char* name,
  ast_t* type, int index)
{
  gentype_t g;
  gentype(c, type, &g);

  LLVMValueRef param = LLVMGetParam(func, index);
  LLVMSetValueName(param, name);

  LLVMValueRef value = LLVMBuildAlloca(c->builder, g.use_type, name);
  LLVMBuildStore(c->builder, param, value);
  codegen_setlocal(c, name, value);
}
Exemplo n.º 17
0
static bool generate_actor(compile_t* c, ast_t* ast)
{
  ast_t* id = ast_child(ast);
  ast_t* type = type_builtin(c->opt, ast, ast_name(id));

  if(type == NULL)
    return false;

  gentype_t g;
  bool ok = gentype(c, type, &g);
  ast_free_unattached(type);

  return ok;
}
Exemplo n.º 18
0
Arquivo: gentype.c Projeto: nunb/ponyc
static bool make_components(compile_t* c, gentype_t* g)
{
  for(int i = 0; i < g->field_count; i++)
  {
    gentype_t field_g;

    if(!gentype(c, g->fields[i], &field_g))
      return false;

    dwarf_field(&c->dwarf, g, &field_g, i);
  }

  return true;
}
Exemplo n.º 19
0
Arquivo: gengas.c Projeto: 8l/mc
static void gentypes(FILE *fd)
{
	Type *ty;
	size_t i;

	for (i = Ntypes; i < ntypes; i++) {
		if (!types[i]->isreflect)
			continue;
		ty = tydedup(types[i]);
		if (ty->isemitted || ty->isimport)
			continue;
		gentype(fd, ty);
	}
	fprintf(fd, "\n");
}
Exemplo n.º 20
0
Arquivo: gentype.c Projeto: 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);
}
Exemplo n.º 21
0
Arquivo: genexe.c Projeto: volth/ponyc
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);
  }
}
Exemplo n.º 22
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);

  ast_t* type = ast_type(ast);
  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  // If we contain TK_DONTCARE, we have no usable value.
  if(g.primitive == NULL)
    return GEN_NOVALUE;

  LLVMValueRef tuple = LLVMGetUndef(g.primitive);
  int i = 0;

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

    if(value == NULL)
      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)
      tuple = LLVMBuildInsertValue(c->builder, tuple, value, i++, "");

    child = ast_sibling(child);
  }

  return tuple;
}
Exemplo n.º 23
0
Arquivo: ga.c Projeto: haiy/XF_PRISM
//initialize the population
void ini_pop(mic_matrix M,population *pop)
{
    pop->m=(chro_ptr)malloc(sizeof(chrosome)*(pop->n));
    if(pop->m==NULL)
    {
        printf("Ini_pop memory error!\n");
    }
    int i=0;
    while(i < pop->n)
    {
        /* Here pop->m[i].l denotes the length of the chrosome ,染色体长度不应该包含类标签*/
        pop->m[i].l=M.atrn-1;
        pop->m[i].chro=(int *)malloc(sizeof(int)*(pop->m[i].l));
        if(pop->m[i].chro==NULL)
        {
            printf("GA ini_pop mem error!\n");
            exit(0);
        }
        int j=0;
        for(;j<pop->m[i].l;j++)
        {
            pop->m[i].chro[j]=rand()%2;
        }
        int **gtp=(int **)malloc(sizeof(int *));
        if(gtp==NULL)
        {
            puts("GA gtp mem error!");
            exit(1);
        }
        int num=gentype(pop->m[i].chro,gtp,pop->m[i].l);
        pop->m[i].sig=cal_merit(gtp[0],num,M);
        free(*gtp);
        free(gtp);
        gtp=NULL;
     
        i++;
    };
}
Exemplo n.º 24
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 = strlen(name);

  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), "$strval");
  LLVMSetLinkage(g_str, LLVMInternalLinkage);
  LLVMSetInitializer(g_str, str);
  LLVMSetGlobalConstant(g_str, true);
  LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2);

  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  args[0] = g.desc;
  args[1] = LLVMConstInt(c->i64, len, false);
  args[2] = LLVMConstInt(c->i64, 0, false);
  args[3] = str_ptr;

  LLVMValueRef inst = LLVMConstNamedStruct(g.structure, args, 4);
  LLVMValueRef g_inst = LLVMAddGlobal(c->module, g.structure, "$string");
  LLVMSetInitializer(g_inst, inst);
  LLVMSetGlobalConstant(g_inst, true);
  LLVMSetLinkage(g_inst, LLVMInternalLinkage);

  return g_inst;
}
Exemplo n.º 25
0
LLVMValueRef gen_ffi(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, typeargs, args);

  // Get the function name, +1 to skip leading @
  const char* f_name = ast_name(id) + 1;

  // Generate the return type.
  ast_t* type = ast_type(ast);
  gentype_t g;

  // Emit dwarf location of ffi call
  dwarf_location(&c->dwarf, ast);

  if(!gentype(c, type, &g))
    return NULL;

  // Get the function.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, f_name);

  if(func == NULL)
  {
    // If we have no prototype, declare one.
    if(!strncmp(f_name, "llvm.", 5))
    {
      // Intrinsic, so use the exact types we supply.
      int count = (int)ast_childcount(args);
      size_t buf_size = count * sizeof(LLVMTypeRef);
      LLVMTypeRef* f_params = (LLVMTypeRef*)pool_alloc_size(buf_size);
      count = 0;

      ast_t* arg = ast_child(args);

      while(arg != NULL)
      {
        ast_t* p_type = ast_type(arg);
        gentype_t param_g;

        if(!gentype(c, p_type, &param_g))
          return NULL;

        f_params[count++] = param_g.use_type;
        arg = ast_sibling(arg);
      }

      // We may have generated the function by generating a parameter type.
      func = LLVMGetNamedFunction(c->module, f_name);

      if(func == NULL)
      {
        LLVMTypeRef r_type;

        if(g.underlying == TK_TUPLETYPE)
        {
          // Can't use the named type. Build an unnamed type with the same
          // elements.
          unsigned int count = LLVMCountStructElementTypes(g.use_type);
          size_t buf_size = count * sizeof(LLVMTypeRef);
          LLVMTypeRef* e_types = (LLVMTypeRef*)pool_alloc_size(buf_size);
          LLVMGetStructElementTypes(g.use_type, e_types);
          r_type = LLVMStructTypeInContext(c->context, e_types, count, false);
          pool_free_size(buf_size, e_types);
        } else {
          r_type = g.use_type;
        }

        LLVMTypeRef f_type = LLVMFunctionType(r_type, f_params, count,
          false);
        func = LLVMAddFunction(c->module, f_name, f_type);

        if(!ast_canerror(ast))
          LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
      }

      pool_free_size(buf_size, f_params);
    } else {
      // Make it varargs.
      LLVMTypeRef f_type = LLVMFunctionType(g.use_type, NULL, 0, true);
      func = LLVMAddFunction(c->module, f_name, f_type);

      if(!ast_canerror(ast))
        LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
    }
  }

  // Generate the arguments.
  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* f_args = (LLVMValueRef*)pool_alloc_size(buf_size);
  ast_t* arg = ast_child(args);

  for(int i = 0; i < count; i++)
  {
    f_args[i] = gen_expr(c, arg);

    if(f_args[i] == NULL)
    {
      pool_free_size(buf_size, f_args);
      return NULL;
    }

    arg = ast_sibling(arg);
  }

  // If we can error out and we have an invoke target, generate an invoke
  // instead of a call.
  LLVMValueRef result;

  if(ast_canerror(ast) && (c->frame->invoke_target != NULL))
    result = invoke_fun(c, func, f_args, count, "", false);
  else
    result = LLVMBuildCall(c->builder, func, f_args, count, "");

  pool_free_size(buf_size, f_args);

  // Special case a None return value, which is used for void functions.
  if(is_none(type))
    return g.instance;

  return result;
}
Exemplo n.º 26
0
LLVMValueRef gen_call(compile_t* c, ast_t* ast)
{
  // Special case calls.
  LLVMValueRef special;

  if(special_case_call(c, ast, &special))
    return special;

  AST_GET_CHILDREN(ast, positional, named, postfix);
  AST_GET_CHILDREN(postfix, receiver, method);
  ast_t* typeargs = NULL;

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

    default: {}
  }

  // Generate the receiver type.
  const char* method_name = ast_name(method);
  ast_t* type = ast_type(receiver);
  gentype_t g;

  if(!gentype(c, type, &g))
    return NULL;

  // Generate the arguments.
  LLVMTypeRef f_type = genfun_sig(c, &g, method_name, typeargs);

  if(f_type == NULL)
  {
    ast_error(ast, "couldn't create a signature for '%s'", method_name);
    return NULL;
  }

  size_t count = ast_childcount(positional) + 1;
  size_t buf_size = count * sizeof(void*);

  LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(buf_size);
  LLVMTypeRef* params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  LLVMGetParamTypes(f_type, params);

  ast_t* arg = ast_child(positional);
  int i = 1;

  while(arg != NULL)
  {
    LLVMValueRef value = make_arg(c, params[i], arg);

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

    args[i] = value;
    arg = ast_sibling(arg);
    i++;
  }

  // Generate the receiver. Must be done after the arguments because the args
  // could change things in the receiver expression that must be accounted for.
  if(call_needs_receiver(postfix, &g))
  {
    switch(ast_id(postfix))
    {
      case TK_NEWREF:
      case TK_NEWBEREF:
      {
        ast_t* parent = ast_parent(ast);
        ast_t* sibling = ast_sibling(ast);

        // If we're constructing an embed field, pass a pointer to the field
        // as the receiver. Otherwise, allocate an object.
        if((ast_id(parent) == TK_ASSIGN) && (ast_id(sibling) == TK_EMBEDREF))
          args[0] = gen_fieldptr(c, sibling);
        else
          args[0] = gencall_alloc(c, &g);
        break;
      }

      case TK_BEREF:
      case TK_FUNREF:
        args[0] = gen_expr(c, receiver);
        break;

      default:
        assert(0);
        return NULL;
    }
  } else {
    // Use a null for the receiver type.
    args[0] = LLVMConstNull(g.use_type);
  }

  // Always emit location info for a call, to prevent inlining errors. This may
  // be disabled in dispatch_function, if the target function has no debug
  // info set.
  ast_setdebug(ast, true);
  dwarf_location(&c->dwarf, ast);

  // Static or virtual dispatch.
  LLVMValueRef func = dispatch_function(c, ast, &g, args[0], method_name,
    typeargs);

  LLVMValueRef r = NULL;

  if(func != NULL)
  {
    // If we can error out and we have an invoke target, generate an invoke
    // instead of a call.
    if(ast_canerror(ast) && (c->frame->invoke_target != NULL))
      r = invoke_fun(c, func, args, i, "", true);
    else
      r = codegen_call(c, func, args, i);
  }

  ponyint_pool_free_size(buf_size, args);
  ponyint_pool_free_size(buf_size, params);
  return r;
}
Exemplo n.º 27
0
static LLVMValueRef declare_ffi(compile_t* c, const char* f_name,
  gentype_t* g, ast_t* args, bool err)
{
  ast_t* last_arg = ast_childlast(args);

  if((last_arg != NULL) && (ast_id(last_arg) == TK_ELLIPSIS))
    return declare_ffi_vararg(c, f_name, g, err);

  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* f_params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  count = 0;

  ast_t* arg = ast_child(args);

  while(arg != NULL)
  {
    ast_t* p_type = ast_type(arg);

    if(p_type == NULL)
      p_type = ast_childidx(arg, 1);

    gentype_t param_g;

    if(!gentype(c, p_type, &param_g))
      return NULL;

    f_params[count++] = param_g.use_type;
    arg = ast_sibling(arg);
  }

  // We may have generated the function by generating a parameter type.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, f_name);

  if(func == NULL)
  {
    LLVMTypeRef r_type;

    if(g->underlying == TK_TUPLETYPE)
    {
      // Can't use the named type. Build an unnamed type with the same
      // elements.
      unsigned int count = LLVMCountStructElementTypes(g->use_type);
      size_t buf_size = count * sizeof(LLVMTypeRef);
      LLVMTypeRef* e_types = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
      LLVMGetStructElementTypes(g->use_type, e_types);
      r_type = LLVMStructTypeInContext(c->context, e_types, count, false);
      ponyint_pool_free_size(buf_size, e_types);
    } else {
      r_type = g->use_type;
    }

    LLVMTypeRef f_type = LLVMFunctionType(r_type, f_params, count, false);
    func = LLVMAddFunction(c->module, f_name, f_type);

    if(!err)
      LLVMAddFunctionAttr(func, LLVMNoUnwindAttribute);
  }

  ponyint_pool_free_size(buf_size, f_params);
  return func;
}
Exemplo n.º 28
0
LLVMValueRef gen_ffi(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, typeargs, args, named_args, can_err);
  bool err = (ast_id(can_err) == TK_QUESTION);

  // Get the function name, +1 to skip leading @
  const char* f_name = ast_name(id) + 1;

  // Generate the return type.
  ast_t* type = ast_type(ast);
  gentype_t g;

  // Emit dwarf location of ffi call
  dwarf_location(&c->dwarf, ast);

  if(!gentype(c, type, &g))
    return NULL;

  // Get the function.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, f_name);

  if(func == NULL)
  {
    // If we have no prototype, declare one.
    ast_t* decl = (ast_t*)ast_data(ast);

    if(decl != NULL)
    {
      // Define using the declared types.
      AST_GET_CHILDREN(decl, decl_id, decl_ret, decl_params, decl_err);
      err = (ast_id(decl_err) == TK_QUESTION);
      func = declare_ffi(c, f_name, &g, decl_params, err);
    } else if(!strncmp(f_name, "llvm.", 5)) {
      // Intrinsic, so use the exact types we supply.
      func = declare_ffi(c, f_name, &g, args, err);
    } else {
      // Make it varargs.
      func = declare_ffi_vararg(c, f_name, &g, err);
    }
  }

  // Generate the arguments.
  int count = (int)ast_childcount(args);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* f_args = (LLVMValueRef*)ponyint_pool_alloc_size(buf_size);

  LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func));
  LLVMTypeRef* f_params = NULL;
  bool vararg = (LLVMIsFunctionVarArg(f_type) != 0);

  if(!vararg)
  {
    f_params = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
    LLVMGetParamTypes(f_type, f_params);
  }

  ast_t* arg = ast_child(args);

  for(int i = 0; i < count; i++)
  {
    f_args[i] = gen_expr(c, arg);

    if(!vararg && (LLVMGetTypeKind(f_params[i]) == LLVMPointerTypeKind))
    {
      if(LLVMGetTypeKind(LLVMTypeOf(f_args[i])) == LLVMIntegerTypeKind)
        f_args[i] = LLVMBuildIntToPtr(c->builder, f_args[i], f_params[i], "");
      else
        f_args[i] = LLVMBuildBitCast(c->builder, f_args[i], f_params[i], "");
    }

    if(f_args[i] == NULL)
    {
      ponyint_pool_free_size(buf_size, f_args);
      return NULL;
    }

    arg = ast_sibling(arg);
  }

  // If we can error out and we have an invoke target, generate an invoke
  // instead of a call.
  LLVMValueRef result;

  if(err && (c->frame->invoke_target != NULL))
    result = invoke_fun(c, func, f_args, count, "", false);
  else
    result = LLVMBuildCall(c->builder, func, f_args, count, "");

  ponyint_pool_free_size(buf_size, f_args);

  if(!vararg)
    ponyint_pool_free_size(buf_size, f_params);

  // Special case a None return value, which is used for void functions.
  if(is_none(type))
    return g.instance;

  return result;
}
Exemplo n.º 29
0
Arquivo: gentype.c Projeto: nunb/ponyc
static bool make_struct(compile_t* c, gentype_t* g)
{
  LLVMTypeRef type;
  int extra = 0;

  if(g->underlying != TK_TUPLETYPE)
  {
    type = g->structure;

    if(g->underlying != TK_STRUCT)
      extra++;
  } else {
    type = g->primitive;
  }

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

  size_t buf_size = (g->field_count + extra) * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size);

  // Create the type descriptor as element 0.
  if(extra > 0)
    elements[0] = LLVMPointerType(g->desc_type, 0);

  // Create the actor pad as element 1.
  if(g->underlying == TK_ACTOR)
    elements[1] = c->actor_pad;

  // Get a preliminary type for each field and set the struct body. This is
  // needed in case a struct for the type being generated here is required when
  // generating a field.
  for(int i = 0; i < g->field_count; i++)
  {
    gentype_t field_g;
    bool ok;

    if((g->field_keys != NULL) && (g->field_keys[i] == TK_EMBED))
    {
      ok = gentype(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.structure;
    } else {
      ok = gentype_prelim(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.use_type;
    }

    if(!ok)
    {
      pool_free_size(buf_size, elements);
      return false;
    }
  }

  // An embedded field may have caused the current type to be fully generated
  // at this point. If so, finish gracefully.
  if(!LLVMIsOpaqueStruct(type))
  {
    g->done = true;
    return true;
  }

  LLVMStructSetBody(type, elements, g->field_count + extra, false);

  // Create a box type for tuples.
  if(g->underlying == TK_TUPLETYPE)
    make_box_type(c, g);

  pool_free_size(buf_size, elements);
  return true;
}
Exemplo n.º 30
0
LLVMValueRef gen_match(compile_t* c, ast_t* ast)
{
  bool needed = is_result_needed(ast);
  ast_t* type = ast_type(ast);
  AST_GET_CHILDREN(ast, match_expr, cases, else_expr);

  // We will have no type if all case have control types.
  gentype_t phi_type;

  if(needed && !is_control_type(type) && !gentype(c, type, &phi_type))
  {
    assert(0);
    return NULL;
  }

  ast_t* match_type = alias(ast_type(match_expr));
  LLVMValueRef match_value = gen_expr(c, match_expr);

  LLVMBasicBlockRef pattern_block = codegen_block(c, "case_pattern");
  LLVMBasicBlockRef else_block = codegen_block(c, "match_else");
  LLVMBasicBlockRef post_block = NULL;
  LLVMBasicBlockRef next_block = NULL;

  // Jump to the first case.
  LLVMBuildBr(c->builder, pattern_block);

  LLVMValueRef phi = GEN_NOVALUE;

  if(!is_control_type(type))
  {
    // Start the post block so that a case can modify the phi node.
    post_block = codegen_block(c, "match_post");
    LLVMPositionBuilderAtEnd(c->builder, post_block);

    if(needed)
      phi = LLVMBuildPhi(c->builder, phi_type.use_type, "");
    else
      phi = GEN_NOTNEEDED;
  }

  // Iterate over the cases.
  ast_t* the_case = ast_child(cases);

  while(the_case != NULL)
  {
    ast_t* next_case = ast_sibling(the_case);

    if(next_case != NULL)
      next_block = codegen_block(c, "case_pattern");
    else
      next_block = else_block;

    AST_GET_CHILDREN(the_case, pattern, guard, body);
    LLVMPositionBuilderAtEnd(c->builder, pattern_block);
    codegen_pushscope(c);

    ast_t* pattern_type = ast_type(pattern);
    bool ok = true;

    if(is_matchtype(match_type, pattern_type) != MATCHTYPE_ACCEPT)
    {
      // If there's no possible match, jump directly to the next block.
      LLVMBuildBr(c->builder, next_block);
    } else {
      // Check the pattern.
      ok = static_match(c, match_value, match_type, pattern, next_block);

      // Check the guard.
      ok = ok && guard_match(c, guard, next_block);

      // Case body.
      ok = ok && case_body(c, body, post_block, phi, phi_type.use_type);
    }

    codegen_popscope(c);

    if(!ok)
    {
      ast_free_unattached(match_type);
      return NULL;
    }

    the_case = next_case;
    pattern_block = next_block;
  }

  ast_free_unattached(match_type);

  // Else body.
  LLVMPositionBuilderAtEnd(c->builder, else_block);
  codegen_pushscope(c);
  bool ok = case_body(c, else_expr, post_block, phi, phi_type.use_type);
  codegen_popscope(c);

  if(!ok)
    return NULL;

  if(post_block != NULL)
    LLVMPositionBuilderAtEnd(c->builder, post_block);

  return phi;
}