+ gallivm_destroy(variant->gallivm);
+
+ remove_from_list(&variant->list_item_local);
+ variant->shader->variants_cached--;
+ remove_from_list(&variant->list_item_global);
+ llvm->nr_variants--;
+ FREE(variant);
+}
+
+
+/**
+ * Create LLVM types for various structures.
+ */
+static void
+create_gs_jit_types(struct draw_gs_llvm_variant *var)
+{
+ struct gallivm_state *gallivm = var->gallivm;
+ LLVMTypeRef texture_type, sampler_type, context_type;
+
+ texture_type = create_jit_texture_type(gallivm, "texture");
+ sampler_type = create_jit_sampler_type(gallivm, "sampler");
+
+ context_type = create_gs_jit_context_type(gallivm,
+ var->shader->base.vector_length,
+ texture_type, sampler_type,
+ "draw_gs_jit_context");
+ var->context_ptr_type = LLVMPointerType(context_type, 0);
+
+ var->input_array_type = create_gs_jit_input_type(gallivm);
+}
+
+static LLVMTypeRef
+get_gs_context_ptr_type(struct draw_gs_llvm_variant *variant)
+{
+ if (!variant->context_ptr_type)
+ create_gs_jit_types(variant);
+ return variant->context_ptr_type;
+}
+
+static LLVMValueRef
+generate_mask_value(struct draw_gs_llvm_variant *variant,
+ struct lp_type gs_type)
+{
+ struct gallivm_state *gallivm = variant->gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ struct lp_type mask_type = lp_int_type(gs_type);
+ LLVMValueRef num_prims;
+ LLVMValueRef mask_val = lp_build_const_vec(gallivm, mask_type, 0);
+ unsigned i;
+
+ num_prims = lp_build_broadcast(gallivm, lp_build_vec_type(gallivm, mask_type),
+ variant->num_prims);
+ for (i = 0; i < gs_type.length; i++) {
+ LLVMValueRef idx = lp_build_const_int32(gallivm, i);
+ mask_val = LLVMBuildInsertElement(builder, mask_val, idx, idx, "");
+ }
+ mask_val = lp_build_compare(gallivm, mask_type,
+ PIPE_FUNC_GREATER, num_prims, mask_val);
+
+ return mask_val;
+}
+
+static void
+draw_gs_llvm_generate(struct draw_llvm *llvm,
+ struct draw_gs_llvm_variant *variant)
+{
+ struct gallivm_state *gallivm = variant->gallivm;
+ LLVMContextRef context = gallivm->context;
+ LLVMTypeRef int32_type = LLVMInt32TypeInContext(context);
+ LLVMTypeRef arg_types[7];
+ LLVMTypeRef func_type;
+ LLVMValueRef variant_func;
+ LLVMValueRef context_ptr;
+ LLVMValueRef prim_id_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+ LLVMValueRef io_ptr, input_array, num_prims, mask_val;
+ struct lp_build_sampler_soa *sampler = 0;
+ struct lp_build_context bld;
+ struct lp_bld_tgsi_system_values system_values;
+ char func_name[64];
+ struct lp_type gs_type;
+ unsigned i;
+ struct draw_gs_llvm_iface gs_iface;
+ const struct tgsi_token *tokens = variant->shader->base.state.tokens;
+ LLVMValueRef consts_ptr, num_consts_ptr;
+ LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
+ struct lp_build_mask_context mask;
+ const struct tgsi_shader_info *gs_info = &variant->shader->base.info;
+ unsigned vector_length = variant->shader->base.vector_length;
+
+ memset(&system_values, 0, sizeof(system_values));
+
+ util_snprintf(func_name, sizeof(func_name), "draw_llvm_gs_variant%u",
+ variant->shader->variants_cached);
+
+ assert(variant->vertex_header_ptr_type);
+
+ arg_types[0] = get_gs_context_ptr_type(variant); /* context */
+ arg_types[1] = variant->input_array_type; /* input */
+ arg_types[2] = variant->vertex_header_ptr_type; /* vertex_header */
+ arg_types[3] = int32_type; /* num_prims */
+ arg_types[4] = int32_type; /* instance_id */
+ arg_types[5] = LLVMPointerType(
+ LLVMVectorType(int32_type, vector_length), 0); /* prim_id_ptr */
+ arg_types[6] = int32_type;
+
+ func_type = LLVMFunctionType(int32_type, arg_types, ARRAY_SIZE(arg_types), 0);
+
+ variant_func = LLVMAddFunction(gallivm->module, func_name, func_type);
+
+ variant->function = variant_func;
+
+ LLVMSetFunctionCallConv(variant_func, LLVMCCallConv);
+
+ for (i = 0; i < ARRAY_SIZE(arg_types); ++i)
+ if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
+ LLVMAddAttribute(LLVMGetParam(variant_func, i),
+ LLVMNoAliasAttribute);
+
+ context_ptr = LLVMGetParam(variant_func, 0);
+ input_array = LLVMGetParam(variant_func, 1);
+ io_ptr = LLVMGetParam(variant_func, 2);
+ num_prims = LLVMGetParam(variant_func, 3);
+ system_values.instance_id = LLVMGetParam(variant_func, 4);
+ prim_id_ptr = LLVMGetParam(variant_func, 5);
+ system_values.invocation_id = LLVMGetParam(variant_func, 6);
+
+ lp_build_name(context_ptr, "context");
+ lp_build_name(input_array, "input");
+ lp_build_name(io_ptr, "io");
+ lp_build_name(num_prims, "num_prims");
+ lp_build_name(system_values.instance_id, "instance_id");
+ lp_build_name(prim_id_ptr, "prim_id_ptr");
+ lp_build_name(system_values.invocation_id, "invocation_id");
+
+ variant->context_ptr = context_ptr;
+ variant->io_ptr = io_ptr;
+ variant->num_prims = num_prims;
+
+ gs_iface.base.fetch_input = draw_gs_llvm_fetch_input;
+ gs_iface.base.emit_vertex = draw_gs_llvm_emit_vertex;
+ gs_iface.base.end_primitive = draw_gs_llvm_end_primitive;
+ gs_iface.base.gs_epilogue = draw_gs_llvm_epilogue;
+ gs_iface.input = input_array;
+ gs_iface.variant = variant;
+
+ /*
+ * Function body
+ */
+
+ block = LLVMAppendBasicBlockInContext(gallivm->context, variant_func, "entry");
+ builder = gallivm->builder;
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ lp_build_context_init(&bld, gallivm, lp_type_int(32));
+
+ memset(&gs_type, 0, sizeof gs_type);
+ gs_type.floating = TRUE; /* floating point values */
+ gs_type.sign = TRUE; /* values are signed */
+ gs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */
+ gs_type.width = 32; /* 32-bit float */
+ gs_type.length = vector_length;
+
+ consts_ptr = draw_gs_jit_context_constants(variant->gallivm, context_ptr);
+ num_consts_ptr =
+ draw_gs_jit_context_num_constants(variant->gallivm, context_ptr);
+
+ /* code generated texture sampling */
+ sampler = draw_llvm_sampler_soa_create(variant->key.samplers);
+
+ mask_val = generate_mask_value(variant, gs_type);
+ lp_build_mask_begin(&mask, gallivm, gs_type, mask_val);
+
+ if (gs_info->uses_primid) {
+ system_values.prim_id = LLVMBuildLoad(builder, prim_id_ptr, "prim_id");