Mesa (master): gallivm: work around LLVM 2.6 bug when calling C functions

Brian Paul brianp at kemper.freedesktop.org
Thu Dec 16 17:20:56 UTC 2010


Module: Mesa
Branch: master
Commit: ee16e97ed1d0921c533c77688b278bef393d9922
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ee16e97ed1d0921c533c77688b278bef393d9922

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Dec 16 10:13:02 2010 -0700

gallivm: work around LLVM 2.6 bug when calling C functions

Create a constant int pointer to the C function, then cast it to the
function's type.  This avoids using trampoline code which seem to be
inadvertantly freed by LLVM in some situations (which leads to segfaults).
The root issue and work-around were found by José.

NOTE: This is a candidate for the 7.10 branch

---

 src/gallium/auxiliary/gallivm/lp_bld_const.h      |   18 +++++++
 src/gallium/auxiliary/gallivm/lp_bld_format_aos.c |   54 ++++++++++++++++----
 2 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_const.h b/src/gallium/auxiliary/gallivm/lp_bld_const.h
index c749a7a..680211f 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_const.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_const.h
@@ -125,4 +125,22 @@ lp_build_const_float(struct gallivm_state *gallivm, float x)
 }
 
 
+/** Return constant-valued pointer to int */
+static INLINE LLVMValueRef
+lp_build_const_int_pointer(struct gallivm_state *gallivm, const void *ptr)
+{
+   LLVMTypeRef int_type;
+   LLVMValueRef v;
+
+   /* int type large enough to hold a pointer */
+   int_type = LLVMIntTypeInContext(gallivm->context, 8 * sizeof(void *));
+   v = LLVMConstInt(int_type, (unsigned long long) ptr, 0);
+   v = LLVMBuildIntToPtr(gallivm->builder, v,
+                         LLVMPointerType(int_type, 0),
+                         "cast int to ptr");
+   return v;
+}
+
+
+
 #endif /* !LP_BLD_CONST_H */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index 75d2e66..905cf66 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -36,6 +36,7 @@
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_pointer.h"
 #include "util/u_string.h"
 
 #include "lp_bld_arit.h"
@@ -520,6 +521,7 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
       LLVMValueRef tmp_ptr;
       LLVMValueRef tmp;
       LLVMValueRef res;
+      LLVMValueRef callee;
       unsigned k;
 
       util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_8unorm",
@@ -535,6 +537,10 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
 
       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;
@@ -542,19 +548,26 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
          ret_type = LLVMVoidTypeInContext(gallivm->context);
          arg_types[0] = pi8t;
          arg_types[1] = pi8t;
-         arg_types[3] = arg_types[2] = LLVMIntTypeInContext(gallivm->context, sizeof(unsigned) * 8);
-         function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0);
+         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));
-
-         LLVMAddGlobalMapping(gallivm->engine, function,
-                              func_to_pointer((func_pointer)format_desc->fetch_rgba_8unorm));
       }
 
+      /* 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, i32t, "");
 
       res = LLVMGetUndef(LLVMVectorType(i32t, num_pixels));
@@ -619,10 +632,13 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
       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",
@@ -638,26 +654,42 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
 
       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] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0);
-         arg_types[3] = arg_types[2] = LLVMIntTypeInContext(gallivm->context, sizeof(unsigned) * 8);
-         function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0);
+         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));
-
-         LLVMAddGlobalMapping(gallivm->engine, function,
-                              func_to_pointer((func_pointer)format_desc->fetch_rgba_float));
       }
 
+      /* 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, "");
 
       /*




More information about the mesa-commit mailing list