Add arguments() and arguments_mut() methods.
Provide a generic way of accessing the value arguments on an instruction. This is provided as two slice references. One for the fixed arguments and one for any VariableArgs. The arguments() methods return an array of two slices which is a bit awkward. Also provide an each_arg() method which passes each argument value to a closure.
This commit is contained in:
@@ -9,6 +9,7 @@ import cretonne
|
||||
|
||||
|
||||
def gen_formats(fmt):
|
||||
# type: (srcgen.Formatter) -> None
|
||||
"""Generate an instruction format enumeration"""
|
||||
|
||||
fmt.doc_comment('An instruction format')
|
||||
@@ -38,7 +39,63 @@ def gen_formats(fmt):
|
||||
fmt.line()
|
||||
|
||||
|
||||
def gen_arguments_method(fmt, is_mut):
|
||||
# type: (srcgen.Formatter, bool) -> None
|
||||
method = 'arguments'
|
||||
mut = ''
|
||||
rslice = 'ref_slice'
|
||||
if is_mut:
|
||||
method += '_mut'
|
||||
mut = 'mut '
|
||||
rslice += '_mut'
|
||||
|
||||
with fmt.indented(
|
||||
'pub fn {f}(&{m}self) -> [&{m}[Value]; 2] {{'
|
||||
.format(f=method, m=mut), '}'):
|
||||
with fmt.indented('match *self {', '}'):
|
||||
for f in cretonne.InstructionFormat.all_formats:
|
||||
n = 'InstructionData::' + f.name
|
||||
has_varargs = cretonne.variable_args in f.kinds
|
||||
# Formats with both fixed and variable arguments delegate to
|
||||
# the data struct. We need to work around borrow checker quirks
|
||||
# when extracting two mutable references.
|
||||
if has_varargs and len(f.value_operands) > 0:
|
||||
fmt.line(
|
||||
'{} {{ ref {}data, .. }} => data.{}(),'
|
||||
.format(n, mut, method))
|
||||
continue
|
||||
# Fixed args.
|
||||
if len(f.value_operands) == 0:
|
||||
arg = '&{}[]'.format(mut)
|
||||
capture = ''
|
||||
elif len(f.value_operands) == 1:
|
||||
if f.boxed_storage:
|
||||
capture = 'ref {}data, '.format(mut)
|
||||
arg = '{}(&{}data.arg)'.format(rslice, mut)
|
||||
else:
|
||||
capture = 'ref {}arg, '.format(mut)
|
||||
arg = '{}(arg)'.format(rslice)
|
||||
else:
|
||||
if f.boxed_storage:
|
||||
capture = 'ref {}data, '.format(mut)
|
||||
arg = '&{}data.args'.format(mut)
|
||||
else:
|
||||
capture = 'ref {}args, '.format(mut)
|
||||
arg = 'args'
|
||||
# Varargs.
|
||||
if cretonne.variable_args in f.kinds:
|
||||
varg = '&{}data.varargs'.format(mut)
|
||||
capture = 'ref {}data, '.format(mut)
|
||||
else:
|
||||
varg = '&{}[]'.format(mut)
|
||||
|
||||
fmt.line(
|
||||
'{} {{ {} .. }} => [{}, {}],'
|
||||
.format(n, capture, arg, varg))
|
||||
|
||||
|
||||
def gen_instruction_data_impl(fmt):
|
||||
# type: (srcgen.Formatter) -> None
|
||||
"""
|
||||
Generate the boring parts of the InstructionData implementation.
|
||||
|
||||
@@ -49,6 +106,7 @@ def gen_instruction_data_impl(fmt):
|
||||
- `pub fn first_type(&self) -> Type`
|
||||
- `pub fn second_result(&self) -> Option<Value>`
|
||||
- `pub fn second_result_mut<'a>(&'a mut self) -> Option<&'a mut Value>`
|
||||
- `pub fn arguments(&self) -> (&[Value], &[Value])`
|
||||
"""
|
||||
|
||||
# The `opcode` and `first_type` methods simply read the `opcode` and `ty`
|
||||
@@ -148,6 +206,22 @@ def gen_instruction_data_impl(fmt):
|
||||
' {{ ref args, .. }} => Some(args[{}]),'
|
||||
.format(i))
|
||||
|
||||
fmt.doc_comment(
|
||||
"""
|
||||
Get the value arguments to this instruction.
|
||||
|
||||
This is returned as two `Value` slices. The first one
|
||||
represents the fixed arguments, the second any variable
|
||||
arguments.
|
||||
""")
|
||||
gen_arguments_method(fmt, False)
|
||||
fmt.doc_comment(
|
||||
"""
|
||||
Get mutable references to the value arguments to this
|
||||
instruction.
|
||||
""")
|
||||
gen_arguments_method(fmt, True)
|
||||
|
||||
|
||||
def collect_instr_groups(isas):
|
||||
seen = set()
|
||||
|
||||
@@ -15,6 +15,8 @@ use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
||||
use ir::condcodes::*;
|
||||
use ir::types;
|
||||
|
||||
use ref_slice::*;
|
||||
|
||||
// Include code generated by `lib/cretonne/meta/gen_instr.py`. This file contains:
|
||||
//
|
||||
// - The `pub enum InstructionFormat` enum with all the instruction formats.
|
||||
@@ -339,6 +341,18 @@ pub struct BranchData {
|
||||
pub varargs: VariableArgs,
|
||||
}
|
||||
|
||||
impl BranchData {
|
||||
/// Get references to the arguments.
|
||||
pub fn arguments(&self) -> [&[Value]; 2] {
|
||||
[ref_slice(&self.arg), &self.varargs]
|
||||
}
|
||||
|
||||
/// Get mutable references to the arguments.
|
||||
pub fn arguments_mut(&mut self) -> [&mut [Value]; 2] {
|
||||
[ref_slice_mut(&mut self.arg), &mut self.varargs]
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BranchData {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
try!(write!(f, "{}, {}", self.arg, self.destination));
|
||||
@@ -372,6 +386,18 @@ pub struct IndirectCallData {
|
||||
pub varargs: VariableArgs,
|
||||
}
|
||||
|
||||
impl IndirectCallData {
|
||||
/// Get references to the arguments.
|
||||
pub fn arguments(&self) -> [&[Value]; 2] {
|
||||
[ref_slice(&self.arg), &self.varargs]
|
||||
}
|
||||
|
||||
/// Get mutable references to the arguments.
|
||||
pub fn arguments_mut(&mut self) -> [&mut [Value]; 2] {
|
||||
[ref_slice_mut(&mut self.arg), &mut self.varargs]
|
||||
}
|
||||
}
|
||||
|
||||
/// Payload of a return instruction.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReturnData {
|
||||
@@ -381,9 +407,33 @@ pub struct ReturnData {
|
||||
|
||||
/// Analyzing an instruction.
|
||||
///
|
||||
/// Avoid large matches on instruction formats by using the methods efined here to examine
|
||||
/// Avoid large matches on instruction formats by using the methods defined here to examine
|
||||
/// instructions.
|
||||
impl InstructionData {
|
||||
/// Execute a closure once for each argument to this instruction.
|
||||
/// See also the `arguments()` method.
|
||||
pub fn each_arg<F>(&self, func: F)
|
||||
where F: Fn(Value)
|
||||
{
|
||||
for part in &self.arguments() {
|
||||
for &arg in part.iter() {
|
||||
func(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute a closure with a mutable reference to each argument to this instruction.
|
||||
/// See also the `arguments_mut()` method.
|
||||
pub fn each_arg_mut<F>(&mut self, func: F)
|
||||
where F: Fn(&mut Value)
|
||||
{
|
||||
for part in &mut self.arguments_mut() {
|
||||
for arg in part.iter_mut() {
|
||||
func(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return information about the destination of a branch or jump instruction.
|
||||
///
|
||||
/// Any instruction that can transfer control to another EBB reveals its possible destinations
|
||||
|
||||
Reference in New Issue
Block a user