[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/nolankramer/daScript/master/src/simulate/simulate_exceptions.cpp [Back]  [Original]

#include "daScript/misc/platform.h"

#include "daScript/simulate/simulate.h"
#include "daScript/simulate/aot.h"
#include "daScript/simulate/simulate_nodes.h"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4611)
#endif

/*
    NOTE: this should be the only file where daslang needs exceptions enabled.
*/

namespace das {
    static void stackWalkToErr(Context & ctx, const LineInfo & at, bool showArguments, bool showLocalVariables) {
        const das::string stack = ctx.getStackWalk(&at, showArguments, showLocalVariables);
        ctx.to_err(&at, stack.c_str());
    }

    void Context::throw_fatal_error ( const char * message, const LineInfo & at ) {
        exceptionMessage = message ? message : "";
        exceptionMessage += "\n";
        exception = exceptionMessage.c_str();
        exceptionAt = at;
#if DAS_ENABLE_EXCEPTIONS
        if ( alwaysErrorOnException ) {
            to_err(&at, exception);
        }
        if ( alwaysStackWalkOnException ) {
            stackWalkToErr(*this, at, showArgumentsOnException, showLocalVariablesOnException);
        }
        if ( breakOnException ) breakPoint(at, "exception", exception);
        throw dasException(exception, at);
#else
        if ( throwBuf ) {
            if ( alwaysErrorOnException ) {
                to_err(&at, exception);
            }
            if ( alwaysStackWalkOnException ) {
                stackWalkToErr(*this, at, showArgumentsOnException, showLocalVariablesOnException);
            }
            if ( breakOnException ) breakPoint(at, "exception", exception);
#if defined(WIN64) || defined(_WIN64)
            //  "An invalid or unaligned stack was encountered during an unwind operation." exception is issued via longjmp
            //  this is a known issue with longjmp on x64, and this workaround disables stack unwinding
            ((_JUMP_BUFFER *)throwBuf)->Frame = 0;
#endif
            longjmp(*throwBuf,1);
        } else {
            string msg = "\nunhandled exception\n" + exceptionAt.describe() + ": " + exception;
            to_err(&at, msg.c_str());
            stackWalkToErr(*this, at, showArgumentsOnException, showLocalVariablesOnException);
            breakPoint(at, "exception", exception);
        }
#endif
#if !defined(_MSC_VER) || (_MSC_VER>1900)
        exit(0);
#endif
    }

    void Context::rethrow () {
#if DAS_ENABLE_EXCEPTIONS
        throw dasException(exception ? exception : "", exceptionAt);
#else
        if ( throwBuf ) {
#if defined(WIN64) || defined(_WIN64)
            //  "An invalid or unaligned stack was encountered during an unwind operation." exception is issued via longjmp
            //  this is a known issue with longjmp on x64, and this workaround disables stack unwinding
            ((_JUMP_BUFFER *)throwBuf)->Frame = 0;
#endif

            longjmp(*throwBuf,1);
        } else {
            if ( exception ) {
                string msg = "\nunhandled exception\n" + exceptionAt.describe() + ": " + exception + "\n";
                to_err(nullptr, msg.c_str());
            } else {
                to_err(nullptr, "\nunhandled exception\n");
            }
            stackWalk(nullptr, false, false);
            os_debug_break();
        }
#endif
#if !defined(_MSC_VER) || (_MSC_VER>1900)
        exit(0);
#endif
    }

    vec4f WIN_EH_NO_ASAN Context::evalWithCatch ( SimNode * node ) {
        auto aa = abiArg;
        auto acm = abiCMRES;
        auto atba = abiThisBlockArg;
        char * EP, * SP;
        stack.watermark(EP,SP);
        vec4f vres = v_zero();
#if DAS_ENABLE_EXCEPTIONS
        try {
            vres = node->eval(*this);
        } catch ( const dasException & ex ) {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
            exceptionMessage = ex.what();
            exception = exceptionMessage.c_str();
            exceptionAt = ex.exceptionAt;
        }
#else
        jmp_buf ev;
        jmp_buf * JB = throwBuf;
        throwBuf = &ev;
        if ( !setjmp(ev) ) {
            vres = node->eval(*this);
        } else {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
        }
        throwBuf = JB;
#endif
        return vres;
    }

    bool WIN_EH_NO_ASAN Context::runWithCatch ( const callable & subexpr ) {
        auto aa = abiArg;
        auto acm = abiCMRES;
        auto atba = abiThisBlockArg;
        char * EP, * SP;
        stack.watermark(EP,SP);
        bool bres = false;
#if DAS_ENABLE_EXCEPTIONS
        try {
            subexpr();
            bres = true;
        } catch ( const dasException & ex ) {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
            exceptionMessage = ex.what();
            exception = exceptionMessage.c_str();
            exceptionAt = ex.exceptionAt;
        }
#else
        jmp_buf ev;
        jmp_buf * JB = throwBuf;
        throwBuf = &ev;
        if ( !setjmp(ev) ) {
            subexpr();
            bres = true;
        } else {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
        }
        throwBuf = JB;
#endif
        return bres;
    }

    vec4f WIN_EH_NO_ASAN Context::evalWithCatch ( SimFunction * fnPtr, vec4f * args, void * res ) {
        auto aa = abiArg;
        auto acm = abiCMRES;
        auto atba = abiThisBlockArg;
        char * EP, * SP;
        stack.watermark(EP,SP);
        vec4f vres = v_zero();
#if DAS_ENABLE_EXCEPTIONS
        try {
            vres = callWithCopyOnReturn(fnPtr, args, res, 0);
        } catch ( const dasException & ex ) {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
            exceptionMessage = ex.what();
            exception = exceptionMessage.c_str();
            exceptionAt = ex.exceptionAt;
        }
#else
        jmp_buf ev;
        jmp_buf * JB = throwBuf;
        throwBuf = &ev;
        if ( !setjmp(ev) ) {
            vres = callWithCopyOnReturn(fnPtr, args, res, 0);
        } else {
            abiArg = aa;
            abiCMRES = acm;
            abiThisBlockArg = atba;
            stack.pop(EP,SP);
        }
        throwBuf = JB;
#endif
        return vres;
    }

    // SimNode_TryCatch

    vec4f WIN_EH_NO_ASAN SimNode_TryCatch::eval ( Context & context ) {
        DAS_PROFILE_NODE
        auto aa = context.abiArg; auto acm = context.abiCMRES;
        char * EP, * SP;
        context.stack.watermark(EP,SP);
        #if DAS_ENABLE_EXCEPTIONS
            try {
                try_block->eval(context);
            } catch ( const dasException & ) {
                context.abiArg = aa;
                context.abiCMRES = acm;
                context.stack.pop(EP,SP);
                context.stopFlags = 0;
                context.last_exception = context.exception;
                context.exception = nullptr;
                catch_block->eval(context);
            }
        #else
            jmp_buf ev;
            jmp_buf * JB = context.throwBuf;
            context.throwBuf = &ev;
            if ( !setjmp(ev) ) {
                try_block->eval(context);
            } else {
                context.throwBuf = JB;
                context.abiArg = aa;
                context.abiCMRES = acm;
                context.stack.pop(EP,SP);
                context.stopFlags = 0;
                context.last_exception = context.exception;
                context.exception = nullptr;
                catch_block->eval(context);
            }
            context.throwBuf = JB;
        #endif
        return v_zero();
    }

#if DAS_DEBUGGER
    vec4f WIN_EH_NO_ASAN SimNodeDebug_TryCatch::eval ( Context & context ) {
        DAS_PROFILE_NODE
        auto aa = context.abiArg; auto acm = context.abiCMRES;
        char * EP, * SP;
        context.stack.watermark(EP,SP);
        #if DAS_ENABLE_EXCEPTIONS
            try {
                DAS_SINGLE_STEP(context,try_block->debugInfo,false);
                try_block->eval(context);
            } catch ( const dasException & ) {
                context.abiArg = aa;
                context.abiCMRES = acm;
                context.stack.pop(EP,SP);
                context.stopFlags = 0;
                context.last_exception = context.exception;
                context.exception = nullptr;
                DAS_SINGLE_STEP(context,catch_block->debugInfo,false);
                catch_block->eval(context);
            }
        #else
            jmp_buf ev;
            jmp_buf * JB = context.throwBuf;
            context.throwBuf = &ev;
            if ( !setjmp(ev) ) {
                DAS_SINGLE_STEP(context,try_block->debugInfo,false);
                try_block->eval(context);
            } else {
                context.throwBuf = JB;
                context.abiArg = aa;
                context.abiCMRES = acm;
                context.stack.pop(EP,SP);
                context.stopFlags = 0;
                context.last_exception = context.exception;
                context.exception = nullptr;
                DAS_SINGLE_STEP(context,catch_block->debugInfo,false);
                catch_block->eval(context);
            }
            context.throwBuf = JB;
        #endif
        return v_zero();
    }
#endif

    void WIN_EH_NO_ASAN das_try_recover ( Context * __context__, const callable & try_block, const callable & catch_block ) {
        auto aa = __context__->abiArg; auto acm = __context__->abiCMRES;
        char * EP, * SP;
        __context__->stack.watermark(EP,SP);
#if DAS_ENABLE_EXCEPTIONS
        try {
            try_block();
        } catch ( const dasException & ) {
            catch_block();
            __context__->abiArg = aa;
            __context__->abiCMRES = acm;
            __context__->stack.pop(EP,SP);
            __context__->stopFlags = 0;
            __context__->last_exception = __context__->exception;
            __context__->exception = nullptr;
        }
#else
        jmp_buf ev;
        jmp_buf * JB = __context__->throwBuf;
        __context__->throwBuf = &ev;
        if ( !setjmp(ev) ) {
            try_block();
        } else {
            catch_block();
            __context__->throwBuf = JB;
            __context__->abiArg = aa;
            __context__->abiCMRES = acm;
            __context__->stack.pop(EP,SP);
            __context__->stopFlags = 0;
            __context__->last_exception = __context__->exception;
            __context__->exception = nullptr;
        }
        __context__->throwBuf = JB;
#endif
    }

    void WIN_EH_NO_ASAN builtin_try_recover ( const Block & try_block, const Block & catch_block, Context * context, LineInfoArg * at ) {
        auto aa = context->abiArg; auto acm = context->abiCMRES;
        char * EP, * SP;
        context->stack.watermark(EP,SP);
        #if DAS_ENABLE_EXCEPTIONS
            try {
                context->invoke(try_block, nullptr, nullptr, at);
            } catch ( const dasException & ) {
                context->abiArg = aa;
                context->abiCMRES = acm;
                context->stack.pop(EP,SP);
                context->stopFlags = 0;
                context->last_exception = context->exception;
                context->exception = nullptr;
                context->invoke(catch_block,nullptr,nullptr, at);
            }
        #else
            jmp_buf ev;
            jmp_buf * JB = context->throwBuf;
            context->throwBuf = &ev;
            if ( !setjmp(ev) ) {
                context->invoke(try_block,nullptr,nullptr, at);
            } else {
                context->throwBuf = JB;
                context->abiArg = aa;
                context->abiCMRES = acm;
                context->stack.pop(EP,SP);
                context->stopFlags = 0;
                context->last_exception = context->exception;
                context->exception = nullptr;
                context->invoke(catch_block,nullptr,nullptr, at);
            }
            context->throwBuf = JB;
        #endif
    }
}

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

Web Proxy Viewer  |  New URL  |  Original Page