[meta] Introduce the EntityRefs structure instead of using dynamic lookup;
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
|
||||
|
||||
@@ -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",
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user