Updated code generation so that for vertex shader output position is written at last...
[mesa.git] / src / libre-soc / vulkan / libresoc_llvm.c
index 100fc1ea2347f914765bff89fd149e3b55b1312b..14f4de0dbd54072c44b4115992cb1a52508cd97b 100644 (file)
@@ -3,8 +3,13 @@
 
 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;
@@ -121,6 +126,17 @@ void handle_shader_output_decl(struct libresoc_nir_tran_ctx *ctx,
    }
 }
 
+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)
@@ -179,6 +195,26 @@ static LLVMValueRef get_src(struct libresoc_nir_tran_ctx *ctx, nir_src src)
    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;
@@ -683,6 +719,146 @@ static LLVMTypeRef glsl_to_llvm_type(struct libresoc_llvm_context *lc, const str
    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;
@@ -876,15 +1052,6 @@ static void visit_deref(struct libresoc_nir_tran_ctx *ctx, nir_deref_instr *inst
    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);
@@ -1737,6 +1904,32 @@ static void visit_store_var(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins
 
    switch (deref->mode) {
    case nir_var_shader_out:
+       if (ctx->stage == MESA_SHADER_VERTEX && var->data.location == VARYING_SLOT_POS) {
+
+           LLVMValueRef vertexCache = LLVMGetParam(ctx->main_function, 2); 
+           LLVMValueRef idx[3];
+
+           idx[0] = LLVMConstInt(ctx->lc.i32, 0, false);
+           idx[1] = LLVMConstInt(ctx->lc.i32, 0, false);
+           LLVMValueRef outPos = LLVMConstInBoundsGEP(vertexCache,
+                   idx,
+                   2);
+           LLVMBuildStore(ctx->lc.builder, src, outPos);
+           break;
+       }
+       if (ctx->stage == MESA_SHADER_FRAGMENT && var->data.location == FRAG_RESULT_DATA0) {
+
+           LLVMValueRef outColor = LLVMGetParam(ctx->main_function, 4); 
+           // LLVMValueRef idx[3];
+
+           // idx[0] = LLVMConstInt(ctx->lc.i32, 0, false);
+           // idx[1] = LLVMConstInt(ctx->lc.i32, 0, false);
+           // LLVMValueRef outPos = LLVMConstInBoundsGEP(vertexCache,
+           //         idx,
+           //         2);
+           LLVMBuildStore(ctx->lc.builder, src, outColor);
+           break;
+       }
       /* TODO: remove this after RADV switches to lowered IO */
       // if (ctx->stage == MESA_SHADER_TESS_CTRL) {
       //    LLVMValueRef vertex_index = NULL;
@@ -1903,8 +2096,9 @@ static void visit_intrinsic(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins
       // result = ctx->abi->load_local_group_size(ctx->abi);
       break;
    case nir_intrinsic_load_vertex_id:
-      result = LLVMBuildAdd(ctx->lc.builder, LLVMGetParam(ctx->main_function, ctx->args.vertex_id.arg_index),
-                             LLVMGetParam(ctx->main_function, ctx->args.base_vertex.arg_index), "");
+      result = LLVMGetParam(ctx->main_function, 1); 
+      // result = LLVMBuildAdd(ctx->lc.builder, LLVMGetParam(ctx->main_function, ctx->args.vertex_id.arg_index),
+      //                        LLVMGetParam(ctx->main_function, ctx->args.base_vertex.arg_index), "");
       break;
    case nir_intrinsic_load_vertex_id_zero_base: {
       // result = ctx->abi->vertex_id;
@@ -2062,10 +2256,10 @@ static void visit_intrinsic(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins
       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:
@@ -2335,61 +2529,61 @@ static void visit_intrinsic(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins
       // 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:
@@ -2519,10 +2713,39 @@ LLVMModuleRef libresoc_nir_translate(struct libresoc_llvm *llvm_ref, struct nir_
       arg_types[i] = arg_llvm_type(ctx.args.args[i].type, ctx.args.args[i].size, &ctx.lc);
    }
 
-   //TODO: this is zero argument function and returns void
-   LLVMTypeRef main_function_type = LLVMFunctionType(ret_type, arg_types, ctx.args.arg_count, 0);
-
-   LLVMValueRef main_function = LLVMAddFunction(mod, "main_function", main_function_type);
+    LLVMTypeRef main_function_type;
+    if(nir->info.stage == MESA_SHADER_VERTEX) {
+        LLVMTypeRef arg_types[32];
+        LLVMTypeRef floatType = LLVMFloatTypeInContext(llvm_ref->lc.context);
+        LLVMTypeRef float4 = LLVMVectorType(floatType, 4);
+        LLVMTypeRef f4arrayType = LLVMArrayType(float4, 10);
+        arg_types[0] = float4;
+        arg_types[1] = f4arrayType;
+        LLVMTypeRef vertexCacheType = LLVMStructTypeInContext(llvm_ref->lc.context, arg_types, 2, false);
+        LLVMTypeRef gpuStatePtrType = LLVMPointerType(LLVMStructCreateNamed(llvm_ref->lc.context, "GPUState"), 0);
+        arg_types[0] = gpuStatePtrType;
+        arg_types[1] = LLVMIntTypeInContext(llvm_ref->lc.context, 32);
+        arg_types[2] = LLVMPointerType(vertexCacheType, 0);
+        main_function_type = LLVMFunctionType(ret_type, arg_types, 3, 0);
+    } else {
+
+        LLVMTypeRef floatType = LLVMFloatTypeInContext(llvm_ref->lc.context);
+        LLVMTypeRef float4 = LLVMVectorType(floatType, 4);
+        LLVMTypeRef f4arrayType = LLVMArrayType(float4, 10);
+        arg_types[0] = float4;
+        arg_types[1] = f4arrayType;
+        LLVMTypeRef vertexCacheType = LLVMStructTypeInContext(llvm_ref->lc.context, arg_types, 2, false);
+        arg_types[3] = LLVMPointerType(vertexCacheType, 0);
+        LLVMTypeRef gpuStatePtrType = LLVMPointerType(LLVMStructCreateNamed(llvm_ref->lc.context, "GPUState"), 0);
+        arg_types[0] = gpuStatePtrType;
+        arg_types[1] = LLVMFloatTypeInContext(llvm_ref->lc.context);
+        arg_types[2] = LLVMPointerType(float4, 0);
+        arg_types[4] = LLVMPointerType(float4, 0);
+        main_function_type = LLVMFunctionType(ret_type, arg_types, 3, 0);
+        //TODO: this is zero argument function and returns void
+        main_function_type = LLVMFunctionType(ret_type, arg_types, 5, 0);
+    }
+   LLVMValueRef main_function = LLVMAddFunction(mod, gl_shader_stage_name(nir->info.stage), main_function_type);
    LLVMBasicBlockRef main_function_body =
       LLVMAppendBasicBlockInContext(ctx.lc.context, main_function, "main_body");
    LLVMPositionBuilderAtEnd(ctx.lc.builder, main_function_body);
@@ -2548,10 +2771,78 @@ LLVMModuleRef libresoc_nir_translate(struct libresoc_llvm *llvm_ref, struct nir_
     // 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 ,gl_shader_stage_name(nir->info.stage));
+        // if(nir->info.stage == MESA_SHADER_VERTEX)
+        // {
+        //     pipeline->vs = (VertexShader)MainAddr;
+        // }
+        // else if(nir->info.stage == MESA_SHADER_FRAGMENT)
+        // {
+        //     pipeline->fs = (FragmentShader)MainAddr;
+        // }
+        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() };
@@ -2573,3 +2864,9 @@ LLVMModuleRef libresoc_nir_translate(struct libresoc_llvm *llvm_ref, struct nir_
     //         orc_sym_resolver,
     //         (void *)(llvm_ref->orc_ref));
 }
+
+Shader GetFuncPointer(struct libresoc_llvm *llvm_ref, const char *name) {
+    LLVMOrcTargetAddress MainAddr;
+    LLVMOrcGetSymbolAddress(llvm_ref->orc_ref, &MainAddr , name);
+    return (Shader)MainAddr;
+}