|
1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 * |
|
3 * Permission is hereby granted, free of charge, to any person obtaining a |
|
4 * copy of this software and /or associated documentation files |
|
5 * (the "Materials "), to deal in the Materials without restriction, |
|
6 * including without limitation the rights to use, copy, modify, merge, |
|
7 * publish, distribute, sublicense, and/or sell copies of the Materials, |
|
8 * and to permit persons to whom the Materials are furnished to do so, |
|
9 * subject to the following conditions: |
|
10 * |
|
11 * The above copyright notice and this permission notice shall be included |
|
12 * in all copies or substantial portions of the Materials. |
|
13 * |
|
14 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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 MATERIALS OR |
|
20 * THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
21 */ |
|
22 |
|
23 #ifndef __SFCOMPILER_H |
|
24 # include "sfCompiler.h" |
|
25 #endif |
|
26 |
|
27 #ifndef __RIPIXELPIPE_H |
|
28 # include "riPixelPipe.h" |
|
29 #endif |
|
30 |
|
31 #include <iostream> |
|
32 #include <sstream> |
|
33 #include <stdio.h> |
|
34 |
|
35 #include "llvm/LLVMContext.h" |
|
36 #include "llvm/Module.h" |
|
37 #include "llvm/Bitcode/ReaderWriter.h" |
|
38 #include "llvm/Support/MemoryBuffer.h" |
|
39 #include "llvm/Type.h" |
|
40 #include "llvm/Value.h" |
|
41 #include "llvm/Constant.h" |
|
42 #include "llvm/Constants.h" |
|
43 #include "llvm/Argument.h" |
|
44 #include "llvm/Transforms/Utils/Cloning.h" |
|
45 |
|
46 #include "llvm/Pass.h" |
|
47 #include "llvm/PassManager.h" |
|
48 #include "llvm/Support/StandardPasses.h" |
|
49 #include "llvm/Transforms/Utils/BasicInliner.h" |
|
50 |
|
51 #include "llvm/ExecutionEngine/JIT.h" |
|
52 #include "llvm/ExecutionEngine/ExecutionEngine.h" |
|
53 #include "llvm/Target/TargetSelect.h" |
|
54 #include "llvm/Support/ManagedStatic.h" |
|
55 |
|
56 // This file is found as an output of compilation (in the binary directory). |
|
57 // Rationale for this is that the output is somewhat platform dependent. |
|
58 #include "binaryPixelPipe.h" |
|
59 #include "binaryBlitter.h" |
|
60 |
|
61 namespace OpenVGRI { |
|
62 |
|
63 static bool single_compiler = true; |
|
64 |
|
65 PPCompiler* PPCompiler::s_compiler = NULL; |
|
66 |
|
67 PPCompiler::PPCompiler() : |
|
68 m_executionEngine(NULL), |
|
69 m_ppCache(NUM_CACHED_PIXELPIPES), |
|
70 m_blitterCache(NUM_CACHED_BLITTERS), |
|
71 m_llvmContext() |
|
72 { |
|
73 // \todo Make this class into a singleton? |
|
74 RI_ASSERT(single_compiler); |
|
75 |
|
76 if (single_compiler) |
|
77 single_compiler = false; |
|
78 |
|
79 ::llvm::InitializeNativeTarget(); |
|
80 init(); |
|
81 } |
|
82 |
|
83 PPCompiler::~PPCompiler() |
|
84 { |
|
85 if (m_executionEngine) |
|
86 delete m_executionEngine; |
|
87 } |
|
88 |
|
89 PPCompiler::PPCompilerContext::PPCompilerContext() : |
|
90 module(NULL), |
|
91 llvmFunction(NULL) |
|
92 { |
|
93 } |
|
94 |
|
95 PPCompiler::PPCompilerContext::~PPCompilerContext() |
|
96 { |
|
97 // All the other objects should be owned by the executionengine, and |
|
98 // that is owned by the PPCompiler, so do nothing here. |
|
99 |
|
100 } |
|
101 |
|
102 bool PPCompiler::initPPContext( |
|
103 PPCompilerContext& context, |
|
104 const unsigned char* data, |
|
105 size_t dataSize, |
|
106 const char* functionName) |
|
107 { |
|
108 try { |
|
109 std::string err; |
|
110 |
|
111 const char *byteCodeStart = (const char*)data; |
|
112 const char *byteCodeEnd = (const char*)(data + dataSize); |
|
113 |
|
114 ::llvm::MemoryBuffer* memBuffer = ::llvm::MemoryBuffer::getMemBufferCopy(byteCodeStart, byteCodeEnd); |
|
115 |
|
116 llvmCheckPtrError((void*)memBuffer, err); |
|
117 |
|
118 // Make sure the module is fully read: |
|
119 //::llvm::Module* ppModule = moduleProvider->materializeModule(&err); |
|
120 ::llvm::Module* ppModule = ::llvm::getLazyBitcodeModule(memBuffer, getLLVMContext(), &err); |
|
121 ppModule->MaterializeAll(); |
|
122 |
|
123 llvmCheckPtrError(ppModule, err); |
|
124 context.module = ppModule; |
|
125 //ppModule->dump(); |
|
126 |
|
127 if (!m_executionEngine) |
|
128 { |
|
129 m_executionEngine = ::llvm::ExecutionEngine::createJIT(ppModule, &err, NULL, ::llvm::CodeGenOpt::Aggressive); |
|
130 llvmCheckPtrError(m_executionEngine, err); |
|
131 } |
|
132 else |
|
133 m_executionEngine->addModule(ppModule); |
|
134 |
|
135 //m_executionEngine->runStaticConstructorsDestructors(false); |
|
136 |
|
137 ::llvm::Function* originalFunc = findFunctionWithString(ppModule, functionName); |
|
138 |
|
139 llvmCheckPtrError((const void*)originalFunc, err); |
|
140 context.llvmFunction = originalFunc; |
|
141 //originalFunc->dump(); |
|
142 } catch (int err) |
|
143 { |
|
144 (void)err; |
|
145 std::cerr << "*** Failed to initialize a pixelpipeline module." << std::endl; |
|
146 return false; |
|
147 } |
|
148 |
|
149 return true; |
|
150 } |
|
151 |
|
152 |
|
153 /** |
|
154 * \brief Loads the modules this compiler supports. |
|
155 */ |
|
156 bool PPCompiler::init() |
|
157 { |
|
158 if (!initPPContext(m_ppContext, integerPixelPipe_binary, sizeof(integerPixelPipe_binary), "executePixelPipeline")) |
|
159 return false; |
|
160 |
|
161 if (!initPPContext(m_blitterContext, integerBlitter_binary, sizeof(integerBlitter_binary), "executeBlitter")) |
|
162 return false; |
|
163 |
|
164 m_ppCache.setLLVMInterface(m_executionEngine, m_ppContext.module); |
|
165 m_blitterCache.setLLVMInterface(m_executionEngine, m_blitterContext.module); |
|
166 |
|
167 return true; |
|
168 } |
|
169 |
|
170 // Helps cast void* to function pointers (may be platform dependent, usually works): |
|
171 union FuncCaster { |
|
172 void* ptr; |
|
173 PixelPipeFunction pipeFunc; |
|
174 BlitterFunction blitFunc; |
|
175 }; |
|
176 |
|
177 PPCompiler::PartialEvalFunc PPCompiler::compilePixelPipeline(::llvm::LLVMContext& llvmContext, PPCompilerContext& compilerContext, ConstantGenFunc constGenFunc, const void* state, const std::string& newFunctionName) |
|
178 { |
|
179 // Get the constant state argument (must be the first in the list): |
|
180 ::llvm::Function::arg_iterator argit = compilerContext.llvmFunction->arg_begin(); |
|
181 ::llvm::Argument& arg = *argit; |
|
182 //arg.getType()->dump(); |
|
183 |
|
184 ::llvm::Constant* constantState = constGenFunc(state, llvmContext, arg.getType()->getContainedType(0)); |
|
185 |
|
186 RI_ASSERT(constantState); |
|
187 |
|
188 //constantState->dump(); |
|
189 |
|
190 // \todo Even though this variable could be automatically cleaned up by the optimizations, |
|
191 // it should be stored in the cache and destroyed along with the function when |
|
192 // the cache-entry is dropped out. |
|
193 ::llvm::GlobalVariable* constantStateVariable = new ::llvm::GlobalVariable( |
|
194 *compilerContext.module, constantState->getType(), true, ::llvm::GlobalValue::PrivateLinkage, constantState, newFunctionName + "_constState"); |
|
195 |
|
196 // When to delete the global variable? |
|
197 // -> When the pixel-pipe is removed from the cache. Also, when the compiler is deleted. |
|
198 |
|
199 ::llvm::DenseMap<const ::llvm::Value*, ::llvm::Value*> valueMap; |
|
200 std::pair<const ::llvm::Value*, ::llvm::Value*> valueReplacement((::llvm::Value*)&arg, constantStateVariable); |
|
201 valueMap.insert(valueReplacement); |
|
202 |
|
203 ::llvm::Function* specializedFunc = ::llvm::CloneFunction(compilerContext.llvmFunction, valueMap, NULL); |
|
204 specializedFunc->setName(newFunctionName); |
|
205 //specializedFunc->dump(); |
|
206 |
|
207 compilerContext.module->getFunctionList().push_back(specializedFunc); |
|
208 |
|
209 // \note Currently this creates the pass manager every time a pipeline is compiled... |
|
210 ::llvm::PassManager pm; |
|
211 // \todo Seems like the greater the threshold, the more the pass will inline: |
|
212 // In practice, everything should be inlineed into the resulting pipe. |
|
213 ::llvm::Pass* inliningPass = ::llvm::createFunctionInliningPass(100000); |
|
214 ::llvm::createStandardModulePasses(&pm, 3, false, true, true, true, false, inliningPass); |
|
215 pm.run(*compilerContext.module); |
|
216 |
|
217 //ppModule->dump(); |
|
218 |
|
219 //compilerContext.llvmFunction->dump(); |
|
220 PartialEvalFunc ret = {specializedFunc, constantStateVariable}; |
|
221 return ret; |
|
222 } |
|
223 |
|
224 /** |
|
225 * \brief Compile a pipeline if necessary. If the pipeline is cached, return a |
|
226 * handle to it. |
|
227 * \return NULL handle if operation was not successful, otherwise a handle to the pipeline. |
|
228 * \todo For deferred JITting, it might make sense to return a special value |
|
229 * to indicate that the pipeline is under compilation. |
|
230 * \note LLVM compilation should be thread-safe internally. |
|
231 */ |
|
232 PPCompiler::PixelPipeHandle PPCompiler::compilePixelPipeline(const PixelPipe::SignatureState& state) |
|
233 { |
|
234 PixelPipeHash hash; |
|
235 calculatePPHash(hash, state); |
|
236 |
|
237 PixelPipeEntryHandle entry = m_ppCache.findCachedItemByHash(hash); |
|
238 |
|
239 if (!entry) |
|
240 { |
|
241 PartialEvalFunc pf; |
|
242 std::string funcName = "compiledPPFunc_" + PPCompiler::stringOfArray(hash.value, sizeof(hash.value)/sizeof(hash.value[0])); |
|
243 pf = compilePixelPipeline(getLLVMContext(), m_ppContext, createPPConstant, (const void*)&state, funcName.c_str()); |
|
244 entry = m_ppCache.cacheFunction(hash, pf.llvmFunc, pf.llvmConst); |
|
245 #if defined(RI_DEBUG) && 0 |
|
246 pf.llvmFunc->dump(); |
|
247 #endif |
|
248 } |
|
249 |
|
250 if (!entry) |
|
251 { |
|
252 RI_ASSERT(false); |
|
253 // Release the function! |
|
254 } |
|
255 |
|
256 return (PixelPipeHandle)entry; |
|
257 } |
|
258 |
|
259 PPCompiler::BlitterHandle PPCompiler::compileBlitter(const DynamicBlitter::BlitSignatureState& state) |
|
260 { |
|
261 // \todo This function is almost the same as compilePixelPipeline. |
|
262 BlitterHash hash; |
|
263 DynamicBlitter::calculateHash(hash, state); |
|
264 |
|
265 BlitterEntryHandle entry = m_blitterCache.findCachedItemByHash(hash); |
|
266 |
|
267 if (!entry) |
|
268 { |
|
269 PartialEvalFunc pf; |
|
270 std::string funcName = "compiledBlitterFunc_" + PPCompiler::stringOfArray(hash.value, sizeof(hash.value)/sizeof(hash.value[0])); |
|
271 pf = compilePixelPipeline(getLLVMContext(), m_blitterContext, createBlitterConstant, (const void*)&state, funcName.c_str()); |
|
272 entry = m_blitterCache.cacheFunction(hash, pf.llvmFunc, pf.llvmConst); |
|
273 } |
|
274 |
|
275 if (!entry) |
|
276 { |
|
277 RI_ASSERT(false); |
|
278 // Release the function! |
|
279 } |
|
280 |
|
281 RI_ASSERT(entry); |
|
282 |
|
283 return (BlitterHandle)entry; |
|
284 } |
|
285 |
|
286 PixelPipeFunction PPCompiler::getPixelPipePtr(PixelPipeHandle handle) |
|
287 { |
|
288 PixelPipeEntryHandle entryHandle = (PixelPipeEntryHandle)handle; |
|
289 ::llvm::Function* function = m_ppCache.getFunction(entryHandle); |
|
290 |
|
291 FuncCaster c; |
|
292 c.ptr = m_executionEngine->getPointerToFunction(function); |
|
293 return c.pipeFunc; |
|
294 } |
|
295 |
|
296 BlitterFunction PPCompiler::getBlitterPtr(BlitterHandle handle) |
|
297 { |
|
298 BlitterEntryHandle entryHandle = (BlitterEntryHandle)handle; |
|
299 ::llvm::Function* function = m_blitterCache.getFunction(entryHandle); |
|
300 |
|
301 FuncCaster c; |
|
302 c.ptr = m_executionEngine->getPointerToFunction(function); |
|
303 return c.blitFunc; |
|
304 } |
|
305 |
|
306 // Release a reference to a pixel-pipeline handle. |
|
307 void PPCompiler::releasePixelPipeline(PixelPipeHandle handle) |
|
308 { |
|
309 PixelPipeEntryHandle entryHandle = (PixelPipeEntryHandle)handle; |
|
310 m_ppCache.releaseEntry(entryHandle); |
|
311 } |
|
312 |
|
313 // Release a reference to a blitter handle. |
|
314 void PPCompiler::releaseBlitter(BlitterHandle handle) |
|
315 { |
|
316 BlitterEntryHandle entryHandle = (BlitterEntryHandle)handle; |
|
317 m_blitterCache.releaseEntry(entryHandle); |
|
318 } |
|
319 |
|
320 #if 0 |
|
321 // \todo Complete this and make it fully recursive: this way all the C-structs |
|
322 // can be converted to corresponding LLVM classes at runtime. |
|
323 ::llvm::Constant* PPCompiler::createConstantStruct(const void* structure, size_t structSize, ::llvm::LLVMContext& llvmContext, const ::llvm::Type* structType) const |
|
324 { |
|
325 // Only copies integer-values (int, bools) |
|
326 RIuint8* bytePtr = (RIuint8*)structure; |
|
327 ::llvm::Type::subtype_iterator subtypeBegin, subtypeEnd; |
|
328 |
|
329 subtypeBegin = structType->subtype_begin(); |
|
330 subtypeEnd = structType->subtype_end(); |
|
331 |
|
332 for(::llvm::Type::subtype_iterator it = subtypeBegin; it != subtypeEnd; ++it) |
|
333 { |
|
334 ::llvm::Type* elementType = *it; |
|
335 RI_ASSERT(elementType->isSized()); |
|
336 unsigned int elementBitSize = elementType->getPrimitiveSizeInBits(); |
|
337 RI_ASSERT((elementBitSize % 8) == 0); |
|
338 unsigned int elementSize = elementBitSize / 8; |
|
339 RI_ASSERT(elementSize > 0 && elementSize <= 4); |
|
340 |
|
341 bytePtr += elementSize; |
|
342 } |
|
343 } |
|
344 #endif |
|
345 /** |
|
346 * \brief Creates a LLVM constant from a color descriptor. |
|
347 * \todo Create global constants from these for every possible color format! |
|
348 */ |
|
349 RI_INLINE static ::llvm::Constant* createDescConstant(const Color::Descriptor& desc, ::llvm::LLVMContext& llvmContext, const ::llvm::Type* structType) |
|
350 { |
|
351 ::llvm::Constant* constants[] = { |
|
352 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.redBits, true), |
|
353 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.redShift, true), |
|
354 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.greenBits, true), |
|
355 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.greenShift, true), |
|
356 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.blueBits, true), |
|
357 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.blueShift, true), |
|
358 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.alphaBits, true), |
|
359 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.alphaShift, true), |
|
360 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.luminanceBits, true), |
|
361 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.luminanceShift, true), |
|
362 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.shape, false), |
|
363 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.vgFormat, false), |
|
364 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.internalFormat, false), |
|
365 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.bitsPerPixel, true), |
|
366 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.bytesPerPixel, true), |
|
367 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.maskBits, true), |
|
368 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), desc.maskShift, true), |
|
369 }; |
|
370 |
|
371 std::vector< ::llvm::Constant*> structConsts; |
|
372 |
|
373 for (size_t i = 0; i < sizeof(constants)/sizeof(constants[0]); i++) |
|
374 { |
|
375 structConsts.push_back(constants[i]); |
|
376 } |
|
377 |
|
378 ::llvm::Constant* constStruct = ::llvm::ConstantStruct::get((::llvm::StructType*)structType, structConsts); |
|
379 |
|
380 return constStruct; |
|
381 } |
|
382 |
|
383 ::llvm::Constant* PPCompiler::createPPConstant(const void* signatureState, ::llvm::LLVMContext& llvmContext, const ::llvm::Type* structType) |
|
384 { |
|
385 // Get the actual object. This is a messy way to abstract setting the structure, but |
|
386 // there is little sense in making more classes/adapters/whatever at this point. |
|
387 const PixelPipe::SignatureState& state = *(const PixelPipe::SignatureState*)signatureState; |
|
388 // \todo There seems to be no way to track the structure member names once |
|
389 // LLVM has generated the bitcode (only offsets and references to those |
|
390 // offsets remain). Means to track proper setting of struct members in |
|
391 // DEBUG build must be implemented in some other way. |
|
392 // |
|
393 // For now, the state and this function must be kept carefully in sync! |
|
394 |
|
395 const int cDescriptorElementIndex = 8; |
|
396 const ::llvm::Type* descType = structType->getContainedType(cDescriptorElementIndex); |
|
397 |
|
398 ::llvm::Constant* constants[] = { |
|
399 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.blendMode, false), |
|
400 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.imageMode, false), |
|
401 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.paintType, false), |
|
402 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.maskOperation, false), |
|
403 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.paintTilingMode, false), |
|
404 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.paintSampler, false), |
|
405 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.imageSampler, false), |
|
406 |
|
407 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.imageGradientType, false), |
|
408 |
|
409 createDescConstant(state.dstDesc, llvmContext, descType), |
|
410 createDescConstant(state.maskDesc, llvmContext, descType), |
|
411 createDescConstant(state.imageDesc, llvmContext, descType), |
|
412 createDescConstant(state.patternDesc, llvmContext, descType), |
|
413 |
|
414 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.hasMasking, false), |
|
415 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.hasImage, false), |
|
416 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.hasColorTransform, false), |
|
417 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.isRenderToMask, false), |
|
418 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.fillColorTransparent, false), |
|
419 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.unsafeImageInput, false), |
|
420 }; |
|
421 |
|
422 std::vector< ::llvm::Constant*> structConsts; |
|
423 |
|
424 for (size_t i = 0; i < sizeof(constants)/sizeof(constants[0]); i++) |
|
425 { |
|
426 structConsts.push_back(constants[i]); |
|
427 } |
|
428 |
|
429 ::llvm::Constant* constStruct = ::llvm::ConstantStruct::get((::llvm::StructType*)structType, structConsts); |
|
430 |
|
431 return constStruct; |
|
432 } |
|
433 |
|
434 ::llvm::Constant* PPCompiler::createBlitterConstant(const void* signatureState, ::llvm::LLVMContext& llvmContext, const ::llvm::Type* structType) |
|
435 { |
|
436 const DynamicBlitter::BlitSignatureState& state = *(const DynamicBlitter::BlitSignatureState*)signatureState; |
|
437 |
|
438 const int cDescriptorElementIndex = 4; |
|
439 const ::llvm::Type* descType = structType->getContainedType(cDescriptorElementIndex); |
|
440 |
|
441 ::llvm::Constant* constants[] = { |
|
442 ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(llvmContext), state.maskOperation, false), |
|
443 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.incompatibleStrides, false), |
|
444 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.isMaskOperation, false), |
|
445 ::llvm::ConstantInt::get(::llvm::Type::getInt8Ty(llvmContext), state.unsafeInput, false), |
|
446 |
|
447 createDescConstant(state.srcDesc, llvmContext, descType), |
|
448 createDescConstant(state.dstDesc, llvmContext, descType), |
|
449 }; |
|
450 |
|
451 std::vector< ::llvm::Constant*> structConsts; |
|
452 |
|
453 for (size_t i = 0; i < sizeof(constants)/sizeof(constants[0]); i++) |
|
454 { |
|
455 structConsts.push_back(constants[i]); |
|
456 } |
|
457 |
|
458 ::llvm::Constant* constStruct = ::llvm::ConstantStruct::get((::llvm::StructType*)structType, structConsts); |
|
459 |
|
460 return constStruct; |
|
461 } |
|
462 |
|
463 /** |
|
464 * \brief Find a function whose name containst ``namepart''. Useful for finding c++ |
|
465 * decorated names from modules (if they are unique). |
|
466 * \note Maybe should use C-functions only in the final product. |
|
467 */ |
|
468 ::llvm::Function* PPCompiler::findFunctionWithString(::llvm::Module* module, const char* namepart) |
|
469 { |
|
470 // Find a function whose name contains 'namepart' |
|
471 llvm::Module::iterator it, end; |
|
472 it = module->begin(); |
|
473 end = module->end(); |
|
474 for (; it != end; ++it) |
|
475 { |
|
476 if (!it->isDeclaration()) |
|
477 if (it->getNameStr().find(namepart) != std::string::npos) |
|
478 return it; |
|
479 } |
|
480 return NULL; |
|
481 } |
|
482 |
|
483 void PPCompiler::llvmCheckPtrError(const void* ptr, std::string& err) |
|
484 { |
|
485 #if defined(RI_DEBUG) |
|
486 (void)err; |
|
487 //std::cout << "LLVM returned: " << ptr << ". Error string: \"" << err << "\"" << std::endl; |
|
488 #else |
|
489 (void)err; |
|
490 #endif |
|
491 if (!ptr) |
|
492 throw(-1); |
|
493 } |
|
494 |
|
495 /*static*/ std::string PPCompiler::stringOfArray(const RIuint32* arr, int nElems) |
|
496 { |
|
497 char tempBuffer[9]; |
|
498 std::stringstream out; |
|
499 // Ambiquities resolved by using a constant width: |
|
500 RI_ASSERT(nElems > 0); |
|
501 int i = nElems-1; |
|
502 do { |
|
503 snprintf(tempBuffer, sizeof(tempBuffer), "%08x", arr[i]); |
|
504 out << tempBuffer; |
|
505 i--; |
|
506 } while(i >= 0); |
|
507 |
|
508 return out.str(); |
|
509 } |
|
510 |
|
511 } |
|
512 |