Added tests, some refactoring, fixed a parsing bug.
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
a58ccb1125
commit
4525929df2
25
cranelift/filetests/parser/instruction_encoding.cton
Normal file
25
cranelift/filetests/parser/instruction_encoding.cton
Normal 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: }
|
||||
@@ -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>
|
||||
|
||||
@@ -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,8 +583,9 @@ 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>)
|
||||
-> Result<Vec<(Function, Details<'a>)>> {
|
||||
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() {
|
||||
list.push(self.parse_function(unique_isa)?);
|
||||
@@ -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,8 +959,9 @@ impl<'a> Parser<'a> {
|
||||
ctx.map.def_value(vx, value, &vx_location)
|
||||
}
|
||||
|
||||
fn parse_instruction_encoding(&mut self, ctx: &Context)
|
||||
-> Result<(Option<Encoding>, Option<Vec<&'a str>>)> {
|
||||
fn parse_instruction_encoding(&mut self,
|
||||
ctx: &Context)
|
||||
-> Result<(Option<Encoding>, Option<Vec<&'a str>>)> {
|
||||
let (mut encoding, mut result_registers) = (None, None);
|
||||
|
||||
// encoding ::= "[" encoding_literal result_registers "]"
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user