[meta] Remove name lookups in formats;

This does a lot at once, since there was no clear way to split the three
commits:

- Instruction need to be passed an explicit InstructionFormat,
- InstructionFormat deduplication is checked once all entities have been
defined;
This commit is contained in:
Benjamin Bouvier
2019-10-18 19:24:03 +02:00
parent 9e9a7626d7
commit 0243b642e3
17 changed files with 1002 additions and 730 deletions

View File

@@ -4,13 +4,11 @@ use cranelift_codegen_shared::constant_hash;
use cranelift_entity::EntityRef;
use crate::cdsl::camel_case;
use crate::cdsl::formats::{FormatRegistry, InstructionFormat};
use crate::cdsl::formats::InstructionFormat;
use crate::cdsl::instructions::{AllInstructions, Instruction};
use crate::cdsl::operands::Operand;
use crate::cdsl::typevar::{TypeSet, TypeVar};
use crate::shared::Definitions as SharedDefinitions;
use crate::error;
use crate::srcgen::{Formatter, Match};
use crate::unique_table::{UniqueSeqTable, UniqueTable};
@@ -19,7 +17,7 @@ use crate::unique_table::{UniqueSeqTable, UniqueTable};
const TYPESET_LIMIT: usize = 0xff;
/// Generate an instruction format enumeration.
fn gen_formats(registry: &FormatRegistry, fmt: &mut Formatter) {
fn gen_formats(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
fmt.doc_comment(
r#"
An instruction format
@@ -32,7 +30,7 @@ fn gen_formats(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.line("#[derive(Copy, Clone, PartialEq, Eq, Debug)]");
fmt.line("pub enum InstructionFormat {");
fmt.indent(|fmt| {
for format in registry.iter() {
for format in formats {
fmt.doc_comment(format.to_string());
fmtln!(fmt, "{},", format.name);
}
@@ -47,7 +45,7 @@ fn gen_formats(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.line("fn from(inst: &'a InstructionData) -> Self {");
fmt.indent(|fmt| {
let mut m = Match::new("*inst");
for format in registry.iter() {
for format in formats {
m.arm(
format!("InstructionData::{}", format.name),
vec![".."],
@@ -67,12 +65,12 @@ fn gen_formats(registry: &FormatRegistry, fmt: &mut Formatter) {
/// Every variant must contain an `opcode` field. The size of `InstructionData` should be kept at
/// 16 bytes on 64-bit architectures. If more space is needed to represent an instruction, use a
/// `ValueList` to store the additional information out of line.
fn gen_instruction_data(registry: &FormatRegistry, fmt: &mut Formatter) {
fn gen_instruction_data(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
fmt.line("#[derive(Clone, Debug)]");
fmt.line("#[allow(missing_docs)]");
fmt.line("pub enum InstructionData {");
fmt.indent(|fmt| {
for format in registry.iter() {
for format in formats {
fmtln!(fmt, "{} {{", format.name);
fmt.indent(|fmt| {
fmt.line("opcode: Opcode,");
@@ -95,7 +93,7 @@ fn gen_instruction_data(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.line("}");
}
fn gen_arguments_method(registry: &FormatRegistry, fmt: &mut Formatter, is_mut: bool) {
fn gen_arguments_method(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter, is_mut: bool) {
let (method, mut_, rslice, as_slice) = if is_mut {
(
"arguments_mut",
@@ -117,7 +115,7 @@ fn gen_arguments_method(registry: &FormatRegistry, fmt: &mut Formatter, is_mut:
);
fmt.indent(|fmt| {
let mut m = Match::new("*self");
for format in registry.iter() {
for format in formats {
let name = format!("InstructionData::{}", format.name);
// Formats with a value list put all of their arguments in the list. We don't split
@@ -165,14 +163,14 @@ fn gen_arguments_method(registry: &FormatRegistry, fmt: &mut Formatter, is_mut:
/// - `pub fn put_value_list(&mut self, args: ir::ValueList>`
/// - `pub fn eq(&self, &other: Self, &pool) -> bool`
/// - `pub fn hash<H: Hasher>(&self, state: &mut H, &pool)`
fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
fmt.line("impl InstructionData {");
fmt.indent(|fmt| {
fmt.doc_comment("Get the opcode of this instruction.");
fmt.line("pub fn opcode(&self) -> Opcode {");
fmt.indent(|fmt| {
let mut m = Match::new("*self");
for format in registry.iter() {
for format in formats {
m.arm(format!("InstructionData::{}", format.name), vec!["opcode", ".."],
"opcode".to_string());
}
@@ -185,7 +183,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.line("pub fn typevar_operand(&self, pool: &ir::ValueListPool) -> Option<Value> {");
fmt.indent(|fmt| {
let mut m = Match::new("*self");
for format in registry.iter() {
for format in formats {
let name = format!("InstructionData::{}", format.name);
if format.typevar_operand.is_none() {
m.arm(name, vec![".."], "None".to_string());
@@ -208,12 +206,12 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.empty_line();
fmt.doc_comment("Get the value arguments to this instruction.");
gen_arguments_method(registry, fmt, false);
gen_arguments_method(formats, fmt, false);
fmt.empty_line();
fmt.doc_comment(r#"Get mutable references to the value arguments to this
instruction."#);
gen_arguments_method(registry, fmt, true);
gen_arguments_method(formats, fmt, true);
fmt.empty_line();
fmt.doc_comment(r#"
@@ -227,7 +225,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.indent(|fmt| {
let mut m = Match::new("*self");
for format in registry.iter() {
for format in formats {
if format.has_value_list {
m.arm(format!("InstructionData::{}", format.name),
vec!["ref mut args", ".."],
@@ -254,7 +252,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.indent(|fmt| {
fmt.line("let args = match *self {");
fmt.indent(|fmt| {
for format in registry.iter() {
for format in formats {
if format.has_value_list {
fmtln!(fmt, "InstructionData::{} {{ ref mut args, .. }} => args,", format.name);
}
@@ -284,7 +282,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.line("match (self, other) {");
fmt.indent(|fmt| {
for format in registry.iter() {
for format in formats {
let name = format!("&InstructionData::{}", format.name);
let mut members = vec!["opcode"];
@@ -336,7 +334,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) {
fmt.indent(|fmt| {
fmt.line("match *self {");
fmt.indent(|fmt| {
for format in registry.iter() {
for format in formats {
let name = format!("InstructionData::{}", format.name);
let mut members = vec!["opcode"];
@@ -1037,7 +1035,11 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
}
/// Generate a Builder trait with methods for all instructions.
fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) {
fn gen_builder(
instructions: &AllInstructions,
formats: &Vec<&InstructionFormat>,
fmt: &mut Formatter,
) {
fmt.doc_comment(
r#"
Convenience methods for building instructions.
@@ -1060,7 +1062,7 @@ fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &m
for inst in instructions.values() {
gen_inst_builder(inst, &*inst.format, fmt);
}
for format in formats.iter() {
for format in formats {
gen_format_constructor(format, fmt);
}
});
@@ -1068,20 +1070,18 @@ fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &m
}
pub(crate) fn generate(
shared_defs: &SharedDefinitions,
formats: Vec<&InstructionFormat>,
all_inst: &AllInstructions,
opcode_filename: &str,
inst_builder_filename: &str,
out_dir: &str,
) -> Result<(), error::Error> {
let format_registry = &shared_defs.format_registry;
let all_inst = &shared_defs.all_instructions;
// Opcodes.
let mut fmt = Formatter::new();
gen_formats(format_registry, &mut fmt);
gen_instruction_data(format_registry, &mut fmt);
gen_formats(&formats, &mut fmt);
gen_instruction_data(&formats, &mut fmt);
fmt.empty_line();
gen_instruction_data_impl(format_registry, &mut fmt);
gen_instruction_data_impl(&formats, &mut fmt);
fmt.empty_line();
gen_opcodes(all_inst, &mut fmt);
gen_type_constraints(all_inst, &mut fmt);
@@ -1089,7 +1089,7 @@ pub(crate) fn generate(
// Instruction builder.
let mut fmt = Formatter::new();
gen_builder(all_inst, format_registry, &mut fmt);
gen_builder(all_inst, &formats, &mut fmt);
fmt.update_file(inst_builder_filename, out_dir)?;
Ok(())