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; }
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); } }