static void kill_if_fetch_args(struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { const struct tgsi_full_instruction *inst = emit_data->inst; struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; unsigned i; LLVMValueRef conds[TGSI_NUM_CHANNELS]; for (i = 0; i < TGSI_NUM_CHANNELS; i++) { LLVMValueRef value = lp_build_emit_fetch(bld_base, inst, 0, i); conds[i] = LLVMBuildFCmp(builder, LLVMRealOLT, value, bld_base->base.zero, ""); } /* Or the conditions together */ for (i = TGSI_NUM_CHANNELS - 1; i > 0; i--) { conds[i - 1] = LLVMBuildOr(builder, conds[i], conds[i - 1], ""); } emit_data->dst_type = LLVMVoidTypeInContext(gallivm->context); emit_data->arg_count = 1; emit_data->args[0] = LLVMBuildSelect(builder, conds[0], lp_build_const_float(gallivm, -1.0f), bld_base->base.zero, ""); }
static void llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); struct lp_build_context * base = &bld_base->base; unsigned i; /* Add the necessary export instructions */ for (i = 0; i < ctx->output_reg_count; i++) { unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { LLVMValueRef output; LLVMValueRef store_output; unsigned adjusted_reg_idx = i + ctx->reserved_reg_count; LLVMValueRef reg_index = lp_build_const_int32( base->gallivm, radeon_llvm_reg_index_soa(adjusted_reg_idx, chan)); output = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][chan], ""); store_output = lp_build_intrinsic_binary( base->gallivm->builder, "llvm.AMDGPU.store.output", base->elem_type, output, reg_index); lp_build_intrinsic_unary(base->gallivm->builder, "llvm.AMDGPU.export.reg", LLVMVoidTypeInContext(base->gallivm->context), store_output); } } }
static LLVMValueRef add_printf_test(struct gallivm_state *gallivm) { LLVMModuleRef module = gallivm->module; LLVMTypeRef args[1] = { LLVMIntTypeInContext(gallivm->context, 32) }; LLVMValueRef func = LLVMAddFunction(module, "test_printf", LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context), args, 1, 0)); LLVMBuilderRef builder = gallivm->builder; LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(gallivm->context, func, "entry"); LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); lp_build_printf(gallivm, "hello, world\n"); lp_build_printf(gallivm, "print 5 6: %d %d\n", LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 5, 0), LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 6, 0)); /* Also test lp_build_assert(). This should not fail. */ lp_build_assert(gallivm, LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 1, 0), "assert(1)"); LLVMBuildRetVoid(builder); gallivm_verify_function(gallivm, func); return func; }
static LLVMValueRef add_blend_test(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, struct lp_type type) { LLVMModuleRef module = gallivm->module; LLVMContextRef context = gallivm->context; LLVMTypeRef vec_type; LLVMTypeRef args[5]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef src1_ptr; LLVMValueRef dst_ptr; LLVMValueRef const_ptr; LLVMValueRef res_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; const enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; const unsigned rt = 0; const unsigned char swizzle[4] = { 0, 1, 2, 3 }; LLVMValueRef src; LLVMValueRef src1; LLVMValueRef dst; LLVMValueRef con; LLVMValueRef res; vec_type = lp_build_vec_type(gallivm, type); args[4] = args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidTypeInContext(context), args, 5, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); src1_ptr = LLVMGetParam(func, 1); dst_ptr = LLVMGetParam(func, 2); const_ptr = LLVMGetParam(func, 3); res_ptr = LLVMGetParam(func, 4); block = LLVMAppendBasicBlockInContext(context, func, "entry"); builder = gallivm->builder; LLVMPositionBuilderAtEnd(builder, block); src = LLVMBuildLoad(builder, src_ptr, "src"); src1 = LLVMBuildLoad(builder, src1_ptr, "src1"); dst = LLVMBuildLoad(builder, dst_ptr, "dst"); con = LLVMBuildLoad(builder, const_ptr, "const"); res = lp_build_blend_aos(gallivm, blend, format, type, rt, src, NULL, src1, NULL, dst, NULL, con, NULL, swizzle, 4); lp_build_name(res, "res"); LLVMBuildStore(builder, res, res_ptr); LLVMBuildRetVoid(builder);; gallivm_verify_function(gallivm, func); return func; }
/* returns a LLVM representation corresponding to the C translation of the * given IDL type. */ LLVMTypeRef llvm_value_type(struct llvm_ctx *ctx, IDL_tree type) { if(type == NULL) return LLVMVoidTypeInContext(ctx->ctx); switch(IDL_NODE_TYPE(type)) { case IDLN_TYPE_INTEGER: { static short bitlens[] = { [IDL_INTEGER_TYPE_SHORT] = 16, [IDL_INTEGER_TYPE_LONG] = 32, [IDL_INTEGER_TYPE_LONGLONG] = 64, }; int t = IDL_TYPE_INTEGER(type).f_type; assert(t < G_N_ELEMENTS(bitlens)); return LLVMIntTypeInContext(ctx->ctx, bitlens[t]); } case IDLN_NATIVE: { /* each of these is the size of a single word, which is all LLVM * wants to know. */ if(IS_WORD_TYPE(type) || IS_FPAGE_TYPE(type) || IS_TIME_TYPE(type)) { return ctx->wordt; } else { fprintf(stderr, "%s: native type `%s' not supported\n", __FUNCTION__, NATIVE_NAME(type)); abort(); } break; } case IDLN_TYPE_FLOAT: switch(IDL_TYPE_FLOAT(type).f_type) { case IDL_FLOAT_TYPE_FLOAT: return LLVMFloatTypeInContext(ctx->ctx); case IDL_FLOAT_TYPE_DOUBLE: return LLVMDoubleTypeInContext(ctx->ctx); case IDL_FLOAT_TYPE_LONGDOUBLE: return LLVMFP128TypeInContext(ctx->ctx); } g_assert_not_reached(); case IDLN_TYPE_BOOLEAN: case IDLN_TYPE_OCTET: case IDLN_TYPE_CHAR: return LLVMInt8TypeInContext(ctx->ctx); case IDLN_TYPE_WIDE_CHAR: return ctx->i32t; case IDLN_TYPE_ENUM: return LLVMInt16TypeInContext(ctx->ctx); default: NOTDEFINED(type); } }
static LLVMValueRef add_conv_test(struct gallivm_state *gallivm, struct lp_type src_type, unsigned num_srcs, struct lp_type dst_type, unsigned num_dsts) { LLVMModuleRef module = gallivm->module; LLVMContextRef context = gallivm->context; LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef args[2]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef dst_ptr; LLVMBasicBlockRef block; LLVMValueRef src[LP_MAX_VECTOR_LENGTH]; LLVMValueRef dst[LP_MAX_VECTOR_LENGTH]; unsigned i; args[0] = LLVMPointerType(lp_build_vec_type(gallivm, src_type), 0); args[1] = LLVMPointerType(lp_build_vec_type(gallivm, dst_type), 0); func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidTypeInContext(context), args, 2, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); dst_ptr = LLVMGetParam(func, 1); block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMPositionBuilderAtEnd(builder, block); for(i = 0; i < num_srcs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, src_ptr, &index, 1, ""); src[i] = LLVMBuildLoad(builder, ptr, ""); } lp_build_conv(gallivm, src_type, dst_type, src, num_srcs, dst, num_dsts); for(i = 0; i < num_dsts; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, dst_ptr, &index, 1, ""); LLVMBuildStore(builder, dst[i], ptr); } LLVMBuildRetVoid(builder);; gallivm_verify_function(gallivm, func); return func; }
/* Initialize module-independent parts of the context. * * The caller is responsible for initializing ctx::module and ctx::builder. */ void ac_llvm_context_init(struct ac_llvm_context *ctx, LLVMContextRef context) { LLVMValueRef args[1]; ctx->context = context; ctx->module = NULL; ctx->builder = NULL; ctx->voidt = LLVMVoidTypeInContext(ctx->context); ctx->i1 = LLVMInt1TypeInContext(ctx->context); ctx->i8 = LLVMInt8TypeInContext(ctx->context); ctx->i16 = LLVMIntTypeInContext(ctx->context, 16); ctx->i32 = LLVMIntTypeInContext(ctx->context, 32); ctx->i64 = LLVMIntTypeInContext(ctx->context, 64); ctx->f16 = LLVMHalfTypeInContext(ctx->context); ctx->f32 = LLVMFloatTypeInContext(ctx->context); ctx->f64 = LLVMDoubleTypeInContext(ctx->context); ctx->v4i32 = LLVMVectorType(ctx->i32, 4); ctx->v4f32 = LLVMVectorType(ctx->f32, 4); ctx->v8i32 = LLVMVectorType(ctx->i32, 8); ctx->i32_0 = LLVMConstInt(ctx->i32, 0, false); ctx->i32_1 = LLVMConstInt(ctx->i32, 1, false); ctx->f32_0 = LLVMConstReal(ctx->f32, 0.0); ctx->f32_1 = LLVMConstReal(ctx->f32, 1.0); ctx->range_md_kind = LLVMGetMDKindIDInContext(ctx->context, "range", 5); ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(ctx->context, "invariant.load", 14); ctx->fpmath_md_kind = LLVMGetMDKindIDInContext(ctx->context, "fpmath", 6); args[0] = LLVMConstReal(ctx->f32, 2.5); ctx->fpmath_md_2p5_ulp = LLVMMDNodeInContext(ctx->context, args, 1); ctx->uniform_md_kind = LLVMGetMDKindIDInContext(ctx->context, "amdgpu.uniform", 14); ctx->empty_md = LLVMMDNodeInContext(ctx->context, NULL, 0); }
static void llvm_emit_prologue(struct lp_build_tgsi_context * bld_base) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); struct lp_build_context * base = &bld_base->base; unsigned i; /* Reserve special input registers */ for (i = 0; i < ctx->reserved_reg_count; i++) { unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { LLVMValueRef reg_index = lp_build_const_int32( base->gallivm, radeon_llvm_reg_index_soa(i, chan)); lp_build_intrinsic_unary(base->gallivm->builder, "llvm.AMDGPU.reserve.reg", LLVMVoidTypeInContext(base->gallivm->context), reg_index); } } }
/* * Build LLVM function that exercises the unary operator builder. */ static LLVMValueRef build_unary_test_func(struct gallivm_state *gallivm, const struct unary_test_t *test) { struct lp_type type = lp_type_float_vec(32, lp_native_vector_width); LLVMContextRef context = gallivm->context; LLVMModuleRef module = gallivm->module; LLVMTypeRef vf32t = lp_build_vec_type(gallivm, type); LLVMTypeRef args[2] = { LLVMPointerType(vf32t, 0), LLVMPointerType(vf32t, 0) }; LLVMValueRef func = LLVMAddFunction(module, test->name, LLVMFunctionType(LLVMVoidTypeInContext(context), args, Elements(args), 0)); LLVMValueRef arg0 = LLVMGetParam(func, 0); LLVMValueRef arg1 = LLVMGetParam(func, 1); LLVMBuilderRef builder = gallivm->builder; LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMValueRef ret; struct lp_build_context bld; lp_build_context_init(&bld, gallivm, type); LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); arg1 = LLVMBuildLoad(builder, arg1, ""); ret = test->builder(&bld, arg1); LLVMBuildStore(builder, ret, arg0); LLVMBuildRetVoid(builder); gallivm_verify_function(gallivm, func); return func; }
static void llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); struct lp_build_context * base = &bld_base->base; struct pipe_stream_output_info * so = ctx->stream_outputs; unsigned i; unsigned next_pos = 60; unsigned next_param = 0; unsigned color_count = 0; boolean has_color = false; if (ctx->type == TGSI_PROCESSOR_VERTEX && so->num_outputs) { for (i = 0; i < so->num_outputs; i++) { unsigned register_index = so->output[i].register_index; unsigned start_component = so->output[i].start_component; unsigned num_components = so->output[i].num_components; unsigned dst_offset = so->output[i].dst_offset; unsigned chan; LLVMValueRef elements[4]; if (dst_offset < start_component) { for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { elements[chan] = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[register_index][(chan + start_component) % TGSI_NUM_CHANNELS], ""); } start_component = 0; } else { for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { elements[chan] = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[register_index][chan], ""); } } LLVMValueRef output = lp_build_gather_values(base->gallivm, elements, 4); LLVMValueRef args[4]; args[0] = output; args[1] = lp_build_const_int32(base->gallivm, dst_offset - start_component); args[2] = lp_build_const_int32(base->gallivm, so->output[i].output_buffer); args[3] = lp_build_const_int32(base->gallivm, ((1 << num_components) - 1) << start_component); lp_build_intrinsic(base->gallivm->builder, "llvm.R600.store.stream.output", LLVMVoidTypeInContext(base->gallivm->context), args, 4); } } /* Add the necessary export instructions */ for (i = 0; i < ctx->output_reg_count; i++) { unsigned chan; LLVMValueRef elements[4]; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { elements[chan] = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][chan], ""); } if (ctx->alpha_to_one && ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->r600_outputs[i].name == TGSI_SEMANTIC_COLOR) elements[3] = lp_build_const_float(base->gallivm, 1.0f); LLVMValueRef output = lp_build_gather_values(base->gallivm, elements, 4); if (ctx->type == TGSI_PROCESSOR_VERTEX) { switch (ctx->r600_outputs[i].name) { case TGSI_SEMANTIC_POSITION: case TGSI_SEMANTIC_PSIZE: { LLVMValueRef args[3]; args[0] = output; args[1] = lp_build_const_int32(base->gallivm, next_pos++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); break; } case TGSI_SEMANTIC_CLIPVERTEX: { LLVMValueRef args[3]; unsigned reg_index; unsigned base_vector_chan; LLVMValueRef adjusted_elements[4]; for (reg_index = 0; reg_index < 2; reg_index ++) { for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { LLVMValueRef offset = lp_build_const_int32(bld_base->base.gallivm, reg_index * 4 + chan); LLVMValueRef base_vector = llvm_load_const_buffer(bld_base, offset, CONSTANT_BUFFER_1_ADDR_SPACE); args[0] = output; args[1] = base_vector; adjusted_elements[chan] = build_intrinsic(base->gallivm->builder, "llvm.AMDGPU.dp4", bld_base->base.elem_type, args, 2, LLVMReadNoneAttribute); } args[0] = lp_build_gather_values(base->gallivm, adjusted_elements, 4); args[1] = lp_build_const_int32(base->gallivm, next_pos++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); } break; } case TGSI_SEMANTIC_CLIPDIST : { LLVMValueRef args[3]; args[0] = output; args[1] = lp_build_const_int32(base->gallivm, next_pos++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); args[1] = lp_build_const_int32(base->gallivm, next_param++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); break; } case TGSI_SEMANTIC_FOG: { elements[0] = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][0], ""); elements[1] = elements[2] = lp_build_const_float(base->gallivm, 0.0f); elements[3] = lp_build_const_float(base->gallivm, 1.0f); LLVMValueRef args[3]; args[0] = lp_build_gather_values(base->gallivm, elements, 4); args[1] = lp_build_const_int32(base->gallivm, next_param++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); break; } default: { LLVMValueRef args[3]; args[0] = output; args[1] = lp_build_const_int32(base->gallivm, next_param++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); break; } } } else if (ctx->type == TGSI_PROCESSOR_FRAGMENT) { switch (ctx->r600_outputs[i].name) { case TGSI_SEMANTIC_COLOR: has_color = true; if ( color_count < ctx->color_buffer_count) { LLVMValueRef args[3]; args[0] = output; if (ctx->fs_color_all) { for (unsigned j = 0; j < ctx->color_buffer_count; j++) { args[1] = lp_build_const_int32(base->gallivm, j); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); } } else { args[1] = lp_build_const_int32(base->gallivm, color_count++); args[2] = lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL); build_intrinsic( base->gallivm->builder, "llvm.R600.store.swizzle", LLVMVoidTypeInContext(base->gallivm->context), args, 3, 0); } } break; case TGSI_SEMANTIC_POSITION: lp_build_intrinsic_unary( base->gallivm->builder, "llvm.R600.store.pixel.depth", LLVMVoidTypeInContext(base->gallivm->context), LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][2], "")); break; case TGSI_SEMANTIC_STENCIL: lp_build_intrinsic_unary( base->gallivm->builder, "llvm.R600.store.pixel.stencil", LLVMVoidTypeInContext(base->gallivm->context), LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][1], "")); break; } } } // Add dummy exports if (ctx->type == TGSI_PROCESSOR_VERTEX) { if (!next_param) { lp_build_intrinsic_unary(base->gallivm->builder, "llvm.R600.store.dummy", LLVMVoidTypeInContext(base->gallivm->context), lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM)); } if (!(next_pos-60)) { lp_build_intrinsic_unary(base->gallivm->builder, "llvm.R600.store.dummy", LLVMVoidTypeInContext(base->gallivm->context), lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS)); } } if (ctx->type == TGSI_PROCESSOR_FRAGMENT) { if (!has_color) { lp_build_intrinsic_unary(base->gallivm->builder, "llvm.R600.store.dummy", LLVMVoidTypeInContext(base->gallivm->context), lp_build_const_int32(base->gallivm, V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL)); } } }
LLVMTypeRef ett_llvm_type(EagleComplexType *type) { switch(type->type) { case ETVoid: return LLVMVoidTypeInContext(utl_get_current_context()); case ETFloat: return LLVMFloatTypeInContext(utl_get_current_context()); case ETDouble: return LLVMDoubleTypeInContext(utl_get_current_context()); case ETInt1: return LLVMInt1TypeInContext(utl_get_current_context()); case ETGeneric: // In practice this doesn't matter case ETAny: case ETInt8: case ETUInt8: return LLVMInt8TypeInContext(utl_get_current_context()); case ETInt16: case ETUInt16: return LLVMInt16TypeInContext(utl_get_current_context()); case ETInt32: case ETUInt32: return LLVMInt32TypeInContext(utl_get_current_context()); case ETInt64: case ETUInt64: return LLVMInt64TypeInContext(utl_get_current_context()); case ETCString: return LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); case ETEnum: return LLVMInt64TypeInContext(utl_get_current_context()); case ETGenerator: { if(generator_type) return generator_type; LLVMTypeRef ptmp[2]; ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); ptmp[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); generator_type = LLVMStructCreateNamed(utl_get_current_context(), "__egl_gen_strct"); LLVMStructSetBody(generator_type, ptmp, 2, 0); return generator_type; } case ETClass: case ETStruct: { EagleStructType *st = (EagleStructType *)type; LLVMTypeRef loaded = LLVMGetTypeByName(the_module, st->name); if(loaded) return loaded; return NULL; // LLVMTypeRef ty = LLVMStructTypeInContext(utl_get_current_context(), } case ETInterface: { return LLVMInt8TypeInContext(utl_get_current_context()); } case ETPointer: { EaglePointerType *pt = (EaglePointerType *)type; if(pt->counted || pt->weak) { LLVMTypeRef ptmp[2]; ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); ptmp[1] = LLVMInt1TypeInContext(utl_get_current_context()); LLVMTypeRef tys[6]; tys[0] = LLVMInt64TypeInContext(utl_get_current_context()); tys[1] = LLVMInt16TypeInContext(utl_get_current_context()); tys[2] = LLVMInt16TypeInContext(utl_get_current_context()); tys[3] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); tys[4] = LLVMPointerType(LLVMFunctionType(LLVMVoidTypeInContext(utl_get_current_context()), ptmp, 2, 0), 0); tys[5] = ett_llvm_type(pt->to); return LLVMPointerType(ty_get_counted(LLVMStructTypeInContext(utl_get_current_context(), tys, 6, 0)), 0); } return LLVMPointerType(ett_llvm_type(((EaglePointerType *)type)->to), 0); } case ETArray: { EagleArrayType *at = (EagleArrayType *)type; if(at->ct < 0) return LLVMPointerType(ett_llvm_type(at->of), 0); else return LLVMArrayType(ett_llvm_type(at->of), at->ct); } case ETFunction: { EagleFunctionType *ft = (EagleFunctionType *)type; if(ET_IS_CLOSURE(type)) { LLVMTypeRef tys[2]; tys[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); tys[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); return LLVMStructTypeInContext(utl_get_current_context(), tys, 2, 0); } LLVMTypeRef *tys = malloc(sizeof(LLVMTypeRef) * ft->pct); int i; for(i = 0; i < ft->pct; i++) tys[i] = ett_llvm_type(ft->params[i]); LLVMTypeRef out = LLVMFunctionType(ett_llvm_type(ft->retType), tys, ft->pct, 0); free(tys); return out; } default: return NULL; } }
static void init_runtime(compile_t* c) { c->str_builtin = stringtab("$0"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_ILong = stringtab("ILong"); c->str_ISize = stringtab("ISize"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_ULong = stringtab("ULong"); c->str_USize = stringtab("USize"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Maybe = stringtab("MaybePointer"); c->str_DoNotOptimise = stringtab("DoNotOptimise"); c->str_Array = stringtab("Array"); c->str_String = stringtab("String"); c->str_Platform = stringtab("Platform"); c->str_Main = stringtab("Main"); c->str_Env = stringtab("Env"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_add_unsafe = stringtab("add_unsafe"); c->str_sub_unsafe = stringtab("sub_unsafe"); c->str_mul_unsafe = stringtab("mul_unsafe"); c->str_div_unsafe = stringtab("div_unsafe"); c->str_mod_unsafe = stringtab("mod_unsafe"); c->str_neg_unsafe = stringtab("neg_unsafe"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_shl_unsafe = stringtab("shl_unsafe"); c->str_shr_unsafe = stringtab("shr_unsafe"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); c->str_eq_unsafe = stringtab("eq_unsafe"); c->str_ne_unsafe = stringtab("ne_unsafe"); c->str_lt_unsafe = stringtab("lt_unsafe"); c->str_le_unsafe = stringtab("le_unsafe"); c->str_ge_unsafe = stringtab("ge_unsafe"); c->str_gt_unsafe = stringtab("gt_unsafe"); c->str_this = stringtab("this"); c->str_create = stringtab("create"); c->str__create = stringtab("_create"); c->str__init = stringtab("_init"); c->str__final = stringtab("_final"); c->str__event_notify = stringtab("_event_notify"); c->str__serialise_space = stringtab("_serialise_space"); c->str__serialise = stringtab("_serialise"); c->str__deserialise = stringtab("_deserialise"); LLVMTypeRef type; LLVMTypeRef params[5]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "__object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "__message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 2, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // serialise // void (*)(i8*, __object*, i8*, intptr, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->void_ptr; params[3] = c->intptr; params[4] = c->i32; c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false); c->serialise_fn = LLVMPointerType(c->serialise_type, 0); // serialise_space // i64 (__object*) params[0] = c->object_ptr; c->custom_serialise_space_fn = LLVMPointerType( LLVMFunctionType(c->i64, params, 1, false), 0); // custom_deserialise // void (*)(__object*, void*) params[0] = c->object_ptr; params[1] = c->void_ptr; c->custom_deserialise_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 2, false), 0); // dispatch // void (*)(i8*, __object*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)(__object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in gendesc_basetype(c, c->descriptor_type); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); #if PONY_LLVM >= 309 LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0); LLVM_DECLARE_ATTRIBUTEREF(readnone_attr, readnone, 0); LLVM_DECLARE_ATTRIBUTEREF(readonly_attr, readonly, 0); LLVM_DECLARE_ATTRIBUTEREF(inacc_or_arg_mem_attr, inaccessiblemem_or_argmemonly, 0); LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0); LLVM_DECLARE_ATTRIBUTEREF(noreturn_attr, noreturn, 0); LLVM_DECLARE_ATTRIBUTEREF(deref_actor_attr, dereferenceable, PONY_ACTOR_PAD_SIZE + (target_is_ilp32(c->opt->triple) ? 4 : 8)); LLVM_DECLARE_ATTRIBUTEREF(align_pool_attr, align, ponyint_pool_size(0)); LLVM_DECLARE_ATTRIBUTEREF(align_heap_attr, align, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_or_null_alloc_attr, dereferenceable_or_null, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_small_attr, dereferenceable, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_large_attr, dereferenceable, HEAP_MAX << 1); #endif // i8* pony_ctx() type = LLVMFunctionType(c->void_ptr, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_ctx", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadNoneAttribute); #endif // __object* pony_create(i8*, __Desc*) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_create", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_actor_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE + (target_is_ilp32(c->opt->triple) ? 4 : 8)); #endif // void ponyint_destroy(__object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "ponyint_destroy", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_sendv(i8*, __object*, $message*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; params[3] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_sendv", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_sendv_single(i8*, __object*, $message*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; params[3] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_sendv_single", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i8* pony_alloc(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_small_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); #endif // i8* pony_alloc_large(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_large_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX << 1); #endif // i8* pony_realloc(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_realloc", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_final(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small_final(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_small_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); #endif // i8* pony_alloc_large_final(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_large_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX << 1); #endif // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); #endif // void pony_trace(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_trace", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadNoneAttribute); #endif // void pony_traceknown(i8*, __object*, __Desc*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->descriptor_ptr; params[3] = c->i32; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_traceknown", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // void pony_traceunknown(i8*, __object*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // void pony_gc_send(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_gc_recv(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_send_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_send_done", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); #endif // void pony_recv_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); #endif // void pony_serialise_reserve(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_serialise_reserve", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadNoneAttribute); #endif // intptr pony_serialise_offset(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->intptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_serialise_offset", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // i8* pony_deserialise_offset(i8*, __desc*, intptr) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_offset", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #elif PONY_LLVM == 308 LLVMSetInaccessibleMemOrArgMemOnly(value); #endif // i8* pony_deserialise_block(i8*, intptr, intptr) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_block", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); #else # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); #endif // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_become(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_become", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i32 pony_start(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_start", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i32 pony_get_exitcode() type = LLVMFunctionType(c->i32, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_get_exitcode", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute); #endif // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_throw", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, noreturn_attr); #else LLVMAddFunctionAttr(value, LLVMNoReturnAttribute); #endif // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // i32 memcmp(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->i32, params, 3, false); value = LLVMAddFunction(c->module, "memcmp", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr); LLVMAddAttributeAtIndex(value, 1, readonly_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute); LLVMValueRef param = LLVMGetParam(value, 0); LLVMAddAttribute(param, LLVMReadOnlyAttribute); param = LLVMGetParam(value, 1); LLVMAddAttribute(param, LLVMReadOnlyAttribute); #endif }
static void init_runtime(compile_t* c) { c->str_1 = stringtab("$1"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Array = stringtab("Array"); c->str_Platform = stringtab("Platform"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); LLVMTypeRef type; LLVMTypeRef params[4]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "$object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "$message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)($object*) params[0] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 1, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // dispatch // void (*)($object*, $message*) params[0] = c->object_ptr; params[1] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 2, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)($object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in c->descriptor_type = gendesc_type(c, NULL); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); // $object* pony_create($desc*) params[0] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 1, false); value = LLVMAddFunction(c->module, "pony_create", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_destroy($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_destroy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); //LLVMSetReturnNoAlias(value); // void pony_sendv($object*, $message*); params[0] = c->object_ptr; params[1] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_sendv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_alloc(i64) params[0] = c->i64; type = LLVMFunctionType(c->void_ptr, params, 1, false); value = LLVMAddFunction(c->module, "pony_alloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // i8* pony_realloc(i8*, i64) params[0] = c->void_ptr; params[1] = c->i64; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_realloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // i8* pony_alloc_final(i64, c->final_fn) params[0] = c->i64; params[1] = c->final_fn; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_trace(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_trace", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceactor($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_traceactor", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceobject($object*, trace_fn) params[0] = c->object_ptr; params[1] = c->trace_fn; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_traceobject", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceunknown($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_trace_tag_or_actor($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_trace_tag_or_actor", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_send() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_recv() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_send_done() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_send_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_recv_done() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_become($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_become", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_start(i32) params[0] = c->i32; type = LLVMFunctionType(c->i32, params, 1, false); value = LLVMAddFunction(c->module, "pony_start", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); LLVMAddFunction(c->module, "pony_throw", type); // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // i8* memcpy(...) type = LLVMFunctionType(c->void_ptr, NULL, 0, true); value = LLVMAddFunction(c->module, "memcpy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* memmove(...) type = LLVMFunctionType(c->void_ptr, NULL, 0, true); value = LLVMAddFunction(c->module, "memmove", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); }
LLVMValueRef get_struct_fn( struct llvm_ctx *ctx, IDL_tree ctyp, bool for_encode) { const char *s_id = IDL_IDENT(IDL_TYPE_STRUCT(ctyp).ident).repo_id; char *lookup_name = talloc_asprintf(ctx, "%c%s", for_encode ? 'e' : 'd', s_id); LLVMValueRef fn = strmap_get(&ctx->struct_decoder_fns, lookup_name); if(fn != NULL) { talloc_free(lookup_name); return fn; } const struct packed_format *fmt = packed_format_of(ctyp); assert(fmt != NULL); /* only sane for packable structs */ int namelen = strlen(s_id); char flatname[namelen + 1]; /* FIXME: make this proper, i.e. use a name mangler that works */ for(int i=0; i < namelen; i++) { flatname[i] = isalnum(s_id[i]) ? s_id[i] : '_'; } flatname[namelen] = '\0'; T types[3], rettyp = LLVMVoidTypeInContext(ctx->ctx); types[0] = LLVMPointerType(llvm_rigid_type(ctx, ctyp), 0); int nparms; if(!for_encode) { /* decoder */ types[1] = ctx->i32t; types[2] = ctx->i32t; nparms = fmt->num_bits < BITS_PER_WORD ? 3 : 2; } else if(fmt->num_bits < BITS_PER_WORD) { /* subword encoder */ rettyp = ctx->wordt; types[1] = ctx->wordt; types[2] = ctx->i32t; nparms = 3; } else { /* non-subword encoder */ types[1] = ctx->i32t; nparms = 2; } T fntype = LLVMFunctionType(rettyp, types, nparms, 0); char *fnname = g_strdup_printf("__muidl_idl_%scode__%s", for_encode ? "en" : "de", flatname); fn = LLVMAddFunction(ctx->module, fnname, fntype); LLVMSetLinkage(fn, LLVMExternalLinkage); V params[nparms]; assert(LLVMCountParams(fn) == nparms); LLVMGetParams(fn, params); LLVMAddAttribute(params[0], LLVMNoAliasAttribute); LLVMAddAttribute(params[0], LLVMNoCaptureAttribute); for(int i=0; i<nparms; i++) { LLVMAddAttribute(params[i], LLVMInRegAttribute); } g_free(fnname); bool ok = strmap_add(&ctx->struct_decoder_fns, lookup_name, fn); assert(ok || errno != EEXIST); return fn; }
static void llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); struct lp_build_context * base = &bld_base->base; unsigned i; unsigned color_count = 0; boolean has_color = false; /* Add the necessary export instructions */ for (i = 0; i < ctx->output_reg_count; i++) { unsigned chan; for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { LLVMValueRef output; unsigned adjusted_reg_idx = i + ctx->reserved_reg_count; output = LLVMBuildLoad(base->gallivm->builder, ctx->soa.outputs[i][chan], ""); if (ctx->type == TGSI_PROCESSOR_VERTEX) { LLVMValueRef reg_index = lp_build_const_int32( base->gallivm, radeon_llvm_reg_index_soa(adjusted_reg_idx, chan)); lp_build_intrinsic_binary( base->gallivm->builder, "llvm.AMDGPU.store.output", LLVMVoidTypeInContext(base->gallivm->context), output, reg_index); } else if (ctx->type == TGSI_PROCESSOR_FRAGMENT) { switch (ctx->r600_outputs[i].name) { case TGSI_SEMANTIC_COLOR: has_color = true; if ( color_count/4 < ctx->color_buffer_count) { if (ctx->fs_color_all) { for (unsigned j = 0; j < ctx->color_buffer_count; j++) { LLVMValueRef reg_index = lp_build_const_int32( base->gallivm, (j * 4) + chan); lp_build_intrinsic_binary( base->gallivm->builder, "llvm.R600.store.pixel.color", LLVMVoidTypeInContext(base->gallivm->context), output, reg_index); } } else { LLVMValueRef reg_index = lp_build_const_int32( base->gallivm, (color_count++/4) * 4 + chan); lp_build_intrinsic_binary( base->gallivm->builder, "llvm.R600.store.pixel.color", LLVMVoidTypeInContext(base->gallivm->context), output, reg_index); } } break; case TGSI_SEMANTIC_POSITION: if (chan != 2) continue; lp_build_intrinsic_unary( base->gallivm->builder, "llvm.R600.store.pixel.depth", LLVMVoidTypeInContext(base->gallivm->context), output); break; case TGSI_SEMANTIC_STENCIL: if (chan != 1) continue; lp_build_intrinsic_unary( base->gallivm->builder, "llvm.R600.store.pixel.stencil", LLVMVoidTypeInContext(base->gallivm->context), output); break; } } } } if (!has_color && ctx->type == TGSI_PROCESSOR_FRAGMENT) lp_build_intrinsic(base->gallivm->builder, "llvm.R600.store.pixel.dummy", LLVMVoidTypeInContext(base->gallivm->context), 0, 0); }
static LLVMValueRef add_blend_test(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, enum vector_mode mode, struct lp_type type) { LLVMModuleRef module = gallivm->module; LLVMContextRef context = gallivm->context; LLVMTypeRef vec_type; LLVMTypeRef args[4]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef dst_ptr; LLVMValueRef const_ptr; LLVMValueRef res_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; const enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; const unsigned rt = 0; const unsigned char swizzle[4] = { 0, 1, 2, 3 }; vec_type = lp_build_vec_type(gallivm, type); args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidTypeInContext(context), 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 = LLVMAppendBasicBlockInContext(context, func, "entry"); builder = gallivm->builder; 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(gallivm, blend, &format, type, rt, src, dst, NULL, con, swizzle); 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(LLVMInt32TypeInContext(context), 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(gallivm, blend, type, rt, src, dst, con, res); for(i = 0; i < 4; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); lp_build_name(res[i], "res.%c", "rgba"[i]); LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, "")); } } LLVMBuildRetVoid(builder);; return func; }
static void init_runtime(compile_t* c) { c->str_builtin = stringtab("$0"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_ILong = stringtab("ILong"); c->str_ISize = stringtab("ISize"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_ULong = stringtab("ULong"); c->str_USize = stringtab("USize"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Maybe = stringtab("MaybePointer"); c->str_DoNotOptimise = stringtab("DoNotOptimise"); c->str_Array = stringtab("Array"); c->str_String = stringtab("String"); c->str_Platform = stringtab("Platform"); c->str_Main = stringtab("Main"); c->str_Env = stringtab("Env"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); c->str_this = stringtab("this"); c->str_create = stringtab("create"); c->str__create = stringtab("_create"); c->str__init = stringtab("_init"); c->str__final = stringtab("_final"); c->str__event_notify = stringtab("_event_notify"); LLVMTypeRef type; LLVMTypeRef params[5]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->ibool = LLVMInt8TypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "__object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "__message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 2, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // serialise // void (*)(i8*, __object*, i8*, intptr, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->void_ptr; params[3] = c->intptr; params[4] = c->i32; c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false); c->serialise_fn = LLVMPointerType(c->serialise_type, 0); // dispatch // void (*)(i8*, __object*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)(__object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in gendesc_basetype(c, c->descriptor_type); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); // $i8* pony_ctx() type = LLVMFunctionType(c->void_ptr, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_ctx", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadNoneAttribute); // __object* pony_create(i8*, __Desc*) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_create", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE); // void ponyint_destroy(__object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "ponyint_destroy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_sendv(i8*, __object*, $message*); params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_sendv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_alloc(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); // i8* pony_alloc_large(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX + 1); // i8* pony_realloc(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_realloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_final(i8*, intptr, c->final_fn) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->final_fn; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_trace(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_trace", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_traceobject(i8*, __object*, __Desc*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->descriptor_ptr; params[3] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 4, false); value = LLVMAddFunction(c->module, "pony_traceknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_traceunknown(i8*, __object*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_send(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_recv(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_send_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_send_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_recv_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_serialise_reserve(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_serialise_reserve", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // intptr pony_serialise_offset(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->intptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_serialise_offset", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_deserialise_offset(i8*, __desc*, intptr) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_offset", type); // i8* pony_deserialise_block(i8*, intptr, intptr) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_block", type); // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_become(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_become", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_start(i32) params[0] = c->i32; type = LLVMFunctionType(c->i32, params, 1, false); value = LLVMAddFunction(c->module, "pony_start", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); LLVMAddFunction(c->module, "pony_throw", type); // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // void llvm.memcpy.*(i8*, i8*, i32/64, i32, i1) params[0] = c->void_ptr; params[1] = c->void_ptr; params[3] = c->i32; params[4] = c->i1; if(target_is_ilp32(c->opt->triple)) { params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i32", type); } else { params[2] = c->i64; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i64", type); } LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void llvm.memmove.*(i8*, i8*, i32/64, i32, i1) params[0] = c->void_ptr; params[1] = c->void_ptr; params[3] = c->i32; params[4] = c->i1; if(target_is_ilp32(c->opt->triple)) { params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i32", type); } else { params[2] = c->i64; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i64", type); } LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); }
/** * Fetch a pixel into a 4 float AoS. * * \param format_desc describes format of the image we're fetching from * \param ptr address of the pixel block (or the texel if uncompressed) * \param i, j the sub-block pixel coordinates. For non-compressed formats * these will always be (0, 0). * \return a 4 element vector with the pixel's RGBA values. */ LLVMValueRef lp_build_fetch_rgba_aos(struct gallivm_state *gallivm, const struct util_format_description *format_desc, struct lp_type type, LLVMValueRef base_ptr, LLVMValueRef offset, LLVMValueRef i, LLVMValueRef j) { LLVMBuilderRef builder = gallivm->builder; unsigned num_pixels = type.length / 4; struct lp_build_context bld; assert(type.length <= LP_MAX_VECTOR_LENGTH); assert(type.length % 4 == 0); lp_build_context_init(&bld, gallivm, type); /* * Trivial case * * The format matches the type (apart of a swizzle) so no need for * scaling or converting. */ if (format_matches_type(format_desc, type) && format_desc->block.bits <= type.width * 4 && util_is_power_of_two(format_desc->block.bits)) { LLVMValueRef packed; /* * The format matches the type (apart of a swizzle) so no need for * scaling or converting. */ packed = lp_build_gather(gallivm, type.length/4, format_desc->block.bits, type.width*4, base_ptr, offset); assert(format_desc->block.bits <= type.width * type.length); packed = LLVMBuildBitCast(gallivm->builder, packed, lp_build_vec_type(gallivm, type), ""); return lp_build_format_swizzle_aos(format_desc, &bld, packed); } /* * Bit arithmetic */ if (format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) && format_desc->block.width == 1 && format_desc->block.height == 1 && util_is_power_of_two(format_desc->block.bits) && format_desc->block.bits <= 32 && format_desc->is_bitmask && !format_desc->is_mixed && (format_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED || format_desc->channel[1].type == UTIL_FORMAT_TYPE_UNSIGNED)) { LLVMValueRef tmps[LP_MAX_VECTOR_LENGTH/4]; LLVMValueRef res; unsigned k; /* * Unpack a pixel at a time into a <4 x float> RGBA vector */ for (k = 0; k < num_pixels; ++k) { LLVMValueRef packed; packed = lp_build_gather_elem(gallivm, num_pixels, format_desc->block.bits, 32, base_ptr, offset, k); tmps[k] = lp_build_unpack_arith_rgba_aos(gallivm, format_desc, packed); } /* * Type conversion. * * TODO: We could avoid floating conversion for integer to * integer conversions. */ if (gallivm_debug & GALLIVM_DEBUG_PERF && !type.floating) { debug_printf("%s: unpacking %s with floating point\n", __FUNCTION__, format_desc->short_name); } lp_build_conv(gallivm, lp_float32_vec4_type(), type, tmps, num_pixels, &res, 1); return lp_build_format_swizzle_aos(format_desc, &bld, res); } /* * YUV / subsampled formats */ if (format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) { struct lp_type tmp_type; LLVMValueRef tmp; memset(&tmp_type, 0, sizeof tmp_type); tmp_type.width = 8; tmp_type.length = num_pixels * 4; tmp_type.norm = TRUE; tmp = lp_build_fetch_subsampled_rgba_aos(gallivm, format_desc, num_pixels, base_ptr, offset, i, j); lp_build_conv(gallivm, tmp_type, type, &tmp, 1, &tmp, 1); return tmp; } /* * Fallback to util_format_description::fetch_rgba_8unorm(). */ if (format_desc->fetch_rgba_8unorm && !type.floating && type.width == 8 && !type.sign && type.norm) { /* * Fallback to calling util_format_description::fetch_rgba_8unorm. * * This is definitely not the most efficient way of fetching pixels, as * we miss the opportunity to do vectorization, but this it is a * convenient for formats or scenarios for which there was no opportunity * or incentive to optimize. */ LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder))); char name[256]; LLVMTypeRef i8t = LLVMInt8TypeInContext(gallivm->context); LLVMTypeRef pi8t = LLVMPointerType(i8t, 0); LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef function; LLVMValueRef tmp_ptr; LLVMValueRef tmp; LLVMValueRef res; LLVMValueRef callee; unsigned k; util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_8unorm", format_desc->short_name); if (gallivm_debug & GALLIVM_DEBUG_PERF) { debug_printf("%s: falling back to %s\n", __FUNCTION__, name); } /* * Declare and bind format_desc->fetch_rgba_8unorm(). */ function = LLVMGetNamedFunction(module, name); if (!function) { /* * Function to call looks like: * fetch(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) */ LLVMTypeRef ret_type; LLVMTypeRef arg_types[4]; LLVMTypeRef function_type; ret_type = LLVMVoidTypeInContext(gallivm->context); arg_types[0] = pi8t; arg_types[1] = pi8t; arg_types[2] = i32t; arg_types[3] = i32t; function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0); function = LLVMAddFunction(module, name, function_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); LLVMSetLinkage(function, LLVMExternalLinkage); assert(LLVMIsDeclaration(function)); } /* make const pointer for the C fetch_rgba_float function */ callee = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer) format_desc->fetch_rgba_8unorm)); /* cast the callee pointer to the function's type */ function = LLVMBuildBitCast(builder, callee, LLVMTypeOf(function), "cast callee"); tmp_ptr = lp_build_alloca(gallivm, i32t, ""); res = LLVMGetUndef(LLVMVectorType(i32t, num_pixels)); /* * Invoke format_desc->fetch_rgba_8unorm() for each pixel and insert the result * in the SoA vectors. */ for (k = 0; k < num_pixels; ++k) { LLVMValueRef index = lp_build_const_int32(gallivm, k); LLVMValueRef args[4]; args[0] = LLVMBuildBitCast(builder, tmp_ptr, pi8t, ""); args[1] = lp_build_gather_elem_ptr(gallivm, num_pixels, base_ptr, offset, k); if (num_pixels == 1) { args[2] = i; args[3] = j; } else { args[2] = LLVMBuildExtractElement(builder, i, index, ""); args[3] = LLVMBuildExtractElement(builder, j, index, ""); } LLVMBuildCall(builder, function, args, Elements(args), ""); tmp = LLVMBuildLoad(builder, tmp_ptr, ""); if (num_pixels == 1) { res = tmp; } else { res = LLVMBuildInsertElement(builder, res, tmp, index, ""); } } /* Bitcast from <n x i32> to <4n x i8> */ res = LLVMBuildBitCast(builder, res, bld.vec_type, ""); return res; } /* * Fallback to util_format_description::fetch_rgba_float(). */ if (format_desc->fetch_rgba_float) { /* * Fallback to calling util_format_description::fetch_rgba_float. * * This is definitely not the most efficient way of fetching pixels, as * we miss the opportunity to do vectorization, but this it is a * convenient for formats or scenarios for which there was no opportunity * or incentive to optimize. */ LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); char name[256]; LLVMTypeRef f32t = LLVMFloatTypeInContext(gallivm->context); LLVMTypeRef f32x4t = LLVMVectorType(f32t, 4); LLVMTypeRef pf32t = LLVMPointerType(f32t, 0); LLVMTypeRef pi8t = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0); LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef function; LLVMValueRef tmp_ptr; LLVMValueRef tmps[LP_MAX_VECTOR_LENGTH/4]; LLVMValueRef res; LLVMValueRef callee; unsigned k; util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_float", format_desc->short_name); if (gallivm_debug & GALLIVM_DEBUG_PERF) { debug_printf("%s: falling back to %s\n", __FUNCTION__, name); } /* * Declare and bind format_desc->fetch_rgba_float(). */ function = LLVMGetNamedFunction(module, name); if (!function) { /* * Function to call looks like: * fetch(float *dst, const uint8_t *src, unsigned i, unsigned j) */ LLVMTypeRef ret_type; LLVMTypeRef arg_types[4]; LLVMTypeRef function_type; ret_type = LLVMVoidTypeInContext(gallivm->context); arg_types[0] = pf32t; arg_types[1] = pi8t; arg_types[2] = i32t; arg_types[3] = i32t; function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0); function = LLVMAddFunction(module, name, function_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); LLVMSetLinkage(function, LLVMExternalLinkage); assert(LLVMIsDeclaration(function)); } /* Note: we're using this casting here instead of LLVMAddGlobalMapping() * to work around a bug in LLVM 2.6. */ /* make const pointer for the C fetch_rgba_float function */ callee = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer) format_desc->fetch_rgba_float)); /* cast the callee pointer to the function's type */ function = LLVMBuildBitCast(builder, callee, LLVMTypeOf(function), "cast callee"); tmp_ptr = lp_build_alloca(gallivm, f32x4t, ""); /* * Invoke format_desc->fetch_rgba_float() for each pixel and insert the result * in the SoA vectors. */ for (k = 0; k < num_pixels; ++k) { LLVMValueRef args[4]; args[0] = LLVMBuildBitCast(builder, tmp_ptr, pf32t, ""); args[1] = lp_build_gather_elem_ptr(gallivm, num_pixels, base_ptr, offset, k); if (num_pixels == 1) { args[2] = i; args[3] = j; } else { LLVMValueRef index = lp_build_const_int32(gallivm, k); args[2] = LLVMBuildExtractElement(builder, i, index, ""); args[3] = LLVMBuildExtractElement(builder, j, index, ""); } LLVMBuildCall(builder, function, args, Elements(args), ""); tmps[k] = LLVMBuildLoad(builder, tmp_ptr, ""); } lp_build_conv(gallivm, lp_float32_vec4_type(), type, tmps, num_pixels, &res, 1); return res; } assert(0); return lp_build_undef(gallivm, type); }
static void update_cached_block(struct gallivm_state *gallivm, const struct util_format_description *format_desc, LLVMValueRef ptr_addr, LLVMValueRef hash_index, LLVMValueRef cache) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef i8t = LLVMInt8TypeInContext(gallivm->context); LLVMTypeRef pi8t = LLVMPointerType(i8t, 0); LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context); LLVMTypeRef i32x4 = LLVMVectorType(LLVMInt32TypeInContext(gallivm->context), 4); LLVMValueRef function; LLVMValueRef tag_value, tmp_ptr; LLVMValueRef col[4]; unsigned i, j; /* * Use format_desc->fetch_rgba_8unorm() for each pixel in the block. * This doesn't actually make any sense whatsoever, someone would need * to write a function doing this for all pixels in a block (either as * an external c function or with generated code). Don't ask. */ { /* * Function to call looks like: * fetch(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) */ LLVMTypeRef ret_type; LLVMTypeRef arg_types[4]; LLVMTypeRef function_type; assert(format_desc->fetch_rgba_8unorm); ret_type = LLVMVoidTypeInContext(gallivm->context); arg_types[0] = pi8t; arg_types[1] = pi8t; arg_types[2] = i32t; arg_types[3] = i32t; function_type = LLVMFunctionType(ret_type, arg_types, ARRAY_SIZE(arg_types), 0); /* make const pointer for the C fetch_rgba_8unorm function */ function = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer) format_desc->fetch_rgba_8unorm)); /* cast the callee pointer to the function's type */ function = LLVMBuildBitCast(builder, function, LLVMPointerType(function_type, 0), "cast callee"); } tmp_ptr = lp_build_array_alloca(gallivm, i32x4, lp_build_const_int32(gallivm, 16), "tmp_decode_store"); tmp_ptr = LLVMBuildBitCast(builder, tmp_ptr, pi8t, ""); /* * Invoke format_desc->fetch_rgba_8unorm() for each pixel. * This is going to be really really slow. * Note: the block store format is actually * x0y0x0y1x0y2x0y3 x1y0x1y1x1y2x1y3 ... */ for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { LLVMValueRef args[4]; LLVMValueRef dst_offset = lp_build_const_int32(gallivm, (i * 4 + j) * 4); /* * Note we actually supply a pointer to the start of the block, * not the start of the texture. */ args[0] = LLVMBuildGEP(gallivm->builder, tmp_ptr, &dst_offset, 1, ""); args[1] = ptr_addr; args[2] = LLVMConstInt(i32t, i, 0); args[3] = LLVMConstInt(i32t, j, 0); LLVMBuildCall(builder, function, args, ARRAY_SIZE(args), ""); } } /* Finally store the block - pointless mem copy + update tag. */ tmp_ptr = LLVMBuildBitCast(builder, tmp_ptr, LLVMPointerType(i32x4, 0), ""); for (i = 0; i < 4; ++i) { LLVMValueRef tmp_offset = lp_build_const_int32(gallivm, i); LLVMValueRef ptr = LLVMBuildGEP(gallivm->builder, tmp_ptr, &tmp_offset, 1, ""); col[i] = LLVMBuildLoad(builder, ptr, ""); } tag_value = LLVMBuildPtrToInt(gallivm->builder, ptr_addr, LLVMInt64TypeInContext(gallivm->context), ""); store_cached_block(gallivm, col, tag_value, hash_index, cache); }