예제 #1
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var size = InstructionSize.Size64;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(IRInstruction.LoadInteger, size, context.Result, context.Operand1, Operand.CreateConstant(methodCompiler.TypeSystem, 0));
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.LoadInteger, size, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new InvalidCompilerException();
            }
        }
예제 #2
0
        /// <summary>
        /// Floating point compare instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.FloatCompare(Context context)
        {
            Operand       result    = context.Result;
            Operand       left      = context.Operand1;
            Operand       right     = context.Operand2;
            ConditionCode condition = context.ConditionCode;

            // normalize condition
            switch (condition)
            {
            case ConditionCode.Equal: break;

            case ConditionCode.NotEqual: break;

            case ConditionCode.UnsignedGreaterOrEqual: condition = ConditionCode.GreaterOrEqual; break;

            case ConditionCode.UnsignedGreaterThan: condition = ConditionCode.GreaterThan; break;

            case ConditionCode.UnsignedLessOrEqual: condition = ConditionCode.LessOrEqual; break;

            case ConditionCode.UnsignedLessThan: condition = ConditionCode.LessThan; break;
            }

            // TODO - Move the following to its own pre-IR decomposition stage for this instruction
            // Swap, if necessary, the operands to place register operand first than memory operand
            // otherwise the memory operand will have to be loaded into a register
            if ((condition == ConditionCode.Equal || condition == ConditionCode.NotEqual) && left.IsMemoryAddress && !right.IsMemoryAddress)
            {
                // swap order of operands to move
                var t = left;
                left  = right;
                right = t;
            }

            Context before = context.InsertBefore();

            // Compare using the smallest precision
            if (left.IsR4 && right.IsR8)
            {
                Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4);
                before.SetInstruction(X86.Cvtsd2ss, rop, right);
                right = rop;
            }
            if (left.IsR8 && right.IsR4)
            {
                Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4);
                before.SetInstruction(X86.Cvtsd2ss, rop, left);
                left = rop;
            }

            X86Instruction  instruction = null;
            InstructionSize size        = InstructionSize.None;

            if (left.IsR4)
            {
                instruction = X86.Ucomiss;
                size        = InstructionSize.Size32;
            }
            else
            {
                instruction = X86.Ucomisd;
                size        = InstructionSize.Size64;
            }

            switch (condition)
            {
            case ConditionCode.Equal:
            {
                //  a==b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L3
                //	jne	L3
                //	ret
                //L3:
                //	mov	eax, 0

                var     newBlocks = CreateNewBlockContexts(2);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, newBlocks[1].Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Branch, ConditionCode.NotEqual, newBlocks[1].Block);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                newBlocks[1].AppendInstruction(X86.Mov, result, ConstantZero);
                newBlocks[1].AppendInstruction(X86.Jmp, nextBlock.Block);

                break;
            }

            case ConditionCode.NotEqual:
            {
                //  a!=b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L5
                //	setne	al
                //	movzx	eax, al
                //L5:

                var     newBlocks = CreateNewBlockContexts(1);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, nextBlock.Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Setcc, ConditionCode.NotEqual, result);
                newBlocks[0].AppendInstruction(X86.Movzx, result, result);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                break;
            }

            case ConditionCode.LessThan:
            {
                //	a<b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.GreaterThan:
            {
                //	a>b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.LessOrEqual:
            {
                //	a<=b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }

            case ConditionCode.GreaterOrEqual:
            {
                //	a>=b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }
            }
        }
        protected override void Setup()
        {
            base.Setup();

            ConstantFour = Operand.CreateConstant(MethodCompiler.TypeSystem, 4);
        }
예제 #4
0
        /// <summary>
        /// Decodes the specified instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
        public override void Decode(InstructionNode ctx, IInstructionDecoder decoder)
        {
            // Decode base classes first
            base.Decode(ctx, decoder);

            Operand constantValueOperand;

            // Opcode specific handling
            switch (opcode)
            {
            case OpCode.Ldc_i4:
            {
                int i = (int)decoder.Instruction.Operand;
                constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, i);
            }
            break;

            case OpCode.Ldc_i4_s:
            {
                sbyte sb = (sbyte)decoder.Instruction.Operand;
                constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, sb);
            }
            break;

            case OpCode.Ldc_i8:
            {
                long l = (long)decoder.Instruction.Operand;
                constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, l);
            }
            break;

            case OpCode.Ldc_r4:
            {
                float f = (float)decoder.Instruction.Operand;
                constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, f);
            }
            break;

            case OpCode.Ldc_r8:
            {
                double d = (double)decoder.Instruction.Operand;
                constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, d);
            }
            break;

            case OpCode.Ldnull: constantValueOperand = Operand.GetNull(decoder.TypeSystem); break;

            case OpCode.Ldc_i4_0: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 0); break;

            case OpCode.Ldc_i4_1: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 1); break;

            case OpCode.Ldc_i4_2: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 2); break;

            case OpCode.Ldc_i4_3: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 3); break;

            case OpCode.Ldc_i4_4: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 4); break;

            case OpCode.Ldc_i4_5: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 5); break;

            case OpCode.Ldc_i4_6: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 6); break;

            case OpCode.Ldc_i4_7: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 7); break;

            case OpCode.Ldc_i4_8: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, 8); break;

            case OpCode.Ldc_i4_m1: constantValueOperand = Operand.CreateConstant(decoder.TypeSystem, -1); break;

            default: throw new NotImplementCompilerException();
            }

            ctx.Operand1 = constantValueOperand;
            ctx.Result   = decoder.Compiler.CreateVirtualRegister(constantValueOperand.Type);
        }
        protected void ReplaceVirtualRegisterWithConstant(Operand target, ulong value)
        {
            if (trace.Active)
            {
                trace.Log(target.ToString() + " = " + value.ToString() + " Uses: " + target.Uses.Count.ToString());
            }

            Debug.Assert(target.Definitions.Count == 1);

            if (target.Uses.Count != 0)
            {
                var constant = Operand.CreateConstant(target.Type, value);

                // for each statement T that uses operand, substituted c in statement T
                foreach (var node in target.Uses.ToArray())
                {
                    Debug.Assert(node.Instruction != IRInstruction.AddressOf);

                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var operand = node.GetOperand(i);

                        if (operand != target)
                        {
                            continue;
                        }

                        if (trace.Active)
                        {
                            trace.Log("*** ConditionalConstantPropagation");
                        }
                        if (trace.Active)
                        {
                            trace.Log("BEFORE:\t" + node.ToString());
                        }
                        node.SetOperand(i, constant);
                        conditionalConstantPropagation++;
                        if (trace.Active)
                        {
                            trace.Log("AFTER: \t" + node.ToString());
                        }

                        changed = true;
                    }
                }
            }

            Debug.Assert(target.Uses.Count == 0);

            if (target.Definitions.Count == 0)
            {
                return;
            }

            var defNode = target.Definitions[0];

            if (trace.Active)
            {
                trace.Log("REMOVED:\t" + defNode.ToString());
            }
            defNode.SetInstruction(IRInstruction.Nop);
            instructionsRemovedCount++;
        }
예제 #6
0
        protected override void Run()
        {
            triggered = false;

            // The method declaring type must be a valuetype
            if (!MethodCompiler.Type.IsValueType)
            {
                return;
            }

            // If the method is static, non-virtual or is a constructor then don't process
            if (MethodCompiler.Method.IsStatic || !MethodCompiler.Method.IsVirtual || MethodCompiler.Method.Name.Equals(".ctor"))
            {
                return;
            }

            // If the method does not belong to an interface then don't process
            if (!(IsInterfaceMethod() || OverridesMethod()))
            {
                return;
            }

            // If the method is empty then don't process
            if (BasicBlocks.PrologueBlock.NextBlocks.Count == 0 || BasicBlocks.PrologueBlock.NextBlocks[0] == BasicBlocks.EpilogueBlock)
            {
                return;
            }

            triggered = true;

            // Get the this pointer
            var thisPtr = MethodCompiler.Parameters[0];

            //todo: move this to the end of prologue
            var context = new Context(BasicBlocks.PrologueBlock.NextBlocks[0].First);

            // Now push the this pointer by two native pointer sizes
            var v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.TypedRef);

            context.AppendInstruction(IRInstruction.LoadInteger, NativeInstructionSize, v1, StackFrame, thisPtr);
            context.AppendInstruction(IRInstruction.AddSigned, NativeInstructionSize, v1, v1, Operand.CreateConstant(TypeSystem.BuiltIn.I4, NativePointerSize * 2));
            context.AppendInstruction(IRInstruction.StoreInteger, NativeInstructionSize, null, StackFrame, thisPtr, v1);
        }
예제 #7
0
 public static Operand Create(MosaType type, uint value)
 {
     return(Operand.CreateConstant(type, value));
 }
        /// <summary>
        /// Floating point compare instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        private void FloatCompare(Context context, X86Instruction instruction, InstructionSize size)
        {
            Operand       result    = context.Result;
            Operand       left      = context.Operand1;
            Operand       right     = context.Operand2;
            ConditionCode condition = context.ConditionCode;

            // normalize condition
            switch (condition)
            {
            case ConditionCode.Equal: break;

            case ConditionCode.NotEqual: break;

            case ConditionCode.UnsignedGreaterOrEqual: condition = ConditionCode.GreaterOrEqual; break;

            case ConditionCode.UnsignedGreaterThan: condition = ConditionCode.GreaterThan; break;

            case ConditionCode.UnsignedLessOrEqual: condition = ConditionCode.LessOrEqual; break;

            case ConditionCode.UnsignedLessThan: condition = ConditionCode.LessThan; break;
            }

            Debug.Assert(!(left.IsR4 && right.IsR8));
            Debug.Assert(!(left.IsR8 && right.IsR4));

            switch (condition)
            {
            case ConditionCode.Equal:
            {
                //  a==b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L3
                //	jne	L3
                //	ret
                //L3:
                //	mov	eax, 0

                var     newBlocks = CreateNewBlockContexts(2);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, newBlocks[1].Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Branch, ConditionCode.NotEqual, newBlocks[1].Block);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                newBlocks[1].AppendInstruction(X86.Mov, result, ConstantZero);
                newBlocks[1].AppendInstruction(X86.Jmp, nextBlock.Block);
                break;
            }

            case ConditionCode.NotEqual:
            {
                //  a!=b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L5
                //	setne	al
                //	movzx	eax, al
                //L5:

                var     newBlocks = CreateNewBlockContexts(1);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, nextBlock.Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);
                newBlocks[0].AppendInstruction(X86.Setcc, ConditionCode.NotEqual, result);

                //newBlocks[0].AppendInstruction(X86.Movzx, InstructionSize.Size8, result, result);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);
                break;
            }

            case ConditionCode.LessThan:
            {
                //	a<b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.GreaterThan:
            {
                //	a>b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.LessOrEqual:
            {
                //	a<=b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }

            case ConditionCode.GreaterOrEqual:
            {
                //	a>=b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }
            }
        }
예제 #9
0
        private void GotoLeaveTargetInstruction(InstructionNode node)
        {
            var ctx = new Context(node);

            // clear exception register
            // FIXME: This will need to be preserved for filtered exceptions; will need a flag to know this - maybe an upper bit of leaveTargetRegister
            ctx.SetInstruction(IRInstruction.MoveInteger, exceptionRegister, nullOperand);

            var label            = node.Label;
            var exceptionContext = FindImmediateExceptionContext(label);

            // 1) currently within a try block with a finally handler --- call it.
            if (exceptionContext.ExceptionHandlerType == ExceptionHandlerType.Finally && exceptionContext.IsLabelWithinTry(node.Label))
            {
                var handlerBlock = BasicBlocks.GetByLabel(exceptionContext.HandlerStart);

                ctx.AppendInstruction(IRInstruction.Jmp, handlerBlock);

                return;
            }

            // 2) else, find the next finally handler (if any), check if it should be called, if so, call it
            var nextFinallyContext = FindNextEnclosingFinallyContext(exceptionContext);

            if (nextFinallyContext != null)
            {
                var handlerBlock = BasicBlocks.GetByLabel(nextFinallyContext.HandlerStart);

                var nextBlock = Split(ctx);

                // compare leaveTargetRegister > handlerBlock.End, then goto finally handler
                ctx.AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.GreaterThan, null, Operand.CreateConstant(TypeSystem, handlerBlock.Label), leaveTargetRegister, nextBlock.Block);
                ctx.AppendInstruction(IRInstruction.Jmp, handlerBlock);

                ctx = nextBlock;
            }

            // find all the available targets within the method from this node's location
            var targets = new List <BasicBlock>();

            // using the end of the protected as the location
            var location = exceptionContext.TryEnd;

            foreach (var targetBlock in leaveTargets)
            {
                var source = targetBlock.Item2;
                var target = targetBlock.Item1;

                // target must be after end of exception context
                if (target.Label <= location)
                {
                    continue;
                }

                // target must be found within try or handler
                if (exceptionContext.IsLabelWithinTry(source.Label) || exceptionContext.IsLabelWithinHandler(source.Label))
                {
                    targets.AddIfNew(target);
                }
            }

            if (targets.Count == 0)
            {
                // this is an unreachable location

                // clear this block --- should only have on instruction
                ctx.Empty();

                var currentBlock  = ctx.Block;
                var previousBlock = currentBlock.PreviousBlocks[0];

                var otherBranch = (previousBlock.NextBlocks[0] == currentBlock) ? previousBlock.NextBlocks[1] : previousBlock.NextBlocks[0];

                ReplaceBranchTargets(previousBlock, currentBlock, otherBranch);

                // the optimizer will remove the branch comparison

                return;
            }

            if (targets.Count == 1)
            {
                ctx.AppendInstruction(IRInstruction.Jmp, targets[0]);
                return;
            }
            else
            {
                var newBlocks = CreateNewBlockContexts(targets.Count - 1);

                ctx.AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.Equal, null, leaveTargetRegister, Operand.CreateConstant(TypeSystem, targets[0].Label), targets[0]);
                ctx.AppendInstruction(IRInstruction.Jmp, newBlocks[0].Block);

                for (int b = 1; b < targets.Count - 2; b++)
                {
                    newBlocks[b - 1].AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.Equal, null, leaveTargetRegister, Operand.CreateConstant(TypeSystem, targets[b].Label), targets[b]);
                    newBlocks[b - 1].AppendInstruction(IRInstruction.Jmp, newBlocks[b + 1].Block);
                }

                newBlocks[targets.Count - 2].AppendInstruction(IRInstruction.Jmp, targets[targets.Count - 1]);
            }
        }
예제 #10
0
 public static Operand Create(MosaType type, long value)
 {
     return(Operand.CreateConstant(type, (ulong)value));
 }
예제 #11
0
        protected override void Run()
        {
            exceptionVirtualRegisters     = new Dictionary <BasicBlock, Operand>();
            finallyReturnVirtualRegisters = new Dictionary <BasicBlock, Operand>();

            exceptionType = TypeSystem.GetTypeByName("System", "Exception");

            var exceptionRegister = Operand.CreateCPURegister(exceptionType, Architecture.ExceptionRegister);

            var finallyReturnBlockRegister = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, Architecture.FinallyReturnBlockRegister);

            var nullOperand = Operand.GetNull(TypeSystem);

            for (int i = 0; i < BasicBlocks.Count; i++)
            {
                var block = BasicBlocks[i];

                for (var node = block.First; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Throw)
                    {
                        var method = PlatformInternalRuntimeType.FindMethodByName("ExceptionHandler");
                        var ctx    = new Context(node);

                        ctx.SetInstruction(IRInstruction.Move, exceptionRegister, node.Operand1);

                        //ctx.AppendInstruction(IRInstruction.KillAllExcept, null, exceptionRegister);
                        ctx.AppendInstruction(IRInstruction.Call, null, Operand.CreateSymbolFromMethod(TypeSystem, method));
                        ctx.InvokeMethod = method;
                    }
                    else if (node.Instruction == IRInstruction.CallFinally)
                    {
                        var target        = node.BranchTargets[0];
                        var finallyReturn = node.BranchTargets[1];
                        var ctx           = new Context(node);

                        ctx.SetInstruction(IRInstruction.KillAll);
                        ctx.AppendInstruction(IRInstruction.Move, exceptionRegister, nullOperand);
                        ctx.AppendInstruction(IRInstruction.Move, finallyReturnBlockRegister, Operand.CreateConstant(TypeSystem, finallyReturn.Label));
                        ctx.AppendInstruction(IRInstruction.Jmp, target);
                    }
                    else if (node.Instruction == IRInstruction.FinallyStart)
                    {
                        // Remove from header blocks
                        BasicBlocks.RemoveHeaderBlock(node.Block);

                        var exceptionVirtualRegister          = node.Result;
                        var finallyReturnBlockVirtualRegister = node.Result2;
                        var ctx = new Context(node);

                        exceptionVirtualRegisters.Add(node.Block, exceptionVirtualRegister);
                        finallyReturnVirtualRegisters.Add(node.Block, finallyReturnBlockRegister);

                        ctx.SetInstruction(IRInstruction.KillAll);
                        ctx.AppendInstruction(IRInstruction.Gen, exceptionRegister);
                        ctx.AppendInstruction(IRInstruction.Gen, finallyReturnBlockRegister);

                        ctx.AppendInstruction(IRInstruction.Move, exceptionVirtualRegister, exceptionRegister);
                        ctx.AppendInstruction(IRInstruction.Move, finallyReturnBlockVirtualRegister, finallyReturnBlockRegister);
                    }
                    else if (node.Instruction == IRInstruction.FinallyEnd)
                    {
                        var header      = FindImmediateExceptionHandler(node);
                        var headerBlock = BasicBlocks.GetByLabel(header.HandlerStart);

                        var exceptionVirtualRegister          = exceptionVirtualRegisters[headerBlock];
                        var finallyReturnBlockVirtualRegister = finallyReturnVirtualRegisters[headerBlock];

                        var newBlocks = CreateNewBlockContexts(1);
                        var ctx       = new Context(node);
                        var nextBlock = Split(ctx);

                        ctx.SetInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.NotEqual, null, exceptionVirtualRegister, nullOperand, newBlocks[0].Block);
                        ctx.AppendInstruction(IRInstruction.Jmp, nextBlock.Block);

                        var method = PlatformInternalRuntimeType.FindMethodByName("ExceptionHandler");

                        newBlocks[0].AppendInstruction(IRInstruction.Move, exceptionRegister, exceptionVirtualRegister);
                        newBlocks[0].AppendInstruction(IRInstruction.Call, null, Operand.CreateSymbolFromMethod(TypeSystem, method));
                        newBlocks[0].InvokeMethod = method;
                    }
                    else if (node.Instruction == IRInstruction.FinallyReturn)
                    {
                        var targets = node.BranchTargets;

                        var header      = FindImmediateExceptionHandler(node);
                        var headerBlock = BasicBlocks.GetByLabel(header.HandlerStart);

                        var finallyReturnBlockVirtualRegister = finallyReturnVirtualRegisters[headerBlock];

                        Debug.Assert(targets.Count != 0);

                        if (targets.Count == 1)
                        {
                            node.SetInstruction(IRInstruction.Jmp, targets[0]);
                        }
                        else
                        {
                            var newBlocks = CreateNewBlockContexts(targets.Count - 1);
                            var ctx       = new Context(node);

                            ctx.SetInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, finallyReturnBlockVirtualRegister, Operand.CreateConstant(TypeSystem, targets[0].Label), targets[0]);
                            ctx.AppendInstruction(IRInstruction.Jmp, newBlocks[0].Block);

                            for (int b = 1; b < targets.Count - 2; b++)
                            {
                                newBlocks[b - 1].AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, finallyReturnBlockVirtualRegister, Operand.CreateConstant(TypeSystem, targets[b].Label), targets[b]);
                                newBlocks[b - 1].AppendInstruction(IRInstruction.Jmp, newBlocks[b + 1].Block);
                            }

                            newBlocks[targets.Count - 2].AppendInstruction(IRInstruction.Jmp, targets[targets.Count - 1]);
                        }
                    }
                    else if (node.Instruction == IRInstruction.ExceptionStart)
                    {
                        var exceptionVirtualRegister = node.Result;
                        var ctx = new Context(node);

                        ctx.SetInstruction(IRInstruction.KillAll);
                        ctx.AppendInstruction(IRInstruction.Gen, exceptionRegister);
                        ctx.AppendInstruction(IRInstruction.Move, exceptionVirtualRegister, exceptionRegister);
                    }
                    else if (node.Instruction == IRInstruction.ExceptionEnd)
                    {
                        node.SetInstruction(IRInstruction.Jmp, node.BranchTargets[0]);
                    }
                    else if (node.Instruction == IRInstruction.Flow)
                    {
                        node.Empty();
                    }
                }
            }
        }
예제 #12
0
 public Operand CreateConstant(double value)
 {
     return(Operand.CreateConstant(value, TypeSystem));
 }
예제 #13
0
 public Operand CreateConstant(ulong value)
 {
     return(Operand.CreateConstant(TypeSystem.BuiltIn.U8, value));
 }
예제 #14
0
 public Operand CreateConstant(int value)
 {
     return(Operand.CreateConstant(TypeSystem.BuiltIn.I4, value));
 }
예제 #15
0
 public Operand CreateConstant(byte value)
 {
     return(Operand.CreateConstant(TypeSystem.BuiltIn.U1, value));
 }