bool bailed_out() const                        { return compilation()->bailed_out(); }
 // unified bailout support
 void bailout(const char* msg) const            { compilation()->bailout(msg); }
Ejemplo n.º 3
0
 void increment_invocation_counter(CodeEmitInfo *info) {
   if (compilation()->count_invocations()) {
     increment_event_counter(info, InvocationEntryBci, false);
   }
 }
Ejemplo n.º 4
0
 void increment_backedge_counter(CodeEmitInfo* info, int bci) {
   if (compilation()->count_backedges()) {
     increment_event_counter(info, bci, true);
   }
 }
Ejemplo n.º 5
0
void LIR_Assembler::emit_op1(LIR_Op1* op) {
    switch (op->code()) {
    case lir_move:
        if (op->move_kind() == lir_move_volatile) {
            assert(op->patch_code() == lir_patch_none, "can't patch volatiles");
            volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info());
        } else {
            move_op(op->in_opr(), op->result_opr(), op->type(),
                    op->patch_code(), op->info(), op->pop_fpu_stack(),
                    op->move_kind() == lir_move_unaligned,
                    op->move_kind() == lir_move_wide);
        }
        break;

    case lir_roundfp: {
        LIR_OpRoundFP* round_op = op->as_OpRoundFP();
        roundfp_op(round_op->in_opr(), round_op->tmp(), round_op->result_opr(), round_op->pop_fpu_stack());
        break;
    }

    case lir_return:
        return_op(op->in_opr());
        break;

    case lir_safepoint:
        if (compilation()->debug_info_recorder()->last_pc_offset() == code_offset()) {
            _masm->nop();
        }
        safepoint_poll(op->in_opr(), op->info());
        break;

    case lir_fxch:
        fxch(op->in_opr()->as_jint());
        break;

    case lir_fld:
        fld(op->in_opr()->as_jint());
        break;

    case lir_ffree:
        ffree(op->in_opr()->as_jint());
        break;

    case lir_branch:
        break;

    case lir_push:
        push(op->in_opr());
        break;

    case lir_pop:
        pop(op->in_opr());
        break;

    case lir_neg:
        negate(op->in_opr(), op->result_opr());
        break;

    case lir_leal:
        leal(op->in_opr(), op->result_opr());
        break;

    case lir_null_check:
        if (GenerateCompilerNullChecks) {
            ImplicitNullCheckStub* stub = add_debug_info_for_null_check_here(op->info());

            if (op->in_opr()->is_single_cpu()) {
                _masm->null_check(op->in_opr()->as_register(), stub->entry());
            } else {
                Unimplemented();
            }
        }
        break;

    case lir_monaddr:
        monitor_address(op->in_opr()->as_constant_ptr()->as_jint(), op->result_opr());
        break;

#ifdef SPARC
    case lir_pack64:
        pack64(op->in_opr(), op->result_opr());
        break;

    case lir_unpack64:
        unpack64(op->in_opr(), op->result_opr());
        break;
#endif

    case lir_unwind:
        unwind_op(op->in_opr());
        break;

    default:
        Unimplemented();
        break;
    }
}
Ejemplo n.º 6
0
void LIR_Assembler::emit_op0(LIR_Op0* op) {
    switch (op->code()) {
    case lir_word_align: {
        _masm->align(BytesPerWord);
        break;
    }

    case lir_nop:
        assert(op->info() == NULL, "not supported");
        _masm->nop();
        break;

    case lir_label:
        Unimplemented();
        break;

    case lir_build_frame:
        build_frame();
        break;

    case lir_std_entry:
        // init offsets
        offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset());
        _masm->align(CodeEntryAlignment);
        if (needs_icache(compilation()->method())) {
            check_icache();
        }
        offsets()->set_value(CodeOffsets::Verified_Entry, _masm->offset());
        _masm->verified_entry();
        build_frame();
        offsets()->set_value(CodeOffsets::Frame_Complete, _masm->offset());
        break;

    case lir_osr_entry:
        offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset());
        osr_entry();
        break;

    case lir_24bit_FPU:
        set_24bit_FPU();
        break;

    case lir_reset_FPU:
        reset_FPU();
        break;

    case lir_breakpoint:
        breakpoint();
        break;

    case lir_fpop_raw:
        fpop();
        break;

    case lir_membar:
        membar();
        break;

    case lir_membar_acquire:
        membar_acquire();
        break;

    case lir_membar_release:
        membar_release();
        break;

    case lir_membar_loadload:
        membar_loadload();
        break;

    case lir_membar_storestore:
        membar_storestore();
        break;

    case lir_membar_loadstore:
        membar_loadstore();
        break;

    case lir_membar_storeload:
        membar_storeload();
        break;

    case lir_get_thread:
        get_thread(op->result_opr());
        break;

    default:
        ShouldNotReachHere();
        break;
    }
}
Ejemplo n.º 7
0
bool CompilerEngine::compileCode(const QString &pCode)
{
    // Reset our compiler engine

    reset();

    // Determine our target triple
    // Note: normally, we would call llvm::sys::getProcessTriple(), but this
    //       returns the information about the system on which LLVM was built.
    //       In most cases it is fine, but on OS X it may be a problem. Indeed,
    //       with OS X 10.9, Apple decided to extend the C standard by adding
    //       some functions (e.g. __exp10()). So, if the given code needs one of
    //       those functions, then OpenCOR will crash if run on an 'old' version
    //       of OS X. So, to avoid this issue, we set the target triple
    //       ourselves, based on the system on which OpenCOR is being used...

    std::string targetTriple;

#if defined(Q_OS_WIN)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-windows-msvc-elf":"x86_64-pc-windows-msvc-elf";
    // Note: MCJIT currently works only through the ELF object format, hence we
    //       are appending "-elf"...
#elif defined(Q_OS_LINUX)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-linux-gnu":"x86_64-pc-linux-gnu";
#elif defined(Q_OS_MAC)
    targetTriple = "x86_64-apple-darwin"+std::to_string(QSysInfo::MacintoshVersion+2);
#else
    #error Unsupported platform
#endif

    // Get a driver to compile our code

#ifdef QT_DEBUG
    llvm::raw_ostream &outputStream = llvm::outs();
#else
    llvm::raw_ostream &outputStream = llvm::nulls();
#endif
    llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOptions = new clang::DiagnosticOptions();

    clang::DiagnosticsEngine diagnosticsEngine(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()),
                                               &*diagnosticOptions,
                                               new clang::TextDiagnosticPrinter(outputStream, &*diagnosticOptions));

    clang::driver::Driver driver("clang", targetTriple, diagnosticsEngine);

    driver.setCheckInputsExist(false);

    // Get a compilation object to which we pass some arguments

    llvm::StringRef dummyFileName("dummyFile.c");

    llvm::SmallVector<const char *, 16> compilationArguments;

    compilationArguments.push_back("clang");
    compilationArguments.push_back("-fsyntax-only");
    compilationArguments.push_back("-O3");
    compilationArguments.push_back("-ffast-math");
    compilationArguments.push_back("-Werror");
    compilationArguments.push_back(dummyFileName.data());

    std::unique_ptr<clang::driver::Compilation> compilation(driver.BuildCompilation(compilationArguments));

    if (!compilation) {
        mError = tr("the compilation object could not be created");

        return false;
    }

    // The compilation object should have only one command, so if it doesn't
    // then something went wrong

    const clang::driver::JobList &jobList = compilation->getJobs();

    if (    (jobList.size() != 1)
        || !llvm::isa<clang::driver::Command>(*jobList.begin())) {
        mError = tr("the compilation object must contain only one command");

        return false;
    }

    // Retrieve the command job

    const clang::driver::Command &command = llvm::cast<clang::driver::Command>(*jobList.begin());
    QString commandName = command.getCreator().getName();

    if (commandName.compare("clang")) {
        mError = tr("a <strong>clang</strong> command was expected, but a <strong>%1</strong> command was found instead").arg(commandName);

        return false;
    }

    // Create a compiler invocation using our command's arguments

    const clang::driver::ArgStringList &commandArguments = command.getArguments();
    std::unique_ptr<clang::CompilerInvocation> compilerInvocation(new clang::CompilerInvocation());

    clang::CompilerInvocation::CreateFromArgs(*compilerInvocation,
                                              commandArguments.data(),
                                              commandArguments.data()+commandArguments.size(),
                                              diagnosticsEngine);

    // Map our dummy file to a memory buffer

    QByteArray codeByteArray = pCode.toUtf8();

    compilerInvocation->getPreprocessorOpts().addRemappedFile(dummyFileName, llvm::MemoryBuffer::getMemBuffer(codeByteArray.constData()).release());

    // Create a compiler instance to handle the actual work

    clang::CompilerInstance compilerInstance;

    compilerInstance.setInvocation(compilerInvocation.release());

    // Create the compiler instance's diagnostics engine

    compilerInstance.createDiagnostics();

    if (!compilerInstance.hasDiagnostics()) {
        mError = tr("the diagnostics engine could not be created");

        return false;
    }

    // Create and execute the frontend to generate an LLVM bitcode module
    // Note: the LLVM team has been meaning to modify
    //       CompilerInstance::ExecuteAction() so that we could specify the
    //       output stream we want to use (rather than always use llvm::errs()),
    //       but they have yet to actually do it, so we modified it ourselves...

    std::unique_ptr<clang::CodeGenAction> codeGenerationAction(new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext()));

    if (!compilerInstance.ExecuteAction(*codeGenerationAction, outputStream)) {
        mError = tr("the code could not be compiled");

        reset(false);

        return false;
    }

    // Retrieve the LLVM bitcode module

    std::unique_ptr<llvm::Module> module = codeGenerationAction->takeModule();

    // Initialise the native target (and its ASM printer), so not only can we
    // then create an execution engine, but more importantly its data layout
    // will match that of our target platform

    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();

    // Create and keep track of an execution engine

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>(llvm::EngineBuilder(std::move(module)).setEngineKind(llvm::EngineKind::JIT).create());

    if (!mExecutionEngine) {
        mError = tr("the execution engine could not be created");

        delete module.release();

        return false;
    }

    return true;
}
Ejemplo n.º 8
0
 ciMethod* method() const                       { return compilation()->method(); }
Ejemplo n.º 9
0
 ValueStack* copy_state_if_bb(bool is_bb) {
     return (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
 }
Ejemplo n.º 10
0
 ValueStack* copy_state_indexed_access() {
     return compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception();
 }
void LIRGenerator::do_Base(Base* x) {
  emit()->std_entry(scope(), compilation()->get_init_vars(), receiverRInfo(), icKlassRInfo());
}
 // Compute a CPData offset for the current method & bci
 int find_cpdoff() const { 
   return compilation()->get_cpdata() + sizeof(CodeProfile) + method()->bci2cpd_map()->bci_to_cpdoff(bci());
 }
void LIR_Assembler::add_debug_info_for_branch(CodeEmitInfo* info) {
  masm()->add_dbg( code_offset(), info->debug_scope() );
  if (info->exception_handlers() != NULL) {
compilation()->add_exception_handlers_for_pco(code_offset(),info->exception_handlers());
  }
}
Ejemplo n.º 14
0
bool Compiler::addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
{
    Q_D(Compiler);
    const QString &importUri = stringAt(import->uriIndex);
    const QString &importQualifier = stringAt(import->qualifierIndex);

    if (import->type == QV4::CompiledData::Import::ImportScript) {
        // TBD: qqmltypeloader.cpp:1320
        QmlCompilation::ScriptReference scriptRef;
        scriptRef.location = import->location;
        scriptRef.qualifier = importQualifier;
        scriptRef.compilation = NULL;
        d->compilation->scripts.append(scriptRef);
    } else if (import->type == QV4::CompiledData::Import::ImportLibrary) {
        QString qmldirFilePath;
        QString qmldirUrl;
        if (QQmlMetaType::isLockedModule(importUri, import->majorVersion)) {
            //Locked modules are checked first, to save on filesystem checks
            if (!d->compilation->importCache->addLibraryImport(d->compilation->importDatabase, importUri, importQualifier, import->majorVersion,
                                          import->minorVersion, QString(), QString(), false, errors))
                return false;

        } else if (d->compilation->importCache->locateQmldir(d->compilation->importDatabase, importUri, import->majorVersion, import->minorVersion,
                                 &qmldirFilePath, &qmldirUrl)) {
            // This is a local library import
            if (!d->compilation->importCache->addLibraryImport(d->compilation->importDatabase, importUri, importQualifier, import->majorVersion,
                                          import->minorVersion, qmldirFilePath, qmldirUrl, false, errors))
                return false;

            if (!importQualifier.isEmpty()) {
                // Does this library contain any qualified scripts?
                QUrl libraryUrl(qmldirUrl);
                QQmlTypeLoader* typeLoader = &QQmlEnginePrivate::get(d->compilation->engine)->typeLoader;
                const QQmlTypeLoader::QmldirContent *qmldir = typeLoader->qmldirContent(qmldirFilePath, qmldirUrl);
                // File loading will import the dependency and takes care of
                // everything there. Adding a script reference here just seems
                // to add an unnecessary reference that might actually be a bug.
                // In case something is needed, see: qqmltypeloader.cpp:1343
            }
        } else {
            // Is this a module?
            qDebug() << "Importing local module" << importUri;
            if (QQmlMetaType::isAnyModule(importUri)) {
                if (!d->compilation->importCache->addLibraryImport(d->compilation->importDatabase, importUri, importQualifier, import->majorVersion,
                                              import->minorVersion, QString(), QString(), false, errors))
                    return false;
            } else {
                QQmlError error;
                error.setDescription("Unresolved import " + importUri);
                error.setLine(import->location.line);
                error.setColumn(import->location.column);
                error.setUrl(d->compilation->url);
                appendError(error);
                return false;
                // TBD: else add to unresolved imports qqmltypeloader.cpp:1356
            }
        }
    } else {
        // qqmltypeloader.cpp:1383
        Q_ASSERT(import->type == QV4::CompiledData::Import::ImportFile);

        QUrl qmldirUrl;
        if (importQualifier.isEmpty()) {
            qmldirUrl = compilation()->loadUrl.resolved(QUrl(importUri + QLatin1String("/qmldir")));
            if (!QQmlImports::isLocal(qmldirUrl)) {
                qDebug() << "File import from network not supported";
                QQmlError error;
                error.setDescription("File import from network not supported");
                errors->append(error);
                return false;
            }
        }

        if (!compilation()->importCache->addFileImport(compilation()->importDatabase, importUri, importQualifier, import->majorVersion,
                                   import->minorVersion, /*incomplete*/ false, errors))
            return false;
    }
    return true;
}
Ejemplo n.º 15
0
bool CompilerEngine::compileCode(const QString &pCode)
{
    // Prepend all the external functions that may, or not, be needed by the
    // given code
    // Note: indeed, we cannot include header files since we don't (and don't
    //       want in order to avoid complications) deploy them with OpenCOR. So,
    //       instead, we must declare as external functions all the functions
    //       that we would normally use through header files...

    QString code =  "extern double fabs(double);\n"
                    "\n"
                    "extern double log(double);\n"
                    "extern double exp(double);\n"
                    "\n"
                    "extern double floor(double);\n"
                    "extern double ceil(double);\n"
                    "\n"
                    "extern double factorial(double);\n"
                    "\n"
                    "extern double sin(double);\n"
                    "extern double sinh(double);\n"
                    "extern double asin(double);\n"
                    "extern double asinh(double);\n"
                    "\n"
                    "extern double cos(double);\n"
                    "extern double cosh(double);\n"
                    "extern double acos(double);\n"
                    "extern double acosh(double);\n"
                    "\n"
                    "extern double tan(double);\n"
                    "extern double tanh(double);\n"
                    "extern double atan(double);\n"
                    "extern double atanh(double);\n"
                    "\n"
                    "extern double sec(double);\n"
                    "extern double sech(double);\n"
                    "extern double asec(double);\n"
                    "extern double asech(double);\n"
                    "\n"
                    "extern double csc(double);\n"
                    "extern double csch(double);\n"
                    "extern double acsc(double);\n"
                    "extern double acsch(double);\n"
                    "\n"
                    "extern double cot(double);\n"
                    "extern double coth(double);\n"
                    "extern double acot(double);\n"
                    "extern double acoth(double);\n"
                    "\n"
                    "extern double arbitrary_log(double, double);\n"
                    "\n"
                    "extern double pow(double, double);\n"
                    "\n"
                    "extern double multi_min(int, ...);\n"
                    "extern double multi_max(int, ...);\n"
                    "\n"
                    "extern double gcd_multi(int, ...);\n"
                    "extern double lcm_multi(int, ...);\n"
                    "\n"
                   +pCode;

    // Reset our compiler engine

    reset();

    // Determine our target triple
    // Note: normally, we would call llvm::sys::getProcessTriple(), but this
    //       returns the information about the system on which LLVM was built.
    //       In most cases it is fine, but on OS X it may be a problem. Indeed,
    //       with OS X 10.9, Apple decided to extend the C standard by adding
    //       some functions (e.g. __exp10()). So, if the given code needs one of
    //       those functions, then OpenCOR will crash if run on an 'old' version
    //       of OS X. So, to avoid this issue, we set the target triple
    //       ourselves, based on the system on which OpenCOR is to be used...

    std::string targetTriple;

#if defined(Q_OS_WIN)
    targetTriple = "x86_64-pc-windows-msvc-elf";
    // Note: MCJIT currently works only through the ELF object format, hence we
    //       are appending "-elf"...
#elif defined(Q_OS_LINUX)
    targetTriple = "x86_64-pc-linux-gnu";
#elif defined(Q_OS_MAC)
    targetTriple = "x86_64-apple-darwin"+std::to_string(QSysInfo::MacintoshVersion+2);
#else
    #error Unsupported platform
#endif

    // Get a driver to compile our code

    llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOptions = new clang::DiagnosticOptions();
    clang::DiagnosticsEngine diagnosticsEngine(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()),
                                               &*diagnosticOptions);
    clang::driver::Driver driver("clang", targetTriple, diagnosticsEngine);

    driver.setCheckInputsExist(false);

    // Get a compilation object to which we pass some arguments

    llvm::StringRef dummyFileName("dummyFile.c");
    llvm::SmallVector<const char *, 16> compilationArguments;

    compilationArguments.push_back("clang");
    compilationArguments.push_back("-fsyntax-only");
    compilationArguments.push_back("-O3");
    compilationArguments.push_back("-ffast-math");
    compilationArguments.push_back("-Werror");
    compilationArguments.push_back(dummyFileName.data());

    std::unique_ptr<clang::driver::Compilation> compilation(driver.BuildCompilation(compilationArguments));

    if (!compilation) {
        mError = tr("the compilation object could not be created");

        return false;
    }

    // The compilation object should have only one command, so if it doesn't
    // then something went wrong

    const clang::driver::JobList &jobList = compilation->getJobs();

    if (    (jobList.size() != 1)
        || !llvm::isa<clang::driver::Command>(*jobList.begin())) {
        mError = tr("the compilation object must contain only one command");

        return false;
    }

    // Retrieve the command job

    const clang::driver::Command &command = llvm::cast<clang::driver::Command>(*jobList.begin());
    QString commandName = command.getCreator().getName();

    if (commandName.compare("clang")) {
        mError = tr("a <strong>clang</strong> command was expected, but a <strong>%1</strong> command was found instead").arg(commandName);

        return false;
    }

    // Create a compiler invocation using our command's arguments

    const clang::driver::ArgStringList &commandArguments = command.getArguments();
    std::unique_ptr<clang::CompilerInvocation> compilerInvocation(new clang::CompilerInvocation());

    clang::CompilerInvocation::CreateFromArgs(*compilerInvocation,
                                              commandArguments.data(),
                                              commandArguments.data()+commandArguments.size(),
                                              diagnosticsEngine);

    // Map our dummy file to a memory buffer

    QByteArray codeByteArray = code.toUtf8();

    compilerInvocation->getPreprocessorOpts().addRemappedFile(dummyFileName, llvm::MemoryBuffer::getMemBuffer(codeByteArray.constData()).release());

    // Create a compiler instance to handle the actual work

    clang::CompilerInstance compilerInstance;

    compilerInstance.setInvocation(compilerInvocation.release());

    // Create the compiler instance's diagnostics engine

    compilerInstance.createDiagnostics();

    if (!compilerInstance.hasDiagnostics()) {
        mError = tr("the diagnostics engine could not be created");

        return false;
    }

    // Create and execute the frontend to generate an LLVM bitcode module

    std::unique_ptr<clang::CodeGenAction> codeGenerationAction(new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext()));

    if (!compilerInstance.ExecuteAction(*codeGenerationAction)) {
        mError = tr("the code could not be compiled");

        reset(false);

        return false;
    }

    // Retrieve the LLVM bitcode module

    std::unique_ptr<llvm::Module> module = codeGenerationAction->takeModule();

    // Initialise the native target (and its ASM printer), so not only can we
    // then create an execution engine, but more importantly its data layout
    // will match that of our target platform

    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();

    // Create and keep track of an execution engine

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>(llvm::EngineBuilder(std::move(module)).setEngineKind(llvm::EngineKind::JIT).create());

    if (!mExecutionEngine) {
        mError = tr("the execution engine could not be created");

        delete module.release();

        return false;
    }

    // Map all the external functions that may, or not, be needed by the given
    // code

#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
    #define FUNCTION_NAME(x) (x)
#elif defined(Q_OS_MAC)
    #define FUNCTION_NAME(x) (std::string(std::string("_")+(x)).c_str())
#else
    #error Unsupported platform
#endif

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("fabs"), (uint64_t) compiler_fabs);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("log"), (uint64_t) compiler_log);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("exp"), (uint64_t) compiler_exp);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("floor"), (uint64_t) compiler_floor);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("ceil"), (uint64_t) compiler_ceil);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("factorial"), (uint64_t) compiler_factorial);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("sin"), (uint64_t) compiler_sin);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("sinh"), (uint64_t) compiler_sinh);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("asin"), (uint64_t) compiler_asin);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("asinh"), (uint64_t) compiler_asinh);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("cos"), (uint64_t) compiler_cos);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("cosh"), (uint64_t) compiler_cosh);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acos"), (uint64_t) compiler_acos);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acosh"), (uint64_t) compiler_acosh);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("tan"), (uint64_t) compiler_tan);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("tanh"), (uint64_t) compiler_tanh);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("atan"), (uint64_t) compiler_atan);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("atanh"), (uint64_t) compiler_atanh);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("sec"), (uint64_t) compiler_sec);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("sech"), (uint64_t) compiler_sech);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("asec"), (uint64_t) compiler_asec);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("asech"), (uint64_t) compiler_asech);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("csc"), (uint64_t) compiler_csc);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("csch"), (uint64_t) compiler_csch);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acsc"), (uint64_t) compiler_acsc);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acsch"), (uint64_t) compiler_acsch);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("cot"), (uint64_t) compiler_cot);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("coth"), (uint64_t) compiler_coth);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acot"), (uint64_t) compiler_acot);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("acoth"), (uint64_t) compiler_acoth);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("arbitrary_log"), (uint64_t) compiler_arbitrary_log);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("pow"), (uint64_t) compiler_pow);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("multi_min"), (uint64_t) compiler_multi_min);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("multi_max"), (uint64_t) compiler_multi_max);

    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("gcd_multi"), (uint64_t) compiler_gcd_multi);
    mExecutionEngine->addGlobalMapping(FUNCTION_NAME("lcm_multi"), (uint64_t) compiler_lcm_multi);

    return true;
}