Ejemplo n.º 1
0
        static void BuildTables(IEnumerable <JumpEntry> jumps, LabelOperand defaultLabel, out List <JumpTable> tables, out List <JumpEntry> rest)
        {
            rest = new List <JumpEntry>();

            var numbers = FilterJumps(jumps, rest);

            var comparer = new GenericComparer <JumpTableEntry <int> >((b1, b2) => b1.Value - b2.Value);

            numbers.Sort(comparer);

            tables = new List <JumpTable>();

            for (var i = 0; i < numbers.Count; i++)
            {
                var table = TryBuildTable(numbers, i, defaultLabel);

                if (table != null)
                {
                    tables.Add(table);
                    i += table.Entries.Count - table.Holes - 1;
                }
                else
                {
                    rest.Add(new JumpEntry(numbers[i].Condition, numbers[i].Label));
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Emits the displacement operand.
        /// </summary>
        /// <param name="displacement">The displacement operand.</param>
        public void WriteDisplacement(Operand displacement)
        {
            byte[] disp;

            MemberOperand member = displacement as MemberOperand;
            LabelOperand  label  = displacement as LabelOperand;
            SymbolOperand symbol = displacement as SymbolOperand;

            if (label != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, label.Name, IntPtr.Zero));
            }
            else if (member != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, member.Member.ToString(), member.Offset));
            }
            else if (symbol != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, symbol.Name, IntPtr.Zero));
            }
            else
            {
                disp = LittleEndianBitConverter.GetBytes((displacement as MemoryOperand).Offset.ToInt32());
            }

            _codeStream.Write(disp, 0, disp.Length);
        }
Ejemplo n.º 3
0
        public FunctionContext(ExpressionCompiler compiler, string name)
        {
            _compiler = compiler;
            _instructions = new List<Instruction>();
            _loopLabels = new IndexedStack<Tuple<LabelOperand, LabelOperand>>();

            Name = name != null ? _compiler.Identifier(name) : null;
            Label = _compiler.MakeLabel("function");

            IdentifierCount = 0;
        }
        /// <summary>
        /// This function emits a constant variable into the read-only data section.
        /// </summary>
        /// <param name="op">The operand to emit as a constant.</param>
        /// <returns>An operand, which represents the reference to the read-only constant.</returns>
        /// <remarks>
        /// This function checks if the given operand needs to be moved into the read-only data
        /// section of the executable. For x86 this concerns only floating point operands, as these
        /// can't be specified in inline assembly.<para/>
        /// This function checks if the given operand needs to be moved and rewires the operand, if
        /// it must be moved.
        /// </remarks>
        protected Operand EmitConstant(Operand op)
        {
            ConstantOperand cop = op as ConstantOperand;

            if (cop != null && (cop.StackType == StackTypeCode.F || cop.StackType == StackTypeCode.Int64))
            {
                int size, alignment;
                architecture.GetTypeRequirements(cop.Type, out size, out alignment);

                string name = String.Format("C_{0}", Guid.NewGuid());
                using (Stream stream = methodCompiler.Linker.Allocate(name, SectionKind.ROData, size, alignment))
                {
                    byte[] buffer;

                    switch (cop.Type.Type)
                    {
                    case CilElementType.R4:
                        buffer = LittleEndianBitConverter.GetBytes((float)cop.Value);
                        break;

                    case CilElementType.R8:
                        buffer = LittleEndianBitConverter.GetBytes((double)cop.Value);
                        break;

                    case CilElementType.I8:
                        buffer = LittleEndianBitConverter.GetBytes((long)cop.Value);
                        break;

                    case CilElementType.U8:
                        buffer = LittleEndianBitConverter.GetBytes((ulong)cop.Value);
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    stream.Write(buffer, 0, buffer.Length);
                }

                // FIXME: Attach the label operand to the linker symbol
                // FIXME: Rename the operand to SymbolOperand
                // FIXME: Use the provided name to link
                LabelOperand lop = new LabelOperand(cop.Type, name);
                op = lop;
            }
            return(op);
        }
Ejemplo n.º 5
0
        private Instruction decodePcRelative(uint index, uint data)
        {
            var rs     = new RegisterOperand(data, 21);
            var offset = new LabelOperand(getSymbolName(index, (ushort)data << 2));

            switch ((data >> 16) & 0x1f)
            {
            case 0:
                addXref(index - 4, (uint)((index + (short)data) << 2));
                m_analysisQueue.Enqueue(index + (uint)((short)data << 2));
                return(new ConditionalBranchInstruction(ConditionalBranchInstruction.Operation.SignedLess,
                                                        rs,
                                                        new ImmediateOperand(0),
                                                        offset));

            case 1:
                addXref(index - 4, (uint)((index + (short)data) << 2));
                m_analysisQueue.Enqueue(index + (uint)((short)data << 2));
                return(new ConditionalBranchInstruction(ConditionalBranchInstruction.Operation.SignedGreaterEqual,
                                                        rs,
                                                        new ImmediateOperand(0),
                                                        offset));

            case 16:
                addCall(index - 4, (uint)((index + (short)data) << 2));
                m_analysisQueue.Enqueue(index + (uint)((short)data << 2));
                return(new ConditionalCallInstruction(ConditionalBranchInstruction.Operation.SignedLess,
                                                      rs,
                                                      new ImmediateOperand(0),
                                                      offset));

            case 17:
                addCall(index - 4, (uint)((index + (short)data) << 2));
                m_analysisQueue.Enqueue(index + (uint)((short)data << 2));
                return(new ConditionalCallInstruction(ConditionalBranchInstruction.Operation.SignedGreaterEqual,
                                                      rs,
                                                      new ImmediateOperand(0),
                                                      offset));

            default:
                return(new WordData(data));
            }
        }
Ejemplo n.º 6
0
        public SwitchInstruction(LabelOperand caseTable, uint caseCount, LabelOperand defaultLabel,
                                 Register caseValueRegister, Register boolTestRegister, Register shiftedCaseValue)
        {
            _caseTable         = caseTable;
            _caseCount         = caseCount;
            _defaultLabel      = defaultLabel;
            _caseValueRegister = caseValueRegister;
            _boolTestRegister  = boolTestRegister;
            _shiftedCaseValue  = shiftedCaseValue;

            Operands = new IOperand[]
            {
                caseTable,
                new ImmediateOperand(caseCount),
                defaultLabel,
                new RegisterOperand(caseValueRegister),
                new RegisterOperand(boolTestRegister)
            };
        }
Ejemplo n.º 7
0
        public FunctionContext(ExpressionCompiler compiler, int argIndex, int localIndex, Scope prevScope, string parentName, string name)
        {
            _instructions = new List<Instruction>();
            _loopLabels = new IndexedStack<Tuple<LabelOperand, LabelOperand>>();

            Compiler = compiler;
            ArgIndex = argIndex;
            LocalIndex = localIndex;

            Scope = prevScope;

            ParentName = parentName;
            Name = name;
            FullName = string.Format("{0}{1}{2}", parentName, string.IsNullOrEmpty(parentName) ? "" : ".", Name ?? "");

            AssignedName = name != null ? prevScope.Get(name) : null;
            Label = Compiler.MakeLabel("function");

            IdentifierCount = 0;
        }
Ejemplo n.º 8
0
        public override void CompileBody(FunctionContext context)
        {
            var stack = 0;

            EndLabel = context.MakeLabel("state_end");

            stack += context.Bind(context.Label);
            stack += context.Enter();

            // jump to state label
            stack += context.Load(State);
            stack += context.JumpTable(0, _stateLabels);
            stack += context.Jump(EndLabel);

            // first state
            stack += context.Bind(MakeStateLabel(context));

            // compile body
            stack += Block.Compile(context);

            // set enumerator.current to undefined
            // do this before EndLabel so we dont overwrite return values
            stack += context.LoadUndefined();
            stack += context.Load(Enumerable);
            stack += context.StoreField(context.String("current"));

            stack += context.Bind(EndLabel);

            // set state to end
            stack += context.Load(context.Number(-1));
            stack += context.Store(State);

            stack += context.LoadFalse();
            stack += context.Return();

            CheckStack(stack, 0);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Emits the displacement operand.
        /// </summary>
        /// <param name="displacement">The displacement operand.</param>
        private void EmitDisplacement(MemoryOperand displacement)
        {
            byte[] disp;

            MemberOperand member = displacement as MemberOperand;
            LabelOperand  label  = displacement as LabelOperand;

            if (null != label)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method, pos, 0, label.Name, IntPtr.Zero));
            }
            else if (null != member)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method, pos, 0, member.Member, member.Offset));
            }
            else
            {
                disp = LittleEndianBitConverter.GetBytes(displacement.Offset.ToInt32());
            }

            _codeStream.Write(disp, 0, disp.Length);
        }
Ejemplo n.º 10
0
        public override int Compile(FunctionContext context)
        {
            context.Position(Token);

            var stack      = 0;
            var caseLabels = new List <LabelOperand>(Branches.Count);

            var             caseEnd      = context.MakeLabel("caseEnd");
            LabelOperand    caseDefault  = null;
            BlockExpression defaultBlock = null;

            for (var i = 0; i < Branches.Count; i++)
            {
                var label = context.MakeLabel("caseBranch_" + i);
                caseLabels.Add(label);

                var conditions = Branches[i].Conditions;
                if (conditions.Any(c => c == null))
                {
                    caseDefault = label;

                    if (conditions.Count == 1)
                    {
                        defaultBlock = Branches[i].Block;
                    }
                }
            }

            var emptyDefault = caseDefault == null;

            if (emptyDefault)
            {
                caseDefault = context.MakeLabel("caseDefault");
            }

            context.PushScope();

            context.Statement(Expression);
            stack += Expression.Compile(context);

            var flattenedBranches = FlattenBranches(Branches, caseLabels, caseDefault);

            BuildTables(flattenedBranches, caseDefault, out var tables, out var rest);

            foreach (var table in tables)
            {
                var start  = table.Entries[0].Value;
                var labels = table.Entries.Select(e => e.Label).ToList();

                stack += context.Dup();
                stack += context.JumpTable(start, labels);
            }

            foreach (var entry in rest)
            {
                stack += context.Dup();
                stack += entry.Condition.Compile(context);
                stack += context.BinaryOperation(TokenType.EqualTo);
                stack += context.JumpTrue(entry.Label);
            }

            stack += context.Jump(caseDefault);

            context.PushLoop(null, caseEnd);

            for (var i = 0; i < Branches.Count; i++)
            {
                var branchStack = stack;
                var branch      = Branches[i];

                branchStack += context.Bind(caseLabels[i]);
                branchStack += context.Drop();
                branchStack += branch.Block.Compile(context);
                branchStack += context.Jump(caseEnd);

                CheckStack(branchStack, 0);
            }

            // only bind if we need a default block
            if (emptyDefault || defaultBlock != null)
            {
                stack += context.Bind(caseDefault);
            }

            // always drop the switch value
            stack += context.Drop();

            if (defaultBlock != null)
            {
                stack += defaultBlock.Compile(context);
            }

            context.PopLoop();

            stack += context.Bind(caseEnd);

            context.PopScope();

            CheckStack(stack, 0);
            return(stack);
        }
Ejemplo n.º 11
0
 public CaseTableEntry([NotNull] LabelOperand labelOperand)
 {
     _labelOperand = labelOperand;
 }
Ejemplo n.º 12
0
 public override void PushLoop(LabelOperand continueTarget, LabelOperand breakTarget)
 {
     _parent.PushLoop(continueTarget, breakTarget);
 }
Ejemplo n.º 13
0
        static JumpTable TryBuildTable(IList <JumpTableEntry <int> > jumps, int offset, LabelOperand defaultLabel)
        {
            var tableEntries = new List <JumpTableEntry <int> >();
            var tableHoles   = 0;

            var prev = jumps[offset].Value;

            for (var i = offset; i < jumps.Count; i++)
            {
                var holeSize = jumps[i].Value - prev;
                if (holeSize < 0)
                {
                    throw new Exception("not sorted");
                }

                holeSize--;

                if (holeSize > 3)
                {
                    break;
                }

                for (var j = 0; j < holeSize; j++)
                {
                    tableEntries.Add(new JumpTableEntry <int>(null, 0, defaultLabel));
                }

                tableEntries.Add(jumps[i]);

                tableHoles += Math.Max(holeSize, 0);
                prev        = jumps[i].Value;
            }

            if (tableEntries.Count < 3)
            {
                return(null);
            }

            if ((double)tableHoles / tableEntries.Count >= 0.25) // TODO: allow more holes for large tables?
            {
                return(null);
            }

            return(new JumpTable(tableEntries, tableHoles));
        }
Ejemplo n.º 14
0
 public JumpTableEntry(Expression condition, T value, LabelOperand label)
 {
     Condition = condition;
     Value     = value;
     Label     = label;
 }
Ejemplo n.º 15
0
        static IEnumerable <JumpEntry> FlattenBranches(IList <Branch> branches, IList <LabelOperand> labels, LabelOperand defaultLabel)
        {
            var branchConditions = new HashSet <MondValue>();

            for (var i = 0; i < branches.Count; i++)
            {
                foreach (var condition in branches[i].Conditions)
                {
                    if (condition == null) // default
                    {
                        yield return(new JumpEntry(null, defaultLabel));

                        continue;
                    }

                    var constantExpression = condition as IConstantExpression;
                    if (constantExpression == null)
                    {
                        throw new MondCompilerException(condition, CompilerError.ExpectedConstant);
                    }

                    if (!branchConditions.Add(constantExpression.GetValue()))
                    {
                        throw new MondCompilerException(condition, CompilerError.DuplicateCase);
                    }

                    yield return(new JumpEntry(condition, labels[i]));
                }
            }
        }
Ejemplo n.º 16
0
 public void JumpTruePeek(LabelOperand label)
 {
     Emit(new Instruction(InstructionType.JmpTrueP, label));
 }
Ejemplo n.º 17
0
 public JumpEntry(Expression condition, LabelOperand label)
 {
     Condition = condition;
     Label     = label;
 }
Ejemplo n.º 18
0
 public void PushLoop(LabelOperand continueTarget, LabelOperand breakTarget)
 {
     _loopLabels.Push(Tuple.Create(continueTarget, breakTarget));
 }
Ejemplo n.º 19
0
 public void TailCall(int argumentCount, LabelOperand label)
 {
     Emit(new Instruction(InstructionType.TailCall, new ImmediateOperand(argumentCount), label));
 }
Ejemplo n.º 20
0
 public void Jump(LabelOperand label)
 {
     Emit(new Instruction(InstructionType.Jmp, label));
 }
Ejemplo n.º 21
0
 public void Closure(LabelOperand label)
 {
     Emit(new Instruction(InstructionType.Closure, label));
 }
Ejemplo n.º 22
0
 public void Bind(LabelOperand label)
 {
     Emit(new Instruction(InstructionType.Label, label));
 }