Ejemplo n.º 1
0
static LLVMValueRef genfun_new(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs)
{
  ast_t* fun = get_fun(g, name, typeargs);
  LLVMValueRef func = get_prototype(c, g, name, typeargs, fun);

  if(func == NULL)
  {
    ast_free_unattached(fun);
    return NULL;
  }

  if(LLVMCountBasicBlocks(func) != 0)
  {
    ast_free_unattached(fun);
    return func;
  }

  codegen_startfun(c, func, ast_debug(fun));
  name_params(c, g->ast, ast_childidx(fun, 3), func);
  genfun_dwarf(c, g, name, typeargs, fun);

  if(!gen_field_init(c, g))
  {
    ast_free_unattached(fun);
    return NULL;
  }

  ast_t* body = ast_childidx(fun, 6);
  LLVMValueRef value = gen_expr(c, body);

  if(value == NULL)
  {
    ast_free_unattached(fun);
    return NULL;
  }

  genfun_dwarf_return(c, body);

  // Return 'this'.
  LLVMBuildRet(c->builder, LLVMGetParam(func, 0));
  codegen_finishfun(c);

  ast_free_unattached(fun);
  return func;
}
Ejemplo n.º 2
0
void codegen_startfun(compile_t* c, LLVMValueRef fun, LLVMMetadataRef file,
  LLVMMetadataRef scope)
{
  compile_frame_t* frame = push_frame(c);

  frame->fun = fun;
  frame->is_function = true;
  frame->di_file = file;
  frame->di_scope = scope;

  if(LLVMCountBasicBlocks(fun) == 0)
  {
    LLVMBasicBlockRef block = codegen_block(c, "entry");
    LLVMPositionBuilderAtEnd(c->builder, block);
  }

  LLVMSetCurrentDebugLocation2(c->builder, 0, 0, NULL);
}
Ejemplo n.º 3
0
Archivo: genfun.c Proyecto: fydot/ponyc
static LLVMValueRef genfun_fun(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs)
{
  ast_t* fun = get_fun(g, name, typeargs);
  LLVMValueRef func = get_prototype(c, g, name, typeargs, fun);

  if(func == NULL)
  {
    ast_free_unattached(fun);
    return NULL;
  }

  if(LLVMCountBasicBlocks(func) != 0)
  {
    ast_free_unattached(fun);
    return func;
  }

  codegen_startfun(c, func, ast_debug(fun));
  name_params(c, g->ast, ast_childidx(fun, 3), func);
  genfun_dwarf(c, g, name, typeargs, fun);

  ast_t* body = ast_childidx(fun, 6);
  LLVMValueRef value = gen_expr(c, body);

  if(value == NULL)
  {
    ast_free_unattached(fun);
    return NULL;
  } else if(value != GEN_NOVALUE) {
    genfun_dwarf_return(c, body);

    LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func));
    LLVMTypeRef r_type = LLVMGetReturnType(f_type);

    LLVMValueRef ret = gen_assign_cast(c, r_type, value, ast_type(body));
    LLVMBuildRet(c->builder, ret);
  }

  codegen_finishfun(c);
  ast_free_unattached(fun);

  return func;
}
Ejemplo n.º 4
0
Archivo: codegen.c Proyecto: dckc/ponyc
void codegen_startfun(compile_t* c, LLVMValueRef fun, bool has_source)
{
  compile_frame_t* frame = push_frame(c);

  frame->fun = fun;
  frame->restore_builder = LLVMGetInsertBlock(c->builder);
  frame->has_source = has_source;
  frame->is_function = true;
  c->dwarf.has_source = has_source;

  // Reset debug locations
  dwarf_location(&c->dwarf, NULL);

  if(LLVMCountBasicBlocks(fun) == 0)
  {
    LLVMBasicBlockRef block = codegen_block(c, "entry");
    LLVMPositionBuilderAtEnd(c->builder, block);
  }
}
Ejemplo n.º 5
0
int module_list_functions(void) {
  LLVMModuleRef M = load_module(false, false);
  LLVMValueRef f;

  f = LLVMGetFirstFunction(M);
  while (f) {
    if (LLVMIsDeclaration(f)) {
      printf("FunctionDeclaration: %s\n", LLVMGetValueName(f));
    } else {
      LLVMBasicBlockRef bb;
      LLVMValueRef isn;
      unsigned nisn = 0;
      unsigned nbb = 0;

      printf("FunctionDefinition: %s [#bb=%u]\n", LLVMGetValueName(f),
             LLVMCountBasicBlocks(f));

      for (bb = LLVMGetFirstBasicBlock(f); bb;
           bb = LLVMGetNextBasicBlock(bb)) {
        nbb++;
        for (isn = LLVMGetFirstInstruction(bb); isn;
             isn = LLVMGetNextInstruction(isn)) {
          nisn++;
          if (LLVMIsACallInst(isn)) {
            LLVMValueRef callee =
                LLVMGetOperand(isn, LLVMGetNumOperands(isn) - 1);
            printf(" calls: %s\n", LLVMGetValueName(callee));
          }
        }
      }
      printf(" #isn: %u\n", nisn);
      printf(" #bb: %u\n\n", nbb);
    }
    f = LLVMGetNextFunction(f);
  }

  LLVMDisposeModule(M);

  return 0;
}
Ejemplo n.º 6
0
// Generates the function prototype but overrides the name. This is used by
// the metadata to create external APIs to C.
//
// node          - The node.
// module        - The compilation unit this node is a part of.
// function_name - The name of the function to generate.
// is_external   - A flag stating if this is an external prototype.
// value         - A pointer to where the LLVM value should be returned to.
//
// Returns 0 if successful, otherwise returns -1.
int qip_ast_function_codegen_prototype_with_name(qip_ast_node *node,
                                                 qip_module *module,
                                                 bstring function_name,
                                                 bool is_external,
                                                 LLVMValueRef *value)
{
    int rc;
    unsigned int i;
    LLVMValueRef func = NULL;
    bstring arg_type_name = NULL;
    bstring return_type_name = NULL;

    LLVMContextRef context = LLVMGetModuleContext(module->llvm_module);

    // Determine the number of arguments. External calls always have an
    // additional first argument that is the module reference.
    unsigned int offset = (is_external ? 1 : 0);
    unsigned int total_arg_count = node->function.arg_count + offset;

    // Check for an existing prototype.
    func = LLVMGetNamedFunction(module->llvm_module, bdata(function_name));
    
    // If a prototype exists then simply verify it matches and return it.
    if(func != NULL) {
        check(LLVMCountBasicBlocks(func) == 0, "Illegal function redefinition");
        check(LLVMCountParams(func) == total_arg_count, "Function prototype already exists with different arguments");
    }
    // If there is no prototype then create one.
    else {
        // Dynamically generate the return type of the function if it is missing.
        if(node->function.return_type == NULL) {
            rc = qip_ast_function_generate_return_type(node, module);
            check(rc == 0, "Unable to generate return type for function");
        }

        // Create a list of function argument types.
        qip_ast_node *arg;
        LLVMTypeRef *params = malloc(sizeof(LLVMTypeRef) * total_arg_count);

        // Create module argument for external calls.
        if(is_external) {
            params[0] = LLVMPointerType(LLVMInt8TypeInContext(context), 0);
        }

        // Create arguments.
        for(i=0; i<node->function.arg_count; i++) {
            qip_ast_node *arg = node->function.args[i];
            LLVMTypeRef param = NULL;
            rc = qip_module_get_type_ref(module, arg->farg.var_decl->var_decl.type, NULL, &param);
            check(rc == 0, "Unable to determine function argument type");
        
            // Pass argument as reference if this is a complex type.
            if(qip_module_is_complex_type(module, param)) {
                params[i+offset] = LLVMPointerType(param, 0);
            }
            // Otherwise pass it by value.
            else {
                params[i+offset] = param;
            }
        }

        // Determine return type.
        LLVMTypeRef return_type;
        rc = qip_module_get_type_ref(module, node->function.return_type, NULL, &return_type);
        check(rc == 0, "Unable to determine function return type");

        if(qip_module_is_complex_type(module, return_type)) {
            return_type = LLVMPointerType(return_type, 0);
        }

        // Create function type.
        LLVMTypeRef funcType = LLVMFunctionType(return_type, params, total_arg_count, false);
        check(funcType != NULL, "Unable to create function type");

        // Create function.
        func = LLVMAddFunction(module->llvm_module, bdata(function_name), funcType);
        check(func != NULL, "Unable to create function");
    
        // Assign module argument name.
        if(is_external) {
            LLVMSetValueName(LLVMGetParam(func, 0), "module");
        }
    
        // Assign names to function arguments.
        for(i=0; i<node->function.arg_count; i++) {
            arg = node->function.args[i];
            LLVMValueRef param = LLVMGetParam(func, i+offset);
            LLVMSetValueName(param, bdata(arg->farg.var_decl->var_decl.name));
        }
    }
    
    // Return function prototype;
    *value = func;
    
    bdestroy(arg_type_name);
    bdestroy(return_type_name);
    return 0;

error:
    bdestroy(arg_type_name);
    bdestroy(return_type_name);
    if(func) LLVMDeleteFunction(func);
    *value = NULL;
    return -1;
}