From d92778a19e117f21ce95db0947188e027be1bb84 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 18 Apr 2019 18:27:33 +0200 Subject: [PATCH] [meta] Add Instruction helpers and change its representation to make it easily copiable; - adds helpers used by other parts of the code - allows cheap copies by having Instruction be a lightweight ref-cloned wrapper of the actual instruction's content. --- cranelift/codegen/meta/src/cdsl/inst.rs | 93 +++++++++++++++------ cranelift/codegen/meta/src/cdsl/operands.rs | 2 +- 2 files changed, 69 insertions(+), 26 deletions(-) diff --git a/cranelift/codegen/meta/src/cdsl/inst.rs b/cranelift/codegen/meta/src/cdsl/inst.rs index 4199d6424d..c3aeed9ac0 100644 --- a/cranelift/codegen/meta/src/cdsl/inst.rs +++ b/cranelift/codegen/meta/src/cdsl/inst.rs @@ -1,10 +1,15 @@ use crate::cdsl::camel_case; -use crate::cdsl::formats::{FormatRegistry, InstructionFormat, InstructionFormatIndex}; +use crate::cdsl::formats::{ + FormatField, FormatRegistry, InstructionFormat, InstructionFormatIndex, +}; use crate::cdsl::operands::Operand; use crate::cdsl::type_inference::Constraint; +use crate::cdsl::types::ValueType; use crate::cdsl::typevar::TypeVar; use std::fmt; +use std::ops; +use std::rc::Rc; use std::slice; /// Every instruction must belong to exactly one instruction group. A given @@ -32,6 +37,13 @@ impl InstructionGroup { pub fn iter(&self) -> slice::Iter { self.instructions.iter() } + + pub fn by_name(&self, name: &'static str) -> &Instruction { + self.instructions + .iter() + .find(|inst| inst.name == name) + .expect(&format!("unexisting instruction with name {}", name)) + } } pub struct PolymorphicInfo { @@ -40,7 +52,7 @@ pub struct PolymorphicInfo { pub other_typevars: Vec, } -pub struct Instruction { +pub struct InstructionContent { /// Instruction mnemonic, also becomes opcode name. pub name: &'static str, pub camel_name: String, @@ -53,7 +65,7 @@ pub struct Instruction { /// Output operands. The output operands must be SSA values or `variable_args`. pub operands_out: Vec, /// Instruction-specific TypeConstraints. - _constraints: Vec, + pub constraints: Vec, /// Instruction format, automatically derived from the input operands. pub format: InstructionFormatIndex, @@ -90,6 +102,18 @@ pub struct Instruction { pub writes_cpu_flags: bool, } +#[derive(Clone)] +pub struct Instruction { + content: Rc, +} + +impl ops::Deref for Instruction { + type Target = InstructionContent; + fn deref(&self) -> &Self::Target { + &*self.content + } +} + impl Instruction { pub fn snake_name(&self) -> &'static str { if self.name == "return" { @@ -108,6 +132,17 @@ impl Instruction { } "" } + + pub fn all_typevars(&self) -> Vec<&TypeVar> { + match &self.polymorphic_info { + Some(poly) => { + let mut result = vec![&poly.ctrl_typevar]; + result.extend(&poly.other_typevars); + result + } + None => Vec::new(), + } + } } impl fmt::Display for Instruction { @@ -272,32 +307,40 @@ impl InstructionBuilder { let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags()); Instruction { - name: self.name, - camel_name: camel_case(self.name), - doc: self.doc, - operands_in, - operands_out, - _constraints: self.constraints.unwrap_or_else(Vec::new), - format: format_index, - polymorphic_info, - value_opnums, - value_results, - imm_opnums, - is_terminator: self.is_terminator, - is_branch: self.is_branch, - is_indirect_branch: self.is_indirect_branch, - is_call: self.is_call, - is_return: self.is_return, - is_ghost: self.is_ghost, - can_load: self.can_load, - can_store: self.can_store, - can_trap: self.can_trap, - other_side_effects: self.other_side_effects, - writes_cpu_flags, + content: Rc::new(InstructionContent { + name: self.name, + camel_name: camel_case(self.name), + doc: self.doc, + operands_in, + operands_out, + constraints: self.constraints.unwrap_or_else(Vec::new), + format: format_index, + polymorphic_info, + value_opnums, + value_results, + imm_opnums, + is_terminator: self.is_terminator, + is_branch: self.is_branch, + is_indirect_branch: self.is_indirect_branch, + is_call: self.is_call, + is_return: self.is_return, + is_ghost: self.is_ghost, + can_load: self.can_load, + can_store: self.can_store, + can_trap: self.can_trap, + other_side_effects: self.other_side_effects, + writes_cpu_flags, + }), } } } +#[derive(Clone)] +pub struct BoundInstruction { + pub inst: Instruction, + pub value_types: Vec, +} + /// Check if this instruction is polymorphic, and verify its use of type variables. fn verify_polymorphic( operands_in: &Vec, diff --git a/cranelift/codegen/meta/src/cdsl/operands.rs b/cranelift/codegen/meta/src/cdsl/operands.rs index f460225bfe..93a92823be 100644 --- a/cranelift/codegen/meta/src/cdsl/operands.rs +++ b/cranelift/codegen/meta/src/cdsl/operands.rs @@ -134,7 +134,7 @@ pub struct OperandKind { /// The camel-cased name of an operand kind is also the Rust type used to represent it. pub rust_type: String, - fields: OperandKindFields, + pub fields: OperandKindFields, } impl OperandKind {