void InitLLVM(struct libresoc_llvm *llvm_ref)
{
- LLVMInitializeNativeTarget();
- LLVMInitializeNativeAsmPrinter();
+ // LLVMInitializeNativeTarget();
+ // LLVMInitializeNativeAsmPrinter();
+ LLVMInitializeAllAsmPrinters();
+ LLVMInitializeAllTargets();
+ LLVMInitializeAllTargetInfos();
+ LLVMInitializeAllTargetMCs();
+ LLVMInitializeAllDisassemblers();
//LLVMLinkInMCJIT();
char *def_triple = LLVMGetDefaultTargetTriple(); // E.g. "x86_64-linux-gnu"
char *error;
}
}
+LLVMValueRef extract_components(struct libresoc_llvm_context *ctx, LLVMValueRef value, unsigned start,
+ unsigned channels)
+{
+ LLVMValueRef chan[channels];
+
+ for (unsigned i = 0; i < channels; i++)
+ chan[i] = llvm_extract_elem(ctx, value, i + start);
+
+ return build_gather_values(ctx, chan, channels);
+}
+
static void build_store_values_extended(struct libresoc_llvm_context *lc, LLVMValueRef *values,
unsigned value_count, unsigned value_stride,
LLVMValueRef vec)
return ctx->ssa_defs[src.ssa->index];
}
+static LLVMTypeRef get_def_type(struct libresoc_nir_tran_ctx *ctx, const nir_ssa_def *def)
+{
+ LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, def->bit_size);
+ if (def->num_components > 1) {
+ type = LLVMVectorType(type, def->num_components);
+ }
+ return type;
+}
+
+static LLVMValueRef get_memory_ptr(struct libresoc_nir_tran_ctx *ctx, nir_src src, unsigned bit_size)
+{
+ LLVMValueRef ptr = get_src(ctx, src);
+ ptr = LLVMBuildGEP(ctx->lc.builder, ctx->lc.lds, &ptr, 1, "");
+ int addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
+
+ LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, bit_size);
+
+ return LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(type, addr_space), "");
+}
+
static uint32_t widen_mask(uint32_t mask, unsigned multiplier)
{
uint32_t new_mask = 0;
return LLVMStructTypeInContext(lc->context, member_types, glsl_get_length(type), false);
}
+// static LLVMValueRef visit_load(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_instr *instr,
+// bool is_output)
+// {
+// LLVMValueRef values[8];
+// LLVMTypeRef dest_type = get_def_type(ctx, &instr->dest.ssa);
+// LLVMTypeRef component_type;
+// unsigned base = nir_intrinsic_base(instr);
+// unsigned component = nir_intrinsic_component(instr);
+// unsigned count = instr->dest.ssa.num_components * (instr->dest.ssa.bit_size == 64 ? 2 : 1);
+// nir_src *vertex_index_src = nir_get_io_vertex_index_src(instr);
+// LLVMValueRef vertex_index = vertex_index_src ? get_src(ctx, *vertex_index_src) : NULL;
+// nir_src offset = *nir_get_io_offset_src(instr);
+// LLVMValueRef indir_index = NULL;
+
+// if (LLVMGetTypeKind(dest_type) == LLVMVectorTypeKind)
+// component_type = LLVMGetElementType(dest_type);
+// else
+// component_type = dest_type;
+
+// if (nir_src_is_const(offset))
+// assert(nir_src_as_uint(offset) == 0);
+// else
+// indir_index = get_src(ctx, offset);
+
+// if (ctx->stage == MESA_SHADER_TESS_CTRL || (ctx->stage == MESA_SHADER_TESS_EVAL && !is_output)) {
+// LLVMValueRef result = ctx->abi->load_tess_varyings(
+// ctx->abi, component_type, vertex_index, indir_index, 0, 0, base * 4, component,
+// instr->num_components, false, false, !is_output);
+// if (instr->dest.ssa.bit_size == 16) {
+// result = to_integer(&ctx->lc, result);
+// result = LLVMBuildTrunc(ctx->lc.builder, result, dest_type, "");
+// }
+// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, "");
+// }
+
+// /* No indirect indexing is allowed after this point. */
+// assert(!indir_index);
+
+// if (ctx->stage == MESA_SHADER_GEOMETRY) {
+// LLVMTypeRef type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size);
+// assert(nir_src_is_const(*vertex_index_src));
+
+// return ctx->abi->load_inputs(ctx->abi, 0, base * 4, component, instr->num_components,
+// nir_src_as_uint(*vertex_index_src), 0, type);
+// }
+
+// if (ctx->stage == MESA_SHADER_FRAGMENT && is_output &&
+// nir_intrinsic_io_semantics(instr).fb_fetch_output)
+// return ctx->abi->emit_fbfetch(ctx->abi);
+
+// /* Other non-fragment cases have inputs and outputs in temporaries. */
+// if (ctx->stage != MESA_SHADER_FRAGMENT) {
+// for (unsigned chan = component; chan < count + component; chan++) {
+// if (is_output) {
+// values[chan] = LLVMBuildLoad(ctx->lc.builder, ctx->outputs[base * 4 + chan], "");
+// } else {
+// values[chan] = ctx->inputs[base * 4 + chan];
+// if (!values[chan])
+// values[chan] = LLVMGetUndef(ctx->lc.i32);
+// }
+// }
+// LLVMValueRef result = build_varying_gather_values(&ctx->lc, values, count, component);
+// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, "");
+// }
+
+// /* Fragment shader inputs. */
+// unsigned vertex_id = 2; /* P0 */
+
+// if (instr->intrinsic == nir_intrinsic_load_input_vertex) {
+// nir_const_value *src0 = nir_src_as_const_value(instr->src[0]);
+
+// switch (src0[0].i32) {
+// case 0:
+// vertex_id = 2;
+// break;
+// case 1:
+// vertex_id = 0;
+// break;
+// case 2:
+// vertex_id = 1;
+// break;
+// default:
+// unreachable("Invalid vertex index");
+// }
+// }
+
+// LLVMValueRef attr_number = LLVMConstInt(ctx->lc.i32, base, false);
+
+// for (unsigned chan = 0; chan < count; chan++) {
+// if (component + chan > 4)
+// attr_number = LLVMConstInt(ctx->lc.i32, base + 1, false);
+// LLVMValueRef llvm_chan = LLVMConstInt(ctx->lc.i32, (component + chan) % 4, false);
+// values[chan] =
+// build_fs_interp_mov(&ctx->lc, LLVMConstInt(ctx->lc.i32, vertex_id, false), llvm_chan,
+// attr_number, get_arg(&ctx->lc, ctx->args->prim_mask));
+// values[chan] = LLVMBuildBitCast(ctx->lc.builder, values[chan], ctx->lc.i32, "");
+// values[chan] =
+// LLVMBuildTruncOrBitCast(ctx->lc.builder, values[chan],
+// instr->dest.ssa.bit_size == 16 ? ctx->lc.i16 : ctx->lc.i32, "");
+// }
+
+// LLVMValueRef result = build_gather_values(&ctx->lc, values, count);
+// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, "");
+// }
+
+static LLVMValueRef visit_load_shared(struct libresoc_nir_tran_ctx *ctx, const nir_intrinsic_instr *instr)
+{
+ LLVMValueRef values[4], derived_ptr, index, ret;
+
+ LLVMValueRef ptr = get_memory_ptr(ctx, instr->src[0], instr->dest.ssa.bit_size);
+
+ for (int chan = 0; chan < instr->num_components; chan++) {
+ index = LLVMConstInt(ctx->lc.i32, chan, 0);
+ derived_ptr = LLVMBuildGEP(ctx->lc.builder, ptr, &index, 1, "");
+ values[chan] = LLVMBuildLoad(ctx->lc.builder, derived_ptr, "");
+ }
+
+ ret = build_gather_values(&ctx->lc, values, instr->num_components);
+ return LLVMBuildBitCast(ctx->lc.builder, ret, get_def_type(ctx, &instr->dest.ssa), "");
+}
+
+static void visit_store_shared(struct libresoc_nir_tran_ctx *ctx, const nir_intrinsic_instr *instr)
+{
+ LLVMValueRef derived_ptr, data, index;
+ LLVMBuilderRef builder = ctx->lc.builder;
+
+ LLVMValueRef ptr = get_memory_ptr(ctx, instr->src[1], instr->src[0].ssa->bit_size);
+ LLVMValueRef src = get_src(ctx, instr->src[0]);
+
+ int writemask = nir_intrinsic_write_mask(instr);
+ for (int chan = 0; chan < 4; chan++) {
+ if (!(writemask & (1 << chan))) {
+ continue;
+ }
+ data = llvm_extract_elem(&ctx->lc, src, chan);
+ index = LLVMConstInt(ctx->lc.i32, chan, 0);
+ derived_ptr = LLVMBuildGEP(builder, ptr, &index, 1, "");
+ LLVMBuildStore(builder, data, derived_ptr);
+ }
+}
static void visit_load_const(struct libresoc_nir_tran_ctx *ctx, const nir_load_const_instr *instr)
{
LLVMValueRef values[4], value = NULL;
ctx->ssa_defs[instr->dest.ssa.index] = result;
}
-static LLVMTypeRef get_def_type(struct libresoc_nir_tran_ctx *ctx, const nir_ssa_def *def)
-{
- LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, def->bit_size);
- if (def->num_components > 1) {
- type = LLVMVectorType(type, def->num_components);
- }
- return type;
-}
-
static void visit_phi(struct libresoc_nir_tran_ctx *ctx, nir_phi_instr *instr)
{
LLVMTypeRef type = get_def_type(ctx, &instr->dest.ssa);
visit_store_output(ctx, instr);
break;
case nir_intrinsic_load_shared:
- // result = visit_load_shared(ctx, instr);
+ result = visit_load_shared(ctx, instr);
break;
case nir_intrinsic_store_shared:
- // visit_store_shared(ctx, instr);
+ visit_store_shared(ctx, instr);
break;
case nir_intrinsic_bindless_image_samples:
case nir_intrinsic_image_deref_samples:
// result = ac_build_mbcnt(&ctx->ac, get_src(ctx, instr->src[0]));
break;
case nir_intrinsic_load_scratch: {
- // LLVMValueRef offset = get_src(ctx, instr->src[0]);
- // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->scratch, offset);
- // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size);
- // LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1
- // ? comp_type
- // : LLVMVectorType(comp_type, instr->dest.ssa.num_components);
- // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
- // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(vec_type, addr_space), "");
- // result = LLVMBuildLoad(ctx->ac.builder, ptr, "");
+ LLVMValueRef offset = get_src(ctx, instr->src[0]);
+ LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->scratch, offset);
+ LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->dest.ssa.bit_size);
+ LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1
+ ? comp_type
+ : LLVMVectorType(comp_type, instr->dest.ssa.num_components);
+ unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
+ ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(vec_type, addr_space), "");
+ result = LLVMBuildLoad(ctx->lc.builder, ptr, "");
break;
}
case nir_intrinsic_store_scratch: {
- // LLVMValueRef offset = get_src(ctx, instr->src[1]);
- // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->scratch, offset);
- // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->src[0].ssa->bit_size);
- // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
- // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(comp_type, addr_space), "");
- // LLVMValueRef src = get_src(ctx, instr->src[0]);
- // unsigned wrmask = nir_intrinsic_write_mask(instr);
- // while (wrmask) {
- // int start, count;
- // u_bit_scan_consecutive_range(&wrmask, &start, &count);
-
- // LLVMValueRef offset = LLVMConstInt(ctx->ac.i32, start, false);
- // LLVMValueRef offset_ptr = LLVMBuildGEP(ctx->ac.builder, ptr, &offset, 1, "");
- // LLVMTypeRef vec_type = count == 1 ? comp_type : LLVMVectorType(comp_type, count);
- // offset_ptr = LLVMBuildBitCast(ctx->ac.builder, offset_ptr,
- // LLVMPointerType(vec_type, addr_space), "");
- // LLVMValueRef offset_src = ac_extract_components(&ctx->ac, src, start, count);
- // LLVMBuildStore(ctx->ac.builder, offset_src, offset_ptr);
- // }
+ LLVMValueRef offset = get_src(ctx, instr->src[1]);
+ LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->scratch, offset);
+ LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->src[0].ssa->bit_size);
+ unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
+ ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(comp_type, addr_space), "");
+ LLVMValueRef src = get_src(ctx, instr->src[0]);
+ unsigned wrmask = nir_intrinsic_write_mask(instr);
+ while (wrmask) {
+ int start, count;
+ u_bit_scan_consecutive_range(&wrmask, &start, &count);
+
+ LLVMValueRef offset = LLVMConstInt(ctx->lc.i32, start, false);
+ LLVMValueRef offset_ptr = LLVMBuildGEP(ctx->lc.builder, ptr, &offset, 1, "");
+ LLVMTypeRef vec_type = count == 1 ? comp_type : LLVMVectorType(comp_type, count);
+ offset_ptr = LLVMBuildBitCast(ctx->lc.builder, offset_ptr,
+ LLVMPointerType(vec_type, addr_space), "");
+ LLVMValueRef offset_src = extract_components(&ctx->lc, src, start, count);
+ LLVMBuildStore(ctx->lc.builder, offset_src, offset_ptr);
+ }
break;
}
case nir_intrinsic_load_constant: {
- // unsigned base = nir_intrinsic_base(instr);
- // unsigned range = nir_intrinsic_range(instr);
+ unsigned base = nir_intrinsic_base(instr);
+ unsigned range = nir_intrinsic_range(instr);
- // LLVMValueRef offset = get_src(ctx, instr->src[0]);
- // offset = LLVMBuildAdd(ctx->ac.builder, offset, LLVMConstInt(ctx->ac.i32, base, false), "");
+ LLVMValueRef offset = get_src(ctx, instr->src[0]);
+ offset = LLVMBuildAdd(ctx->lc.builder, offset, LLVMConstInt(ctx->lc.i32, base, false), "");
- // /* Clamp the offset to avoid out-of-bound access because global
- // * instructions can't handle them.
- // */
- // LLVMValueRef size = LLVMConstInt(ctx->ac.i32, base + range, false);
- // LLVMValueRef cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT, offset, size, "");
- // offset = LLVMBuildSelect(ctx->ac.builder, cond, offset, size, "");
+ /* Clamp the offset to avoid out-of-bound access because global
+ * instructions can't handle them.
+ */
+ LLVMValueRef size = LLVMConstInt(ctx->lc.i32, base + range, false);
+ LLVMValueRef cond = LLVMBuildICmp(ctx->lc.builder, LLVMIntULT, offset, size, "");
+ offset = LLVMBuildSelect(ctx->lc.builder, cond, offset, size, "");
- // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->constant_data, offset);
- // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size);
- // LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1
- // ? comp_type
- // : LLVMVectorType(comp_type, instr->dest.ssa.num_components);
- // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
- // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(vec_type, addr_space), "");
- // result = LLVMBuildLoad(ctx->ac.builder, ptr, "");
+ LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->constant_data, offset);
+ LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->dest.ssa.bit_size);
+ LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1
+ ? comp_type
+ : LLVMVectorType(comp_type, instr->dest.ssa.num_components);
+ unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr));
+ ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(vec_type, addr_space), "");
+ result = LLVMBuildLoad(ctx->lc.builder, ptr, "");
break;
}
default:
// if (gl_shader_stage_is_compute(nir->info.stage))
// setup_shared(&ctx, nir);
visit_cf_list(&ctx, &func->impl->body);
+ LLVMBuildRetVoid(ctx.lc.builder);
char *error = NULL;
LLVMVerifyModule(mod, LLVMPrintMessageAction, &error);
LLVMDumpModule(mod);
LLVMDisposeMessage(error);
+ LLVMOrcModuleHandle mod_handle;
+ LLVMErrorRef error_ref = LLVMOrcAddEagerlyCompiledIR(llvm_ref->orc_ref,
+ &mod_handle,
+ mod,
+ orc_sym_resolver,
+ (void *)(llvm_ref->orc_ref));
+ LLVMDumpModule(mod);
+ char *def_triple = LLVMGetDefaultTargetTriple(); // E.g. "x86_64-linux-gnu"
+ LLVMDisasmContextRef disasm = LLVMCreateDisasm(def_triple, NULL,
+ 0, NULL,
+ NULL);
+ if (disasm) {
+LLVMOrcTargetAddress MainAddr;
+LLVMOrcGetSymbolAddress(llvm_ref->orc_ref, &MainAddr ,"main_function");
+ const uint8_t *bytes = (const uint8_t *)MainAddr;
+ char outline[1024];
+uint64_t pc;
+ pc = 0;
+uint64_t extent = 200;
+ while (pc < extent) {
+ size_t Size;
+
+ /*
+ * Print address. We use addresses relative to the start of the function,
+ * so that between runs.
+ */
+
+
+ Size = LLVMDisasmInstruction(disasm, (uint8_t *)bytes + pc, extent - pc, 0, outline,
+ sizeof outline);
+
+ /*
+ * Print the instruction.
+ */
+ printf("\t%s \n", outline);
+
+
+ /*
+ * Stop disassembling on return statements, if there is no record of a
+ * jump to a successive address.
+ *
+ * XXX: This currently assumes x86
+ */
+
+ if (Size == 1 && bytes[pc] == 0xc3) {
+ break;
+ }
+
+ /*
+ * Advance.
+ */
+
+ pc += Size;
+
+ if (pc >= extent) {
+ break;
+ }
+ }
+ }
return mod;
// LLVMModuleRef mod = LLVMModuleCreateWithName("libresoc_mod");
// LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() };