Add FunctionName, Signature to repr::Function.
Simplify the uses in parser.rs to avoid too many module qualifiers.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
//! Representation of Cretonne IL functions.
|
//! Representation of Cretonne IL functions.
|
||||||
|
|
||||||
use types::Type;
|
use types::{Type, FunctionName, Signature};
|
||||||
use immediates::*;
|
use immediates::*;
|
||||||
use std::fmt::{self, Display, Formatter, Write};
|
use std::fmt::{self, Display, Formatter, Write};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
@@ -39,6 +39,12 @@ pub const NO_VALUE: Value = Value(u32::MAX);
|
|||||||
/// container for those objects by implementing both `Index<Inst>` and `Index<Ebb>`.
|
/// container for those objects by implementing both `Index<Inst>` and `Index<Ebb>`.
|
||||||
///
|
///
|
||||||
pub struct Function {
|
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
|
/// 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.
|
/// necessarily in program order. The `Inst` reference indexes into this vector.
|
||||||
instructions: Vec<InstructionData>,
|
instructions: Vec<InstructionData>,
|
||||||
@@ -269,9 +275,11 @@ impl InstructionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
/// Create a new empty function.
|
/// Create a function with the given name and signature.
|
||||||
pub fn new() -> Function {
|
pub fn with_name_signature(name: FunctionName, sig: Signature) -> Function {
|
||||||
Function {
|
Function {
|
||||||
|
name: name,
|
||||||
|
signature: sig,
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
extended_basic_blocks: Vec::new(),
|
extended_basic_blocks: Vec::new(),
|
||||||
extended_values: 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.
|
/// Resolve an instruction reference.
|
||||||
pub fn inst(&self, i: Inst) -> &InstructionData {
|
pub fn inst(&self, i: Inst) -> &InstructionData {
|
||||||
&self.instructions[i.0 as usize]
|
&self.instructions[i.0 as usize]
|
||||||
|
|||||||
@@ -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.
|
/// Function argument extension options.
|
||||||
///
|
///
|
||||||
/// On some architectures, small integer function arguments are extended to the width of a
|
/// On some architectures, small integer function arguments are extended to the width of a
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
use std::result;
|
use std::result;
|
||||||
use std::fmt::{self, Display, Formatter, Write};
|
use std::fmt::{self, Display, Formatter, Write};
|
||||||
use lexer::{self, Lexer, Token};
|
use lexer::{self, Lexer, Token};
|
||||||
use cretonne::{types, repr};
|
use cretonne::types::{FunctionName, Signature, ArgumentType, ArgumentExtension};
|
||||||
|
use cretonne::repr::Function;
|
||||||
|
|
||||||
pub use lexer::Location;
|
pub use lexer::Location;
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the entire string into a list of functions.
|
/// Parse the entire string into a list of functions.
|
||||||
pub fn parse(text: &'a str) -> Result<Vec<repr::Function>> {
|
pub fn parse(text: &'a str) -> Result<Vec<Function>> {
|
||||||
Self::new(text).parse_function_list()
|
Self::new(text).parse_function_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// Parse a list of function definitions.
|
/// Parse a list of function definitions.
|
||||||
///
|
///
|
||||||
/// This is the top-level parse function matching the whole contents of a file.
|
/// This is the top-level parse function matching the whole contents of a file.
|
||||||
pub fn parse_function_list(&mut self) -> Result<Vec<repr::Function>> {
|
pub fn parse_function_list(&mut self) -> Result<Vec<Function>> {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
while self.token().is_some() {
|
while self.token().is_some() {
|
||||||
list.push(try!(self.parse_function()));
|
list.push(try!(self.parse_function()));
|
||||||
@@ -123,25 +124,36 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Parse a whole function definition.
|
// Parse a whole function definition.
|
||||||
//
|
//
|
||||||
// function ::= * "function" name signature { ... }
|
// function ::= * function-spec "{" preample function-body "}"
|
||||||
//
|
//
|
||||||
fn parse_function(&mut self) -> Result<repr::Function> {
|
fn parse_function(&mut self) -> Result<Function> {
|
||||||
try!(self.match_token(Token::Function, "expected 'function' keyword"));
|
let (name, sig) = try!(self.parse_function_spec());
|
||||||
|
let mut func = Function::with_name_signature(name, sig);
|
||||||
// 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();
|
|
||||||
|
|
||||||
|
// function ::= function-spec * "{" preample function-body "}"
|
||||||
try!(self.match_token(Token::LBrace, "expected '{' before 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"));
|
try!(self.match_token(Token::RBrace, "expected '}' after function body"));
|
||||||
|
|
||||||
Ok(func)
|
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.
|
// Parse a function name.
|
||||||
//
|
//
|
||||||
// function ::= "function" * name signature { ... }
|
// function ::= "function" * name signature { ... }
|
||||||
@@ -160,8 +172,8 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// signature ::= * "(" [arglist] ")" ["->" retlist] [call_conv]
|
// signature ::= * "(" [arglist] ")" ["->" retlist] [call_conv]
|
||||||
//
|
//
|
||||||
fn parse_signature(&mut self) -> Result<types::Signature> {
|
fn parse_signature(&mut self) -> Result<Signature> {
|
||||||
let mut sig = types::Signature::new();
|
let mut sig = Signature::new();
|
||||||
|
|
||||||
try!(self.match_token(Token::LPar, "expected function signature: ( args... )"));
|
try!(self.match_token(Token::LPar, "expected function signature: ( args... )"));
|
||||||
// signature ::= "(" * [arglist] ")" ["->" retlist] [call_conv]
|
// signature ::= "(" * [arglist] ")" ["->" retlist] [call_conv]
|
||||||
@@ -182,7 +194,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// arglist ::= * arg { "," arg }
|
// arglist ::= * arg { "," arg }
|
||||||
//
|
//
|
||||||
fn parse_argument_list(&mut self) -> Result<Vec<types::ArgumentType>> {
|
fn parse_argument_list(&mut self) -> Result<Vec<ArgumentType>> {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
|
|
||||||
// arglist ::= * arg { "," arg }
|
// arglist ::= * arg { "," arg }
|
||||||
@@ -198,10 +210,10 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse a single argument type with flags.
|
// Parse a single argument type with flags.
|
||||||
fn parse_argument_type(&mut self) -> Result<types::ArgumentType> {
|
fn parse_argument_type(&mut self) -> Result<ArgumentType> {
|
||||||
// arg ::= * type { flag }
|
// arg ::= * type { flag }
|
||||||
let mut arg = if let Some(Token::Type(t)) = self.token() {
|
let mut arg = if let Some(Token::Type(t)) = self.token() {
|
||||||
types::ArgumentType::new(t)
|
ArgumentType::new(t)
|
||||||
} else {
|
} else {
|
||||||
return Err(self.error("expected argument type"));
|
return Err(self.error("expected argument type"));
|
||||||
};
|
};
|
||||||
@@ -210,8 +222,8 @@ impl<'a> Parser<'a> {
|
|||||||
// arg ::= type * { flag }
|
// arg ::= type * { flag }
|
||||||
while let Some(Token::Identifier(s)) = self.token() {
|
while let Some(Token::Identifier(s)) = self.token() {
|
||||||
match s {
|
match s {
|
||||||
"uext" => arg.extension = types::ArgumentExtension::Uext,
|
"uext" => arg.extension = ArgumentExtension::Uext,
|
||||||
"sext" => arg.extension = types::ArgumentExtension::Sext,
|
"sext" => arg.extension = ArgumentExtension::Sext,
|
||||||
"inreg" => arg.inreg = true,
|
"inreg" => arg.inreg = true,
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user