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, "");
}
Beispiel #2
0
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);
		}
	}
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
/* 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;
}
Beispiel #7
0
/* 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);
}
Beispiel #8
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));
		}
	}

}
Beispiel #11
0
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;
    }
}
Beispiel #12
0
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
}
Beispiel #13
0
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);
}
Beispiel #14
0
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;
}
Beispiel #15
0
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);
}
Beispiel #16
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;
}
Beispiel #17
0
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);
}