libclamav/c++/bytecode2llvm.cpp
f18dc607
 /*
e32caecb
  *  JIT compile ClamAV bytecode.
f18dc607
  *
c442ca9c
  *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  *  Copyright (C) 2009-2013 Sourcefire, Inc.
f18dc607
  *
  *  Authors: Török Edvin
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  */
6b67ec6e
 #define DEBUG_TYPE "clamavjit"
884a0b8f
 #include <pthread.h>
 #ifndef _WIN32
 #include <sys/time.h>
 #endif
9f8df4ae
 #include <cstdlib>
 #include <csetjmp>
 #include <new>
 #include <cerrno>
 #include <string>
fb2b05cb
 
1e30496d
 #include "ClamBCModule.h"
daad92ac
 #include "ClamBCDiagnostics.h"
9f8df4ae
 #include "llvm30_compat.h"
 
daffb518
 #include "llvm/ADT/DenseMap.h"
459b13ed
 #include "llvm/ADT/BitVector.h"
99536a17
 #include "llvm/ADT/PostOrderIterator.h"
65c740d7
 #include "llvm/ADT/StringMap.h"
b3571ea9
 #include "llvm/ADT/StringSwitch.h"
6eeadbfe
 #include "llvm/ADT/Triple.h"
99536a17
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/ScalarEvolution.h"
4a40b53a
 #if LLVM_VERSION < 35
99536a17
 #include "llvm/Analysis/Verifier.h"
744c40d1
 #include "llvm/AutoUpgrade.h"
4a40b53a
 #include "llvm/Support/TargetFolder.h"
 #else
 #include "llvm/IR/Verifier.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/Analysis/TargetFolder.h"
 #endif
3b33bd68
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
2c859ec7
 #if LLVM_VERSION < 36
3b33bd68
 #include "llvm/ExecutionEngine/JIT.h"
2c859ec7
 #else
 #include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Object/ObjectFile.h"
 #endif
3b33bd68
 #include "llvm/ExecutionEngine/JITEventListener.h"
ee8f1888
 #include "llvm/PassManager.h"
3b33bd68
 #include "llvm/Support/Compiler.h"
6b67ec6e
 #include "llvm/Support/Debug.h"
3b33bd68
 #include "llvm/Support/CommandLine.h"
d1487222
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
65c740d7
 #include "llvm/Support/MemoryBuffer.h"
d1487222
 #include "llvm/Support/raw_ostream.h"
65c740d7
 #include "llvm/Support/SourceMgr.h"
3b33bd68
 #include "llvm/Support/PrettyStackTrace.h"
0c79cc55
 
9f8df4ae
 #if LLVM_VERSION < 29
 #include "llvm/System/DataTypes.h"
 #include "llvm/System/Host.h"
 #include "llvm/System/Memory.h"
 #include "llvm/System/Mutex.h"
 #include "llvm/System/Signals.h"
 #include "llvm/System/Threading.h"
 #include "llvm/System/ThreadLocal.h"
 #else
 #include "llvm/PassRegistry.h"
0c79cc55
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/Mutex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/ThreadLocal.h"
9f8df4ae
 #endif
 
34d8b8cf
 #if LLVM_VERSION < 33
 #include "llvm/IntrinsicInst.h"
 #else
 #include "llvm/IR/IntrinsicInst.h"
 #endif
0c79cc55
 
 #include "llvm/Support/Timer.h"
dccafff0
 
ce238673
 extern "C" {
dccafff0
 void LLVMInitializeX86AsmPrinter();
 void LLVMInitializePowerPCAsmPrinter();
ce238673
 }
9f8df4ae
 
 #if LLVM_VERSION < 30
d1487222
 #include "llvm/Target/TargetSelect.h"
9f8df4ae
 #else
 #include "llvm/Support/TargetSelect.h"
59f1b78b
 #endif
9f8df4ae
 
d2171abf
 #include "llvm/Target/TargetOptions.h"
6b67ec6e
 #include "llvm/Transforms/Scalar.h"
6e52ce67
 #include "llvm/Transforms/IPO.h"
99536a17
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
d1487222
 
34d8b8cf
 #if LLVM_VERSION < 32
 #include "llvm/Analysis/DebugInfo.h"
4a40b53a
 #elif LLVM_VERSION < 35
34d8b8cf
 #include "llvm/DebugInfo.h"
4a40b53a
 #else
 #include "llvm/IR/DebugInfo.h"
34d8b8cf
 #endif
 
 #if LLVM_VERSION < 32
 #include "llvm/Support/IRBuilder.h"
 #include "llvm/Target/TargetData.h"
 #elif LLVM_VERSION < 33
 #include "llvm/IRBuilder.h"
 #include "llvm/DataLayout.h"
 #else
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/DataLayout.h"
 #endif
 
 #if LLVM_VERSION < 33
 #include "llvm/CallingConv.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Module.h"
 #else
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Module.h"
 #endif
 
9f8df4ae
 #if LLVM_VERSION < 34
 #include "llvm/Support/CFG.h"
 #else
34d8b8cf
 #include "llvm/Analysis/CFG.h"
 #endif
 
4a40b53a
 #if LLVM_VERSION >= 35
 #include "llvm/IR/Dominators.h"
 #endif
 
6e52ce67
 //#define TIMING
 #undef TIMING
 
2c7d5adc
 #include "llvm/Config/config.h"
34d8b8cf
 #ifdef ENABLE_THREADS
ee6ab4f8
 #if !ENABLE_THREADS
 #error "Thread support was explicitly disabled. Cannot continue"
2c7d5adc
 #endif
34d8b8cf
 #endif
 
 #ifdef LLVM_ENABLE_THREADS
 #if !LLVM_ENABLE_THREADS
 #error "Thread support was explicitly disabled. Cannot continue"
 #endif
 #endif
d38d6dad
 
bcb354a6
 #ifdef _GLIBCXX_PARALLEL
 #error "libstdc++ parallel mode is not supported for ClamAV. Please remove -D_GLIBCXX_PARALLEL from CXXFLAGS!"
 #endif
 
d38d6dad
 #ifdef HAVE_CONFIG_H
 #undef PACKAGE_BUGREPORT
 #undef PACKAGE_NAME
 #undef PACKAGE_STRING
 #undef PACKAGE_TARNAME
 #undef PACKAGE_VERSION
f60c59a4
 #undef PACKAGE_URL
d38d6dad
 #include "clamav-config.h"
 #endif
fb2b05cb
 
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
f60c59a4
 #include "dconf.h"
d1487222
 #include "clamav.h"
 #include "clambc.h"
 #include "bytecode.h"
0a11015b
 #include "bytecode_priv.h"
80b4b3fb
 #include "type_desc.h"
d1487222
 
 #define MODULE "libclamav JIT: "
 
9463f9fd
 extern "C" unsigned int cli_rndnum(unsigned int max);
d1487222
 using namespace llvm;
daffb518
 typedef DenseMap<const struct cli_bc_func*, void*> FunctionMapTy;
d1487222
 struct cli_bcengine {
     ExecutionEngine *EE;
e2752b2c
     JITEventListener *Listener;
d1487222
     LLVMContext Context;
3b33bd68
     FunctionMapTy compiledFunctions;
9463f9fd
     union {
 	unsigned char b[16];
 	void* align;/* just to align field to ptr */
     } guard;
d1487222
 };
 
09667cdd
 extern "C" uint8_t cli_debug_flag;
9f8df4ae
 #if LLVM_VERSION >= 29
0c79cc55
 namespace llvm {
     void initializeRuntimeLimitsPass(PassRegistry&);
 };
 #endif
d1487222
 namespace {
 
9f8df4ae
 #if LLVM_VERSION >= 28
e3a54503
 #define llvm_report_error(x) report_fatal_error(x)
 #define llvm_install_error_handler(x) install_fatal_error_handler(x)
 #define DwarfExceptionHandling JITExceptionHandling
 #define SetCurrentDebugLocation(x) SetCurrentDebugLocation(DebugLoc::getFromDILocation(x))
1755adf0
 #define DEFINEPASS(passname) passname() : FunctionPass(ID)
 #else
 #define DEFINEPASS(passname) passname() : FunctionPass(&ID)
e3a54503
 #endif
 
9f8df4ae
 #if LLVM_VERSION >= 29
0c79cc55
 #define NORETURN LLVM_ATTRIBUTE_NORETURN
 #endif
 
6b67ec6e
 static sys::ThreadLocal<const jmp_buf> ExceptionReturn;
 
744c40d1
 static void UpgradeCall(CallInst *&C, Function *Intr)
 {
     Function *New;
     if (!UpgradeIntrinsicFunction(Intr, New) || New == Intr)
 	return;
     UpgradeIntrinsicCall(C, New);
 }
 
162c2e43
 extern "C" {
 #ifdef __GNUC__
 void cli_errmsg(const char *str, ...) __attribute__((format(printf, 1, 2)));
 #else
 void cli_errmsg(const char *str, ...);
 #endif
 
 #ifdef __GNUC__
 void cli_warnmsg(const char *str, ...) __attribute__((format(printf, 1, 2)));
 #else
 void cli_warnmsg(const char *str, ...);
 #endif
 
 #ifdef __GNUC__
 void cli_dbgmsg_internal(const char *str, ...) __attribute__((format(printf, 1, 2)));
 #else
 void cli_dbgmsg_internal(const char *str, ...);
 #endif
 }
 
 class ScopedExceptionHandler {
     public:
3a35520b
 	jmp_buf &getEnv() { return env;}
 	void Set() {
 	    /* set the exception handler's return location to here for the
 	     * current thread */
 	    ExceptionReturn.set((const jmp_buf*)&env);
162c2e43
 	}
 	~ScopedExceptionHandler() {
 	    /* leaving scope, remove exception handler for current thread */
 	    ExceptionReturn.erase();
 	}
     private:
 	jmp_buf env;
 };
3a35520b
 #define HANDLER_TRY(handler) \
     if (setjmp(handler.getEnv()) == 0) {\
 	handler.Set();
 
 #define HANDLER_END(handler) \
     } else cli_warnmsg("[Bytecode JIT]: recovered from error\n");
 
162c2e43
 
3b33bd68
 void do_shutdown() {
162c2e43
     ScopedExceptionHandler handler;
3a35520b
     HANDLER_TRY(handler) {
162c2e43
 	// TODO: be on the safe side, and clear errors here,
 	// otherwise destructor calls report_fatal_error
 	((class raw_fd_ostream&)errs()).clear_error();
 
 	llvm_shutdown();
 
 	((class raw_fd_ostream&)errs()).clear_error();
     }
3a35520b
     HANDLER_END(handler);
f62d5398
     remove_fatal_error_handler();
3b33bd68
 }
daffb518
 
6b67ec6e
 static void NORETURN jit_exception_handler(void)
 {
ce238673
     jmp_buf* buf = const_cast<jmp_buf*>(ExceptionReturn.get());
162c2e43
     if (buf) {
 	// For errors raised during bytecode generation and execution.
 	longjmp(*buf, 1);
     } else {
 	// Oops, got no error recovery pointer set up,
 	// this is probably an error raised during shutdown.
 	cli_errmsg("[Bytecode JIT]: exception handler called, but no recovery point set up");
f62d5398
 	// should never happen, we remove the error handler when we don't use
 	// LLVM anymore, and when we use it, we do set an error recovery point.
ce238673
 	llvm_unreachable("Bytecode JIT]: no exception handler recovery installed, but exception hit!");
162c2e43
     }
6b67ec6e
 }
 
9463f9fd
 static void NORETURN jit_ssp_handler(void)
 {
162c2e43
     cli_errmsg("[Bytecode JIT]: *** stack smashing detected, bytecode aborted\n");
9463f9fd
     jit_exception_handler();
 }
 
34d8b8cf
 #if LLVM_VERSION < 33
3b33bd68
 void llvm_error_handler(void *user_data, const std::string &reason)
34d8b8cf
 #else
 void llvm_error_handler(void *user_data, const std::string &reason, bool gen_crash_diag = true)
 #endif
3b33bd68
 {
80b4b3fb
     // Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg
162c2e43
     cli_errmsg("[Bytecode JIT]: [LLVM error] %s\n", reason.c_str());
6b67ec6e
     jit_exception_handler();
3b33bd68
 }
daffb518
 
b3571ea9
 // Since libgcc is not available on all compilers (for example on win32),
 // just define what these functions should do, the compiler will forward to
 // the appropriate libcall if needed.
 static int64_t rtlib_sdiv_i64(int64_t a, int64_t b)
 {
     return a/b;
 }
 
 static uint64_t rtlib_udiv_i64(uint64_t a, uint64_t b)
 {
     return a/b;
 }
 
 static int64_t rtlib_srem_i64(int64_t a, int64_t b)
 {
     return a%b;
 }
 
 static uint64_t rtlib_urem_i64(uint64_t a, uint64_t b)
 {
     return a%b;
 }
 
 static int64_t rtlib_mul_i64(uint64_t a, uint64_t b)
 {
     return a*b;
 }
 
 static int64_t rtlib_shl_i64(int64_t a, int32_t b)
 {
     return a << b;
 }
 
 static int64_t rtlib_srl_i64(int64_t a, int32_t b)
 {
     return (uint64_t)a >> b;
 }
 /* Implementation independent sign-extended signed right shift */
 #ifdef HAVE_SAR
 #define CLI_SRS(n,s) ((n)>>(s))
 #else
 #define CLI_SRS(n,s) ((((n)>>(s)) ^ (1<<(sizeof(n)*8-1-s))) - (1<<(sizeof(n)*8-1-s)))
 #endif
 static int64_t rtlib_sra_i64(int64_t a, int32_t b)
 {
     return CLI_SRS(a, b);//CLI_./..
 }
 
cb1260cc
 static void rtlib_bzero(void *s, size_t n)
 {
     memset(s, 0, n);
 }
 
49558860
 #ifdef _WIN32
e92dda94
 #ifdef _WIN64
 extern "C" void __chkstk(void);
 #else
49558860
 extern "C" void _chkstk(void);
 #endif
e92dda94
 #endif
b3571ea9
 // Resolve integer libcalls, but nothing else.
 static void* noUnknownFunctions(const std::string& name) {
     void *addr =
 	StringSwitch<void*>(name)
 	.Case("__divdi3", (void*)(intptr_t)rtlib_sdiv_i64)
 	.Case("__udivdi3", (void*)(intptr_t)rtlib_udiv_i64)
 	.Case("__moddi3", (void*)(intptr_t)rtlib_srem_i64)
 	.Case("__umoddi3", (void*)(intptr_t)rtlib_urem_i64)
 	.Case("__muldi3", (void*)(intptr_t)rtlib_mul_i64)
 	.Case("__ashrdi3", (void*)(intptr_t)rtlib_sra_i64)
 	.Case("__ashldi3", (void*)(intptr_t)rtlib_shl_i64)
 	.Case("__lshrdi3", (void*)(intptr_t)rtlib_srl_i64)
cb1260cc
 	.Case("__bzero", (void*)(intptr_t)rtlib_bzero)
4395bb9a
 	.Case("memmove", (void*)(intptr_t)memmove)
 	.Case("memcpy", (void*)(intptr_t)memcpy)
 	.Case("memset", (void*)(intptr_t)memset)
1e30496d
 	.Case("abort", (void*)(intptr_t)jit_exception_handler)
49558860
 #ifdef _WIN32
ca3e6c58
 #ifdef _WIN64
3d8ca9f6
 	.Case("_chkstk", (void*)(intptr_t)__chkstk)
ca3e6c58
 #else
49558860
 	.Case("_chkstk", (void*)(intptr_t)_chkstk)
 #endif
ca3e6c58
 #endif
b3571ea9
 	.Default(0);
     if (addr)
 	return addr;
 
2c859ec7
 #if LLVM_VERSION < 36
b3571ea9
     std::string reason((Twine("Attempt to call external function ")+name).str());
     llvm_error_handler(0, reason);
2c859ec7
 #else
     // noUnknownFunctions relies on addGlobalMapping, which doesn't work with MCJIT.
     // Now the function pointers are found with SymbolSearching.
 #endif
b3571ea9
     return 0;
 }
 
09667cdd
 class NotifyListener : public JITEventListener {
 public:
2c859ec7
 #if LLVM_VERSION < 36
09667cdd
     virtual void NotifyFunctionEmitted(const Function &F,
 				       void *Code, size_t Size,
 				       const EmittedFunctionDetails &Details)
     {
 	if (!cli_debug_flag)
 	    return;
29553b8e
 	cli_dbgmsg_internal("[Bytecode JIT]: emitted function %s of %ld bytes at %p\n",
34d8b8cf
 #if LLVM_VERSION < 31
29553b8e
 			    F.getNameStr().c_str(), (long)Size, Code);
34d8b8cf
 #else
 			    F.getName().str().c_str(), (long)Size, Code);
 #endif
09667cdd
     }
2c859ec7
 #else
     // MCJIT doesn't emit single functions, but instead whole objects.
     virtual void NotifyObjectEmitted(const object::ObjectFile &Obj,
                                      const RuntimeDyld::LoadedObjectInfo &L)
     {
         if (!cli_debug_flag)
             return;
         cli_dbgmsg_internal("[Bytecode JIT]; emitted %s %s of %zd bytes\n",
                             Obj.getFileFormatName().str().c_str(),
                             Obj.getFileName().str().c_str(), Obj.getData().size());
     }
 #endif
09667cdd
 };
 
c0a306b2
 class TimerWrapper {
 private:
     Timer *t;
 public:
     TimerWrapper(const std::string &name) {
 	t = 0;
 #ifdef TIMING
 	t = new Timer(name);
 #endif
     }
     ~TimerWrapper()
     {
 	if (t)
 	    delete t;
     }
     void startTimer()
     {
 	if (t)
 	    t->startTimer();
     }
     void stopTimer()
     {
 	if (t)
 	    t->stopTimer();
     }
 };
 
e32caecb
 class LLVMTypeMapper {
3b33bd68
 private:
9f8df4ae
 #if LLVM_VERSION < 30
e32caecb
     std::vector<PATypeHolder> TypeMap;
9f8df4ae
 #else
     std::vector<Type*> TypeMap;
59f1b78b
 #endif
3b33bd68
     LLVMContext &Context;
e32caecb
     unsigned numTypes;
59f1b78b
     constType *getStatic(uint16_t ty)
3b33bd68
     {
 	if (!ty)
 	    return Type::getVoidTy(Context);
ee8f1888
 	if (ty <= 64)
3b33bd68
 	    return IntegerType::get(Context, ty);
 	switch (ty) {
 	    case 65:
 		return PointerType::getUnqual(Type::getInt8Ty(Context));
 	    case 66:
 		return PointerType::getUnqual(Type::getInt16Ty(Context));
 	    case 67:
 		return PointerType::getUnqual(Type::getInt32Ty(Context));
 	    case 68:
 		return PointerType::getUnqual(Type::getInt64Ty(Context));
 	}
e32caecb
 	llvm_unreachable("getStatic");
     }
 public:
c0a306b2
     TimerWrapper pmTimer;
     TimerWrapper irgenTimer;
6e52ce67
 
e32caecb
     LLVMTypeMapper(LLVMContext &Context, const struct cli_bc_type *types,
59f1b78b
 		   unsigned count, constType *Hidden=0) : Context(Context), numTypes(count),
6e52ce67
     pmTimer("Function passes"),irgenTimer("IR generation")
e32caecb
     {
 	TypeMap.reserve(count);
 	// During recursive type construction pointers to Type* may be
 	// invalidated, so we must use a TypeHolder to an Opaque type as a
 	// start.
 	for (unsigned i=0;i<count;i++) {
9f8df4ae
 #if LLVM_VERSION < 30
e32caecb
 	    TypeMap.push_back(OpaqueType::get(Context));
9f8df4ae
 #else
 	    TypeMap.push_back(0);
59f1b78b
 #endif
e32caecb
 	}
 	for (unsigned i=0;i<count;i++) {
 	    const struct cli_bc_type *type = &types[i];
59f1b78b
 
 	    constType *Ty = buildType(type, types, Hidden, 0);
9f8df4ae
 #if LLVM_VERSION < 30
59f1b78b
 	    // Make the opaque type a concrete type, doing recursive type
 	    // unification if needed.
 	    cast<OpaqueType>(TypeMap[i].get())->refineAbstractTypeTo(Ty);
9f8df4ae
 #else
 	    TypeMap[i] = Ty;
59f1b78b
 #endif
 	}
     }
 
     constType *buildType(const struct cli_bc_type *type, const struct cli_bc_type *types, constType *Hidden,
 			 int recursive)
     {
 	std::vector<constType*> Elts;
 	unsigned n = type->kind == DArrayType ? 1 : type->numElements;
 	for (unsigned j=0;j<n;j++) {
 	    Elts.push_back(get(type->containedTypes[j], types, Hidden));
 	}
 	constType *Ty;
 	switch (type->kind) {
 	    case DFunctionType:
e32caecb
 		{
 		    assert(Elts.size() > 0 && "Function with no return type?");
59f1b78b
 		    constType *RetTy = Elts[0];
d0af4afe
 		    if (Hidden)
 			Elts[0] = Hidden;
 		    else
 			Elts.erase(Elts.begin());
e32caecb
 		    Ty = FunctionType::get(RetTy, Elts, false);
 		    break;
 		}
59f1b78b
 	    case DPointerType:
 		if (!PointerType::isValidElementType(Elts[0]))
 		    Ty = PointerType::getUnqual(Type::getInt8Ty(Context));
 		else
 		    Ty = PointerType::getUnqual(Elts[0]);
 		break;
 	    case DStructType:
 	    case DPackedStructType:
 		Ty = StructType::get(Context, Elts, type->kind == DPackedStructType);
 		break;
 	    case DArrayType:
 		Ty = ArrayType::get(Elts[0], type->numElements);
 		break;
 	    default:
 		llvm_unreachable("type->kind");
e32caecb
 	}
59f1b78b
 	return Ty;
e32caecb
     }
 
59f1b78b
     constType *get(uint16_t ty, const struct cli_bc_type *types, constType *Hidden)
e32caecb
     {
a45e2577
 	ty &= 0x7fff;
e32caecb
 	if (ty < 69)
 	    return getStatic(ty);
3b33bd68
 	ty -= 69;
e32caecb
 	assert(ty < numTypes && "TypeID out of range");
9f8df4ae
 #if LLVM_VERSION < 30
 	return TypeMap[ty].get();
 #else
59f1b78b
 	Type *Ty = TypeMap[ty];
 	if (Ty)
 	    return Ty;
 	assert(types && Hidden || "accessing not-yet-built type");
 	Ty = buildType(&types[ty], types, Hidden, 1);
 	TypeMap[ty] = Ty;
 	return Ty;
 #endif
3b33bd68
     }
e32caecb
 };
3b33bd68
 
57bbb2eb
 struct CommonFunctions {
     Function *FHandler;
     Function *FMemset;
     Function *FMemmove;
     Function *FMemcpy;
     Function *FRealmemset;
     Function *FRealMemmove;
     Function *FRealmemcmp;
     Function *FRealmemcpy;
     Function *FBSwap16;
     Function *FBSwap32;
     Function *FBSwap64;
 };
daffb518
 
99536a17
 // loops with tripcounts higher than this need timeout check
 static const unsigned LoopThreshold = 1000;
 
 // after every N API calls we need timeout check
 static const unsigned ApiThreshold = 100;
 
 class RuntimeLimits : public FunctionPass {
     typedef SmallVector<std::pair<const BasicBlock*, const BasicBlock*>, 16>
 	BBPairVectorTy;
     typedef SmallSet<BasicBlock*, 16> BBSetTy;
     typedef DenseMap<const BasicBlock*, unsigned> BBMapTy;
     bool loopNeedsTimeoutCheck(ScalarEvolution &SE, const Loop *L, BBMapTy &Map) {
 	// This BB is a loop header, if trip count is small enough
 	// no timeout checks are needed here.
 	const SCEV *S = SE.getMaxBackedgeTakenCount(L);
 	if (isa<SCEVCouldNotCompute>(S))
 	    return true;
 	DEBUG(errs() << "Found loop trip count" << *S << "\n");
 	ConstantRange CR = SE.getUnsignedRange(S);
 	uint64_t max = CR.getUnsignedMax().getLimitedValue();
 	DEBUG(errs() << "Found max trip count " << max << "\n");
 	if (max > LoopThreshold)
 	    return true;
 	unsigned apicalls = 0;
 	for (Loop::block_iterator J=L->block_begin(),JE=L->block_end();
 	     J != JE; ++J) {
 	    apicalls += Map[*J];
 	}
 	apicalls *= max;
 	if (apicalls > ApiThreshold) {
 	    DEBUG(errs() << "apicall threshold exceeded: " << apicalls << "\n");
 	    return true;
 	}
 	Map[L->getHeader()] = apicalls;
 	return false;
     }
 
 public:
     static char ID;
0c79cc55
     DEFINEPASS(RuntimeLimits) {
9f8df4ae
 #if LLVM_VERSION >= 29
0c79cc55
 	PassRegistry &Registry = *PassRegistry::getPassRegistry();
 	initializeRuntimeLimitsPass(Registry);
 #endif
     }
99536a17
 
     virtual bool runOnFunction(Function &F) {
 	BBSetTy BackedgeTargets;
 	if (!F.isDeclaration()) {
 	    // Get the common backedge targets.
 	    // Note that we don't rely on LoopInfo here, since
 	    // it is possible to construct a CFG that doesn't have natural loops,
 	    // yet it does have backedges, and thus can lead to unbounded/high
 	    // execution time.
 	    BBPairVectorTy V;
 	    FindFunctionBackedges(F, V);
 	    for (BBPairVectorTy::iterator I=V.begin(),E=V.end();I != E; ++I) {
 		BackedgeTargets.insert(const_cast<BasicBlock*>(I->second));
 	    }
 	}
 	BBSetTy  needsTimeoutCheck;
 	BBMapTy BBMap;
4a40b53a
 #if LLVM_VERSION < 35
99536a17
 	DominatorTree &DT = getAnalysis<DominatorTree>();
4a40b53a
 #else
 	DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
 #endif
99536a17
 	for (Function::iterator I=F.begin(),E=F.end(); I != E; ++I) {
 	    BasicBlock *BB = &*I;
 	    unsigned apicalls = 0;
 	    for (BasicBlock::const_iterator J=BB->begin(),JE=BB->end();
 		 J != JE; ++J) {
 		if (const CallInst *CI = dyn_cast<CallInst>(J)) {
 		    Function *F = CI->getCalledFunction();
 		    if (!F || F->isDeclaration())
 			apicalls++;
 		}
 	    }
 	    if (apicalls > ApiThreshold) {
 		DEBUG(errs() << "apicall threshold exceeded: " << apicalls << "\n");
 		needsTimeoutCheck.insert(BB);
 		apicalls = 0;
 	    }
 	    BBMap[BB] = apicalls;
 	}
 	if (!BackedgeTargets.empty()) {
 	    LoopInfo &LI = getAnalysis<LoopInfo>();
 	    ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
 
 	    // Now check whether any of these backedge targets are part of a loop
 	    // with a small constant trip count
 	    for (BBSetTy::iterator I=BackedgeTargets.begin(),E=BackedgeTargets.end();
 		 I != E; ++I) {
 		const Loop *L = LI.getLoopFor(*I);
 		if (L && L->getHeader() == *I &&
 		    !loopNeedsTimeoutCheck(SE, L, BBMap))
 		    continue;
 		needsTimeoutCheck.insert(*I);
 		BBMap[*I] = 0;
 	    }
 	}
 	// Estimate number of apicalls by walking dominator-tree bottom-up.
 	// BBs that have timeout checks are considered to have 0 APIcalls
 	// (since we already checked for timeout).
 	for (po_iterator<DomTreeNode*> I = po_begin(DT.getRootNode()),
 	     E = po_end(DT.getRootNode()); I != E; ++I) {
 	    if (needsTimeoutCheck.count(I->getBlock()))
 		continue;
 	    unsigned apicalls = BBMap[I->getBlock()];
 	    for (DomTreeNode::iterator J=I->begin(),JE=I->end();
 		 J != JE; ++J) {
 		apicalls += BBMap[(*J)->getBlock()];
 	    }
 	    if (apicalls > ApiThreshold) {
 		needsTimeoutCheck.insert(I->getBlock());
 		apicalls = 0;
 	    }
 	    BBMap[I->getBlock()] = apicalls;
 	}
 	if (needsTimeoutCheck.empty())
 	    return false;
 	DEBUG(errs() << "needs timeoutcheck:\n");
59f1b78b
 	std::vector<constType*>args;
99536a17
 	FunctionType* abrtTy = FunctionType::get(
 	    Type::getVoidTy(F.getContext()),args,false);
 	Constant *func_abort =
 	    F.getParent()->getOrInsertFunction("abort", abrtTy);
 	BasicBlock *AbrtBB = BasicBlock::Create(F.getContext(), "", &F);
         CallInst* AbrtC = CallInst::Create(func_abort, "", AbrtBB);
         AbrtC->setCallingConv(CallingConv::C);
         AbrtC->setTailCall(true);
34d8b8cf
 #if LLVM_VERSION < 32
99536a17
         AbrtC->setDoesNotReturn(true);
         AbrtC->setDoesNotThrow(true);
34d8b8cf
 #else
         AbrtC->setDoesNotReturn();
         AbrtC->setDoesNotThrow();
 #endif
99536a17
         new UnreachableInst(F.getContext(), AbrtBB);
 	IRBuilder<false> Builder(F.getContext());
872d0a90
 
 	Value *Flag = F.arg_begin();
9f8df4ae
 #if LLVM_VERSION < 30
99536a17
 	Function *LSBarrier = Intrinsic::getDeclaration(F.getParent(),
 							Intrinsic::memory_barrier);
 	Value *MBArgs[] = {
 	    ConstantInt::getFalse(F.getContext()),
 	    ConstantInt::getFalse(F.getContext()),
 	    ConstantInt::getTrue(F.getContext()),
 	    ConstantInt::getFalse(F.getContext()),
 	    ConstantInt::getFalse(F.getContext())
 	};
872d0a90
 #endif
99536a17
 	verifyFunction(F);
 	BasicBlock *BB = &F.getEntryBlock();
 	Builder.SetInsertPoint(BB, BB->getTerminator());
 	Flag = Builder.CreatePointerCast(Flag, PointerType::getUnqual(
 		Type::getInt1Ty(F.getContext())));
 	for (BBSetTy::iterator I=needsTimeoutCheck.begin(),
 	     E=needsTimeoutCheck.end(); I != E; ++I) {
 	    BasicBlock *BB = *I;
 	    Builder.SetInsertPoint(BB, BB->getTerminator());
9f8df4ae
 #if LLVM_VERSION < 30
99536a17
 	    // store-load barrier: will be a no-op on x86 but not other arches
59f1b78b
 	    Builder.CreateCall(LSBarrier, ARRAYREF(Value*, MBArgs, MBArgs+5));
9f8df4ae
 #else
 	    Builder.CreateFence(Release);
872d0a90
 #endif
99536a17
 	    // Load Flag that tells us we timed out (first byte in bc_ctx)
 	    Value *Cond = Builder.CreateLoad(Flag, true);
 	    BasicBlock *newBB = SplitBlock(BB, BB->getTerminator(), this);
 	    TerminatorInst *TI = BB->getTerminator();
 	    BranchInst::Create(AbrtBB, newBB, Cond, TI);
 	    TI->eraseFromParent();
 	    // Update dominator info
 	    DomTreeNode *N = DT.getNode(AbrtBB);
 	    if (!N) {
 		DT.addNewBlock(AbrtBB, BB);
 	    } else {
 		BasicBlock *DomBB = DT.findNearestCommonDominator(BB,
 								  N->getIDom()->getBlock());
 		DT.changeImmediateDominator(AbrtBB, DomBB);
 	    }
 	    DEBUG(errs() << *I << "\n");
 	}
bdd9aeae
 	//verifyFunction(F);
99536a17
 	return true;
     }
 
     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesAll();
       AU.addRequired<LoopInfo>();
       AU.addRequired<ScalarEvolution>();
4a40b53a
 #if LLVM_VERSION < 35
99536a17
       AU.addRequired<DominatorTree>();
4a40b53a
 #else
       AU.addRequired<DominatorTreeWrapperPass>();
 #endif
99536a17
     }
 };
 char RuntimeLimits::ID;
 
6e52ce67
 // select i1 false ... which instcombine would simplify but we don't run
 // instcombine.
 class BrSimplifier : public FunctionPass {
 public:
     static char ID;
1755adf0
     DEFINEPASS(BrSimplifier) {}
6e52ce67
 
     virtual bool runOnFunction(Function &F) {
 	bool Changed = false;
 	for (Function::iterator I=F.begin(),E=F.end(); I != E; ++I) {
 	    if (BranchInst *BI = dyn_cast<BranchInst>(I->getTerminator())) {
 		if (BI->isUnconditional())
 		    continue;
 		Value *V = BI->getCondition();
 		if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
 		    BasicBlock *Other;
 		    if (CI->isOne()) {
 			BranchInst::Create(BI->getSuccessor(0), &*I);
 			Other = BI->getSuccessor(1);
 		    } else {
 			BranchInst::Create(BI->getSuccessor(1), &*I);
 			Other = BI->getSuccessor(0);
 		    }
 		    Other->removePredecessor(&*I);
 		    BI->eraseFromParent();
 		    Changed = true;
 		}
 	    }
 	    for (BasicBlock::iterator J=I->begin(),JE=I->end();
 		 J != JE;) {
 		SelectInst *SI = dyn_cast<SelectInst>(J);
 		++J;
 		if (!SI)
 		    continue;
 		ConstantInt *CI = dyn_cast<ConstantInt>(SI->getCondition());
 		if (!CI)
 		    continue;
 		if (CI->isOne())
 		    SI->replaceAllUsesWith(SI->getTrueValue());
 		else
 		    SI->replaceAllUsesWith(SI->getFalseValue());
 		SI->eraseFromParent();
 		Changed = true;
 	    }
 	}
 
 	return Changed;
     }
 };
 char BrSimplifier::ID;
 /*
 class SimpleGlobalDCE : public ModulePass {
     ExecutionEngine *EE;
 public:
     static char ID;
     SimpleGlobalDCE(ExecutionEngine *EE) : ModulePass(&ID), EE(EE) {}
 
     virtual bool runOnModule(Module &M) {
 	bool Changed = false;
 	std::vector<GlobalValue*> toErase;
 	for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
 	    GlobalValue *GV = &*I;
 	    if (GV->use_empty() && !EE->getPointerToGlobalIfAvailable(GV))
 		toErase.push_back(GV);
 	}
 	for (std::vector<GlobalValue*>::iterator I=toErase.begin(), E=toErase.end();
 	     I != E; ++I) {
 	    (*I)->eraseFromParent();
 	    Changed = true;
 	}
 
 	return Changed;
     }
 };
 char SimpleGlobalDCE::ID;
 */
e3a54503
 class LLVMCodegen {
e32caecb
 private:
     const struct cli_bc *bc;
     Module *M;
     LLVMContext &Context;
3cd48316
     ExecutionEngine *EE;
6e52ce67
     FunctionPassManager &PM, &PMUnsigned;
e32caecb
     LLVMTypeMapper *TypeMap;
3cd48316
 
e32caecb
     Function **apiFuncs;
9fac78c7
     LLVMTypeMapper &apiMap;
3cd48316
     FunctionMapTy &compiledFunctions;
e32caecb
     Twine BytecodeID;
3cd48316
 
e32caecb
     TargetFolder Folder;
     IRBuilder<false, TargetFolder> Builder;
3cd48316
 
459b13ed
     std::vector<Value*> globals;
3cd48316
     DenseMap<unsigned, unsigned> GVoffsetMap;
59f1b78b
     DenseMap<unsigned, constType*> GVtypeMap;
e32caecb
     Value **Values;
     unsigned numLocals;
     unsigned numArgs;
53bd5bb1
     std::vector<MDNode*> mdnodes;
3b33bd68
 
57bbb2eb
     struct CommonFunctions *CF;
 
59f1b78b
     Value *getOperand(const struct cli_bc_func *func, constType *Ty, operand_t operand)
e6d1fe78
     {
 	unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4};
 	if (operand < func->numValues)
 	    return Values[operand];
09667cdd
 	unsigned w = Ty->getPrimitiveSizeInBits();
 	if (w > 1)
 	    w = (w+7)/8;
 	else
 	    w = 0;
e6d1fe78
 	return convertOperand(func, map[w], operand);
     }
 
59f1b78b
     Value *convertOperand(const struct cli_bc_func *func, constType *Ty, operand_t operand)
ee8f1888
     {
 	unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4};
 	if (operand < func->numArgs)
 	    return Values[operand];
e6d1fe78
 	if (operand < func->numValues) {
 	    Value *V = Values[operand];
a45e2577
 	    if (func->types[operand]&0x8000 && V->getType() == Ty) {
e6d1fe78
 		return V;
a45e2577
 	    }
 	    V = Builder.CreateLoad(V);
688799d1
 	    if (V->getType() != Ty &&
 		isa<PointerType>(V->getType()) &&
 		isa<PointerType>(Ty))
 		V = Builder.CreateBitCast(V, Ty);
322a0ea6
 	    if (V->getType() != Ty) {
29553b8e
 		if (cli_debug_flag) {
 		    std::string str;
 		    raw_string_ostream ostr(str);
 		    ostr << operand << " " ;
 		    V->print(ostr);
 		    Ty->print(ostr);
b6187b63
 		    M->dump();
 		    cli_dbgmsg_internal("[Bytecode JIT]: operand %d: %s\n", operand,ostr.str().c_str());
29553b8e
 		}
322a0ea6
 		llvm_report_error("(libclamav) Type mismatch converting operand");
 	    }
a45e2577
 	    return V;
e6d1fe78
 	}
09667cdd
 	unsigned w = Ty->getPrimitiveSizeInBits();
 	if (w > 1)
 	    w = (w+7)/8;
 	else
 	    w = 0;
ee8f1888
 	return convertOperand(func, map[w], operand);
     }
 
     Value *convertOperand(const struct cli_bc_func *func,
3b33bd68
 			  const struct cli_bc_inst *inst,  operand_t operand)
     {
ee8f1888
 	return convertOperand(func, inst->interp_op%5, operand);
     }
 
     Value *convertOperand(const struct cli_bc_func *func,
 			  unsigned w, operand_t operand) {
 	if (operand < func->numArgs)
 	    return Values[operand];
a45e2577
 	if (operand < func->numValues) {
 	    if (func->types[operand]&0x8000)
 		return Values[operand];
ee8f1888
 	    return Builder.CreateLoad(Values[operand]);
a45e2577
 	}
ee8f1888
 
ec077929
 	if (operand & 0x80000000) {
 	    operand &= 0x7fffffff;
 	    assert(operand < globals.size() && "Global index out of range");
 	    // Global
65c740d7
 	    if (!operand)
 		return ConstantPointerNull::get(PointerType::getUnqual(Type::getInt8Ty(Context)));
124af5e8
 	    assert(globals[operand]);
459b13ed
 	    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(globals[operand])) {
 		if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) {
 		    return CE;
 		}
 		return GV;
7189addb
 	    }
459b13ed
 	    return globals[operand];
ec077929
 	}
ee8f1888
 	// Constant
 	operand -= func->numValues;
 	// This was already validated by libclamav.
6b67ec6e
 	assert(operand < func->numConstants && "Constant out of range");
ee8f1888
 	uint64_t *c = &func->constants[operand];
 	uint64_t v;
59f1b78b
 	constType *Ty;
ee8f1888
 	switch (w) {
 	    case 0:
 	    case 1:
e32caecb
 		Ty = w ? Type::getInt8Ty(Context) :
ee8f1888
 		    Type::getInt1Ty(Context);
 		v = *(uint8_t*)c;
 		break;
 	    case 2:
 		Ty = Type::getInt16Ty(Context);
 		v = *(uint16_t*)c;
 		break;
 	    case 3:
 		Ty = Type::getInt32Ty(Context);
 		v = *(uint32_t*)c;
 		break;
 	    case 4:
 		Ty = Type::getInt64Ty(Context);
 		v = *(uint64_t*)c;
 		break;
3cd48316
 	    default:
 		llvm_unreachable("width");
3b33bd68
 	}
ee8f1888
 	return ConstantInt::get(Ty, v);
     }
 
     void Store(uint16_t dest, Value *V)
     {
 	assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range");
 	Builder.CreateStore(V, Values[dest]);
3b33bd68
     }
6b67ec6e
 
57bbb2eb
     // Insert code that calls \arg CF->FHandler if \arg FailCond is true.
6b67ec6e
     void InsertVerify(Value *FailCond, BasicBlock *&Fail, Function *FHandler, 
 		      Function *F) {
 	if (!Fail) {
 	    Fail = BasicBlock::Create(Context, "fail", F);
 	    CallInst::Create(FHandler,"",Fail);
 	    new UnreachableInst(Context, Fail);
 	}
 	BasicBlock *OkBB = BasicBlock::Create(Context, "", F);
 	Builder.CreateCondBr(FailCond, Fail, OkBB);
 	Builder.SetInsertPoint(OkBB);
     }
e32caecb
 
59f1b78b
     constType* mapType(uint16_t typeID)
e32caecb
     {
59f1b78b
 	return TypeMap->get(typeID&0x7fffffff, NULL, NULL);
e32caecb
     }
ec077929
 
59f1b78b
     Constant *buildConstant(constType *Ty, uint64_t *components, unsigned &c)
ec077929
     {
59f1b78b
         if (constPointerType *PTy = dyn_cast<PointerType>(Ty)) {
236fb136
           Value *idxs[1] = {
 	      ConstantInt::get(Type::getInt64Ty(Context), components[c++])
7189addb
 	  };
459b13ed
 	  unsigned idx = components[c++];
65c740d7
 	  if (!idx)
 	      return ConstantPointerNull::get(PTy);
459b13ed
 	  assert(idx < globals.size());
 	  GlobalVariable *GV = cast<GlobalVariable>(globals[idx]);
59f1b78b
 	  Type *IP8Ty = PointerType::getUnqual(Type::getInt8Ty(Ty->getContext()));
236fb136
 	  Constant *C = ConstantExpr::getPointerCast(GV, IP8Ty);
 	  //TODO: check constant bounds here
7945ff1e
 	  return ConstantExpr::getPointerCast(
59f1b78b
 	      ConstantExpr::getInBoundsGetElementPtr(C, ARRAYREF(Value*, idxs, 1)),
7945ff1e
 	      PTy);
7189addb
         }
ec077929
 	if (isa<IntegerType>(Ty)) {
 	    return ConstantInt::get(Ty, components[c++]);
 	}
59f1b78b
 	if (constArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
ec077929
 	   std::vector<Constant*> elements;
 	   elements.reserve(ATy->getNumElements());
 	   for (unsigned i=0;i<ATy->getNumElements();i++) {
 	       elements.push_back(buildConstant(ATy->getElementType(), components, c));
 	   }
 	   return ConstantArray::get(ATy, elements);
 	}
59f1b78b
 	if (constStructType *STy = dyn_cast<StructType>(Ty)) {
ec077929
 	   std::vector<Constant*> elements;
 	   elements.reserve(STy->getNumElements());
 	   for (unsigned i=0;i<STy->getNumElements();i++) {
 	       elements.push_back(buildConstant(STy->getElementType(i), components, c));
 	   }
 	   return ConstantStruct::get(STy, elements);
 	}
 	Ty->dump();
3cd48316
 	llvm_unreachable("invalid type");
ec077929
 	return 0;
     }
 
3b33bd68
 public:
57bbb2eb
     LLVMCodegen(const struct cli_bc *bc, Module *M, struct CommonFunctions *CF, FunctionMapTy &cFuncs,
6e52ce67
 		ExecutionEngine *EE, FunctionPassManager &PM, FunctionPassManager &PMUnsigned,
9fac78c7
 		Function **apiFuncs, LLVMTypeMapper &apiMap)
3cd48316
 	: bc(bc), M(M), Context(M->getContext()), EE(EE),
3609e2d7
 	PM(PM),PMUnsigned(PMUnsigned), TypeMap(), apiFuncs(apiFuncs),apiMap(apiMap),
3cd48316
 	compiledFunctions(cFuncs), BytecodeID("bc"+Twine(bc->id)),
34d8b8cf
 #if LLVM_VERSION < 32
3609e2d7
 	Folder(EE->getTargetData()), Builder(Context, Folder), Values(), CF(CF) {
34d8b8cf
 #else
 	Folder(EE->getDataLayout()), Builder(Context, Folder), Values(), CF(CF) {
 #endif
3cd48316
 
9fac78c7
 	for (unsigned i=0;i<cli_apicall_maxglobal - _FIRST_GLOBAL;i++) {
80b4b3fb
 	    unsigned id = cli_globals[i].globalid;
 	    GVoffsetMap[id] = cli_globals[i].offset;
 	}
3609e2d7
 	numLocals = 0;
 	numArgs = 0;
80b4b3fb
     }
daffb518
 
9f8df4ae
 #if LLVM_VERSION < 30
a45e2577
     template <typename InputIterator>
59f1b78b
 #endif
     Value* createGEP(Value *Base, constType *ETy, ARRAYREFPARAM(Value*,InputIterator Start,InputIterator End,ARef)) {
 	constType *Ty = GetElementPtrInst::getIndexedType(Base->getType(),ARRAYREFP(Start,End,ARef));
322a0ea6
 	if (!Ty || (ETy && (Ty != ETy && (!isa<IntegerType>(Ty) || !isa<IntegerType>(ETy))))) {
29553b8e
 	    if (cli_debug_flag) {
 		std::string str;
 		raw_string_ostream ostr(str);
 
 		ostr << "Wrong indices for GEP opcode: "
 		    << " expected type: " << *ETy;
 		if (Ty)
 		    ostr << " actual type: " << *Ty;
 		ostr << " base: " << *Base << ";";
 		Base->getType()->print(ostr);
 		ostr << "\n indices: ";
9f8df4ae
 #if LLVM_VERSION < 30
29553b8e
 		for (InputIterator I=Start; I != End; I++) {
9f8df4ae
 #else
 		for (ArrayRef<Value*>::iterator I=ARef.begin(); I != ARef.end(); I++) {
59f1b78b
 #endif
29553b8e
 		    ostr << **I << ", ";
 		}
 		ostr << "\n";
 		cli_dbgmsg_internal("[Bytecode JIT]: %s\n", ostr.str().c_str());
 	    } else {
 		cli_warnmsg("[Bytecode JIT]: Wrong indices for GEP opcode\n");
a45e2577
 	    }
322a0ea6
 	    return 0;
a45e2577
 	}
59f1b78b
 	return Builder.CreateGEP(Base,ARRAYREFP(Start,End,ARef));
322a0ea6
     }
 
9f8df4ae
 #if LLVM_VERSION < 30
322a0ea6
     template <typename InputIterator>
59f1b78b
 #endif
     bool createGEP(unsigned dest, Value *Base, ARRAYREFPARAM(Value*,InputIterator Start,InputIterator End,ARef)) {
322a0ea6
 	assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range");
59f1b78b
 	constType *ETy = cast<PointerType>(cast<PointerType>(Values[dest]->getType())->getElementType())->getElementType();
 	Value *V = createGEP(Base, ETy, ARRAYREFP(Start,End,ARef));
688799d1
 	if (!V) {
29553b8e
 	    if (cli_debug_flag)
 		cli_dbgmsg_internal("[Bytecode JIT] @%d\n", dest);
322a0ea6
 	    return false;
688799d1
 	}
322a0ea6
 	V = Builder.CreateBitCast(V, PointerType::getUnqual(ETy));
a45e2577
 	Store(dest, V);
 	return true;
     }
 
53bd5bb1
     MDNode *convertMDNode(unsigned i) {
 	if (i < mdnodes.size()) {
 	    if (mdnodes[i])
 		return mdnodes[i];
 	} else 
 	    mdnodes.resize(i+1);
 	assert(i < mdnodes.size());
 	const struct cli_bc_dbgnode *node = &bc->dbgnodes[i];
2c859ec7
 #if LLVM_VERSION < 36
53bd5bb1
 	Value **Vals = new Value*[node->numelements];
2c859ec7
 #else
 	Metadata **Vals = new Metadata*[node->numelements];
 #endif
53bd5bb1
 	for (unsigned j=0;j<node->numelements;j++) {
 	    const struct cli_bc_dbgnode_element* el = &node->elements[j];
2c859ec7
 #if LLVM_VERSION < 36
53bd5bb1
 	    Value *V;
2c859ec7
 #else
 	    Metadata *V;
 #endif
53bd5bb1
 	    if (!el->len) {
 		if (el->nodeid == ~0u)
 		    V = 0;
 		else if (el->nodeid)
 		    V = convertMDNode(el->nodeid);
 		else
 		    V = MDString::get(Context, "");
 	    } else if (el->string) {
 		V = MDString::get(Context, StringRef(el->string, el->len));
 	    } else {
2c859ec7
 #if LLVM_VERSION < 36
53bd5bb1
 		V = ConstantInt::get(IntegerType::get(Context, el->len),
 				     el->constant);
2c859ec7
 #else
 		V = ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(Context, el->len),
 				     el->constant));
 #endif
53bd5bb1
 	    }
 	    Vals[j] = V;
 	}
2c859ec7
 #if LLVM_VERSION < 36
59f1b78b
 	MDNode *N = MDNode::get(Context, ARRAYREF(Value*,Vals, node->numelements));
2c859ec7
 #else
 	MDNode *N = MDNode::get(Context, ARRAYREF(Metadata*,Vals, node->numelements));
 #endif
53bd5bb1
 	delete[] Vals;
 	mdnodes[i] = N;
 	return N;
     }
 
9463f9fd
     void AddStackProtect(Function *F)
     {
 	BasicBlock &BB = F->getEntryBlock();
 	if (isa<AllocaInst>(BB.begin())) {
 	    // Have an alloca -> some instruction uses its address otherwise
 	    // mem2reg would have converted it to an SSA register.
 	    // Enable stack protector for this function.
9f8df4ae
 #if LLVM_VERSION < 29
0c79cc55
 	    // LLVM 2.9 has broken SSP, it does a 'mov 0x28, $rax', which tries
 	    // to read from the address 0x28 and crashes
9463f9fd
 	    F->addFnAttr(Attribute::StackProtectReq);
0c79cc55
 #endif
9463f9fd
 	}
f1d071c8
 	// always add stackprotect attribute (bb #2239), so we know this
 	// function was verified. If there is no alloca it won't actually add
 	// stack protector in emitted code so this won't slow down the app.
9f8df4ae
 #if LLVM_VERSION < 29
f1d071c8
 	F->addFnAttr(Attribute::StackProtect);
0c79cc55
 #endif
9463f9fd
     }
 
b2de4fd8
     Value *GEPOperand(Value *V) {
 	if (LoadInst *LI = dyn_cast<LoadInst>(V)) {
 	    Value *VI = LI->getOperand(0);
 	    StoreInst *SI = 0;
 	    for (Value::use_iterator I=VI->use_begin(),
 		 E=VI->use_end(); I != E; ++I) {
1300b002
 		Value *I_V = *I;
 		if (StoreInst *S = dyn_cast<StoreInst>(I_V)) {
b2de4fd8
 		    if (SI)
 			return V;
 		    SI = S;
1300b002
 		} else if (!isa<LoadInst>(I_V))
b2de4fd8
 		    return V;
 	    }
 	    V = SI->getOperand(0);
 	}
34d8b8cf
 #if LLVM_VERSION < 32
b2de4fd8
 	if (EE->getTargetData()->getPointerSize() == 8) {
34d8b8cf
 #else
 	if (EE->getDataLayout()->getPointerSize() == 8) {
 #endif
b2de4fd8
 	    // eliminate useless trunc, GEP can take i64 too
 	    if (TruncInst *I = dyn_cast<TruncInst>(V)) {
 		Value *Src = I->getOperand(0);
 		if (Src->getType() == Type::getInt64Ty(Context) &&
 		    I->getType() == Type::getInt32Ty(Context))
 		    return Src;
 	    }
 	}
 	return V;
     }
 
6e52ce67
    Function* generate() {
         PrettyStackTraceString CrashInfo("Generate LLVM IR functions");
 	apiMap.irgenTimer.startTimer();
e32caecb
 	TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5);
53bd5bb1
 	for (unsigned i=0;i<bc->dbgnode_cnt;i++) {
 	    mdnodes.push_back(convertMDNode(i));
 	}
6b67ec6e
 
9fac78c7
 	for (unsigned i=0;i<cli_apicall_maxglobal - _FIRST_GLOBAL;i++) {
80b4b3fb
 	    unsigned id = cli_globals[i].globalid;
59f1b78b
 	    constType *Ty = apiMap.get(cli_globals[i].type, NULL, NULL);
322a0ea6
 	    /*if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty))
 		Ty = PointerType::getUnqual(ATy->getElementType());*/
646395bb
 	    GVtypeMap[id] = Ty;
80b4b3fb
 	}
a45e2577
 
d0af4afe
 	// The hidden ctx param to all functions
aa745db7
 	unsigned maxh = cli_globals[0].offset + sizeof(struct cli_bc_hooks);
59f1b78b
 	constType *HiddenCtx = PointerType::getUnqual(ArrayType::get(Type::getInt8Ty(Context), maxh));
d0af4afe
 
ec077929
 	globals.reserve(bc->num_globals);
459b13ed
 	BitVector FakeGVs;
284ffd21
 	FakeGVs.resize(bc->num_globals);
65c740d7
 	globals.push_back(0);
284ffd21
 	for (unsigned i=1;i<bc->num_globals;i++) {
59f1b78b
 	    constType *Ty = mapType(bc->globaltys[i]);
1d1dd80f
 
ec077929
 	    // TODO: validate number of components against type_components
 	    unsigned c = 0;
459b13ed
 	    GlobalVariable *GV;
 	    if (isa<PointerType>(Ty)) {
80b4b3fb
 		unsigned g = bc->globals[i][1];
 		if (GVoffsetMap.count(g)) {
284ffd21
 		    FakeGVs.set(i);
459b13ed
 		    globals.push_back(0);
 		    continue;
 		}
 	    }
1d1dd80f
 	    Constant *C = buildConstant(Ty, bc->globals[i], c);
459b13ed
 	    GV = new GlobalVariable(*M, Ty, true,
 				    GlobalValue::InternalLinkage,
 				    C, "glob"+Twine(i));
ec077929
 	    globals.push_back(GV);
 	}
ee8f1888
 	Function **Functions = new Function*[bc->num_func];
daffb518
 	for (unsigned j=0;j<bc->num_func;j++) {
3b33bd68
 	    // Create LLVM IR Function
daffb518
 	    const struct cli_bc_func *func = &bc->funcs[j];
59f1b78b
 	    std::vector<constType*> argTypes;
d0af4afe
 	    argTypes.push_back(HiddenCtx);
daffb518
 	    for (unsigned a=0;a<func->numArgs;a++) {
3b33bd68
 		argTypes.push_back(mapType(func->types[a]));
 	    }
59f1b78b
 	    constType *RetTy = mapType(func->returnType);
c466339d
 	    FunctionType *FTy =  FunctionType::get(RetTy, argTypes,
3b33bd68
 							 false);
d0af4afe
 	    Functions[j] = Function::Create(FTy, Function::InternalLinkage,
3b33bd68
 					   BytecodeID+"f"+Twine(j), M);
6b67ec6e
 	    Functions[j]->setDoesNotThrow();
d0af4afe
 	    Functions[j]->setCallingConv(CallingConv::Fast);
6e52ce67
 	    Functions[j]->setLinkage(GlobalValue::InternalLinkage);
3eef86ee
 #ifdef C_LINUX
 	    /* bb #2270, this should really be fixed either by LLVM or GCC.*/
34d8b8cf
 #if LLVM_VERSION < 32
3eef86ee
 	    Functions[j]->addFnAttr(Attribute::constructStackAlignmentFromInt(16));
34d8b8cf
 #else
 	// TODO: How does this translate?
 //	    Functions[j]->addFnAttr(Attribute::StackAlignment);
 #endif
3eef86ee
 #endif
ee8f1888
 	}
59f1b78b
 	constType *I32Ty = Type::getInt32Ty(Context);
ee8f1888
 	for (unsigned j=0;j<bc->num_func;j++) {
 	    PrettyStackTraceString CrashInfo("Generate LLVM IR");
 	    const struct cli_bc_func *func = &bc->funcs[j];
9e1f0d90
 	    bool broken = false;
e32caecb
 
3b33bd68
 	    // Create all BasicBlocks
ee8f1888
 	    Function *F = Functions[j];
3b33bd68
 	    BasicBlock **BB = new BasicBlock*[func->numBB];
 	    for (unsigned i=0;i<func->numBB;i++) {
 		BB[i] = BasicBlock::Create(Context, "", F);
daffb518
 	    }
3b33bd68
 
6b67ec6e
 	    BasicBlock *Fail = 0;
ee8f1888
 	    Values = new Value*[func->numValues];
 	    Builder.SetInsertPoint(BB[0]);
 	    Function::arg_iterator I = F->arg_begin();
3cd48316
 	    assert(F->arg_size() == (unsigned)(func->numArgs + 1) && "Mismatched args");
d0af4afe
 	    ++I;
ee8f1888
 	    for (unsigned i=0;i<func->numArgs; i++) {
 		assert(I != F->arg_end());
 		Values[i] = &*I;
 		++I;
 	    }
 	    for (unsigned i=func->numArgs;i<func->numValues;i++) {
479fa713
 		if (!func->types[i]) {
 		    //instructions without return value, like store
 		    Values[i] = 0;
 		    continue;
 		}
ee8f1888
 		Values[i] = Builder.CreateAlloca(mapType(func->types[i]));
 	    }
 	    numLocals = func->numLocals;
 	    numArgs = func->numArgs;
459b13ed
 
 	    if (FakeGVs.any()) {
 		Argument *Ctx = F->arg_begin();
 		for (unsigned i=0;i<bc->num_globals;i++) {
284ffd21
 		    if (!FakeGVs[i])
459b13ed
 			continue;
80b4b3fb
 		    unsigned g = bc->globals[i][1];
 		    unsigned offset = GVoffsetMap[g];
aa745db7
 
80b4b3fb
 		    Constant *Idx = ConstantInt::get(Type::getInt32Ty(Context),
 						     offset);
aa745db7
 		    Value *Idxs[2] = {
 			ConstantInt::get(Type::getInt32Ty(Context), 0),
 			Idx
 		    };
59f1b78b
 		    Value *GEP = Builder.CreateInBoundsGEP(Ctx, ARRAYREF(Value*, Idxs, Idxs+2));
 		    constType *Ty = GVtypeMap[g];
a45e2577
 		    Ty = PointerType::getUnqual(PointerType::getUnqual(Ty));
 		    Value *Cast = Builder.CreateBitCast(GEP, Ty);
80b4b3fb
 		    Value *SpecialGV = Builder.CreateLoad(Cast);
59f1b78b
 		    constType *IP8Ty = Type::getInt8Ty(Context);
236fb136
 		    IP8Ty = PointerType::getUnqual(IP8Ty);
 		    SpecialGV = Builder.CreateBitCast(SpecialGV, IP8Ty);
688799d1
 		    SpecialGV->setName("g"+Twine(g-_FIRST_GLOBAL)+"_");
a45e2577
 		    Value *C[] = {
 			ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0])
 		    };
59f1b78b
 		    globals[i] = createGEP(SpecialGV, 0, ARRAYREF(Value*,C, C+1));
322a0ea6
 		    if (!globals[i]) {
29553b8e
 			if (cli_debug_flag) {
 			    std::string str;
 			    raw_string_ostream ostr(str);
 			    ostr << i << ":" << g << ":" << bc->globals[i][0] <<"\n";
 			    Ty->print(ostr);
 			    cli_dbgmsg_internal("[Bytecode JIT]: %s\n", ostr.str().c_str());
 			}
322a0ea6
 			llvm_report_error("(libclamav) unable to create fake global");
 		    }
236fb136
 		    globals[i] = Builder.CreateBitCast(globals[i], Ty);
 		    if(GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(globals[i])) {
322a0ea6
 			GI->setIsInBounds(true);
688799d1
 			GI->setName("geped"+Twine(i)+"_");
 		    }
459b13ed
 		}
 	    }
 
3b33bd68
 	    // Generate LLVM IR for each BB
9e1f0d90
 	    for (unsigned i=0;i<func->numBB && !broken;i++) {
a45e2577
 		bool unreachable = false;
3b33bd68
 		const struct cli_bc_bb *bb = &func->BB[i];
 		Builder.SetInsertPoint(BB[i]);
53bd5bb1
 		unsigned c = 0;
9e1f0d90
 		for (unsigned j=0;j<bb->numInsts && !broken;j++) {
ee8f1888
 		    const struct cli_bc_inst *inst = &bb->insts[j];
a7b7a648
 		    Value *Op0=0, *Op1=0, *Op2=0;
ee8f1888
 		    // libclamav has already validated this.
52dd3a6b
 		    assert(inst->opcode < OP_BC_INVALID && "Invalid opcode");
53bd5bb1
 		    if (func->dbgnodes) {
 			if (func->dbgnodes[c] != ~0u) {
 			unsigned j = func->dbgnodes[c];
 			assert(j < mdnodes.size());
 			Builder.SetCurrentDebugLocation(mdnodes[j]);
 			} else
 			    Builder.SetCurrentDebugLocation(0);
 		    }
 		    c++;
ee8f1888
 		    switch (inst->opcode) {
52dd3a6b
 			case OP_BC_JMP:
 			case OP_BC_BRANCH:
 			case OP_BC_CALL_API:
 			case OP_BC_CALL_DIRECT:
 			case OP_BC_ZEXT:
 			case OP_BC_SEXT:
 			case OP_BC_TRUNC:
 			case OP_BC_GEP1:
9463f9fd
 			case OP_BC_GEPZ:
52dd3a6b
 			case OP_BC_GEPN:
 			case OP_BC_STORE:
 			case OP_BC_COPY:
a45e2577
 			case OP_BC_RET:
1e30496d
 			case OP_BC_PTRDIFF32:
44e13431
 			case OP_BC_PTRTOINT64:
ee8f1888
 			    // these instructions represents operands differently
 			    break;
 			default:
 			    switch (operand_counts[inst->opcode]) {
 				case 1:
 				    Op0 = convertOperand(func, inst, inst->u.unaryop);
 				    break;
 				case 2:
 				    Op0 = convertOperand(func, inst, inst->u.binop[0]);
 				    Op1 = convertOperand(func, inst, inst->u.binop[1]);
322a0ea6
 				    if (Op0->getType() != Op1->getType()) {
 					Op0->dump();
 					Op1->dump();
 					llvm_report_error("(libclamav) binop type mismatch");
 				    }
ee8f1888
 				    break;
 				case 3:
 				    Op0 = convertOperand(func, inst, inst->u.three[0]);
 				    Op1 = convertOperand(func, inst, inst->u.three[1]);
 				    Op2 = convertOperand(func, inst, inst->u.three[2]);
 				    break;
 			    }
 		    }
3b33bd68
 
 		    switch (inst->opcode) {
52dd3a6b
 			case OP_BC_ADD:
ee8f1888
 			    Store(inst->dest, Builder.CreateAdd(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_SUB:
ee8f1888
 			    Store(inst->dest, Builder.CreateSub(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_MUL:
ee8f1888
 			    Store(inst->dest, Builder.CreateMul(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_UDIV:
6b67ec6e
 			{
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
57bbb2eb
 			    InsertVerify(Bad, Fail, CF->FHandler, F);
ee8f1888
 			    Store(inst->dest, Builder.CreateUDiv(Op0, Op1));
 			    break;
6b67ec6e
 			}
52dd3a6b
 			case OP_BC_SDIV:
6b67ec6e
 			{
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
57bbb2eb
 			    InsertVerify(Bad, Fail, CF->FHandler, F);
ee8f1888
 			    Store(inst->dest, Builder.CreateSDiv(Op0, Op1));
 			    break;
6b67ec6e
 			}
52dd3a6b
 			case OP_BC_UREM:
6b67ec6e
 			{
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
57bbb2eb
 			    InsertVerify(Bad, Fail, CF->FHandler, F);
ee8f1888
 			    Store(inst->dest, Builder.CreateURem(Op0, Op1));
 			    break;
6b67ec6e
 			}
52dd3a6b
 			case OP_BC_SREM:
6b67ec6e
 			{
 			    //TODO: also verify Op0 == -1 && Op1 = INT_MIN
 			    Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
57bbb2eb
 			    InsertVerify(Bad, Fail, CF->FHandler, F);
ee8f1888
 			    Store(inst->dest, Builder.CreateSRem(Op0, Op1));
 			    break;
6b67ec6e
 			}
52dd3a6b
 			case OP_BC_SHL:
ee8f1888
 			    Store(inst->dest, Builder.CreateShl(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_LSHR:
ee8f1888
 			    Store(inst->dest, Builder.CreateLShr(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_ASHR:
ee8f1888
 			    Store(inst->dest, Builder.CreateAShr(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_AND:
ee8f1888
 			    Store(inst->dest, Builder.CreateAnd(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_OR:
ee8f1888
 			    Store(inst->dest, Builder.CreateOr(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_XOR:
ee8f1888
 			    Store(inst->dest, Builder.CreateXor(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_TRUNC:
ee8f1888
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
59f1b78b
 			    constType *Ty = mapType(func->types[inst->dest]);
ee8f1888
 			    Store(inst->dest, Builder.CreateTrunc(Src,  Ty));
 			    break;
 			}
52dd3a6b
 			case OP_BC_ZEXT:
ee8f1888
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
59f1b78b
 			    constType *Ty = mapType(func->types[inst->dest]);
ee8f1888
 			    Store(inst->dest, Builder.CreateZExt(Src,  Ty));
 			    break;
 			}
52dd3a6b
 			case OP_BC_SEXT:
ee8f1888
 			{
 			    Value *Src = convertOperand(func, inst, inst->u.cast.source);
59f1b78b
 			    constType *Ty = mapType(func->types[inst->dest]);
ee8f1888
 			    Store(inst->dest, Builder.CreateSExt(Src,  Ty));
 			    break;
 			}
52dd3a6b
 			case OP_BC_BRANCH:
ee8f1888
 			{
 			    Value *Cond = convertOperand(func, inst, inst->u.branch.condition);
 			    BasicBlock *True = BB[inst->u.branch.br_true];
 			    BasicBlock *False = BB[inst->u.branch.br_false];
 			    if (Cond->getType() != Type::getInt1Ty(Context)) {
29553b8e
 				cli_warnmsg("[Bytecode JIT]: type mismatch in condition");
9e1f0d90
 				broken = true;
 				break;
ee8f1888
 			    }
 			    Builder.CreateCondBr(Cond, True, False);
 			    break;
 			}
52dd3a6b
 			case OP_BC_JMP:
ee8f1888
 			{
 			    BasicBlock *Jmp = BB[inst->u.jump];
 			    Builder.CreateBr(Jmp);
 			    break;
 			}
52dd3a6b
 			case OP_BC_RET:
a45e2577
 			{
 			    Op0 = convertOperand(func, F->getReturnType(), inst->u.unaryop);
ee8f1888
 			    Builder.CreateRet(Op0);
 			    break;
a45e2577
 			}
d38d6dad
 			case OP_BC_RET_VOID:
 			    Builder.CreateRetVoid();
 			    break;
52dd3a6b
 			case OP_BC_ICMP_EQ:
ee8f1888
 			    Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_ICMP_NE:
ee8f1888
 			    Store(inst->dest, Builder.CreateICmpNE(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_ICMP_UGT:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpUGT(Op0, Op1));
ee8f1888
 			    break;
52dd3a6b
 			case OP_BC_ICMP_UGE:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpUGE(Op0, Op1));
3b33bd68
 			    break;
52dd3a6b
 			case OP_BC_ICMP_ULT:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpULT(Op0, Op1));
ee8f1888
 			    break;
52dd3a6b
 			case OP_BC_ICMP_ULE:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpULE(Op0, Op1));
ee8f1888
 			    break;
52dd3a6b
 			case OP_BC_ICMP_SGT:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpSGT(Op0, Op1));
ee8f1888
 			    break;
52dd3a6b
 			case OP_BC_ICMP_SGE:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpSGE(Op0, Op1));
ee8f1888
 			    break;
52dd3a6b
 			case OP_BC_ICMP_SLT:
6b67ec6e
 			    Store(inst->dest, Builder.CreateICmpSLT(Op0, Op1));
ee8f1888
 			    break;
b331b610
 			case OP_BC_ICMP_SLE:
 			    Store(inst->dest, Builder.CreateICmpSLE(Op0, Op1));
 			    break;
52dd3a6b
 			case OP_BC_SELECT:
ee8f1888
 			    Store(inst->dest, Builder.CreateSelect(Op0, Op1, Op2));
 			    break;
52dd3a6b
 			case OP_BC_COPY:
a1781898
 			{
 			    Value *Dest = Values[inst->u.binop[1]];
59f1b78b
 			    constPointerType *PTy = cast<PointerType>(Dest->getType());
a1781898
 			    Op0 = convertOperand(func, PTy->getElementType(), inst->u.binop[0]);
fa0a9143
 			    PTy = PointerType::getUnqual(Op0->getType());
 			    Dest = Builder.CreateBitCast(Dest, PTy);
a1781898
 			    Builder.CreateStore(Op0, Dest);
ee8f1888
 			    break;
a1781898
 			}
52dd3a6b
 			case OP_BC_CALL_DIRECT:
ee8f1888
 			{
 			    Function *DestF = Functions[inst->u.ops.funcid];
 			    SmallVector<Value*, 2> args;
d0af4afe
 			    args.push_back(&*F->arg_begin()); // pass hidden arg
ee8f1888
 			    for (unsigned a=0;a<inst->u.ops.numOps;a++) {
 				operand_t op = inst->u.ops.ops[a];
d0af4afe
 				args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op));
ee8f1888
 			    }
59f1b78b
 			    CallInst *CI = Builder.CreateCall(DestF, ARRAYREF(Value*, args.begin(), args.end()));
d0af4afe
 			    CI->setCallingConv(CallingConv::Fast);
34d8b8cf
 #if LLVM_VERSION < 32
b2de4fd8
 			    CI->setDoesNotThrow(true);
34d8b8cf
 #else
 			    CI->setDoesNotThrow();
 #endif
d38d6dad
 			    if (CI->getType()->getTypeID() != Type::VoidTyID)
 				Store(inst->dest, CI);
ee8f1888
 			    break;
 			}
52dd3a6b
 			case OP_BC_CALL_API:
e32caecb
 			{
 			    assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range");
 			    std::vector<Value*> args;
 			    Function *DestF = apiFuncs[inst->u.ops.funcid];
ab402e6a
 			    if (!strcmp(cli_apicalls[inst->u.ops.funcid].name, "engine_functionality_level")) {
 				Store(inst->dest,
 				      ConstantInt::get(Type::getInt32Ty(Context),
 						       cl_retflevel()));
 			    } else {
d0af4afe
 			    args.push_back(&*F->arg_begin()); // pass hidden arg
e32caecb
 			    for (unsigned a=0;a<inst->u.ops.numOps;a++) {
 				operand_t op = inst->u.ops.ops[a];
d0af4afe
 				args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op));
e32caecb
 			    }
59f1b78b
 			    CallInst *CI = Builder.CreateCall(DestF, ARRAYREFVECTOR(Value*, args));
34d8b8cf
 #if LLVM_VERSION < 32
b2de4fd8
 			    CI->setDoesNotThrow(true);
34d8b8cf
 #else
 			    CI->setDoesNotThrow();
 #endif
b2de4fd8
 			    Store(inst->dest, CI);
ab402e6a
 			    }
e32caecb
 			    break;
 			}
52dd3a6b
 			case OP_BC_GEP1:
e6d1fe78
 			{
59f1b78b
 			    constType *SrcTy = mapType(inst->u.three[0]);
688799d1
 			    Value *V = convertOperand(func, SrcTy, inst->u.three[1]);
1e30496d
 			    Value *Op = convertOperand(func, I32Ty, inst->u.three[2]);
b2de4fd8
 			    Op = GEPOperand(Op);
3aca6c4a
 			    if (!createGEP(inst->dest, V, ARRAYREF(Value*, &Op, &Op+1))) {
9e1f0d90
 				cli_warnmsg("[Bytecode JIT]: OP_BC_GEP1 createGEP failed\n");
 				broken = true;
3aca6c4a
 			    }
e6d1fe78
 			    break;
 			}
9463f9fd
 			case OP_BC_GEPZ:
 			{
 			    Value *Ops[2];
 			    Ops[0] = ConstantInt::get(Type::getInt32Ty(Context), 0);
59f1b78b
 			    constType *SrcTy = mapType(inst->u.three[0]);
9463f9fd
 			    Value *V = convertOperand(func, SrcTy, inst->u.three[1]);
1e30496d
 			    Ops[1] = convertOperand(func, I32Ty, inst->u.three[2]);
b2de4fd8
 			    Ops[1] = GEPOperand(Ops[1]);
3aca6c4a
 			    if (!createGEP(inst->dest, V, ARRAYREF(Value*, Ops, Ops+2))) {
9e1f0d90
 				cli_warnmsg("[Bytecode JIT]: OP_BC_GEPZ createGEP failed\n");
 				broken = true;
3aca6c4a
 			    }
9463f9fd
 			    break;
 			}
52dd3a6b
 			case OP_BC_GEPN:
e6d1fe78
 			{
 			    std::vector<Value*> Idxs;
688799d1
 			    assert(inst->u.ops.numOps > 2);
59f1b78b
 			    constType *SrcTy = mapType(inst->u.ops.ops[0]);
688799d1
 			    Value *V = convertOperand(func, SrcTy, inst->u.ops.ops[1]);
236fb136
 			    for (unsigned a=2;a<inst->u.ops.numOps;a++) {
1e30496d
 				Value *Op = convertOperand(func, I32Ty, inst->u.ops.ops[a]);
b2de4fd8
 				Op = GEPOperand(Op);
236fb136
 				Idxs.push_back(Op);
 			    }
3aca6c4a
 			    if (!createGEP(inst->dest, V, ARRAYREFVECTOR(Value*, Idxs))) {
9e1f0d90
 				cli_warnmsg("[Bytecode JIT]: OP_BC_GEPN createGEP failed\n");
 				broken = true;
3aca6c4a
 			    }
e6d1fe78
 			    break;
 			}
52dd3a6b
 			case OP_BC_STORE:
e6d1fe78
 			{
 			    Value *Dest = convertOperand(func, inst, inst->u.binop[1]);
322a0ea6
 			    Value *V = convertOperand(func, inst, inst->u.binop[0]);
59f1b78b
 			    constType *VPTy = PointerType::getUnqual(V->getType());
322a0ea6
 			    if (VPTy != Dest->getType())
 				Dest = Builder.CreateBitCast(Dest, VPTy);
 			    Builder.CreateStore(V, Dest);
e6d1fe78
 			    break;
 			}
52dd3a6b
 			case OP_BC_LOAD:
a45e2577
 			{
 			    Op0 = Builder.CreateBitCast(Op0,
 							Values[inst->dest]->getType());
a1781898
 			    Op0 = Builder.CreateLoad(Op0);
e6d1fe78
 			    Store(inst->dest, Op0);
 			    break;
a45e2577
 			}
 			case OP_BC_MEMSET:
 			{
 			    Value *Dst = convertOperand(func, inst, inst->u.three[0]);
6ea339ae
 			    Dst = Builder.CreatePointerCast(Dst, PointerType::getUnqual(Type::getInt8Ty(Context)));
a45e2577
 			    Value *Val = convertOperand(func, Type::getInt8Ty(Context), inst->u.three[1]);
99aeada8
 			    Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
deafd8fa
 #if LLVM_VERSION < 29
9f8df4ae
 			    CallInst *c = Builder.CreateCall4(CF->FMemset, Dst, Val, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1));
 #else
59f1b78b
 			    CallInst *c = Builder.CreateCall5(CF->FMemset, Dst, Val, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1),
 								ConstantInt::get(Type::getInt1Ty(Context), 0)
 								);
 #endif
a45e2577
 			    c->setTailCall(true);
 			    c->setDoesNotThrow();
744c40d1
 			    UpgradeCall(c, CF->FMemset);
a45e2577
 			    break;
 			}
 			case OP_BC_MEMCPY:
 			{
 			    Value *Dst = convertOperand(func, inst, inst->u.three[0]);
6ea339ae
 			    Dst = Builder.CreatePointerCast(Dst, PointerType::getUnqual(Type::getInt8Ty(Context)));
a45e2577
 			    Value *Src = convertOperand(func, inst, inst->u.three[1]);
6ea339ae
 			    Src = Builder.CreatePointerCast(Src, PointerType::getUnqual(Type::getInt8Ty(Context)));
99aeada8
 			    Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
deafd8fa
 #if LLVM_VERSION < 29
9f8df4ae
 			    CallInst *c = Builder.CreateCall4(CF->FMemcpy, Dst, Src, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1));
 #else
59f1b78b
 			    CallInst *c = Builder.CreateCall5(CF->FMemcpy, Dst, Src, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1),
 								ConstantInt::get(Type::getInt1Ty(Context), 0)
 								);
 #endif
a45e2577
 			    c->setTailCall(true);
 			    c->setDoesNotThrow();
744c40d1
 			    UpgradeCall(c, CF->FMemcpy);
a45e2577
 			    break;
 			}
 			case OP_BC_MEMMOVE:
 			{
 			    Value *Dst = convertOperand(func, inst, inst->u.three[0]);
6ea339ae
 			    Dst = Builder.CreatePointerCast(Dst, PointerType::getUnqual(Type::getInt8Ty(Context)));
a45e2577
 			    Value *Src = convertOperand(func, inst, inst->u.three[1]);
b0a5ddb3
 			    Src = Builder.CreatePointerCast(Src, PointerType::getUnqual(Type::getInt8Ty(Context)));
99aeada8
 			    Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
deafd8fa
 #if LLVM_VERSION < 29
9f8df4ae
 			    CallInst *c = Builder.CreateCall4(CF->FMemmove, Dst, Src, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1));
 #else
59f1b78b
 			    CallInst *c = Builder.CreateCall5(CF->FMemmove, Dst, Src, Len,
 								ConstantInt::get(Type::getInt32Ty(Context), 1),
 								ConstantInt::get(Type::getInt1Ty(Context), 0));
 #endif
a45e2577
 			    c->setTailCall(true);
 			    c->setDoesNotThrow();
744c40d1
 			    UpgradeCall(c, CF->FMemmove);
a45e2577
 			    break;
 			}
 			case OP_BC_MEMCMP:
 			{
 			    Value *Dst = convertOperand(func, inst, inst->u.three[0]);
6ea339ae
 			    Dst = Builder.CreatePointerCast(Dst, PointerType::getUnqual(Type::getInt8Ty(Context)));
a45e2577
 			    Value *Src = convertOperand(func, inst, inst->u.three[1]);
b0a5ddb3
 			    Src = Builder.CreatePointerCast(Src, PointerType::getUnqual(Type::getInt8Ty(Context)));
34d8b8cf
 #if LLVM_VERSION < 32
a45e2577
 			    Value *Len = convertOperand(func, EE->getTargetData()->getIntPtrType(Context), inst->u.three[2]);
34d8b8cf
 #else
 			    Value *Len = convertOperand(func, EE->getDataLayout()->getIntPtrType(Context), inst->u.three[2]);
 #endif
57bbb2eb
 			    CallInst *c = Builder.CreateCall3(CF->FRealmemcmp, Dst, Src, Len);
a45e2577
 			    c->setTailCall(true);
 			    c->setDoesNotThrow();
 			    Store(inst->dest, c);
 			    break;
 			}
 			case OP_BC_ISBIGENDIAN:
 			    Store(inst->dest, WORDS_BIGENDIAN ?
 				  ConstantInt::getTrue(Context) :
 				  ConstantInt::getFalse(Context));
 			    break;
 			case OP_BC_ABORT:
 			    if (!unreachable) {
57bbb2eb
 				CallInst *CI = Builder.CreateCall(CF->FHandler);
a45e2577
 				CI->setDoesNotReturn();
 				CI->setDoesNotThrow();
 				Builder.CreateUnreachable();
 				unreachable = true;
 			    }
 			    break;
8997b147
 			case OP_BC_BSWAP16:
 			    {
57bbb2eb
 				CallInst *C = Builder.CreateCall(CF->FBSwap16, convertOperand(func, inst, inst->u.unaryop));
8997b147
 				C->setTailCall(true);
34d8b8cf
 #if LLVM_VERSION < 32
8997b147
 				C->setDoesNotThrow(true);
34d8b8cf
 #else
 				C->setDoesNotThrow();
 #endif
8997b147
 				Store(inst->dest, C);
 				break;
 			    }
 			case OP_BC_BSWAP32:
 			    {
57bbb2eb
 				CallInst *C = Builder.CreateCall(CF->FBSwap32, convertOperand(func, inst, inst->u.unaryop));
8997b147
 				C->setTailCall(true);
34d8b8cf
 #if LLVM_VERSION < 32
8997b147
 				C->setDoesNotThrow(true);
34d8b8cf
 #else
 				C->setDoesNotThrow();
 #endif
8997b147
 				Store(inst->dest, C);
 				break;
 			    }
 			case OP_BC_BSWAP64:
 			    {
57bbb2eb
 				CallInst *C = Builder.CreateCall(CF->FBSwap64, convertOperand(func, inst, inst->u.unaryop));
8997b147
 				C->setTailCall(true);
34d8b8cf
 #if LLVM_VERSION < 32
8997b147
 				C->setDoesNotThrow(true);
34d8b8cf
 #else
 				C->setDoesNotThrow();
 #endif
8997b147
 				Store(inst->dest, C);
 				break;
 			    }
4395bb9a
 			case OP_BC_PTRDIFF32:
 			    {
 				Value *P1 = convertOperand(func, inst, inst->u.binop[0]);
 				Value *P2 = convertOperand(func, inst, inst->u.binop[1]);
 				P1 = Builder.CreatePtrToInt(P1, Type::getInt64Ty(Context));
 				P2 = Builder.CreatePtrToInt(P2, Type::getInt64Ty(Context));
 				Value *R = Builder.CreateSub(P1, P2);
 				R = Builder.CreateTrunc(R, Type::getInt32Ty(Context));
 				Store(inst->dest, R);
 				break;
 			    }
44e13431
 			case OP_BC_PTRTOINT64:
 			    {
 				Value *P1 = convertOperand(func, inst, inst->u.unaryop);
 				P1 = Builder.CreatePtrToInt(P1, Type::getInt64Ty(Context));
 				Store(inst->dest, P1);
 				break;
 			    }
ee8f1888
 			default:
29553b8e
 			    cli_warnmsg("[Bytecode JIT]: JIT doesn't implement opcode %d yet!\n",
 					inst->opcode);
9e1f0d90
 			    broken = true;
 			    break;
3b33bd68
 		    }
 		}
 	    }
 
9e1f0d90
 	    // If successful so far, run verifyFunction
 	    if (!broken) {
4a40b53a
 #if LLVM_VERSION < 35
9e1f0d90
 		if (verifyFunction(*F, PrintMessageAction)) {
4a40b53a
 #else
 		if (verifyFunction(*F, &errs())) {
 #endif
9e1f0d90
 		    // verification failed
 		    broken = true;
 		    cli_warnmsg("[Bytecode JIT]: Verification failed\n");
 		    if (cli_debug_flag) {
 			std::string str;
 			raw_string_ostream ostr(str);
 			F->print(ostr);
 			cli_dbgmsg_internal("[Bytecode JIT]: %s\n", ostr.str().c_str());
 		    }
29553b8e
 		}
9e1f0d90
 	    }
 
 	    delete [] Values;
 
 	    // Cleanup after failure and return 0
 	    if (broken) {
3aca6c4a
 		for (unsigned z=0; z < func->numBB ; z++) {
 		    delete BB[z];
 		}
 		delete [] BB;
 		apiMap.irgenTimer.stopTimer();
 		delete TypeMap;
 		for (unsigned z=0; z < bc->num_func; z++) {
 		    delete Functions[z];
 		}
 		delete [] Functions;
6e52ce67
 		return 0;
ee8f1888
 	    }
9e1f0d90
 
6b67ec6e
 	    delete [] BB;
6e52ce67
 	    apiMap.irgenTimer.stopTimer();
 	    apiMap.pmTimer.startTimer();
 	    if (bc->trusted) {
 		PM.doInitialization();
 		PM.run(*F);
 		PM.doFinalization();
 	    }
 	    else {
 		PMUnsigned.doInitialization();
 		PMUnsigned.run(*F);
 		PMUnsigned.doFinalization();
 	    }
 	    apiMap.pmTimer.stopTimer();
 	    apiMap.irgenTimer.startTimer();
ee8f1888
 	}
556eaf04
 
 	for (unsigned j=0;j<bc->num_func;j++) {
 	    Function *F = Functions[j];
 	    AddStackProtect(F);
 	}
e32caecb
 	delete TypeMap;
59f1b78b
 	std::vector<constType*> args;
a45e2577
 	args.clear();
aa745db7
 	args.push_back(HiddenCtx);
d0af4afe
 	FunctionType *Callable = FunctionType::get(Type::getInt32Ty(Context),
 						   args, false);
6b67ec6e
 
6e52ce67
 	// If prototype matches, add to callable functions
 	if (Functions[0]->getFunctionType() != Callable) {
29553b8e
 	    cli_warnmsg("[Bytecode JIT]: Wrong prototype for function 0 in bytecode %d\n",  bc->id);
3aca6c4a
 	    apiMap.irgenTimer.stopTimer();
 	    for (unsigned z=0; z < bc->num_func; z++) {
 		delete Functions[z];
 	    }
 	    delete [] Functions;
6e52ce67
 	    return 0;
 	}
 	// All functions have the Fast calling convention, however
 	// entrypoint can only be C, emit wrapper
 	Function *F = Function::Create(Functions[0]->getFunctionType(),
 				       Function::ExternalLinkage,
34d8b8cf
 #if LLVM_VERSION < 33
6e52ce67
 				       Functions[0]->getName()+"_wrap", M);
34d8b8cf
 #else
 				       Functions[0]->getName().str()+"_wrap", M);
 #endif
6e52ce67
 	F->setDoesNotThrow();
 	BasicBlock *BB = BasicBlock::Create(Context, "", F);
 	std::vector<Value*> Args;
 	for (Function::arg_iterator J=F->arg_begin(),
 	     JE=F->arg_end(); J != JE; ++JE) {
 	    Args.push_back(&*J);
 	}
59f1b78b
 	CallInst *CI = CallInst::Create(Functions[0], ARRAYREFVECTOR(Value*, Args), "", BB);
6e52ce67
 	CI->setCallingConv(CallingConv::Fast);
 	ReturnInst::Create(Context, CI, BB);
d0af4afe
 
6e52ce67
 	delete [] Functions;
4a40b53a
 #if LLVM_VERSION < 35
6e52ce67
 	if (verifyFunction(*F, PrintMessageAction))
4a40b53a
 #else
 	if (verifyFunction(*F, &errs()))
 #endif
6e52ce67
 	    return 0;
 
 /*			DEBUG(errs() << "Generating code\n");
853b6e5d
 			// Codegen current function as executable machine code.
f121d43d
 			EE->getPointerToFunction(Functions[j]);
853b6e5d
 			void *code = EE->getPointerToFunction(F);
6e52ce67
 			DEBUG(errs() << "Code generation finished\n");*/
d0af4afe
 
6e52ce67
 //		compiledFunctions[func] = code;
 	apiMap.irgenTimer.stopTimer();
 	return F;
daffb518
     }
3b33bd68
 };
ee6ab4f8
 
 static sys::Mutex llvm_api_lock;
 
 // This class automatically acquires the lock when instantiated,
 // and releases the lock when leaving scope.
 class LLVMApiScopedLock {
     public:
 	// when multithreaded mode is false (no atomics available),
 	// we need to wrap all LLVM API calls with a giant mutex lock, but
 	// only then.
 	LLVMApiScopedLock() {
a7cf187a
 	    // It is safer to just run all codegen under the mutex,
 	    // it is not like we are going to codegen from multiple threads
 	    // at a time anyway.
 //	    if (!llvm_is_multithreaded())
2c859ec7
 #if LLVM_VERSION < 36
ee6ab4f8
 		llvm_api_lock.acquire();
2c859ec7
 #else
 		llvm_api_lock.lock();
 #endif
ee6ab4f8
 	}
 	~LLVMApiScopedLock() {
a7cf187a
 //	    if (!llvm_is_multithreaded())
2c859ec7
 #if LLVM_VERSION < 36
ee6ab4f8
 		llvm_api_lock.release();
2c859ec7
 #else
 		llvm_api_lock.unlock();
 #endif
ee6ab4f8
 	}
 };
 
57bbb2eb
 static void addFunctionProtos(struct CommonFunctions *CF, ExecutionEngine *EE, Module *M)
 {
     LLVMContext &Context = M->getContext();
     FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
 					  false);
     CF->FHandler = Function::Create(FTy, Function::ExternalLinkage,
 					  "clamjit.fail", M);
     CF->FHandler->setDoesNotReturn();
     CF->FHandler->setDoesNotThrow();
34d8b8cf
 #if LLVM_VERSION == 32
     CF->FHandler->addFnAttr(Attributes::NoInline);
 #else
57bbb2eb
     CF->FHandler->addFnAttr(Attribute::NoInline);
34d8b8cf
 #endif
2c859ec7
 #if LLVM_VERSION < 36
     // addGlobalMapping still exists in LLVM 3.6, but it doesn't work with MCJIT, which now replaces the JIT implementation.
57bbb2eb
     EE->addGlobalMapping(CF->FHandler, (void*)(intptr_t)jit_exception_handler);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(CF->FHandler->getName(), (void*)(intptr_t)jit_exception_handler);
 #endif
57bbb2eb
     EE->InstallLazyFunctionCreator(noUnknownFunctions);
f121d43d
     EE->getPointerToFunction(CF->FHandler);
57bbb2eb
 
59f1b78b
     std::vector<constType*> args;
57bbb2eb
     args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
     args.push_back(Type::getInt8Ty(Context));
99aeada8
     args.push_back(Type::getInt32Ty(Context));
57bbb2eb
     args.push_back(Type::getInt32Ty(Context));
deafd8fa
 #if LLVM_VERSION >= 29
59f1b78b
     args.push_back(Type::getInt1Ty(Context));
 #endif
57bbb2eb
     FunctionType* FuncTy_3 = FunctionType::get(Type::getVoidTy(Context),
 					       args, false);
     CF->FMemset = Function::Create(FuncTy_3, GlobalValue::ExternalLinkage,
deafd8fa
 #if LLVM_VERSION < 29
99aeada8
                                    "llvm.memset.i32",
9f8df4ae
 #else
99aeada8
                                    "llvm.memset.p0i8.i32",
59f1b78b
 #endif
fb2b05cb
                                    M);
57bbb2eb
     CF->FMemset->setDoesNotThrow();
34d8b8cf
 #if LLVM_VERSION < 32
57bbb2eb
     CF->FMemset->setDoesNotCapture(1, true);
34d8b8cf
 #else
     CF->FMemset->setDoesNotCapture(1);
 #endif
57bbb2eb
 
     args.clear();
     args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
     args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
99aeada8
     args.push_back(Type::getInt32Ty(Context));
57bbb2eb
     args.push_back(Type::getInt32Ty(Context));
deafd8fa
 #if LLVM_VERSION >= 29
59f1b78b
     args.push_back(Type::getInt1Ty(Context));
 #endif
57bbb2eb
     FunctionType* FuncTy_4 = FunctionType::get(Type::getVoidTy(Context),
 					       args, false);
     CF->FMemmove = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage,
deafd8fa
 #if LLVM_VERSION < 29
99aeada8
                                     "llvm.memmove.i32",
9f8df4ae
 #else
99aeada8
                                     "llvm.memmove.p0i8.i32",
59f1b78b
 #endif
fb2b05cb
                                     M);
57bbb2eb
     CF->FMemmove->setDoesNotThrow();
34d8b8cf
 #if LLVM_VERSION < 32
57bbb2eb
     CF->FMemmove->setDoesNotCapture(1, true);
34d8b8cf
 #else
     CF->FMemmove->setDoesNotCapture(1);
 #endif
57bbb2eb
 
     CF->FMemcpy = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage,
deafd8fa
 #if LLVM_VERSION < 29
99aeada8
                                    "llvm.memcpy.i32",
9f8df4ae
 #else
99aeada8
                                    "llvm.memcpy.p0i8.p0i8.i32",
59f1b78b
 #endif
fb2b05cb
                                    M);
57bbb2eb
     CF->FMemcpy->setDoesNotThrow();
34d8b8cf
 #if LLVM_VERSION < 32
57bbb2eb
     CF->FMemcpy->setDoesNotCapture(1, true);
34d8b8cf
 #else
     CF->FMemcpy->setDoesNotCapture(1);
 #endif
57bbb2eb
 
     args.clear();
     args.push_back(Type::getInt16Ty(Context));
     FunctionType *FuncTy_5 = FunctionType::get(Type::getInt16Ty(Context), args, false);
     CF->FBSwap16 = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage,
 					  "llvm.bswap.i16", M);
     CF->FBSwap16->setDoesNotThrow();
 
     args.clear();
     args.push_back(Type::getInt32Ty(Context));
     FunctionType *FuncTy_6 = FunctionType::get(Type::getInt32Ty(Context), args, false);
     CF->FBSwap32 = Function::Create(FuncTy_6, GlobalValue::ExternalLinkage,
 					  "llvm.bswap.i32", M);
     CF->FBSwap32->setDoesNotThrow();
 
     args.clear();
     args.push_back(Type::getInt64Ty(Context));
     FunctionType *FuncTy_7 = FunctionType::get(Type::getInt64Ty(Context), args, false);
     CF->FBSwap64 = Function::Create(FuncTy_7, GlobalValue::ExternalLinkage,
 					  "llvm.bswap.i64", M);
     CF->FBSwap64->setDoesNotThrow();
 
     FunctionType* DummyTy = FunctionType::get(Type::getVoidTy(Context), false);
     CF->FRealmemset = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
 					     "memset", M);
2c859ec7
 #if LLVM_VERSION < 36
57bbb2eb
     EE->addGlobalMapping(CF->FRealmemset, (void*)(intptr_t)memset);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(CF->FRealmemset->getName(), (void*)(intptr_t)memset);
 #endif
f121d43d
     EE->getPointerToFunction(CF->FRealmemset);
57bbb2eb
     CF->FRealMemmove = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
 					      "memmove", M);
2c859ec7
 #if LLVM_VERSION < 36
57bbb2eb
     EE->addGlobalMapping(CF->FRealMemmove, (void*)(intptr_t)memmove);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(CF->FRealMemmove->getName(), (void*)(intptr_t)memmove);
 #endif
f121d43d
     EE->getPointerToFunction(CF->FRealMemmove);
57bbb2eb
     CF->FRealmemcpy = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
 					     "memcpy", M);
2c859ec7
 #if LLVM_VERSION < 36
57bbb2eb
     EE->addGlobalMapping(CF->FRealmemcpy, (void*)(intptr_t)memcpy);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(CF->FRealmemcpy->getName(), (void*)(intptr_t)memcpy);
 #endif
f121d43d
     EE->getPointerToFunction(CF->FRealmemcpy);
57bbb2eb
 
     args.clear();
     args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
     args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
34d8b8cf
 #if LLVM_VERSION < 32
57bbb2eb
     args.push_back(EE->getTargetData()->getIntPtrType(Context));
34d8b8cf
 #else
     args.push_back(EE->getDataLayout()->getIntPtrType(Context));
 #endif
57bbb2eb
     FuncTy_5 = FunctionType::get(Type::getInt32Ty(Context),
 				 args, false);
     CF->FRealmemcmp = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage, "memcmp", M);
2c859ec7
 #if LLVM_VERSION < 36
57bbb2eb
     EE->addGlobalMapping(CF->FRealmemcmp, (void*)(intptr_t)memcmp);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(CF->FRealmemcmp->getName(), (void*)(intptr_t)memcmp);
 #endif
f121d43d
     EE->getPointerToFunction(CF->FRealmemcmp);
57bbb2eb
 }
 
d1487222
 }
9f8df4ae
 #if LLVM_VERSION >= 29
0c79cc55
 INITIALIZE_PASS_BEGIN(RuntimeLimits, "rl", "Runtime Limits", false, false)
 INITIALIZE_PASS_DEPENDENCY(LoopInfo)
 INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
4a40b53a
 #if LLVM_VERSION < 35
0c79cc55
 INITIALIZE_PASS_DEPENDENCY(DominatorTree)
4a40b53a
 #else
 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
 #endif
0c79cc55
 INITIALIZE_PASS_END(RuntimeLimits, "rl" ,"Runtime Limits", false, false)
 #endif
d1487222
 
e51fc058
 static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER;
bb5572cb
 static pthread_cond_t watchdog_cond2 = PTHREAD_COND_INITIALIZER;
e51fc058
 static int watchdog_running = 0;
 
 struct watchdog_item {
bdd9aeae
     volatile uint8_t* timeout;
e51fc058
     struct timespec abstimeout;
     struct watchdog_item *next;
bb5572cb
     int in_use;
884a0b8f
 };
 
e51fc058
 static struct watchdog_item* watchdog_head = NULL;
 static struct watchdog_item* watchdog_tail = NULL;
 
bb5572cb
 extern "C" const char *cli_strerror(int errnum, char* buf, size_t len);
e51fc058
 #define WATCHDOG_IDLE 10
bdd9aeae
 static void *bytecode_watchdog(void *arg)
 {
e51fc058
     struct timeval tv;
     struct timespec out;
bb5572cb
     int ret;
     char err[128];
e51fc058
     pthread_mutex_lock(&watchdog_mutex);
     if (cli_debug_flag)
 	cli_dbgmsg_internal("bytecode watchdog is running\n");
     do {
 	struct watchdog_item *item;
 	gettimeofday(&tv, NULL);
 	out.tv_sec = tv.tv_sec + WATCHDOG_IDLE;
 	out.tv_nsec = tv.tv_usec*1000;
 	/* wait for some work, up to WATCHDOG_IDLE time */
bb5572cb
 	while (watchdog_head == NULL) {
 	    ret = pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex,
 					 &out);
 	    if (ret == ETIMEDOUT)
 		break;
 	    if (ret) {
 		cli_warnmsg("bytecode_watchdog: cond_timedwait(1) failed: %s\n",
 			    cli_strerror(ret, err, sizeof(err)));
 		break;
 	    }
 	}
e51fc058
 	if (watchdog_head == NULL)
 	    break;
 	/* wait till timeout is reached on this item */
 	item = watchdog_head;
bb5572cb
 	while (item == watchdog_head) {
 	    item->in_use = 1;
 	    ret = pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex,
 					 &item->abstimeout);
 	    if (ret == ETIMEDOUT)
 		break;
 	    if (ret) {
 		cli_warnmsg("bytecode_watchdog: cond_timedwait(2) failed: %s\n",
 			    cli_strerror(ret, err, sizeof(err)));
 		break;
 	    }
 	}
 	item->in_use = 0;
 	pthread_cond_signal(&watchdog_cond2);
e51fc058
 	if (item != watchdog_head)
 	    continue;/* got removed meanwhile */
 	/* timeout reached, signal it to bytecode */
 	*item->timeout = 1;
162c2e43
 	cli_warnmsg("[Bytecode JIT]: Bytecode run timed out, timeout flag set\n");
e51fc058
 	watchdog_head = item->next;
 	if (!watchdog_head)
 	    watchdog_tail = NULL;
     } while (1);
     watchdog_running = 0;
     if (cli_debug_flag)
 	cli_dbgmsg_internal("bytecode watchdog quiting\n");
     pthread_mutex_unlock(&watchdog_mutex);
bdd9aeae
     return NULL;
 }
 
e51fc058
 static void watchdog_disarm(struct watchdog_item *item)
 {
     struct watchdog_item *q, *p = NULL;
     if (!item)
 	return;
     pthread_mutex_lock(&watchdog_mutex);
     for (q=watchdog_head;q && q != item;p = q, q = q->next) {}
     if (q == item) {
 	if (p)
 	    p->next = q->next;
 	if (q == watchdog_head)
 	    watchdog_head = q->next;
 	if (q == watchdog_tail)
 	    watchdog_tail = p;
     }
bb5572cb
     /* don't remove the item from the list until the watchdog is sleeping on
      * item, or it'll wake up on uninit data */
     while (item->in_use) {
 	pthread_cond_signal(&watchdog_cond);
 	pthread_cond_wait(&watchdog_cond2, &watchdog_mutex);
     }
e51fc058
     pthread_mutex_unlock(&watchdog_mutex);
 }
 
 static int watchdog_arm(struct watchdog_item *item, int ms, volatile uint8_t *timeout)
 {
     int rc = 0;
     struct timeval tv0;
 
     *timeout = 0;
     item->timeout = timeout;
     item->next = NULL;
bb5572cb
     item->in_use = 0;
e51fc058
 
     gettimeofday(&tv0, NULL);
     tv0.tv_usec += ms * 1000;
     item->abstimeout.tv_sec = tv0.tv_sec + tv0.tv_usec/1000000;
     item->abstimeout.tv_nsec = (tv0.tv_usec%1000000)*1000;
 
     pthread_mutex_lock(&watchdog_mutex);
     if (!watchdog_running) {
 	pthread_t thread;
 	pthread_attr_t attr;
 	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
 	if ((rc = pthread_create(&thread, &attr, bytecode_watchdog, NULL))) {
 	    char buf[256];
 	    cli_errmsg("(watchdog) pthread_create failed: %s\n", cli_strerror(rc, buf, sizeof(buf)));
 	}
bb5572cb
 	if (!rc)
 	    watchdog_running = 1;
e51fc058
 	pthread_attr_destroy(&attr);
     }
     if (!rc) {
 	if (watchdog_tail)
 	    watchdog_tail->next = item;
 	watchdog_tail = item;
 	if (!watchdog_head)
 	    watchdog_head = item;
     }
     pthread_cond_signal(&watchdog_cond);
     pthread_mutex_unlock(&watchdog_mutex);
     return rc;
 }
 
bdd9aeae
 static int bytecode_execute(intptr_t code, struct cli_bc_ctx *ctx)
d1487222
 {
162c2e43
     ScopedExceptionHandler handler;
85a25497
     // execute;
3a35520b
     HANDLER_TRY(handler) {
6b67ec6e
 	// setup exception handler to longjmp back here
3cd48316
 	uint32_t result = ((uint32_t (*)(struct cli_bc_ctx *))(intptr_t)code)(ctx);
6b67ec6e
 	*(uint32_t*)ctx->values = result;
 	return 0;
     }
3a35520b
     HANDLER_END(handler);
162c2e43
     cli_warnmsg("[Bytecode JIT]: JITed code intercepted runtime error!\n");
bdd9aeae
     return CL_EBYTECODE;
884a0b8f
 }
 
 int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx,
 		       const struct cli_bc_func *func)
 {
     int ret;
     struct timeval tv0, tv1;
e51fc058
     struct watchdog_item witem;
884a0b8f
     // no locks needed here, since LLVM automatically acquires a JIT lock
     // if needed.
     void *code = bcs->engine->compiledFunctions[func];
     if (!code) {
29553b8e
 	cli_warnmsg("[Bytecode JIT]: Unable to find compiled function\n");
884a0b8f
 	if (func->numArgs)
29553b8e
 	    cli_warnmsg("[Bytecode JIT] Function has %d arguments, it must have 0 to be called as entrypoint\n",
 			func->numArgs);
884a0b8f
 	return CL_EBYTECODE;
     }
e51fc058
     if (cli_debug_flag)
 	gettimeofday(&tv0, NULL);
bdd9aeae
 
71ca3536
     if (ctx->bytecode_timeout) {
 	/* only spawn if timeout is set.
 	 * we don't set timeout for selfcheck (see bb #2235) */
e51fc058
 	if (watchdog_arm(&witem, ctx->bytecode_timeout, &ctx->timeout))
71ca3536
 	    return CL_EBYTECODE;
884a0b8f
     }
 
bdd9aeae
     ret = bytecode_execute((intptr_t)code, ctx);
e51fc058
 
     if (ctx->bytecode_timeout)
 	watchdog_disarm(&witem);
bdd9aeae
 
884a0b8f
     if (cli_debug_flag) {
29553b8e
 	long diff;
884a0b8f
 	gettimeofday(&tv1, NULL);
 	tv1.tv_sec -= tv0.tv_sec;
 	tv1.tv_usec -= tv0.tv_usec;
29553b8e
 	diff = tv1.tv_sec*1000000 + tv1.tv_usec;
 	cli_dbgmsg_internal("bytecode finished in %ld us\n", diff);
884a0b8f
     }
bdd9aeae
     return ctx->timeout ? CL_ETIMEOUT : ret;
d1487222
 }
 
9463f9fd
 static unsigned char name_salt[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 };
 static void setGuard(unsigned char* guardbuf)
 {
     char salt[48];
     memcpy(salt, name_salt, 16);
     for(unsigned i = 16; i < 48; i++)
34d8b8cf
 	salt[i] = cli_rndnum(255);
9463f9fd
 
dd2ed14d
     cl_hash_data((char*)"md5", salt, 48, guardbuf, NULL);
9463f9fd
 }
34d8b8cf
 #if LLVM_VERSION < 32
6e52ce67
 static void addFPasses(FunctionPassManager &FPM, bool trusted, const TargetData *TD)
4a40b53a
 #elif LLVM_VERSION < 35
34d8b8cf
 static void addFPasses(FunctionPassManager &FPM, bool trusted, const DataLayout *TD)
2c859ec7
 #elif LLVM_VERSION < 36
4a40b53a
 static void addFPasses(FunctionPassManager &FPM, bool trusted, const Module *M)
2c859ec7
 #else
 static void addFPasses(FunctionPassManager &FPM, bool trusted, Module *M)
34d8b8cf
 #endif
6e52ce67
 {
     // Set up the optimizer pipeline.  Start with registering info about how
     // the target lays out data structures.
34d8b8cf
 #if LLVM_VERSION < 32
6e52ce67
     FPM.add(new TargetData(*TD));
4a40b53a
 #elif LLVM_VERSION < 35
34d8b8cf
     FPM.add(new DataLayout(*TD));
2c859ec7
 #elif LLVM_VERSION < 36
4a40b53a
     FPM.add(new DataLayoutPass(M));
2c859ec7
 #else
     DataLayoutPass *DLP = new DataLayoutPass();
     DLP->doInitialization(*M);
     FPM.add(DLP);
34d8b8cf
 #endif
6e52ce67
     // Promote allocas to registers.
     FPM.add(createPromoteMemoryToRegisterPass());
     FPM.add(new BrSimplifier());
     FPM.add(createDeadCodeEliminationPass());
 }
 
d1487222
 int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
 {
2487a4a3
   if (!bcs->engine)
       return CL_EBYTECODE;
162c2e43
   ScopedExceptionHandler handler;
ee6ab4f8
   LLVMApiScopedLock scopedLock;
6b67ec6e
   // setup exception handler to longjmp back here
3a35520b
   HANDLER_TRY(handler) {
d1487222
   // LLVM itself never throws exceptions, but operator new may throw bad_alloc
   try {
     Module *M = new Module("ClamAV jit module", bcs->engine->Context);
     {
 	// Create the JIT.
 	std::string ErrorMsg;
2c859ec7
 #if LLVM_VERSION < 36
04d11afe
 	EngineBuilder builder(M);
2c859ec7
 #else
 	EngineBuilder builder(std::move(std::unique_ptr<Module>(M)));
 #endif
34d8b8cf
 
 #if LLVM_VERSION >= 31
 	TargetOptions Options;
 #ifdef CL_DEBUG
 	//disable this for now, it leaks
 	Options.JITEmitDebugInfo = false;
 //	Options.JITEmitDebugInfo = true;
 #else
 	Options.JITEmitDebugInfo = false;
 #endif
 #if LLVM_VERSION < 34
 	Options.DwarfExceptionHandling = false;
 #else
 	// TODO: How to do this now?
 #endif
 	builder.setTargetOptions(Options);
 #endif
 
d1487222
 	builder.setErrorStr(&ErrorMsg);
 	builder.setEngineKind(EngineKind::JIT);
9463f9fd
 	builder.setOptLevel(CodeGenOpt::Default);
d1487222
 	ExecutionEngine *EE = bcs->engine->EE = builder.create();
 	if (!EE) {
 	    if (!ErrorMsg.empty())
29553b8e
 		cli_errmsg("[Bytecode JIT]: error creating execution engine: %s\n",
 			   ErrorMsg.c_str());
d1487222
 	    else
29553b8e
 		cli_errmsg("[Bytecode JIT]: JIT not registered?\n");
d1487222
 	    return CL_EBYTECODE;
 	}
e2752b2c
 	bcs->engine->Listener  = new NotifyListener();
 	EE->RegisterJITEventListener(bcs->engine->Listener);
1f1a2497
 //	EE->RegisterJITEventListener(createOProfileJITEventListener());
2487a4a3
 	// Due to LLVM PR4816 only X86 supports non-lazy compilation, disable
 	// for now.
53bd5bb1
 	EE->DisableLazyCompilation();
2c859ec7
 #if LLVM_VERSION < 36
6b67ec6e
 	EE->DisableSymbolSearching();
2c859ec7
 #else
 	// This must be enabled for AddSymbol to work.
 	EE->DisableSymbolSearching(false);
 #endif
d1487222
 
57bbb2eb
 	struct CommonFunctions CF;
 	addFunctionProtos(&CF, EE, M);
 
6e52ce67
 	FunctionPassManager OurFPM(M), OurFPMUnsigned(M);
34d8b8cf
 #if LLVM_VERSION < 32
b2de4fd8
 	M->setDataLayout(EE->getTargetData()->getStringRepresentation());
34d8b8cf
 #else
 	M->setDataLayout(EE->getDataLayout()->getStringRepresentation());
 #endif
 #if LLVM_VERSION < 31
b2de4fd8
 	M->setTargetTriple(sys::getHostTriple());
34d8b8cf
 #else
 	M->setTargetTriple(sys::getDefaultTargetTriple());
 #endif
 #if LLVM_VERSION < 32
6e52ce67
 	addFPasses(OurFPM, true, EE->getTargetData());
 	addFPasses(OurFPMUnsigned, false, EE->getTargetData());
4a40b53a
 #elif LLVM_VERSION < 35
34d8b8cf
 	addFPasses(OurFPM, true, EE->getDataLayout());
 	addFPasses(OurFPMUnsigned, false, EE->getDataLayout());
4a40b53a
 #else
 	addFPasses(OurFPM, true, M);
 	addFPasses(OurFPMUnsigned, false, M);
34d8b8cf
 #endif
 
e32caecb
 
d0af4afe
 	//TODO: create a wrapper that calls pthread_getspecific
aa745db7
 	unsigned maxh = cli_globals[0].offset + sizeof(struct cli_bc_hooks);
59f1b78b
 	constType *HiddenCtx = PointerType::getUnqual(ArrayType::get(Type::getInt8Ty(bcs->engine->Context), maxh));
d0af4afe
 
 	LLVMTypeMapper apiMap(bcs->engine->Context, cli_apicall_types, cli_apicall_maxtypes, HiddenCtx);
e32caecb
 	Function **apiFuncs = new Function *[cli_apicall_maxapi];
 	for (unsigned i=0;i<cli_apicall_maxapi;i++) {
 	    const struct cli_apicall *api = &cli_apicalls[i];
59f1b78b
 	    constFunctionType *FTy = cast<FunctionType>(apiMap.get(69+api->type, NULL, NULL));
e32caecb
 	    Function *F = Function::Create(FTy, Function::ExternalLinkage,
 					   api->name, M);
 	    void *dest;
 	    switch (api->kind) {
 		case 0:
3cd48316
 		    dest = (void*)(intptr_t)cli_apicalls0[api->idx];
e32caecb
 		    break;
 		case 1:
3cd48316
 		    dest = (void*)(intptr_t)cli_apicalls1[api->idx];
e32caecb
 		    break;
2d45ef06
 		case 2:
 		    dest = (void*)(intptr_t)cli_apicalls2[api->idx];
 		    break;
 		case 3:
 		    dest = (void*)(intptr_t)cli_apicalls3[api->idx];
 		    break;
b56bea54
 		case 4:
 		    dest = (void*)(intptr_t)cli_apicalls4[api->idx];
 		    break;
75e18b29
 		case 5:
 		    dest = (void*)(intptr_t)cli_apicalls5[api->idx];
 		    break;
 		case 6:
 		    dest = (void*)(intptr_t)cli_apicalls6[api->idx];
 		    break;
6ad39a40
 		case 7:
 		    dest = (void*)(intptr_t)cli_apicalls7[api->idx];
 		    break;
7a7365ef
 		case 8:
 		    dest = (void*)(intptr_t)cli_apicalls8[api->idx];
 		    break;
 		case 9:
 		    dest = (void*)(intptr_t)cli_apicalls9[api->idx];
 		    break;
3cd48316
 		default:
 		    llvm_unreachable("invalid api type");
e32caecb
 	    }
7a7365ef
 	    if (!dest) {
 		std::string reason((Twine("No mapping for builtin api ")+api->name).str());
 		llvm_error_handler(0, reason);
 	    }
2c859ec7
 #if LLVM_VERSION < 36
e32caecb
 	    EE->addGlobalMapping(F, dest);
2c859ec7
 #else
     // addGlobalMapping doesn't work with MCJIT, so use symbol searching instead.
     sys::DynamicLibrary::AddSymbol(F->getName(), dest);
 #endif
f121d43d
 	    EE->getPointerToFunction(F);
e32caecb
 	    apiFuncs[i] = F;
 	}
 
9463f9fd
 	// stack protector
 	FunctionType *FTy = FunctionType::get(Type::getVoidTy(M->getContext()),
 						    false);
 	GlobalVariable *Guard = new GlobalVariable(*M, PointerType::getUnqual(Type::getInt8Ty(M->getContext())),
6e52ce67
 						    true, GlobalValue::ExternalLinkage, 0, "__stack_chk_guard");
9463f9fd
 	unsigned plus = 0;
 	if (2*sizeof(void*) <= 16 && cli_rndnum(2)==2) {
 	    plus = sizeof(void*);
 	}
2c859ec7
 #if LLVM_VERSION < 36
9463f9fd
 	EE->addGlobalMapping(Guard, (void*)(&bcs->engine->guard.b[plus]));
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(Guard->getName(), (void*)(&bcs->engine->guard.b[plus]));
 #endif
9463f9fd
 	setGuard(bcs->engine->guard.b);
 	bcs->engine->guard.b[plus+sizeof(void*)-1] = 0x00;
 //	printf("%p\n", *(void**)(&bcs->engine->guard.b[plus]));
 	Function *SFail = Function::Create(FTy, Function::ExternalLinkage,
 					      "__stack_chk_fail", M);
2c859ec7
 #if LLVM_VERSION < 36
9463f9fd
 	EE->addGlobalMapping(SFail, (void*)(intptr_t)jit_ssp_handler);
2c859ec7
 #else
     sys::DynamicLibrary::AddSymbol(SFail->getName(), (void*)(intptr_t)jit_ssp_handler);
 #endif
f121d43d
         EE->getPointerToFunction(SFail);
9463f9fd
 
6e52ce67
 	llvm::Function **Functions = new Function*[bcs->count];
daffb518
 	for (unsigned i=0;i<bcs->count;i++) {
3b33bd68
 	    const struct cli_bc *bc = &bcs->all_bcs[i];
49eb0108
 	    if (bc->state == bc_skip || bc->state == bc_interp) {
 		Functions[i] = 0;
4789b8a5
 		continue;
49eb0108
 	    }
57bbb2eb
 	    LLVMCodegen Codegen(bc, M, &CF, bcs->engine->compiledFunctions, EE,
6e52ce67
 				OurFPM, OurFPMUnsigned, apiFuncs, apiMap);
 	    Function *F = Codegen.generate();
 	    if (!F) {
29553b8e
 		cli_errmsg("[Bytecode JIT]: JIT codegen failed\n");
3aca6c4a
 		delete [] apiFuncs;
 		for (unsigned z=0; z < i; z++) {
 		    delete Functions[z];
 		}
 		delete [] Functions;
ee8f1888
 		return CL_EBYTECODE;
 	    }
6e52ce67
 	    Functions[i] = F;
daffb518
 	}
6e52ce67
 	delete [] apiFuncs;
 
 	bool has_untrusted = false;
daffb518
 
85a25497
 	for (unsigned i=0;i<bcs->count;i++) {
6e52ce67
 	    if (!bcs->all_bcs[i].trusted) {
 		has_untrusted = true;
 		break;
 	    }
85a25497
 	}
6e52ce67
 	PassManager PM;
34d8b8cf
 #if LLVM_VERSION < 32
6e52ce67
 	PM.add(new TargetData(*EE->getTargetData()));
4a40b53a
 #elif LLVM_VERSION < 35
34d8b8cf
 	PM.add(new DataLayout(*EE->getDataLayout()));
2c859ec7
 #elif LLVM_VERSION < 36
4a40b53a
 	PM.add(new DataLayoutPass(M));
2c859ec7
 #else
     DataLayoutPass *DLP = new DataLayoutPass();
     DLP->doInitialization(*M);
     PM.add(DLP);
34d8b8cf
 #endif
6e52ce67
 	// TODO: only run this on the untrusted bytecodes, not all of them...
 	if (has_untrusted)
 	    PM.add(createClamBCRTChecks());
2c859ec7
 #if LLVM_VERSION >= 36
 	// With LLVM 3.6 (MCJIT) this Pass is required to work around
 	// a crash in LLVM caused by the SCCP Pass:
 	// Pass 'Sparse Conditional Constant Propagation' is not initialized.
 	// Verify if there is a pass dependency cycle.
 	// Required Passes:
 	//
 	// Program received signal SIGSEGV, Segmentation fault.
 	PM.add(createGVNPass());
 #endif
6e52ce67
 	PM.add(createSCCPPass());
ab402e6a
 	PM.add(createCFGSimplificationPass());
6e52ce67
 	PM.add(createGlobalOptimizerPass());
 	PM.add(createConstantMergePass());
0c79cc55
 
 	RuntimeLimits *RL = new RuntimeLimits();
 	PM.add(RL);
c0a306b2
 	TimerWrapper pmTimer2("Transform passes");
6e52ce67
 	pmTimer2.startTimer();
 	PM.run(*M);
 	pmTimer2.stopTimer();
 	DEBUG(M->dump());
 
2c859ec7
 #if LLVM_VERSION >= 36
 	EE->finalizeObject();
 #endif
 
6e52ce67
 	{
 	    PrettyStackTraceString CrashInfo2("Native machine codegen");
c0a306b2
 	    TimerWrapper codegenTimer("Native codegen");
6e52ce67
 	    codegenTimer.startTimer();
 	    // compile all functions now, not lazily!
 	    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
 		Function *Fn = &*I;
ab402e6a
 		if (!Fn->isDeclaration()) {
6e52ce67
 		    EE->getPointerToFunction(Fn);
ab402e6a
 		}
6e52ce67
 	    }
 	    codegenTimer.stopTimer();
d1487222
 	}
6e52ce67
 
 	for (unsigned i=0;i<bcs->count;i++) {
 	    const struct cli_bc_func *func = &bcs->all_bcs[i].funcs[0];
49eb0108
 	    if (!Functions[i])
 		continue;// not JITed
6e52ce67
 	    bcs->engine->compiledFunctions[func] = EE->getPointerToFunction(Functions[i]);
 	    bcs->all_bcs[i].state = bc_jit;
 	}
 	delete [] Functions;
d1487222
     }
a5a19f45
     return CL_SUCCESS;
d1487222
   } catch (std::bad_alloc &badalloc) {
29553b8e
       cli_errmsg("[Bytecode JIT]: bad_alloc: %s\n",
 		 badalloc.what());
d1487222
       return CL_EMEM;
   } catch (...) {
22cb38ed
       cli_errmsg("[Bytecode JIT]: Unexpected unknown exception occurred\n");
d1487222
       return CL_EBYTECODE;
   }
3a35520b
   return 0;
   } HANDLER_END(handler);
   cli_errmsg("[Bytecode JIT] *** FATAL error encountered during bytecode generation\n");
   return CL_EBYTECODE;
d1487222
 }
 
 int bytecode_init(void)
 {
df52b258
     // If already initialized return
4a40b53a
 #if LLVM_VERSION < 35
ee6ab4f8
     if (llvm_is_multithreaded()) {
26b86d8d
 	cli_warnmsg("bytecode_init: already initialized\n");
ee6ab4f8
 	return CL_EARG;
     }
4a40b53a
 #else
     if (!LLVMIsMultithreaded()) {
         cli_warnmsg("bytecode_init: LLVM is compiled without multithreading support\n");
     }
 #endif
 
d6699b05
     // LLVM safety assertion prevention fix
     // TODO: do we want to do a full shutdown?
     remove_fatal_error_handler();
d1487222
     llvm_install_error_handler(llvm_error_handler);
52dd3a6b
 #ifdef CL_DEBUG
d1487222
     sys::PrintStackTraceOnErrorSignal();
34d8b8cf
 #if LLVM_VERSION >= 34
     llvm::EnablePrettyStackTrace();
 #endif
d38d6dad
 #else
34d8b8cf
 #if LLVM_VERSION < 34
d38d6dad
     llvm::DisablePrettyStackTrace = true;
52dd3a6b
 #endif
34d8b8cf
 #endif
d1487222
     atexit(do_shutdown);
 
34d8b8cf
 #if LLVM_VERSION < 31
d2171abf
 #ifdef CL_DEBUG
11cee1b7
     //disable this for now, it leaks
     llvm::JITEmitDebugInfo = false;
 //    llvm::JITEmitDebugInfo = true;
482e97db
 #else
     llvm::JITEmitDebugInfo = false;
d2171abf
 #endif
482e97db
     llvm::DwarfExceptionHandling = false;
34d8b8cf
 #endif
4a40b53a
 #if LLVM_VERSION < 33
d1487222
     llvm_start_multithreaded();
4a40b53a
 #else
     // This is now deprecated/useless: Multi-threading can only be enabled/disabled with the compile time define LLVM_ENABLE_THREADS in LLVM.
 #endif
d1487222
 
     // If we have a native target, initialize it to ensure it is linked in and
     // usable by the JIT.
dec93ea8
 #ifndef AC_APPLE_UNIVERSAL_BUILD
d1487222
     InitializeNativeTarget();
2c859ec7
 #if LLVM_VERSION >= 36
     InitializeNativeTargetAsmPrinter();
     InitializeNativeTargetAsmParser();
 #endif
dec93ea8
 #else
     InitializeAllTargets();
 #endif
ee6ab4f8
 
4a40b53a
 #if LLVM_VERSION < 35
ee6ab4f8
     if (!llvm_is_multithreaded()) {
4a40b53a
 #else
     if (!LLVMIsMultithreaded()) {
 #endif
ee6ab4f8
 	//TODO:cli_dbgmsg
 	DEBUG(errs() << "WARNING: ClamAV JIT built w/o atomic builtins\n"
 	      << "On x86 for best performance ClamAV should be built for i686, not i386!\n");
     }
d1487222
     return 0;
 }
 
 // Called once when loading a new set of BC files
6eeadbfe
 int cli_bytecode_init_jit(struct cli_all_bc *bcs, unsigned dconfmask)
d1487222
 {
ee6ab4f8
     LLVMApiScopedLock scopedLock;
c52e9274
     bcs->engine = new(std::nothrow) cli_bcengine;
d1487222
     if (!bcs->engine)
 	return CL_EMEM;
52dd3a6b
     bcs->engine->EE = 0;
84edf09b
     bcs->engine->Listener = 0;
d1487222
     return 0;
 }
 
a5a19f45
 int cli_bytecode_done_jit(struct cli_all_bc *bcs, int partial)
d1487222
 {
ee6ab4f8
     LLVMApiScopedLock scopedLock;
2487a4a3
     if (bcs->engine) {
e2752b2c
 	if (bcs->engine->EE) {
84edf09b
 	    if (bcs->engine->Listener)
 		bcs->engine->EE->UnregisterJITEventListener(bcs->engine->Listener);
2487a4a3
 	    delete bcs->engine->EE;
a5a19f45
 	    bcs->engine->EE = 0;
e2752b2c
 	}
 	delete bcs->engine->Listener;
a5a19f45
 	bcs->engine->Listener = 0;
 	if (!partial) {
 	    delete bcs->engine;
 	    bcs->engine = 0;
 	}
2487a4a3
     }
d1487222
     return 0;
 }
3b33bd68
 
 void cli_bytecode_debug(int argc, char **argv)
 {
   cl::ParseCommandLineOptions(argc, argv);
 }
2487a4a3
 
3cd48316
 typedef struct lines {
65c740d7
     MemoryBuffer *buffer;
853b6e5d
     std::vector<const char*> linev;
3cd48316
 } linesTy;
65c740d7
 
 static struct lineprinter {
3cd48316
     StringMap<linesTy*> files;
65c740d7
 } LinePrinter;
 
 void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx)
 {
0a11015b
     if (!ctx->file || !ctx->directory || !ctx->line) {
 	errs() << (ctx->directory ? "d":"null") << ":" << (ctx->file ? "f" : "null")<< ":" << ctx->line << "\n";
65c740d7
 	return;
     }
     // acquire a mutex here
     sys::Mutex mtx(false);
     sys::SmartScopedLock<false> lock(mtx);
 
     std::string path = std::string(ctx->directory) + "/" + std::string(ctx->file);
3cd48316
     StringMap<linesTy*>::iterator I = LinePrinter.files.find(path);
     linesTy *lines;
65c740d7
     if (I == LinePrinter.files.end()) {
3cd48316
 	lines = new linesTy;
65c740d7
 	std::string ErrorMessage;
9f8df4ae
 #if LLVM_VERSION < 29
 	lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage);
4a40b53a
 #elif LLVM_VERSION < 35
0c79cc55
 	OwningPtr<MemoryBuffer> File;
 	error_code ec = MemoryBuffer::getFile(path, File);
 	if (ec) {
 	    ErrorMessage = ec.message();
 	    lines->buffer = 0;
 	} else
 	    lines->buffer = File.take();
4a40b53a
 #else
 	ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = MemoryBuffer::getFile(path);
 	if (!FileOrErr) {
 		// TODO: How to handle ErrorMessage?
 		lines->buffer = 0;
 	}
 	else {
 		lines->buffer = FileOrErr.get().release();
 	}
0c79cc55
 #endif
65c740d7
 	if (!lines->buffer) {
 	    errs() << "Unable to open file '" << path << "'\n";
bebd86a6
 	    delete lines;
65c740d7
 	    return ;
 	}
 	LinePrinter.files[path] = lines;
     } else {
 	lines = I->getValue();
     }
853b6e5d
     while (lines->linev.size() <= ctx->line+1) {
65c740d7
 	const char *p;
853b6e5d
 	if (lines->linev.empty()) {
65c740d7
 	    p = lines->buffer->getBufferStart();
853b6e5d
 	    lines->linev.push_back(p);
65c740d7
 	} else {
853b6e5d
 	    p = lines->linev.back();
65c740d7
 	    if (p == lines->buffer->getBufferEnd())
 		break;
 	    p = strchr(p, '\n');
 	    if (!p) {
 		p = lines->buffer->getBufferEnd();
853b6e5d
 		lines->linev.push_back(p);
65c740d7
 	    } else
853b6e5d
 		lines->linev.push_back(p+1);
65c740d7
 	}
     }
853b6e5d
     if (ctx->line >= lines->linev.size()) {
0a11015b
 	errs() << "Line number " << ctx->line << "out of file\n";
65c740d7
 	return;
     }
853b6e5d
     assert(ctx->line < lines->linev.size());
e4a0f2c9
 
9f8df4ae
 #if LLVM_VERSION < 28
e4a0f2c9
     int line = (int)ctx->line ? (int)ctx->line : -1;
     int col = (int)ctx->col ? (int)ctx->col : -1;
e3a54503
     //TODO: print this ourselves, instead of using SMDiagnostic
e4a0f2c9
     SMDiagnostic diag(ctx->file, line, col,
853b6e5d
 		 "", std::string(lines->linev[ctx->line-1], lines->linev[ctx->line]-1));
65c740d7
     diag.Print("[trace]", errs());
e3a54503
 #endif
65c740d7
 }
 
2487a4a3
 int have_clamjit=1;
d0934caf
 void cli_bytecode_printversion()
 {
   cl::PrintVersionMessage();
 }
e4a0f2c9
 
2a7f1cda
 void cli_printcxxver()
 {
     /* Try to print information about some commonly used compilers */
 #ifdef __GNUC__
     printf("GNU C++: %s (%u.%u.%u)\n", __VERSION__, __GNUC__, __GNUC_MINOR__,
 	   __GNUC_PATCHLEVEL__);
 #endif
 #ifdef __INTEL_COMPILER
     printf("Intel Compiler C++ %u\n", __INTEL_COMPILER);
 #endif
 #ifdef _MSC_VER
     printf("Microsoft Visual C++ %u\n", _MSC_VER);
 #endif
 }
 
e4a0f2c9
 namespace ClamBCModule {
 void stop(const char *msg, llvm::Function* F, llvm::Instruction* I)
 {
29553b8e
     if (F && F->hasName()) {
34d8b8cf
 #if LLVM_VERSION < 31
29553b8e
 	cli_warnmsg("[Bytecode JIT] in function %s: %s", F->getNameStr().c_str(), msg);
34d8b8cf
 #else
 	cli_warnmsg("[Bytecode JIT] in function %s: %s", F->getName().str().c_str(), msg);
 #endif
29553b8e
     } else {
 	cli_warnmsg("[Bytecode JIT] %s", msg);
     }
e4a0f2c9
 }
 }
daad92ac
 
9f8df4ae
 #if LLVM_VERSION >= 29
2c859ec7
 #if LLVM_VERSION < 36
0c79cc55
 static Value *findDbgGlobalDeclare(GlobalVariable *V) {
2c859ec7
 #else
 static Metadata *findDbgGlobalDeclare(GlobalVariable *V) {
 #endif
0c79cc55
   const Module *M = V->getParent();
   NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
   if (!NMD)
     return 0;
 
   for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
     DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
     if (!DIG.isGlobalVariable())
       continue;
     if (DIGlobalVariable(DIG).getGlobal() == V)
       return DIG;
   }
   return 0;
 }
 
 /// Find the debug info descriptor corresponding to this function.
2c859ec7
 #if LLVM_VERSION < 36
0c79cc55
 static Value *findDbgSubprogramDeclare(Function *V) {
2c859ec7
 #else
 static Metadata *findDbgSubprogramDeclare(Function *V) {
 #endif
0c79cc55
   const Module *M = V->getParent();
   NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp");
   if (!NMD)
     return 0;
 
   for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
     DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
     if (!DIG.isSubprogram())
       continue;
     if (DISubprogram(DIG).getFunction() == V)
       return DIG;
   }
   return 0;
 }
 
 /// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
 /// It looks through pointer casts too.
 static const DbgDeclareInst *findDbgDeclare(const Value *V) {
   V = V->stripPointerCasts();
 
   if (!isa<Instruction>(V) && !isa<Argument>(V))
     return 0;
 
   const Function *F = NULL;
   if (const Instruction *I = dyn_cast<Instruction>(V))
     F = I->getParent()->getParent();
   else if (const Argument *A = dyn_cast<Argument>(V))
     F = A->getParent();
 
   for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
     for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
          BI != BE; ++BI)
       if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
         if (DDI->getAddress() == V)
           return DDI;
 
   return 0;
 }
 static bool getLocationInfo(const Value *V, std::string &DisplayName,
                             std::string &Type, unsigned &LineNo,
                             std::string &File, std::string &Dir) {
34d8b8cf
 #if LLVM_VERSION < 33
0c79cc55
   DICompileUnit Unit;
34d8b8cf
 #else
   StringRef G;
   StringRef H;
 #endif
4a40b53a
 #if LLVM_VERSION < 35
0c79cc55
   DIType TypeD;
4a40b53a
 #endif
   StringRef T;
0c79cc55
 
   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) {
2c859ec7
 #if LLVM_VERSION < 36
0c79cc55
     Value *DIGV = findDbgGlobalDeclare(GV);
2c859ec7
 #else
     Metadata *DIGV = findDbgGlobalDeclare(GV);
 #endif
0c79cc55
     if (!DIGV) return false;
     DIGlobalVariable Var(cast<MDNode>(DIGV));
 
     StringRef D = Var.getDisplayName();
     if (!D.empty())
       DisplayName = D;
     LineNo = Var.getLineNumber();
34d8b8cf
 #if LLVM_VERSION < 33
0c79cc55
     Unit = Var.getCompileUnit();
34d8b8cf
 #else
     G = Var.getFilename();
     H = Var.getDirectory();
 #endif
4a40b53a
 #if LLVM_VERSION < 35
0c79cc55
     TypeD = Var.getType();
4a40b53a
 #else
     T = Var.getType().getName();
 #endif
0c79cc55
   } else if (Function *F = dyn_cast<Function>(const_cast<Value*>(V))){
2c859ec7
 #if LLVM_VERSION < 36
0c79cc55
     Value *DIF = findDbgSubprogramDeclare(F);
2c859ec7
 #else
     Metadata *DIF = findDbgSubprogramDeclare(F);
 #endif
0c79cc55
     if (!DIF) return false;
     DISubprogram Var(cast<MDNode>(DIF));
 
     StringRef D = Var.getDisplayName();
     if (!D.empty())
       DisplayName = D;
     LineNo = Var.getLineNumber();
34d8b8cf
 #if LLVM_VERSION < 33
0c79cc55
     Unit = Var.getCompileUnit();
34d8b8cf
 #else
     G = Var.getFilename();
     H = Var.getDirectory();
 #endif
4a40b53a
 #if LLVM_VERSION < 35
0c79cc55
     TypeD = Var.getType();
4a40b53a
 #else
     T = Var.getType().getName();
 #endif
0c79cc55
   } else {
     const DbgDeclareInst *DDI = findDbgDeclare(V);
     if (!DDI) return false;
     DIVariable Var(cast<MDNode>(DDI->getVariable()));
 
     StringRef D = Var.getName();
     if (!D.empty())
       DisplayName = D;
     LineNo = Var.getLineNumber();
34d8b8cf
 #if LLVM_VERSION < 33
0c79cc55
     Unit = Var.getCompileUnit();
34d8b8cf
 #else
     // getFilename and getDirectory are not defined
     G = StringRef();
     H = StringRef();
 #endif
4a40b53a
 #if LLVM_VERSION < 35
0c79cc55
     TypeD = Var.getType();
4a40b53a
 #else
     T = Var.getType().getName();
 #endif
0c79cc55
   }
 
4a40b53a
 #if LLVM_VERSION < 35
   T = TypeD.getName();
 #endif
0c79cc55
   if (!T.empty())
     Type = T;
34d8b8cf
 #if LLVM_VERSION < 33
   StringRef G = Unit.getFilename();
   StringRef H = Unit.getDirectory();
 #endif
   if (!G.empty())
     File = G;
   if (!H.empty())
     Dir = H;
0c79cc55
   return true;
 }
 #endif
 
daad92ac
 void printValue(llvm::Value *V, bool a, bool b) {
     std::string DisplayName;
     std::string Type;
     unsigned Line;
     std::string File;
     std::string Dir;
     if (!getLocationInfo(V, DisplayName, Type, Line, File, Dir)) {
 	errs() << *V << "\n";
 	return;
     }
     errs() << "'" << DisplayName << "' (" << File << ":" << Line << ")";
 }
 
 void printLocation(llvm::Instruction *I, bool a, bool b) {
     if (MDNode *N = I->getMetadata("dbg")) {
 	DILocation Loc(N);
 	errs() << Loc.getFilename() << ":" << Loc.getLineNumber();
 	if (unsigned Col = Loc.getColumnNumber()) {
   	    errs() << ":" << Col;
   	}
   	errs() << ": ";
   	return;
     }
     errs() << *I << ":\n";
 }