Пример #1
0
        public Function ParseFunction(Node funcNode)
        {
            // Left node is identifier, right node is funcNode
            Expect(funcNode.Left, TokenType.Identifier);
            Expect(funcNode.Right, TokenType.Block);

            var func = new Function(funcNode, funcNode.Left.Value);

            if (funcNode.Right.Right == null)
            {
                return(func);
            }

            // Create a data label for this functions lr store
            var data = new Data(DataType.Return)
            {
                Name  = "return" + Data.Count,
                Type  = DataType.Word,
                Value = "0"
            };

            Data.Add(data);

            var lrRegister = func.AddRegister(data);

            func.StoreLr(data, lrRegister);

            // Iterate through statements in this functions block
            // Parse return separately
            var statement = funcNode.Right.Right;

            do
            {
                if (statement.Type == TokenType.Return)
                {
                    func.AddReturn(ParseReturn(func, statement));
                }
                else
                {
                    func.AddData(ParseStatement(func, statement));
                }

                statement = statement.Right;
            } while (statement != null);

            func.LoadLr(data, lrRegister);

            return(func);
        }
Пример #2
0
        /// <summary>
        /// Generate assembly code to load an identifier into a register.
        /// </summary>
        /// <param name="identifierNode">Node to generate for</param>
        /// <param name="parent">Parent containing assembly code</param>
        /// <param name="register">Register to load into</param>
        private void LoadIdentifier(Node identifierNode, Function parent, int register)
        {
            Logger.Instance.Debug("LoadIdentifier() {0}", identifierNode.ToString());
            var locData = GetDataWithName(parent, identifierNode.Value);

            // If this is an identifier we just load it into the right register
            var data = locData as Statement;

            if (data != null && data.Type != DataType.Function)
            {
                var s = data;
                if (register != s.Register) // Don't load it in if it is already in the right register
                {
                    parent.Lines.Add(string.Format("\tmov r{0}, r{1}\n", register, s.Register));
                }

                return;
            }

            // Otherwise, take a different action dpeending on data type
            switch (locData.Type)
            {
            case DataType.Global:     // if global, find the global and assemble from this parent
                var global = (Global)locData;
                parent.AssembleData(global.Datas, false, false);
                break;

            case DataType.Number:
                parent.Lines.Add(string.Format("\tmov r{0}, #{1}\n", register, locData.Value));
                break;

            case DataType.Asciz:
                parent.Lines.Add(string.Format("\tldr r{0}, addr_{1}\n", register, locData.Name));
                break;

            case DataType.Function:
                // Check if anything is already in r0 (function return)
                int?backupReg  = null;
                var backupData = parent.Registers.ElementAtOrDefault(0);
                if (backupData != null)
                {
                    // Move into an unused register
                    backupReg = parent.AddRegister(backupData) + 1;
                    parent.Lines.Add(string.Format("\tmov r{0}, r0\n", backupReg));
                }

                // Call function
                parent.Lines.Add(string.Format("\tbl {0}\n", locData.Value));

                // Result of function is in r0
                // Move that into the required register
                if (register != 0)
                {
                    parent.Lines.Add(string.Format("\tmov r{0}, r0\n", register));
                }

                // If data was backed up restore it
                if (backupReg != null)
                {
                    parent.Lines.Add(string.Format("\tmov r0, r{0}\n", backupReg));
                }

                break;

            case DataType.Operator:
                // Data is in a register in parent, find it and load it
                var regData = parent.Registers.FirstOrDefault(r => r.Name == locData.Name);
                if (regData == null)
                {
                    throw new Exception("Missing variable");
                }

                // Useless moving data into a register its already in
                var existingRegister = ((Statement)regData).Register;
                if (existingRegister != register)
                {
                    parent.Lines.Add(string.Format("\tmov r{0}, r{1}\n", register, existingRegister));
                }

                break;

            default:
                throw new NotImplementedException("Cannot load this data type as an identifier");
            }
        }