SetOperand() public method

Sets the operand by index.
public SetOperand ( int index, Operand operand ) : void
index int The index.
operand Operand The operand.
return void
Beispiel #1
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        void IMethodCompilerStage.Run()
        {
            if (AreExceptions)
                return;

            foreach (var block in this.basicBlocks)
            {
                if (block.Label == Int32.MaxValue)
                    continue;

                for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
                {
                    if (context.Instruction is PhiInstruction)
                        this.ProcessPhiInstruction(block, context);

                    for (var i = 0; i < context.OperandCount; ++i)
                    {
                        var op = context.GetOperand(i);
                        if (op is SsaOperand)
                            context.SetOperand(i, (op as SsaOperand).Operand);
                    }

                    for (var i = 0; i < context.ResultCount; ++i)
                    {
                        var op = context.GetResult(i);
                        if (op is SsaOperand)
                            context.SetResult(i, (op as SsaOperand).Operand);
                    }
                }
            }
        }
        private static void PatchInvoke(BaseMethodCompiler methodCompiler)
        {
            // check if instance is null (if so, it's a static call to the methodPointer)

            MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer");
            int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField);
            Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset);

            MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance");
            int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField);
            Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset);

            var size = methodCompiler.Architecture.NativeInstructionSize;
            bool withReturn = (methodCompiler.Method.Signature.ReturnType == null) ? false : !methodCompiler.Method.Signature.ReturnType.IsVoid;

            Context b0 = new Context(CreateMethodStructure(methodCompiler, false));
            Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock());

            Operand[] vrs = new Operand[methodCompiler.Parameters.Length];

            for (int i = 0; i < methodCompiler.Parameters.Length; i++)
            {
                vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type);

                //fixme: handle structs
                var loadInstruction = BaseMethodCompilerStage.GetLoadInstruction(vrs[i].Type);
                var moveSize = BaseMethodCompilerStage.GetInstructionSize(vrs[i].Type);

                b0.AppendInstruction(loadInstruction, moveSize, vrs[i], methodCompiler.StackFrame, methodCompiler.Parameters[i]);
            }

            Operand thisOperand = vrs[0];

            Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4);
            Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type);
            Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4);

            Operand opReturn = withReturn ? methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType) : null;
            Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0);

            b0.AppendInstruction(IRInstruction.LoadInteger, size, opMethod, thisOperand, methodPointerOffsetOperand);
            b0.AppendInstruction(IRInstruction.LoadInteger, size, opInstance, thisOperand, instanceOffsetOperand);
            b0.AppendInstruction(IRInstruction.CompareInteger, ConditionCode.Equal, opCompare, opInstance, c0);
            b0.AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.Equal, null, opCompare, c0);
            b0.AddBranchTarget(b2.Block);
            b0.AppendInstruction(IRInstruction.Jmp, b1.Block);

            // no instance
            b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b1.InvokeMethod = methodCompiler.Method;
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
                b1.AddOperand(vrs[i]);
            if (withReturn)
                b1.SetResult(0, opReturn);
            b1.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // instance
            b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b2.InvokeMethod = methodCompiler.Method;
            b2.AddOperand(opInstance);
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
                b2.AddOperand(vrs[i]);
            if (withReturn)
                b2.SetResult(0, opReturn);
            b2.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // return
            b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock);
            if (withReturn)
                b3.SetOperand(0, opReturn);
        }
Beispiel #3
0
        /// <summary>
        /// Replaces this operand in all uses and defs with the given operand.
        /// </summary>
        /// <param name="replacement">The replacement operand.</param>
        /// <param name="instructionSet">The instruction set.</param>
        public void Replace(Operand replacement, InstructionSet instructionSet)
        {
            // Iterate all definition sites first
            foreach (int index in Definitions.ToArray())
            {
                Context ctx = new Context(instructionSet, index);

                if (ctx.Result != null)
                {
                    // Is this the operand?
                    if (ReferenceEquals(ctx.Result, this))
                    {
                        ctx.Result = replacement;
                    }

                }
            }

            // Iterate all use sites
            foreach (int index in Uses.ToArray())
            {
                Context ctx = new Context(instructionSet, index);

                int opIdx = 0;
                foreach (Operand r in ctx.Operands)
                {
                    // Is this the operand?
                    if (ReferenceEquals(r, this))
                    {
                        ctx.SetOperand(opIdx, replacement);
                    }

                    opIdx++;
                }
            }
        }
        private static void PatchInvoke(BaseMethodCompiler methodCompiler, bool withReturn)
        {
            // check if instance is null (if so, it's a static call to the methodPointer)

            MosaField methodPointerField         = GetField(methodCompiler.Method.DeclaringType, "methodPointer");
            int       methodPointerOffset        = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField);
            Operand   methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset);

            MosaField instanceField         = GetField(methodCompiler.Method.DeclaringType, "instance");
            int       instanceOffset        = methodCompiler.TypeLayout.GetFieldOffset(instanceField);
            Operand   instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset);

            var size = methodCompiler.Architecture.NativeInstructionSize;

            Context b0 = new Context(CreateMethodStructure(methodCompiler, false));
            Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock());

            Operand[] vrs = new Operand[methodCompiler.Parameters.Length];

            for (int i = 0; i < methodCompiler.Parameters.Length; i++)
            {
                vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type);

                if (methodCompiler.TypeLayout.IsCompoundType(methodCompiler.Parameters[i].Type))
                {
                    b0.AppendInstruction(IRInstruction.CompoundMove, vrs[i], methodCompiler.Parameters[i]);
                }
                else
                {
                    b0.AppendInstruction(IRInstruction.Move, vrs[i], methodCompiler.Parameters[i]);
                }
            }

            Operand thisOperand = vrs[0];

            Operand opMethod   = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4);
            Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type);
            Operand opCompare  = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4);

            Operand opReturn = withReturn ? methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.Object) : null;
            Operand c0       = Operand.CreateConstant(methodCompiler.TypeSystem, 0);

            b0.AppendInstruction(IRInstruction.Load, size, opMethod, thisOperand, methodPointerOffsetOperand);
            b0.AppendInstruction(IRInstruction.Load, size, opInstance, thisOperand, instanceOffsetOperand);
            b0.AppendInstruction(IRInstruction.IntegerCompare, ConditionCode.Equal, opCompare, opInstance, c0);
            b0.AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, opCompare, c0);
            b0.AddBranchTarget(b2.Block);
            b0.AppendInstruction(IRInstruction.Jmp, b1.Block);

            // no instance
            b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b1.InvokeMethod = methodCompiler.Method;
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
            {
                b1.AddOperand(vrs[i]);
            }
            b1.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // instance
            b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b2.InvokeMethod = methodCompiler.Method;
            b2.AddOperand(opInstance);
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
            {
                b2.AddOperand(vrs[i]);
            }
            b2.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // return
            b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock);
            if (withReturn)
            {
                b3.SetOperand(0, opReturn);
            }
        }
        /// <summary>
        /// Replaces the operand.
        /// </summary>
        /// <param name="lr">The lr.</param>
        /// <param name="replacement">The replacement.</param>
        private void ReplaceOperand(LiveRange lr, RegisterOperand replacement)
        {
            int opIdx;

            // Iterate all definition sites first
            foreach (int index in lr.Op.Definitions.ToArray())
            {
                Context def = new Context(instructionSet, index);
                if (def.Offset == lr.Start)
                {
                    opIdx = 0;
                    foreach (Operand r in def.Results)
                    {
                        // Is this the operand?
                        if (object.ReferenceEquals(r, lr.Op))
                            def.SetResult(opIdx, replacement);

                        opIdx++;
                    }

                    break;
                }
            }

            // Iterate all use sites
            foreach (int index in lr.Op.Uses.ToArray())
            {
                Context instr = new Context(instructionSet, index);

                if (instr.Offset <= lr.Start)
                {
                    // A use on instr.Offset == lr.Start is one from a previous definition!!
                }
                else if (instr.Offset <= lr.End)
                {
                    opIdx = 0;
                    foreach (Operand r in instr.Operands)
                    {
                        // Is this the operand?
                        if (object.ReferenceEquals(r, lr.Op))
                            instr.SetOperand(opIdx, replacement);

                        opIdx++;
                    }
                }
                else
                {
                    break;
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="block"></param>
        private void RenameVariables(BasicBlock block)
        {
            for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
            {
                if (!(context.Instruction is PhiInstruction))
                {
                    for (var i = 0; i < context.OperandCount; ++i)
                    {
                        var op = context.GetOperand(i);
                        if (!(op is StackOperand))
                            continue;
                        var name = NameForOperand(context.GetOperand(i));
                        if (!this.variableInformation.ContainsKey(name))
                            throw new Exception(name + " is not in dictionary [block = " + block + "]");
                        var index = this.variableInformation[name].Stack.Peek();
                        context.SetOperand(i, new SsaOperand(context.GetOperand(i), index));
                    }
                }

                if (PhiPlacementStage.IsAssignmentToStackVariable(context))
                {
                    var name = NameForOperand(context.Result);
                    var index = this.variableInformation[name].Count;
                    context.SetResult(new SsaOperand(context.Result, index));
                    this.variableInformation[name].Stack.Push(index);
                    ++this.variableInformation[name].Count;
                }
            }

            foreach (var s in block.NextBlocks)
            {
                var j = this.WhichPredecessor(s, block);
                for (var context = new Context(this.instructionSet, s); !context.EndOfInstruction; context.GotoNext())
                {
                    if (!(context.Instruction is PhiInstruction))
                        continue;
                    var name = NameForOperand(context.GetOperand(j));
                    if (this.variableInformation[name].Stack.Count > 0)
                    {
                        var index = this.variableInformation[name].Stack.Peek();
                        context.SetOperand(j, new SsaOperand(context.GetOperand(j), index));
                    }
                }
            }

            foreach (var s in this.dominanceCalculationStage.GetChildren(block))
            {
                this.RenameVariables(s);
            }

            for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
            {
                if (PhiPlacementStage.IsAssignmentToStackVariable(context))
                {
                    var instName = context.Label + "." + context.Index;
                    var op = this.oldLefHandSide[instName];
                    var name = NameForOperand(op);
                    this.variableInformation[name].Stack.Pop();
                }
            }
        }
        /// <summary>
        /// Assigns the operands from CIL stack.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="currentStack">The current stack.</param>
        private void AssignOperandsFromCILStack(Context ctx, Stack<Operand> currentStack)
        {
            for (int index = ctx.OperandCount - 1; index >= 0; --index)
            {
                if (ctx.GetOperand(index) != null)
                    continue;

                ctx.SetOperand(index, currentStack.Pop());
            }
        }
        private static void PatchInvoke(BaseMethodCompiler methodCompiler, bool withReturn)
        {
            // check if instance is null (if so, it's a static call to the methodPointer)

            MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer");
            int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField);
            Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset);

            MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance");
            int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField);
            Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset);

            var size = methodCompiler.Architecture.NativeInstructionSize;

            Context b0 = new Context(CreateMethodStructure(methodCompiler, false));
            Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock());
            Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock());

            Operand[] vrs = new Operand[methodCompiler.Parameters.Length];

            for (int i = 0; i < methodCompiler.Parameters.Length; i++)
            {
                vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type);

                if (methodCompiler.TypeLayout.IsCompoundType(methodCompiler.Parameters[i].Type))
                {
                    b0.AppendInstruction(IRInstruction.CompoundMove, vrs[i], methodCompiler.Parameters[i]);
                }
                else
                {
                    b0.AppendInstruction(IRInstruction.Move, vrs[i], methodCompiler.Parameters[i]);
                }
            }

            Operand thisOperand = vrs[0];

            Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4);
            Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type);
            Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4);

            Operand opReturn = withReturn ? methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.Object) : null;
            Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0);

            b0.AppendInstruction(IRInstruction.Load, size, opMethod, thisOperand, methodPointerOffsetOperand);
            b0.AppendInstruction(IRInstruction.Load, size, opInstance, thisOperand, instanceOffsetOperand);
            b0.AppendInstruction(IRInstruction.IntegerCompare, ConditionCode.Equal, opCompare, opInstance, c0);
            b0.AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, opCompare, c0);
            b0.AddBranchTarget(b2.Block);
            b0.AppendInstruction(IRInstruction.Jmp, b1.Block);

            // no instance
            b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b1.InvokeMethod = methodCompiler.Method;
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
            {
                b1.AddOperand(vrs[i]);
            }
            b1.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // instance
            b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod);
            b2.InvokeMethod = methodCompiler.Method;
            b2.AddOperand(opInstance);
            for (int i = 1; i < methodCompiler.Parameters.Length; i++)
            {
                b2.AddOperand(vrs[i]);
            }
            b2.AppendInstruction(IRInstruction.Jmp, b3.Block);

            // return
            b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock);
            if (withReturn)
            {
                b3.SetOperand(0, opReturn);
            }
        }
        /// <summary>
        /// Visitation function for RemFloat.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.RemFloat(Context context)
        {
            var result = context.Result;
            var dividend = context.Operand1;
            var divisor = context.Operand2;
            var method = (result.IsR8) ? "RemR8" : "RemR4";

            var type = TypeSystem.GetTypeByName("Mosa.Platform.Internal.x86", "Division");

            Debug.Assert(type != null, "Cannot find type: Mosa.Platform.Internal.x86.Division type");

            var mosaMethod = type.FindMethodByName(method);

            Debug.Assert(method != null, "Cannot find method: " + method);

            context.ReplaceInstructionOnly(IRInstruction.Call);
            context.SetOperand(0, Operand.CreateSymbolFromMethod(TypeSystem, mosaMethod));
            context.Result = result;
            context.Operand2 = dividend;
            context.Operand3 = divisor;
            context.OperandCount = 3;
            context.ResultCount = 1;
            context.InvokeMethod = mosaMethod;

            // Since we are already in IR Transformation Stage we gotta call this now
            CallingConvention.MakeCall(MethodCompiler, TypeLayout, context);
        }
        private void ReplaceWithDivisionCall(Context context, string methodName)
        {
            var type = TypeSystem.GetTypeByName("Mosa.Runtime.x86", "Division");

            Debug.Assert(type != null, "Cannot find type: Mosa.Runtime.x86.Division type");

            var method = type.FindMethodByName(methodName);

            Debug.Assert(method != null, "Cannot find method: " + methodName);

            context.ReplaceInstructionOnly(IRInstruction.Call);
            context.SetOperand(0, Operand.CreateSymbolFromMethod(TypeSystem, method));
            context.OperandCount = 1;
            context.InvokeMethod = method;
        }