示例#1
0
            private static unsafe Jsm.ExecutableSegment MakeScript(Operation *operation, UInt16 count)
            {
                List <JsmInstruction> instructions = new List <JsmInstruction>(count / 2);
                LabeledStack          stack        = new LabeledStack();
                LabelBuilder          labelBuilder = new LabelBuilder(count);

                for (Int32 i = 0; i < count; i++)
                {
                    Jsm.Opcode opcode    = operation->Opcode;
                    Int32      parameter = operation->Parameter;
                    operation++;

                    stack.CurrentLabel = i;
                    IJsmExpression expression = Jsm.Expression.TryMake(opcode, parameter, stack);
                    if (expression != null)
                    {
                        stack.Push(expression);
                        continue;
                    }

                    JsmInstruction instruction = JsmInstruction.TryMake(opcode, parameter, stack);
                    if (instruction != null)
                    {
                        labelBuilder.TraceInstruction(i, stack.CurrentLabel, new IndexedInstruction(instructions.Count, instruction));
                        instructions.Add(instruction);
                        continue;
                    }

                    throw new NotSupportedException(opcode.ToString());
                }

                if (stack.Count != 0)
                {
                    throw new InvalidProgramException("Stack unbalanced.");
                }

                if (!(instructions.First() is LBL))
                {
                    throw new InvalidProgramException("Script must start with a label.");
                }

                if (!(instructions.Last() is IRET))
                {
                    throw new InvalidProgramException("Script must end with a return.");
                }

                // Switch from opcodes to instructions
                HashSet <Int32> labelIndices = labelBuilder.Commit();

                // Merge similar instructions
                instructions = InstructionMerger.Merge(instructions, labelIndices);

                // Combine instructions to logical blocks
                IReadOnlyList <Jsm.IJsmControl> controls = Jsm.Control.Builder.Build(instructions);

                // Arrange instructions by segments and return root
                return(Jsm.Segment.Builder.Build(instructions, controls));
            }
示例#2
0
                private void FormatBranch(StringBuilder sb, Segment range)
                {
                    sb.AppendLine("{");
                    for (Int32 i = range.From + 1; i < range.To; i++)
                    {
                        JsmInstruction instruction = _instructions[i];
                        sb.Append('\t').AppendLine(instruction.ToString());
                    }

                    sb.AppendLine("}");
                }
示例#3
0
            public static List <JsmInstruction> Merge(List <JsmInstruction> instructions, HashSet <Int32> labelIndices)
            {
                List <JsmInstruction> result = new List <JsmInstruction>(instructions.Count);

                for (Int32 i = 0; i < instructions.Count; i++)
                {
                    JsmInstruction instruction = instructions[i];
                    result.Add(instruction);
                    if (labelIndices.Contains(i))
                    {
                        continue;
                    }

                    if (!(instructions[i] is JPF newJpf))
                    {
                        continue;
                    }

                    if (i + 1 < instructions.Count && instructions[i + 1] is JMP nextJmp)
                    {
                        newJpf.Inverse(nextJmp);
                    }

                    if (!(result[result.Count - 2] is JPF oldJpf))
                    {
                        continue;
                    }

                    if (oldJpf.Index != newJpf.Index)
                    {
                        continue;
                    }

                    Int32 currentIndex = result.LastIndex();

                    oldJpf.Union(newJpf);
                    result.RemoveLast();
                    oldJpf.Index--;

                    for (Int32 k = 0; k < instructions.Count; k++)
                    {
                        if (instructions[k] is IJumpToInstruction jmp && jmp.Index >= currentIndex && jmp != oldJpf)
                        {
                            jmp.Index--;
                        }
                    }
                }

                return(result);
            }
示例#4
0
                public override String ToString()
                {
                    StringBuilder sb = new StringBuilder();

                    sb.Append("while(");
                    sb.Append((JPF)_instructions[_segment.From]);
                    sb.AppendLine(")");

                    sb.AppendLine("{");
                    for (Int32 i = _segment.From + 1; i < _segment.To; i++)
                    {
                        JsmInstruction instruction = _instructions[i];
                        sb.Append('\t').AppendLine(instruction.ToString());
                    }

                    sb.AppendLine("}");

                    return(base.ToString());
                }
 public IndexedInstruction(Int32 index, JsmInstruction instruction)
 {
     Index       = index;
     Instruction = instruction;
 }