Ejemplo n.º 1
0
        protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics)
        {
            //Jumps need special treatment for label resolution

            if (Instruction.Arguments == -1)
            {
                switch (Instruction.OpCode)
                {
                    case OpCode.jump:
                        target.EmitJump(Position, Instruction.Id);
                        break;
                    case OpCode.jump_t:
                        target.EmitJumpIfTrue(Position, Instruction.Id);
                        break;
                    case OpCode.jump_f:
                        target.EmitJumpIfFalse(Position, Instruction.Id);
                        break;
                    case OpCode.leave:
                        target.EmitLeave(Position, Instruction.Id);
                        break;
                    default:
                        goto emitNormally;
                }
            }
            else
                goto emitNormally;

            return;
            emitNormally:
            target.Emit(Position, Instruction);
        }
Ejemplo n.º 2
0
        protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics)
        {
            if(stackSemantics == StackSemantics.Value)
                throw new NotSupportedException("Try-catch-finally blocks cannot be used with value stack semantics (They don't produce values)");

            var prefix = "try\\" + Guid.NewGuid().ToString("N") + "\\";
            var beginTryLabel = prefix + "beginTry";
            var beginFinallyLabel = prefix + "beginFinally";
            var beginCatchLabel = prefix + "beginCatch";
            var endTry = prefix + "endTry";

            if (TryBlock.IsEmpty)
                if (FinallyBlock.IsEmpty)
                    return;
                else
                {
                    //The finally block is not protected
                    //  A trycatchfinally with just a finally block is equivalent to the contents of the finally block
                    //  " try {} finally { $code } " => " $code "
                    FinallyBlock.EmitEffectCode(target);
                    return;
                }

            //Emit try block
            target.EmitLabel(Position, beginTryLabel);
            target.Emit(Position,OpCode.@try);
            TryBlock.EmitEffectCode(target);

            //Emit finally block
            target.EmitLabel(FinallyBlock.Position, beginFinallyLabel);
            var beforeEmit = target.Code.Count;
            FinallyBlock.EmitEffectCode(target);
            if (FinallyBlock.Count > 0 && target.Code.Count == beforeEmit)
                target.Emit(FinallyBlock.Position, OpCode.nop);
            target.EmitLeave(FinallyBlock.Position, endTry);

            //Emit catch block
            target.EmitLabel(CatchBlock.Position, beginCatchLabel);
            var usesException = ExceptionVar != null;
            var justRethrow = CatchBlock.IsEmpty && !usesException;

            if (usesException)
            {
                //Assign exception
                ExceptionVar = _GetOptimizedNode(target, ExceptionVar) as AstGetSet ?? ExceptionVar;
                ExceptionVar.Arguments.Add(new AstGetException(File, Line, Column));
                ExceptionVar.Call = PCall.Set;
                ExceptionVar.EmitEffectCode(target);
            }

            if (!justRethrow)
            {
                //Exception handled
                CatchBlock.EmitEffectCode(target);
            }
            else
            {
                //Exception not handled => rethrow.
                // * Rethrow is implemented in the runtime *
                //AstThrow th = new AstThrow(File, Line, Column);
                //th.Expression = new AstGetException(File, Line, Column);
                //th.EmitCode(target);
            }

            target.EmitLabel(Position, endTry);
            target.Emit(Position,OpCode.nop);

            var block =
                new TryCatchFinallyBlock(
                    _getAddress(target, beginTryLabel), _getAddress(target, endTry))
                    {
                        BeginFinally =
                            (!FinallyBlock.IsEmpty ? _getAddress(target, beginFinallyLabel) : -1),
                        BeginCatch = (!justRethrow ? _getAddress(target, beginCatchLabel) : -1),
                        UsesException = usesException
                    };

            //Register try-catch-finally block
            target.Function.Meta.AddTo(TryCatchFinallyBlock.MetaKey, block);
            target.Function.InvalidateTryCatchFinallyBlocks();
        }