Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 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
#if HAVE_LLVM >= 0x0301
58
#include 
59
#include 
60
#endif
61
#include 
62
#include 
63
 
64
#if HAVE_LLVM >= 0x0300
65
#include 
66
#else /* HAVE_LLVM < 0x0300 */
67
#include 
68
#endif /* HAVE_LLVM < 0x0300 */
69
 
70
#if HAVE_LLVM >= 0x0303
71
#include 
72
#include 
73
#include 
74
#endif
75
 
76
#include "pipe/p_config.h"
77
#include "util/u_debug.h"
78
#include "util/u_cpu_detect.h"
79
 
80
#include "lp_bld_misc.h"
81
 
82
namespace {
83
 
84
class LLVMEnsureMultithreaded {
85
public:
86
   LLVMEnsureMultithreaded()
87
   {
88
#if HAVE_LLVM < 0x0303
89
      if (!llvm::llvm_is_multithreaded()) {
90
         llvm::llvm_start_multithreaded();
91
      }
92
#else
93
      if (!LLVMIsMultithreaded()) {
94
         LLVMStartMultithreaded();
95
      }
96
#endif
97
   }
98
};
99
 
100
static LLVMEnsureMultithreaded lLVMEnsureMultithreaded;
101
 
102
}
103
 
104
extern "C" void
105
lp_set_target_options(void)
106
{
107
#if HAVE_LLVM <= 0x0300
108
#if defined(DEBUG)
109
#if HAVE_LLVM >= 0x0207
110
   llvm::JITEmitDebugInfo = true;
111
#endif
112
#endif
113
 
114
   /*
115
    * LLVM revision 123367 switched the default stack alignment to 16 bytes on
116
    * Linux (and several other Unices in later revisions), to match recent gcc
117
    * versions.
118
    *
119
    * However our drivers can be loaded by old binary applications, still
120
    * maintaining a 4 bytes stack alignment.  Therefore we must tell LLVM here
121
    * to only assume a 4 bytes alignment for backwards compatibility.
122
    */
123
#if defined(PIPE_ARCH_X86)
124
#if HAVE_LLVM == 0x0300
125
   llvm::StackAlignmentOverride = 4;
126
#else
127
   llvm::StackAlignment = 4;
128
#endif
129
#endif
130
 
131
#if defined(DEBUG) || defined(PROFILE)
132
   llvm::NoFramePointerElim = true;
133
#if HAVE_LLVM >= 0x0208
134
   llvm::NoFramePointerElimNonLeaf = true;
135
#endif
136
#endif
137
 
138
   llvm::NoExcessFPPrecision = false;
139
 
140
   /* XXX: Investigate this */
141
#if 0
142
   llvm::UnsafeFPMath = true;
143
#endif
144
#endif  /* HAVE_LLVM <= 0x0300 */
145
 
146
#if HAVE_LLVM < 0x0209
147
   /*
148
    * LLVM will generate MMX instructions for vectors <= 64 bits, leading to
149
    * innefficient code, and in 32bit systems, to the corruption of the FPU
150
    * stack given that it expects the user to generate the EMMS instructions.
151
    *
152
    * See also:
153
    * - http://llvm.org/bugs/show_bug.cgi?id=3287
154
    * - http://l4.me.uk/post/2009/06/07/llvm-wrinkle-3-configuration-what-configuration/
155
    *
156
    * The -disable-mmx global option can be specified only once  since we
157
    * dynamically link against LLVM it will reside in a separate shared object,
158
    * which may or not be delete when this shared object is, so we use the
159
    * llvm::DisablePrettyStackTrace variable (which we set below and should
160
    * reside in the same shared library) to determine whether the -disable-mmx
161
    * option has been set or not.
162
    *
163
    * Thankfully this ugly hack is not necessary on LLVM 2.9 onwards.
164
    */
165
   if (!llvm::DisablePrettyStackTrace) {
166
      static boolean first = TRUE;
167
      static const char* options[] = {
168
         "prog",
169
         "-disable-mmx"
170
      };
171
      assert(first);
172
      llvm::cl::ParseCommandLineOptions(2, const_cast(options));
173
      first = FALSE;
174
   }
175
#endif
176
 
177
   /*
178
    * By default LLVM adds a signal handler to output a pretty stack trace.
179
    * This signal handler is never removed, causing problems when unloading the
180
    * shared object where the gallium driver resides.
181
    */
182
   llvm::DisablePrettyStackTrace = true;
183
 
184
   // If we have a native target, initialize it to ensure it is linked in and
185
   // usable by the JIT.
186
   llvm::InitializeNativeTarget();
187
 
188
#if HAVE_LLVM >= 0x0208
189
   llvm::InitializeNativeTargetAsmPrinter();
190
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
191
   LLVMInitializeX86AsmPrinter();
192
#elif defined(PIPE_ARCH_ARM)
193
   LLVMInitializeARMAsmPrinter();
194
#elif defined(PIPE_ARCH_PPC)
195
   LLVMInitializePowerPCAsmPrinter();
196
#endif
197
 
198
#if HAVE_LLVM >= 0x0207
199
#  if HAVE_LLVM >= 0x0301
200
   llvm::InitializeNativeTargetDisassembler();
201
#  elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
202
   LLVMInitializeX86Disassembler();
203
#  elif defined(PIPE_ARCH_ARM)
204
   LLVMInitializeARMDisassembler();
205
#  endif
206
#endif
207
}
208
 
209
 
210
extern "C" void
211
lp_func_delete_body(LLVMValueRef FF)
212
{
213
   llvm::Function *func = llvm::unwrap(FF);
214
   func->deleteBody();
215
}
216
 
217
 
218
extern "C"
219
LLVMValueRef
220
lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal,
221
                       const char *Name)
222
{
223
   return llvm::wrap(llvm::unwrap(B)->CreateLoad(llvm::unwrap(PointerVal), true, Name));
224
}
225
 
226
 
227
extern "C"
228
void
229
lp_set_load_alignment(LLVMValueRef Inst,
230
                       unsigned Align)
231
{
232
   llvm::unwrap(Inst)->setAlignment(Align);
233
}
234
 
235
extern "C"
236
void
237
lp_set_store_alignment(LLVMValueRef Inst,
238
		       unsigned Align)
239
{
240
   llvm::unwrap(Inst)->setAlignment(Align);
241
}
242
 
243
 
244
#if HAVE_LLVM >= 0x301
245
 
246
/**
247
 * Same as LLVMCreateJITCompilerForModule, but:
248
 * - allows using MCJIT and enabling AVX feature where available.
249
 * - set target options
250
 *
251
 * See also:
252
 * - llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
253
 * - llvm/tools/lli/lli.cpp
254
 * - http://markmail.org/message/ttkuhvgj4cxxy2on#query:+page:1+mid:aju2dggerju3ivd3+state:results
255
 */
256
extern "C"
257
LLVMBool
258
lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
259
                                        LLVMModuleRef M,
260
                                        unsigned OptLevel,
261
                                        int useMCJIT,
262
                                        char **OutError)
263
{
264
   using namespace llvm;
265
 
266
   std::string Error;
267
   EngineBuilder builder(unwrap(M));
268
 
269
   /**
270
    * LLVM 3.1+ haven't more "extern unsigned llvm::StackAlignmentOverride" and
271
    * friends for configuring code generation options, like stack alignment.
272
    */
273
   TargetOptions options;
274
#if defined(PIPE_ARCH_X86)
275
   options.StackAlignmentOverride = 4;
276
   options.RealignStack = true;
277
#endif
278
 
279
#if defined(DEBUG)
280
   options.JITEmitDebugInfo = true;
281
#endif
282
 
283
#if defined(DEBUG) || defined(PROFILE)
284
   options.NoFramePointerElimNonLeaf = true;
285
   options.NoFramePointerElim = true;
286
#endif
287
 
288
   builder.setEngineKind(EngineKind::JIT)
289
          .setErrorStr(&Error)
290
          .setTargetOptions(options)
291
          .setOptLevel((CodeGenOpt::Level)OptLevel);
292
 
293
   if (useMCJIT) {
294
       builder.setUseMCJIT(true);
295
   }
296
 
297
   llvm::SmallVector MAttrs;
298
   if (util_cpu_caps.has_avx) {
299
      /*
300
       * AVX feature is not automatically detected from CPUID by the X86 target
301
       * yet, because the old (yet default) JIT engine is not capable of
302
       * emitting the opcodes.  But as we're using MCJIT here, it is safe to
303
       * add set this attribute.
304
       */
305
      MAttrs.push_back("+avx");
306
      if (util_cpu_caps.has_f16c) {
307
         MAttrs.push_back("+f16c");
308
      }
309
      builder.setMAttrs(MAttrs);
310
   }
311
   builder.setJITMemoryManager(JITMemoryManager::CreateDefaultMemManager());
312
 
313
   ExecutionEngine *JIT;
314
#if 0
315
   JIT = builder.create();
316
#else
317
   /*
318
    * Workaround http://llvm.org/bugs/show_bug.cgi?id=12833
319
    */
320
   StringRef MArch = "";
321
   StringRef MCPU = "";
322
   Triple TT(unwrap(M)->getTargetTriple());
323
   JIT = builder.create(builder.selectTarget(TT, MArch, MCPU, MAttrs));
324
#endif
325
   if (JIT) {
326
      *OutJIT = wrap(JIT);
327
      return 0;
328
   }
329
   *OutError = strdup(Error.c_str());
330
   return 1;
331
}
332
 
333
#endif /* HAVE_LLVM >= 0x301 */