LLVMModuleRef radeon_llvm_get_kernel_module(LLVMContextRef ctx, unsigned index, const char *bitcode, unsigned bitcode_len) { LLVMModuleRef mod; unsigned num_kernels; LLVMValueRef *kernel_metadata; unsigned i; mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len); num_kernels = LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels"); kernel_metadata = MALLOC(num_kernels * sizeof(LLVMValueRef)); LLVMGetNamedMetadataOperands(mod, "opencl.kernels", kernel_metadata); for (i = 0; i < num_kernels; i++) { LLVMValueRef kernel_signature, *kernel_function; unsigned num_kernel_md_operands; if (i == index) { continue; } kernel_signature = kernel_metadata[i]; num_kernel_md_operands = LLVMGetMDNodeNumOperands(kernel_signature); kernel_function = MALLOC(num_kernel_md_operands * sizeof (LLVMValueRef)); LLVMGetMDNodeOperands(kernel_signature, kernel_function); LLVMDeleteFunction(*kernel_function); FREE(kernel_function); } FREE(kernel_metadata); radeon_llvm_optimize(mod); return mod; }
void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); struct lp_fragment_shader *shader = fs; struct lp_fragment_shader_variant *variant; assert(fs != llvmpipe->fs); variant = shader->variants; while(variant) { struct lp_fragment_shader_variant *next = variant->next; if(variant->function) { if(variant->jit_function) LLVMFreeMachineCodeForFunction(screen->engine, variant->function); LLVMDeleteFunction(variant->function); } FREE(variant); variant = next; } FREE((void *) shader->base.tokens); FREE(shader); }
static void remove_shader_variant(struct llvmpipe_context *lp, struct lp_fragment_shader_variant *variant) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); unsigned i; if (gallivm_debug & GALLIVM_DEBUG_IR) { debug_printf("llvmpipe: del fs #%u var #%u v created #%u v cached #%u v total cached #%u\n", variant->shader->no, variant->no, variant->shader->variants_created, variant->shader->variants_cached, lp->nr_fs_variants); } for (i = 0; i < Elements(variant->function); i++) { if (variant->function[i]) { if (variant->jit_function[i]) LLVMFreeMachineCodeForFunction(screen->engine, variant->function[i]); LLVMDeleteFunction(variant->function[i]); } } remove_from_list(&variant->list_item_local); variant->shader->variants_cached--; remove_from_list(&variant->list_item_global); lp->nr_fs_variants--; FREE(variant); }
static bool make_trace(compile_t* c, gentype_t* g) { // Do nothing if we have no fields. if(g->field_count == 0) return true; if(g->underlying == TK_CLASS) { // Special case the array trace function. AST_GET_CHILDREN(g->ast, pkg, id); const char* package = ast_name(pkg); const char* name = ast_name(id); if((package == c->str_builtin) && (name == c->str_Array)) { genprim_array_trace(c, g); return true; } } // Create a trace function. const char* trace_name = genname_trace(g->type_name); LLVMValueRef trace_fn = codegen_addfun(c, trace_name, c->trace_type); codegen_startfun(c, trace_fn, false); LLVMSetFunctionCallConv(trace_fn, LLVMCCallConv); LLVMValueRef ctx = LLVMGetParam(trace_fn, 0); LLVMValueRef arg = LLVMGetParam(trace_fn, 1); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, g->structure_ptr, "object"); // If we don't ever trace anything, delete this function. int extra = 0; // Non-structs have a type descriptor. if(g->underlying != TK_STRUCT) extra++; // Actors have a pad. if(g->underlying == TK_ACTOR) extra++; bool need_trace = trace_fields(c, g, ctx, object, extra); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); if(!need_trace) LLVMDeleteFunction(trace_fn); return true; }
/** * Free the function (and its machine code). */ void gallivm_free_function(struct gallivm_state *gallivm, LLVMValueRef func, const void *code) { #if !USE_MCJIT if (code) { LLVMFreeMachineCodeForFunction(gallivm->engine, func); } LLVMDeleteFunction(func); #endif }
void JITImpl::reclaimUnreachableFunctions(JITCoreInfo &coreInfo) { std::vector<uint32_t> &unreachableFunctions = coreInfo.unreachableFunctions; std::map<uint32_t,JITFunctionInfo*> &functionMap = coreInfo.functionMap; for (std::vector<uint32_t>::iterator it = unreachableFunctions.begin(), e = unreachableFunctions.end(); it != e; ++it) { std::map<uint32_t,JITFunctionInfo*>::iterator entry = functionMap.find(*it); if (entry == functionMap.end()) continue; LLVMValueRef value = entry->second->value; LLVMFreeMachineCodeForFunction(executionEngine, value); LLVMReplaceAllUsesWith(value, LLVMGetUndef(LLVMTypeOf(value))); LLVMDeleteFunction(value); delete entry->second; functionMap.erase(entry); } unreachableFunctions.clear(); }
void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); struct lp_fragment_shader *shader = fs; struct lp_fragment_shader_variant *variant; assert(fs != llvmpipe->fs); (void) llvmpipe; /* * XXX: we need to flush the context until we have some sort of reference * counting in fragment shaders as they may still be binned */ draw_flush(llvmpipe->draw); lp_setup_flush(llvmpipe->setup, 0); variant = shader->variants; while(variant) { struct lp_fragment_shader_variant *next = variant->next; unsigned i; for (i = 0; i < Elements(variant->function); i++) { if (variant->function[i]) { if (variant->jit_function[i]) LLVMFreeMachineCodeForFunction(screen->engine, variant->function[i]); LLVMDeleteFunction(variant->function[i]); } } FREE(variant); variant = next; } FREE((void *) shader->base.tokens); FREE(shader); }
static bool make_trace(compile_t* c, gentype_t* g) { // Do nothing if we have no fields. if(g->field_count == 0) return true; if(g->underlying == TK_CLASS) { // Special case the array trace function. AST_GET_CHILDREN(g->ast, pkg, id); const char* package = ast_name(pkg); const char* name = ast_name(id); if((package == c->str_1) && (name == c->str_Array)) { genprim_array_trace(c, g); return true; } } // Create a trace function. const char* trace_name = genname_trace(g->type_name); LLVMValueRef trace_fn = codegen_addfun(c, trace_name, c->trace_type); codegen_startfun(c, trace_fn, false); LLVMSetFunctionCallConv(trace_fn, LLVMCCallConv); LLVMValueRef arg = LLVMGetParam(trace_fn, 0); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, g->structure_ptr, "object"); // If we don't ever trace anything, delete this function. bool need_trace; if(g->underlying == TK_TUPLETYPE) { // Create another function that traces the tuple members. const char* trace_tuple_name = genname_tracetuple(g->type_name); LLVMTypeRef trace_tuple_type = LLVMFunctionType(c->void_type, &g->primitive, 1, false); LLVMValueRef trace_tuple_fn = codegen_addfun(c, trace_tuple_name, trace_tuple_type); codegen_startfun(c, trace_tuple_fn, false); LLVMSetFunctionCallConv(trace_tuple_fn, LLVMCCallConv); LLVMValueRef arg = LLVMGetParam(trace_tuple_fn, 0); need_trace = trace_elements(c, g, arg); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); if(need_trace) { // Get the tuple primitive. LLVMValueRef tuple_ptr = LLVMBuildStructGEP(c->builder, object, 1, ""); LLVMValueRef tuple = LLVMBuildLoad(c->builder, tuple_ptr, ""); // Call the tuple trace function with the unboxed primitive type. LLVMBuildCall(c->builder, trace_tuple_fn, &tuple, 1, ""); } else { LLVMDeleteFunction(trace_tuple_fn); } } else { int extra = 1; // Actors have a pad. if(g->underlying == TK_ACTOR) extra++; need_trace = trace_fields(c, g, object, extra); } LLVMBuildRetVoid(c->builder); codegen_finishfun(c); if(!need_trace) LLVMDeleteFunction(trace_fn); return true; }
// 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; }