예제 #1
0
        /// <summary>
        /// Converts a ProgramBlock to C.
        /// </summary>
        /// <param name="block">ProgramBlock to convert.</param>
        /// <returns>ProgramBlock in C.</returns>
        public string[] EmitBlock(ProgramBlock block)
        {
            LinkedList<string> blockList = new LinkedList<string>();
            string[] blockSource;

            blockList.AddLast("{");

            foreach (IProgramChunk chunk in block.Program)
            {
                foreach(string line in EmitChunk(chunk))
                    blockList.AddLast(line);
            }

            blockList.AddLast("}");

            blockSource = new string[blockList.Count];
            blockList.CopyTo(blockSource, 0);

            return blockSource;
        }
예제 #2
0
        //HACK: there should be a better way.
        /// <summary>
        /// Decompiles source code in a given array. The result is placed into the TextBox that was passed.
        /// </summary>
        /// <param name="assemblyFile">Array of strings containting code.</param>
        /// <param name="TextBoxOutput">TextBox that result will be copied to.</param>
        public void DecompileAssembly(string[] assemblyFile, TextBox TextBoxOutput)
        {
            //TODO: we need to identify blocks here and split them apart.
            ProgramBlock newBlock = new ProgramBlock();
            string[] sourceFile;

            activeFrontend.Preprocess(assemblyFile);

            foreach(string line in assemblyFile)
            {
                try
                {
                    newBlock.Program.AddLast(activeFrontend.TranslateLine(line, newBlock));
                }
                catch (Exception err)
                {
                    UtilDebugConsole.AddException(err);
                }
            }

            SimplifyStructures.SimplifyProgramBlock(newBlock);

            sourceFile = activeBackend.EmitBlock(newBlock);

            sourceFile = activeBackend.ProcessOutput(sourceFile);

            if(!newBlock.IsSane())
                UtilDebugConsole.AddException(new ExceptionWarning("DeAssembly - Insane Blocks were found."));

            if (assemblyFile.Length != sourceFile.Length)
                UtilDebugConsole.AddException(new ExceptionWarning("The number of input and output lines differ, GUI may function incorrectly."));

            //FIXME: this should really be in the gui code, however, if we pass the
            //textbox as a object it doesn't update. And we can't ref it either.
            TextBoxOutput.Lines = sourceFile;
        }
예제 #3
0
        private static void SimplifyLoops(ProgramBlock currentBlock)
        {
            //Attempt at detecting loops; starting with a simple branch/j loop and moving on to variable initializations afterward
            //Note: The label/assignment checks and jump/branch checks are
            //put in seperate foreach statements because this way the lists
            //will be complete by the time it checks the jumps

            ProgramBlock codeToDelete = new ProgramBlock();
            ProgramChunkLoop newLoop = null;
            ProgramChunkJumpTarget startLabel = null;

            foreach (IProgramChunk chunk in currentBlock.Program)
            {
                //This checks a program chunk in order to see if it is part of a loop.

                if (chunk is ProgramChunkJumpTarget)
                {
                    currentBlock.ProgramAllJumpTargets.AddLast(chunk); //Add branch label to list to check on a jump
                }
                if (chunk is ProgramChunkAssignment)
                {
                    currentBlock.ProgramAllIncrementers.AddLast(chunk); //Add incrementer to list to check on a jump
                }
            }

            foreach (IProgramChunk chunk in currentBlock.Program)
            {
                if (chunk is ProgramChunkJumpUnconditional) //Check all the jump statements
                {
                    foreach (IProgramChunk chunk2 in currentBlock.ProgramAllJumpTargets)
                    {
                        if (((ProgramChunkJumpUnconditional)chunk).Target == chunk2) //Continue only if a jump statement branches to something in the list of labels
                        {
                            //Label and jump to label detected; if label is before jump loop will be detected
                            //This check determines if the specified label occurs before the jump to it

                            foreach (IProgramChunk chunk3 in currentBlock.Program)
                            {
                                if (chunk3 is ProgramChunkJumpTarget)
                                {
                                    if (chunk3 == chunk2) //Branch label comes first, loop detected
                                    {
                                        UtilDebugConsole.AddMessage("Loop involving an unconditional jump found");

                                        /*This section of code will use a while loop to run through the code.
                                         Upon detecting chunk2 (the label), it will create a list of the
                                         loop code AS WELL as the code inside the loop.  Upon detecting
                                         chunk, the code will stop writing to both lists.  At this point, one
                                         list will hold the whole loop and one will hold the code within the
                                         loop.  A loop will then be created using chunk, chunk2, and the
                                         linked list of the code within the loop, with everything in the
                                         linked list of the whole loop being deleted from the linked list of
                                         the entire program.  */

                                        ProgramBlock loopInnerCode = new ProgramBlock();
                                        ProgramBlock loopOuterCode = new ProgramBlock();
                                        bool copyCode = false;

                                        foreach (IProgramChunk loopRearrange in currentBlock.Program)
                                        {

                                            if (loopRearrange is ProgramChunkJumpTarget)
                                            {
                                                if (loopRearrange == chunk2)
                                                {
                                                    loopOuterCode.Program.AddLast(loopRearrange);
                                                    copyCode = true;
                                                    //UtilDebugConsole.AddMessage("Added label to ProgramChunkLoop");

                                                }
                                            }
                                            else if (loopRearrange is ProgramChunkJumpUnconditional) //Upon detecting jump, stop writing to lists
                                            {
                                                if (loopRearrange == chunk)
                                                {
                                                    loopOuterCode.Program.AddLast(loopRearrange);
                                                    copyCode = false;
                                                    //UtilDebugConsole.AddMessage("Added jump to ProgramChunkLoop");
                                                }
                                            }
                                            if ((copyCode == true) && (loopRearrange != chunk2)) //The second part of this check is here because the way this is set up this will run upon detecting the label
                                            { //Write all code to inside of loop but only if it's detected the label
                                                loopOuterCode.Program.AddLast(loopRearrange);
                                                loopInnerCode.Program.AddLast(loopRearrange);
                                                //UtilDebugConsole.AddMessage("Added line to ProgramChunkLoop");
                                            }

                                        }
                                        newLoop = new ProgramChunkLoop(loopInnerCode);
                                        // // // Code to add ProgramChunkLoop before chunk2 goes here; I can't figure out how to change the input to fit the required function // // //
                                        //currentBlock.Program.AddBefore(currentBlock.Program.Last, newLoop);

                                        foreach (IProgramChunk loopDelete in loopOuterCode.Program) {
                                            codeToDelete.Program.AddLast(loopDelete);
                                        }

                                    }
                                }
                                else if (chunk3 is ProgramChunkJumpUnconditional)
                                {
                                    if (chunk3 == chunk) //Jump comes first, not a loop
                                        break;
                                }
                            }

                        }
                    }
                }
            }

            //find label that code should be added before
            foreach (IProgramChunk chunk in codeToDelete.Program)
                if (chunk is ProgramChunkJumpTarget)
                {
                    startLabel = (ProgramChunkJumpTarget)chunk;
                    break;
                }

            //HACK:
            if (newLoop != null)
                currentBlock.Program.AddBefore(currentBlock.Program.Find(startLabel), newLoop);

            foreach (IProgramChunk loopDelete in codeToDelete.Program)
            {
                currentBlock.Program.Remove(loopDelete);
            }

            /* Code required for this isn't implemented yet, commenting this part out
            foreach (IProgramChunk chunk in currentBlock.Program)
            {
                //This code will supposedly work despite the lack of checking if
                //the incrementor is inside the loop; it assumes that the code
                //passed through it has been checked beforehand.  This check
                //should likely be added in though, as the code might not have
                //been checked manually.
                if (chunk is ProgramChunkBranch)
                {
                    foreach (IProgramChunk chunk2 in currentBlock.ProgramAllIncrementers)
                    {
                        //if (((ProgramChunkBranch)chunk).NOT IMPLEMENTED YET == chunk2 //Checks if variable associated with branch is same as incrementer
                        foreach (IProgramChunk chunk3 in currentBlock.ProgramAllJumpTargets)
                        {
                            if (((ProgramChunkJumpUnconditional)chunk).Target == chunk3) //Checks if target associated with jump is same as branch
                            {
                                UtilDebugConsole.AddMessage("Possible loop involving a branch found");
                            }
                        }
                        //}
                    }
                }
            }
            */
        }
예제 #4
0
 public static void SimplifyProgramBlock(ProgramBlock workingBlock)
 {
     SimplifyLoops(workingBlock);
 }
예제 #5
0
        //Returns a ProgramBlock from a given list of IProgramChunks.
        public ProgramBlock GenerateSubProgramBlock(LinkedList<IProgramChunk> chunks)
        {
            ProgramBlock subBlock = new ProgramBlock();

            //Move chunks to new ProgramBlock.
            foreach (IProgramChunk chunk in chunks)
                subBlock.Program.AddLast(chunk);

            //Remove those chunks from this ProgramBlock.
            foreach (IProgramChunk chunk in chunks)
                program.Remove(chunk);

            return subBlock;
        }
예제 #6
0
        /// <summary>
        /// Translates a line of MIPS assembly into the intermediate format and returns
        /// the result.
        /// </summary>
        /// <param name="assembly">MIPS assembly.</param>
        /// <param name="parentBlock">ProgramBlock containing previously translated code
        /// and associated information</param>
        /// <returns>Translated chunk.</returns>
        public IProgramChunk TranslateLine(string assembly, ProgramBlock parentBlock)
        {
            IProgramChunk translatedChunk = null;

            //***LABELS***
            if (assembly.Contains(":"))
            {
                string labelName = assembly.Substring(0, assembly.IndexOf(":"));

                //label does not exist as an orphan
                if(parentBlock.GetOrphanJumpTargetByLabel(labelName) == null)
                    translatedChunk = new ProgramChunkJumpTarget(labelName);
                //label does exist as an orphan.
                else
                {
                    translatedChunk = parentBlock.GetOrphanJumpTargetByLabel(labelName);
                    parentBlock.RemoveOrphanJumpTarget(parentBlock.GetOrphanJumpTargetByLabel(labelName));
                }
            }
            //**KEYWORDS**
            else
            {
                string lineKeyword = assembly.Split(' ')[0];
                string[] lineParameters = assembly.Substring(assembly.IndexOf(' ') + 1).Split(' ');

                switch (lineKeyword)
                {
                    #region J - Unconditional Jump
                    case "j":
                    {
                        ProgramChunkJumpTarget target = parentBlock.GetJumpTargetByLabel(lineParameters[0]);

                        //label does not exist but should be defined later. create an orphan placeholder.
                        if (target == null)
                        {
                            target = new ProgramChunkJumpTarget(lineParameters[0]);
                            parentBlock.AddOrphanJumpTarget(target);
                        }

                        translatedChunk = new ProgramChunkJumpUnconditional(target);
                    }
                    break;
                    #endregion

                    #region Form: (command) product, multiplicand, multiplier

                    case "addi":
                    case "add":
                    case "sllv"://SLL - Shift Left Logical (variable)
                    case "sll": //SLL - Shift Left Logical (constant)
                    case "sub":
                    case "subi":
                        //Form: (command) product, multiplicand, multiplier
                        //see below (or above i guess) to see acceptable commands

                        //Addition: 'add', and 'addi' (default)
                        Operand commandOperand = Operand.ADDITION;

                        //Multiplication: 'sll', and 'sllv'
                        if(lineKeyword.Equals("sll") || lineKeyword.Equals("sllv"))
                            commandOperand = Operand.MULTIPLICATION;

                        //Subtraction: 'sub', and 'subi'
                        if(lineKeyword.Equals("sub") || lineKeyword.Equals("subi"))
                            commandOperand = Operand.SUBTRACTION;

                        BlockVariable termAssignee;  //must be variable
                        ProgramChunkExpressionTerm termMultiplicand;//constant or variable? I think the doc only support var's
                        ProgramChunkExpressionTerm termMultiplier; //constant or variable

                        #region 1) find assignee

                        if (IsVariable(lineParameters[0]))
                        {
                            ProcessVariable(ref lineParameters[0]);

                            BlockVariable variable = parentBlock.GetVariableByNameForced(lineParameters[0]);

                            termAssignee = variable;
                        }
                        else
                            throw new Exception("FrontendMIPS - Detected attempt to assign expression to constant.");

                        #endregion

                        #region 2) find multiplicand

                        if (IsVariable(lineParameters[1]))
                        {
                            ProcessVariable(ref lineParameters[1]);

                            BlockVariable variable = parentBlock.GetVariableByNameForced(lineParameters[1]);

                            termMultiplicand = variable;
                        }
                        else //The first (real) term is a constant
                        {
                            //CHECKME: attempt to parse hex numbers, does it work this way?
                            int term = int.Parse(lineParameters[1], System.Globalization.NumberStyles.HexNumber);

                            termMultiplicand = new BlockConstant(term);
                        }

                        #endregion

                        #region 3) find multiplier

                        if (IsVariable(lineParameters[2]))
                        {
                            ProcessVariable(ref lineParameters[2]);

                            BlockVariable variable = parentBlock.GetVariableByNameForced(lineParameters[2]);

                            termMultiplier = variable;
                        }
                        else//constant
                        {
                            //TODO: support hex numbers
                            if(lineParameters[2].Contains("x"))
                                throw new Exception("FrontendMIPS - Cannot parse hexidecimal numbers.");

                            int term = int.Parse(lineParameters[2]);

                            //deal with bit shifts
                            if (lineKeyword.Equals("sll"))
                                term *= 2;
                            else if (lineKeyword.Equals("sllv"))
                                throw new Exception("FrontendMIPS - Cannot bit shift by variable without subexpression support.");

                            termMultiplier = new BlockConstant(term);
                        }

                        #endregion

                        ProgramChunkExpression expression = new ProgramChunkExpression(termMultiplicand, commandOperand, termMultiplier);

                        translatedChunk = new ProgramChunkAssignment(termAssignee, expression);
                        break;
                    #endregion

                    #region Branchs (BNE, BEQ)

                    //Form: if (var equality var) goto label.
                    //e.g. "beq $a1 0 finish"
                    case "bne":
                    case "beq":
                    {
                        Equality equality;
                        ProgramChunkExpressionTerm first;
                        ProgramChunkExpressionTerm second;
                        ProgramChunkJumpTarget target;

                        #region 1) determine equality

                        if (lineKeyword.Equals("bne"))
                            equality = Equality.NOT_EQUAL;
                        else if (lineKeyword.Equals("beq"))
                            equality = Equality.EQUAL;
                        else
                            throw new Exception("FrontendMIPS - Unimplemented equality found.");

                        #endregion

                        #region 2) find first item to evaluate

                        if (IsVariable(lineParameters[0]))
                        {
                            ProcessVariable(ref lineParameters[0]);
                            first = parentBlock.GetVariableByNameForced(lineParameters[0]);
                        }
                        else //constant
                        {
                            //TODO: support hex numbers
                            if (lineParameters[0].Contains("x"))
                                throw new Exception("FrontendMIPS - Cannot parse hexidecimal numbers.");

                            first = new BlockConstant(int.Parse(lineParameters[0]));
                        }

                        #endregion

                        #region 3) find second item to evaluate

                        if (IsVariable(lineParameters[1]))
                        {
                            ProcessVariable(ref lineParameters[1]);
                            second = parentBlock.GetVariableByNameForced(lineParameters[1]);
                        }
                        else //constant
                        {
                            //TODO: support hex numbers
                            if (lineParameters[1].Contains("x"))
                                throw new Exception("FrontendMIPS - Cannot parse hexidecimal numbers.");

                            second = new BlockConstant(int.Parse(lineParameters[1]));
                        }

                        #endregion

                        #region 4) generate jump for true

                        target = parentBlock.GetJumpTargetByLabel(lineParameters[2]);

                        //label does not exist but should be defined later. create an orphan placeholder.
                        if (target == null)
                        {
                            target = new ProgramChunkJumpTarget(lineParameters[2]);
                            parentBlock.AddOrphanJumpTarget(target);
                        }

                        #endregion

                        translatedChunk = new ProgramChunkBranch(equality, first, new ProgramChunkJumpUnconditional(target), second, new ProgramChunkNoOperation());
                    }
                    break;

                    #endregion
                }
            }

            if (translatedChunk == null)
            {
                translatedChunk = new ProgramChunkNoOperation();
                UtilDebugConsole.AddException(new Exception("FrontendMIPS - Unidentified assembly encountered during translation."));
            }

            return translatedChunk;
        }