Hi,

On Wednesday, September 24, 2014 12:42:24 Jose Fonseca wrote:
> We're not the only one with similar needs.  Webkit has similar needs. 
> Though they opted by using LLVMCreateSimpleMCJITMemoryManager 
> https://trac.webkit.org/browser/trunk/Tools/ReducedFTL/ReducedFTL.c#L321 
>   and implemeting the memory manager themselves.
> 
> We could do the same.  We even have the code for it in 
> src/gallium/auxiliary/rtasm/rtasm_execmem.*    ( And if we add a mutex 
> we could make this thread safe too, without needing multiple jit 
> managers around)
> 
> 
> The other alternative would be to have another function besides 
> LLVMCreateSimpleMCJITMemoryManager that would create a standard 
> LLVMMCJITMemoryManagerRef.
> 
> 
> That said, the way we use these things are still a bit in flux. Mathias 
> has some pending patches.   BTW, Mathis, should I submit your patches 
> for making llvmpipe thread safe?  Also, what are your thoughts on this 
> issue?

Ok, I have updated the patches to keep that compiling with both versions
and still be thread safe with old enough llvm.
These updated ones are attached to this mail.
I don't mind if you want to push them now.
I expect that its introducing less potential conflicts on your
site if you can coordinate when these get applied?
And thanks for the heads up!!

With respect to that shader memory manager, I have just tried to
make this recently introduced piece of code work with multiple threads in 
action.
So, I do not need to keep this one. The time before that shader memory manager
was even easier for thread safety and the introduction of that one introduced
additional complications.
So every simple algorithm there is fine as long as the appropriate locks
are there to make them thread safe.
I only had a short look into your proposal, both variants look fine to me.

Thanks

Mathias
>From ae29a897c2b330408cdffd82c6b326121d1a6681 Mon Sep 17 00:00:00 2001
Message-Id: <ae29a897c2b330408cdffd82c6b326121d1a6681.1411584609.git.mathias.froehl...@gmx.net>
In-Reply-To: <b82942217cba1a87df430e688e5a75491a205917.1411584609.git.mathias.froehl...@gmx.net>
References: <b82942217cba1a87df430e688e5a75491a205917.1411584609.git.mathias.froehl...@gmx.net>
From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <mathias.froehl...@gmx.net>
Date: Sun, 21 Sep 2014 08:54:00 +0200
Subject: [PATCH 3/3] llvmpipe: Reuse llvmpipes LLVMContext in the draw
 context.

Reuse the LLVMContext already allocated in llvmpipe_context
for draw_llvm if ppossible. This should decrease the memory
footprint of an llvmpipe context.

Signed-off-by: Mathias Froehlich <mathias.froehl...@web.de>
---
 src/gallium/auxiliary/draw/draw_context.c | 18 ++++++++++++++----
 src/gallium/auxiliary/draw/draw_context.h |  5 +++++
 src/gallium/auxiliary/draw/draw_llvm.c    | 11 ++++++++---
 src/gallium/auxiliary/draw/draw_llvm.h    |  3 ++-
 src/gallium/drivers/llvmpipe/lp_context.c |  3 ++-
 5 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 001446f..18af6b5 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -81,7 +81,8 @@ draw_get_option_use_llvm(void)
  * Create new draw module context with gallivm state for LLVM JIT.
  */
 static struct draw_context *
-draw_create_context(struct pipe_context *pipe, boolean try_llvm)
+draw_create_context(struct pipe_context *pipe, void *context,
+                    boolean try_llvm)
 {
    struct draw_context *draw = CALLOC_STRUCT( draw_context );
    if (draw == NULL)
@@ -92,7 +93,7 @@ draw_create_context(struct pipe_context *pipe, boolean try_llvm)
 
 #if HAVE_LLVM
    if (try_llvm && draw_get_option_use_llvm()) {
-      draw->llvm = draw_llvm_create(draw);
+      draw->llvm = draw_llvm_create(draw, (LLVMContextRef)context);
       if (!draw->llvm)
          goto err_destroy;
    }
@@ -122,17 +123,26 @@ err_out:
 struct draw_context *
 draw_create(struct pipe_context *pipe)
 {
-   return draw_create_context(pipe, TRUE);
+   return draw_create_context(pipe, NULL, TRUE);
 }
 
 
+#if HAVE_LLVM
+struct draw_context *
+draw_create_with_llvm_context(struct pipe_context *pipe,
+                              void *context)
+{
+   return draw_create_context(pipe, context, TRUE);
+}
+#endif
+
 /**
  * Create a new draw context, without LLVM JIT.
  */
 struct draw_context *
 draw_create_no_llvm(struct pipe_context *pipe)
 {
-   return draw_create_context(pipe, FALSE);
+   return draw_create_context(pipe, NULL, FALSE);
 }
 
 
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 48549fe..a5a6df5 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -64,6 +64,11 @@ struct draw_so_target {
 
 struct draw_context *draw_create( struct pipe_context *pipe );
 
+#if HAVE_LLVM
+struct draw_context *draw_create_with_llvm_context(struct pipe_context *pipe,
+                                                   void *context);
+#endif
+
 struct draw_context *draw_create_no_llvm(struct pipe_context *pipe);
 
 void draw_destroy( struct draw_context *draw );
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index ae14fed..2b0bd79 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -480,7 +480,7 @@ get_vertex_header_ptr_type(struct draw_llvm_variant *variant)
  * Create per-context LLVM info.
  */
 struct draw_llvm *
-draw_llvm_create(struct draw_context *draw)
+draw_llvm_create(struct draw_context *draw, LLVMContextRef context)
 {
    struct draw_llvm *llvm;
 
@@ -492,7 +492,11 @@ draw_llvm_create(struct draw_context *draw)
 
    llvm->draw = draw;
 
-   llvm->context = LLVMContextCreate();
+   llvm->context = context;
+   if (!llvm->context) {
+      llvm->context = LLVMContextCreate();
+      llvm->context_owned = true;
+   }
    if (!llvm->context)
       goto fail;
 
@@ -516,7 +520,8 @@ fail:
 void
 draw_llvm_destroy(struct draw_llvm *llvm)
 {
-   LLVMContextDispose(llvm->context);
+   if (llvm->context_owned)
+      LLVMContextDispose(llvm->context);
    llvm->context = NULL;
 
    /* XXX free other draw_llvm data? */
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index a4bd1ed..54a7da2 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -462,6 +462,7 @@ struct draw_llvm {
    struct draw_context *draw;
 
    LLVMContextRef context;
+   boolean context_owned;
 
    struct draw_jit_context jit_context;
    struct draw_gs_jit_context gs_jit_context;
@@ -490,7 +491,7 @@ llvm_geometry_shader(struct draw_geometry_shader *gs)
 
 
 struct draw_llvm *
-draw_llvm_create(struct draw_context *draw);
+draw_llvm_create(struct draw_context *draw, LLVMContextRef llvm_context);
 
 void
 draw_llvm_destroy(struct draw_llvm *llvm);
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index 3a9b4c2..37b1ff4 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -171,7 +171,8 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
    /*
     * Create drawing context and plug our rendering stage into it.
     */
-   llvmpipe->draw = draw_create(&llvmpipe->pipe);
+   llvmpipe->draw = draw_create_with_llvm_context(&llvmpipe->pipe,
+                                                  llvmpipe->context);
    if (!llvmpipe->draw)
       goto fail;
 
-- 
1.9.3

>From b3cbe1c5c188073361e027b43316876412820cd5 Mon Sep 17 00:00:00 2001
Message-Id: <b3cbe1c5c188073361e027b43316876412820cd5.1411584609.git.mathias.froehl...@gmx.net>
In-Reply-To: <b82942217cba1a87df430e688e5a75491a205917.1411584609.git.mathias.froehl...@gmx.net>
References: <b82942217cba1a87df430e688e5a75491a205917.1411584609.git.mathias.froehl...@gmx.net>
From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <mathias.froehl...@gmx.net>
Date: Sun, 13 Jul 2014 12:49:41 +0200
Subject: [PATCH 2/3] llvmpipe: Make a llvmpipe OpenGL context thread safe.

This fixes the remaining problem with the recently introduced
global jit memory manager. This change again uses a memory manager
that is local to gallivm_state. This implementation still frees
the majority of the memory immediately after compilation.
Only the generated code is deferred until this code is no longer used.

This change and the previous one using private LLVMContext instances
I can now safely run several independent OpenGL contexts driven
by llvmpipe from different threads.

Reviewed-by: Jose Fonseca <jfons...@vmware.com>
Signed-off-by: Mathias Froehlich <mathias.froehl...@web.de>
---
 src/gallium/auxiliary/gallivm/lp_bld_init.c   | 13 +++++++++
 src/gallium/auxiliary/gallivm/lp_bld_init.h   |  3 ++
 src/gallium/auxiliary/gallivm/lp_bld_misc.cpp | 41 +++++++++++++++------------
 src/gallium/auxiliary/gallivm/lp_bld_misc.h   |  3 ++
 4 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c
index 910b459..93de8ac 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c
@@ -219,6 +219,10 @@ gallivm_free_code(struct gallivm_state *gallivm)
    assert(!gallivm->engine);
    lp_free_generated_code(gallivm->code);
    gallivm->code = NULL;
+#if HAVE_LLVM < 0x0306
+   LLVMDisposeMCJITMemoryManager(gallivm->memorymgr);
+   gallivm->memorymgr = NULL;
+#endif
 }
 
 
@@ -240,6 +244,7 @@ init_gallivm_engine(struct gallivm_state *gallivm)
       ret = lp_build_create_jit_compiler_for_module(&gallivm->engine,
                                                     &gallivm->code,
                                                     gallivm->module,
+                                                    gallivm->memorymgr,
                                                     (unsigned) optlevel,
                                                     USE_MCJIT,
                                                     &error);
@@ -311,6 +316,14 @@ init_gallivm_state(struct gallivm_state *gallivm, const char *name,
    if (!gallivm->builder)
       goto fail;
 
+#if HAVE_LLVM < 0x0306
+   gallivm->memorymgr = lp_get_default_memory_manager();
+   if (!gallivm->memorymgr)
+      goto fail;
+#else
+   gallivm->memorymgr = 0;
+#endif
+
    /* FIXME: MC-JIT only allows compiling one module at a time, and it must be
     * complete when MC-JIT is created. So defer the MC-JIT engine creation for
     * now.
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h
index 8f20158..7459b71 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h
@@ -44,7 +44,10 @@ struct gallivm_state
    LLVMPassManagerRef passmgr;
    LLVMContextRef context;
    LLVMBuilderRef builder;
+/* #if HAVE_LLVM < 0x0306 */
+   LLVMMCJITMemoryManagerRef memorymgr;
    struct lp_generated_code *code;
+/* #endif */
    unsigned compiled;
 };
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
index 06d29bc..c173ab6 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
+++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
@@ -322,15 +322,15 @@ class DelegatingJITMemoryManager : public llvm::JITMemoryManager {
  */
 class ShaderMemoryManager : public DelegatingJITMemoryManager {
 
-   static llvm::JITMemoryManager *TheMM;
-   static unsigned NumUsers;
+   llvm::JITMemoryManager *TheMM;
 
    struct GeneratedCode {
       typedef std::vector<void *> Vec;
       Vec FunctionBody, ExceptionTable;
+      llvm::JITMemoryManager *TheMM;
 
-      GeneratedCode() {
-         ++NumUsers;
+      GeneratedCode(llvm::JITMemoryManager *MM) {
+         TheMM = MM;
       }
 
       ~GeneratedCode() {
@@ -347,27 +347,20 @@ class ShaderMemoryManager : public DelegatingJITMemoryManager {
 	 for ( i = ExceptionTable.begin(); i != ExceptionTable.end(); ++i )
 	    TheMM->deallocateExceptionTable(*i);
 #endif
-         --NumUsers;
-         if (NumUsers == 0) {
-            delete TheMM;
-            TheMM = 0;
-         }
       }
    };
 
    GeneratedCode *code;
 
    llvm::JITMemoryManager *mgr() const {
-      if (!TheMM) {
-         TheMM = CreateDefaultMemManager();
-      }
       return TheMM;
    }
 
    public:
 
-      ShaderMemoryManager() {
-         code = new GeneratedCode;
+      ShaderMemoryManager(llvm::JITMemoryManager* MM) {
+         TheMM = MM;
+         code = new GeneratedCode(MM);
       }
 
       virtual ~ShaderMemoryManager() {
@@ -398,9 +391,6 @@ class ShaderMemoryManager : public DelegatingJITMemoryManager {
       }
 };
 
-llvm::JITMemoryManager *ShaderMemoryManager::TheMM = 0;
-unsigned ShaderMemoryManager::NumUsers = 0;
-
 #endif
 
 /**
@@ -418,6 +408,7 @@ LLVMBool
 lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
                                         lp_generated_code **OutCode,
                                         LLVMModuleRef M,
+                                        LLVMMCJITMemoryManagerRef CMM,
                                         unsigned OptLevel,
                                         int useMCJIT,
                                         char **OutError)
@@ -510,7 +501,8 @@ lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
    builder.setMCPU(MCPU);
 #endif
 
-   ShaderMemoryManager *MM = new ShaderMemoryManager();
+   llvm::JITMemoryManager* JMM = reinterpret_cast<llvm::JITMemoryManager*>(CMM);
+   ShaderMemoryManager *MM = new ShaderMemoryManager(JMM);
    *OutCode = MM->getGeneratedCode();
 
    builder.setJITMemoryManager(MM);
@@ -549,3 +541,16 @@ lp_free_generated_code(struct lp_generated_code *code)
    ShaderMemoryManager::freeGeneratedCode(code);
 #endif
 }
+
+extern "C"
+LLVMMCJITMemoryManagerRef
+lp_get_default_memory_manager()
+{
+#if HAVE_LLVM < 0x0306
+   llvm::JITMemoryManager *mm;
+   mm = llvm::JITMemoryManager::CreateDefaultMemManager();
+   return reinterpret_cast<LLVMMCJITMemoryManagerRef>(mm);
+#else
+   return 0;
+#endif
+}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.h b/src/gallium/auxiliary/gallivm/lp_bld_misc.h
index 64d2a04..40d3e79 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_misc.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.h
@@ -54,6 +54,7 @@ extern int
 lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
                                         struct lp_generated_code **OutCode,
                                         LLVMModuleRef M,
+                                        LLVMMCJITMemoryManagerRef MM,
                                         unsigned OptLevel,
                                         int useMCJIT,
                                         char **OutError);
@@ -61,6 +62,8 @@ lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
 extern void
 lp_free_generated_code(struct lp_generated_code *code);
 
+extern LLVMMCJITMemoryManagerRef
+lp_get_default_memory_manager();
 
 #ifdef __cplusplus
 }
-- 
1.9.3

>From b82942217cba1a87df430e688e5a75491a205917 Mon Sep 17 00:00:00 2001
Message-Id: <b82942217cba1a87df430e688e5a75491a205917.1411584609.git.mathias.froehl...@gmx.net>
From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <mathias.froehl...@gmx.net>
Date: Thu, 28 Aug 2014 19:49:35 +0200
Subject: [PATCH 1/3] llvmpipe: Use two LLVMContexts per OpenGL context instead
 of a global one.

This is one step to make llvmpipe thread safe as mandated by the OpenGL
standard. Using the global LLVMContext is obviously a problem for
that kind of use pattern. The patch introduces two LLVMContext
instances that are private to an OpenGL context and used for all
compiles. One is put into struct draw_llvm and the other
one into struct llvmpipe_context.

Reviewed-by: Jose Fonseca <jfons...@vmware.com>
Signed-off-by: Mathias Froehlich <mathias.froehl...@web.de>
---
 src/gallium/auxiliary/draw/draw_llvm.c        | 15 ++++++++++++--
 src/gallium/auxiliary/draw/draw_llvm.h        |  2 ++
 src/gallium/auxiliary/gallivm/lp_bld_init.c   | 28 +++++++--------------------
 src/gallium/auxiliary/gallivm/lp_bld_init.h   |  2 +-
 src/gallium/drivers/llvmpipe/lp_context.c     |  7 +++++++
 src/gallium/drivers/llvmpipe/lp_context.h     |  3 +++
 src/gallium/drivers/llvmpipe/lp_state_fs.c    |  2 +-
 src/gallium/drivers/llvmpipe/lp_state_setup.c |  2 +-
 src/gallium/drivers/llvmpipe/lp_test_arit.c   |  2 +-
 src/gallium/drivers/llvmpipe/lp_test_blend.c  |  2 +-
 src/gallium/drivers/llvmpipe/lp_test_conv.c   |  2 +-
 src/gallium/drivers/llvmpipe/lp_test_format.c |  2 +-
 src/gallium/drivers/llvmpipe/lp_test_printf.c |  2 +-
 13 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index e8e837a..ae14fed 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -492,6 +492,10 @@ draw_llvm_create(struct draw_context *draw)
 
    llvm->draw = draw;
 
+   llvm->context = LLVMContextCreate();
+   if (!llvm->context)
+      goto fail;
+
    llvm->nr_variants = 0;
    make_empty_list(&llvm->vs_variants_list);
 
@@ -499,6 +503,10 @@ draw_llvm_create(struct draw_context *draw)
    make_empty_list(&llvm->gs_variants_list);
 
    return llvm;
+
+fail:
+   draw_llvm_destroy(llvm);
+   return NULL;
 }
 
 
@@ -508,6 +516,9 @@ draw_llvm_create(struct draw_context *draw)
 void
 draw_llvm_destroy(struct draw_llvm *llvm)
 {
+   LLVMContextDispose(llvm->context);
+   llvm->context = NULL;
+
    /* XXX free other draw_llvm data? */
    FREE(llvm);
 }
@@ -539,7 +550,7 @@ draw_llvm_create_variant(struct draw_llvm *llvm,
    util_snprintf(module_name, sizeof(module_name), "draw_llvm_vs_variant%u",
                  variant->shader->variants_cached);
 
-   variant->gallivm = gallivm_create(module_name);
+   variant->gallivm = gallivm_create(module_name, llvm->context);
 
    create_jit_types(variant);
 
@@ -2194,7 +2205,7 @@ draw_gs_llvm_create_variant(struct draw_llvm *llvm,
    util_snprintf(module_name, sizeof(module_name), "draw_llvm_gs_variant%u",
                  variant->shader->variants_cached);
 
-   variant->gallivm = gallivm_create(module_name);
+   variant->gallivm = gallivm_create(module_name, llvm->context);
 
    create_gs_jit_types(variant);
 
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index ed97cf7..a4bd1ed 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -461,6 +461,8 @@ struct llvm_geometry_shader {
 struct draw_llvm {
    struct draw_context *draw;
 
+   LLVMContextRef context;
+
    struct draw_jit_context jit_context;
    struct draw_gs_jit_context gs_jit_context;
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c
index 243d248..910b459 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c
@@ -78,17 +78,6 @@
 void LLVMLinkInMCJIT();
 #endif
 
-/*
- * LLVM has several global caches which pointing/derived from objects
- * owned by the context, so if we freeing contexts causes
- * memory leaks and false cache hits when these objects are destroyed.
- *
- * TODO: For thread safety on multi-threaded OpenGL we should use one LLVM
- * context per thread, and put them in a pool when threads are destroyed.
- */
-#define USE_GLOBAL_CONTEXT 1
-
-
 #ifdef DEBUG
 unsigned gallivm_debug = 0;
 
@@ -209,8 +198,7 @@ gallivm_free_ir(struct gallivm_state *gallivm)
    if (gallivm->builder)
       LLVMDisposeBuilder(gallivm->builder);
 
-   if (!USE_GLOBAL_CONTEXT && gallivm->context)
-      LLVMContextDispose(gallivm->context);
+   /* The LLVMContext should be owned by the parent of gallivm. */
 
    gallivm->engine = NULL;
    gallivm->target = NULL;
@@ -301,18 +289,16 @@ fail:
  * \return  TRUE for success, FALSE for failure
  */
 static boolean
-init_gallivm_state(struct gallivm_state *gallivm, const char *name)
+init_gallivm_state(struct gallivm_state *gallivm, const char *name,
+                   LLVMContextRef context)
 {
    assert(!gallivm->context);
    assert(!gallivm->module);
 
    lp_build_init();
 
-   if (USE_GLOBAL_CONTEXT) {
-      gallivm->context = LLVMGetGlobalContext();
-   } else {
-      gallivm->context = LLVMContextCreate();
-   }
+   gallivm->context = context;
+
    if (!gallivm->context)
       goto fail;
 
@@ -485,13 +471,13 @@ lp_build_init(void)
  * Create a new gallivm_state object.
  */
 struct gallivm_state *
-gallivm_create(const char *name)
+gallivm_create(const char *name, LLVMContextRef context)
 {
    struct gallivm_state *gallivm;
 
    gallivm = CALLOC_STRUCT(gallivm_state);
    if (gallivm) {
-      if (!init_gallivm_state(gallivm, name)) {
+      if (!init_gallivm_state(gallivm, name, context)) {
          FREE(gallivm);
          gallivm = NULL;
       }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h
index 2e32cf8..8f20158 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h
@@ -54,7 +54,7 @@ lp_build_init(void);
 
 
 struct gallivm_state *
-gallivm_create(const char *name);
+gallivm_create(const char *name, LLVMContextRef context);
 
 void
 gallivm_destroy(struct gallivm_state *gallivm);
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index d9696c2..3a9b4c2 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -93,6 +93,9 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
 
    lp_delete_setup_variants(llvmpipe);
 
+   LLVMContextDispose(llvmpipe->context);
+   llvmpipe->context = NULL;
+
    align_free( llvmpipe );
 }
 
@@ -161,6 +164,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
    llvmpipe_init_context_resource_funcs( &llvmpipe->pipe );
    llvmpipe_init_surface_functions(llvmpipe);
 
+   llvmpipe->context = LLVMContextCreate();
+   if (!llvmpipe->context)
+      goto fail;
+
    /*
     * Create drawing context and plug our rendering stage into it.
     */
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index ee0831f..0d47c0d 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -153,6 +153,9 @@ struct llvmpipe_context {
    struct pipe_query *render_cond_query;
    uint render_cond_mode;
    boolean render_cond_cond;
+
+   /** The LLVMContext to use for LLVM related work */
+   LLVMContextRef context;
 };
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 0b74d15..ff2939d 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -2565,7 +2565,7 @@ generate_variant(struct llvmpipe_context *lp,
    util_snprintf(module_name, sizeof(module_name), "fs%u_variant%u",
                  shader->no, shader->variants_created);
 
-   variant->gallivm = gallivm_create(module_name);
+   variant->gallivm = gallivm_create(module_name, lp->context);
    if (!variant->gallivm) {
       FREE(variant);
       return NULL;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c
index 63c92d5..49741db 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c
@@ -731,7 +731,7 @@ generate_setup_variant(struct lp_setup_variant_key *key,
    util_snprintf(func_name, sizeof(func_name), "setup_variant_%u",
                  variant->no);
 
-   variant->gallivm = gallivm = gallivm_create(func_name);
+   variant->gallivm = gallivm = gallivm_create(func_name, lp->context);
    if (!variant->gallivm) {
       goto fail;
    }
diff --git a/src/gallium/drivers/llvmpipe/lp_test_arit.c b/src/gallium/drivers/llvmpipe/lp_test_arit.c
index bf405a5..660ad4d 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_arit.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_arit.c
@@ -354,7 +354,7 @@ test_unary(unsigned verbose, FILE *fp, const struct unary_test_t *test)
       in[i] = 1.0;
    }
 
-   gallivm = gallivm_create("test_module");
+   gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
 
    test_func = build_unary_test_func(gallivm, test);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
index 4775aff..37420b0 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_blend.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -450,7 +450,7 @@ test_one(unsigned verbose,
    if(verbose >= 1)
       dump_blend_type(stdout, blend, type);
 
-   gallivm = gallivm_create("test_module");
+   gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
 
    func = add_blend_test(gallivm, blend, type);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index 948a218..8290da4 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -211,7 +211,7 @@ test_one(unsigned verbose,
 
    eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type));
 
-   gallivm = gallivm_create("test_module");
+   gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
 
    func = add_conv_test(gallivm, src_type, num_srcs, dst_type, num_dsts);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c
index 2c83219..8a81151 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_format.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_format.c
@@ -138,7 +138,7 @@ test_format_float(unsigned verbose, FILE *fp,
    boolean success = TRUE;
    unsigned i, j, k, l;
 
-   gallivm = gallivm_create("test_module_float");
+   gallivm = gallivm_create("test_module_float", LLVMGetGlobalContext());
 
    fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_float32_vec4_type());
 
diff --git a/src/gallium/drivers/llvmpipe/lp_test_printf.c b/src/gallium/drivers/llvmpipe/lp_test_printf.c
index 4b74ae9..fe4ce0f 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_printf.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_printf.c
@@ -94,7 +94,7 @@ test_printf(unsigned verbose, FILE *fp,
    test_printf_t test_printf_func;
    boolean success = TRUE;
 
-   gallivm = gallivm_create("test_module");
+   gallivm = gallivm_create("test_module", LLVMGetGlobalContext());
 
    test = add_printf_test(gallivm);
 
-- 
1.9.3

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to