예제 #1
0
        private void GenerateFunction(FunctionNode function)
        {
            // No need to generate non-definitions
            if (!function.IsDefinition)
            {
                return;
            }

            currentFunction = function;
            labelCounter    = 0;

            localVariableMaps.Push(new LocalVariableMap());
            // Add local variables to the map
            int i = 0;

            foreach (var var in function.Parameters)
            {
                CurrentVariableMap.AddParamInt(var, i++);
            }

            // Function label
            writer.WriteLine(".globl {0}", GetFunctionLabel(function.Name));
            writer.WriteLine(GetFunctionLabel(function.Name) + ":");

            // Function prologue, epiloge is included in return statement generation
            writer.WriteLine("push    %ebp");           // Store ebp on the stack
            writer.WriteLine("movl    %esp, %ebp");     // Use the current esp as our ebp
                                                        // TODO: Add more prologue/epilogue depending on calling conventions?

            // Process all block items
            foreach (var item in function.BodyItems)
            {
                GenerateBlockItem(item);
            }

            currentFunction = null;
        }
예제 #2
0
        private FunctionNode ParseFunction()
        {
            // Return type of the function
            var typeToken = tokens.Dequeue() as FixedToken;

            if (typeToken == null || typeToken.TokenKind != FixedToken.Kind.Int)
            {
                throw new UnexpectedTokenException("Did not get Int token", typeToken);
            }

            // Identifier of the function
            var nameToken = TakeIdentifierToken();

            // Opening parenthesis
            TakeFixedToken(FixedToken.Kind.ParOpen);
            // Parse parameters until we hit and take the closing parenthesis
            var parameters = new List <string>();

            while (!TryTakeFixedToken(FixedToken.Kind.ParClose))
            {
                // TODO: Other types...
                if (parameters.Count > 0)
                {
                    // Not the first parameter, so we should have a comma
                    TakeFixedToken(FixedToken.Kind.Comma);
                }
                TakeFixedToken(FixedToken.Kind.Int);        // int
                var name = TakeIdentifierToken().Name;      // name
                if (parameters.Contains(name))
                {
                    throw new ParsingException(string.Format("Duplicate parameter name {0} in function {1}", name, nameToken.Name));
                }
                parameters.Add(name);
            }

            // We should get either a semi or a opening bracket
            if (TryTakeFixedToken(FixedToken.Kind.SemiColon))
            {
                // This is just a declaration
                var node = new FunctionNode(nameToken.Name, parameters, null);
                if (functionDeclarations.ContainsKey(nameToken.Name) &&
                    functionDeclarations[nameToken.Name].Parameters.Count != parameters.Count)
                {
                    throw new ParsingException("Conflicting function declarations for " + nameToken.Name);
                }
                functionDeclarations[node.Name] = node;
                return(node);
            }
            else
            {
                // This should be a definition, but register declaration first to allow recursion
                var tmpDefNode = new FunctionNode(nameToken.Name, parameters, null);
                if (functionDeclarations.ContainsKey(nameToken.Name) &&
                    functionDeclarations[nameToken.Name].Parameters.Count != parameters.Count)
                {
                    throw new ParsingException("Conflicting function declarations for " + nameToken.Name);
                }
                functionDeclarations[tmpDefNode.Name] = tmpDefNode;

                // Opening bracket
                TakeFixedToken(FixedToken.Kind.BracketOpen);

                // Parse statements until we find (and take!) a closing bracket after one
                var blockItems = new List <BlockItemNode>();
                while (!TryTakeFixedToken(FixedToken.Kind.BracketClose))
                {
                    var statement = ParseBlockItem();
                    blockItems.Add(statement);
                }
                ;

                // Check if we are missing a return statement. If so add a return 0;
                // TODO: Update this to handle void and other return types when we get to it
                if (blockItems.Count == 0 || !(blockItems[blockItems.Count - 1] is ReturnNode))
                {
                    blockItems.Add(new ReturnNode(new ConstantNode(0)));
                }

                // Create definition node
                var node = new FunctionNode(nameToken.Name, parameters, blockItems);
                if (functionDeclarations.ContainsKey(nameToken.Name) &&
                    functionDeclarations[nameToken.Name].Parameters.Count != parameters.Count)
                {
                    throw new ParsingException("Conflicting function declarations for " + nameToken.Name);
                }
                functionDeclarations[node.Name] = node;
                if (functionDefinitions.ContainsKey(node.Name))
                {
                    throw new ParsingException("More than 1 function definition for" + nameToken.Name);
                }
                functionDefinitions.Add(node.Name, node);
                return(node);
            }
        }