|
@ -29,12 +29,7 @@ use sourcemap::{SourceMap, MutableSourceMap}; |
|
|
///
|
|
|
///
|
|
|
/// Any test commands or ISA declarations are ignored.
|
|
|
/// Any test commands or ISA declarations are ignored.
|
|
|
pub fn parse_functions(text: &str) -> Result<Vec<Function>> { |
|
|
pub fn parse_functions(text: &str) -> Result<Vec<Function>> { |
|
|
parse_test(text).map(|file| { |
|
|
parse_test(text).map(|file| file.functions.into_iter().map(|(func, _)| func).collect()) |
|
|
file.functions |
|
|
|
|
|
.into_iter() |
|
|
|
|
|
.map(|(func, _)| func) |
|
|
|
|
|
.collect() |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// Parse the entire `text` as a test case file.
|
|
|
/// Parse the entire `text` as a test case file.
|
|
@ -753,9 +748,7 @@ impl<'a> Parser<'a> { |
|
|
sig.return_types = self.parse_argument_list(unique_isa)?; |
|
|
sig.return_types = self.parse_argument_list(unique_isa)?; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if sig.argument_types |
|
|
if sig.argument_types.iter().all(|a| a.location.is_assigned()) { |
|
|
.iter() |
|
|
|
|
|
.all(|a| a.location.is_assigned()) { |
|
|
|
|
|
sig.compute_argument_bytes(); |
|
|
sig.compute_argument_bytes(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1319,48 +1312,50 @@ impl<'a> Parser<'a> { |
|
|
inst_data: &InstructionData) |
|
|
inst_data: &InstructionData) |
|
|
-> Result<Type> { |
|
|
-> Result<Type> { |
|
|
let constraints = opcode.constraints(); |
|
|
let constraints = opcode.constraints(); |
|
|
let ctrl_type = |
|
|
let ctrl_type = match explicit_ctrl_type { |
|
|
match explicit_ctrl_type { |
|
|
Some(t) => t, |
|
|
Some(t) => t, |
|
|
None => { |
|
|
None => { |
|
|
if constraints.use_typevar_operand() { |
|
|
if constraints.use_typevar_operand() { |
|
|
// This is an opcode that supports type inference, AND there was no
|
|
|
// This is an opcode that supports type inference, AND there was no
|
|
|
// explicit type specified. Look up `ctrl_value` to see if it was defined
|
|
|
// explicit type specified. Look up `ctrl_value` to see if it was defined
|
|
|
// already.
|
|
|
// already.
|
|
|
// TBD: If it is defined in another block, the type should have been
|
|
|
// TBD: If it is defined in another block, the type should have been
|
|
|
// specified explicitly. It is unfortunate that the correctness of IL
|
|
|
// specified explicitly. It is unfortunate that the correctness of IL
|
|
|
// depends on the layout of the blocks.
|
|
|
// depends on the layout of the blocks.
|
|
|
let ctrl_src_value = inst_data |
|
|
let ctrl_src_value = inst_data |
|
|
.typevar_operand(&ctx.function.dfg.value_lists) |
|
|
.typevar_operand(&ctx.function.dfg.value_lists) |
|
|
.expect("Constraints <-> Format inconsistency"); |
|
|
.expect("Constraints <-> Format inconsistency"); |
|
|
ctx.function |
|
|
ctx.function.dfg.value_type(match ctx.map.get_value(ctrl_src_value) { |
|
|
.dfg |
|
|
Some(v) => v, |
|
|
.value_type(match ctx.map.get_value(ctrl_src_value) { |
|
|
None => { |
|
|
Some(v) => v, |
|
|
if let Some(v) = ctx.aliases |
|
|
None => { |
|
|
.get(&ctrl_src_value) |
|
|
if let Some(v) = ctx.aliases |
|
|
.and_then(|&(aliased, _)| ctx.map.get_value(aliased)) |
|
|
.get(&ctrl_src_value) |
|
|
{ |
|
|
.and_then(|&(aliased, _)| { |
|
|
v |
|
|
ctx.map.get_value(aliased) |
|
|
} else { |
|
|
}) { |
|
|
return err!(self.loc, |
|
|
v |
|
|
"cannot determine type of operand {}", |
|
|
} else { |
|
|
ctrl_src_value); |
|
|
return err!(self.loc, |
|
|
} |
|
|
"cannot determine type of operand {}", |
|
|
} |
|
|
ctrl_src_value); |
|
|
}) |
|
|
} |
|
|
} else if constraints.is_polymorphic() { |
|
|
} |
|
|
// This opcode does not support type inference, so the explicit type
|
|
|
}) |
|
|
// variable is required.
|
|
|
} else if constraints.is_polymorphic() { |
|
|
return err!(self.loc, |
|
|
// This opcode does not support type inference, so the explicit type
|
|
|
"type variable required for polymorphic opcode, e.g. '{}.{}'", |
|
|
// variable is required.
|
|
|
opcode, |
|
|
return err!(self.loc, |
|
|
constraints.ctrl_typeset().unwrap().example()); |
|
|
"type variable required for polymorphic opcode, e.g. '{}.{}'", |
|
|
} else { |
|
|
opcode, |
|
|
// This is a non-polymorphic opcode. No typevar needed.
|
|
|
constraints.ctrl_typeset().unwrap().example()); |
|
|
VOID |
|
|
} else { |
|
|
} |
|
|
// This is a non-polymorphic opcode. No typevar needed.
|
|
|
|
|
|
VOID |
|
|
} |
|
|
} |
|
|
}; |
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// Verify that `ctrl_type` is valid for the controlling type variable. We don't want to
|
|
|
// Verify that `ctrl_type` is valid for the controlling type variable. We don't want to
|
|
|
// attempt deriving types from an incorrect basis.
|
|
|
// attempt deriving types from an incorrect basis.
|
|
@ -1616,8 +1611,7 @@ impl<'a> Parser<'a> { |
|
|
InstructionFormat::BranchTable => { |
|
|
InstructionFormat::BranchTable => { |
|
|
let arg = self.match_value("expected SSA value operand")?; |
|
|
let arg = self.match_value("expected SSA value operand")?; |
|
|
self.match_token(Token::Comma, "expected ',' between operands")?; |
|
|
self.match_token(Token::Comma, "expected ',' between operands")?; |
|
|
let table = self.match_jt() |
|
|
let table = self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))?; |
|
|
.and_then(|num| ctx.get_jt(num, &self.loc))?; |
|
|
|
|
|
InstructionData::BranchTable { opcode, arg, table } |
|
|
InstructionData::BranchTable { opcode, arg, table } |
|
|
} |
|
|
} |
|
|
InstructionFormat::StackLoad => { |
|
|
InstructionFormat::StackLoad => { |
|
|