+ * LLVM targets should be initialized before the driver or state-tracker tries
+ * to access the registry.
+ */
+ call_once(&init_native_targets_once_flag, init_native_targets);
+}
+
+extern "C"
+LLVMTargetLibraryInfoRef
+gallivm_create_target_library_info(const char *triple)
+{
+ return reinterpret_cast<LLVMTargetLibraryInfoRef>(
+#if HAVE_LLVM < 0x0307
+ new llvm::TargetLibraryInfo(
+#else
+ new llvm::TargetLibraryInfoImpl(
+#endif
+ llvm::Triple(triple)));
+}
+
+extern "C"
+void
+gallivm_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info)
+{
+ delete reinterpret_cast<
+#if HAVE_LLVM < 0x0307
+ llvm::TargetLibraryInfo
+#else
+ llvm::TargetLibraryInfoImpl
+#endif
+ *>(library_info);
+}
+
+
+#if HAVE_LLVM < 0x0304
+
+extern "C"
+void
+LLVMSetAlignmentBackport(LLVMValueRef V,
+ unsigned Bytes)
+{
+ switch (LLVMGetInstructionOpcode(V)) {
+ case LLVMLoad:
+ llvm::unwrap<llvm::LoadInst>(V)->setAlignment(Bytes);
+ break;
+ case LLVMStore:
+ llvm::unwrap<llvm::StoreInst>(V)->setAlignment(Bytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+#endif
+
+
+#if HAVE_LLVM < 0x0306
+typedef llvm::JITMemoryManager BaseMemoryManager;
+#else
+typedef llvm::RTDyldMemoryManager BaseMemoryManager;
+#endif
+
+
+/*
+ * Delegating is tedious but the default manager class is hidden in an
+ * anonymous namespace in LLVM, so we cannot just derive from it to change
+ * its behavior.
+ */
+class DelegatingJITMemoryManager : public BaseMemoryManager {
+
+ protected:
+ virtual BaseMemoryManager *mgr() const = 0;
+
+ public:
+#if HAVE_LLVM < 0x0306
+ /*
+ * From JITMemoryManager
+ */
+ virtual void setMemoryWritable() {
+ mgr()->setMemoryWritable();
+ }
+ virtual void setMemoryExecutable() {
+ mgr()->setMemoryExecutable();
+ }
+ virtual void setPoisonMemory(bool poison) {
+ mgr()->setPoisonMemory(poison);
+ }
+ virtual void AllocateGOT() {
+ mgr()->AllocateGOT();
+ /*
+ * isManagingGOT() is not virtual in base class so we can't delegate.
+ * Instead we mirror the value of HasGOT in our instance.
+ */
+ HasGOT = mgr()->isManagingGOT();
+ }
+ virtual uint8_t *getGOTBase() const {
+ return mgr()->getGOTBase();
+ }
+ virtual uint8_t *startFunctionBody(const llvm::Function *F,
+ uintptr_t &ActualSize) {
+ return mgr()->startFunctionBody(F, ActualSize);
+ }
+ virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
+ unsigned StubSize,
+ unsigned Alignment) {
+ return mgr()->allocateStub(F, StubSize, Alignment);
+ }
+ virtual void endFunctionBody(const llvm::Function *F,
+ uint8_t *FunctionStart,
+ uint8_t *FunctionEnd) {
+ mgr()->endFunctionBody(F, FunctionStart, FunctionEnd);
+ }
+ virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
+ return mgr()->allocateSpace(Size, Alignment);
+ }
+ virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
+ return mgr()->allocateGlobal(Size, Alignment);
+ }
+ virtual void deallocateFunctionBody(void *Body) {
+ mgr()->deallocateFunctionBody(Body);
+ }
+#if HAVE_LLVM < 0x0304
+ virtual uint8_t *startExceptionTable(const llvm::Function *F,
+ uintptr_t &ActualSize) {
+ return mgr()->startExceptionTable(F, ActualSize);
+ }
+ virtual void endExceptionTable(const llvm::Function *F,
+ uint8_t *TableStart,
+ uint8_t *TableEnd,
+ uint8_t *FrameRegister) {
+ mgr()->endExceptionTable(F, TableStart, TableEnd,
+ FrameRegister);
+ }
+ virtual void deallocateExceptionTable(void *ET) {
+ mgr()->deallocateExceptionTable(ET);
+ }
+#endif
+ virtual bool CheckInvariants(std::string &s) {
+ return mgr()->CheckInvariants(s);
+ }
+ virtual size_t GetDefaultCodeSlabSize() {
+ return mgr()->GetDefaultCodeSlabSize();
+ }
+ virtual size_t GetDefaultDataSlabSize() {
+ return mgr()->GetDefaultDataSlabSize();
+ }
+ virtual size_t GetDefaultStubSlabSize() {
+ return mgr()->GetDefaultStubSlabSize();
+ }
+ virtual unsigned GetNumCodeSlabs() {
+ return mgr()->GetNumCodeSlabs();
+ }
+ virtual unsigned GetNumDataSlabs() {
+ return mgr()->GetNumDataSlabs();
+ }
+ virtual unsigned GetNumStubSlabs() {
+ return mgr()->GetNumStubSlabs();
+ }
+#endif
+
+ /*
+ * From RTDyldMemoryManager
+ */
+#if HAVE_LLVM >= 0x0304
+ virtual uint8_t *allocateCodeSection(uintptr_t Size,
+ unsigned Alignment,
+ unsigned SectionID,
+ llvm::StringRef SectionName) {
+ return mgr()->allocateCodeSection(Size, Alignment, SectionID,
+ SectionName);
+ }
+#else
+ virtual uint8_t *allocateCodeSection(uintptr_t Size,
+ unsigned Alignment,
+ unsigned SectionID) {
+ return mgr()->allocateCodeSection(Size, Alignment, SectionID);
+ }
+#endif
+ virtual uint8_t *allocateDataSection(uintptr_t Size,
+ unsigned Alignment,
+ unsigned SectionID,
+#if HAVE_LLVM >= 0x0304
+ llvm::StringRef SectionName,
+#endif
+ bool IsReadOnly) {
+ return mgr()->allocateDataSection(Size, Alignment, SectionID,
+#if HAVE_LLVM >= 0x0304
+ SectionName,
+#endif
+ IsReadOnly);
+ }
+#if HAVE_LLVM >= 0x0304
+ virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
+ mgr()->registerEHFrames(Addr, LoadAddr, Size);
+ }
+#else
+ virtual void registerEHFrames(llvm::StringRef SectionData) {
+ mgr()->registerEHFrames(SectionData);
+ }
+#endif
+#if HAVE_LLVM >= 0x0500
+ virtual void deregisterEHFrames() {
+ mgr()->deregisterEHFrames();
+ }
+#elif HAVE_LLVM >= 0x0304
+ virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
+ mgr()->deregisterEHFrames(Addr, LoadAddr, Size);
+ }
+#endif
+ virtual void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure=true) {
+ return mgr()->getPointerToNamedFunction(Name, AbortOnFailure);
+ }
+#if HAVE_LLVM <= 0x0303
+ virtual bool applyPermissions(std::string *ErrMsg = 0) {
+ return mgr()->applyPermissions(ErrMsg);
+ }
+#else
+ virtual bool finalizeMemory(std::string *ErrMsg = 0) {
+ return mgr()->finalizeMemory(ErrMsg);
+ }
+#endif
+};
+
+
+/*
+ * Delegate memory management to one shared manager for more efficient use
+ * of memory than creating a separate pool for each LLVM engine.
+ * Keep generated code until freeGeneratedCode() is called, instead of when
+ * memory manager is destroyed, which happens during engine destruction.
+ * This allows additional memory savings as we don't have to keep the engine
+ * around in order to use the code.
+ * All methods are delegated to the shared manager except destruction and
+ * deallocating code. For the latter we just remember what needs to be
+ * deallocated later. The shared manager is deleted once it is empty.
+ */
+class ShaderMemoryManager : public DelegatingJITMemoryManager {
+
+ BaseMemoryManager *TheMM;
+
+ struct GeneratedCode {
+ typedef std::vector<void *> Vec;
+ Vec FunctionBody, ExceptionTable;
+ BaseMemoryManager *TheMM;
+
+ GeneratedCode(BaseMemoryManager *MM) {
+ TheMM = MM;
+ }
+
+ ~GeneratedCode() {
+ /*
+ * Deallocate things as previously requested and
+ * free shared manager when no longer used.
+ */
+#if HAVE_LLVM < 0x0306
+ Vec::iterator i;
+
+ assert(TheMM);
+ for ( i = FunctionBody.begin(); i != FunctionBody.end(); ++i )
+ TheMM->deallocateFunctionBody(*i);
+#if HAVE_LLVM < 0x0304
+ for ( i = ExceptionTable.begin(); i != ExceptionTable.end(); ++i )
+ TheMM->deallocateExceptionTable(*i);
+#endif /* HAVE_LLVM < 0x0304 */
+#endif /* HAVE_LLVM < 0x0306 */
+ }
+ };
+
+ GeneratedCode *code;
+
+ BaseMemoryManager *mgr() const {
+ return TheMM;
+ }
+
+ public:
+
+ ShaderMemoryManager(BaseMemoryManager* MM) {
+ TheMM = MM;
+ code = new GeneratedCode(MM);
+ }
+
+ virtual ~ShaderMemoryManager() {
+ /*
+ * 'code' is purposely not deleted. It is the user's responsibility
+ * to call getGeneratedCode() and freeGeneratedCode().
+ */
+ }
+
+ struct lp_generated_code *getGeneratedCode() {
+ return (struct lp_generated_code *) code;
+ }
+
+ static void freeGeneratedCode(struct lp_generated_code *code) {
+ delete (GeneratedCode *) code;
+ }
+
+#if HAVE_LLVM < 0x0304
+ virtual void deallocateExceptionTable(void *ET) {
+ // remember for later deallocation
+ code->ExceptionTable.push_back(ET);
+ }
+#endif
+
+ virtual void deallocateFunctionBody(void *Body) {
+ // remember for later deallocation
+ code->FunctionBody.push_back(Body);
+ }
+};
+
+
+/**
+ * Same as LLVMCreateJITCompilerForModule, but:
+ * - allows using MCJIT and enabling AVX feature where available.
+ * - set target options
+ *
+ * See also:
+ * - llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+ * - llvm/tools/lli/lli.cpp
+ * - http://markmail.org/message/ttkuhvgj4cxxy2on#query:+page:1+mid:aju2dggerju3ivd3+state:results
+ */
+extern "C"
+LLVMBool
+lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
+ lp_generated_code **OutCode,
+ LLVMModuleRef M,
+ LLVMMCJITMemoryManagerRef CMM,
+ unsigned OptLevel,
+ int useMCJIT,
+ char **OutError)
+{
+ using namespace llvm;
+
+ std::string Error;
+#if HAVE_LLVM >= 0x0306
+ EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));
+#else
+ EngineBuilder builder(unwrap(M));
+#endif
+
+ /**
+ * LLVM 3.1+ haven't more "extern unsigned llvm::StackAlignmentOverride" and
+ * friends for configuring code generation options, like stack alignment.