Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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 
52
 
53
#include 
54
#include 
55
#include 
56
#include 
57
#include 
58
#if HAVE_LLVM < 0x0306
59
#include 
60
#else
61
#include 
62
#endif
63
#include 
64
#include 
65
#include 
66
 
67
#include 
68
 
69
#include 
70
#include 
71
#include 
72
 
73
#include "pipe/p_config.h"
74
#include "util/u_debug.h"
75
#include "util/u_cpu_detect.h"
76
 
77
#include "lp_bld_misc.h"
78
 
79
namespace {
80
 
81
class LLVMEnsureMultithreaded {
82
public:
83
   LLVMEnsureMultithreaded()
84
   {
85
      if (!LLVMIsMultithreaded()) {
86
         LLVMStartMultithreaded();
87
      }
88
   }
89
};
90
 
91
static LLVMEnsureMultithreaded lLVMEnsureMultithreaded;
92
 
93
}
94
 
95
extern "C" void
96
lp_set_target_options(void)
97
{
98
#if HAVE_LLVM < 0x0304
99
   /*
100
    * By default LLVM adds a signal handler to output a pretty stack trace.
101
    * This signal handler is never removed, causing problems when unloading the
102
    * shared object where the gallium driver resides.
103
    */
104
   llvm::DisablePrettyStackTrace = true;
105
#endif
106
 
107
   // If we have a native target, initialize it to ensure it is linked in and
108
   // usable by the JIT.
109
   llvm::InitializeNativeTarget();
110
 
111
   llvm::InitializeNativeTargetAsmPrinter();
112
 
113
   llvm::InitializeNativeTargetDisassembler();
114
}
115
 
116
 
117
extern "C"
118
LLVMValueRef
119
lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal,
120
                       const char *Name)
121
{
122
   return llvm::wrap(llvm::unwrap(B)->CreateLoad(llvm::unwrap(PointerVal), true, Name));
123
}
124
 
125
 
126
extern "C"
127
void
128
lp_set_load_alignment(LLVMValueRef Inst,
129
                       unsigned Align)
130
{
131
   llvm::unwrap(Inst)->setAlignment(Align);
132
}
133
 
134
extern "C"
135
void
136
lp_set_store_alignment(LLVMValueRef Inst,
137
                       unsigned Align)
138
{
139
   llvm::unwrap(Inst)->setAlignment(Align);
140
}
141
 
142
 
143
#if HAVE_LLVM < 0x0306
144
typedef llvm::JITMemoryManager BaseMemoryManager;
145
#else
146
typedef llvm::RTDyldMemoryManager BaseMemoryManager;
147
#endif
148
 
149
 
150
/*
151
 * Delegating is tedious but the default manager class is hidden in an
152
 * anonymous namespace in LLVM, so we cannot just derive from it to change
153
 * its behavior.
154
 */
155
class DelegatingJITMemoryManager : public BaseMemoryManager {
156
 
157
   protected:
158
      virtual BaseMemoryManager *mgr() const = 0;
159
 
160
   public:
161
#if HAVE_LLVM < 0x0306
162
      /*
163
       * From JITMemoryManager
164
       */
165
      virtual void setMemoryWritable() {
166
         mgr()->setMemoryWritable();
167
      }
168
      virtual void setMemoryExecutable() {
169
         mgr()->setMemoryExecutable();
170
      }
171
      virtual void setPoisonMemory(bool poison) {
172
         mgr()->setPoisonMemory(poison);
173
      }
174
      virtual void AllocateGOT() {
175
         mgr()->AllocateGOT();
176
         /*
177
          * isManagingGOT() is not virtual in base class so we can't delegate.
178
          * Instead we mirror the value of HasGOT in our instance.
179
          */
180
         HasGOT = mgr()->isManagingGOT();
181
      }
182
      virtual uint8_t *getGOTBase() const {
183
         return mgr()->getGOTBase();
184
      }
185
      virtual uint8_t *startFunctionBody(const llvm::Function *F,
186
                                         uintptr_t &ActualSize) {
187
         return mgr()->startFunctionBody(F, ActualSize);
188
      }
189
      virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
190
                                    unsigned StubSize,
191
                                    unsigned Alignment) {
192
         return mgr()->allocateStub(F, StubSize, Alignment);
193
      }
194
      virtual void endFunctionBody(const llvm::Function *F,
195
                                   uint8_t *FunctionStart,
196
                                   uint8_t *FunctionEnd) {
197
         mgr()->endFunctionBody(F, FunctionStart, FunctionEnd);
198
      }
199
      virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
200
         return mgr()->allocateSpace(Size, Alignment);
201
      }
202
      virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
203
         return mgr()->allocateGlobal(Size, Alignment);
204
      }
205
      virtual void deallocateFunctionBody(void *Body) {
206
         mgr()->deallocateFunctionBody(Body);
207
      }
208
#if HAVE_LLVM < 0x0304
209
      virtual uint8_t *startExceptionTable(const llvm::Function *F,
210
                                           uintptr_t &ActualSize) {
211
         return mgr()->startExceptionTable(F, ActualSize);
212
      }
213
      virtual void endExceptionTable(const llvm::Function *F,
214
                                     uint8_t *TableStart,
215
                                     uint8_t *TableEnd,
216
                                     uint8_t *FrameRegister) {
217
         mgr()->endExceptionTable(F, TableStart, TableEnd,
218
                                  FrameRegister);
219
      }
220
      virtual void deallocateExceptionTable(void *ET) {
221
         mgr()->deallocateExceptionTable(ET);
222
      }
223
#endif
224
      virtual bool CheckInvariants(std::string &s) {
225
         return mgr()->CheckInvariants(s);
226
      }
227
      virtual size_t GetDefaultCodeSlabSize() {
228
         return mgr()->GetDefaultCodeSlabSize();
229
      }
230
      virtual size_t GetDefaultDataSlabSize() {
231
         return mgr()->GetDefaultDataSlabSize();
232
      }
233
      virtual size_t GetDefaultStubSlabSize() {
234
         return mgr()->GetDefaultStubSlabSize();
235
      }
236
      virtual unsigned GetNumCodeSlabs() {
237
         return mgr()->GetNumCodeSlabs();
238
      }
239
      virtual unsigned GetNumDataSlabs() {
240
         return mgr()->GetNumDataSlabs();
241
      }
242
      virtual unsigned GetNumStubSlabs() {
243
         return mgr()->GetNumStubSlabs();
244
      }
245
#endif
246
 
247
      /*
248
       * From RTDyldMemoryManager
249
       */
250
#if HAVE_LLVM >= 0x0304
251
      virtual uint8_t *allocateCodeSection(uintptr_t Size,
252
                                           unsigned Alignment,
253
                                           unsigned SectionID,
254
                                           llvm::StringRef SectionName) {
255
         return mgr()->allocateCodeSection(Size, Alignment, SectionID,
256
                                           SectionName);
257
      }
258
#else
259
      virtual uint8_t *allocateCodeSection(uintptr_t Size,
260
                                           unsigned Alignment,
261
                                           unsigned SectionID) {
262
         return mgr()->allocateCodeSection(Size, Alignment, SectionID);
263
      }
264
#endif
265
      virtual uint8_t *allocateDataSection(uintptr_t Size,
266
                                           unsigned Alignment,
267
                                           unsigned SectionID,
268
#if HAVE_LLVM >= 0x0304
269
                                           llvm::StringRef SectionName,
270
#endif
271
                                           bool IsReadOnly) {
272
         return mgr()->allocateDataSection(Size, Alignment, SectionID,
273
#if HAVE_LLVM >= 0x0304
274
                                           SectionName,
275
#endif
276
                                           IsReadOnly);
277
      }
278
#if HAVE_LLVM >= 0x0304
279
      virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
280
         mgr()->registerEHFrames(Addr, LoadAddr, Size);
281
      }
282
      virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
283
         mgr()->deregisterEHFrames(Addr, LoadAddr, Size);
284
      }
285
#else
286
      virtual void registerEHFrames(llvm::StringRef SectionData) {
287
         mgr()->registerEHFrames(SectionData);
288
      }
289
#endif
290
      virtual void *getPointerToNamedFunction(const std::string &Name,
291
                                              bool AbortOnFailure=true) {
292
         return mgr()->getPointerToNamedFunction(Name, AbortOnFailure);
293
      }
294
#if HAVE_LLVM <= 0x0303
295
      virtual bool applyPermissions(std::string *ErrMsg = 0) {
296
         return mgr()->applyPermissions(ErrMsg);
297
      }
298
#else
299
      virtual bool finalizeMemory(std::string *ErrMsg = 0) {
300
         return mgr()->finalizeMemory(ErrMsg);
301
      }
302
#endif
303
};
304
 
305
 
306
/*
307
 * Delegate memory management to one shared manager for more efficient use
308
 * of memory than creating a separate pool for each LLVM engine.
309
 * Keep generated code until freeGeneratedCode() is called, instead of when
310
 * memory manager is destroyed, which happens during engine destruction.
311
 * This allows additional memory savings as we don't have to keep the engine
312
 * around in order to use the code.
313
 * All methods are delegated to the shared manager except destruction and
314
 * deallocating code.  For the latter we just remember what needs to be
315
 * deallocated later.  The shared manager is deleted once it is empty.
316
 */
317
class ShaderMemoryManager : public DelegatingJITMemoryManager {
318
 
319
   BaseMemoryManager *TheMM;
320
 
321
   struct GeneratedCode {
322
      typedef std::vector Vec;
323
      Vec FunctionBody, ExceptionTable;
324
      BaseMemoryManager *TheMM;
325
 
326
      GeneratedCode(BaseMemoryManager *MM) {
327
         TheMM = MM;
328
      }
329
 
330
      ~GeneratedCode() {
331
         /*
332
          * Deallocate things as previously requested and
333
          * free shared manager when no longer used.
334
          */
335
#if HAVE_LLVM < 0x0306
336
         Vec::iterator i;
337
 
338
         assert(TheMM);
339
         for ( i = FunctionBody.begin(); i != FunctionBody.end(); ++i )
340
            TheMM->deallocateFunctionBody(*i);
341
#if HAVE_LLVM < 0x0304
342
         for ( i = ExceptionTable.begin(); i != ExceptionTable.end(); ++i )
343
            TheMM->deallocateExceptionTable(*i);
344
#endif /* HAVE_LLVM < 0x0304 */
345
#endif /* HAVE_LLVM < 0x0306 */
346
      }
347
   };
348
 
349
   GeneratedCode *code;
350
 
351
   BaseMemoryManager *mgr() const {
352
      return TheMM;
353
   }
354
 
355
   public:
356
 
357
      ShaderMemoryManager(BaseMemoryManager* MM) {
358
         TheMM = MM;
359
         code = new GeneratedCode(MM);
360
      }
361
 
362
      virtual ~ShaderMemoryManager() {
363
         /*
364
          * 'code' is purposely not deleted.  It is the user's responsibility
365
          * to call getGeneratedCode() and freeGeneratedCode().
366
          */
367
      }
368
 
369
      struct lp_generated_code *getGeneratedCode() {
370
         return (struct lp_generated_code *) code;
371
      }
372
 
373
      static void freeGeneratedCode(struct lp_generated_code *code) {
374
         delete (GeneratedCode *) code;
375
      }
376
 
377
#if HAVE_LLVM < 0x0304
378
      virtual void deallocateExceptionTable(void *ET) {
379
         // remember for later deallocation
380
         code->ExceptionTable.push_back(ET);
381
      }
382
#endif
383
 
384
      virtual void deallocateFunctionBody(void *Body) {
385
         // remember for later deallocation
386
         code->FunctionBody.push_back(Body);
387
      }
388
};
389
 
390
 
391
/**
392
 * Same as LLVMCreateJITCompilerForModule, but:
393
 * - allows using MCJIT and enabling AVX feature where available.
394
 * - set target options
395
 *
396
 * See also:
397
 * - llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
398
 * - llvm/tools/lli/lli.cpp
399
 * - http://markmail.org/message/ttkuhvgj4cxxy2on#query:+page:1+mid:aju2dggerju3ivd3+state:results
400
 */
401
extern "C"
402
LLVMBool
403
lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
404
                                        lp_generated_code **OutCode,
405
                                        LLVMModuleRef M,
406
                                        LLVMMCJITMemoryManagerRef CMM,
407
                                        unsigned OptLevel,
408
                                        int useMCJIT,
409
                                        char **OutError)
410
{
411
   using namespace llvm;
412
 
413
   std::string Error;
414
#if HAVE_LLVM >= 0x0306
415
   EngineBuilder builder(std::unique_ptr(unwrap(M)));
416
#else
417
   EngineBuilder builder(unwrap(M));
418
#endif
419
 
420
   /**
421
    * LLVM 3.1+ haven't more "extern unsigned llvm::StackAlignmentOverride" and
422
    * friends for configuring code generation options, like stack alignment.
423
    */
424
   TargetOptions options;
425
#if defined(PIPE_ARCH_X86)
426
   options.StackAlignmentOverride = 4;
427
#if HAVE_LLVM < 0x0304
428
   options.RealignStack = true;
429
#endif
430
#endif
431
 
432
#if defined(DEBUG) && HAVE_LLVM < 0x0307
433
   options.JITEmitDebugInfo = true;
434
#endif
435
 
436
   /* XXX: Workaround http://llvm.org/PR21435 */
437
#if defined(DEBUG) || defined(PROFILE) || \
438
    (HAVE_LLVM >= 0x0303 && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)))
439
#if HAVE_LLVM < 0x0304
440
   options.NoFramePointerElimNonLeaf = true;
441
#endif
442
   options.NoFramePointerElim = true;
443
#endif
444
 
445
   builder.setEngineKind(EngineKind::JIT)
446
          .setErrorStr(&Error)
447
          .setTargetOptions(options)
448
          .setOptLevel((CodeGenOpt::Level)OptLevel);
449
 
450
   if (useMCJIT) {
451
#if HAVE_LLVM < 0x0306
452
       builder.setUseMCJIT(true);
453
#endif
454
#ifdef _WIN32
455
       /*
456
        * MCJIT works on Windows, but currently only through ELF object format.
457
        */
458
       std::string targetTriple = llvm::sys::getProcessTriple();
459
       targetTriple.append("-elf");
460
       unwrap(M)->setTargetTriple(targetTriple);
461
#endif
462
   }
463
 
464
   llvm::SmallVector MAttrs;
465
   if (util_cpu_caps.has_avx) {
466
      /*
467
       * AVX feature is not automatically detected from CPUID by the X86 target
468
       * yet, because the old (yet default) JIT engine is not capable of
469
       * emitting the opcodes. On newer llvm versions it is and at least some
470
       * versions (tested with 3.3) will emit avx opcodes without this anyway.
471
       */
472
      MAttrs.push_back("+avx");
473
      if (util_cpu_caps.has_f16c) {
474
         MAttrs.push_back("+f16c");
475
      }
476
      builder.setMAttrs(MAttrs);
477
   }
478
 
479
#if HAVE_LLVM >= 0x0305
480
   StringRef MCPU = llvm::sys::getHostCPUName();
481
   /*
482
    * The cpu bits are no longer set automatically, so need to set mcpu manually.
483
    * Note that the MAttrs set above will be sort of ignored (since we should
484
    * not set any which would not be set by specifying the cpu anyway).
485
    * It ought to be safe though since getHostCPUName() should include bits
486
    * not only from the cpu but environment as well (for instance if it's safe
487
    * to use avx instructions which need OS support). According to
488
    * http://llvm.org/bugs/show_bug.cgi?id=19429 however if I understand this
489
    * right it may be necessary to specify older cpu (or disable mattrs) though
490
    * when not using MCJIT so no instructions are generated which the old JIT
491
    * can't handle. Not entirely sure if we really need to do anything yet.
492
    */
493
   builder.setMCPU(MCPU);
494
#endif
495
 
496
   ShaderMemoryManager *MM = NULL;
497
   if (useMCJIT) {
498
#if HAVE_LLVM > 0x0303
499
       BaseMemoryManager* JMM = reinterpret_cast(CMM);
500
       MM = new ShaderMemoryManager(JMM);
501
       *OutCode = MM->getGeneratedCode();
502
 
503
#if HAVE_LLVM >= 0x0306
504
       builder.setMCJITMemoryManager(std::unique_ptr(MM));
505
       MM = NULL; // ownership taken by std::unique_ptr
506
#else
507
       builder.setMCJITMemoryManager(MM);
508
#endif
509
#endif
510
   } else {
511
#if HAVE_LLVM < 0x0306
512
       BaseMemoryManager* JMM = reinterpret_cast(CMM);
513
       MM = new ShaderMemoryManager(JMM);
514
       *OutCode = MM->getGeneratedCode();
515
 
516
       builder.setJITMemoryManager(MM);
517
#else
518
       assert(0);
519
#endif
520
   }
521
 
522
   ExecutionEngine *JIT;
523
 
524
   JIT = builder.create();
525
   if (JIT) {
526
      *OutJIT = wrap(JIT);
527
      return 0;
528
   }
529
   lp_free_generated_code(*OutCode);
530
   *OutCode = 0;
531
   delete MM;
532
   *OutError = strdup(Error.c_str());
533
   return 1;
534
}
535
 
536
 
537
extern "C"
538
void
539
lp_free_generated_code(struct lp_generated_code *code)
540
{
541
   ShaderMemoryManager::freeGeneratedCode(code);
542
}
543
 
544
extern "C"
545
LLVMMCJITMemoryManagerRef
546
lp_get_default_memory_manager()
547
{
548
   BaseMemoryManager *mm;
549
#if HAVE_LLVM < 0x0306
550
   mm = llvm::JITMemoryManager::CreateDefaultMemManager();
551
#else
552
   mm = new llvm::SectionMemoryManager();
553
#endif
554
   return reinterpret_cast(mm);
555
}
556
 
557
extern "C"
558
void
559
lp_free_memory_manager(LLVMMCJITMemoryManagerRef memorymgr)
560
{
561
   delete reinterpret_cast(memorymgr);
562
}