[meta] Uniquely number every instruction in the Rust crate;

This commit is contained in:
Benjamin Bouvier
2019-06-06 16:33:18 +02:00
parent 102dbbb343
commit f1d1d1e960
13 changed files with 127 additions and 90 deletions

View File

@@ -1,3 +1,10 @@
use std::fmt;
use std::ops;
use std::rc::Rc;
use std::slice;
use cranelift_entity::{entity_impl, PrimaryMap};
use crate::cdsl::camel_case; use crate::cdsl::camel_case;
use crate::cdsl::formats::{ use crate::cdsl::formats::{
FormatField, FormatRegistry, InstructionFormat, InstructionFormatIndex, FormatField, FormatRegistry, InstructionFormat, InstructionFormatIndex,
@@ -7,41 +14,49 @@ use crate::cdsl::type_inference::Constraint;
use crate::cdsl::types::{LaneType, ValueType}; use crate::cdsl::types::{LaneType, ValueType};
use crate::cdsl::typevar::TypeVar; use crate::cdsl::typevar::TypeVar;
use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
use std::ops; pub struct OpcodeNumber(u32);
use std::rc::Rc; entity_impl!(OpcodeNumber);
use std::slice;
pub struct InstructionGroupBuilder<'format_reg> { pub type AllInstructions = PrimaryMap<OpcodeNumber, Instruction>;
pub struct InstructionGroupBuilder<'format_reg, 'all_inst> {
_name: &'static str, _name: &'static str,
_doc: &'static str, _doc: &'static str,
format_registry: &'format_reg FormatRegistry, format_registry: &'format_reg FormatRegistry,
instructions: Vec<Instruction>, all_instructions: &'all_inst mut AllInstructions,
own_instructions: Vec<Instruction>,
} }
impl<'format_reg> InstructionGroupBuilder<'format_reg> { impl<'format_reg, 'all_inst> InstructionGroupBuilder<'format_reg, 'all_inst> {
pub fn new( pub fn new(
name: &'static str, name: &'static str,
doc: &'static str, doc: &'static str,
all_instructions: &'all_inst mut AllInstructions,
format_registry: &'format_reg FormatRegistry, format_registry: &'format_reg FormatRegistry,
) -> Self { ) -> Self {
Self { Self {
_name: name, _name: name,
_doc: doc, _doc: doc,
format_registry, format_registry,
instructions: Vec::new(), all_instructions,
own_instructions: Vec::new(),
} }
} }
pub fn push(&mut self, builder: InstructionBuilder) { pub fn push(&mut self, builder: InstructionBuilder) {
self.instructions.push(builder.build(self.format_registry)); let opcode_number = OpcodeNumber(self.all_instructions.next_key().as_u32());
let inst = builder.build(self.format_registry, opcode_number);
// Note this clone is cheap, since Instruction is a Rc<> wrapper for InstructionContent.
self.own_instructions.push(inst.clone());
self.all_instructions.push(inst);
} }
pub fn build(self) -> InstructionGroup { pub fn build(self) -> InstructionGroup {
InstructionGroup { InstructionGroup {
_name: self._name, _name: self._name,
_doc: self._doc, _doc: self._doc,
instructions: self.instructions, instructions: self.own_instructions,
} }
} }
} }
@@ -78,6 +93,7 @@ pub struct InstructionContent {
/// Instruction mnemonic, also becomes opcode name. /// Instruction mnemonic, also becomes opcode name.
pub name: String, pub name: String,
pub camel_name: String, pub camel_name: String,
pub opcode_number: OpcodeNumber,
/// Documentation string. /// Documentation string.
doc: String, doc: String,
@@ -300,7 +316,7 @@ impl InstructionBuilder {
self self
} }
fn build(self, format_registry: &FormatRegistry) -> Instruction { fn build(self, format_registry: &FormatRegistry, opcode_number: OpcodeNumber) -> Instruction {
let operands_in = self.operands_in.unwrap_or_else(Vec::new); let operands_in = self.operands_in.unwrap_or_else(Vec::new);
let operands_out = self.operands_out.unwrap_or_else(Vec::new); let operands_out = self.operands_out.unwrap_or_else(Vec::new);
@@ -333,10 +349,12 @@ impl InstructionBuilder {
let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags()); let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags());
let camel_name = camel_case(&self.name); let camel_name = camel_case(&self.name);
Instruction { Instruction {
content: Rc::new(InstructionContent { content: Rc::new(InstructionContent {
name: self.name, name: self.name,
camel_name, camel_name,
opcode_number,
doc: self.doc, doc: self.doc,
operands_in, operands_in,
operands_out, operands_out,

View File

@@ -404,11 +404,12 @@ impl TransformGroups {
#[should_panic] #[should_panic]
fn test_double_custom_legalization() { fn test_double_custom_legalization() {
use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder}; use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder};
use crate::cdsl::instructions::{InstructionBuilder, InstructionGroupBuilder}; use crate::cdsl::instructions::{AllInstructions, InstructionBuilder, InstructionGroupBuilder};
let mut dummy_all = AllInstructions::new();
let mut format = FormatRegistry::new(); let mut format = FormatRegistry::new();
format.insert(InstructionFormatBuilder::new("nullary")); format.insert(InstructionFormatBuilder::new("nullary"));
let mut inst_group = InstructionGroupBuilder::new("test", "", &format); let mut inst_group = InstructionGroupBuilder::new("test", "", &mut dummy_all, &format);
inst_group.push(InstructionBuilder::new("dummy", "doc")); inst_group.push(InstructionBuilder::new("dummy", "doc"));
let inst_group = inst_group.build(); let inst_group = inst_group.build();
let dummy_inst = inst_group.by_name("dummy"); let dummy_inst = inst_group.by_name("dummy");

View File

@@ -1,3 +1,5 @@
use std::iter;
pub fn simple_hash(s: &str) -> usize { pub fn simple_hash(s: &str) -> usize {
let mut h: u32 = 5381; let mut h: u32 = 5381;
for c in s.chars() { for c in s.chars() {
@@ -9,8 +11,12 @@ pub fn simple_hash(s: &str) -> usize {
/// Compute an open addressed, quadratically probed hash table containing /// Compute an open addressed, quadratically probed hash table containing
/// `items`. The returned table is a list containing the elements of the /// `items`. The returned table is a list containing the elements of the
/// iterable `items` and `None` in unused slots. /// iterable `items` and `None` in unused slots.
pub fn generate_table<T, H: Fn(&T) -> usize>(items: &Vec<T>, hash_function: H) -> Vec<Option<&T>> { pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
let size = (1.20 * items.len() as f64) as usize; items: I,
num_items: usize,
hash_function: H,
) -> Vec<Option<&'cont T>> {
let size = (1.20 * num_items as f64) as usize;
// TODO do we really need the multiply by two here? // TODO do we really need the multiply by two here?
let size = if size.is_power_of_two() { let size = if size.is_power_of_two() {
size * 2 size * 2
@@ -18,10 +24,10 @@ pub fn generate_table<T, H: Fn(&T) -> usize>(items: &Vec<T>, hash_function: H) -
size.next_power_of_two() size.next_power_of_two()
}; };
let mut table: Vec<Option<&T>> = vec![None; size]; let mut table = vec![None; size];
for i in items { for i in items {
let mut h = hash_function(i) % size; let mut h = hash_function(&i) % size;
let mut s = 0; let mut s = 0;
while table[h].is_some() { while table[h].is_some() {
s += 1; s += 1;
@@ -36,7 +42,7 @@ pub fn generate_table<T, H: Fn(&T) -> usize>(items: &Vec<T>, hash_function: H) -
#[test] #[test]
fn test_generate_table() { fn test_generate_table() {
let v = vec!["Hello".to_string(), "world".to_string()]; let v = vec!["Hello".to_string(), "world".to_string()];
let table = generate_table(&v, |s| simple_hash(&s)); let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s));
assert_eq!( assert_eq!(
table, table,
vec![ vec![

View File

@@ -1,15 +1,20 @@
use std::fmt;
use cranelift_entity::EntityRef;
use crate::cdsl::camel_case; use crate::cdsl::camel_case;
use crate::cdsl::formats::{FormatRegistry, InstructionFormat}; use crate::cdsl::formats::{FormatRegistry, InstructionFormat};
use crate::cdsl::instructions::{Instruction, InstructionGroup}; use crate::cdsl::instructions::{AllInstructions, Instruction};
use crate::cdsl::operands::Operand; use crate::cdsl::operands::Operand;
use crate::cdsl::typevar::{TypeSet, TypeVar}; use crate::cdsl::typevar::{TypeSet, TypeVar};
use crate::shared::Definitions as SharedDefinitions;
use crate::constant_hash; use crate::constant_hash;
use crate::error; use crate::error;
use crate::srcgen::{Formatter, Match}; use crate::srcgen::{Formatter, Match};
use crate::unique_table::{UniqueSeqTable, UniqueTable}; use crate::unique_table::{UniqueSeqTable, UniqueTable};
use std::fmt;
// TypeSet indexes are encoded in 8 bits, with `0xff` reserved. // TypeSet indexes are encoded in 8 bits, with `0xff` reserved.
const TYPESET_LIMIT: usize = 0xff; const TYPESET_LIMIT: usize = 0xff;
@@ -368,7 +373,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
} }
fn gen_bool_accessor<T: Fn(&Instruction) -> bool>( fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
instruction_groups: &Vec<&InstructionGroup>, all_inst: &AllInstructions,
get_attr: T, get_attr: T,
name: &'static str, name: &'static str,
doc: &'static str, doc: &'static str,
@@ -378,13 +383,11 @@ fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
fmtln!(fmt, "pub fn {}(self) -> bool {{", name); fmtln!(fmt, "pub fn {}(self) -> bool {{", name);
fmt.indent(|fmt| { fmt.indent(|fmt| {
let mut m = Match::new("self"); let mut m = Match::new("self");
for group in instruction_groups.iter() { for inst in all_inst.values() {
for inst in group.iter() {
if get_attr(inst) { if get_attr(inst) {
m.arm_no_fields(format!("Opcode::{}", inst.camel_name), "true"); m.arm_no_fields(format!("Opcode::{}", inst.camel_name), "true");
} }
} }
}
m.arm_no_fields("_", "false"); m.arm_no_fields("_", "false");
fmt.add_match(m); fmt.add_match(m);
}); });
@@ -392,18 +395,7 @@ fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
fmt.empty_line(); fmt.empty_line();
} }
fn gen_opcodes<'a>( fn gen_opcodes<'a>(all_inst: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) {
formats: &FormatRegistry,
igroups: &Vec<&'a InstructionGroup>,
fmt: &mut Formatter,
) -> Vec<&'a Instruction> {
let mut all_inst = Vec::new();
for group in igroups {
for inst in group.iter() {
all_inst.push(inst);
}
}
fmt.doc_comment( fmt.doc_comment(
r#" r#"
An instruction opcode. An instruction opcode.
@@ -420,10 +412,7 @@ fn gen_opcodes<'a>(
fmt.line("pub enum Opcode {"); fmt.line("pub enum Opcode {");
fmt.indent(|fmt| { fmt.indent(|fmt| {
let mut is_first_opcode = true; let mut is_first_opcode = true;
for inst in &all_inst { for inst in all_inst.values() {
// TODO we might need to set an instruction number here. Probably can do in the
// InstructionGroup itself when adding instruction (would need to remember last
// instruction number in the SharedDefinitions or somewhere else).
let format = formats.get(inst.format); let format = formats.get(inst.format);
fmt.doc_comment(format!("`{}`. ({})", inst, format.name)); fmt.doc_comment(format!("`{}`. ({})", inst, format.name));
@@ -440,6 +429,8 @@ fn gen_opcodes<'a>(
// Enum variant itself. // Enum variant itself.
if is_first_opcode { if is_first_opcode {
assert!(inst.opcode_number.index() == 0);
// TODO the python crate requires opcode numbers to start from one.
fmtln!(fmt, "{} = 1,", inst.camel_name); fmtln!(fmt, "{} = 1,", inst.camel_name);
is_first_opcode = false; is_first_opcode = false;
} else { } else {
@@ -453,77 +444,77 @@ fn gen_opcodes<'a>(
fmt.line("impl Opcode {"); fmt.line("impl Opcode {");
fmt.indent(|fmt| { fmt.indent(|fmt| {
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_terminator, |inst| inst.is_terminator,
"is_terminator", "is_terminator",
"True for instructions that terminate the EBB", "True for instructions that terminate the EBB",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_branch, |inst| inst.is_branch,
"is_branch", "is_branch",
"True for all branch or jump instructions.", "True for all branch or jump instructions.",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_indirect_branch, |inst| inst.is_indirect_branch,
"is_indirect_branch", "is_indirect_branch",
"True for all indirect branch or jump instructions.", "True for all indirect branch or jump instructions.",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_call, |inst| inst.is_call,
"is_call", "is_call",
"Is this a call instruction?", "Is this a call instruction?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_return, |inst| inst.is_return,
"is_return", "is_return",
"Is this a return instruction?", "Is this a return instruction?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.is_ghost, |inst| inst.is_ghost,
"is_ghost", "is_ghost",
"Is this a ghost instruction?", "Is this a ghost instruction?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.can_load, |inst| inst.can_load,
"can_load", "can_load",
"Can this instruction read from memory?", "Can this instruction read from memory?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.can_store, |inst| inst.can_store,
"can_store", "can_store",
"Can this instruction write to memory?", "Can this instruction write to memory?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.can_trap, |inst| inst.can_trap,
"can_trap", "can_trap",
"Can this instruction cause a trap?", "Can this instruction cause a trap?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.other_side_effects, |inst| inst.other_side_effects,
"other_side_effects", "other_side_effects",
"Does this instruction have other side effects besides can_* flags?", "Does this instruction have other side effects besides can_* flags?",
fmt, fmt,
); );
gen_bool_accessor( gen_bool_accessor(
igroups, all_inst,
|inst| inst.writes_cpu_flags, |inst| inst.writes_cpu_flags,
"writes_cpu_flags", "writes_cpu_flags",
"Does this instruction write to CPU flags?", "Does this instruction write to CPU flags?",
@@ -540,7 +531,7 @@ fn gen_opcodes<'a>(
all_inst.len() all_inst.len()
); );
fmt.indent(|fmt| { fmt.indent(|fmt| {
for inst in &all_inst { for inst in all_inst.values() {
let format = formats.get(inst.format); let format = formats.get(inst.format);
fmtln!(fmt, "InstructionFormat::{}, // {}", format.name, inst.name); fmtln!(fmt, "InstructionFormat::{}, // {}", format.name, inst.name);
} }
@@ -552,7 +543,7 @@ fn gen_opcodes<'a>(
fmt.line("fn opcode_name(opc: Opcode) -> &\'static str {"); fmt.line("fn opcode_name(opc: Opcode) -> &\'static str {");
fmt.indent(|fmt| { fmt.indent(|fmt| {
let mut m = Match::new("opc"); let mut m = Match::new("opc");
for inst in &all_inst { for inst in all_inst.values() {
m.arm_no_fields( m.arm_no_fields(
format!("Opcode::{}", inst.camel_name), format!("Opcode::{}", inst.camel_name),
format!("\"{}\"", inst.name), format!("\"{}\"", inst.name),
@@ -564,8 +555,9 @@ fn gen_opcodes<'a>(
fmt.empty_line(); fmt.empty_line();
// Generate an opcode hash table for looking up opcodes by name. // Generate an opcode hash table for looking up opcodes by name.
let hash_table = let hash_table = constant_hash::generate_table(all_inst.values(), all_inst.len(), |inst| {
constant_hash::generate_table(&all_inst, |inst| constant_hash::simple_hash(&inst.name)); constant_hash::simple_hash(&inst.name)
});
fmtln!( fmtln!(
fmt, fmt,
"const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = [", "const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = [",
@@ -581,8 +573,6 @@ fn gen_opcodes<'a>(
}); });
fmtln!(fmt, "];"); fmtln!(fmt, "];");
fmt.empty_line(); fmt.empty_line();
all_inst
} }
/// Get the value type constraint for an SSA value operand, where /// Get the value type constraint for an SSA value operand, where
@@ -698,7 +688,7 @@ pub fn gen_typesets_table(type_sets: &UniqueTable<TypeSet>, fmt: &mut Formatter)
/// - Emit a compact constant table of ValueTypeSet objects. /// - Emit a compact constant table of ValueTypeSet objects.
/// - Emit a compact constant table of OperandConstraint objects. /// - Emit a compact constant table of OperandConstraint objects.
/// - Emit an opcode-indexed table of instruction constraints. /// - Emit an opcode-indexed table of instruction constraints.
fn gen_type_constraints(all_inst: &Vec<&Instruction>, fmt: &mut Formatter) { fn gen_type_constraints(all_inst: &AllInstructions, fmt: &mut Formatter) {
// Table of TypeSet instances. // Table of TypeSet instances.
let mut type_sets = UniqueTable::new(); let mut type_sets = UniqueTable::new();
@@ -719,7 +709,7 @@ fn gen_type_constraints(all_inst: &Vec<&Instruction>, fmt: &mut Formatter) {
all_inst.len() all_inst.len()
); );
fmt.indent(|fmt| { fmt.indent(|fmt| {
for inst in all_inst { for inst in all_inst.values() {
let (ctrl_typevar, ctrl_typeset) = if let Some(poly) = &inst.polymorphic_info { let (ctrl_typevar, ctrl_typeset) = if let Some(poly) = &inst.polymorphic_info {
let index = type_sets.add(&*poly.ctrl_typevar.get_raw_typeset()); let index = type_sets.add(&*poly.ctrl_typevar.get_raw_typeset());
(Some(&poly.ctrl_typevar), index) (Some(&poly.ctrl_typevar), index)
@@ -1035,7 +1025,7 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
} }
/// Generate a Builder trait with methods for all instructions. /// Generate a Builder trait with methods for all instructions.
fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt: &mut Formatter) { fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) {
fmt.doc_comment( fmt.doc_comment(
r#" r#"
Convenience methods for building instructions. Convenience methods for building instructions.
@@ -1055,7 +1045,7 @@ fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt:
); );
fmt.line("pub trait InstBuilder<'f>: InstBuilderBase<'f> {"); fmt.line("pub trait InstBuilder<'f>: InstBuilderBase<'f> {");
fmt.indent(|fmt| { fmt.indent(|fmt| {
for inst in instructions { for inst in instructions.values() {
gen_inst_builder(inst, formats.get(inst.format), fmt); gen_inst_builder(inst, formats.get(inst.format), fmt);
} }
for format in formats.iter() { for format in formats.iter() {
@@ -1066,12 +1056,14 @@ fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt:
} }
pub fn generate( pub fn generate(
all_inst_groups: Vec<&InstructionGroup>, shared_defs: &SharedDefinitions,
format_registry: &FormatRegistry,
opcode_filename: &str, opcode_filename: &str,
inst_builder_filename: &str, inst_builder_filename: &str,
out_dir: &str, out_dir: &str,
) -> Result<(), error::Error> { ) -> Result<(), error::Error> {
let format_registry = &shared_defs.format_registry;
let all_inst = &shared_defs.all_instructions;
// Opcodes. // Opcodes.
let mut fmt = Formatter::new(); let mut fmt = Formatter::new();
gen_formats(format_registry, &mut fmt); gen_formats(format_registry, &mut fmt);
@@ -1079,13 +1071,13 @@ pub fn generate(
fmt.empty_line(); fmt.empty_line();
gen_instruction_data_impl(format_registry, &mut fmt); gen_instruction_data_impl(format_registry, &mut fmt);
fmt.empty_line(); fmt.empty_line();
let all_inst = gen_opcodes(format_registry, &all_inst_groups, &mut fmt); gen_opcodes(all_inst, format_registry, &mut fmt);
gen_type_constraints(&all_inst, &mut fmt); gen_type_constraints(all_inst, &mut fmt);
fmt.update_file(opcode_filename, out_dir)?; fmt.update_file(opcode_filename, out_dir)?;
// Instruction builder. // Instruction builder.
let mut fmt = Formatter::new(); let mut fmt = Formatter::new();
gen_builder(&all_inst, format_registry, &mut fmt); gen_builder(all_inst, format_registry, &mut fmt);
fmt.update_file(inst_builder_filename, out_dir)?; fmt.update_file(inst_builder_filename, out_dir)?;
Ok(()) Ok(())

View File

@@ -308,7 +308,9 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
hash_entries.extend(group.settings.iter().map(|x| SettingOrPreset::Setting(x))); hash_entries.extend(group.settings.iter().map(|x| SettingOrPreset::Setting(x)));
hash_entries.extend(group.presets.iter().map(|x| SettingOrPreset::Preset(x))); hash_entries.extend(group.presets.iter().map(|x| SettingOrPreset::Preset(x)));
let hash_table = generate_table(&hash_entries, |entry| simple_hash(entry.name())); let hash_table = generate_table(hash_entries.iter(), hash_entries.len(), |entry| {
simple_hash(entry.name())
});
fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len()); fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len());
fmt.indent(|fmt| { fmt.indent(|fmt| {
for h in &hash_table { for h in &hash_table {

View File

@@ -55,6 +55,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let inst_group = InstructionGroupBuilder::new( let inst_group = InstructionGroupBuilder::new(
"arm32", "arm32",
"arm32 specific instruction set", "arm32 specific instruction set",
&mut shared_defs.all_instructions,
&shared_defs.format_registry, &shared_defs.format_registry,
) )
.build(); .build();

View File

@@ -51,6 +51,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let inst_group = InstructionGroupBuilder::new( let inst_group = InstructionGroupBuilder::new(
"arm64", "arm64",
"arm64 specific instruction set", "arm64 specific instruction set",
&mut shared_defs.all_instructions,
&shared_defs.format_registry, &shared_defs.format_registry,
) )
.build(); .build();

View File

@@ -89,6 +89,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let inst_group = InstructionGroupBuilder::new( let inst_group = InstructionGroupBuilder::new(
"riscv", "riscv",
"riscv specific instruction set", "riscv specific instruction set",
&mut shared_defs.all_instructions,
&shared_defs.format_registry, &shared_defs.format_registry,
) )
.build(); .build();

View File

@@ -2,16 +2,23 @@
use crate::cdsl::formats::FormatRegistry; use crate::cdsl::formats::FormatRegistry;
use crate::cdsl::instructions::{ use crate::cdsl::instructions::{
InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder,
}; };
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc};
use crate::cdsl::types::ValueType; use crate::cdsl::types::ValueType;
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
use crate::shared::types; use crate::shared::types;
pub fn define(format_registry: &FormatRegistry) -> InstructionGroup { pub fn define(
let mut ig = mut all_instructions: &mut AllInstructions,
InstructionGroupBuilder::new("x86", "x86 specific instruction set", format_registry); format_registry: &FormatRegistry,
) -> InstructionGroup {
let mut ig = InstructionGroupBuilder::new(
"x86",
"x86 specific instruction set",
&mut all_instructions,
format_registry,
);
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into(); let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();

View File

@@ -15,7 +15,10 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let settings = settings::define(&shared_defs.settings); let settings = settings::define(&shared_defs.settings);
let regs = registers::define(); let regs = registers::define();
let inst_group = instructions::define(&shared_defs.format_registry); let inst_group = instructions::define(
&mut shared_defs.all_instructions,
&shared_defs.format_registry,
);
legalize::define(shared_defs, &inst_group); legalize::define(shared_defs, &inst_group);
// CPU modes for 32-bit and 64-bit operations. // CPU modes for 32-bit and 64-bit operations.

View File

@@ -35,16 +35,7 @@ pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error>
// Per ISA definitions. // Per ISA definitions.
let isas = isa::define(isas, &mut shared_defs); let isas = isa::define(isas, &mut shared_defs);
let mut all_inst_groups = vec![&shared_defs.instructions]; gen_inst::generate(&shared_defs, "opcodes.rs", "inst_builder.rs", &out_dir)?;
all_inst_groups.extend(isas.iter().map(|isa| &isa.instructions));
gen_inst::generate(
all_inst_groups,
&shared_defs.format_registry,
"opcodes.rs",
"inst_builder.rs",
&out_dir,
)?;
gen_legalizer::generate( gen_legalizer::generate(
&isas, &isas,

View File

@@ -2,7 +2,7 @@
use crate::cdsl::formats::FormatRegistry; use crate::cdsl::formats::FormatRegistry;
use crate::cdsl::instructions::{ use crate::cdsl::instructions::{
InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder,
}; };
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc};
use crate::cdsl::type_inference::Constraint::WiderOrEq; use crate::cdsl::type_inference::Constraint::WiderOrEq;
@@ -11,12 +11,17 @@ use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
use crate::shared::{types, OperandKinds}; use crate::shared::{types, OperandKinds};
pub fn define( pub fn define(
all_instructions: &mut AllInstructions,
format_registry: &FormatRegistry, format_registry: &FormatRegistry,
immediates: &OperandKinds, immediates: &OperandKinds,
entities: &OperandKinds, entities: &OperandKinds,
) -> InstructionGroup { ) -> InstructionGroup {
let mut ig = let mut ig = InstructionGroupBuilder::new(
InstructionGroupBuilder::new("base", "Shared base instruction set", format_registry); "base",
"Shared base instruction set",
all_instructions,
format_registry,
);
// Operand kind shorthands. // Operand kind shorthands.
let intcc = immediates.by_name("intcc"); let intcc = immediates.by_name("intcc");

View File

@@ -9,13 +9,14 @@ pub mod settings;
pub mod types; pub mod types;
use crate::cdsl::formats::FormatRegistry; use crate::cdsl::formats::FormatRegistry;
use crate::cdsl::instructions::InstructionGroup; use crate::cdsl::instructions::{AllInstructions, InstructionGroup};
use crate::cdsl::operands::OperandKind; use crate::cdsl::operands::OperandKind;
use crate::cdsl::settings::SettingGroup; use crate::cdsl::settings::SettingGroup;
use crate::cdsl::xform::TransformGroups; use crate::cdsl::xform::TransformGroups;
pub struct Definitions { pub struct Definitions {
pub settings: SettingGroup, pub settings: SettingGroup,
pub all_instructions: AllInstructions,
pub instructions: InstructionGroup, pub instructions: InstructionGroup,
pub operand_kinds: OperandKinds, pub operand_kinds: OperandKinds,
pub format_registry: FormatRegistry, pub format_registry: FormatRegistry,
@@ -50,14 +51,22 @@ impl OperandKinds {
} }
pub fn define() -> Definitions { pub fn define() -> Definitions {
let mut all_instructions = AllInstructions::new();
let immediates = OperandKinds(immediates::define()); let immediates = OperandKinds(immediates::define());
let entities = OperandKinds(entities::define()); let entities = OperandKinds(entities::define());
let format_registry = formats::define(&immediates, &entities); let format_registry = formats::define(&immediates, &entities);
let instructions = instructions::define(&format_registry, &immediates, &entities); let instructions = instructions::define(
&mut all_instructions,
&format_registry,
&immediates,
&entities,
);
let transform_groups = legalize::define(&instructions, &immediates); let transform_groups = legalize::define(&instructions, &immediates);
Definitions { Definitions {
settings: settings::define(), settings: settings::define(),
all_instructions,
instructions, instructions,
operand_kinds: immediates, operand_kinds: immediates,
format_registry, format_registry,