diff --git a/cranelift/src/libcretonne/repr.rs b/cranelift/src/libcretonne/repr.rs index 1318a0936a..7d11b62bd1 100644 --- a/cranelift/src/libcretonne/repr.rs +++ b/cranelift/src/libcretonne/repr.rs @@ -1,7 +1,7 @@ //! Representation of Cretonne IL functions. -use types::Type; +use types::{Type, FunctionName, Signature}; use immediates::*; use std::fmt::{self, Display, Formatter, Write}; use std::u32; @@ -39,6 +39,12 @@ pub const NO_VALUE: Value = Value(u32::MAX); /// container for those objects by implementing both `Index` and `Index`. /// pub struct Function { + /// Name of this function. Mostly used by `.cton` files. + name: FunctionName, + + /// Signature of this function. + signature: Signature, + /// Data about all of the instructions in the function. The instructions in this vector is not /// necessarily in program order. The `Inst` reference indexes into this vector. instructions: Vec, @@ -269,9 +275,11 @@ impl InstructionData { } impl Function { - /// Create a new empty function. - pub fn new() -> Function { + /// Create a function with the given name and signature. + pub fn with_name_signature(name: FunctionName, sig: Signature) -> Function { Function { + name: name, + signature: sig, instructions: Vec::new(), extended_basic_blocks: Vec::new(), extended_values: Vec::new(), @@ -279,6 +287,11 @@ impl Function { } } + /// Create a new empty, anomymous function. + pub fn new() -> Function { + Self::with_name_signature(FunctionName::new(), Signature::new()) + } + /// Resolve an instruction reference. pub fn inst(&self, i: Inst) -> &InstructionData { &self.instructions[i.0 as usize] diff --git a/cranelift/src/libcretonne/types.rs b/cranelift/src/libcretonne/types.rs index d54b3c51d0..9d4f2d93af 100644 --- a/cranelift/src/libcretonne/types.rs +++ b/cranelift/src/libcretonne/types.rs @@ -194,6 +194,12 @@ impl Display for Type { // // ====--------------------------------------------------------------------------------------====// +/// The name of a function can be any UTF-8 string. +/// +/// Function names are mostly a testing and debugging tool. In partucular, `.cton` files use +/// function names to identify functions. +pub type FunctionName = String; + /// Function argument extension options. /// /// On some architectures, small integer function arguments are extended to the width of a diff --git a/cranelift/src/libctonfile/parser.rs b/cranelift/src/libctonfile/parser.rs index a56d69df00..22b9adcc93 100644 --- a/cranelift/src/libctonfile/parser.rs +++ b/cranelift/src/libctonfile/parser.rs @@ -8,7 +8,8 @@ use std::result; use std::fmt::{self, Display, Formatter, Write}; use lexer::{self, Lexer, Token}; -use cretonne::{types, repr}; +use cretonne::types::{FunctionName, Signature, ArgumentType, ArgumentExtension}; +use cretonne::repr::Function; pub use lexer::Location; @@ -51,7 +52,7 @@ impl<'a> Parser<'a> { } /// Parse the entire string into a list of functions. - pub fn parse(text: &'a str) -> Result> { + pub fn parse(text: &'a str) -> Result> { Self::new(text).parse_function_list() } @@ -113,7 +114,7 @@ impl<'a> Parser<'a> { /// Parse a list of function definitions. /// /// This is the top-level parse function matching the whole contents of a file. - pub fn parse_function_list(&mut self) -> Result> { + pub fn parse_function_list(&mut self) -> Result> { let mut list = Vec::new(); while self.token().is_some() { list.push(try!(self.parse_function())); @@ -123,25 +124,36 @@ impl<'a> Parser<'a> { // Parse a whole function definition. // - // function ::= * "function" name signature { ... } + // function ::= * function-spec "{" preample function-body "}" // - fn parse_function(&mut self) -> Result { - try!(self.match_token(Token::Function, "expected 'function' keyword")); - - // function ::= "function" * name signature { ... } - let name = try!(self.parse_function_name()); - - // function ::= "function" name * signature { ... } - let sig = try!(self.parse_signature()); - - let mut func = repr::Function::new(); + fn parse_function(&mut self) -> Result { + let (name, sig) = try!(self.parse_function_spec()); + let mut func = Function::with_name_signature(name, sig); + // function ::= function-spec * "{" preample function-body "}" try!(self.match_token(Token::LBrace, "expected '{' before function body")); + // function ::= function-spec "{" preample function-body * "}" try!(self.match_token(Token::RBrace, "expected '}' after function body")); Ok(func) } + // Parse a function spec. + // + // function-spec ::= * "function" name signature + // + fn parse_function_spec(&mut self) -> Result<(FunctionName, Signature)> { + try!(self.match_token(Token::Function, "expected 'function' keyword")); + + // function-spec ::= "function" * name signature + let name = try!(self.parse_function_name()); + + // function-spec ::= "function" name * signature + let sig = try!(self.parse_signature()); + + Ok((name, sig)) + } + // Parse a function name. // // function ::= "function" * name signature { ... } @@ -160,8 +172,8 @@ impl<'a> Parser<'a> { // // signature ::= * "(" [arglist] ")" ["->" retlist] [call_conv] // - fn parse_signature(&mut self) -> Result { - let mut sig = types::Signature::new(); + fn parse_signature(&mut self) -> Result { + let mut sig = Signature::new(); try!(self.match_token(Token::LPar, "expected function signature: ( args... )")); // signature ::= "(" * [arglist] ")" ["->" retlist] [call_conv] @@ -182,7 +194,7 @@ impl<'a> Parser<'a> { // // arglist ::= * arg { "," arg } // - fn parse_argument_list(&mut self) -> Result> { + fn parse_argument_list(&mut self) -> Result> { let mut list = Vec::new(); // arglist ::= * arg { "," arg } @@ -198,10 +210,10 @@ impl<'a> Parser<'a> { } // Parse a single argument type with flags. - fn parse_argument_type(&mut self) -> Result { + fn parse_argument_type(&mut self) -> Result { // arg ::= * type { flag } let mut arg = if let Some(Token::Type(t)) = self.token() { - types::ArgumentType::new(t) + ArgumentType::new(t) } else { return Err(self.error("expected argument type")); }; @@ -210,8 +222,8 @@ impl<'a> Parser<'a> { // arg ::= type * { flag } while let Some(Token::Identifier(s)) = self.token() { match s { - "uext" => arg.extension = types::ArgumentExtension::Uext, - "sext" => arg.extension = types::ArgumentExtension::Sext, + "uext" => arg.extension = ArgumentExtension::Uext, + "sext" => arg.extension = ArgumentExtension::Sext, "inreg" => arg.inreg = true, _ => break, }