committed by
Jakob Stoklund Olesen
parent
c8be39fa9d
commit
7459fee71a
@@ -171,13 +171,13 @@ def gen_display(sgrp, fmt):
|
|||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {',
|
'fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {',
|
||||||
'}'):
|
'}'):
|
||||||
fmt.line('try!(writeln!(f, "[{}]"));'.format(sgrp.name))
|
fmt.line('writeln!(f, "[{}]")?;'.format(sgrp.name))
|
||||||
with fmt.indented('for d in &DESCRIPTORS {', '}'):
|
with fmt.indented('for d in &DESCRIPTORS {', '}'):
|
||||||
fmt.line('try!(write!(f, "{} = ", d.name));')
|
fmt.line('write!(f, "{} = ", d.name)?;')
|
||||||
fmt.line(
|
fmt.line(
|
||||||
'try!(TEMPLATE.format_toml_value(d.detail,' +
|
'TEMPLATE.format_toml_value(d.detail,' +
|
||||||
'self.bytes[d.offset as usize], f));')
|
'self.bytes[d.offset as usize], f)?;')
|
||||||
fmt.line('try!(writeln!(f, ""));')
|
fmt.line('writeln!(f, "")?;')
|
||||||
fmt.line('Ok(())')
|
fmt.line('Ok(())')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ fn needs_quotes(name: &str) -> bool {
|
|||||||
impl fmt::Display for FunctionName {
|
impl fmt::Display for FunctionName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if needs_quotes(&self.0) {
|
if needs_quotes(&self.0) {
|
||||||
try!(f.write_char('"'));
|
f.write_char('"')?;
|
||||||
for c in self.0.chars().flat_map(char::escape_default) {
|
for c in self.0.chars().flat_map(char::escape_default) {
|
||||||
try!(f.write_char(c));
|
f.write_char(c)?;
|
||||||
}
|
}
|
||||||
f.write_char('"')
|
f.write_char('"')
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ impl Display for Imm64 {
|
|||||||
// 0xffff_ffff_fff8_4400
|
// 0xffff_ffff_fff8_4400
|
||||||
//
|
//
|
||||||
let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
|
let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
|
||||||
try!(write!(f, "0x{:04x}", (x >> pos) & 0xffff));
|
write!(f, "0x{:04x}", (x >> pos) & 0xffff)?;
|
||||||
while pos > 0 {
|
while pos > 0 {
|
||||||
pos -= 16;
|
pos -= 16;
|
||||||
try!(write!(f, "_{:04x}", (x >> pos) & 0xffff));
|
write!(f, "_{:04x}", (x >> pos) & 0xffff)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
|
|||||||
|
|
||||||
// All formats share the leading sign.
|
// All formats share the leading sign.
|
||||||
if sign_bit != 0 {
|
if sign_bit != 0 {
|
||||||
try!(write!(f, "-"));
|
write!(f, "-")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if e_bits == 0 {
|
if e_bits == 0 {
|
||||||
|
|||||||
@@ -265,9 +265,9 @@ impl Display for VariableArgs {
|
|||||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut 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 {
|
||||||
try!(write!(fmt, "{}", val));
|
write!(fmt, "{}", val)?;
|
||||||
} else {
|
} else {
|
||||||
try!(write!(fmt, ", {}", val));
|
write!(fmt, ", {}", val)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -289,9 +289,9 @@ pub struct UnaryImmVectorData {
|
|||||||
|
|
||||||
impl Display for UnaryImmVectorData {
|
impl Display for UnaryImmVectorData {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
try!(write!(f, "#"));
|
write!(f, "#")?;
|
||||||
for b in &self.imm {
|
for b in &self.imm {
|
||||||
try!(write!(f, "{:02x}", b));
|
write!(f, "{:02x}", b)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -356,9 +356,9 @@ impl BranchData {
|
|||||||
|
|
||||||
impl Display for BranchData {
|
impl Display for BranchData {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
try!(write!(f, "{}, {}", self.arg, self.destination));
|
write!(f, "{}, {}", self.arg, self.destination)?;
|
||||||
if !self.varargs.is_empty() {
|
if !self.varargs.is_empty() {
|
||||||
try!(write!(f, "({})", self.varargs));
|
write!(f, "({})", self.varargs)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,14 +97,14 @@ impl<'a> Iterator for Entries<'a> {
|
|||||||
impl Display for JumpTableData {
|
impl Display for JumpTableData {
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
match self.table.first().and_then(|e| e.expand()) {
|
match self.table.first().and_then(|e| e.expand()) {
|
||||||
None => try!(write!(fmt, "jump_table 0")),
|
None => write!(fmt, "jump_table 0")?,
|
||||||
Some(first) => try!(write!(fmt, "jump_table {}", first)),
|
Some(first) => write!(fmt, "jump_table {}", first)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
for dest in self.table.iter().skip(1).map(|e| e.expand()) {
|
for dest in self.table.iter().skip(1).map(|e| e.expand()) {
|
||||||
match dest {
|
match dest {
|
||||||
None => try!(write!(fmt, ", 0")),
|
None => write!(fmt, ", 0")?,
|
||||||
Some(ebb) => try!(write!(fmt, ", {}", ebb)),
|
Some(ebb) => write!(fmt, ", {}", ebb)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ fn parse_enum_value(value: &str, choices: &[&str]) -> Result<u8> {
|
|||||||
impl Configurable for Builder {
|
impl Configurable for Builder {
|
||||||
fn set_bool(&mut self, name: &str, value: bool) -> Result<()> {
|
fn set_bool(&mut self, name: &str, value: bool) -> Result<()> {
|
||||||
use self::detail::Detail;
|
use self::detail::Detail;
|
||||||
let (offset, detail) = try!(self.lookup(name));
|
let (offset, detail) = self.lookup(name)?;
|
||||||
if let Detail::Bool { bit } = detail {
|
if let Detail::Bool { bit } = detail {
|
||||||
self.set_bit(offset, bit, value);
|
self.set_bit(offset, bit, value);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -114,17 +114,17 @@ impl Configurable for Builder {
|
|||||||
|
|
||||||
fn set(&mut self, name: &str, value: &str) -> Result<()> {
|
fn set(&mut self, name: &str, value: &str) -> Result<()> {
|
||||||
use self::detail::Detail;
|
use self::detail::Detail;
|
||||||
let (offset, detail) = try!(self.lookup(name));
|
let (offset, detail) = self.lookup(name)?;
|
||||||
match detail {
|
match detail {
|
||||||
Detail::Bool { bit } => {
|
Detail::Bool { bit } => {
|
||||||
self.set_bit(offset, bit, try!(parse_bool_value(value)));
|
self.set_bit(offset, bit, parse_bool_value(value))?;
|
||||||
}
|
}
|
||||||
Detail::Num => {
|
Detail::Num => {
|
||||||
self.bytes[offset] = try!(value.parse().map_err(|_| Error::BadValue));
|
self.bytes[offset] = value.parse().map_err(|_| Error::BadValue)?;
|
||||||
}
|
}
|
||||||
Detail::Enum { last, enumerators } => {
|
Detail::Enum { last, enumerators } => {
|
||||||
self.bytes[offset] = try!(parse_enum_value(value,
|
self.bytes[offset] = parse_enum_value(value,
|
||||||
self.template.enums(last, enumerators)));
|
self.template.enums(last, enumerators))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -159,8 +159,8 @@ impl<'a> Verifier<'a> {
|
|||||||
pub fn run(&self) -> Result<()> {
|
pub fn run(&self) -> Result<()> {
|
||||||
for ebb in self.func.layout.ebbs() {
|
for ebb in self.func.layout.ebbs() {
|
||||||
for inst in self.func.layout.ebb_insts(ebb) {
|
for inst in self.func.layout.ebb_insts(ebb) {
|
||||||
try!(self.ebb_integrity(ebb, inst));
|
self.ebb_integrity(ebb, inst)?;
|
||||||
try!(self.instruction_integrity(inst));
|
self.instruction_integrity(inst)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ use std::result;
|
|||||||
/// 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>) -> Result {
|
||||||
try!(write_spec(w, func));
|
write_spec(w, func)?;
|
||||||
try!(writeln!(w, " {{"));
|
writeln!(w, " {{")?;
|
||||||
let mut any = try!(write_preamble(w, func));
|
let mut any = write_preamble(w, func)?;
|
||||||
for ebb in &func.layout {
|
for ebb in &func.layout {
|
||||||
if any {
|
if any {
|
||||||
try!(writeln!(w, ""));
|
writeln!(w, "")?;
|
||||||
}
|
}
|
||||||
try!(write_ebb(w, func, isa, ebb));
|
write_ebb(w, func, isa, ebb)?;
|
||||||
any = true;
|
any = true;
|
||||||
}
|
}
|
||||||
writeln!(w, "}}")
|
writeln!(w, "}}")
|
||||||
@@ -40,24 +40,24 @@ fn write_preamble(w: &mut Write, func: &Function) -> result::Result<bool, Error>
|
|||||||
|
|
||||||
for ss in func.stack_slots.keys() {
|
for ss in func.stack_slots.keys() {
|
||||||
any = true;
|
any = true;
|
||||||
try!(writeln!(w, " {} = {}", ss, func.stack_slots[ss]));
|
writeln!(w, " {} = {}", ss, func.stack_slots[ss])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out all signatures before functions since function declarations can refer to
|
// Write out all signatures before functions since function declarations can refer to
|
||||||
// signatures.
|
// signatures.
|
||||||
for sig in func.dfg.signatures.keys() {
|
for sig in func.dfg.signatures.keys() {
|
||||||
any = true;
|
any = true;
|
||||||
try!(writeln!(w, " {} = signature{}", sig, func.dfg.signatures[sig]));
|
writeln!(w, " {} = signature{}", sig, func.dfg.signatures[sig])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for fnref in func.dfg.ext_funcs.keys() {
|
for fnref in func.dfg.ext_funcs.keys() {
|
||||||
any = true;
|
any = true;
|
||||||
try!(writeln!(w, " {} = {}", fnref, func.dfg.ext_funcs[fnref]));
|
writeln!(w, " {} = {}", fnref, func.dfg.ext_funcs[fnref])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for jt in func.jump_tables.keys() {
|
for jt in func.jump_tables.keys() {
|
||||||
any = true;
|
any = true;
|
||||||
try!(writeln!(w, " {} = {}", jt, func.jump_tables[jt]));
|
writeln!(w, " {} = {}", jt, func.jump_tables[jt])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(any)
|
Ok(any)
|
||||||
@@ -83,29 +83,29 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
|
|||||||
|
|
||||||
// If we're writing encoding annotations, shift by 20.
|
// If we're writing encoding annotations, shift by 20.
|
||||||
if !func.encodings.is_empty() {
|
if !func.encodings.is_empty() {
|
||||||
try!(write!(w, " "));
|
write!(w, " ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut args = func.dfg.ebb_args(ebb);
|
let mut args = func.dfg.ebb_args(ebb);
|
||||||
match args.next() {
|
match args.next() {
|
||||||
None => return writeln!(w, "{}:", ebb),
|
None => return writeln!(w, "{}:", ebb),
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
try!(write!(w, "{}(", ebb));
|
write!(w, "{}(", ebb)?;
|
||||||
try!(write_arg(w, func, arg));
|
write_arg(w, func, arg)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remaining arguments.
|
// Remaining arguments.
|
||||||
for arg in args {
|
for arg in args {
|
||||||
try!(write!(w, ", "));
|
write!(w, ", ")?;
|
||||||
try!(write_arg(w, func, arg));
|
write_arg(w, func, arg)?;
|
||||||
}
|
}
|
||||||
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) -> Result {
|
||||||
try!(write_ebb_header(w, func, ebb));
|
write_ebb_header(w, func, ebb)?;
|
||||||
for inst in func.layout.ebb_insts(ebb) {
|
for inst in func.layout.ebb_insts(ebb) {
|
||||||
try!(write_instruction(w, func, isa, inst));
|
write_instruction(w, func, isa, inst)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ fn write_value_aliases(w: &mut Write, func: &Function, inst: Inst, indent: usize
|
|||||||
for &arg in func.dfg[inst].arguments().iter().flat_map(|x| x.iter()) {
|
for &arg in func.dfg[inst].arguments().iter().flat_map(|x| x.iter()) {
|
||||||
let resolved = func.dfg.resolve_aliases(arg);
|
let resolved = func.dfg.resolve_aliases(arg);
|
||||||
if resolved != arg {
|
if resolved != arg {
|
||||||
try!(writeln!(w, "{1:0$}{2} -> {3}", indent, "", arg, resolved));
|
writeln!(w, "{1:0$}{2} -> {3}", indent, "", arg, resolved)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -166,13 +166,13 @@ fn write_instruction(w: &mut Write,
|
|||||||
let indent = if func.encodings.is_empty() { 4 } else { 24 };
|
let indent = if func.encodings.is_empty() { 4 } else { 24 };
|
||||||
|
|
||||||
// Value aliases come out on lines before the instruction using them.
|
// Value aliases come out on lines before the instruction using them.
|
||||||
try!(write_value_aliases(w, func, inst, indent));
|
write_value_aliases(w, func, inst, indent)?;
|
||||||
|
|
||||||
// Write out encoding info.
|
// Write out encoding info.
|
||||||
if let Some(enc) = func.encodings.get(inst).cloned() {
|
if let Some(enc) = func.encodings.get(inst).cloned() {
|
||||||
let mut s = String::with_capacity(16);
|
let mut s = String::with_capacity(16);
|
||||||
if let Some(isa) = isa {
|
if let Some(isa) = isa {
|
||||||
try!(write!(s, "[{}", isa.display_enc(enc)));
|
write!(s, "[{}", isa.display_enc(enc))?;
|
||||||
// Write value locations, if we have them.
|
// Write value locations, if we have them.
|
||||||
if !func.locations.is_empty() {
|
if !func.locations.is_empty() {
|
||||||
let regs = isa.register_info();
|
let regs = isa.register_info();
|
||||||
@@ -184,15 +184,15 @@ fn write_instruction(w: &mut Write,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try!(write!(s, "]"));
|
write!(s, "]")?;
|
||||||
} else {
|
} else {
|
||||||
try!(write!(s, "[{}]", enc));
|
write!(s, "[{}]", enc)?;
|
||||||
}
|
}
|
||||||
// Align instruction following ISA annotation to col 24.
|
// Align instruction following ISA annotation to col 24.
|
||||||
try!(write!(w, "{:23} ", s));
|
write!(w, "{:23} ", s)?;
|
||||||
} else {
|
} else {
|
||||||
// No annotations, simply indent.
|
// No annotations, simply indent.
|
||||||
try!(write!(w, "{1:0$}", indent, ""));
|
write!(w, "{1:0$}", indent, "")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the result values, if any.
|
// Write out the result values, if any.
|
||||||
@@ -200,21 +200,21 @@ fn write_instruction(w: &mut Write,
|
|||||||
for r in func.dfg.inst_results(inst) {
|
for r in func.dfg.inst_results(inst) {
|
||||||
if !has_results {
|
if !has_results {
|
||||||
has_results = true;
|
has_results = true;
|
||||||
try!(write!(w, "{}", r));
|
write!(w, "{}", r)?;
|
||||||
} else {
|
} else {
|
||||||
try!(write!(w, ", {}", r));
|
write!(w, ", {}", r)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if has_results {
|
if has_results {
|
||||||
try!(write!(w, " = "));
|
write!(w, " = ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then the opcode, possibly with a '.type' suffix.
|
// Then the opcode, possibly with a '.type' suffix.
|
||||||
let opcode = func.dfg[inst].opcode();
|
let opcode = func.dfg[inst].opcode();
|
||||||
|
|
||||||
match type_suffix(func, inst) {
|
match type_suffix(func, inst) {
|
||||||
Some(suf) => try!(write!(w, "{}.{}", opcode, suf)),
|
Some(suf) => write!(w, "{}.{}", opcode, suf)?,
|
||||||
None => try!(write!(w, "{}", opcode)),
|
None => write!(w, "{}", opcode)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then the operands, depending on format.
|
// Then the operands, depending on format.
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl Directive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All other commands are followed by a pattern.
|
// All other commands are followed by a pattern.
|
||||||
let pat = try!(rest.parse());
|
let pat = rest.parse()?;
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
"check" => Ok(Directive::Check(pat)),
|
"check" => Ok(Directive::Check(pat)),
|
||||||
@@ -99,7 +99,7 @@ impl CheckerBuilder {
|
|||||||
pub fn directive(&mut self, l: &str) -> Result<bool> {
|
pub fn directive(&mut self, l: &str) -> Result<bool> {
|
||||||
match self.linerx.captures(l) {
|
match self.linerx.captures(l) {
|
||||||
Some(caps) => {
|
Some(caps) => {
|
||||||
self.directives.push(try!(Directive::new(caps)));
|
self.directives.push(Directive::new(caps)?);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
@@ -112,7 +112,7 @@ impl CheckerBuilder {
|
|||||||
/// This method can be used to parse a whole test file containing multiple directives.
|
/// This method can be used to parse a whole test file containing multiple directives.
|
||||||
pub fn text(&mut self, t: &str) -> Result<&mut Self> {
|
pub fn text(&mut self, t: &str) -> Result<&mut Self> {
|
||||||
for caps in self.linerx.captures_iter(t) {
|
for caps in self.linerx.captures_iter(t) {
|
||||||
self.directives.push(try!(Directive::new(caps)));
|
self.directives.push(Directive::new(caps)?);
|
||||||
}
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ impl Checker {
|
|||||||
/// Explain how directives are matched against the input text.
|
/// Explain how directives are matched against the input text.
|
||||||
pub fn explain(&self, text: &str, vars: &VariableMap) -> Result<(bool, String)> {
|
pub fn explain(&self, text: &str, vars: &VariableMap) -> Result<(bool, String)> {
|
||||||
let mut expl = Explainer::new(text);
|
let mut expl = Explainer::new(text);
|
||||||
let success = try!(self.run(text, vars, &mut expl));
|
let success = self.run(text, vars, &mut expl)?;
|
||||||
expl.finish();
|
expl.finish();
|
||||||
Ok((success, expl.to_string()))
|
Ok((success, expl.to_string()))
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ impl Checker {
|
|||||||
// The `not:` directives test the same range as `unordered:` directives. In
|
// The `not:` directives test the same range as `unordered:` directives. In
|
||||||
// particular, if they refer to defined variables, their range is restricted to
|
// particular, if they refer to defined variables, their range is restricted to
|
||||||
// the text following the match that defined the variable.
|
// the text following the match that defined the variable.
|
||||||
nots.push((dct_idx, state.unordered_begin(pat), try!(pat.resolve(&state))));
|
nots.push((dct_idx, state.unordered_begin(pat), pat.resolve(&state)?));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Directive::Regex(ref var, ref rx) => {
|
Directive::Regex(ref var, ref rx) => {
|
||||||
@@ -192,7 +192,7 @@ impl Checker {
|
|||||||
};
|
};
|
||||||
// Check if `pat` matches in `range`.
|
// Check if `pat` matches in `range`.
|
||||||
state.recorder.directive(dct_idx);
|
state.recorder.directive(dct_idx);
|
||||||
if let Some((match_begin, match_end)) = try!(state.match_positive(pat, range)) {
|
if let Some((match_begin, match_end)) = state.match_positive(pat, range)? {
|
||||||
if let &Directive::Unordered(_) = dct {
|
if let &Directive::Unordered(_) = dct {
|
||||||
// This was an unordered unordered match.
|
// This was an unordered unordered match.
|
||||||
// Keep track of the largest matched position, but leave `last_ordered` alone.
|
// Keep track of the largest matched position, but leave `last_ordered` alone.
|
||||||
@@ -318,7 +318,7 @@ impl<'a> State<'a> {
|
|||||||
// Search for `pat` in `range`, return the range matched.
|
// Search for `pat` in `range`, return the range matched.
|
||||||
// After a positive match, update variable definitions, if any.
|
// After a positive match, update variable definitions, if any.
|
||||||
fn match_positive(&mut self, pat: &Pattern, range: MatchRange) -> Result<Option<MatchRange>> {
|
fn match_positive(&mut self, pat: &Pattern, range: MatchRange) -> Result<Option<MatchRange>> {
|
||||||
let rx = try!(pat.resolve(self));
|
let rx = pat.resolve(self)?;
|
||||||
let txt = &self.text[range.0..range.1];
|
let txt = &self.text[range.0..range.1];
|
||||||
let defs = pat.defs();
|
let defs = pat.defs();
|
||||||
let matched_range = if defs.is_empty() {
|
let matched_range = if defs.is_empty() {
|
||||||
@@ -382,7 +382,7 @@ impl Display for Directive {
|
|||||||
impl Display for Checker {
|
impl Display for Checker {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
for (idx, dir) in self.directives.iter().enumerate() {
|
for (idx, dir) in self.directives.iter().enumerate() {
|
||||||
try!(write!(f, "#{} {}", idx, dir));
|
write!(f, "#{} {}", idx, dir)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,34 +89,34 @@ impl<'a> Display for Explainer<'a> {
|
|||||||
.map(|d| nextln + d + 1)
|
.map(|d| nextln + d + 1)
|
||||||
.unwrap_or(self.text.len());
|
.unwrap_or(self.text.len());
|
||||||
assert!(newln > nextln);
|
assert!(newln > nextln);
|
||||||
try!(writeln!(f, "> {}", &self.text[nextln..newln - 1]));
|
writeln!(f, "> {}", &self.text[nextln..newln - 1])?;
|
||||||
curln = nextln;
|
curln = nextln;
|
||||||
nextln = newln;
|
nextln = newln;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit ~~~ under the part of the match in curln.
|
// Emit ~~~ under the part of the match in curln.
|
||||||
if m.is_match {
|
if m.is_match {
|
||||||
try!(write!(f, " "));
|
write!(f, " ")?;
|
||||||
let mend = min(m.range.1, nextln - 1);
|
let mend = min(m.range.1, nextln - 1);
|
||||||
for pos in curln..mend {
|
for pos in curln..mend {
|
||||||
try!(if pos < m.range.0 {
|
if pos < m.range.0 {
|
||||||
write!(f, " ")
|
write!(f, " ")
|
||||||
} else if pos == m.range.0 {
|
} else if pos == m.range.0 {
|
||||||
write!(f, "^")
|
write!(f, "^")
|
||||||
} else {
|
} else {
|
||||||
write!(f, "~")
|
write!(f, "~")
|
||||||
});
|
}?;
|
||||||
}
|
}
|
||||||
try!(writeln!(f, ""));
|
writeln!(f, "")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the match message itself.
|
// Emit the match message itself.
|
||||||
try!(writeln!(f,
|
writeln!(f,
|
||||||
"{} #{}{}: {}",
|
"{} #{}{}: {}",
|
||||||
if m.is_match { "Matched" } else { "Missed" },
|
if m.is_match { "Matched" } else { "Missed" },
|
||||||
m.directive,
|
m.directive,
|
||||||
if m.is_not { " not" } else { "" },
|
if m.is_not { " not" } else { "" },
|
||||||
m.regex));
|
m.regex)?;
|
||||||
|
|
||||||
// Emit any variable definitions.
|
// Emit any variable definitions.
|
||||||
if let Ok(found) = self.vardefs.binary_search_by_key(&m.directive, |v| v.directive) {
|
if let Ok(found) = self.vardefs.binary_search_by_key(&m.directive, |v| v.directive) {
|
||||||
@@ -128,14 +128,14 @@ impl<'a> Display for Explainer<'a> {
|
|||||||
if d.directive != m.directive {
|
if d.directive != m.directive {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try!(writeln!(f, "Define {}={}", d.varname, d.value));
|
writeln!(f, "Define {}={}", d.varname, d.value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit trailing lines.
|
// Emit trailing lines.
|
||||||
for line in self.text[nextln..].lines() {
|
for line in self.text[nextln..].lines() {
|
||||||
try!(writeln!(f, "> {}", line));
|
writeln!(f, "> {}", line)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ impl Pattern {
|
|||||||
let def = if varname.is_empty() {
|
let def = if varname.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(try!(self.add_def(&varname)))
|
Some(self.add_def(&varname)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Match `$(var=$PAT)`.
|
// Match `$(var=$PAT)`.
|
||||||
@@ -270,7 +270,7 @@ impl FromStr for Pattern {
|
|||||||
let mut pat = Pattern::new();
|
let mut pat = Pattern::new();
|
||||||
let mut pos = 0;
|
let mut pos = 0;
|
||||||
while pos < s.len() {
|
while pos < s.len() {
|
||||||
let (part, len) = try!(pat.parse_part(&s[pos..]));
|
let (part, len) = pat.parse_part(&s[pos..])?;
|
||||||
if let Some(v) = part.ref_var() {
|
if let Some(v) = part.ref_var() {
|
||||||
if pat.defines_var(v) {
|
if pat.defines_var(v) {
|
||||||
return Err(Error::Backref(format!("unsupported back-reference to '${}' \
|
return Err(Error::Backref(format!("unsupported back-reference to '${}' \
|
||||||
@@ -353,7 +353,7 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(try!(RegexBuilder::new(&out).multi_line(true).compile()))
|
Ok(RegexBuilder::new(&out).multi_line(true).compile()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +361,7 @@ impl Display for Pattern {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
for part in &self.parts {
|
for part in &self.parts {
|
||||||
use self::Part::*;
|
use self::Part::*;
|
||||||
try!(match *part {
|
match *part {
|
||||||
Text(ref txt) if txt == "" => write!(f, "$()"),
|
Text(ref txt) if txt == "" => write!(f, "$()"),
|
||||||
Text(ref txt) if txt == "$" => write!(f, "$$"),
|
Text(ref txt) if txt == "$" => write!(f, "$$"),
|
||||||
Text(ref txt) => write!(f, "{}", txt),
|
Text(ref txt) => write!(f, "{}", txt),
|
||||||
@@ -374,7 +374,7 @@ impl Display for Pattern {
|
|||||||
write!(f, "$({}={})", defvar, litrx)
|
write!(f, "$({}={})", defvar, litrx)
|
||||||
}
|
}
|
||||||
DefVar { def, ref var } => write!(f, "$({}=${})", self.defs[def], var),
|
DefVar { def, ref var } => write!(f, "$({}=${})", self.defs[def], var),
|
||||||
});
|
}?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ pub fn parse_test<'a>(text: &'a str) -> Result<TestFile<'a>> {
|
|||||||
parser.gather_comments(AnyEntity::Function);
|
parser.gather_comments(AnyEntity::Function);
|
||||||
Ok(TestFile {
|
Ok(TestFile {
|
||||||
commands: parser.parse_test_commands(),
|
commands: parser.parse_test_commands(),
|
||||||
isa_spec: try!(parser.parse_isa_specs()),
|
isa_spec: parser.parse_isa_specs()?,
|
||||||
preamble_comments: parser.take_comments(),
|
preamble_comments: parser.take_comments(),
|
||||||
functions: try!(parser.parse_function_list()),
|
functions: parser.parse_function_list()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ impl Context {
|
|||||||
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
||||||
InstructionData::ExtractLane { ref mut arg, .. } |
|
InstructionData::ExtractLane { ref mut arg, .. } |
|
||||||
InstructionData::BranchTable { ref mut arg, .. } => {
|
InstructionData::BranchTable { ref mut arg, .. } => {
|
||||||
try!(self.map.rewrite_value(arg, loc));
|
self.map.rewrite_value(arg, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Binary { ref mut args, .. } |
|
InstructionData::Binary { ref mut args, .. } |
|
||||||
@@ -163,44 +163,44 @@ impl Context {
|
|||||||
InstructionData::InsertLane { ref mut args, .. } |
|
InstructionData::InsertLane { ref mut args, .. } |
|
||||||
InstructionData::IntCompare { ref mut args, .. } |
|
InstructionData::IntCompare { ref mut args, .. } |
|
||||||
InstructionData::FloatCompare { ref mut args, .. } => {
|
InstructionData::FloatCompare { ref mut args, .. } => {
|
||||||
try!(self.map.rewrite_values(args, loc));
|
self.map.rewrite_values(args, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Ternary { ref mut args, .. } => {
|
InstructionData::Ternary { ref mut args, .. } => {
|
||||||
try!(self.map.rewrite_values(args, loc));
|
self.map.rewrite_values(args, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::TernaryOverflow { ref mut data, .. } => {
|
InstructionData::TernaryOverflow { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_values(&mut data.args, loc));
|
self.map.rewrite_values(&mut data.args, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Jump { ref mut data, .. } => {
|
InstructionData::Jump { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_ebb(&mut data.destination, loc));
|
self.map.rewrite_ebb(&mut data.destination, loc)?;
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Branch { ref mut data, .. } => {
|
InstructionData::Branch { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_value(&mut data.arg, loc));
|
self.map.rewrite_value(&mut data.arg, loc)?;
|
||||||
try!(self.map.rewrite_ebb(&mut data.destination, loc));
|
self.map.rewrite_ebb(&mut data.destination, loc)?;
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Call { ref mut data, .. } => {
|
InstructionData::Call { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::IndirectCall { ref mut data, .. } => {
|
InstructionData::IndirectCall { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_value(&mut data.arg, loc));
|
self.map.rewrite_value(&mut data.arg, loc)?;
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Return { ref mut data, .. } => {
|
InstructionData::Return { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::ReturnReg { ref mut data, .. } => {
|
InstructionData::ReturnReg { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_value(&mut data.arg, loc));
|
self.map.rewrite_value(&mut data.arg, loc)?;
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
self.map.rewrite_values(&mut data.varargs, loc)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ impl Context {
|
|||||||
let loc = jt.into();
|
let loc = jt.into();
|
||||||
for ebb_ref in self.function.jump_tables[jt].as_mut_slice() {
|
for ebb_ref in self.function.jump_tables[jt].as_mut_slice() {
|
||||||
if let Some(mut ebb) = ebb_ref.expand() {
|
if let Some(mut ebb) = ebb_ref.expand() {
|
||||||
try!(self.map.rewrite_ebb(&mut ebb, loc));
|
self.map.rewrite_ebb(&mut ebb, loc)?;
|
||||||
// Convert back to a packed option.
|
// Convert back to a packed option.
|
||||||
*ebb_ref = ebb.into();
|
*ebb_ref = ebb.into();
|
||||||
}
|
}
|
||||||
@@ -480,9 +480,9 @@ impl<'a> Parser<'a> {
|
|||||||
match command {
|
match command {
|
||||||
"set" => {
|
"set" => {
|
||||||
last_set_loc = Some(self.loc);
|
last_set_loc = Some(self.loc);
|
||||||
try!(isaspec::parse_options(self.consume_line().trim().split_whitespace(),
|
isaspec::parse_options(self.consume_line().trim().split_whitespace(),
|
||||||
&mut flag_builder,
|
&mut flag_builder,
|
||||||
&self.loc));
|
&self.loc)?;
|
||||||
}
|
}
|
||||||
"isa" => {
|
"isa" => {
|
||||||
last_set_loc = None;
|
last_set_loc = None;
|
||||||
@@ -501,7 +501,7 @@ impl<'a> Parser<'a> {
|
|||||||
Some(b) => b,
|
Some(b) => b,
|
||||||
};
|
};
|
||||||
// Apply the ISA-specific settings to `isa_builder`.
|
// Apply the ISA-specific settings to `isa_builder`.
|
||||||
try!(isaspec::parse_options(words, &mut isa_builder, &self.loc));
|
isaspec::parse_options(words, &mut isa_builder, &self.loc)?;
|
||||||
|
|
||||||
// Construct a trait object with the aggregrate settings.
|
// Construct a trait object with the aggregrate settings.
|
||||||
isas.push(isa_builder.finish(settings::Flags::new(&flag_builder)));
|
isas.push(isa_builder.finish(settings::Flags::new(&flag_builder)));
|
||||||
@@ -526,7 +526,7 @@ impl<'a> Parser<'a> {
|
|||||||
pub fn parse_function_list(&mut self) -> Result<Vec<(Function, Details<'a>)>> {
|
pub fn parse_function_list(&mut self) -> Result<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(try!(self.parse_function()));
|
list.push(self.parse_function()?);
|
||||||
}
|
}
|
||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
@@ -542,17 +542,17 @@ impl<'a> Parser<'a> {
|
|||||||
self.comments.clear();
|
self.comments.clear();
|
||||||
self.gather_comments(AnyEntity::Function);
|
self.gather_comments(AnyEntity::Function);
|
||||||
|
|
||||||
let (location, name, sig) = try!(self.parse_function_spec());
|
let (location, name, sig) = self.parse_function_spec()?;
|
||||||
let mut ctx = Context::new(Function::with_name_signature(name, sig));
|
let mut ctx = Context::new(Function::with_name_signature(name, sig));
|
||||||
|
|
||||||
// function ::= function-spec * "{" preamble function-body "}"
|
// function ::= function-spec * "{" preamble function-body "}"
|
||||||
try!(self.match_token(Token::LBrace, "expected '{' before function body"));
|
self.match_token(Token::LBrace, "expected '{' before function body")?;
|
||||||
// function ::= function-spec "{" * preamble function-body "}"
|
// function ::= function-spec "{" * preamble function-body "}"
|
||||||
try!(self.parse_preamble(&mut ctx));
|
self.parse_preamble(&mut ctx)?;
|
||||||
// function ::= function-spec "{" preamble * function-body "}"
|
// function ::= function-spec "{" preamble * function-body "}"
|
||||||
try!(self.parse_function_body(&mut ctx));
|
self.parse_function_body(&mut ctx)?;
|
||||||
// function ::= function-spec "{" preamble function-body * "}"
|
// function ::= function-spec "{" preamble function-body * "}"
|
||||||
try!(self.match_token(Token::RBrace, "expected '}' after function body"));
|
self.match_token(Token::RBrace, "expected '}' after function body")?;
|
||||||
|
|
||||||
// Collect any comments following the end of the function, then stop gathering comments.
|
// Collect any comments following the end of the function, then stop gathering comments.
|
||||||
self.gather_comments(AnyEntity::Function);
|
self.gather_comments(AnyEntity::Function);
|
||||||
@@ -561,7 +561,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Rewrite references to values and EBBs after parsing everything to allow forward
|
// Rewrite references to values and EBBs after parsing everything to allow forward
|
||||||
// references.
|
// references.
|
||||||
try!(ctx.rewrite_references());
|
ctx.rewrite_references()?;
|
||||||
|
|
||||||
let details = Details {
|
let details = Details {
|
||||||
location: location,
|
location: location,
|
||||||
@@ -577,14 +577,14 @@ impl<'a> Parser<'a> {
|
|||||||
// function-spec ::= * "function" name signature
|
// function-spec ::= * "function" name signature
|
||||||
//
|
//
|
||||||
fn parse_function_spec(&mut self) -> Result<(Location, FunctionName, Signature)> {
|
fn parse_function_spec(&mut self) -> Result<(Location, FunctionName, Signature)> {
|
||||||
try!(self.match_identifier("function", "expected 'function'"));
|
self.match_identifier("function", "expected 'function'")?;
|
||||||
let location = self.loc;
|
let location = self.loc;
|
||||||
|
|
||||||
// function-spec ::= "function" * name signature
|
// function-spec ::= "function" * name signature
|
||||||
let name = try!(self.parse_function_name());
|
let name = self.parse_function_name()?;
|
||||||
|
|
||||||
// function-spec ::= "function" name * signature
|
// function-spec ::= "function" name * signature
|
||||||
let sig = try!(self.parse_signature());
|
let sig = self.parse_signature()?;
|
||||||
|
|
||||||
Ok((location, name, sig))
|
Ok((location, name, sig))
|
||||||
}
|
}
|
||||||
@@ -610,14 +610,14 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_signature(&mut self) -> Result<Signature> {
|
fn parse_signature(&mut self) -> Result<Signature> {
|
||||||
let mut sig = Signature::new();
|
let mut sig = Signature::new();
|
||||||
|
|
||||||
try!(self.match_token(Token::LPar, "expected function signature: ( args... )"));
|
self.match_token(Token::LPar, "expected function signature: ( args... )")?;
|
||||||
// signature ::= "(" * [arglist] ")" ["->" retlist] [call_conv]
|
// signature ::= "(" * [arglist] ")" ["->" retlist] [call_conv]
|
||||||
if self.token() != Some(Token::RPar) {
|
if self.token() != Some(Token::RPar) {
|
||||||
sig.argument_types = try!(self.parse_argument_list());
|
sig.argument_types = self.parse_argument_list()?;
|
||||||
}
|
}
|
||||||
try!(self.match_token(Token::RPar, "expected ')' after function arguments"));
|
self.match_token(Token::RPar, "expected ')' after function arguments")?;
|
||||||
if self.optional(Token::Arrow) {
|
if self.optional(Token::Arrow) {
|
||||||
sig.return_types = try!(self.parse_argument_list());
|
sig.return_types = self.parse_argument_list()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TBD: calling convention.
|
// TBD: calling convention.
|
||||||
@@ -633,12 +633,12 @@ impl<'a> Parser<'a> {
|
|||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
|
|
||||||
// arglist ::= * arg { "," arg }
|
// arglist ::= * arg { "," arg }
|
||||||
list.push(try!(self.parse_argument_type()));
|
list.push(self.parse_argument_type()?);
|
||||||
|
|
||||||
// arglist ::= arg * { "," arg }
|
// arglist ::= arg * { "," arg }
|
||||||
while self.optional(Token::Comma) {
|
while self.optional(Token::Comma) {
|
||||||
// arglist ::= arg { "," * arg }
|
// arglist ::= arg { "," * arg }
|
||||||
list.push(try!(self.parse_argument_type()));
|
list.push(self.parse_argument_type()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(list)
|
Ok(list)
|
||||||
@@ -647,7 +647,7 @@ 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<ArgumentType> {
|
fn parse_argument_type(&mut self) -> Result<ArgumentType> {
|
||||||
// arg ::= * type { flag }
|
// arg ::= * type { flag }
|
||||||
let mut arg = ArgumentType::new(try!(self.match_type("expected argument type")));
|
let mut arg = ArgumentType::new(self.match_type("expected argument type")?);
|
||||||
|
|
||||||
// arg ::= type * { flag }
|
// arg ::= type * { flag }
|
||||||
while let Some(Token::Identifier(s)) = self.token() {
|
while let Some(Token::Identifier(s)) = self.token() {
|
||||||
@@ -674,7 +674,7 @@ impl<'a> Parser<'a> {
|
|||||||
// 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) -> Result<()> {
|
||||||
loop {
|
loop {
|
||||||
try!(match self.token() {
|
match self.token() {
|
||||||
Some(Token::StackSlot(..)) => {
|
Some(Token::StackSlot(..)) => {
|
||||||
self.gather_comments(ctx.function.stack_slots.next_key());
|
self.gather_comments(ctx.function.stack_slots.next_key());
|
||||||
self.parse_stack_slot_decl()
|
self.parse_stack_slot_decl()
|
||||||
@@ -697,7 +697,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
// More to come..
|
// More to come..
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
});
|
}?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,12 +705,12 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// stack-slot-decl ::= * StackSlot(ss) "=" "stack_slot" Bytes {"," stack-slot-flag}
|
// stack-slot-decl ::= * StackSlot(ss) "=" "stack_slot" Bytes {"," stack-slot-flag}
|
||||||
fn parse_stack_slot_decl(&mut self) -> Result<(u32, StackSlotData)> {
|
fn parse_stack_slot_decl(&mut self) -> Result<(u32, StackSlotData)> {
|
||||||
let number = try!(self.match_ss("expected stack slot number: ss«n»"));
|
let number = self.match_ss("expected stack slot number: ss«n»")?;
|
||||||
try!(self.match_token(Token::Equal, "expected '=' in stack_slot decl"));
|
self.match_token(Token::Equal, "expected '=' in stack_slot decl")?;
|
||||||
try!(self.match_identifier("stack_slot", "expected 'stack_slot'"));
|
self.match_identifier("stack_slot", "expected 'stack_slot'")?;
|
||||||
|
|
||||||
// stack-slot-decl ::= StackSlot(ss) "=" "stack_slot" * Bytes {"," stack-slot-flag}
|
// stack-slot-decl ::= StackSlot(ss) "=" "stack_slot" * Bytes {"," stack-slot-flag}
|
||||||
let bytes: i64 = try!(self.match_imm64("expected byte-size in stack_slot decl")).into();
|
let bytes: i64 = self.match_imm64("expected byte-size in stack_slot decl")?.into();
|
||||||
if bytes < 0 {
|
if bytes < 0 {
|
||||||
return err!(self.loc, "negative stack slot size");
|
return err!(self.loc, "negative stack slot size");
|
||||||
}
|
}
|
||||||
@@ -728,10 +728,10 @@ impl<'a> Parser<'a> {
|
|||||||
// signature-decl ::= SigRef(sigref) "=" "signature" signature
|
// signature-decl ::= SigRef(sigref) "=" "signature" signature
|
||||||
//
|
//
|
||||||
fn parse_signature_decl(&mut self) -> Result<(u32, Signature)> {
|
fn parse_signature_decl(&mut self) -> Result<(u32, Signature)> {
|
||||||
let number = try!(self.match_sig("expected signature number: sig«n»"));
|
let number = self.match_sig("expected signature number: sig«n»")?;
|
||||||
try!(self.match_token(Token::Equal, "expected '=' in signature decl"));
|
self.match_token(Token::Equal, "expected '=' in signature decl")?;
|
||||||
try!(self.match_identifier("signature", "expected 'signature'"));
|
self.match_identifier("signature", "expected 'signature'")?;
|
||||||
let data = try!(self.parse_signature());
|
let data = self.parse_signature()?;
|
||||||
Ok((number, data))
|
Ok((number, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,12 +746,12 @@ impl<'a> Parser<'a> {
|
|||||||
// signature which must be declared first.
|
// signature which must be declared first.
|
||||||
//
|
//
|
||||||
fn parse_function_decl(&mut self, ctx: &mut Context) -> Result<(u32, ExtFuncData)> {
|
fn parse_function_decl(&mut self, ctx: &mut Context) -> Result<(u32, ExtFuncData)> {
|
||||||
let number = try!(self.match_fn("expected function number: fn«n»"));
|
let number = self.match_fn("expected function number: fn«n»")?;
|
||||||
try!(self.match_token(Token::Equal, "expected '=' in function decl"));
|
self.match_token(Token::Equal, "expected '=' in function decl")?;
|
||||||
|
|
||||||
let data = match self.token() {
|
let data = match self.token() {
|
||||||
Some(Token::Identifier("function")) => {
|
Some(Token::Identifier("function")) => {
|
||||||
let (loc, name, sig) = try!(self.parse_function_spec());
|
let (loc, name, sig) = self.parse_function_spec()?;
|
||||||
let sigref = ctx.function.dfg.signatures.push(sig);
|
let sigref = ctx.function.dfg.signatures.push(sig);
|
||||||
ctx.map.def_entity(sigref.into(), &loc).expect("duplicate SigRef entities created");
|
ctx.map.def_entity(sigref.into(), &loc).expect("duplicate SigRef entities created");
|
||||||
ExtFuncData {
|
ExtFuncData {
|
||||||
@@ -760,9 +760,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Token::SigRef(sig_src)) => {
|
Some(Token::SigRef(sig_src)) => {
|
||||||
let sig = try!(ctx.get_sig(sig_src, &self.loc));
|
let sig = ctx.get_sig(sig_src, &self.loc)?;
|
||||||
self.consume();
|
self.consume();
|
||||||
let name = try!(self.parse_function_name());
|
let name = self.parse_function_name()?;
|
||||||
ExtFuncData {
|
ExtFuncData {
|
||||||
name: name,
|
name: name,
|
||||||
signature: sig,
|
signature: sig,
|
||||||
@@ -777,15 +777,15 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
// 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<(u32, JumpTableData)> {
|
fn parse_jump_table_decl(&mut self) -> Result<(u32, JumpTableData)> {
|
||||||
let number = try!(self.match_jt());
|
let number = self.match_jt()?;
|
||||||
try!(self.match_token(Token::Equal, "expected '=' in jump_table decl"));
|
self.match_token(Token::Equal, "expected '=' in jump_table decl")?;
|
||||||
try!(self.match_identifier("jump_table", "expected 'jump_table'"));
|
self.match_identifier("jump_table", "expected 'jump_table'")?;
|
||||||
|
|
||||||
let mut data = JumpTableData::new();
|
let mut data = JumpTableData::new();
|
||||||
|
|
||||||
// jump-table-decl ::= JumpTable(jt) "=" "jump_table" * jt-entry {"," jt-entry}
|
// jump-table-decl ::= JumpTable(jt) "=" "jump_table" * jt-entry {"," jt-entry}
|
||||||
for idx in 0usize.. {
|
for idx in 0usize.. {
|
||||||
if let Some(dest) = try!(self.parse_jump_table_entry()) {
|
if let Some(dest) = self.parse_jump_table_entry()? {
|
||||||
data.set_entry(idx, dest);
|
data.set_entry(idx, dest);
|
||||||
}
|
}
|
||||||
if !self.optional(Token::Comma) {
|
if !self.optional(Token::Comma) {
|
||||||
@@ -821,7 +821,7 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
fn parse_function_body(&mut self, ctx: &mut Context) -> Result<()> {
|
fn parse_function_body(&mut self, ctx: &mut Context) -> Result<()> {
|
||||||
while self.token() != Some(Token::RBrace) {
|
while self.token() != Some(Token::RBrace) {
|
||||||
try!(self.parse_extended_basic_block(ctx));
|
self.parse_extended_basic_block(ctx)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -832,14 +832,14 @@ impl<'a> Parser<'a> {
|
|||||||
// ebb-header ::= Ebb(ebb) [ebb-args] ":"
|
// ebb-header ::= Ebb(ebb) [ebb-args] ":"
|
||||||
//
|
//
|
||||||
fn parse_extended_basic_block(&mut self, ctx: &mut Context) -> Result<()> {
|
fn parse_extended_basic_block(&mut self, ctx: &mut Context) -> Result<()> {
|
||||||
let ebb_num = try!(self.match_ebb("expected EBB header"));
|
let ebb_num = self.match_ebb("expected EBB header")?;
|
||||||
let ebb = try!(ctx.add_ebb(ebb_num, &self.loc));
|
let ebb = ctx.add_ebb(ebb_num, &self.loc)?;
|
||||||
self.gather_comments(ebb);
|
self.gather_comments(ebb);
|
||||||
|
|
||||||
if !self.optional(Token::Colon) {
|
if !self.optional(Token::Colon) {
|
||||||
// ebb-header ::= Ebb(ebb) [ * ebb-args ] ":"
|
// ebb-header ::= Ebb(ebb) [ * ebb-args ] ":"
|
||||||
try!(self.parse_ebb_args(ctx, ebb));
|
self.parse_ebb_args(ctx, ebb)?;
|
||||||
try!(self.match_token(Token::Colon, "expected ':' after EBB arguments"));
|
self.match_token(Token::Colon, "expected ':' after EBB arguments")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extended-basic-block ::= ebb-header * { instruction }
|
// extended-basic-block ::= ebb-header * { instruction }
|
||||||
@@ -848,7 +848,7 @@ impl<'a> Parser<'a> {
|
|||||||
Some(Token::Identifier(_)) => true,
|
Some(Token::Identifier(_)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
} {
|
} {
|
||||||
try!(self.parse_instruction(ctx, ebb));
|
self.parse_instruction(ctx, ebb)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -860,19 +860,19 @@ impl<'a> Parser<'a> {
|
|||||||
// ebb-args ::= * "(" ebb-arg { "," ebb-arg } ")"
|
// ebb-args ::= * "(" ebb-arg { "," ebb-arg } ")"
|
||||||
fn parse_ebb_args(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_args(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
||||||
// ebb-args ::= * "(" ebb-arg { "," ebb-arg } ")"
|
// ebb-args ::= * "(" ebb-arg { "," ebb-arg } ")"
|
||||||
try!(self.match_token(Token::LPar, "expected '(' before EBB arguments"));
|
self.match_token(Token::LPar, "expected '(' before EBB arguments")?;
|
||||||
|
|
||||||
// ebb-args ::= "(" * ebb-arg { "," ebb-arg } ")"
|
// ebb-args ::= "(" * ebb-arg { "," ebb-arg } ")"
|
||||||
try!(self.parse_ebb_arg(ctx, ebb));
|
self.parse_ebb_arg(ctx, ebb)?;
|
||||||
|
|
||||||
// ebb-args ::= "(" ebb-arg * { "," ebb-arg } ")"
|
// ebb-args ::= "(" ebb-arg * { "," ebb-arg } ")"
|
||||||
while self.optional(Token::Comma) {
|
while self.optional(Token::Comma) {
|
||||||
// ebb-args ::= "(" ebb-arg { "," * ebb-arg } ")"
|
// ebb-args ::= "(" ebb-arg { "," * ebb-arg } ")"
|
||||||
try!(self.parse_ebb_arg(ctx, ebb));
|
self.parse_ebb_arg(ctx, ebb)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ebb-args ::= "(" ebb-arg { "," ebb-arg } * ")"
|
// ebb-args ::= "(" ebb-arg { "," ebb-arg } * ")"
|
||||||
try!(self.match_token(Token::RPar, "expected ')' after EBB arguments"));
|
self.match_token(Token::RPar, "expected ')' after EBB arguments")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -883,12 +883,12 @@ impl<'a> Parser<'a> {
|
|||||||
//
|
//
|
||||||
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
||||||
// ebb-arg ::= * Value(vx) ":" Type(t)
|
// ebb-arg ::= * Value(vx) ":" Type(t)
|
||||||
let vx = try!(self.match_value("EBB argument must be a value"));
|
let vx = self.match_value("EBB argument must be a value")?;
|
||||||
let vx_location = self.loc;
|
let vx_location = self.loc;
|
||||||
// ebb-arg ::= Value(vx) * ":" Type(t)
|
// ebb-arg ::= Value(vx) * ":" Type(t)
|
||||||
try!(self.match_token(Token::Colon, "expected ':' after EBB argument"));
|
self.match_token(Token::Colon, "expected ':' after EBB argument")?;
|
||||||
// ebb-arg ::= Value(vx) ":" * Type(t)
|
// ebb-arg ::= Value(vx) ":" * Type(t)
|
||||||
let t = try!(self.match_type("expected EBB argument type"));
|
let t = self.match_type("expected EBB argument type")?;
|
||||||
// Allocate the EBB argument and add the mapping.
|
// Allocate the EBB argument and add the mapping.
|
||||||
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
||||||
ctx.map.def_value(vx, value, &vx_location)
|
ctx.map.def_value(vx, value, &vx_location)
|
||||||
@@ -915,10 +915,10 @@ impl<'a> Parser<'a> {
|
|||||||
// inst-results ::= Value(v) * { "," Value(vx) }
|
// inst-results ::= Value(v) * { "," Value(vx) }
|
||||||
while self.optional(Token::Comma) {
|
while self.optional(Token::Comma) {
|
||||||
// inst-results ::= Value(v) { "," * Value(vx) }
|
// inst-results ::= Value(v) { "," * Value(vx) }
|
||||||
results.push(try!(self.match_value("expected result value")));
|
results.push(self.match_value("expected result value")?);
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(self.match_token(Token::Equal, "expected '=' before opcode"));
|
self.match_token(Token::Equal, "expected '=' before opcode")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// instruction ::= [inst-results "="] * Opcode(opc) ["." Type] ...
|
// instruction ::= [inst-results "="] * Opcode(opc) ["." Type] ...
|
||||||
@@ -936,20 +936,20 @@ impl<'a> Parser<'a> {
|
|||||||
// Look for a controlling type variable annotation.
|
// Look for a controlling type variable annotation.
|
||||||
// instruction ::= [inst-results "="] Opcode(opc) * ["." Type] ...
|
// instruction ::= [inst-results "="] Opcode(opc) * ["." Type] ...
|
||||||
let explicit_ctrl_type = if self.optional(Token::Dot) {
|
let explicit_ctrl_type = if self.optional(Token::Dot) {
|
||||||
Some(try!(self.match_type("expected type after 'opcode.'")))
|
Some(self.match_type("expected type after 'opcode.'")?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// instruction ::= [inst-results "="] Opcode(opc) ["." Type] * ...
|
// instruction ::= [inst-results "="] Opcode(opc) ["." Type] * ...
|
||||||
let inst_data = try!(self.parse_inst_operands(ctx, opcode));
|
let inst_data = self.parse_inst_operands(ctx, opcode)?;
|
||||||
|
|
||||||
// We're done parsing the instruction now.
|
// We're done parsing the instruction now.
|
||||||
//
|
//
|
||||||
// We still need to check that the number of result values in the source matches the opcode
|
// We still need to check that the number of result values in the source matches the opcode
|
||||||
// or function call signature. We also need to create values with the right type for all
|
// or function call signature. We also need to create values with the right type for all
|
||||||
// the instruction results.
|
// the instruction results.
|
||||||
let ctrl_typevar = try!(self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data));
|
let ctrl_typevar = self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)?;
|
||||||
let inst = ctx.function.dfg.make_inst(inst_data);
|
let inst = ctx.function.dfg.make_inst(inst_data);
|
||||||
let num_results = ctx.function.dfg.make_inst_results(inst, ctrl_typevar);
|
let num_results = ctx.function.dfg.make_inst_results(inst, ctrl_typevar);
|
||||||
ctx.function.layout.append_inst(inst, ebb);
|
ctx.function.layout.append_inst(inst, ebb);
|
||||||
@@ -1046,7 +1046,7 @@ impl<'a> Parser<'a> {
|
|||||||
V: Iterator<Item = Value>
|
V: Iterator<Item = Value>
|
||||||
{
|
{
|
||||||
for (src, val) in results.zip(new_results) {
|
for (src, val) in results.zip(new_results) {
|
||||||
try!(map.def_value(src, val, &self.loc));
|
map.def_value(src, val, &self.loc)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1066,7 +1066,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while self.optional(Token::Comma) {
|
while self.optional(Token::Comma) {
|
||||||
args.push(try!(self.match_value("expected value in argument list")));
|
args.push(self.match_value("expected value in argument list")?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(args)
|
Ok(args)
|
||||||
@@ -1078,9 +1078,9 @@ impl<'a> Parser<'a> {
|
|||||||
return Ok(VariableArgs::new());
|
return Ok(VariableArgs::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = try!(self.parse_value_list());
|
let args = self.parse_value_list()?;
|
||||||
|
|
||||||
try!(self.match_token(Token::RPar, "expected ')' after arguments"));
|
self.match_token(Token::RPar, "expected ')' after arguments")?;
|
||||||
|
|
||||||
Ok(args)
|
Ok(args)
|
||||||
}
|
}
|
||||||
@@ -1099,28 +1099,28 @@ impl<'a> Parser<'a> {
|
|||||||
InstructionData::Unary {
|
InstructionData::Unary {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
arg: try!(self.match_value("expected SSA value operand")),
|
arg: self.match_value("expected SSA value operand")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::UnaryImm => {
|
InstructionFormat::UnaryImm => {
|
||||||
InstructionData::UnaryImm {
|
InstructionData::UnaryImm {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
imm: try!(self.match_imm64("expected immediate integer operand")),
|
imm: self.match_imm64("expected immediate integer operand")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::UnaryIeee32 => {
|
InstructionFormat::UnaryIeee32 => {
|
||||||
InstructionData::UnaryIeee32 {
|
InstructionData::UnaryIeee32 {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
imm: try!(self.match_ieee32("expected immediate 32-bit float operand")),
|
imm: self.match_ieee32("expected immediate 32-bit float operand")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::UnaryIeee64 => {
|
InstructionFormat::UnaryIeee64 => {
|
||||||
InstructionData::UnaryIeee64 {
|
InstructionData::UnaryIeee64 {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
imm: try!(self.match_ieee64("expected immediate 64-bit float operand")),
|
imm: self.match_ieee64("expected immediate 64-bit float operand")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::UnaryImmVector => {
|
InstructionFormat::UnaryImmVector => {
|
||||||
@@ -1131,13 +1131,13 @@ impl<'a> Parser<'a> {
|
|||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
second_result: None.into(),
|
second_result: None.into(),
|
||||||
arg: try!(self.match_value("expected SSA value operand")),
|
arg: self.match_value("expected SSA value operand")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::Binary => {
|
InstructionFormat::Binary => {
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
InstructionData::Binary {
|
InstructionData::Binary {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1145,9 +1145,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::BinaryImm => {
|
InstructionFormat::BinaryImm => {
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_imm64("expected immediate integer second operand"));
|
let rhs = self.match_imm64("expected immediate integer second operand")?;
|
||||||
InstructionData::BinaryImm {
|
InstructionData::BinaryImm {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1156,9 +1156,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::BinaryImmRev => {
|
InstructionFormat::BinaryImmRev => {
|
||||||
let lhs = try!(self.match_imm64("expected immediate integer first operand"));
|
let lhs = self.match_imm64("expected immediate integer first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
InstructionData::BinaryImmRev {
|
InstructionData::BinaryImmRev {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1167,9 +1167,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::BinaryOverflow => {
|
InstructionFormat::BinaryOverflow => {
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
InstructionData::BinaryOverflow {
|
InstructionData::BinaryOverflow {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1180,11 +1180,11 @@ impl<'a> Parser<'a> {
|
|||||||
InstructionFormat::Ternary => {
|
InstructionFormat::Ternary => {
|
||||||
// Names here refer to the `select` instruction.
|
// Names here refer to the `select` instruction.
|
||||||
// This format is also use by `fma`.
|
// This format is also use by `fma`.
|
||||||
let ctrl_arg = try!(self.match_value("expected SSA value control operand"));
|
let ctrl_arg = self.match_value("expected SSA value control operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let true_arg = try!(self.match_value("expected SSA value true operand"));
|
let true_arg = self.match_value("expected SSA value true operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let false_arg = try!(self.match_value("expected SSA value false operand"));
|
let false_arg = self.match_value("expected SSA value false operand")?;
|
||||||
InstructionData::Ternary {
|
InstructionData::Ternary {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1193,11 +1193,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
InstructionFormat::TernaryOverflow => {
|
InstructionFormat::TernaryOverflow => {
|
||||||
// Names here refer to the `iadd_carry` instruction.
|
// Names here refer to the `iadd_carry` instruction.
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let cin = try!(self.match_value("expected SSA value third operand"));
|
let cin = self.match_value("expected SSA value third operand")?;
|
||||||
InstructionData::TernaryOverflow {
|
InstructionData::TernaryOverflow {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1207,8 +1207,8 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
InstructionFormat::Jump => {
|
InstructionFormat::Jump => {
|
||||||
// Parse the destination EBB number. Don't translate source to local numbers yet.
|
// Parse the destination EBB number. Don't translate source to local numbers yet.
|
||||||
let ebb_num = try!(self.match_ebb("expected jump destination EBB"));
|
let ebb_num = self.match_ebb("expected jump destination EBB")?;
|
||||||
let args = try!(self.parse_opt_value_list());
|
let args = self.parse_opt_value_list()?;
|
||||||
InstructionData::Jump {
|
InstructionData::Jump {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1219,10 +1219,10 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::Branch => {
|
InstructionFormat::Branch => {
|
||||||
let ctrl_arg = try!(self.match_value("expected SSA value control operand"));
|
let ctrl_arg = self.match_value("expected SSA value control operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let ebb_num = try!(self.match_ebb("expected branch destination EBB"));
|
let ebb_num = self.match_ebb("expected branch destination EBB")?;
|
||||||
let args = try!(self.parse_opt_value_list());
|
let args = self.parse_opt_value_list()?;
|
||||||
InstructionData::Branch {
|
InstructionData::Branch {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1234,11 +1234,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::InsertLane => {
|
InstructionFormat::InsertLane => {
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let lane = try!(self.match_uimm8("expected lane number"));
|
let lane = self.match_uimm8("expected lane number")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value last operand"));
|
let rhs = self.match_value("expected SSA value last operand")?;
|
||||||
InstructionData::InsertLane {
|
InstructionData::InsertLane {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1247,9 +1247,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::ExtractLane => {
|
InstructionFormat::ExtractLane => {
|
||||||
let arg = try!(self.match_value("expected SSA value last operand"));
|
let arg = self.match_value("expected SSA value last operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let lane = try!(self.match_uimm8("expected lane number"));
|
let lane = self.match_uimm8("expected lane number")?;
|
||||||
InstructionData::ExtractLane {
|
InstructionData::ExtractLane {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1258,11 +1258,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::IntCompare => {
|
InstructionFormat::IntCompare => {
|
||||||
let cond = try!(self.match_enum("expected intcc condition code"));
|
let cond = self.match_enum("expected intcc condition code")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
InstructionData::IntCompare {
|
InstructionData::IntCompare {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1271,11 +1271,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::FloatCompare => {
|
InstructionFormat::FloatCompare => {
|
||||||
let cond = try!(self.match_enum("expected floatcc condition code"));
|
let cond = self.match_enum("expected floatcc condition code")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let rhs = try!(self.match_value("expected SSA value second operand"));
|
let rhs = self.match_value("expected SSA value second operand")?;
|
||||||
InstructionData::FloatCompare {
|
InstructionData::FloatCompare {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1284,11 +1284,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::Call => {
|
InstructionFormat::Call => {
|
||||||
let func_ref = try!(self.match_fn("expected function reference")
|
let func_ref = self.match_fn("expected function reference")
|
||||||
.and_then(|num| ctx.get_fn(num, &self.loc)));
|
.and_then(|num| ctx.get_fn(num, &self.loc))?;
|
||||||
try!(self.match_token(Token::LPar, "expected '(' before arguments"));
|
self.match_token(Token::LPar, "expected '(' before arguments")?;
|
||||||
let args = try!(self.parse_value_list());
|
let args = self.parse_value_list()?;
|
||||||
try!(self.match_token(Token::RPar, "expected ')' after arguments"));
|
self.match_token(Token::RPar, "expected ')' after arguments")?;
|
||||||
InstructionData::Call {
|
InstructionData::Call {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1300,13 +1300,13 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::IndirectCall => {
|
InstructionFormat::IndirectCall => {
|
||||||
let sig_ref = try!(self.match_sig("expected signature reference")
|
let sig_ref = self.match_sig("expected signature reference")
|
||||||
.and_then(|num| ctx.get_sig(num, &self.loc)));
|
.and_then(|num| ctx.get_sig(num, &self.loc))?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let callee = try!(self.match_value("expected SSA value callee operand"));
|
let callee = self.match_value("expected SSA value callee operand")?;
|
||||||
try!(self.match_token(Token::LPar, "expected '(' before arguments"));
|
self.match_token(Token::LPar, "expected '(' before arguments")?;
|
||||||
let args = try!(self.parse_value_list());
|
let args = self.parse_value_list()?;
|
||||||
try!(self.match_token(Token::RPar, "expected ')' after arguments"));
|
self.match_token(Token::RPar, "expected ')' after arguments")?;
|
||||||
InstructionData::IndirectCall {
|
InstructionData::IndirectCall {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1319,7 +1319,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::Return => {
|
InstructionFormat::Return => {
|
||||||
let args = try!(self.parse_value_list());
|
let args = self.parse_value_list()?;
|
||||||
InstructionData::Return {
|
InstructionData::Return {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
@@ -1327,9 +1327,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::ReturnReg => {
|
InstructionFormat::ReturnReg => {
|
||||||
let raddr = try!(self.match_value("expected SSA value return address operand"));
|
let raddr = self.match_value("expected SSA value return address operand")?;
|
||||||
let args = if self.optional(Token::Comma) {
|
let args = if self.optional(Token::Comma) {
|
||||||
try!(self.parse_value_list())
|
self.parse_value_list()?
|
||||||
} else {
|
} else {
|
||||||
VariableArgs::new()
|
VariableArgs::new()
|
||||||
};
|
};
|
||||||
@@ -1343,9 +1343,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::BranchTable => {
|
InstructionFormat::BranchTable => {
|
||||||
let arg = try!(self.match_value("expected SSA value operand"));
|
let arg = self.match_value("expected SSA value operand")?;
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
let table = try!(self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc)));
|
let table = self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))?;
|
||||||
InstructionData::BranchTable {
|
InstructionData::BranchTable {
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
ty: VOID,
|
ty: VOID,
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ impl SourceMap {
|
|||||||
/// Rewrite a slice of value references.
|
/// Rewrite a slice of value references.
|
||||||
pub fn rewrite_values(&self, vals: &mut [Value], loc: AnyEntity) -> Result<()> {
|
pub fn rewrite_values(&self, vals: &mut [Value], loc: AnyEntity) -> Result<()> {
|
||||||
for val in vals {
|
for val in vals {
|
||||||
try!(self.rewrite_value(val, loc));
|
self.rewrite_value(val, loc)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ impl<'a> TestCommand<'a> {
|
|||||||
|
|
||||||
impl<'a> Display for TestCommand<'a> {
|
impl<'a> Display for TestCommand<'a> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
try!(write!(f, "{}", self.command));
|
write!(f, "{}", self.command)?;
|
||||||
for opt in &self.options {
|
for opt in &self.options {
|
||||||
try!(write!(f, " {}", opt));
|
write!(f, " {}", opt)?;
|
||||||
}
|
}
|
||||||
writeln!(f, "")
|
writeln!(f, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ pub fn run(files: Vec<String>) -> CommandResult {
|
|||||||
if i != 0 {
|
if i != 0 {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
try!(cat_one(f))
|
cat_one(f)?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cat_one(filename: String) -> CommandResult {
|
fn cat_one(filename: String) -> CommandResult {
|
||||||
let buffer = try!(read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e)));
|
let buffer = read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
let items = try!(parse_functions(&buffer).map_err(|e| format!("{}: {}", filename, e)));
|
let items = parse_functions(&buffer).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
|
|
||||||
for (idx, func) in items.into_iter().enumerate() {
|
for (idx, func) in items.into_iter().enumerate() {
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl SubTest for TestLegalizer {
|
|||||||
legalize_function(&mut func, isa);
|
legalize_function(&mut func, isa);
|
||||||
|
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
try!(write_function(&mut text, &func, Some(isa)).map_err(|e| e.to_string()));
|
write_function(&mut text, &func, Some(isa)).map_err(|e| e.to_string())?;
|
||||||
run_filecheck(&text, context)
|
run_filecheck(&text, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ impl SubTest for TestRegalloc {
|
|||||||
comp_ctx.regalloc(isa);
|
comp_ctx.regalloc(isa);
|
||||||
|
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
try!(write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string()));
|
write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string())?;
|
||||||
run_filecheck(&text, context)
|
run_filecheck(&text, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ use filetest::subtest::{SubTest, Context, Result};
|
|||||||
/// If running this test causes a panic, it will propagate as normal.
|
/// If running this test causes a panic, it will propagate as normal.
|
||||||
pub fn run(path: &Path) -> TestResult {
|
pub fn run(path: &Path) -> TestResult {
|
||||||
let started = time::Instant::now();
|
let started = time::Instant::now();
|
||||||
let buffer = try!(read_to_string(path).map_err(|e| e.to_string()));
|
let buffer = read_to_string(path).map_err(|e| e.to_string())?;
|
||||||
let testfile = try!(parse_test(&buffer).map_err(|e| e.to_string()));
|
let testfile = parse_test(&buffer).map_err(|e| e.to_string())?;
|
||||||
if testfile.functions.is_empty() {
|
if testfile.functions.is_empty() {
|
||||||
return Err("no functions found".to_string());
|
return Err("no functions found".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the test commands.
|
// Parse the test commands.
|
||||||
let mut tests = try!(testfile.commands.iter().map(new_subtest).collect::<Result<Vec<_>>>());
|
let mut tests = testfile.commands.iter().map(new_subtest).collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
// Flags to use for those tests that don't need an ISA.
|
// Flags to use for those tests that don't need an ISA.
|
||||||
// This is the cumulative effect of all the `set` commands in the file.
|
// This is the cumulative effect of all the `set` commands in the file.
|
||||||
@@ -39,7 +39,7 @@ pub fn run(path: &Path) -> TestResult {
|
|||||||
tests.sort_by_key(|st| (st.is_mutating(), st.needs_verifier()));
|
tests.sort_by_key(|st| (st.is_mutating(), st.needs_verifier()));
|
||||||
|
|
||||||
// Expand the tests into (test, flags, isa) tuples.
|
// Expand the tests into (test, flags, isa) tuples.
|
||||||
let mut tuples = try!(test_tuples(&tests, &testfile.isa_spec, flags));
|
let mut tuples = test_tuples(&tests, &testfile.isa_spec, flags)?;
|
||||||
|
|
||||||
// Isolate the last test in the hope that this is the only mutating test.
|
// Isolate the last test in the hope that this is the only mutating test.
|
||||||
// If so, we can completely avoid cloning functions.
|
// If so, we can completely avoid cloning functions.
|
||||||
@@ -58,11 +58,11 @@ pub fn run(path: &Path) -> TestResult {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for tuple in &tuples {
|
for tuple in &tuples {
|
||||||
try!(run_one_test(*tuple, Cow::Borrowed(&func), &mut context));
|
run_one_test(*tuple, Cow::Borrowed(&func), &mut context)?;
|
||||||
}
|
}
|
||||||
// Run the last test with an owned function which means it won't need to clone it before
|
// Run the last test with an owned function which means it won't need to clone it before
|
||||||
// mutating.
|
// mutating.
|
||||||
try!(run_one_test(last_tuple, Cow::Owned(func), &mut context));
|
run_one_test(last_tuple, Cow::Owned(func), &mut context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ fn run_one_test<'a>(tuple: (&'a SubTest, &'a Flags, Option<&'a TargetIsa>),
|
|||||||
|
|
||||||
// Should we run the verifier before this test?
|
// Should we run the verifier before this test?
|
||||||
if !context.verified && test.needs_verifier() {
|
if !context.verified && test.needs_verifier() {
|
||||||
try!(verify_function(&func).map_err(|e| e.to_string()));
|
verify_function(&func).map_err(|e| e.to_string())?;
|
||||||
context.verified = true;
|
context.verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,13 +72,13 @@ impl<'a> filecheck::VariableMap for Context<'a> {
|
|||||||
|
|
||||||
/// Run filecheck on `text`, using directives extracted from `context`.
|
/// Run filecheck on `text`, using directives extracted from `context`.
|
||||||
pub fn run_filecheck(text: &str, context: &Context) -> Result<()> {
|
pub fn run_filecheck(text: &str, context: &Context) -> Result<()> {
|
||||||
let checker = try!(build_filechecker(context));
|
let checker = build_filechecker(context)?;
|
||||||
if try!(checker.check(&text, context).map_err(|e| format!("filecheck: {}", e))) {
|
if checker.check(&text, context).map_err(|e| format!("filecheck: {}", e))? {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
// Filecheck mismatch. Emit an explanation as output.
|
// Filecheck mismatch. Emit an explanation as output.
|
||||||
let (_, explain) = try!(checker.explain(&text, context)
|
let (_, explain) = checker.explain(&text, context)
|
||||||
.map_err(|e| format!("explain: {}", e)));
|
.map_err(|e| format!("explain: {}", e))?;
|
||||||
Err(format!("filecheck failed:\n{}{}", checker, explain))
|
Err(format!("filecheck failed:\n{}{}", checker, explain))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,10 +88,10 @@ pub fn build_filechecker(context: &Context) -> Result<Checker> {
|
|||||||
let mut builder = CheckerBuilder::new();
|
let mut builder = CheckerBuilder::new();
|
||||||
// Preamble comments apply to all functions.
|
// Preamble comments apply to all functions.
|
||||||
for comment in context.preamble_comments {
|
for comment in context.preamble_comments {
|
||||||
try!(builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e)));
|
builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e))?;
|
||||||
}
|
}
|
||||||
for comment in &context.details.comments {
|
for comment in &context.details.comments {
|
||||||
try!(builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e)));
|
builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e))?;
|
||||||
}
|
}
|
||||||
let checker = builder.finish();
|
let checker = builder.finish();
|
||||||
if checker.is_empty() {
|
if checker.is_empty() {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub fn run(files: Vec<String>) -> CommandResult {
|
|||||||
if i != 0 {
|
if i != 0 {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
try!(print_cfg(f))
|
print_cfg(f)?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -39,37 +39,37 @@ impl<'a> CFGPrinter<'a> {
|
|||||||
|
|
||||||
/// Write the CFG for this function to `w`.
|
/// Write the CFG for this function to `w`.
|
||||||
pub fn write(&self, w: &mut Write) -> Result {
|
pub fn write(&self, w: &mut Write) -> Result {
|
||||||
try!(self.header(w));
|
self.header(w)?;
|
||||||
try!(self.ebb_nodes(w));
|
self.ebb_nodes(w)?;
|
||||||
try!(self.cfg_connections(w));
|
self.cfg_connections(w)?;
|
||||||
writeln!(w, "}}")
|
writeln!(w, "}}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header(&self, w: &mut Write) -> Result {
|
fn header(&self, w: &mut Write) -> Result {
|
||||||
try!(writeln!(w, "digraph {} {{", self.func.name));
|
writeln!(w, "digraph {} {{", self.func.name)?;
|
||||||
if let Some(entry) = self.func.layout.entry_block() {
|
if let Some(entry) = self.func.layout.entry_block() {
|
||||||
try!(writeln!(w, " {{rank=min; {}}}", entry));
|
writeln!(w, " {{rank=min; {}}}", entry)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ebb_nodes(&self, w: &mut Write) -> Result {
|
fn ebb_nodes(&self, w: &mut Write) -> Result {
|
||||||
for ebb in &self.func.layout {
|
for ebb in &self.func.layout {
|
||||||
try!(write!(w, " {} [shape=record, label=\"{{{}", ebb, ebb));
|
write!(w, " {} [shape=record, label=\"{{{}", ebb, ebb)?;
|
||||||
// Add all outgoing branch instructions to the label.
|
// Add all outgoing branch instructions to the label.
|
||||||
for inst in self.func.layout.ebb_insts(ebb) {
|
for inst in self.func.layout.ebb_insts(ebb) {
|
||||||
let idata = &self.func.dfg[inst];
|
let idata = &self.func.dfg[inst];
|
||||||
match idata.analyze_branch() {
|
match idata.analyze_branch() {
|
||||||
BranchInfo::SingleDest(dest, _) => {
|
BranchInfo::SingleDest(dest, _) => {
|
||||||
try!(write!(w, " | <{}>{} {}", inst, idata.opcode(), dest))
|
write!(w, " | <{}>{} {}", inst, idata.opcode(), dest)?
|
||||||
}
|
}
|
||||||
BranchInfo::Table(table) => {
|
BranchInfo::Table(table) => {
|
||||||
try!(write!(w, " | <{}>{} {}", inst, idata.opcode(), table))
|
write!(w, " | <{}>{} {}", inst, idata.opcode(), table)?
|
||||||
}
|
}
|
||||||
BranchInfo::NotABranch => {}
|
BranchInfo::NotABranch => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try!(writeln!(w, "}}\"]"))
|
writeln!(w, "}}\"]")?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ impl<'a> CFGPrinter<'a> {
|
|||||||
fn cfg_connections(&self, w: &mut Write) -> Result {
|
fn cfg_connections(&self, w: &mut Write) -> Result {
|
||||||
for ebb in &self.func.layout {
|
for ebb in &self.func.layout {
|
||||||
for &(parent, inst) in self.cfg.get_predecessors(ebb) {
|
for &(parent, inst) in self.cfg.get_predecessors(ebb) {
|
||||||
try!(writeln!(w, " {}:{} -> {}", parent, inst, ebb));
|
writeln!(w, " {}:{} -> {}", parent, inst, ebb)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -91,8 +91,8 @@ impl<'a> Display for CFGPrinter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_cfg(filename: String) -> CommandResult {
|
fn print_cfg(filename: String) -> CommandResult {
|
||||||
let buffer = try!(read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e)));
|
let buffer = read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
let items = try!(parse_functions(&buffer).map_err(|e| format!("{}: {}", filename, e)));
|
let items = parse_functions(&buffer).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
|
|
||||||
for (idx, func) in items.into_iter().enumerate() {
|
for (idx, func) in items.into_iter().enumerate() {
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
|
|||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
return Err("No check files".to_string());
|
return Err("No check files".to_string());
|
||||||
}
|
}
|
||||||
let checker = try!(read_checkfile(&files[0]));
|
let checker = read_checkfile(&files[0])?;
|
||||||
if checker.is_empty() {
|
if checker.is_empty() {
|
||||||
return Err(format!("{}: no filecheck directives found", files[0]));
|
return Err(format!("{}: no filecheck directives found", files[0]));
|
||||||
}
|
}
|
||||||
@@ -18,11 +18,11 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
try!(io::stdin().read_to_string(&mut buffer).map_err(|e| format!("stdin: {}", e)));
|
io::stdin().read_to_string(&mut buffer).map_err(|e| format!("stdin: {}", e))?;
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
let (success, explain) = try!(checker.explain(&buffer, NO_VARIABLES)
|
let (success, explain) = checker.explain(&buffer, NO_VARIABLES)
|
||||||
.map_err(|e| e.to_string()));
|
.map_err(|e| e.to_string())?;
|
||||||
print!("{}", explain);
|
print!("{}", explain);
|
||||||
if success {
|
if success {
|
||||||
println!("OK");
|
println!("OK");
|
||||||
@@ -30,18 +30,18 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
|
|||||||
} else {
|
} else {
|
||||||
Err("Check failed".to_string())
|
Err("Check failed".to_string())
|
||||||
}
|
}
|
||||||
} else if try!(checker.check(&buffer, NO_VARIABLES).map_err(|e| e.to_string())) {
|
} else if checker.check(&buffer, NO_VARIABLES).map_err(|e| e.to_string())? {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let (_, explain) = try!(checker.explain(&buffer, NO_VARIABLES).map_err(|e| e.to_string()));
|
let (_, explain) = checker.explain(&buffer, NO_VARIABLES).map_err(|e| e.to_string())?;
|
||||||
print!("{}", explain);
|
print!("{}", explain);
|
||||||
Err("Check failed".to_string())
|
Err("Check failed".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_checkfile(filename: &str) -> Result<Checker, String> {
|
fn read_checkfile(filename: &str) -> Result<Checker, String> {
|
||||||
let buffer = try!(read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e)));
|
let buffer = read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
let mut builder = CheckerBuilder::new();
|
let mut builder = CheckerBuilder::new();
|
||||||
try!(builder.text(&buffer).map_err(|e| format!("{}: {}", filename, e)));
|
builder.text(&buffer).map_err(|e| format!("{}: {}", filename, e))?;
|
||||||
Ok(builder.finish())
|
Ok(builder.finish())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ use std::io::{Result, Read};
|
|||||||
|
|
||||||
/// Read an entire file into a string.
|
/// Read an entire file into a string.
|
||||||
pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
|
pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||||
let mut file = try!(File::open(path));
|
let mut file = File::open(path)?;
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
try!(file.read_to_string(&mut buffer));
|
file.read_to_string(&mut buffer)?;
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user