Parse controlling type variable. Do basic type inference.
Replace the make_multi_inst() function with a make_inst_results() which uses the constraint system to create the result values. A typevar argument ensures that this function does not infer anything from the instruction data arguments. These arguments may not be valid during parsing. Implement basic type inference in the parser. If the designated value operand on a polymorphic instruction refers to a known value, use that to infer the controlling type variable. This simple method of type inference requires the operand value to be defined above the use in the text. Since reordering the EBBs could place a dominating EBB below the current one, this is a bit fragile. One possibility would be to require the value is defined in the same EBB. In all other cases, the controlling typevar should be explicit.
This commit is contained in:
@@ -70,6 +70,14 @@ def gen_instruction_data_impl(fmt):
|
||||
'InstructionData::{} {{ ty, .. }} => ty,'
|
||||
.format(f.name))
|
||||
|
||||
fmt.doc_comment('Mutable reference to the type of the first result.')
|
||||
with fmt.indented('pub fn first_type_mut(&mut self) -> &mut Type {', '}'):
|
||||
with fmt.indented('match *self {', '}'):
|
||||
for f in cretonne.InstructionFormat.all_formats:
|
||||
fmt.line(
|
||||
'InstructionData::{} {{ ref mut ty, .. }} => ty,'
|
||||
.format(f.name))
|
||||
|
||||
# Generate shared and mutable accessors for `second_result` which only
|
||||
# applies to instruction formats that can produce multiple results.
|
||||
# Everything else returns `None`.
|
||||
@@ -120,6 +128,38 @@ def gen_instruction_data_impl(fmt):
|
||||
' { ref mut second_result, .. }' +
|
||||
' => Some(second_result),')
|
||||
|
||||
fmt.doc_comment('Get the controlling type variable operand.')
|
||||
with fmt.indented(
|
||||
'pub fn typevar_operand(&self) -> Option<Value> {', '}'):
|
||||
with fmt.indented('match *self {', '}'):
|
||||
for f in cretonne.InstructionFormat.all_formats:
|
||||
n = 'InstructionData::' + f.name
|
||||
if f.typevar_operand is None:
|
||||
fmt.line(n + ' { .. } => None,')
|
||||
elif len(f.value_operands) == 1:
|
||||
# We have a single value operand called 'arg'.
|
||||
if f.boxed_storage:
|
||||
fmt.line(
|
||||
n + ' { ref data, .. } => Some(data.arg),')
|
||||
else:
|
||||
fmt.line(n + ' { arg, .. } => Some(arg),')
|
||||
else:
|
||||
# We have multiple value operands and an array `args`.
|
||||
# Which `args` index to use?
|
||||
# Map from index into f.kinds into f.value_operands
|
||||
# index.
|
||||
i = f.value_operands.index(f.typevar_operand)
|
||||
if f.boxed_storage:
|
||||
fmt.line(
|
||||
n +
|
||||
' {{ ref data, .. }} => Some(data.args[{}]),'
|
||||
.format(i))
|
||||
else:
|
||||
fmt.line(
|
||||
n +
|
||||
' {{ ref args, .. }} => Some(args[{}]),'
|
||||
.format(i))
|
||||
|
||||
|
||||
def collect_instr_groups(targets):
|
||||
seen = set()
|
||||
|
||||
Reference in New Issue
Block a user