static LLVMValueRef add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func) { LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4); LLVMTypeRef args[1] = { v4sf }; LLVMValueRef func = LLVMAddFunction(module, name, LLVMFunctionType(v4sf, args, 1, 0)); LLVMValueRef arg1 = LLVMGetParam(func, 0); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMValueRef ret; struct lp_build_context bld; bld.builder = builder; bld.type.floating = 1; bld.type.width = 32; bld.type.length = 4; LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); ret = lp_func(&bld, arg1); LLVMBuildRet(builder, ret); LLVMDisposeBuilder(builder); return func; }
int test_kal_codegen_function() { kal_named_value *val; unsigned int arg_count = 1; char **args = malloc(sizeof(char*) * arg_count); args[0] = "foo"; LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); kal_ast_node *prototype = kal_ast_prototype_create("my_func", args, arg_count); kal_ast_node *lhs = kal_ast_variable_create("foo"); kal_ast_node *rhs = kal_ast_number_create(20); kal_ast_node *body = kal_ast_binary_expr_create(KAL_BINOP_PLUS, lhs, rhs); kal_ast_node *node = kal_ast_function_create(prototype, body); kal_codegen_reset(); LLVMValueRef value = kal_codegen(node, module, builder); mu_assert(value != NULL, ""); mu_assert(LLVMGetNamedFunction(module, "my_func") == value, ""); mu_assert(LLVMCountParams(value) == 1, ""); val = kal_codegen_named_value("foo"); mu_assert(val->value == LLVMGetParam(value, 0), ""); mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 0))) == LLVMDoubleTypeKind, ""); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); kal_ast_node_free(node); return 0; }
void vm_state_destroy(struct vm_state *vm) { LLVMBasicBlockRef current_block, return_block; char *error; current_block = LLVMGetInsertBlock(vm->builder); return_block = LLVMInsertBasicBlock(current_block, "ret"); LLVMPositionBuilderAtEnd(vm->builder, current_block); LLVMBuildBr(vm->builder, return_block); LLVMPositionBuilderAtEnd(vm->builder, return_block); LLVMBuildRetVoid(vm->builder); LLVMMoveBasicBlockAfter(return_block, current_block); LLVMDumpModule(vm->module); error = NULL; LLVMVerifyModule(vm->module, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMDisposeBuilder(vm->builder); LLVMDisposeModule(vm->module); symbol_table_destroy(vm->symtab); }
int main(int argc, char const *argv[]) { LLVMModuleRef mod = LLVMModuleCreateWithName("sum"); LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), /* ret type */ param_types, /* arg types */ 2, /* arg count */ 0 /* is variadic */); LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); LLVMBuildRet(builder, tmp); char *error = NULL; LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMExecutionEngineRef engine; error = NULL; LLVMLinkInJIT(); LLVMInitializeNativeTarget(); if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { fprintf(stderr, "failed to create execution engine\n"); abort(); } if (error) { fprintf(stderr, "error: %s\n", error); LLVMDisposeMessage(error); exit(EXIT_FAILURE); } if (argc < 3) { fprintf(stderr, "usage: %s x y\n", argv[0]); exit(EXIT_FAILURE); } long long x = strtoll(argv[1], NULL, 10); long long y = strtoll(argv[2], NULL, 10); LLVMGenericValueRef args[] = { LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0), }; LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); // write bitcode to file if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) { fprintf(stderr, "error writing bitcode to file\n"); } LLVMDisposeBuilder(builder); LLVMDisposeExecutionEngine(engine); }
LLVMCompiledProgram LLVM_compile(ASTNode *node) { char *error = NULL; // Used to retrieve messages from functions LLVMLinkInJIT(); LLVMInitializeNativeTarget(); LLVMModuleRef mod = LLVMModuleCreateWithName("calc_module"); LLVMTypeRef program_args[] = { }; LLVMValueRef program = LLVMAddFunction(mod, "program", LLVMFunctionType(LLVMInt32Type(), program_args, 0, 0)); LLVMSetFunctionCallConv(program, LLVMCCallConv); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(program, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef res = LLVM_visit(node, builder); LLVMBuildRet(builder, res); LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); // Handler == LLVMAbortProcessAction -> No need to check errors LLVMDisposeBuilder(builder); return (LLVMCompiledProgram) { .module = mod, .function = program }; }
static void handle_line(char **tokens, int ntokens) { char *name = tokens[0]; LLVMValueRef param; LLVMValueRef res; LLVMModuleRef M = LLVMModuleCreateWithName(name); LLVMTypeRef I64ty = LLVMInt64Type(); LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); LLVMValueRef F = LLVMAddFunction(M, name, Fty); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); LLVMGetParams(F, ¶m); LLVMSetValueName(param, "in"); res = build_from_tokens(tokens + 1, ntokens - 1, builder, param); if (res) { char *irstr = LLVMPrintModuleToString(M); puts(irstr); LLVMDisposeMessage(irstr); } LLVMDisposeBuilder(builder); LLVMDisposeModule(M); }
SCM llvm_function_destroy(SCM scm_self) { struct llvm_function_t *self = get_llvm_function_no_check(scm_self); if (self->builder) { LLVMDisposeBuilder(self->builder); self->builder = NULL; }; return SCM_UNSPECIFIED; }
int main (void) { LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInitializeNativeTarget(); LLVMTypeRef funcType = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0); LLVMValueRef func = LLVMAddFunction(module, "main", funcType); LLVMSetLinkage(func, LLVMExternalLinkage); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, block); LLVMValueRef cond = LLVMBuildICmp(builder, LLVMIntNE, LLVMConstInt(LLVMInt32Type(), 2, 0), LLVMConstInt(LLVMInt32Type(), 1, 0), "ifcond"); LLVMValueRef owning_block = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); //TODO: WRONG?? //LLVMValueRef owning_block = LLVMBasicBlockAsValue(LLVMGetPreviousBasicBlock(LLVMGetInsertBlock(builder))); // 2. Generate new blocks for cases. LLVMBasicBlockRef then_ref = LLVMAppendBasicBlock(owning_block, "then"); LLVMBasicBlockRef else_ref = LLVMAppendBasicBlock(owning_block, "else"); LLVMBasicBlockRef merge_ref = LLVMAppendBasicBlock(owning_block, "ifmerge"); // 3. Branch conditionally on then or else. LLVMBuildCondBr(builder, cond, then_ref, else_ref); // 4. Build then branch prologue. LLVMPositionBuilderAtEnd(builder, then_ref); LLVMValueRef hi1 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp"); // 5. Connect then branch to merge block. LLVMBuildBr(builder, merge_ref); then_ref = LLVMGetInsertBlock(builder); // 6. Build else branch prologue. LLVMPositionBuilderAtEnd(builder, else_ref); LLVMValueRef hi2 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp2"); // 7. Connect else branch to merge block. LLVMBuildBr(builder, merge_ref); else_ref = LLVMGetInsertBlock(builder); // 8. Position ourselves after the merge block. LLVMPositionBuilderAtEnd(builder, merge_ref); // 9. Build the phi node. // LLVMValueRef phi = LLVMBuildPhi(builder, LLVMDoubleType(), "phi"); // 10. Add incoming edges. // LLVMAddIncoming(phi, &hi1, &then_ref, 1); // LLVMAddIncoming(phi, &hi2, &else_ref, 1); LLVMDumpModule(module); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); return 0; }
/** * Free gallivm object's LLVM allocations, but not the gallivm object itself. */ static void free_gallivm_state(struct gallivm_state *gallivm) { #if HAVE_LLVM >= 0x207 /* XXX or 0x208? */ /* This leads to crashes w/ some versions of LLVM */ LLVMModuleRef mod; char *error; if (gallivm->engine && gallivm->provider) LLVMRemoveModuleProvider(gallivm->engine, gallivm->provider, &mod, &error); #endif if (gallivm->passmgr) { LLVMDisposePassManager(gallivm->passmgr); } #if 0 /* XXX this seems to crash with all versions of LLVM */ if (gallivm->provider) LLVMDisposeModuleProvider(gallivm->provider); #endif if (HAVE_LLVM >= 0x207 && gallivm->engine) { /* This will already destroy any associated module */ LLVMDisposeExecutionEngine(gallivm->engine); } else { LLVMDisposeModule(gallivm->module); } #if !USE_MCJIT /* Don't free the TargetData, it's owned by the exec engine */ #else if (gallivm->target) { LLVMDisposeTargetData(gallivm->target); } #endif /* Never free the LLVM context. */ #if 0 if (gallivm->context) LLVMContextDispose(gallivm->context); #endif if (gallivm->builder) LLVMDisposeBuilder(gallivm->builder); gallivm->engine = NULL; gallivm->target = NULL; gallivm->module = NULL; gallivm->provider = NULL; gallivm->passmgr = NULL; gallivm->context = NULL; gallivm->builder = NULL; }
static void codegen_cleanup(compile_t* c) { while(c->frame != NULL) pop_frame(c); LLVMDisposeBuilder(c->builder); LLVMDisposeModule(c->module); LLVMContextDispose(c->context); LLVMDisposeTargetMachine(c->machine); reach_free(c->reachable); }
/** * Free gallivm object's LLVM allocations, but not the gallivm object itself. */ static void free_gallivm_state(struct gallivm_state *gallivm) { #if HAVE_LLVM >= 0x207 /* XXX or 0x208? */ /* This leads to crashes w/ some versions of LLVM */ LLVMModuleRef mod; char *error; if (gallivm->engine && gallivm->provider) LLVMRemoveModuleProvider(gallivm->engine, gallivm->provider, &mod, &error); #endif #if 0 /* XXX this seems to crash with all versions of LLVM */ if (gallivm->provider) LLVMDisposeModuleProvider(gallivm->provider); #endif if (gallivm->passmgr) LLVMDisposePassManager(gallivm->passmgr); #if HAVE_LLVM >= 0x207 if (gallivm->module) LLVMDisposeModule(gallivm->module); #endif #if 0 /* Don't free the exec engine, it's a global/singleton */ if (gallivm->engine) LLVMDisposeExecutionEngine(gallivm->engine); #endif #if 0 /* Don't free the TargetData, it's owned by the exec engine */ LLVMDisposeTargetData(gallivm->target); #endif if (gallivm->context) LLVMContextDispose(gallivm->context); if (gallivm->builder) LLVMDisposeBuilder(gallivm->builder); gallivm->engine = NULL; gallivm->target = NULL; gallivm->module = NULL; gallivm->provider = NULL; gallivm->passmgr = NULL; gallivm->context = NULL; gallivm->builder = NULL; }
static void codegen_cleanup(compile_t* c) { while(c->frame != NULL) pop_frame(c); LLVMDIBuilderDestroy(c->di); LLVMDisposeBuilder(c->builder); LLVMDisposeModule(c->module); LLVMContextDispose(c->context); LLVMDisposeTargetMachine(c->machine); tbaa_metadatas_free(c->tbaa_mds); reach_free(c->reach); }
/** * Like lp_build_alloca, but do not zero-initialize the variable. */ LLVMValueRef lp_build_alloca_undef(struct gallivm_state *gallivm, LLVMTypeRef type, const char *name) { LLVMBuilderRef first_builder = create_builder_at_entry(gallivm); LLVMValueRef res; res = LLVMBuildAlloca(first_builder, type, name); LLVMDisposeBuilder(first_builder); return res; }
int llvm_set_metadata(void) { LLVMBuilderRef b = LLVMCreateBuilder(); LLVMValueRef values[] = { LLVMConstInt(LLVMInt32Type(), 0, 0) }; // This used to trigger an assertion LLVMSetMetadata( LLVMBuildRetVoid(b), LLVMGetMDKindID("kind", 4), LLVMMDNode(values, 1)); LLVMDisposeBuilder(b); return 0; }
int test_kal_codegen_binary_expr() { LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); kal_ast_node *lhs = kal_ast_number_create(20); kal_ast_node *rhs = kal_ast_number_create(30); kal_ast_node *node = kal_ast_binary_expr_create(KAL_BINOP_PLUS, lhs, rhs); LLVMValueRef value = kal_codegen(node, module, builder); mu_assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMDoubleTypeKind, ""); mu_assert(LLVMIsConstant(value), ""); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); kal_ast_node_free(node); return 0; }
/** * Allocate a scalar (or vector) variable. * * Although not strictly part of control flow, control flow has deep impact in * how variables should be allocated. * * The mem2reg optimization pass is the recommended way to dealing with mutable * variables, and SSA. It looks for allocas and if it can handle them, it * promotes them, but only looks for alloca instructions in the entry block of * the function. Being in the entry block guarantees that the alloca is only * executed once, which makes analysis simpler. * * See also: * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory */ LLVMValueRef lp_build_alloca(struct gallivm_state *gallivm, LLVMTypeRef type, const char *name) { LLVMBuilderRef builder = gallivm->builder; LLVMBuilderRef first_builder = create_builder_at_entry(gallivm); LLVMValueRef res; res = LLVMBuildAlloca(first_builder, type, name); LLVMBuildStore(builder, LLVMConstNull(type), res); LLVMDisposeBuilder(first_builder); return res; }
static LLVMValueRef add_conv_test(LLVMModuleRef module, struct lp_type src_type, unsigned num_srcs, struct lp_type dst_type, unsigned num_dsts) { LLVMTypeRef args[2]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef dst_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef src[LP_MAX_VECTOR_LENGTH]; LLVMValueRef dst[LP_MAX_VECTOR_LENGTH]; unsigned i; args[0] = LLVMPointerType(lp_build_vec_type(src_type), 0); args[1] = LLVMPointerType(lp_build_vec_type(dst_type), 0); func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 2, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); dst_ptr = LLVMGetParam(func, 1); block = LLVMAppendBasicBlock(func, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); for(i = 0; i < num_srcs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, src_ptr, &index, 1, ""); src[i] = LLVMBuildLoad(builder, ptr, ""); } lp_build_conv(builder, src_type, dst_type, src, num_srcs, dst, num_dsts); for(i = 0; i < num_dsts; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, dst_ptr, &index, 1, ""); LLVMBuildStore(builder, dst[i], ptr); } LLVMBuildRetVoid(builder);; LLVMDisposeBuilder(builder); return func; }
int test_kal_codegen_prototype() { kal_named_value *val; unsigned int arg_count = 3; char **args = malloc(sizeof(char*) * arg_count); args[0] = "foo"; args[1] = "bar"; args[2] = "baz"; LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); kal_ast_node *node = kal_ast_prototype_create("my_func", args, 3); kal_codegen_reset(); LLVMValueRef value = kal_codegen(node, module, builder); mu_assert(value != NULL, ""); mu_assert(LLVMGetNamedFunction(module, "my_func") == value, ""); mu_assert(LLVMCountParams(value) == 3, ""); val = kal_codegen_named_value("foo"); mu_assert(val->value == LLVMGetParam(value, 0), ""); mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 0))) == LLVMDoubleTypeKind, ""); val = kal_codegen_named_value("bar"); mu_assert(val->value == LLVMGetParam(value, 1), ""); mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 1))) == LLVMDoubleTypeKind, ""); val = kal_codegen_named_value("baz"); mu_assert(val->value == LLVMGetParam(value, 2), ""); mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 2))) == LLVMDoubleTypeKind, ""); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); kal_ast_node_free(node); return 0; }
/** * Generate the runtime callable function for the whole fragment pipeline. * Note that the function which we generate operates on a block of 16 * pixels at at time. The block contains 2x2 quads. Each quad contains * 2x2 pixels. */ static void generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, struct lp_fragment_shader_variant *variant, unsigned partial_mask) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); const struct lp_fragment_shader_variant_key *key = &variant->key; char func_name[256]; struct lp_type fs_type; struct lp_type blend_type; LLVMTypeRef fs_elem_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef arg_types[11]; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; LLVMValueRef color_ptr_ptr; LLVMValueRef depth_ptr; LLVMValueRef mask_input; LLVMValueRef counter = NULL; LLVMBasicBlockRef block; LLVMBuilderRef builder; struct lp_build_sampler_soa *sampler; struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef function; LLVMValueRef facing; unsigned num_fs; unsigned i; unsigned chan; unsigned cbuf; /* TODO: actually pick these based on the fs and color buffer * characteristics. */ memset(&fs_type, 0, sizeof fs_type); fs_type.floating = TRUE; /* floating point values */ fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ fs_type.width = 32; /* 32-bit float */ fs_type.length = 4; /* 4 elements per vector */ num_fs = 4; /* number of quads per block */ memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ blend_type.sign = FALSE; /* values are unsigned */ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */ blend_type.width = 8; /* 8-bit ubyte values */ blend_type.length = 16; /* 16 elements per vector */ /* * Generate the function prototype. Any change here must be reflected in * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ fs_elem_type = lp_build_elem_type(fs_type); fs_int_vec_type = lp_build_int_vec_type(fs_type); blend_vec_type = lp_build_vec_type(blend_type); util_snprintf(func_name, sizeof(func_name), "fs%u_variant%u_%s", shader->no, variant->no, partial_mask ? "partial" : "whole"); arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ arg_types[3] = LLVMFloatType(); /* facing */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[6] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[7] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ arg_types[9] = LLVMInt32Type(); /* mask_input */ arg_types[10] = LLVMPointerType(LLVMInt32Type(), 0);/* counter */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); function = LLVMAddFunction(screen->module, func_name, func_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); variant->function[partial_mask] = function; /* XXX: need to propagate noalias down into color param now we are * passing a pointer-to-pointer? */ for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(function, i), LLVMNoAliasAttribute); context_ptr = LLVMGetParam(function, 0); x = LLVMGetParam(function, 1); y = LLVMGetParam(function, 2); facing = LLVMGetParam(function, 3); a0_ptr = LLVMGetParam(function, 4); dadx_ptr = LLVMGetParam(function, 5); dady_ptr = LLVMGetParam(function, 6); color_ptr_ptr = LLVMGetParam(function, 7); depth_ptr = LLVMGetParam(function, 8); mask_input = LLVMGetParam(function, 9); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); lp_build_name(y, "y"); lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); lp_build_name(color_ptr_ptr, "color_ptr_ptr"); lp_build_name(depth_ptr, "depth"); lp_build_name(mask_input, "mask_input"); if (key->occlusion_count) { counter = LLVMGetParam(function, 10); lp_build_name(counter, "counter"); } /* * Function body */ block = LLVMAppendBasicBlock(function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); /* * The shader input interpolation info is not explicitely baked in the * shader key, but everything it derives from (TGSI, and flatshade) is * already included in the shader key. */ lp_build_interp_soa_init(&interp, lp->num_inputs, lp->inputs, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x, y); /* code generated texture sampling */ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); /* loop over quads in the block */ for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS]; LLVMValueRef depth_ptr_i; if(i != 0) lp_build_interp_soa_update(&interp, i); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); generate_fs(lp, shader, key, builder, fs_type, context_ptr, i, &interp, sampler, &fs_mask[i], /* output */ out_color, depth_ptr_i, facing, partial_mask, mask_input, counter); for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) for(chan = 0; chan < NUM_CHANNELS; ++chan) fs_out_color[cbuf][chan][i] = out_color[cbuf][chan]; } sampler->destroy(sampler); /* Loop over color outputs / color buffers to do blending. */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { LLVMValueRef color_ptr; LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); LLVMValueRef blend_in_color[NUM_CHANNELS]; unsigned rt; /* * Convert the fs's output color and mask to fit to the blending type. */ for(chan = 0; chan < NUM_CHANNELS; ++chan) { lp_build_conv(builder, fs_type, blend_type, fs_out_color[cbuf][chan], num_fs, &blend_in_color[chan], 1); lp_build_name(blend_in_color[chan], "color%d.%c", cbuf, "rgba"[chan]); } if (partial_mask || !variant->opaque) { lp_build_conv_mask(builder, fs_type, blend_type, fs_mask, num_fs, &blend_mask, 1); } else { blend_mask = lp_build_const_int_vec(blend_type, ~0); } color_ptr = LLVMBuildLoad(builder, LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), ""); lp_build_name(color_ptr, "color_ptr%d", cbuf); /* which blend/colormask state to use */ rt = key->blend.independent_blend_enable ? cbuf : 0; /* * Blending. */ generate_blend(&key->blend, rt, builder, blend_type, context_ptr, blend_mask, blend_in_color, color_ptr); } #ifdef PIPE_ARCH_X86 /* Avoid corrupting the FPU stack on 32bit OSes. */ lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0); #endif LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); /* Verify the LLVM IR. If invalid, dump and abort */ #ifdef DEBUG if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { if (1) lp_debug_dump_value(function); abort(); } #endif /* Apply optimizations to LLVM IR */ LLVMRunFunctionPassManager(screen->pass, function); if (gallivm_debug & GALLIVM_DEBUG_IR) { /* Print the LLVM IR to stderr */ lp_debug_dump_value(function); debug_printf("\n"); } /* * Translate the LLVM IR into machine code. */ { void *f = LLVMGetPointerToGlobal(screen->engine, function); variant->jit_function[partial_mask] = (lp_jit_frag_func)pointer_to_func(f); if (gallivm_debug & GALLIVM_DEBUG_ASM) { lp_disassemble(f); } lp_func_delete_body(function); } }
/** * Generate the runtime callable function for the whole fragment pipeline. */ static struct lp_fragment_shader_variant * generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, const struct lp_fragment_shader_variant_key *key) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); struct lp_fragment_shader_variant *variant; struct lp_type fs_type; struct lp_type blend_type; LLVMTypeRef fs_elem_type; LLVMTypeRef fs_vec_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; LLVMTypeRef arg_types[9]; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; LLVMValueRef mask_ptr; LLVMValueRef color_ptr; LLVMValueRef depth_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef x0; LLVMValueRef y0; struct lp_build_sampler_soa *sampler; struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; unsigned num_fs; unsigned i; unsigned chan; #ifdef DEBUG tgsi_dump(shader->base.tokens, 0); if(key->depth.enabled) { debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format)); debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); debug_printf("depth.writemask = %u\n", key->depth.writemask); } if(key->alpha.enabled) { debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); } if(key->blend.logicop_enable) { debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); } else if(key->blend.blend_enable) { debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rgb_func, TRUE)); debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE)); debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE)); debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.alpha_func, TRUE)); debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE)); debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE)); } debug_printf("blend.colormask = 0x%x\n", key->blend.colormask); for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { if(key->sampler[i].format) { debug_printf("sampler[%u] = \n", i); debug_printf(" .format = %s\n", pf_name(key->sampler[i].format)); debug_printf(" .target = %s\n", debug_dump_tex_target(key->sampler[i].target, TRUE)); debug_printf(" .pot = %u %u %u\n", key->sampler[i].pot_width, key->sampler[i].pot_height, key->sampler[i].pot_depth); debug_printf(" .wrap = %s %s %s\n", debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); debug_printf(" .min_img_filter = %s\n", debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); debug_printf(" .min_mip_filter = %s\n", debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); debug_printf(" .mag_img_filter = %s\n", debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); if(key->sampler[i].compare_mode) debug_printf(" .compare_mode = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE)); debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); debug_printf(" .prefilter = %u\n", key->sampler[i].prefilter); } } #endif variant = CALLOC_STRUCT(lp_fragment_shader_variant); if(!variant) return NULL; variant->shader = shader; memcpy(&variant->key, key, sizeof *key); /* TODO: actually pick these based on the fs and color buffer * characteristics. */ memset(&fs_type, 0, sizeof fs_type); fs_type.floating = TRUE; /* floating point values */ fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ fs_type.width = 32; /* 32-bit float */ fs_type.length = 4; /* 4 element per vector */ num_fs = 4; memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ blend_type.sign = FALSE; /* values are unsigned */ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */ blend_type.width = 8; /* 8-bit ubyte values */ blend_type.length = 16; /* 16 elements per vector */ /* * Generate the function prototype. Any change here must be reflected in * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ fs_elem_type = lp_build_elem_type(fs_type); fs_vec_type = lp_build_vec_type(fs_type); fs_int_vec_type = lp_build_int_vec_type(fs_type); blend_vec_type = lp_build_vec_type(blend_type); blend_int_vec_type = lp_build_int_vec_type(blend_type); arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[6] = LLVMPointerType(fs_int_vec_type, 0); /* mask */ arg_types[7] = LLVMPointerType(blend_vec_type, 0); /* color */ arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); variant->function = LLVMAddFunction(screen->module, "shader", func_type); LLVMSetFunctionCallConv(variant->function, LLVMCCallConv); for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute); context_ptr = LLVMGetParam(variant->function, 0); x = LLVMGetParam(variant->function, 1); y = LLVMGetParam(variant->function, 2); a0_ptr = LLVMGetParam(variant->function, 3); dadx_ptr = LLVMGetParam(variant->function, 4); dady_ptr = LLVMGetParam(variant->function, 5); mask_ptr = LLVMGetParam(variant->function, 6); color_ptr = LLVMGetParam(variant->function, 7); depth_ptr = LLVMGetParam(variant->function, 8); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); lp_build_name(y, "y"); lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); lp_build_name(mask_ptr, "mask"); lp_build_name(color_ptr, "color"); lp_build_name(depth_ptr, "depth"); /* * Function body */ block = LLVMAppendBasicBlock(variant->function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); generate_pos0(builder, x, y, &x0, &y0); lp_build_interp_soa_init(&interp, shader->base.tokens, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x0, y0, 2, 0); #if 0 /* C texture sampling */ sampler = lp_c_sampler_soa_create(context_ptr); #else /* code generated texture sampling */ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); #endif for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef out_color[NUM_CHANNELS]; LLVMValueRef depth_ptr_i; if(i != 0) lp_build_interp_soa_update(&interp); fs_mask[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, mask_ptr, &index, 1, ""), ""); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); generate_fs(lp, shader, key, builder, fs_type, context_ptr, i, &interp, sampler, &fs_mask[i], out_color, depth_ptr_i); for(chan = 0; chan < NUM_CHANNELS; ++chan) fs_out_color[chan][i] = out_color[chan]; } sampler->destroy(sampler); /* * Convert the fs's output color and mask to fit to the blending type. */ for(chan = 0; chan < NUM_CHANNELS; ++chan) { lp_build_conv(builder, fs_type, blend_type, fs_out_color[chan], num_fs, &blend_in_color[chan], 1); lp_build_name(blend_in_color[chan], "color.%c", "rgba"[chan]); } lp_build_conv_mask(builder, fs_type, blend_type, fs_mask, num_fs, &blend_mask, 1); /* * Blending. */ generate_blend(&key->blend, builder, blend_type, context_ptr, blend_mask, blend_in_color, color_ptr); LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); /* * Translate the LLVM IR into machine code. */ if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { LLVMDumpValue(variant->function); abort(); } LLVMRunFunctionPassManager(screen->pass, variant->function); #ifdef DEBUG LLVMDumpValue(variant->function); debug_printf("\n"); #endif variant->jit_function = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, variant->function); #ifdef DEBUG lp_disassemble(variant->jit_function); #endif variant->next = shader->variants; shader->variants = variant; return variant; }
Output::~Output() { LLVMDisposeBuilder(m_builder); }
static LLVMValueRef get_stritem_len_fn(struct llvm_ctx *ctx) { if(ctx->stritem_len_fn != NULL) return ctx->stritem_len_fn; /* returns (i32 len, i32 new_tpos) * params (word *utcbptr, i32 tpos) * * when return value "new_tpos" > tmax + 1, the result is invalid. the function * should also not be called when tpos > tmax + 1. */ LLVMTypeRef ret_types[2] = { ctx->i32t, ctx->i32t }, parm_types[2] = { LLVMPointerType(ctx->wordt, 0), ctx->i32t }, ret_type = LLVMStructTypeInContext(ctx->ctx, ret_types, 2, 0), fn_type = LLVMFunctionType(ret_type, parm_types, 2, 0); LLVMValueRef fn = LLVMAddFunction(ctx->module, "__muidl_get_stritem_len", fn_type); LLVMSetVisibility(fn, LLVMHiddenVisibility); LLVMSetLinkage(fn, LLVMInternalLinkage); V fn_args[2]; LLVMGetParams(fn, fn_args); LLVMAddAttribute(fn_args[0], LLVMNoCaptureAttribute); for(int i=0; i<2; i++) { LLVMAddAttribute(fn_args[i], LLVMInRegAttribute); } ctx->stritem_len_fn = fn; LLVMBuilderRef old_builder = ctx->builder; ctx->builder = LLVMCreateBuilderInContext(ctx->ctx); LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "EntryBlock"), loop_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "loop"), valid_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "valid"), exit_bb = LLVMAppendBasicBlockInContext(ctx->ctx, fn, "exit"); LLVMPositionBuilderAtEnd(ctx->builder, entry_bb); LLVMValueRef old_utcb = ctx->utcb, old_tpos = ctx->tpos; ctx->utcb = fn_args[0]; ctx->tpos = fn_args[1]; LLVMBuildBr(ctx->builder, loop_bb); LLVMPositionBuilderAtEnd(ctx->builder, exit_bb); LLVMValueRef exit_len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "exit.len.phi"), exit_tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "exit.tpos.phi"); LLVMValueRef rvals[2] = { exit_len_phi, exit_tpos_phi }; LLVMBuildAggregateRet(ctx->builder, rvals, 2); LLVMPositionBuilderAtEnd(ctx->builder, loop_bb); LLVMValueRef len_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "len.phi"), tpos_phi = LLVMBuildPhi(ctx->builder, ctx->i32t, "tpos.phi"); LLVMAddIncoming(len_phi, &ctx->zero, &entry_bb, 1); LLVMAddIncoming(tpos_phi, &ctx->tpos, &entry_bb, 1); ctx->tpos = tpos_phi; /* test: if *tpos doesn't look like a string item, conk out. */ LLVMValueRef infoword = build_utcb_load(ctx, ctx->tpos, "si.info"); LLVMValueRef is_cond = LLVMBuildICmp(ctx->builder, LLVMIntEQ, ctx->zero, LLVMBuildAnd(ctx->builder, infoword, CONST_WORD(1 << 4), "infoword.si.mask"), "infoword.si.cond"); /* anything + 100 is sure to be > tmax + 1. */ LLVMValueRef fucked_tpos = LLVMBuildAdd(ctx->builder, tpos_phi, CONST_INT(100), "f****d.tpos"); branch_set_phi(ctx, exit_len_phi, len_phi); branch_set_phi(ctx, exit_tpos_phi, fucked_tpos); LLVMBuildCondBr(ctx->builder, is_cond, valid_bb, exit_bb); LLVMPositionBuilderAtEnd(ctx->builder, valid_bb); LLVMValueRef string_length = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildLShr(ctx->builder, infoword, CONST_INT(10), "si.info.len"), ctx->i32t, "si.info.len.int"), string_j = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildAnd(ctx->builder, CONST_WORD(0x1f), LLVMBuildLShr(ctx->builder, infoword, CONST_WORD(4), "si.info.j.shift"), "si.info.j.masked"), ctx->i32t, "si.info.j"), string_c = LLVMBuildTruncOrBitCast(ctx->builder, LLVMBuildAnd(ctx->builder, CONST_WORD(1 << 9), infoword, "si.info.c.masked"), ctx->i32t, "si.info.c.masked.int"), c_cond = LLVMBuildICmp(ctx->builder, LLVMIntNE, string_c, CONST_WORD(0), "si.info.c.cond"), new_len = LLVMBuildAdd(ctx->builder, len_phi, LLVMBuildMul(ctx->builder, string_length, LLVMBuildAdd(ctx->builder, string_j, CONST_INT(1), "j.plus.one"), "len.incr"), "len.new"), new_tpos = LLVMBuildAdd(ctx->builder, ctx->tpos, LLVMBuildSelect(ctx->builder, c_cond, LLVMBuildAdd(ctx->builder, CONST_INT(2), string_j, "cont.tpos.bump"), CONST_INT(2), "tpos.bump"), "tpos.new"); LLVMAddIncoming(len_phi, &new_len, &valid_bb, 1); LLVMAddIncoming(tpos_phi, &new_tpos, &valid_bb, 1); LLVMAddIncoming(exit_len_phi, &new_len, &valid_bb, 1); LLVMAddIncoming(exit_tpos_phi, &new_tpos, &valid_bb, 1); LLVMBuildCondBr(ctx->builder, c_cond, loop_bb, exit_bb); LLVMDisposeBuilder(ctx->builder); ctx->builder = old_builder; ctx->utcb = old_utcb; ctx->tpos = old_tpos; return ctx->stritem_len_fn; }
int main(int argc, char** argv) { llvm::llvm_shutdown_obj Y; llvm::error_code ec; std::string se; std::string file; if (argc < 2) { llvm::errs() << "Usage llvm-disasm <file>\n"; return 1; } llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); file = argv[1]; llvm::OwningPtr<llvm::object::Binary> bin; ec = llvm::object::createBinary(file, bin); if (ec) { llvm::errs() << file << ": " << ec.message() << "\n"; return 1; } if (!bin->isELF()) { llvm::errs() << file << " isn't an object file\n"; return 1; } llvm::object::ObjectFile* obj = llvm::dyn_cast<llvm::object::ObjectFile>(bin.get()); if (!obj) { llvm::errs() << file << ": failed to cast to llvm::ObjectFile\n"; return 1; } llvm::Triple tri; tri.setArch(llvm::Triple::ArchType(obj->getArch())); std::string targetName = tri.str(); const llvm::Target* target = llvm::TargetRegistry::lookupTarget(targetName, se); if (!target) { llvm::errs() << file << ": failed to get the target descriptor for " << targetName << "\n"; return 1; } STI = target->createMCSubtargetInfo(targetName, "", ""); if (!STI) { llvm::errs() << file << ": " << ": to get the subtarget info!\n"; return 1; } disasm = target->createMCDisassembler(*STI); if (!disasm) { llvm::errs() << file << ": " << ": to get the disassembler!\n"; return 1; } MII = target->createMCInstrInfo(); if (!MII) { llvm::errs() << file << ": no instruction info for target\n"; return 1; } MRI = target->createMCRegInfo(targetName); if (!MRI) { llvm::errs() << file << ": no register info for target\n"; return 1; } llvmBuilder = LLVMCreateBuilder(); LLVMModuleRef llvmModule = LLVMModuleCreateWithName("test"); LLVMTypeRef mainType = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0); LLVMValueRef mainFn = LLVMAddFunction(llvmModule, "main", mainType); LLVMBasicBlockRef blk = LLVMAppendBasicBlock(mainFn, ""); LLVMPositionBuilderAtEnd(llvmBuilder, blk); for (llvm::object::section_iterator i = obj->begin_sections(), e = obj->end_sections(); i != e; i.increment(ec)) { if (ec) { llvm::errs() << "Failed to increment the section iterator!\n"; return 1; } bool isText; llvm::StringRef secName; if (i->getName(secName)) { llvm::errs() << file << ": failed to get the section name\n"; break; } if (i->isText(isText)) { llvm::errs() << file << ": " << secName << ": failed to determine the section type\n"; break; } if (!isText) { continue; } std::set<llvm::object::SymbolRef> symbols; for (llvm::object::symbol_iterator isym = obj->begin_symbols(); isym != obj->end_symbols(); isym.increment(ec)) { bool res; llvm::StringRef symName; llvm::object::SymbolRef::Type symType; if (ec) { llvm::errs() << "Failed to increment the symbol iterator!\n"; return 1; } if (isym->getName(symName)) { llvm::errs() << file << ": " << secName << ": failed to get the symbol name!\n"; return 1; } /* uint64_t secSize, secBase, symAddr; i->getAddress(secBase); i->getSize(secSize); isym->getAddress(symAddr); if (i->containsSymbol(*isym, res)) { llvm::errs() << file << ": " << secName << ": " << symName << ": failed to check whether the symbol is in the section!\n"; return 1; } if (!res) { continue; } if (symAddr < secBase || symAddr >= secBase + secSize) { continue; } */ llvm::object::section_iterator i2 = llvm::object::section_iterator(llvm::object::SectionRef()); isym->getSection(i2); if (i2 != i) { continue; } if (isym->getType(symType)) { llvm::errs() << file << ": " << secName << ": " << symName << ": failed to get the symbol type!\n"; return 1; } if (symType != llvm::object::SymbolRef::ST_Function) { continue; } symbols.insert(*isym); } for (std::set<llvm::object::SymbolRef>::const_iterator isym = symbols.begin(); isym != symbols.end(); ++isym) { if (analyzeSymbol(*isym)) { return 1; } } } LLVMDumpModule(llvmModule); LLVMDisposeModule(llvmModule); LLVMDisposeBuilder(llvmBuilder); return 0; }
static LLVMValueRef add_blend_test(LLVMModuleRef module, const struct pipe_blend_state *blend, enum vector_mode mode, struct lp_type type) { LLVMTypeRef ret_type; LLVMTypeRef vec_type; LLVMTypeRef args[4]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef dst_ptr; LLVMValueRef const_ptr; LLVMValueRef res_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; ret_type = LLVMInt64Type(); vec_type = lp_build_vec_type(type); args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 4, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); dst_ptr = LLVMGetParam(func, 1); const_ptr = LLVMGetParam(func, 2); res_ptr = LLVMGetParam(func, 3); block = LLVMAppendBasicBlock(func, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); if (mode == AoS) { LLVMValueRef src; LLVMValueRef dst; LLVMValueRef con; LLVMValueRef res; src = LLVMBuildLoad(builder, src_ptr, "src"); dst = LLVMBuildLoad(builder, dst_ptr, "dst"); con = LLVMBuildLoad(builder, const_ptr, "const"); res = lp_build_blend_aos(builder, blend, type, src, dst, con, 3); lp_build_name(res, "res"); LLVMBuildStore(builder, res, res_ptr); } if (mode == SoA) { LLVMValueRef src[4]; LLVMValueRef dst[4]; LLVMValueRef con[4]; LLVMValueRef res[4]; unsigned i; for(i = 0; i < 4; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), ""); dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), ""); con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); lp_build_name(src[i], "src.%c", "rgba"[i]); lp_build_name(con[i], "con.%c", "rgba"[i]); lp_build_name(dst[i], "dst.%c", "rgba"[i]); } lp_build_blend_soa(builder, blend, type, src, dst, con, res); for(i = 0; i < 4; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); lp_build_name(res[i], "res.%c", "rgba"[i]); LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, "")); } } LLVMBuildRetVoid(builder);; LLVMDisposeBuilder(builder); return func; }
/** * Generate the runtime callable function for the whole fragment pipeline. * Note that the function which we generate operates on a block of 16 * pixels at at time. The block contains 2x2 quads. Each quad contains * 2x2 pixels. */ static void generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, struct lp_fragment_shader_variant *variant, unsigned do_tri_test) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); const struct lp_fragment_shader_variant_key *key = &variant->key; struct lp_type fs_type; struct lp_type blend_type; LLVMTypeRef fs_elem_type; LLVMTypeRef fs_vec_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; LLVMTypeRef arg_types[14]; LLVMTypeRef func_type; LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; LLVMValueRef color_ptr_ptr; LLVMValueRef depth_ptr; LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef x0; LLVMValueRef y0; struct lp_build_sampler_soa *sampler; struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; LLVMValueRef function; unsigned num_fs; unsigned i; unsigned chan; unsigned cbuf; /* TODO: actually pick these based on the fs and color buffer * characteristics. */ memset(&fs_type, 0, sizeof fs_type); fs_type.floating = TRUE; /* floating point values */ fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ fs_type.width = 32; /* 32-bit float */ fs_type.length = 4; /* 4 elements per vector */ num_fs = 4; /* number of quads per block */ memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ blend_type.sign = FALSE; /* values are unsigned */ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */ blend_type.width = 8; /* 8-bit ubyte values */ blend_type.length = 16; /* 16 elements per vector */ /* * Generate the function prototype. Any change here must be reflected in * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ fs_elem_type = lp_build_elem_type(fs_type); fs_vec_type = lp_build_vec_type(fs_type); fs_int_vec_type = lp_build_int_vec_type(fs_type); blend_vec_type = lp_build_vec_type(blend_type); blend_int_vec_type = lp_build_int_vec_type(blend_type); arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ arg_types[8] = LLVMInt32Type(); /* c0 */ arg_types[9] = LLVMInt32Type(); /* c1 */ arg_types[10] = LLVMInt32Type(); /* c2 */ /* Note: the step arrays are built as int32[16] but we interpret * them here as int32_vec4[4]. */ arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); function = LLVMAddFunction(screen->module, "shader", func_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); variant->function[do_tri_test] = function; /* XXX: need to propagate noalias down into color param now we are * passing a pointer-to-pointer? */ for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(function, i), LLVMNoAliasAttribute); context_ptr = LLVMGetParam(function, 0); x = LLVMGetParam(function, 1); y = LLVMGetParam(function, 2); a0_ptr = LLVMGetParam(function, 3); dadx_ptr = LLVMGetParam(function, 4); dady_ptr = LLVMGetParam(function, 5); color_ptr_ptr = LLVMGetParam(function, 6); depth_ptr = LLVMGetParam(function, 7); c0 = LLVMGetParam(function, 8); c1 = LLVMGetParam(function, 9); c2 = LLVMGetParam(function, 10); step0_ptr = LLVMGetParam(function, 11); step1_ptr = LLVMGetParam(function, 12); step2_ptr = LLVMGetParam(function, 13); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); lp_build_name(y, "y"); lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); lp_build_name(color_ptr_ptr, "color_ptr"); lp_build_name(depth_ptr, "depth"); lp_build_name(c0, "c0"); lp_build_name(c1, "c1"); lp_build_name(c2, "c2"); lp_build_name(step0_ptr, "step0"); lp_build_name(step1_ptr, "step1"); lp_build_name(step2_ptr, "step2"); /* * Function body */ block = LLVMAppendBasicBlock(function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); generate_pos0(builder, x, y, &x0, &y0); lp_build_interp_soa_init(&interp, shader->base.tokens, key->flatshade, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x0, y0); /* code generated texture sampling */ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); /* loop over quads in the block */ for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS]; LLVMValueRef depth_ptr_i; int cbuf; if(i != 0) lp_build_interp_soa_update(&interp, i); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); generate_fs(lp, shader, key, builder, fs_type, context_ptr, i, &interp, sampler, &fs_mask[i], /* output */ out_color, depth_ptr_i, do_tri_test, c0, c1, c2, step0_ptr, step1_ptr, step2_ptr); for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) for(chan = 0; chan < NUM_CHANNELS; ++chan) fs_out_color[cbuf][chan][i] = out_color[cbuf][chan]; } sampler->destroy(sampler); /* Loop over color outputs / color buffers to do blending. */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { LLVMValueRef color_ptr; LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); /* * Convert the fs's output color and mask to fit to the blending type. */ for(chan = 0; chan < NUM_CHANNELS; ++chan) { lp_build_conv(builder, fs_type, blend_type, fs_out_color[cbuf][chan], num_fs, &blend_in_color[chan], 1); lp_build_name(blend_in_color[chan], "color%d.%c", cbuf, "rgba"[chan]); } lp_build_conv_mask(builder, fs_type, blend_type, fs_mask, num_fs, &blend_mask, 1); color_ptr = LLVMBuildLoad(builder, LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), ""); lp_build_name(color_ptr, "color_ptr%d", cbuf); /* * Blending. */ generate_blend(&key->blend, builder, blend_type, context_ptr, blend_mask, blend_in_color, color_ptr); } LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); /* Verify the LLVM IR. If invalid, dump and abort */ #ifdef DEBUG if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { if (1) LLVMDumpValue(function); abort(); } #endif /* Apply optimizations to LLVM IR */ if (1) LLVMRunFunctionPassManager(screen->pass, function); if (LP_DEBUG & DEBUG_JIT) { /* Print the LLVM IR to stderr */ LLVMDumpValue(function); debug_printf("\n"); } /* * Translate the LLVM IR into machine code. */ variant->jit_function[do_tri_test] = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, function); if (LP_DEBUG & DEBUG_ASM) lp_disassemble(variant->jit_function[do_tri_test]); }