diff --git a/cranelift/codegen/meta/src/shared/entities.rs b/cranelift/codegen/meta/src/shared/entities.rs index 358ef8f23e..910722789b 100644 --- a/cranelift/codegen/meta/src/shared/entities.rs +++ b/cranelift/codegen/meta/src/shared/entities.rs @@ -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 { - 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; -} diff --git a/cranelift/codegen/meta/src/shared/formats.rs b/cranelift/codegen/meta/src/shared/formats.rs index 2f79fdbdf1..d631f337c2 100644 --- a/cranelift/codegen/meta/src/shared/formats.rs +++ b/cranelift/codegen/meta/src/shared/formats.rs @@ -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), ); diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index ad94efeb80..9499bf190a 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -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", ); diff --git a/cranelift/codegen/meta/src/shared/mod.rs b/cranelift/codegen/meta/src/shared/mod.rs index 837bf3c71d..29c74caa06 100644 --- a/cranelift/codegen/meta/src/shared/mod.rs +++ b/cranelift/codegen/meta/src/shared/mod.rs @@ -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); - -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> for OperandKinds { - fn from(kinds: Vec) -> 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,