[meta] Introduce the EntityRefs structure instead of using dynamic lookup;

This commit is contained in:
Benjamin Bouvier
2019-09-04 16:37:15 +02:00
parent 29e3ec51c1
commit 8fba449b7b
4 changed files with 137 additions and 137 deletions

View File

@@ -1,65 +1,76 @@
use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder, OperandKindFields};
pub struct EntityRefs {
/// A reference to an extended basic block in the same function.
/// This is primarliy used in control flow instructions.
pub ebb: OperandKind,
/// A reference to a stack slot declared in the function preamble.
pub stack_slot: OperandKind,
/// A reference to a global value.
pub global_value: OperandKind,
/// A reference to a function signature declared in the function preamble.
/// This is used to provide the call signature in a call_indirect instruction.
pub sig_ref: OperandKind,
/// A reference to an external function declared in the function preamble.
/// This is used to provide the callee and signature in a call instruction.
pub func_ref: OperandKind,
/// A reference to a jump table declared in the function preamble.
pub jump_table: OperandKind,
/// A reference to a heap declared in the function preamble.
pub heap: OperandKind,
/// A reference to a table declared in the function preamble.
pub table: OperandKind,
/// A variable-sized list of value operands. Use for Ebb and function call arguments.
pub varargs: OperandKind,
}
impl EntityRefs {
pub fn new() -> Self {
Self {
ebb: create("ebb", "An extended basic block in the same function.")
.default_member("destination")
.build(),
stack_slot: create("stack_slot", "A stack slot").build(),
global_value: create("global_value", "A global value.").build(),
sig_ref: create("sig_ref", "A function signature.").build(),
func_ref: create("func_ref", "An external function.").build(),
jump_table: create("jump_table", "A jump table.")
.default_member("table")
.build(),
heap: create("heap", "A heap.").build(),
table: create("table", "A table.").build(),
varargs: Builder::new("variable_args", OperandKindFields::VariableArgs)
.doc(
r#"
A variable size list of `value` operands.
Use this to represent arguments passed to a function call, arguments
passed to an extended basic block, or a variable number of results
returned from an instruction.
"#,
)
.build(),
}
}
}
/// Small helper to initialize an OperandBuilder with the right kind, for a given name and doc.
fn create(name: &'static str, doc: &'static str) -> Builder {
Builder::new(name, OperandKindFields::EntityRef).doc(doc)
}
pub fn define() -> Vec<OperandKind> {
let mut kinds = Vec::new();
// A reference to an extended basic block in the same function.
// This is primarliy used in control flow instructions.
let ebb = create("ebb", "An extended basic block in the same function.")
.default_member("destination")
.build();
kinds.push(ebb);
// A reference to a stack slot declared in the function preamble.
let stack_slot = create("stack_slot", "A stack slot").build();
kinds.push(stack_slot);
// A reference to a global value.
let global_value = create("global_value", "A global value.").build();
kinds.push(global_value);
// A reference to a function signature declared in the function preamble.
// This is used to provide the call signature in a call_indirect instruction.
let sig_ref = create("sig_ref", "A function signature.").build();
kinds.push(sig_ref);
// A reference to an external function declared in the function preamble.
// This is used to provide the callee and signature in a call instruction.
let func_ref = create("func_ref", "An external function.").build();
kinds.push(func_ref);
// A reference to a jump table declared in the function preamble.
let jump_table = create("jump_table", "A jump table.")
.default_member("table")
.build();
kinds.push(jump_table);
// A reference to a heap declared in the function preamble.
let heap = create("heap", "A heap.").build();
kinds.push(heap);
// A reference to a table declared in the function preamble.
let table = create("table", "A table.").build();
kinds.push(table);
// A variable-sized list of value operands. Use for Ebb and function call arguments.
let varargs = Builder::new("variable_args", OperandKindFields::VariableArgs)
.doc(
r#"
A variable size list of `value` operands.
Use this to represent arguments passed to a function call, arguments
passed to an extended basic block, or a variable number of results
returned from an instruction.
"#,
)
.build();
kinds.push(varargs);
return kinds;
}

View File

@@ -1,18 +1,7 @@
use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder};
use crate::shared::immediates::Immediates;
use crate::shared::OperandKinds;
pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
// Shorthands for entities.
let global_value = entities.by_name("global_value");
let ebb = entities.by_name("ebb");
let jump_table = entities.by_name("jump_table");
let func_ref = entities.by_name("func_ref");
let sig_ref = entities.by_name("sig_ref");
let stack_slot = entities.by_name("stack_slot");
let heap = entities.by_name("heap");
let table = entities.by_name("table");
use crate::shared::{entities::EntityRefs, immediates::Immediates};
pub fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry {
let mut registry = FormatRegistry::new();
registry.insert(Builder::new("Unary").value());
@@ -21,7 +10,7 @@ pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
registry.insert(Builder::new("UnaryIeee32").imm(&imm.ieee32));
registry.insert(Builder::new("UnaryIeee64").imm(&imm.ieee64));
registry.insert(Builder::new("UnaryBool").imm(&imm.boolean));
registry.insert(Builder::new("UnaryGlobalValue").imm(global_value));
registry.insert(Builder::new("UnaryGlobalValue").imm(&entities.global_value));
registry.insert(Builder::new("Binary").value().value());
registry.insert(Builder::new("BinaryImm").value().imm(&imm.imm64));
@@ -80,20 +69,20 @@ pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
.value(),
);
registry.insert(Builder::new("Jump").imm(ebb).varargs());
registry.insert(Builder::new("Branch").value().imm(ebb).varargs());
registry.insert(Builder::new("Jump").imm(&entities.ebb).varargs());
registry.insert(Builder::new("Branch").value().imm(&entities.ebb).varargs());
registry.insert(
Builder::new("BranchInt")
.imm(&imm.intcc)
.value()
.imm(ebb)
.imm(&entities.ebb)
.varargs(),
);
registry.insert(
Builder::new("BranchFloat")
.imm(&imm.floatcc)
.value()
.imm(ebb)
.imm(&entities.ebb)
.varargs(),
);
registry.insert(
@@ -101,23 +90,37 @@ pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
.imm(&imm.intcc)
.value()
.value()
.imm(ebb)
.imm(&entities.ebb)
.varargs(),
);
registry.insert(Builder::new("BranchTable").value().imm(ebb).imm(jump_table));
registry.insert(
Builder::new("BranchTable")
.value()
.imm(&entities.ebb)
.imm(&entities.jump_table),
);
registry.insert(
Builder::new("BranchTableEntry")
.value()
.value()
.imm(&imm.uimm8)
.imm(jump_table),
.imm(&entities.jump_table),
);
registry.insert(Builder::new("BranchTableBase").imm(&entities.jump_table));
registry.insert(
Builder::new("IndirectJump")
.value()
.imm(&entities.jump_table),
);
registry.insert(Builder::new("BranchTableBase").imm(jump_table));
registry.insert(Builder::new("IndirectJump").value().imm(jump_table));
registry.insert(Builder::new("Call").imm(func_ref).varargs());
registry.insert(Builder::new("CallIndirect").imm(sig_ref).value().varargs());
registry.insert(Builder::new("FuncAddr").imm(func_ref));
registry.insert(Builder::new("Call").imm(&entities.func_ref).varargs());
registry.insert(
Builder::new("CallIndirect")
.imm(&entities.sig_ref)
.value()
.varargs(),
);
registry.insert(Builder::new("FuncAddr").imm(&entities.func_ref));
registry.insert(
Builder::new("Load")
@@ -145,21 +148,30 @@ pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
.varargs()
.imm(&imm.offset32),
);
registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(&imm.offset32));
registry.insert(
Builder::new("StackLoad")
.imm(&entities.stack_slot)
.imm(&imm.offset32),
);
registry.insert(
Builder::new("StackStore")
.value()
.imm(stack_slot)
.imm(&entities.stack_slot)
.imm(&imm.offset32),
);
// Accessing a WebAssembly heap.
registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(&imm.uimm32));
registry.insert(
Builder::new("HeapAddr")
.imm(&entities.heap)
.value()
.imm(&imm.uimm32),
);
// Accessing a WebAssembly table.
registry.insert(
Builder::new("TableAddr")
.imm(table)
.imm(&entities.table)
.value()
.imm(&imm.offset32),
);
@@ -180,12 +192,12 @@ pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
Builder::new("RegSpill")
.value()
.imm_with_name("src", &imm.regunit)
.imm_with_name("dst", stack_slot),
.imm_with_name("dst", &entities.stack_slot),
);
registry.insert(
Builder::new("RegFill")
.value()
.imm_with_name("src", stack_slot)
.imm_with_name("src", &entities.stack_slot)
.imm_with_name("dst", &imm.regunit),
);

View File

@@ -8,14 +8,14 @@ use crate::cdsl::operands::{create_operand as operand, create_operand_doc as ope
use crate::cdsl::type_inference::Constraint::WiderOrEq;
use crate::cdsl::types::{LaneType, ValueType};
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
use crate::shared::immediates::Immediates;
use crate::shared::{types, OperandKinds};
use crate::shared::types;
use crate::shared::{entities::EntityRefs, immediates::Immediates};
pub fn define(
all_instructions: &mut AllInstructions,
format_registry: &FormatRegistry,
imm: &Immediates,
entities: &OperandKinds,
entities: &EntityRefs,
) -> InstructionGroup {
let mut ig = InstructionGroupBuilder::new(
"base",
@@ -25,16 +25,6 @@ pub fn define(
);
// Operand kind shorthands.
let ebb = entities.by_name("ebb");
let jump_table = entities.by_name("jump_table");
let variable_args = entities.by_name("variable_args");
let func_ref = entities.by_name("func_ref");
let sig_ref = entities.by_name("sig_ref");
let stack_slot = entities.by_name("stack_slot");
let global_value = entities.by_name("global_value");
let heap = entities.by_name("heap");
let table = entities.by_name("table");
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
let fflags: &TypeVar = &ValueType::Special(types::Flag::FFlags.into()).into();
@@ -132,8 +122,8 @@ pub fn define(
let Cond = &operand("Cond", &imm.intcc);
let x = &operand("x", iB);
let y = &operand("y", iB);
let EBB = &operand_doc("EBB", ebb, "Destination extended basic block");
let args = &operand_doc("args", variable_args, "EBB arguments");
let EBB = &operand_doc("EBB", &entities.ebb, "Destination extended basic block");
let args = &operand_doc("args", &entities.varargs, "EBB arguments");
ig.push(
Inst::new(
@@ -257,7 +247,7 @@ pub fn define(
// The index into the br_table can be any type; legalizer will convert it to the right type.
let x = &operand_doc("x", iB, "index into jump table");
let entry = &operand_doc("entry", iAddr, "entry of jump table");
let JT = &operand("JT", jump_table);
let JT = &operand("JT", &entities.jump_table);
ig.push(
Inst::new(
@@ -433,7 +423,7 @@ pub fn define(
.can_trap(true),
);
let rvals = &operand_doc("rvals", variable_args, "return values");
let rvals = &operand_doc("rvals", &entities.varargs, "return values");
ig.push(
Inst::new(
@@ -467,8 +457,12 @@ pub fn define(
.is_terminator(true),
);
let FN = &operand_doc("FN", func_ref, "function to call, declared by `function`");
let args = &operand_doc("args", variable_args, "call arguments");
let FN = &operand_doc(
"FN",
&entities.func_ref,
"function to call, declared by `function`",
);
let args = &operand_doc("args", &entities.varargs, "call arguments");
ig.push(
Inst::new(
@@ -485,7 +479,7 @@ pub fn define(
.is_call(true),
);
let SIG = &operand_doc("SIG", sig_ref, "function signature");
let SIG = &operand_doc("SIG", &entities.sig_ref, "function signature");
let callee = &operand_doc("callee", iAddr, "address of function to call");
ig.push(
@@ -525,13 +519,13 @@ pub fn define(
.operands_out(vec![addr]),
);
let SS = &operand("SS", stack_slot);
let SS = &operand("SS", &entities.stack_slot);
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from base address");
let x = &operand_doc("x", Mem, "Value to be stored");
let a = &operand_doc("a", Mem, "Value loaded");
let p = &operand("p", iAddr);
let MemFlags = &operand("MemFlags", &imm.memflags);
let args = &operand_doc("args", variable_args, "Address arguments");
let args = &operand_doc("args", &entities.varargs, "Address arguments");
ig.push(
Inst::new(
@@ -917,7 +911,7 @@ pub fn define(
.operands_out(vec![addr]),
);
let GV = &operand("GV", global_value);
let GV = &operand("GV", &entities.global_value);
ig.push(
Inst::new(
@@ -947,7 +941,7 @@ pub fn define(
TypeSetBuilder::new().ints(32..64).build(),
);
let H = &operand("H", heap);
let H = &operand("H", &entities.heap);
let p = &operand("p", HeapOffset);
let Size = &operand_doc("Size", &imm.uimm32, "Size in bytes");
@@ -975,7 +969,7 @@ pub fn define(
"An unsigned table offset",
TypeSetBuilder::new().ints(32..64).build(),
);
let T = &operand("T", table);
let T = &operand("T", &entities.table);
let p = &operand("p", TableOffset);
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from element address");
@@ -1382,7 +1376,7 @@ pub fn define(
let N = &operand_doc(
"args",
variable_args,
&entities.varargs,
"Variable number of args for Stackmap",
);

View File

@@ -1,6 +1,6 @@
//! Shared definitions for the Cranelift intermediate language.
pub mod entities;
mod entities;
pub mod formats;
pub mod immediates;
pub mod instructions;
@@ -10,10 +10,10 @@ pub mod types;
use crate::cdsl::formats::FormatRegistry;
use crate::cdsl::instructions::{AllInstructions, InstructionGroup};
use crate::cdsl::operands::OperandKind;
use crate::cdsl::settings::SettingGroup;
use crate::cdsl::xform::TransformGroups;
use crate::shared::entities::EntityRefs;
use crate::shared::immediates::Immediates;
pub struct Definitions {
@@ -25,28 +25,11 @@ pub struct Definitions {
pub transform_groups: TransformGroups,
}
pub struct OperandKinds(Vec<OperandKind>);
impl OperandKinds {
pub fn by_name(&self, name: &'static str) -> &OperandKind {
self.0
.iter()
.find(|op| op.name == name)
.expect(&format!("unknown Operand name: {}", name))
}
}
impl From<Vec<OperandKind>> for OperandKinds {
fn from(kinds: Vec<OperandKind>) -> Self {
OperandKinds(kinds)
}
}
pub fn define() -> Definitions {
let mut all_instructions = AllInstructions::new();
let immediates = Immediates::new();
let entities = OperandKinds(entities::define());
let entities = EntityRefs::new();;
let format_registry = formats::define(&immediates, &entities);
let instructions = instructions::define(
&mut all_instructions,