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; }
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); }
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; }
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); } }
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; }
// 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, ¶m); 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; }