hostsupport/hostopenvg/src/src/sfCompiler.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     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