Added tests, some refactoring, fixed a parsing bug.

This commit is contained in:
Angus Holder
2017-03-03 21:30:33 +00:00
committed by Jakob Stoklund Olesen
parent a58ccb1125
commit 4525929df2
3 changed files with 58 additions and 20 deletions

View File

@@ -0,0 +1,25 @@
test cat
isa riscv
; regex: WS=[ \t]*
function foo(i32, i32) {
ebb1(v0: i32, v1: i32):
[-,-] v2 = iadd v0, v1
[-] trap
[R#1234, %x5, %x11] v6, v7 = iadd_cout v2, v0
[Rshamt#beef, %x25] v8 = ishl_imm v6, 2
v9 = iadd v8, v7
[Iret#5] return v0, v8
}
; sameln: function foo(i32, i32) {
; nextln: $ebb1($v0: i32, $v1: i32):
; nextln: [-]$WS $v2 = iadd $v0, $v1
; nextln: [-]$WS trap
; nextln: [0#1234]$WS $v6, $v7 = iadd_cout $v2, $v0
; TODO Add the full encoding information available: instruction recipe name and architectural registers if specified
; nextln: [2#beef]$WS $v8 = ishl_imm $v6, 2
; nextln: [-]$WS $v9 = iadd $v8, $v7
; nextln: [3#05]$WS return $v0, $v8
; nextln: }

View File

@@ -22,6 +22,18 @@ pub enum IsaSpec {
Some(Vec<Box<TargetIsa>>),
}
impl IsaSpec {
/// If the `IsaSpec` contains exactly 1 `TargetIsa` we return a reference to it
pub fn unique_isa(&self) -> Option<&TargetIsa> {
if let &IsaSpec::Some(ref isa_vec) = self {
if isa_vec.len() == 1 {
return Some(&*isa_vec[0]);
}
}
None
}
}
/// 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<()>
where I: Iterator<Item = &'a str>

View File

@@ -44,16 +44,7 @@ pub fn parse_test<'a>(text: &'a str) -> Result<TestFile<'a>> {
let commands = parser.parse_test_commands();
let isa_spec = parser.parse_isa_specs()?;
let preamble_comments = parser.take_comments();
let functions = {
let mut unique_isa = None;
if let isaspec::IsaSpec::Some(ref isa_vec) = isa_spec {
if isa_vec.len() == 1 {
unique_isa = Some(&*isa_vec[0]);
}
}
parser.parse_function_list(unique_isa)?
};
let functions = parser.parse_function_list(isa_spec.unique_isa())?;
Ok(TestFile {
commands: commands,
@@ -102,7 +93,7 @@ impl<'a> Context<'a> {
Context {
function: f,
map: SourceMap::new(),
unique_isa: unique_isa
unique_isa: unique_isa,
}
}
@@ -592,7 +583,8 @@ impl<'a> Parser<'a> {
/// Parse a list of function definitions.
///
/// This is the top-level parse function matching the whole contents of a file.
pub fn parse_function_list(&mut self, unique_isa: Option<&TargetIsa>)
pub fn parse_function_list(&mut self,
unique_isa: Option<&TargetIsa>)
-> Result<Vec<(Function, Details<'a>)>> {
let mut list = Vec::new();
while self.token().is_some() {
@@ -605,7 +597,9 @@ impl<'a> Parser<'a> {
//
// function ::= * function-spec "{" preamble function-body "}"
//
fn parse_function(&mut self, unique_isa: Option<&TargetIsa>) -> Result<(Function, Details<'a>)> {
fn parse_function(&mut self,
unique_isa: Option<&TargetIsa>)
-> Result<(Function, Details<'a>)> {
// Begin gathering comments.
// Make sure we don't include any comments before the `function` keyword.
self.token();
@@ -916,6 +910,7 @@ impl<'a> Parser<'a> {
while match self.token() {
Some(Token::Value(_)) => true,
Some(Token::Identifier(_)) => true,
Some(Token::LBracket) => true,
_ => false,
} {
self.parse_instruction(ctx, ebb)?;
@@ -964,7 +959,8 @@ impl<'a> Parser<'a> {
ctx.map.def_value(vx, value, &vx_location)
}
fn parse_instruction_encoding(&mut self, ctx: &Context)
fn parse_instruction_encoding(&mut self,
ctx: &Context)
-> Result<(Option<Encoding>, Option<Vec<&'a str>>)> {
let (mut encoding, mut result_registers) = (None, None);
@@ -977,6 +973,11 @@ impl<'a> Parser<'a> {
if let Some(recipe_index) = ctx.find_recipe_index(recipe) {
encoding = Some(Encoding::new(recipe_index, bits));
} else if ctx.unique_isa.is_some() {
return err!(self.loc, "invalid instruction recipe");
} else {
return err!(self.loc,
"provided instruction encoding for unspecified ISA");
}
}
@@ -1525,7 +1526,7 @@ mod tests {
ss3 = stack_slot 13
ss1 = stack_slot 1
}")
.parse_function()
.parse_function(None)
.unwrap();
assert_eq!(func.name.to_string(), "foo");
let mut iter = func.stack_slots.keys();
@@ -1542,7 +1543,7 @@ mod tests {
ss1 = stack_slot 13
ss1 = stack_slot 1
}")
.parse_function()
.parse_function(None)
.unwrap_err()
.to_string(),
"3: duplicate stack slot: ss1");
@@ -1554,7 +1555,7 @@ mod tests {
ebb0:
ebb4(vx3: i32):
}")
.parse_function()
.parse_function(None)
.unwrap();
assert_eq!(func.name.to_string(), "ebbs");
@@ -1583,7 +1584,7 @@ mod tests {
trap ; Instruction
} ; Trailing.
; More trailing.")
.parse_function()
.parse_function(None)
.unwrap();
assert_eq!(func.name.to_string(), "comment");
assert_eq!(comments.len(), 8); // no 'before' comment.