5f1268bf4f80cdb7d3d17f99c6263c8b541faf13
[mesa.git] / src / mesa / pipe / llvm / gallivm_cpu.cpp
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Zack Rusin zack@tungstengraphics.com
31 */
32 #ifdef MESA_LLVM
33
34 #include "gallivm.h"
35 #include "gallivm_p.h"
36
37 #include "instructions.h"
38 #include "loweringpass.h"
39 #include "storage.h"
40 #include "tgsitollvm.h"
41
42 #include "pipe/p_context.h"
43 #include "pipe/p_shader_tokens.h"
44
45 #include "pipe/tgsi/exec/tgsi_exec.h"
46 #include "pipe/tgsi/util/tgsi_dump.h"
47
48 #include <llvm/Module.h>
49 #include <llvm/CallingConv.h>
50 #include <llvm/Constants.h>
51 #include <llvm/DerivedTypes.h>
52 #include <llvm/Instructions.h>
53 #include <llvm/ModuleProvider.h>
54 #include <llvm/Pass.h>
55 #include <llvm/PassManager.h>
56 #include <llvm/ParameterAttributes.h>
57 #include <llvm/Support/PatternMatch.h>
58 #include <llvm/ExecutionEngine/JIT.h>
59 #include <llvm/ExecutionEngine/Interpreter.h>
60 #include <llvm/ExecutionEngine/GenericValue.h>
61 #include <llvm/Support/MemoryBuffer.h>
62 #include <llvm/LinkAllPasses.h>
63 #include <llvm/Analysis/Verifier.h>
64 #include <llvm/Analysis/LoopPass.h>
65 #include <llvm/Target/TargetData.h>
66 #include <llvm/Bitcode/ReaderWriter.h>
67 #include <llvm/Transforms/Utils/Cloning.h>
68
69 #include <sstream>
70 #include <fstream>
71 #include <iostream>
72
73 struct gallivm_cpu_engine {
74 llvm::ExecutionEngine *engine;
75 };
76
77 static struct gallivm_cpu_engine *CPU = 0;
78
79 typedef int (*fragment_shader_runner)(float x, float y,
80 float (*dests)[16][4],
81 float (*inputs)[16][4],
82 int num_attribs,
83 float (*consts)[4], int num_consts,
84 struct tgsi_sampler *samplers);
85
86 int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
87 float fx, float fy,
88 float (*dests)[16][4],
89 float (*inputs)[16][4],
90 float (*consts)[4],
91 struct tgsi_sampler *samplers)
92 {
93 fragment_shader_runner runner = reinterpret_cast<fragment_shader_runner>(prog->function);
94 assert(runner);
95
96 return runner(fx, fy, dests, inputs, prog->num_interp,
97 consts, prog->num_consts,
98 samplers);
99 }
100
101 static inline llvm::Function *func_for_shader(struct gallivm_prog *prog)
102 {
103 llvm::Module *mod = prog->module;
104 llvm::Function *func = 0;
105
106 switch (prog->type) {
107 case GALLIVM_VS:
108 func = mod->getFunction("run_vertex_shader");
109 break;
110 case GALLIVM_FS:
111 func = mod->getFunction("run_fragment_shader");
112 break;
113 default:
114 assert(!"Unknown shader type!");
115 break;
116 }
117 return func;
118 }
119
120 /*!
121 This function creates a CPU based execution engine for the given gallivm_prog.
122 gallivm_cpu_engine should be used as a singleton throughout the library. Before
123 executing gallivm_prog_exec one needs to call gallivm_cpu_jit_compile.
124 The gallivm_prog instance which is being passed to the constructor is being
125 automatically JIT compiled so one shouldn't call gallivm_cpu_jit_compile
126 with it again.
127 */
128 struct gallivm_cpu_engine * gallivm_cpu_engine_create(struct gallivm_prog *prog)
129 {
130 struct gallivm_cpu_engine *cpu = (struct gallivm_cpu_engine *)
131 calloc(1, sizeof(struct gallivm_cpu_engine));
132 llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
133 llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
134 llvm::ExecutionEngine *ee = llvm::ExecutionEngine::create(mp, false);
135 ee->DisableLazyCompilation();
136 cpu->engine = ee;
137
138 llvm::Function *func = func_for_shader(prog);
139
140 prog->function = ee->getPointerToFunction(func);
141 CPU = cpu;
142 return cpu;
143 }
144
145
146 /*!
147 This function JIT compiles the given gallivm_prog with the given cpu based execution engine.
148 The reference to the generated machine code entry point will be stored
149 in the gallivm_prog program. After executing this function one can call gallivm_prog_exec
150 in order to execute the gallivm_prog on the CPU.
151 */
152 void gallivm_cpu_jit_compile(struct gallivm_cpu_engine *cpu, struct gallivm_prog *prog)
153 {
154 llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
155 llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
156 llvm::ExecutionEngine *ee = cpu->engine;
157 assert(ee);
158 /*FIXME : remove */
159 ee->DisableLazyCompilation();
160 ee->addModuleProvider(mp);
161
162 llvm::Function *func = func_for_shader(prog);
163 prog->function = ee->getPointerToFunction(func);
164 }
165
166 void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *cpu)
167 {
168 free(cpu);
169 }
170
171 struct gallivm_cpu_engine * gallivm_global_cpu_engine()
172 {
173 return CPU;
174 }
175
176
177 typedef void (*vertex_shader_runner)(void *ainputs,
178 void *dests,
179 float (*aconsts)[4],
180 int num_vertices,
181 int num_inputs,
182 int num_attribs,
183 int num_consts);
184
185
186 /*!
187 This function is used to execute the gallivm_prog in software. Before calling
188 this function the gallivm_prog has to be JIT compiled with the gallivm_cpu_jit_compile
189 function.
190 */
191 int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
192 struct tgsi_exec_vector *inputs,
193 struct tgsi_exec_vector *dests,
194 float (*consts)[4])
195 {
196 vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
197 assert(runner);
198 /*FIXME*/
199 runner(inputs, dests, consts, 4, 4, 4, prog->num_consts);
200
201 return 0;
202 }
203
204 #endif