Ejemplo n.º 1
0
        private void UpdateUses(Context ctx, IDictionary <StackOperand, StackOperand> liveOut)
        {
            int index = 0;

            foreach (Operand op1 in ctx.Operands)
            {
                // Is this a stack operand?
                StackOperand op = op1 as StackOperand;

                if (op != null)
                {
                    StackOperand ssa;
                    // Determine the most recent version
                    Debug.Assert(liveOut.TryGetValue(op, out ssa), "Stack operand not in live variable list.");

                    ssa = liveOut[op];

                    // Replace the use with the most recent version
                    ctx.SetOperand(index++, ssa);

                    if (TRACING.TraceInfo)
                    {
                        Trace.WriteLine(String.Format("\\tUse {0} has been replaced with {1}", op, ssa));
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private void RenameStackOperands(Context ctx, IDictionary <StackOperand, StackOperand> liveOut)
        {
            int index = 0;

            // Create new SSA variables for newly defined operands
            foreach (Operand op1 in ctx.Results)
            {
                // Is this a stack operand?
                StackOperand op = op1 as StackOperand;

                if (op != null)
                {
                    StackOperand ssa;
                    if (!liveOut.TryGetValue(op, out ssa))
                    {
                        ssa = op;
                    }

                    ssa         = RedefineOperand(ssa);
                    liveOut[op] = ssa;
                    ctx.SetResult(index++, ssa);

                    if (TRACING.TraceInfo)
                    {
                        Trace.WriteLine(String.Format("\tStore to {0} redefined as {1}", op, ssa));
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Determines whether [contains] [the specified CTX].
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="operand">The operand.</param>
        /// <returns>
        ///     <c>true</c> if [contains] [the specified CTX]; otherwise, <c>false</c>.
        /// </returns>
        public static bool Contains(Context ctx, StackOperand operand)
        {
            PhiData phiData = ctx.Other as PhiData;

            if (phiData == null)
            {
                return(false);
            }

            List <Operand> operands = phiData.Operands as List <Operand>;

            return(operands.Contains(operand));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Redefines a <see cref="StackOperand"/> with a new SSA version.
        /// </summary>
        /// <param name="cur">The StackOperand to redefine.</param>
        /// <returns>A new StackOperand.</returns>
        private StackOperand RedefineOperand(StackOperand cur)
        {
            string name = cur.Name;

            if (cur.Version == 0)
            {
                name = String.Format("T_{0}", name);
            }
            StackOperand op = MethodCompiler.CreateTemporary(cur.Type) as StackOperand;

            //StackOperand op = new LocalVariableOperand(cur.Base, name, idx, cur.Type);
            op.Version = ++_ssaVersion;
            return(op);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Adds the value.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="edge">The edge.</param>
        /// <param name="op">The op.</param>
        public static void AddValue(Context ctx, BasicBlock edge, StackOperand op)
        {
            PhiData phiData = ctx.Other as PhiData;

            if (phiData == null)
            {
                phiData   = new PhiData();
                ctx.Other = phiData;
            }

            List <BasicBlock> blocks = phiData.Blocks as List <BasicBlock>;

            Debug.Assert(blocks.Count < 255, @"Maximum number of operands in PHI exceeded.");

            blocks.Add(edge);
            phiData.Operands.Add(op);
        }
Ejemplo n.º 6
0
        private void MergePhiInstructions(BasicBlock block, BasicBlock caller, IDictionary <StackOperand, StackOperand> liveIn)
        {
            for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                IR.PhiInstruction phi = ctx.Instruction as IR.PhiInstruction;

                if (phi != null && liveIn.ContainsKey(ctx.Result as StackOperand))
                {
                    StackOperand value = liveIn[ctx.Result as StackOperand];

                    if (!IR.PhiInstruction.Contains(ctx, value) && (ctx.Result as StackOperand).Version != value.Version)
                    {
                        IR.PhiInstruction.AddValue(ctx, caller, value);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Adds PHI functions for all ref/out parameters of the method being compiled.
        /// </summary>
        private void AddPhiFunctionsForOutParameters()
        {
            Dictionary <StackOperand, StackOperand> liveIn = null;

            // Retrieve the well known epilogue block
            BasicBlock epilogue = FindBlock(Int32.MaxValue);

            Debug.Assert(epilogue != null, "Method doesn't have epilogue block?");

            Context ctxEpilogue = new Context(InstructionSet, epilogue);

            ctxEpilogue.GotoLast();

            // Iterate all parameter definitions
            foreach (RuntimeParameter rp in MethodCompiler.Method.Parameters)
            {
                // Retrieve the stack operand for the parameter
                StackOperand paramOp = (StackOperand)MethodCompiler.GetParameterOperand(rp.Position - 1);

                // Only add a PHI if the runtime parameter is out or ref...
                if (rp.IsOut || (paramOp.Type is RefSigType || paramOp.Type is PtrSigType))
                {
                    ctxEpilogue.AppendInstruction(IR.Instruction.PhiInstruction, paramOp);

                    if (liveIn == null)
                    {
                        liveIn = new Dictionary <StackOperand, StackOperand> ();
                    }

                    liveIn.Add(paramOp, paramOp);
                }
            }

            // Save the in versions to force a merge later
            if (liveIn != null)
            {
                _liveness[epilogue.Sequence] = liveIn;
            }
        }
Ejemplo n.º 8
0
 void ICallingConvention.GetStackRequirements(StackOperand stackOperand, out int size, out int alignment)
 {
     // Special treatment for some stack types
     // FIXME: Handle the size and alignment requirements of value types
     _architecture.GetTypeRequirements(stackOperand.Type, out size, out alignment);
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Emits an immediate operand.
        /// </summary>
        /// <param name="op">The immediate operand to emit.</param>
        public void EmitImmediate(Operand op)
        {
            byte[] imm = null;
            if (op is LocalVariableOperand)
            {
                // Add the displacement
                StackOperand so = (StackOperand)op;
                imm = LittleEndianBitConverter.GetBytes(so.Offset.ToInt32());
            }
            else if (op is LabelOperand)
            {
                _literals.Add(new Patch((op as LabelOperand).Label, _codeStream.Position));
                imm = new byte[4];
            }
            else if (op is MemoryOperand)
            {
                // Add the displacement
                MemoryOperand mo = (MemoryOperand)op;
                imm = LittleEndianBitConverter.GetBytes(mo.Offset.ToInt32());
            }
            else if (op is ConstantOperand)
            {
                // Add the immediate
                ConstantOperand co = (ConstantOperand)op;
                switch (op.Type.Type)
                {
                case CilElementType.I:
                    try
                    {
                        imm = LittleEndianBitConverter.GetBytes(Convert.ToInt32(co.Value));
                    }
                    catch (OverflowException)
                    {
                        imm = LittleEndianBitConverter.GetBytes(Convert.ToUInt32(co.Value));
                    }
                    break;

                case CilElementType.I1:
                    //imm = LittleEndianBitConverter.GetBytes(Convert.ToSByte(co.Value));
                    imm = new byte[1] {
                        Convert.ToByte(co.Value)
                    };
                    break;

                case CilElementType.I2:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToInt16(co.Value));
                    break;

                case CilElementType.I4: goto case CilElementType.I;

                case CilElementType.U1:
                    //imm = LittleEndianBitConverter.GetBytes(Convert.ToByte(co.Value));
                    imm = new byte[1] {
                        Convert.ToByte(co.Value)
                    };
                    break;

                case CilElementType.Char:
                    goto case CilElementType.U2;

                case CilElementType.U2:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToUInt16(co.Value));
                    break;

                case CilElementType.U4:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToUInt32(co.Value));
                    break;

                case CilElementType.I8:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToInt64(co.Value));
                    break;

                case CilElementType.U8:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToUInt64(co.Value));
                    break;

                case CilElementType.R4:
                    imm = LittleEndianBitConverter.GetBytes(Convert.ToSingle(co.Value));
                    break;

                case CilElementType.R8: goto default;

                default:
                    throw new NotSupportedException();
                }
            }
            else if (op is RegisterOperand)
            {
                // Nothing to do...
            }
            else
            {
                throw new NotImplementedException();
            }

            // Emit the immediate constant to the code
            if (null != imm)
            {
                _codeStream.Write(imm, 0, imm.Length);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            _dominanceProvider = (IDominanceProvider)MethodCompiler.GetPreviousStage(typeof(IDominanceProvider));
            Debug.Assert(_dominanceProvider != null, "SSA Conversion requires a dominance provider.");
            if (_dominanceProvider == null)
            {
                throw new InvalidOperationException("SSA Conversion requires a dominance provider.");
            }

            // Allocate space for live outs
            _liveness = new IDictionary <StackOperand, StackOperand> [BasicBlocks.Count];
            // Retrieve the dominance frontier Blocks
            _dominanceFrontierBlocks = _dominanceProvider.GetDominanceFrontier();

            // Add ref/out parameters to the epilogue block to have uses there...
            AddPhiFunctionsForOutParameters();

            // Transformation worklist
            Queue <WorkItem> workList = new Queue <WorkItem> ();

            /* Move parameter operands into the dictionary as version 0,
             * because they are live at entry and maybe referenced. Anyways, an
             * assignment to a parameter is also SSA related.
             */
            IDictionary <StackOperand, StackOperand> liveIn = new Dictionary <StackOperand, StackOperand> (s_comparer);
            int i = 0;

            if (MethodCompiler.Method.Signature.HasThis)
            {
                StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(0);
                liveIn.Add(param, param);
                i++;
            }
            for (int j = 0; j < MethodCompiler.Method.Parameters.Count; j++)
            {
                StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(i + j);
                liveIn.Add(param, param);
            }

            // Start with the very first block
            workList.Enqueue(new WorkItem(BasicBlocks[0], null, liveIn));

            // Iterate until the worklist is empty
            while (workList.Count != 0)
            {
                // Remove the block From the queue
                WorkItem workItem = workList.Dequeue();

                // Transform the block
                BasicBlock block    = workItem.block;
                bool       schedule = TransformToSsaForm(new Context(InstructionSet, block), workItem.caller, workItem.liveIn, out liveIn);
                _liveness[block.Sequence] = liveIn;

                if (schedule)
                {
                    // Add all branch targets to the work list
                    foreach (BasicBlock next in block.NextBlocks)
                    {
                        // Only follow backward branches, if we've redefined a variable
                        // this may force us to reinsert a PHI function in a block we
                        // already have completed processing on.
                        workList.Enqueue(new WorkItem(next, block, liveIn));
                    }
                }
            }
        }