Rename more Error and Result types.
This commit is contained in:
@@ -36,7 +36,7 @@ def gen_to_and_from_str(ty, values, fmt):
|
|||||||
with fmt.indented('impl str::FromStr for {} {{'.format(ty), '}'):
|
with fmt.indented('impl str::FromStr for {} {{'.format(ty), '}'):
|
||||||
fmt.line('type Err = ();')
|
fmt.line('type Err = ();')
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'fn from_str(s: &str) -> result::Result<Self, Self::Err> {',
|
'fn from_str(s: &str) -> Result<Self, Self::Err> {',
|
||||||
'}'):
|
'}'):
|
||||||
with fmt.indented('match s {', '}'):
|
with fmt.indented('match s {', '}'):
|
||||||
for v in values:
|
for v in values:
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ use isa::enc_tables::Encodings;
|
|||||||
use regalloc;
|
use regalloc;
|
||||||
use result::CodegenResult;
|
use result::CodegenResult;
|
||||||
use settings;
|
use settings;
|
||||||
use settings::CallConv;
|
use settings::{CallConv, SetResult};
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use target_lexicon::{Architecture, Triple};
|
use target_lexicon::{Architecture, Triple};
|
||||||
@@ -146,11 +146,11 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl settings::Configurable for Builder {
|
impl settings::Configurable for Builder {
|
||||||
fn set(&mut self, name: &str, value: &str) -> settings::Result<()> {
|
fn set(&mut self, name: &str, value: &str) -> SetResult<()> {
|
||||||
self.setup.set(name, value)
|
self.setup.set(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(&mut self, name: &str) -> settings::Result<()> {
|
fn enable(&mut self, name: &str) -> SetResult<()> {
|
||||||
self.setup.enable(name)
|
self.setup.enable(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ use constant_hash::{probe, simple_hash};
|
|||||||
use isa::TargetIsa;
|
use isa::TargetIsa;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::result;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// A string-based configurator for settings groups.
|
/// A string-based configurator for settings groups.
|
||||||
@@ -35,12 +34,12 @@ pub trait Configurable {
|
|||||||
/// Set the string value of any setting by name.
|
/// Set the string value of any setting by name.
|
||||||
///
|
///
|
||||||
/// This can set any type of setting whether it is numeric, boolean, or enumerated.
|
/// This can set any type of setting whether it is numeric, boolean, or enumerated.
|
||||||
fn set(&mut self, name: &str, value: &str) -> Result<()>;
|
fn set(&mut self, name: &str, value: &str) -> SetResult<()>;
|
||||||
|
|
||||||
/// Enable a boolean setting or apply a preset.
|
/// Enable a boolean setting or apply a preset.
|
||||||
///
|
///
|
||||||
/// If the identified setting isn't a boolean or a preset, a `BadType` error is returned.
|
/// If the identified setting isn't a boolean or a preset, a `BadType` error is returned.
|
||||||
fn enable(&mut self, name: &str) -> Result<()>;
|
fn enable(&mut self, name: &str) -> SetResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect settings values based on a template.
|
/// Collect settings values based on a template.
|
||||||
@@ -84,9 +83,9 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Look up a descriptor by name.
|
/// Look up a descriptor by name.
|
||||||
fn lookup(&self, name: &str) -> Result<(usize, detail::Detail)> {
|
fn lookup(&self, name: &str) -> SetResult<(usize, detail::Detail)> {
|
||||||
match probe(self.template, name, simple_hash(name)) {
|
match probe(self.template, name, simple_hash(name)) {
|
||||||
Err(_) => Err(Error::BadName),
|
Err(_) => Err(SetError::BadName),
|
||||||
Ok(entry) => {
|
Ok(entry) => {
|
||||||
let d = &self.template.descriptors[self.template.hash_table[entry] as usize];
|
let d = &self.template.descriptors[self.template.hash_table[entry] as usize];
|
||||||
Ok((d.offset as usize, d.detail))
|
Ok((d.offset as usize, d.detail))
|
||||||
@@ -95,23 +94,23 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_bool_value(value: &str) -> Result<bool> {
|
fn parse_bool_value(value: &str) -> SetResult<bool> {
|
||||||
match value {
|
match value {
|
||||||
"true" | "on" | "yes" | "1" => Ok(true),
|
"true" | "on" | "yes" | "1" => Ok(true),
|
||||||
"false" | "off" | "no" | "0" => Ok(false),
|
"false" | "off" | "no" | "0" => Ok(false),
|
||||||
_ => Err(Error::BadValue),
|
_ => Err(SetError::BadValue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_enum_value(value: &str, choices: &[&str]) -> Result<u8> {
|
fn parse_enum_value(value: &str, choices: &[&str]) -> SetResult<u8> {
|
||||||
match choices.iter().position(|&tag| tag == value) {
|
match choices.iter().position(|&tag| tag == value) {
|
||||||
Some(idx) => Ok(idx as u8),
|
Some(idx) => Ok(idx as u8),
|
||||||
None => Err(Error::BadValue),
|
None => Err(SetError::BadValue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configurable for Builder {
|
impl Configurable for Builder {
|
||||||
fn enable(&mut self, name: &str) -> Result<()> {
|
fn enable(&mut self, name: &str) -> SetResult<()> {
|
||||||
use self::detail::Detail;
|
use self::detail::Detail;
|
||||||
let (offset, detail) = self.lookup(name)?;
|
let (offset, detail) = self.lookup(name)?;
|
||||||
match detail {
|
match detail {
|
||||||
@@ -123,27 +122,27 @@ impl Configurable for Builder {
|
|||||||
self.apply_preset(&self.template.presets[offset..]);
|
self.apply_preset(&self.template.presets[offset..]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(Error::BadType),
|
_ => Err(SetError::BadType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, name: &str, value: &str) -> Result<()> {
|
fn set(&mut self, name: &str, value: &str) -> SetResult<()> {
|
||||||
use self::detail::Detail;
|
use self::detail::Detail;
|
||||||
let (offset, detail) = self.lookup(name)?;
|
let (offset, detail) = self.lookup(name)?;
|
||||||
match detail {
|
match detail {
|
||||||
Detail::Bool { bit } => {
|
Detail::Bool { bit } => {
|
||||||
// Cannot currently propagate Result<()> up on functions returning ()
|
// Cannot currently propagate SetResult<()> up on functions returning ()
|
||||||
// with the `?` operator
|
// with the `?` operator
|
||||||
self.set_bit(offset, bit, parse_bool_value(value)?);
|
self.set_bit(offset, bit, parse_bool_value(value)?);
|
||||||
}
|
}
|
||||||
Detail::Num => {
|
Detail::Num => {
|
||||||
self.bytes[offset] = value.parse().map_err(|_| Error::BadValue)?;
|
self.bytes[offset] = value.parse().map_err(|_| SetError::BadValue)?;
|
||||||
}
|
}
|
||||||
Detail::Enum { last, enumerators } => {
|
Detail::Enum { last, enumerators } => {
|
||||||
self.bytes[offset] =
|
self.bytes[offset] =
|
||||||
parse_enum_value(value, self.template.enums(last, enumerators))?;
|
parse_enum_value(value, self.template.enums(last, enumerators))?;
|
||||||
}
|
}
|
||||||
Detail::Preset => return Err(Error::BadName),
|
Detail::Preset => return Err(SetError::BadName),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -151,7 +150,7 @@ impl Configurable for Builder {
|
|||||||
|
|
||||||
/// An error produced when changing a setting.
|
/// An error produced when changing a setting.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum SetError {
|
||||||
/// No setting by this name exists.
|
/// No setting by this name exists.
|
||||||
BadName,
|
BadName,
|
||||||
|
|
||||||
@@ -163,7 +162,7 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A result returned when changing a setting.
|
/// A result returned when changing a setting.
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type SetResult<T> = Result<T, SetError>;
|
||||||
|
|
||||||
/// A reference to just the boolean predicates of a settings object.
|
/// A reference to just the boolean predicates of a settings object.
|
||||||
///
|
///
|
||||||
@@ -348,7 +347,7 @@ impl<'a> From<&'a TargetIsa> for FlagsOrIsa<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Configurable;
|
use super::Configurable;
|
||||||
use super::Error::*;
|
use super::SetError::*;
|
||||||
use super::{builder, Flags};
|
use super::{builder, Flags};
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
use ir::{DataFlowGraph, Ebb, Function, Inst, SigRef, Type, Value, ValueDef};
|
use ir::{DataFlowGraph, Ebb, Function, Inst, SigRef, Type, Value, ValueDef};
|
||||||
use isa::{RegInfo, TargetIsa};
|
use isa::{RegInfo, TargetIsa};
|
||||||
use packed_option::ReservedValue;
|
use packed_option::ReservedValue;
|
||||||
use std::fmt::{self, Error, Result, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::result;
|
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
|
|
||||||
/// Write `func` to `w` as equivalent text.
|
/// Write `func` to `w` as equivalent text.
|
||||||
/// Use `isa` to emit ISA-dependent annotations.
|
/// Use `isa` to emit ISA-dependent annotations.
|
||||||
pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> Result {
|
pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> fmt::Result {
|
||||||
let regs = isa.map(TargetIsa::register_info);
|
let regs = isa.map(TargetIsa::register_info);
|
||||||
let regs = regs.as_ref();
|
let regs = regs.as_ref();
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -
|
|||||||
//
|
//
|
||||||
// Function spec.
|
// Function spec.
|
||||||
|
|
||||||
fn write_spec(w: &mut Write, func: &Function, regs: Option<&RegInfo>) -> Result {
|
fn write_spec(w: &mut Write, func: &Function, regs: Option<&RegInfo>) -> fmt::Result {
|
||||||
write!(w, "{}{}", func.name, func.signature.display(regs))
|
write!(w, "{}{}", func.name, func.signature.display(regs))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ fn write_preamble(
|
|||||||
w: &mut Write,
|
w: &mut Write,
|
||||||
func: &Function,
|
func: &Function,
|
||||||
regs: Option<&RegInfo>,
|
regs: Option<&RegInfo>,
|
||||||
) -> result::Result<bool, Error> {
|
) -> Result<bool, fmt::Error> {
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
|
|
||||||
for (ss, slot) in func.stack_slots.iter() {
|
for (ss, slot) in func.stack_slots.iter() {
|
||||||
@@ -91,7 +90,12 @@ fn write_preamble(
|
|||||||
//
|
//
|
||||||
// Basic blocks
|
// Basic blocks
|
||||||
|
|
||||||
pub fn write_arg(w: &mut Write, func: &Function, regs: Option<&RegInfo>, arg: Value) -> Result {
|
pub fn write_arg(
|
||||||
|
w: &mut Write,
|
||||||
|
func: &Function,
|
||||||
|
regs: Option<&RegInfo>,
|
||||||
|
arg: Value,
|
||||||
|
) -> fmt::Result {
|
||||||
write!(w, "{}: {}", arg, func.dfg.value_type(arg))?;
|
write!(w, "{}: {}", arg, func.dfg.value_type(arg))?;
|
||||||
let loc = func.locations[arg];
|
let loc = func.locations[arg];
|
||||||
if loc.is_assigned() {
|
if loc.is_assigned() {
|
||||||
@@ -107,7 +111,7 @@ pub fn write_ebb_header(
|
|||||||
isa: Option<&TargetIsa>,
|
isa: Option<&TargetIsa>,
|
||||||
ebb: Ebb,
|
ebb: Ebb,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
) -> Result {
|
) -> fmt::Result {
|
||||||
// Write out the basic block header, outdented:
|
// Write out the basic block header, outdented:
|
||||||
//
|
//
|
||||||
// ebb1:
|
// ebb1:
|
||||||
@@ -137,7 +141,7 @@ pub fn write_ebb_header(
|
|||||||
writeln!(w, "):")
|
writeln!(w, "):")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: Ebb) -> Result {
|
pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: Ebb) -> fmt::Result {
|
||||||
// Indent all instructions if any encodings are present.
|
// Indent all instructions if any encodings are present.
|
||||||
let indent = if func.encodings.is_empty() && func.srclocs.is_empty() {
|
let indent = if func.encodings.is_empty() && func.srclocs.is_empty() {
|
||||||
4
|
4
|
||||||
@@ -191,7 +195,7 @@ fn type_suffix(func: &Function, inst: Inst) -> Option<Type> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write out any value aliases appearing in `inst`.
|
// Write out any value aliases appearing in `inst`.
|
||||||
fn write_value_aliases(w: &mut Write, func: &Function, inst: Inst, indent: usize) -> Result {
|
fn write_value_aliases(w: &mut Write, func: &Function, inst: Inst, indent: usize) -> fmt::Result {
|
||||||
for &arg in func.dfg.inst_args(inst) {
|
for &arg in func.dfg.inst_args(inst) {
|
||||||
let resolved = func.dfg.resolve_aliases(arg);
|
let resolved = func.dfg.resolve_aliases(arg);
|
||||||
if resolved != arg {
|
if resolved != arg {
|
||||||
@@ -207,7 +211,7 @@ fn write_instruction(
|
|||||||
isa: Option<&TargetIsa>,
|
isa: Option<&TargetIsa>,
|
||||||
inst: Inst,
|
inst: Inst,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
) -> Result {
|
) -> fmt::Result {
|
||||||
// Value aliases come out on lines before the instruction using them.
|
// Value aliases come out on lines before the instruction using them.
|
||||||
write_value_aliases(w, func, inst, indent)?;
|
write_value_aliases(w, func, inst, indent)?;
|
||||||
|
|
||||||
@@ -272,7 +276,7 @@ pub fn write_operands(
|
|||||||
dfg: &DataFlowGraph,
|
dfg: &DataFlowGraph,
|
||||||
isa: Option<&TargetIsa>,
|
isa: Option<&TargetIsa>,
|
||||||
inst: Inst,
|
inst: Inst,
|
||||||
) -> Result {
|
) -> fmt::Result {
|
||||||
let pool = &dfg.value_lists;
|
let pool = &dfg.value_lists;
|
||||||
use ir::instructions::InstructionData::*;
|
use ir::instructions::InstructionData::*;
|
||||||
match dfg[inst] {
|
match dfg[inst] {
|
||||||
@@ -472,7 +476,7 @@ pub fn write_operands(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write EBB args using optional parantheses.
|
/// Write EBB args using optional parantheses.
|
||||||
fn write_ebb_args(w: &mut Write, args: &[Value]) -> Result {
|
fn write_ebb_args(w: &mut Write, args: &[Value]) -> fmt::Result {
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@@ -484,7 +488,7 @@ fn write_ebb_args(w: &mut Write, args: &[Value]) -> Result {
|
|||||||
struct DisplayValues<'a>(&'a [Value]);
|
struct DisplayValues<'a>(&'a [Value]);
|
||||||
|
|
||||||
impl<'a> fmt::Display for DisplayValues<'a> {
|
impl<'a> fmt::Display for DisplayValues<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
for (i, val) in self.0.iter().enumerate() {
|
for (i, val) in self.0.iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
write!(f, "{}", val)?;
|
write!(f, "{}", val)?;
|
||||||
@@ -499,7 +503,7 @@ impl<'a> fmt::Display for DisplayValues<'a> {
|
|||||||
struct DisplayValuesWithDelimiter<'a>(&'a [Value], char);
|
struct DisplayValuesWithDelimiter<'a>(&'a [Value], char);
|
||||||
|
|
||||||
impl<'a> fmt::Display for DisplayValuesWithDelimiter<'a> {
|
impl<'a> fmt::Display for DisplayValuesWithDelimiter<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
for (i, val) in self.0.iter().enumerate() {
|
for (i, val) in self.0.iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
write!(f, "{}", val)?;
|
write!(f, "{}", val)?;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use cretonne_codegen::{binemit, ir};
|
|||||||
use std::marker;
|
use std::marker;
|
||||||
use DataContext;
|
use DataContext;
|
||||||
use Linkage;
|
use Linkage;
|
||||||
use ModuleError;
|
|
||||||
use ModuleNamespace;
|
use ModuleNamespace;
|
||||||
use ModuleResult;
|
use ModuleResult;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//! Define the `Location`, `Error`, and `Result` types.
|
//! Define the `Location`, `ParseError`, and `ParseResult` types.
|
||||||
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
/// The location of a `Token` or `Error`.
|
/// The location of a `Token` or `Error`.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
@@ -15,14 +14,14 @@ pub struct Location {
|
|||||||
|
|
||||||
/// A parse error is returned when the parse failed.
|
/// A parse error is returned when the parse failed.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error {
|
pub struct ParseError {
|
||||||
/// Location of the error.
|
/// Location of the error.
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
/// Error message.
|
/// Error message.
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for ParseError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.location.line_number == 0 {
|
if self.location.line_number == 0 {
|
||||||
write!(f, "command-line arguments: {}", self.message)
|
write!(f, "command-line arguments: {}", self.message)
|
||||||
@@ -32,20 +31,20 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of a parser operation. The `Error` variant includes a location.
|
/// Result of a parser operation. The `ParseError` variant includes a location.
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type ParseResult<T> = Result<T, ParseError>;
|
||||||
|
|
||||||
// Create an `Err` variant of `Result<X>` from a location and `format!` args.
|
// Create an `Err` variant of `ParseResult<X>` from a location and `format!` args.
|
||||||
macro_rules! err {
|
macro_rules! err {
|
||||||
( $loc:expr, $msg:expr ) => {
|
( $loc:expr, $msg:expr ) => {
|
||||||
Err($crate::Error {
|
Err($crate::ParseError {
|
||||||
location: $loc.clone(),
|
location: $loc.clone(),
|
||||||
message: $msg.to_string(),
|
message: $msg.to_string(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => {
|
( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => {
|
||||||
Err($crate::Error {
|
Err($crate::ParseError {
|
||||||
location: $loc.clone(),
|
location: $loc.clone(),
|
||||||
message: format!( $fmt, $( $arg ),+ ),
|
message: format!( $fmt, $( $arg ),+ ),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
//! ISAs. If the file contains no `isa` commands, the tests will be run against all supported ISAs.
|
//! ISAs. If the file contains no `isa` commands, the tests will be run against all supported ISAs.
|
||||||
|
|
||||||
use cretonne_codegen::isa::TargetIsa;
|
use cretonne_codegen::isa::TargetIsa;
|
||||||
use cretonne_codegen::settings::{Configurable, Error as SetError, Flags};
|
use cretonne_codegen::settings::{Configurable, Flags, SetError};
|
||||||
use error::{Location, Result};
|
use error::{Location, ParseResult};
|
||||||
use testcommand::TestOption;
|
use testcommand::TestOption;
|
||||||
|
|
||||||
/// The ISA specifications in a `.cton` file.
|
/// The ISA specifications in a `.cton` file.
|
||||||
@@ -35,7 +35,7 @@ impl IsaSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an iterator of command line options and apply them to `config`.
|
/// Parse an iterator of command line options and apply them to `config`.
|
||||||
pub fn parse_options<'a, I>(iter: I, config: &mut Configurable, loc: &Location) -> Result<()>
|
pub fn parse_options<'a, I>(iter: I, config: &mut Configurable, loc: &Location) -> ParseResult<()>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a str>,
|
I: Iterator<Item = &'a str>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,19 +63,19 @@ fn token(token: Token, loc: Location) -> Result<LocatedToken, LocatedError> {
|
|||||||
|
|
||||||
/// An error from the lexical analysis.
|
/// An error from the lexical analysis.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum LexError {
|
||||||
InvalidChar,
|
InvalidChar,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `Error` with an associated Location.
|
/// A `LexError` with an associated Location.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct LocatedError {
|
pub struct LocatedError {
|
||||||
pub error: Error,
|
pub error: LexError,
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap up an `Error` with the given location.
|
/// Wrap up a `LexError` with the given location.
|
||||||
fn error<'a>(error: Error, loc: Location) -> Result<LocatedToken<'a>, LocatedError> {
|
fn error<'a>(error: LexError, loc: Location) -> Result<LocatedToken<'a>, LocatedError> {
|
||||||
Err(LocatedError {
|
Err(LocatedError {
|
||||||
error,
|
error,
|
||||||
location: loc,
|
location: loc,
|
||||||
@@ -468,7 +468,7 @@ impl<'a> Lexer<'a> {
|
|||||||
_ => {
|
_ => {
|
||||||
// Skip invalid char, return error.
|
// Skip invalid char, return error.
|
||||||
self.next_ch();
|
self.next_ch();
|
||||||
Some(error(Error::InvalidChar, loc))
|
Some(error(LexError::InvalidChar, loc))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -511,7 +511,7 @@ mod tests {
|
|||||||
Some(super::token(token, Location { line_number: line }))
|
Some(super::token(token, Location { line_number: line }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error<'a>(error: Error, line: usize) -> Option<Result<LocatedToken<'a>, LocatedError>> {
|
fn error<'a>(error: LexError, line: usize) -> Option<Result<LocatedToken<'a>, LocatedError>> {
|
||||||
Some(super::error(error, Location { line_number: line }))
|
Some(super::error(error, Location { line_number: line }))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,7 +539,7 @@ mod tests {
|
|||||||
|
|
||||||
// Scan a comment after an invalid char.
|
// Scan a comment after an invalid char.
|
||||||
let mut lex = Lexer::new("$; hello");
|
let mut lex = Lexer::new("$; hello");
|
||||||
assert_eq!(lex.next(), error(Error::InvalidChar, 1));
|
assert_eq!(lex.next(), error(LexError::InvalidChar, 1));
|
||||||
assert_eq!(lex.next(), token(Token::Comment("; hello"), 1));
|
assert_eq!(lex.next(), token(Token::Comment("; hello"), 1));
|
||||||
assert_eq!(lex.next(), None);
|
assert_eq!(lex.next(), None);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
extern crate cretonne_codegen;
|
extern crate cretonne_codegen;
|
||||||
extern crate target_lexicon;
|
extern crate target_lexicon;
|
||||||
|
|
||||||
pub use error::{Error, Location, Result};
|
pub use error::{Location, ParseError, ParseResult};
|
||||||
pub use isaspec::{parse_options, IsaSpec};
|
pub use isaspec::{parse_options, IsaSpec};
|
||||||
pub use parser::{parse_functions, parse_test};
|
pub use parser::{parse_functions, parse_test};
|
||||||
pub use sourcemap::SourceMap;
|
pub use sourcemap::SourceMap;
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ use cretonne_codegen::isa::{self, Encoding, RegUnit, TargetIsa};
|
|||||||
use cretonne_codegen::packed_option::ReservedValue;
|
use cretonne_codegen::packed_option::ReservedValue;
|
||||||
use cretonne_codegen::settings::CallConv;
|
use cretonne_codegen::settings::CallConv;
|
||||||
use cretonne_codegen::{settings, timing};
|
use cretonne_codegen::{settings, timing};
|
||||||
use error::{Error, Location, Result};
|
use error::{Location, ParseError, ParseResult};
|
||||||
use isaspec;
|
use isaspec;
|
||||||
use lexer::{self, Lexer, Token};
|
use lexer::{LexError, Lexer, LocatedError, LocatedToken, Token};
|
||||||
use sourcemap::SourceMap;
|
use sourcemap::SourceMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -29,7 +29,7 @@ use testfile::{Comment, Details, TestFile};
|
|||||||
/// Parse the entire `text` into a list of functions.
|
/// Parse the entire `text` into a list of functions.
|
||||||
///
|
///
|
||||||
/// Any test commands or target declarations are ignored.
|
/// Any test commands or target declarations are ignored.
|
||||||
pub fn parse_functions(text: &str) -> Result<Vec<Function>> {
|
pub fn parse_functions(text: &str) -> ParseResult<Vec<Function>> {
|
||||||
let _tt = timing::parse_text();
|
let _tt = timing::parse_text();
|
||||||
parse_test(text).map(|file| file.functions.into_iter().map(|(func, _)| func).collect())
|
parse_test(text).map(|file| file.functions.into_iter().map(|(func, _)| func).collect())
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ pub fn parse_functions(text: &str) -> Result<Vec<Function>> {
|
|||||||
/// Parse the entire `text` as a test case file.
|
/// Parse the entire `text` as a test case file.
|
||||||
///
|
///
|
||||||
/// The returned `TestFile` contains direct references to substrings of `text`.
|
/// The returned `TestFile` contains direct references to substrings of `text`.
|
||||||
pub fn parse_test(text: &str) -> Result<TestFile> {
|
pub fn parse_test(text: &str) -> ParseResult<TestFile> {
|
||||||
let _tt = timing::parse_text();
|
let _tt = timing::parse_text();
|
||||||
let mut parser = Parser::new(text);
|
let mut parser = Parser::new(text);
|
||||||
// Gather the preamble comments.
|
// Gather the preamble comments.
|
||||||
@@ -63,7 +63,7 @@ pub fn parse_test(text: &str) -> Result<TestFile> {
|
|||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
lex: Lexer<'a>,
|
lex: Lexer<'a>,
|
||||||
|
|
||||||
lex_error: Option<lexer::Error>,
|
lex_error: Option<LexError>,
|
||||||
|
|
||||||
/// Current lookahead token.
|
/// Current lookahead token.
|
||||||
lookahead: Option<Token<'a>>,
|
lookahead: Option<Token<'a>>,
|
||||||
@@ -121,7 +121,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new stack slot.
|
// Allocate a new stack slot.
|
||||||
fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: &Location) -> Result<()> {
|
fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.stack_slots.next_key().index() <= ss.index() {
|
while self.function.stack_slots.next_key().index() <= ss.index() {
|
||||||
self.function
|
self.function
|
||||||
.create_stack_slot(StackSlotData::new(StackSlotKind::SpillSlot, 0));
|
.create_stack_slot(StackSlotData::new(StackSlotKind::SpillSlot, 0));
|
||||||
@@ -131,7 +131,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a stack slot.
|
// Resolve a reference to a stack slot.
|
||||||
fn check_ss(&self, ss: StackSlot, loc: &Location) -> Result<()> {
|
fn check_ss(&self, ss: StackSlot, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_ss(ss) {
|
if !self.map.contains_ss(ss) {
|
||||||
err!(loc, "undefined stack slot {}", ss)
|
err!(loc, "undefined stack slot {}", ss)
|
||||||
} else {
|
} else {
|
||||||
@@ -140,7 +140,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a global variable slot.
|
// Allocate a global variable slot.
|
||||||
fn add_gv(&mut self, gv: GlobalVar, data: GlobalVarData, loc: &Location) -> Result<()> {
|
fn add_gv(&mut self, gv: GlobalVar, data: GlobalVarData, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.global_vars.next_key().index() <= gv.index() {
|
while self.function.global_vars.next_key().index() <= gv.index() {
|
||||||
self.function.create_global_var(GlobalVarData::Sym {
|
self.function.create_global_var(GlobalVarData::Sym {
|
||||||
name: ExternalName::testcase(""),
|
name: ExternalName::testcase(""),
|
||||||
@@ -152,7 +152,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a global variable.
|
// Resolve a reference to a global variable.
|
||||||
fn check_gv(&self, gv: GlobalVar, loc: &Location) -> Result<()> {
|
fn check_gv(&self, gv: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_gv(gv) {
|
if !self.map.contains_gv(gv) {
|
||||||
err!(loc, "undefined global variable {}", gv)
|
err!(loc, "undefined global variable {}", gv)
|
||||||
} else {
|
} else {
|
||||||
@@ -161,7 +161,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a heap slot.
|
// Allocate a heap slot.
|
||||||
fn add_heap(&mut self, heap: Heap, data: HeapData, loc: &Location) -> Result<()> {
|
fn add_heap(&mut self, heap: Heap, data: HeapData, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.heaps.next_key().index() <= heap.index() {
|
while self.function.heaps.next_key().index() <= heap.index() {
|
||||||
self.function.create_heap(HeapData {
|
self.function.create_heap(HeapData {
|
||||||
base: HeapBase::ReservedReg,
|
base: HeapBase::ReservedReg,
|
||||||
@@ -177,7 +177,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a heap.
|
// Resolve a reference to a heap.
|
||||||
fn check_heap(&self, heap: Heap, loc: &Location) -> Result<()> {
|
fn check_heap(&self, heap: Heap, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_heap(heap) {
|
if !self.map.contains_heap(heap) {
|
||||||
err!(loc, "undefined heap {}", heap)
|
err!(loc, "undefined heap {}", heap)
|
||||||
} else {
|
} else {
|
||||||
@@ -186,7 +186,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new signature.
|
// Allocate a new signature.
|
||||||
fn add_sig(&mut self, sig: SigRef, data: Signature, loc: &Location) -> Result<()> {
|
fn add_sig(&mut self, sig: SigRef, data: Signature, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.dfg.signatures.next_key().index() <= sig.index() {
|
while self.function.dfg.signatures.next_key().index() <= sig.index() {
|
||||||
self.function
|
self.function
|
||||||
.import_signature(Signature::new(CallConv::Fast));
|
.import_signature(Signature::new(CallConv::Fast));
|
||||||
@@ -196,7 +196,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a signature.
|
// Resolve a reference to a signature.
|
||||||
fn check_sig(&self, sig: SigRef, loc: &Location) -> Result<()> {
|
fn check_sig(&self, sig: SigRef, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_sig(sig) {
|
if !self.map.contains_sig(sig) {
|
||||||
err!(loc, "undefined signature {}", sig)
|
err!(loc, "undefined signature {}", sig)
|
||||||
} else {
|
} else {
|
||||||
@@ -205,7 +205,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new external function.
|
// Allocate a new external function.
|
||||||
fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: &Location) -> Result<()> {
|
fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() {
|
while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() {
|
||||||
self.function.import_function(ExtFuncData {
|
self.function.import_function(ExtFuncData {
|
||||||
name: ExternalName::testcase(""),
|
name: ExternalName::testcase(""),
|
||||||
@@ -218,7 +218,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a function.
|
// Resolve a reference to a function.
|
||||||
fn check_fn(&self, fn_: FuncRef, loc: &Location) -> Result<()> {
|
fn check_fn(&self, fn_: FuncRef, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_fn(fn_) {
|
if !self.map.contains_fn(fn_) {
|
||||||
err!(loc, "undefined function {}", fn_)
|
err!(loc, "undefined function {}", fn_)
|
||||||
} else {
|
} else {
|
||||||
@@ -227,7 +227,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new jump table.
|
// Allocate a new jump table.
|
||||||
fn add_jt(&mut self, jt: JumpTable, data: JumpTableData, loc: &Location) -> Result<()> {
|
fn add_jt(&mut self, jt: JumpTable, data: JumpTableData, loc: &Location) -> ParseResult<()> {
|
||||||
while self.function.jump_tables.next_key().index() <= jt.index() {
|
while self.function.jump_tables.next_key().index() <= jt.index() {
|
||||||
self.function.create_jump_table(JumpTableData::new());
|
self.function.create_jump_table(JumpTableData::new());
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a jump table.
|
// Resolve a reference to a jump table.
|
||||||
fn check_jt(&self, jt: JumpTable, loc: &Location) -> Result<()> {
|
fn check_jt(&self, jt: JumpTable, loc: &Location) -> ParseResult<()> {
|
||||||
if !self.map.contains_jt(jt) {
|
if !self.map.contains_jt(jt) {
|
||||||
err!(loc, "undefined jump table {}", jt)
|
err!(loc, "undefined jump table {}", jt)
|
||||||
} else {
|
} else {
|
||||||
@@ -245,7 +245,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assign the global for the stack limit.
|
// Assign the global for the stack limit.
|
||||||
fn set_stack_limit(&mut self, gv: GlobalVar, loc: &Location) -> Result<()> {
|
fn set_stack_limit(&mut self, gv: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||||
if let Some(_) = self.function.set_stack_limit(Some(gv)) {
|
if let Some(_) = self.function.set_stack_limit(Some(gv)) {
|
||||||
err!(loc, "multiple stack_limit declarations")
|
err!(loc, "multiple stack_limit declarations")
|
||||||
} else {
|
} else {
|
||||||
@@ -254,7 +254,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new EBB.
|
// Allocate a new EBB.
|
||||||
fn add_ebb(&mut self, ebb: Ebb, loc: &Location) -> Result<Ebb> {
|
fn add_ebb(&mut self, ebb: Ebb, loc: &Location) -> ParseResult<Ebb> {
|
||||||
while self.function.dfg.num_ebbs() <= ebb.index() {
|
while self.function.dfg.num_ebbs() <= ebb.index() {
|
||||||
self.function.dfg.make_ebb();
|
self.function.dfg.make_ebb();
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ impl<'a> Parser<'a> {
|
|||||||
#[cfg_attr(feature = "cargo-clippy", allow(while_immutable_condition))]
|
#[cfg_attr(feature = "cargo-clippy", allow(while_immutable_condition))]
|
||||||
while self.lookahead == None {
|
while self.lookahead == None {
|
||||||
match self.lex.next() {
|
match self.lex.next() {
|
||||||
Some(Ok(lexer::LocatedToken { token, location })) => {
|
Some(Ok(LocatedToken { token, location })) => {
|
||||||
match token {
|
match token {
|
||||||
Token::Comment(text) => {
|
Token::Comment(text) => {
|
||||||
if self.gathering_comments {
|
if self.gathering_comments {
|
||||||
@@ -309,7 +309,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
self.loc = location;
|
self.loc = location;
|
||||||
}
|
}
|
||||||
Some(Err(lexer::LocatedError { error, location })) => {
|
Some(Err(LocatedError { error, location })) => {
|
||||||
self.lex_error = Some(error);
|
self.lex_error = Some(error);
|
||||||
self.loc = location;
|
self.loc = location;
|
||||||
break;
|
break;
|
||||||
@@ -347,7 +347,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a token without payload.
|
// Match and consume a token without payload.
|
||||||
fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> Result<Token<'a>> {
|
fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> ParseResult<Token<'a>> {
|
||||||
if self.token() == Some(want) {
|
if self.token() == Some(want) {
|
||||||
Ok(self.consume())
|
Ok(self.consume())
|
||||||
} else {
|
} else {
|
||||||
@@ -367,7 +367,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Match and consume a specific identifier string.
|
// Match and consume a specific identifier string.
|
||||||
// Used for pseudo-keywords like "stack_slot" that only appear in certain contexts.
|
// Used for pseudo-keywords like "stack_slot" that only appear in certain contexts.
|
||||||
fn match_identifier(&mut self, want: &'static str, err_msg: &str) -> Result<Token<'a>> {
|
fn match_identifier(&mut self, want: &'static str, err_msg: &str) -> ParseResult<Token<'a>> {
|
||||||
if self.token() == Some(Token::Identifier(want)) {
|
if self.token() == Some(Token::Identifier(want)) {
|
||||||
Ok(self.consume())
|
Ok(self.consume())
|
||||||
} else {
|
} else {
|
||||||
@@ -376,7 +376,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a type.
|
// Match and consume a type.
|
||||||
fn match_type(&mut self, err_msg: &str) -> Result<Type> {
|
fn match_type(&mut self, err_msg: &str) -> ParseResult<Type> {
|
||||||
if let Some(Token::Type(t)) = self.token() {
|
if let Some(Token::Type(t)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
Ok(t)
|
Ok(t)
|
||||||
@@ -386,7 +386,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a stack slot reference.
|
// Match and consume a stack slot reference.
|
||||||
fn match_ss(&mut self, err_msg: &str) -> Result<StackSlot> {
|
fn match_ss(&mut self, err_msg: &str) -> ParseResult<StackSlot> {
|
||||||
if let Some(Token::StackSlot(ss)) = self.token() {
|
if let Some(Token::StackSlot(ss)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(ss) = StackSlot::with_number(ss) {
|
if let Some(ss) = StackSlot::with_number(ss) {
|
||||||
@@ -397,7 +397,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a global variable reference.
|
// Match and consume a global variable reference.
|
||||||
fn match_gv(&mut self, err_msg: &str) -> Result<GlobalVar> {
|
fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalVar> {
|
||||||
if let Some(Token::GlobalVar(gv)) = self.token() {
|
if let Some(Token::GlobalVar(gv)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(gv) = GlobalVar::with_number(gv) {
|
if let Some(gv) = GlobalVar::with_number(gv) {
|
||||||
@@ -408,7 +408,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a function reference.
|
// Match and consume a function reference.
|
||||||
fn match_fn(&mut self, err_msg: &str) -> Result<FuncRef> {
|
fn match_fn(&mut self, err_msg: &str) -> ParseResult<FuncRef> {
|
||||||
if let Some(Token::FuncRef(fnref)) = self.token() {
|
if let Some(Token::FuncRef(fnref)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(fnref) = FuncRef::with_number(fnref) {
|
if let Some(fnref) = FuncRef::with_number(fnref) {
|
||||||
@@ -419,7 +419,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a signature reference.
|
// Match and consume a signature reference.
|
||||||
fn match_sig(&mut self, err_msg: &str) -> Result<SigRef> {
|
fn match_sig(&mut self, err_msg: &str) -> ParseResult<SigRef> {
|
||||||
if let Some(Token::SigRef(sigref)) = self.token() {
|
if let Some(Token::SigRef(sigref)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(sigref) = SigRef::with_number(sigref) {
|
if let Some(sigref) = SigRef::with_number(sigref) {
|
||||||
@@ -430,7 +430,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a heap reference.
|
// Match and consume a heap reference.
|
||||||
fn match_heap(&mut self, err_msg: &str) -> Result<Heap> {
|
fn match_heap(&mut self, err_msg: &str) -> ParseResult<Heap> {
|
||||||
if let Some(Token::Heap(heap)) = self.token() {
|
if let Some(Token::Heap(heap)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(heap) = Heap::with_number(heap) {
|
if let Some(heap) = Heap::with_number(heap) {
|
||||||
@@ -441,7 +441,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a jump table reference.
|
// Match and consume a jump table reference.
|
||||||
fn match_jt(&mut self) -> Result<JumpTable> {
|
fn match_jt(&mut self) -> ParseResult<JumpTable> {
|
||||||
if let Some(Token::JumpTable(jt)) = self.token() {
|
if let Some(Token::JumpTable(jt)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
if let Some(jt) = JumpTable::with_number(jt) {
|
if let Some(jt) = JumpTable::with_number(jt) {
|
||||||
@@ -452,7 +452,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an ebb reference.
|
// Match and consume an ebb reference.
|
||||||
fn match_ebb(&mut self, err_msg: &str) -> Result<Ebb> {
|
fn match_ebb(&mut self, err_msg: &str) -> ParseResult<Ebb> {
|
||||||
if let Some(Token::Ebb(ebb)) = self.token() {
|
if let Some(Token::Ebb(ebb)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
Ok(ebb)
|
Ok(ebb)
|
||||||
@@ -462,7 +462,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a value reference, direct or vtable.
|
// Match and consume a value reference, direct or vtable.
|
||||||
fn match_value(&mut self, err_msg: &str) -> Result<Value> {
|
fn match_value(&mut self, err_msg: &str) -> ParseResult<Value> {
|
||||||
if let Some(Token::Value(v)) = self.token() {
|
if let Some(Token::Value(v)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
Ok(v)
|
Ok(v)
|
||||||
@@ -471,15 +471,15 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&self, message: &str) -> Error {
|
fn error(&self, message: &str) -> ParseError {
|
||||||
Error {
|
ParseError {
|
||||||
location: self.loc,
|
location: self.loc,
|
||||||
message: message.to_string(),
|
message: message.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an Imm64 immediate.
|
// Match and consume an Imm64 immediate.
|
||||||
fn match_imm64(&mut self, err_msg: &str) -> Result<Imm64> {
|
fn match_imm64(&mut self, err_msg: &str) -> ParseResult<Imm64> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
@@ -491,7 +491,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a Uimm32 immediate.
|
// Match and consume a Uimm32 immediate.
|
||||||
fn match_uimm32(&mut self, err_msg: &str) -> Result<Uimm32> {
|
fn match_uimm32(&mut self, err_msg: &str) -> ParseResult<Uimm32> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
@@ -504,7 +504,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Match and consume a u8 immediate.
|
// Match and consume a u8 immediate.
|
||||||
// This is used for lane numbers in SIMD vectors.
|
// This is used for lane numbers in SIMD vectors.
|
||||||
fn match_uimm8(&mut self, err_msg: &str) -> Result<u8> {
|
fn match_uimm8(&mut self, err_msg: &str) -> ParseResult<u8> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
@@ -518,7 +518,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Match and consume an i32 immediate.
|
// Match and consume an i32 immediate.
|
||||||
// This is used for stack argument byte offsets.
|
// This is used for stack argument byte offsets.
|
||||||
fn match_imm32(&mut self, err_msg: &str) -> Result<i32> {
|
fn match_imm32(&mut self, err_msg: &str) -> ParseResult<i32> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
@@ -534,7 +534,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// Note that this will match an empty string as an empty offset, and that if an offset is
|
// Note that this will match an empty string as an empty offset, and that if an offset is
|
||||||
// present, it must contain a sign.
|
// present, it must contain a sign.
|
||||||
fn optional_offset32(&mut self) -> Result<Offset32> {
|
fn optional_offset32(&mut self) -> ParseResult<Offset32> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
@@ -547,7 +547,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an Ieee32 immediate.
|
// Match and consume an Ieee32 immediate.
|
||||||
fn match_ieee32(&mut self, err_msg: &str) -> Result<Ieee32> {
|
fn match_ieee32(&mut self, err_msg: &str) -> ParseResult<Ieee32> {
|
||||||
if let Some(Token::Float(text)) = self.token() {
|
if let Some(Token::Float(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like a float.
|
// Lexer just gives us raw text that looks like a float.
|
||||||
@@ -559,7 +559,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an Ieee64 immediate.
|
// Match and consume an Ieee64 immediate.
|
||||||
fn match_ieee64(&mut self, err_msg: &str) -> Result<Ieee64> {
|
fn match_ieee64(&mut self, err_msg: &str) -> ParseResult<Ieee64> {
|
||||||
if let Some(Token::Float(text)) = self.token() {
|
if let Some(Token::Float(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// Lexer just gives us raw text that looks like a float.
|
// Lexer just gives us raw text that looks like a float.
|
||||||
@@ -571,7 +571,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a boolean immediate.
|
// Match and consume a boolean immediate.
|
||||||
fn match_bool(&mut self, err_msg: &str) -> Result<bool> {
|
fn match_bool(&mut self, err_msg: &str) -> ParseResult<bool> {
|
||||||
if let Some(Token::Identifier(text)) = self.token() {
|
if let Some(Token::Identifier(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
match text {
|
match text {
|
||||||
@@ -585,7 +585,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an enumerated immediate, like one of the condition codes.
|
// Match and consume an enumerated immediate, like one of the condition codes.
|
||||||
fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> Result<T> {
|
fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> ParseResult<T> {
|
||||||
if let Some(Token::Identifier(text)) = self.token() {
|
if let Some(Token::Identifier(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
text.parse().map_err(|_| self.error(err_msg))
|
text.parse().map_err(|_| self.error(err_msg))
|
||||||
@@ -608,7 +608,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an identifier.
|
// Match and consume an identifier.
|
||||||
fn match_any_identifier(&mut self, err_msg: &str) -> Result<&'a str> {
|
fn match_any_identifier(&mut self, err_msg: &str) -> ParseResult<&'a str> {
|
||||||
if let Some(Token::Identifier(text)) = self.token() {
|
if let Some(Token::Identifier(text)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
Ok(text)
|
Ok(text)
|
||||||
@@ -619,7 +619,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Match and consume a HexSequence that fits into a u16.
|
// Match and consume a HexSequence that fits into a u16.
|
||||||
// This is used for instruction encodings.
|
// This is used for instruction encodings.
|
||||||
fn match_hex16(&mut self, err_msg: &str) -> Result<u16> {
|
fn match_hex16(&mut self, err_msg: &str) -> ParseResult<u16> {
|
||||||
if let Some(Token::HexSequence(bits_str)) = self.token() {
|
if let Some(Token::HexSequence(bits_str)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
// The only error we anticipate from this parse is overflow, the lexer should
|
// The only error we anticipate from this parse is overflow, the lexer should
|
||||||
@@ -633,7 +633,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a register unit either by number `%15` or by name `%rax`.
|
// Match and consume a register unit either by number `%15` or by name `%rax`.
|
||||||
fn match_regunit(&mut self, isa: Option<&TargetIsa>) -> Result<RegUnit> {
|
fn match_regunit(&mut self, isa: Option<&TargetIsa>) -> ParseResult<RegUnit> {
|
||||||
if let Some(Token::Name(name)) = self.token() {
|
if let Some(Token::Name(name)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
match isa {
|
match isa {
|
||||||
@@ -654,7 +654,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// Parse an optional source location.
|
/// Parse an optional source location.
|
||||||
///
|
///
|
||||||
/// Return an optional source location if no real location is present.
|
/// Return an optional source location if no real location is present.
|
||||||
fn optional_srcloc(&mut self) -> Result<ir::SourceLoc> {
|
fn optional_srcloc(&mut self) -> ParseResult<ir::SourceLoc> {
|
||||||
if let Some(Token::SourceLoc(text)) = self.token() {
|
if let Some(Token::SourceLoc(text)) = self.token() {
|
||||||
match u32::from_str_radix(text, 16) {
|
match u32::from_str_radix(text, 16) {
|
||||||
Ok(num) => {
|
Ok(num) => {
|
||||||
@@ -681,7 +681,7 @@ impl<'a> Parser<'a> {
|
|||||||
///
|
///
|
||||||
/// Accept a mix of `target` and `set` command lines. The `set` commands are cumulative.
|
/// Accept a mix of `target` and `set` command lines. The `set` commands are cumulative.
|
||||||
///
|
///
|
||||||
pub fn parse_target_specs(&mut self) -> Result<isaspec::IsaSpec> {
|
pub fn parse_target_specs(&mut self) -> ParseResult<isaspec::IsaSpec> {
|
||||||
// Was there any `target` commands?
|
// Was there any `target` commands?
|
||||||
let mut seen_target = false;
|
let mut seen_target = false;
|
||||||
// Location of last `set` command since the last `target`.
|
// Location of last `set` command since the last `target`.
|
||||||
@@ -753,14 +753,14 @@ impl<'a> Parser<'a> {
|
|||||||
pub fn parse_function_list(
|
pub fn parse_function_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
unique_isa: Option<&TargetIsa>,
|
unique_isa: Option<&TargetIsa>,
|
||||||
) -> Result<Vec<(Function, Details<'a>)>> {
|
) -> ParseResult<Vec<(Function, Details<'a>)>> {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
while self.token().is_some() {
|
while self.token().is_some() {
|
||||||
list.push(self.parse_function(unique_isa)?);
|
list.push(self.parse_function(unique_isa)?);
|
||||||
}
|
}
|
||||||
if let Some(err) = self.lex_error {
|
if let Some(err) = self.lex_error {
|
||||||
return match err {
|
return match err {
|
||||||
lexer::Error::InvalidChar => err!(self.loc, "invalid character"),
|
LexError::InvalidChar => err!(self.loc, "invalid character"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(list)
|
Ok(list)
|
||||||
@@ -773,7 +773,7 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_function(
|
fn parse_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
unique_isa: Option<&TargetIsa>,
|
unique_isa: Option<&TargetIsa>,
|
||||||
) -> Result<(Function, Details<'a>)> {
|
) -> ParseResult<(Function, Details<'a>)> {
|
||||||
// Begin gathering comments.
|
// Begin gathering comments.
|
||||||
// Make sure we don't include any comments before the `function` keyword.
|
// Make sure we don't include any comments before the `function` keyword.
|
||||||
self.token();
|
self.token();
|
||||||
@@ -825,7 +825,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// function ::= "function" * name signature { ... }
|
// function ::= "function" * name signature { ... }
|
||||||
//
|
//
|
||||||
fn parse_external_name(&mut self) -> Result<ExternalName> {
|
fn parse_external_name(&mut self) -> ParseResult<ExternalName> {
|
||||||
match self.token() {
|
match self.token() {
|
||||||
Some(Token::Name(s)) => {
|
Some(Token::Name(s)) => {
|
||||||
self.consume();
|
self.consume();
|
||||||
@@ -859,7 +859,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv]
|
// signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv]
|
||||||
//
|
//
|
||||||
fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Signature> {
|
fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> ParseResult<Signature> {
|
||||||
// Calling convention defaults to `fast`, but can be changed.
|
// Calling convention defaults to `fast`, but can be changed.
|
||||||
let mut sig = Signature::new(CallConv::Fast);
|
let mut sig = Signature::new(CallConv::Fast);
|
||||||
|
|
||||||
@@ -895,7 +895,10 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// paramlist ::= * param { "," param }
|
// paramlist ::= * param { "," param }
|
||||||
//
|
//
|
||||||
fn parse_abi_param_list(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Vec<AbiParam>> {
|
fn parse_abi_param_list(
|
||||||
|
&mut self,
|
||||||
|
unique_isa: Option<&TargetIsa>,
|
||||||
|
) -> ParseResult<Vec<AbiParam>> {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
|
|
||||||
// abi-param-list ::= * abi-param { "," abi-param }
|
// abi-param-list ::= * abi-param { "," abi-param }
|
||||||
@@ -911,7 +914,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse a single argument type with flags.
|
// Parse a single argument type with flags.
|
||||||
fn parse_abi_param(&mut self, unique_isa: Option<&TargetIsa>) -> Result<AbiParam> {
|
fn parse_abi_param(&mut self, unique_isa: Option<&TargetIsa>) -> ParseResult<AbiParam> {
|
||||||
// abi-param ::= * type { flag } [ argumentloc ]
|
// abi-param ::= * type { flag } [ argumentloc ]
|
||||||
let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
|
let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
|
||||||
|
|
||||||
@@ -938,7 +941,10 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse an argument location specifier; either a register or a byte offset into the stack.
|
// Parse an argument location specifier; either a register or a byte offset into the stack.
|
||||||
fn parse_argument_location(&mut self, unique_isa: Option<&TargetIsa>) -> Result<ArgumentLoc> {
|
fn parse_argument_location(
|
||||||
|
&mut self,
|
||||||
|
unique_isa: Option<&TargetIsa>,
|
||||||
|
) -> ParseResult<ArgumentLoc> {
|
||||||
// argumentloc ::= '[' regname | uimm32 ']'
|
// argumentloc ::= '[' regname | uimm32 ']'
|
||||||
if self.optional(Token::LBracket) {
|
if self.optional(Token::LBracket) {
|
||||||
let result = match self.token() {
|
let result = match self.token() {
|
||||||
@@ -985,7 +991,7 @@ impl<'a> Parser<'a> {
|
|||||||
// * stack-limit-decl
|
// * stack-limit-decl
|
||||||
//
|
//
|
||||||
// The parsed decls are added to `ctx` rather than returned.
|
// The parsed decls are added to `ctx` rather than returned.
|
||||||
fn parse_preamble(&mut self, ctx: &mut Context) -> Result<()> {
|
fn parse_preamble(&mut self, ctx: &mut Context) -> ParseResult<()> {
|
||||||
loop {
|
loop {
|
||||||
match self.token() {
|
match self.token() {
|
||||||
Some(Token::StackSlot(..)) => {
|
Some(Token::StackSlot(..)) => {
|
||||||
@@ -1034,7 +1040,7 @@ impl<'a> Parser<'a> {
|
|||||||
// | "spill_slot"
|
// | "spill_slot"
|
||||||
// | "incoming_arg"
|
// | "incoming_arg"
|
||||||
// | "outgoing_arg"
|
// | "outgoing_arg"
|
||||||
fn parse_stack_slot_decl(&mut self) -> Result<(StackSlot, StackSlotData)> {
|
fn parse_stack_slot_decl(&mut self) -> ParseResult<(StackSlot, StackSlotData)> {
|
||||||
let ss = self.match_ss("expected stack slot number: ss«n»")?;
|
let ss = self.match_ss("expected stack slot number: ss«n»")?;
|
||||||
self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
|
self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
|
||||||
let kind = self.match_enum("expected stack slot kind")?;
|
let kind = self.match_enum("expected stack slot kind")?;
|
||||||
@@ -1073,7 +1079,7 @@ impl<'a> Parser<'a> {
|
|||||||
// | "deref" "(" GlobalVar(base) ")" offset32
|
// | "deref" "(" GlobalVar(base) ")" offset32
|
||||||
// | globalsym ["colocated"] name
|
// | globalsym ["colocated"] name
|
||||||
//
|
//
|
||||||
fn parse_global_var_decl(&mut self) -> Result<(GlobalVar, GlobalVarData)> {
|
fn parse_global_var_decl(&mut self) -> ParseResult<(GlobalVar, GlobalVarData)> {
|
||||||
let gv = self.match_gv("expected global variable number: gv«n»")?;
|
let gv = self.match_gv("expected global variable number: gv«n»")?;
|
||||||
|
|
||||||
self.match_token(Token::Equal, "expected '=' in global variable declaration")?;
|
self.match_token(Token::Equal, "expected '=' in global variable declaration")?;
|
||||||
@@ -1116,7 +1122,7 @@ impl<'a> Parser<'a> {
|
|||||||
// | "max" Imm64(bytes)
|
// | "max" Imm64(bytes)
|
||||||
// | "guard" Imm64(bytes)
|
// | "guard" Imm64(bytes)
|
||||||
//
|
//
|
||||||
fn parse_heap_decl(&mut self) -> Result<(Heap, HeapData)> {
|
fn parse_heap_decl(&mut self) -> ParseResult<(Heap, HeapData)> {
|
||||||
let heap = self.match_heap("expected heap number: heap«n»")?;
|
let heap = self.match_heap("expected heap number: heap«n»")?;
|
||||||
self.match_token(Token::Equal, "expected '=' in heap declaration")?;
|
self.match_token(Token::Equal, "expected '=' in heap declaration")?;
|
||||||
|
|
||||||
@@ -1183,7 +1189,7 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_signature_decl(
|
fn parse_signature_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
unique_isa: Option<&TargetIsa>,
|
unique_isa: Option<&TargetIsa>,
|
||||||
) -> Result<(SigRef, Signature)> {
|
) -> ParseResult<(SigRef, Signature)> {
|
||||||
let sig = self.match_sig("expected signature number: sig«n»")?;
|
let sig = self.match_sig("expected signature number: sig«n»")?;
|
||||||
self.match_token(Token::Equal, "expected '=' in signature decl")?;
|
self.match_token(Token::Equal, "expected '=' in signature decl")?;
|
||||||
let data = self.parse_signature(unique_isa)?;
|
let data = self.parse_signature(unique_isa)?;
|
||||||
@@ -1205,7 +1211,7 @@ impl<'a> Parser<'a> {
|
|||||||
// The first variant allocates a new signature reference. The second references an existing
|
// The first variant allocates a new signature reference. The second references an existing
|
||||||
// signature which must be declared first.
|
// signature which must be declared first.
|
||||||
//
|
//
|
||||||
fn parse_function_decl(&mut self, ctx: &mut Context) -> Result<(FuncRef, ExtFuncData)> {
|
fn parse_function_decl(&mut self, ctx: &mut Context) -> ParseResult<(FuncRef, ExtFuncData)> {
|
||||||
let fn_ = self.match_fn("expected function number: fn«n»")?;
|
let fn_ = self.match_fn("expected function number: fn«n»")?;
|
||||||
self.match_token(Token::Equal, "expected '=' in function decl")?;
|
self.match_token(Token::Equal, "expected '=' in function decl")?;
|
||||||
|
|
||||||
@@ -1260,7 +1266,7 @@ impl<'a> Parser<'a> {
|
|||||||
// Parse a jump table decl.
|
// Parse a jump table decl.
|
||||||
//
|
//
|
||||||
// jump-table-decl ::= * JumpTable(jt) "=" "jump_table" jt-entry {"," jt-entry}
|
// jump-table-decl ::= * JumpTable(jt) "=" "jump_table" jt-entry {"," jt-entry}
|
||||||
fn parse_jump_table_decl(&mut self) -> Result<(JumpTable, JumpTableData)> {
|
fn parse_jump_table_decl(&mut self) -> ParseResult<(JumpTable, JumpTableData)> {
|
||||||
let jt = self.match_jt()?;
|
let jt = self.match_jt()?;
|
||||||
self.match_token(Token::Equal, "expected '=' in jump_table decl")?;
|
self.match_token(Token::Equal, "expected '=' in jump_table decl")?;
|
||||||
self.match_identifier("jump_table", "expected 'jump_table'")?;
|
self.match_identifier("jump_table", "expected 'jump_table'")?;
|
||||||
@@ -1285,7 +1291,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// jt-entry ::= * Ebb(dest) | "0"
|
// jt-entry ::= * Ebb(dest) | "0"
|
||||||
fn parse_jump_table_entry(&mut self) -> Result<Option<Ebb>> {
|
fn parse_jump_table_entry(&mut self) -> ParseResult<Option<Ebb>> {
|
||||||
match self.token() {
|
match self.token() {
|
||||||
Some(Token::Integer(s)) => {
|
Some(Token::Integer(s)) => {
|
||||||
if s == "0" {
|
if s == "0" {
|
||||||
@@ -1304,7 +1310,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// stack-limit-decl ::= "stack_limit" "=" GlobalVar(gv)
|
/// stack-limit-decl ::= "stack_limit" "=" GlobalVar(gv)
|
||||||
fn parse_stack_limit_decl(&mut self) -> Result<GlobalVar> {
|
fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalVar> {
|
||||||
self.consume();
|
self.consume();
|
||||||
self.match_token(Token::Equal, "expected '=' in stack limit declaration")?;
|
self.match_token(Token::Equal, "expected '=' in stack limit declaration")?;
|
||||||
let gv = self.match_gv("expected global variable")?;
|
let gv = self.match_gv("expected global variable")?;
|
||||||
@@ -1316,7 +1322,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// function-body ::= * { extended-basic-block }
|
// function-body ::= * { extended-basic-block }
|
||||||
//
|
//
|
||||||
fn parse_function_body(&mut self, ctx: &mut Context) -> Result<()> {
|
fn parse_function_body(&mut self, ctx: &mut Context) -> ParseResult<()> {
|
||||||
while self.token() != Some(Token::RBrace) {
|
while self.token() != Some(Token::RBrace) {
|
||||||
self.parse_extended_basic_block(ctx)?;
|
self.parse_extended_basic_block(ctx)?;
|
||||||
}
|
}
|
||||||
@@ -1352,7 +1358,7 @@ impl<'a> Parser<'a> {
|
|||||||
// extended-basic-block ::= * ebb-header { instruction }
|
// extended-basic-block ::= * ebb-header { instruction }
|
||||||
// ebb-header ::= Ebb(ebb) [ebb-params] ":"
|
// ebb-header ::= Ebb(ebb) [ebb-params] ":"
|
||||||
//
|
//
|
||||||
fn parse_extended_basic_block(&mut self, ctx: &mut Context) -> Result<()> {
|
fn parse_extended_basic_block(&mut self, ctx: &mut Context) -> ParseResult<()> {
|
||||||
// Collect comments for the next ebb.
|
// Collect comments for the next ebb.
|
||||||
self.start_gathering_comments();
|
self.start_gathering_comments();
|
||||||
|
|
||||||
@@ -1415,7 +1421,7 @@ impl<'a> Parser<'a> {
|
|||||||
// value numbers of the defined values and the defined types.
|
// value numbers of the defined values and the defined types.
|
||||||
//
|
//
|
||||||
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
|
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
|
||||||
fn parse_ebb_params(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_params(&mut self, ctx: &mut Context, ebb: Ebb) -> ParseResult<()> {
|
||||||
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
|
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
|
||||||
self.match_token(Token::LPar, "expected '(' before EBB parameters")?;
|
self.match_token(Token::LPar, "expected '(' before EBB parameters")?;
|
||||||
|
|
||||||
@@ -1439,7 +1445,7 @@ impl<'a> Parser<'a> {
|
|||||||
// ebb-param ::= * Value(v) ":" Type(t) arg-loc?
|
// ebb-param ::= * Value(v) ":" Type(t) arg-loc?
|
||||||
// arg-loc ::= "[" value-location "]"
|
// arg-loc ::= "[" value-location "]"
|
||||||
//
|
//
|
||||||
fn parse_ebb_param(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_param(&mut self, ctx: &mut Context, ebb: Ebb) -> ParseResult<()> {
|
||||||
// ebb-param ::= * Value(v) ":" Type(t) arg-loc?
|
// ebb-param ::= * Value(v) ":" Type(t) arg-loc?
|
||||||
let v = self.match_value("EBB argument must be a value")?;
|
let v = self.match_value("EBB argument must be a value")?;
|
||||||
let v_location = self.loc;
|
let v_location = self.loc;
|
||||||
@@ -1466,7 +1472,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value_location(&mut self, ctx: &Context) -> Result<ValueLoc> {
|
fn parse_value_location(&mut self, ctx: &Context) -> ParseResult<ValueLoc> {
|
||||||
match self.token() {
|
match self.token() {
|
||||||
Some(Token::StackSlot(src_num)) => {
|
Some(Token::StackSlot(src_num)) => {
|
||||||
self.consume();
|
self.consume();
|
||||||
@@ -1505,7 +1511,7 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_instruction_encoding(
|
fn parse_instruction_encoding(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
) -> Result<(Option<Encoding>, Option<Vec<ValueLoc>>)> {
|
) -> ParseResult<(Option<Encoding>, Option<Vec<ValueLoc>>)> {
|
||||||
let (mut encoding, mut result_locations) = (None, None);
|
let (mut encoding, mut result_locations) = (None, None);
|
||||||
|
|
||||||
// encoding ::= "[" encoding_literal result_locations "]"
|
// encoding ::= "[" encoding_literal result_locations "]"
|
||||||
@@ -1551,7 +1557,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// inst-results ::= Value(v) { "," Value(v) }
|
// inst-results ::= Value(v) { "," Value(v) }
|
||||||
//
|
//
|
||||||
fn parse_inst_results(&mut self) -> Result<Vec<Value>> {
|
fn parse_inst_results(&mut self) -> ParseResult<Vec<Value>> {
|
||||||
// Result value numbers.
|
// Result value numbers.
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|
||||||
@@ -1576,7 +1582,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// value_alias ::= [inst-results] "->" Value(v)
|
// value_alias ::= [inst-results] "->" Value(v)
|
||||||
//
|
//
|
||||||
fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> Result<()> {
|
fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> ParseResult<()> {
|
||||||
if results.len() != 1 {
|
if results.len() != 1 {
|
||||||
return err!(self.loc, "wrong number of aliases");
|
return err!(self.loc, "wrong number of aliases");
|
||||||
}
|
}
|
||||||
@@ -1623,7 +1629,7 @@ impl<'a> Parser<'a> {
|
|||||||
result_locations: Option<Vec<ValueLoc>>,
|
result_locations: Option<Vec<ValueLoc>>,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
ebb: Ebb,
|
ebb: Ebb,
|
||||||
) -> Result<()> {
|
) -> ParseResult<()> {
|
||||||
// Define the result values.
|
// Define the result values.
|
||||||
for val in results {
|
for val in results {
|
||||||
ctx.map.def_value(*val, &self.loc)?;
|
ctx.map.def_value(*val, &self.loc)?;
|
||||||
@@ -1731,7 +1737,7 @@ impl<'a> Parser<'a> {
|
|||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
explicit_ctrl_type: Option<Type>,
|
explicit_ctrl_type: Option<Type>,
|
||||||
inst_data: &InstructionData,
|
inst_data: &InstructionData,
|
||||||
) -> Result<Type> {
|
) -> ParseResult<Type> {
|
||||||
let constraints = opcode.constraints();
|
let constraints = opcode.constraints();
|
||||||
let ctrl_type = match explicit_ctrl_type {
|
let ctrl_type = match explicit_ctrl_type {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
@@ -1808,7 +1814,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// value_list ::= [ value { "," value } ]
|
// value_list ::= [ value { "," value } ]
|
||||||
//
|
//
|
||||||
fn parse_value_list(&mut self) -> Result<VariableArgs> {
|
fn parse_value_list(&mut self) -> ParseResult<VariableArgs> {
|
||||||
let mut args = VariableArgs::new();
|
let mut args = VariableArgs::new();
|
||||||
|
|
||||||
if let Some(Token::Value(v)) = self.token() {
|
if let Some(Token::Value(v)) = self.token() {
|
||||||
@@ -1825,7 +1831,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(args)
|
Ok(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value_sequence(&mut self) -> Result<VariableArgs> {
|
fn parse_value_sequence(&mut self) -> ParseResult<VariableArgs> {
|
||||||
let mut args = VariableArgs::new();
|
let mut args = VariableArgs::new();
|
||||||
|
|
||||||
if let Some(Token::Value(v)) = self.token() {
|
if let Some(Token::Value(v)) = self.token() {
|
||||||
@@ -1843,7 +1849,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse an optional value list enclosed in parantheses.
|
// Parse an optional value list enclosed in parantheses.
|
||||||
fn parse_opt_value_list(&mut self) -> Result<VariableArgs> {
|
fn parse_opt_value_list(&mut self) -> ParseResult<VariableArgs> {
|
||||||
if !self.optional(Token::LPar) {
|
if !self.optional(Token::LPar) {
|
||||||
return Ok(VariableArgs::new());
|
return Ok(VariableArgs::new());
|
||||||
}
|
}
|
||||||
@@ -1861,7 +1867,7 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
) -> Result<InstructionData> {
|
) -> ParseResult<InstructionData> {
|
||||||
let idata = match opcode.format() {
|
let idata = match opcode.format() {
|
||||||
InstructionFormat::Unary => InstructionData::Unary {
|
InstructionFormat::Unary => InstructionData::Unary {
|
||||||
opcode,
|
opcode,
|
||||||
@@ -2289,7 +2295,7 @@ mod tests {
|
|||||||
use cretonne_codegen::ir::StackSlotKind;
|
use cretonne_codegen::ir::StackSlotKind;
|
||||||
use cretonne_codegen::ir::{ArgumentExtension, ArgumentPurpose};
|
use cretonne_codegen::ir::{ArgumentExtension, ArgumentPurpose};
|
||||||
use cretonne_codegen::settings::CallConv;
|
use cretonne_codegen::settings::CallConv;
|
||||||
use error::Error;
|
use error::ParseError;
|
||||||
use isaspec::IsaSpec;
|
use isaspec::IsaSpec;
|
||||||
use testfile::{Comment, Details};
|
use testfile::{Comment, Details};
|
||||||
|
|
||||||
@@ -2300,7 +2306,7 @@ mod tests {
|
|||||||
assert_eq!(arg.value_type, types::I32);
|
assert_eq!(arg.value_type, types::I32);
|
||||||
assert_eq!(arg.extension, ArgumentExtension::Sext);
|
assert_eq!(arg.extension, ArgumentExtension::Sext);
|
||||||
assert_eq!(arg.purpose, ArgumentPurpose::Normal);
|
assert_eq!(arg.purpose, ArgumentPurpose::Normal);
|
||||||
let Error { location, message } = p.parse_abi_param(None).unwrap_err();
|
let ParseError { location, message } = p.parse_abi_param(None).unwrap_err();
|
||||||
assert_eq!(location.line_number, 1);
|
assert_eq!(location.line_number, 1);
|
||||||
assert_eq!(message, "expected parameter type");
|
assert_eq!(message, "expected parameter type");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
use cretonne_codegen::ir::entities::AnyEntity;
|
use cretonne_codegen::ir::entities::AnyEntity;
|
||||||
use cretonne_codegen::ir::{Ebb, FuncRef, GlobalVar, Heap, JumpTable, SigRef, StackSlot, Value};
|
use cretonne_codegen::ir::{Ebb, FuncRef, GlobalVar, Heap, JumpTable, SigRef, StackSlot, Value};
|
||||||
use error::{Location, Result};
|
use error::{Location, ParseResult};
|
||||||
use lexer::split_entity_name;
|
use lexer::split_entity_name;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@@ -140,48 +140,48 @@ impl SourceMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Define the value `entity`.
|
/// Define the value `entity`.
|
||||||
pub fn def_value(&mut self, entity: Value, loc: &Location) -> Result<()> {
|
pub fn def_value(&mut self, entity: Value, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the ebb `entity`.
|
/// Define the ebb `entity`.
|
||||||
pub fn def_ebb(&mut self, entity: Ebb, loc: &Location) -> Result<()> {
|
pub fn def_ebb(&mut self, entity: Ebb, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the stack slot `entity`.
|
/// Define the stack slot `entity`.
|
||||||
pub fn def_ss(&mut self, entity: StackSlot, loc: &Location) -> Result<()> {
|
pub fn def_ss(&mut self, entity: StackSlot, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the global variable `entity`.
|
/// Define the global variable `entity`.
|
||||||
pub fn def_gv(&mut self, entity: GlobalVar, loc: &Location) -> Result<()> {
|
pub fn def_gv(&mut self, entity: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the heap `entity`.
|
/// Define the heap `entity`.
|
||||||
pub fn def_heap(&mut self, entity: Heap, loc: &Location) -> Result<()> {
|
pub fn def_heap(&mut self, entity: Heap, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the signature `entity`.
|
/// Define the signature `entity`.
|
||||||
pub fn def_sig(&mut self, entity: SigRef, loc: &Location) -> Result<()> {
|
pub fn def_sig(&mut self, entity: SigRef, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the external function `entity`.
|
/// Define the external function `entity`.
|
||||||
pub fn def_fn(&mut self, entity: FuncRef, loc: &Location) -> Result<()> {
|
pub fn def_fn(&mut self, entity: FuncRef, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define the jump table `entity`.
|
/// Define the jump table `entity`.
|
||||||
pub fn def_jt(&mut self, entity: JumpTable, loc: &Location) -> Result<()> {
|
pub fn def_jt(&mut self, entity: JumpTable, loc: &Location) -> ParseResult<()> {
|
||||||
self.def_entity(entity.into(), loc)
|
self.def_entity(entity.into(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define an entity. This can be used for instructions whose numbers never
|
/// Define an entity. This can be used for instructions whose numbers never
|
||||||
/// appear in source, or implicitly defined signatures.
|
/// appear in source, or implicitly defined signatures.
|
||||||
pub fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()> {
|
pub fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> ParseResult<()> {
|
||||||
if self.locations.insert(entity, *loc).is_some() {
|
if self.locations.insert(entity, *loc).is_some() {
|
||||||
err!(loc, "duplicate entity: {}", entity)
|
err!(loc, "duplicate entity: {}", entity)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ fn return_at_end() {
|
|||||||
handle_module(Path::new("../../wasmtests/return_at_end.wat"), &flags);
|
handle_module(Path::new("../../wasmtests/return_at_end.wat"), &flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_file(path: &Path) -> Result<Vec<u8>, io::Error> {
|
fn read_file(path: &Path) -> io::Result<Vec<u8>> {
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
let mut file = File::open(path)?;
|
let mut file = File::open(path)?;
|
||||||
file.read_to_end(&mut buf)?;
|
file.read_to_end(&mut buf)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user