gallivm: Remove lp_func_delete_body.
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_misc.cpp
1 /**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28
29 /**
30 * The purpose of this module is to expose LLVM functionality not available
31 * through the C++ bindings.
32 */
33
34
35 #ifndef __STDC_LIMIT_MACROS
36 #define __STDC_LIMIT_MACROS
37 #endif
38
39 #ifndef __STDC_CONSTANT_MACROS
40 #define __STDC_CONSTANT_MACROS
41 #endif
42
43 // Undef these vars just to silence warnings
44 #undef PACKAGE_BUGREPORT
45 #undef PACKAGE_NAME
46 #undef PACKAGE_STRING
47 #undef PACKAGE_TARNAME
48 #undef PACKAGE_VERSION
49
50
51 #include <stddef.h>
52
53 #include <llvm-c/Core.h>
54 #include <llvm-c/ExecutionEngine.h>
55 #include <llvm/Target/TargetOptions.h>
56 #include <llvm/ExecutionEngine/ExecutionEngine.h>
57 #include <llvm/ADT/Triple.h>
58 #include <llvm/ExecutionEngine/JITMemoryManager.h>
59 #include <llvm/Support/CommandLine.h>
60 #include <llvm/Support/PrettyStackTrace.h>
61
62 #include <llvm/Support/TargetSelect.h>
63
64 #if HAVE_LLVM >= 0x0303
65 #include <llvm/IR/IRBuilder.h>
66 #include <llvm/IR/Module.h>
67 #include <llvm/Support/CBindingWrapping.h>
68 #endif
69
70 #include "pipe/p_config.h"
71 #include "util/u_debug.h"
72 #include "util/u_cpu_detect.h"
73
74 #include "lp_bld_misc.h"
75
76 namespace {
77
78 class LLVMEnsureMultithreaded {
79 public:
80 LLVMEnsureMultithreaded()
81 {
82 #if HAVE_LLVM < 0x0303
83 if (!llvm::llvm_is_multithreaded()) {
84 llvm::llvm_start_multithreaded();
85 }
86 #else
87 if (!LLVMIsMultithreaded()) {
88 LLVMStartMultithreaded();
89 }
90 #endif
91 }
92 };
93
94 static LLVMEnsureMultithreaded lLVMEnsureMultithreaded;
95
96 }
97
98 extern "C" void
99 lp_set_target_options(void)
100 {
101 #if HAVE_LLVM < 0x0304
102 /*
103 * By default LLVM adds a signal handler to output a pretty stack trace.
104 * This signal handler is never removed, causing problems when unloading the
105 * shared object where the gallium driver resides.
106 */
107 llvm::DisablePrettyStackTrace = true;
108 #endif
109
110 // If we have a native target, initialize it to ensure it is linked in and
111 // usable by the JIT.
112 llvm::InitializeNativeTarget();
113
114 llvm::InitializeNativeTargetAsmPrinter();
115
116 llvm::InitializeNativeTargetDisassembler();
117 }
118
119
120 extern "C"
121 LLVMValueRef
122 lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal,
123 const char *Name)
124 {
125 return llvm::wrap(llvm::unwrap(B)->CreateLoad(llvm::unwrap(PointerVal), true, Name));
126 }
127
128
129 extern "C"
130 void
131 lp_set_load_alignment(LLVMValueRef Inst,
132 unsigned Align)
133 {
134 llvm::unwrap<llvm::LoadInst>(Inst)->setAlignment(Align);
135 }
136
137 extern "C"
138 void
139 lp_set_store_alignment(LLVMValueRef Inst,
140 unsigned Align)
141 {
142 llvm::unwrap<llvm::StoreInst>(Inst)->setAlignment(Align);
143 }
144
145
146 /*
147 * Delegating is tedious but the default manager class is hidden in an
148 * anonymous namespace in LLVM, so we cannot just derive from it to change
149 * its behavior.
150 */
151 class DelegatingJITMemoryManager : public llvm::JITMemoryManager {
152
153 protected:
154 virtual llvm::JITMemoryManager *mgr() const = 0;
155
156 public:
157 /*
158 * From JITMemoryManager
159 */
160 virtual void setMemoryWritable() {
161 mgr()->setMemoryWritable();
162 }
163 virtual void setMemoryExecutable() {
164 mgr()->setMemoryExecutable();
165 }
166 virtual void setPoisonMemory(bool poison) {
167 mgr()->setPoisonMemory(poison);
168 }
169 virtual void AllocateGOT() {
170 mgr()->AllocateGOT();
171 /*
172 * isManagingGOT() is not virtual in base class so we can't delegate.
173 * Instead we mirror the value of HasGOT in our instance.
174 */
175 HasGOT = mgr()->isManagingGOT();
176 }
177 virtual uint8_t *getGOTBase() const {
178 return mgr()->getGOTBase();
179 }
180 virtual uint8_t *startFunctionBody(const llvm::Function *F,
181 uintptr_t &ActualSize) {
182 return mgr()->startFunctionBody(F, ActualSize);
183 }
184 virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
185 unsigned StubSize,
186 unsigned Alignment) {
187 return mgr()->allocateStub(F, StubSize, Alignment);
188 }
189 virtual void endFunctionBody(const llvm::Function *F,
190 uint8_t *FunctionStart,
191 uint8_t *FunctionEnd) {
192 mgr()->endFunctionBody(F, FunctionStart, FunctionEnd);
193 }
194 virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
195 return mgr()->allocateSpace(Size, Alignment);
196 }
197 virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
198 return mgr()->allocateGlobal(Size, Alignment);
199 }
200 virtual void deallocateFunctionBody(void *Body) {
201 mgr()->deallocateFunctionBody(Body);
202 }
203 #if HAVE_LLVM < 0x0304
204 virtual uint8_t *startExceptionTable(const llvm::Function *F,
205 uintptr_t &ActualSize) {
206 return mgr()->startExceptionTable(F, ActualSize);
207 }
208 virtual void endExceptionTable(const llvm::Function *F,
209 uint8_t *TableStart,
210 uint8_t *TableEnd,
211 uint8_t *FrameRegister) {
212 mgr()->endExceptionTable(F, TableStart, TableEnd,
213 FrameRegister);
214 }
215 virtual void deallocateExceptionTable(void *ET) {
216 mgr()->deallocateExceptionTable(ET);
217 }
218 #endif
219 virtual bool CheckInvariants(std::string &s) {
220 return mgr()->CheckInvariants(s);
221 }
222 virtual size_t GetDefaultCodeSlabSize() {
223 return mgr()->GetDefaultCodeSlabSize();
224 }
225 virtual size_t GetDefaultDataSlabSize() {
226 return mgr()->GetDefaultDataSlabSize();
227 }
228 virtual size_t GetDefaultStubSlabSize() {
229 return mgr()->GetDefaultStubSlabSize();
230 }
231 virtual unsigned GetNumCodeSlabs() {
232 return mgr()->GetNumCodeSlabs();
233 }
234 virtual unsigned GetNumDataSlabs() {
235 return mgr()->GetNumDataSlabs();
236 }
237 virtual unsigned GetNumStubSlabs() {
238 return mgr()->GetNumStubSlabs();
239 }
240
241 /*
242 * From RTDyldMemoryManager
243 */
244 #if HAVE_LLVM >= 0x0304
245 virtual uint8_t *allocateCodeSection(uintptr_t Size,
246 unsigned Alignment,
247 unsigned SectionID,
248 llvm::StringRef SectionName) {
249 return mgr()->allocateCodeSection(Size, Alignment, SectionID,
250 SectionName);
251 }
252 #else
253 virtual uint8_t *allocateCodeSection(uintptr_t Size,
254 unsigned Alignment,
255 unsigned SectionID) {
256 return mgr()->allocateCodeSection(Size, Alignment, SectionID);
257 }
258 #endif
259 #if HAVE_LLVM >= 0x0303
260 virtual uint8_t *allocateDataSection(uintptr_t Size,
261 unsigned Alignment,
262 unsigned SectionID,
263 #if HAVE_LLVM >= 0x0304
264 llvm::StringRef SectionName,
265 #endif
266 bool IsReadOnly) {
267 return mgr()->allocateDataSection(Size, Alignment, SectionID,
268 #if HAVE_LLVM >= 0x0304
269 SectionName,
270 #endif
271 IsReadOnly);
272 }
273 #if HAVE_LLVM >= 0x0304
274 virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
275 mgr()->registerEHFrames(Addr, LoadAddr, Size);
276 }
277 virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
278 mgr()->deregisterEHFrames(Addr, LoadAddr, Size);
279 }
280 #else
281 virtual void registerEHFrames(llvm::StringRef SectionData) {
282 mgr()->registerEHFrames(SectionData);
283 }
284 #endif
285 #else
286 virtual uint8_t *allocateDataSection(uintptr_t Size,
287 unsigned Alignment,
288 unsigned SectionID) {
289 return mgr()->allocateDataSection(Size, Alignment, SectionID);
290 }
291 #endif
292 virtual void *getPointerToNamedFunction(const std::string &Name,
293 bool AbortOnFailure=true) {
294 return mgr()->getPointerToNamedFunction(Name, AbortOnFailure);
295 }
296 #if HAVE_LLVM == 0x0303
297 virtual bool applyPermissions(std::string *ErrMsg = 0) {
298 return mgr()->applyPermissions(ErrMsg);
299 }
300 #elif HAVE_LLVM > 0x0303
301 virtual bool finalizeMemory(std::string *ErrMsg = 0) {
302 return mgr()->finalizeMemory(ErrMsg);
303 }
304 #endif
305 };
306
307
308 /*
309 * Delegate memory management to one shared manager for more efficient use
310 * of memory than creating a separate pool for each LLVM engine.
311 * Keep generated code until freeGeneratedCode() is called, instead of when
312 * memory manager is destroyed, which happens during engine destruction.
313 * This allows additional memory savings as we don't have to keep the engine
314 * around in order to use the code.
315 * All methods are delegated to the shared manager except destruction and
316 * deallocating code. For the latter we just remember what needs to be
317 * deallocated later. The shared manager is deleted once it is empty.
318 */
319 class ShaderMemoryManager : public DelegatingJITMemoryManager {
320
321 static llvm::JITMemoryManager *TheMM;
322 static unsigned NumUsers;
323
324 struct GeneratedCode {
325 typedef std::vector<void *> Vec;
326 Vec FunctionBody, ExceptionTable;
327
328 GeneratedCode() {
329 ++NumUsers;
330 }
331
332 ~GeneratedCode() {
333 /*
334 * Deallocate things as previously requested and
335 * free shared manager when no longer used.
336 */
337 Vec::iterator i;
338
339 assert(TheMM);
340 for ( i = FunctionBody.begin(); i != FunctionBody.end(); ++i )
341 TheMM->deallocateFunctionBody(*i);
342 #if HAVE_LLVM < 0x0304
343 for ( i = ExceptionTable.begin(); i != ExceptionTable.end(); ++i )
344 TheMM->deallocateExceptionTable(*i);
345 #endif
346 --NumUsers;
347 if (NumUsers == 0) {
348 delete TheMM;
349 TheMM = 0;
350 }
351 }
352 };
353
354 GeneratedCode *code;
355
356 llvm::JITMemoryManager *mgr() const {
357 if (!TheMM) {
358 TheMM = CreateDefaultMemManager();
359 }
360 return TheMM;
361 }
362
363 public:
364
365 ShaderMemoryManager() {
366 code = new GeneratedCode;
367 }
368
369 virtual ~ShaderMemoryManager() {
370 /*
371 * 'code' is purposely not deleted. It is the user's responsibility
372 * to call getGeneratedCode() and freeGeneratedCode().
373 */
374 }
375
376 struct lp_generated_code *getGeneratedCode() {
377 return (struct lp_generated_code *) code;
378 }
379
380 static void freeGeneratedCode(struct lp_generated_code *code) {
381 delete (GeneratedCode *) code;
382 }
383
384 #if HAVE_LLVM < 0x0304
385 virtual void deallocateExceptionTable(void *ET) {
386 // remember for later deallocation
387 code->ExceptionTable.push_back(ET);
388 }
389 #endif
390
391 virtual void deallocateFunctionBody(void *Body) {
392 // remember for later deallocation
393 code->FunctionBody.push_back(Body);
394 }
395 };
396
397 llvm::JITMemoryManager *ShaderMemoryManager::TheMM = 0;
398 unsigned ShaderMemoryManager::NumUsers = 0;
399
400
401 /**
402 * Same as LLVMCreateJITCompilerForModule, but:
403 * - allows using MCJIT and enabling AVX feature where available.
404 * - set target options
405 *
406 * See also:
407 * - llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
408 * - llvm/tools/lli/lli.cpp
409 * - http://markmail.org/message/ttkuhvgj4cxxy2on#query:+page:1+mid:aju2dggerju3ivd3+state:results
410 */
411 extern "C"
412 LLVMBool
413 lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
414 lp_generated_code **OutCode,
415 LLVMModuleRef M,
416 unsigned OptLevel,
417 int useMCJIT,
418 char **OutError)
419 {
420 using namespace llvm;
421
422 std::string Error;
423 EngineBuilder builder(unwrap(M));
424
425 /**
426 * LLVM 3.1+ haven't more "extern unsigned llvm::StackAlignmentOverride" and
427 * friends for configuring code generation options, like stack alignment.
428 */
429 TargetOptions options;
430 #if defined(PIPE_ARCH_X86)
431 options.StackAlignmentOverride = 4;
432 #if HAVE_LLVM < 0x0304
433 options.RealignStack = true;
434 #endif
435 #endif
436
437 #if defined(DEBUG)
438 options.JITEmitDebugInfo = true;
439 #endif
440
441 #if defined(DEBUG) || defined(PROFILE)
442 #if HAVE_LLVM < 0x0304
443 options.NoFramePointerElimNonLeaf = true;
444 #endif
445 options.NoFramePointerElim = true;
446 #endif
447
448 builder.setEngineKind(EngineKind::JIT)
449 .setErrorStr(&Error)
450 .setTargetOptions(options)
451 .setOptLevel((CodeGenOpt::Level)OptLevel);
452
453 if (useMCJIT) {
454 builder.setUseMCJIT(true);
455 }
456
457 llvm::SmallVector<std::string, 1> MAttrs;
458 if (util_cpu_caps.has_avx) {
459 /*
460 * AVX feature is not automatically detected from CPUID by the X86 target
461 * yet, because the old (yet default) JIT engine is not capable of
462 * emitting the opcodes. But as we're using MCJIT here, it is safe to
463 * add set this attribute.
464 */
465 MAttrs.push_back("+avx");
466 if (util_cpu_caps.has_f16c) {
467 MAttrs.push_back("+f16c");
468 }
469 builder.setMAttrs(MAttrs);
470 }
471
472 ShaderMemoryManager *MM = new ShaderMemoryManager();
473 *OutCode = MM->getGeneratedCode();
474
475 builder.setJITMemoryManager(MM);
476
477 ExecutionEngine *JIT;
478 #if 0
479 JIT = builder.create();
480 #else
481 /*
482 * Workaround http://llvm.org/bugs/show_bug.cgi?id=12833
483 */
484 StringRef MArch = "";
485 StringRef MCPU = "";
486 Triple TT(unwrap(M)->getTargetTriple());
487 JIT = builder.create(builder.selectTarget(TT, MArch, MCPU, MAttrs));
488 #endif
489 if (JIT) {
490 *OutJIT = wrap(JIT);
491 return 0;
492 }
493 lp_free_generated_code(*OutCode);
494 *OutCode = 0;
495 delete MM;
496 *OutError = strdup(Error.c_str());
497 return 1;
498 }
499
500
501 extern "C"
502 void
503 lp_free_generated_code(struct lp_generated_code *code)
504 {
505 ShaderMemoryManager::freeGeneratedCode(code);
506 }