use crate::cdsl::formats::{InstructionFormat, InstructionFormatBuilder as Builder}; use crate::shared::{entities::EntityRefs, immediates::Immediates}; use std::rc::Rc; pub(crate) struct Formats { pub(crate) atomic_cas: Rc, pub(crate) atomic_rmw: Rc, pub(crate) binary: Rc, pub(crate) binary_imm8: Rc, pub(crate) binary_imm64: Rc, pub(crate) branch: Rc, pub(crate) branch_table: Rc, pub(crate) call: Rc, pub(crate) call_indirect: Rc, pub(crate) cond_trap: Rc, pub(crate) float_compare: Rc, pub(crate) func_addr: Rc, pub(crate) int_compare: Rc, pub(crate) int_compare_imm: Rc, pub(crate) int_add_trap: Rc, pub(crate) jump: Rc, pub(crate) load: Rc, pub(crate) load_no_offset: Rc, pub(crate) multiary: Rc, pub(crate) nullary: Rc, pub(crate) shuffle: Rc, pub(crate) stack_load: Rc, pub(crate) stack_store: Rc, pub(crate) dynamic_stack_load: Rc, pub(crate) dynamic_stack_store: Rc, pub(crate) store: Rc, pub(crate) store_no_offset: Rc, pub(crate) table_addr: Rc, pub(crate) ternary: Rc, pub(crate) ternary_imm8: Rc, pub(crate) trap: Rc, pub(crate) unary: Rc, pub(crate) unary_const: Rc, pub(crate) unary_global_value: Rc, pub(crate) unary_ieee32: Rc, pub(crate) unary_ieee64: Rc, pub(crate) unary_imm: Rc, } impl Formats { pub fn new(imm: &Immediates, entities: &EntityRefs) -> Self { Self { unary: Builder::new("Unary").value().build(), unary_imm: Builder::new("UnaryImm").imm(&imm.imm64).build(), unary_ieee32: Builder::new("UnaryIeee32").imm(&imm.ieee32).build(), unary_ieee64: Builder::new("UnaryIeee64").imm(&imm.ieee64).build(), unary_const: Builder::new("UnaryConst").imm(&imm.pool_constant).build(), unary_global_value: Builder::new("UnaryGlobalValue") .imm(&entities.global_value) .build(), binary: Builder::new("Binary").value().value().build(), binary_imm8: Builder::new("BinaryImm8").value().imm(&imm.uimm8).build(), binary_imm64: Builder::new("BinaryImm64").value().imm(&imm.imm64).build(), // The select instructions are controlled by the second VALUE operand. // The first VALUE operand is the controlling flag which has a derived type. // The fma instruction has the same constraint on all inputs. ternary: Builder::new("Ternary") .value() .value() .value() .typevar_operand(1) .build(), ternary_imm8: Builder::new("TernaryImm8") .value() .imm(&imm.uimm8) .value() .build(), // Catch-all for instructions with many outputs and inputs and no immediate // operands. multiary: Builder::new("MultiAry").varargs().build(), nullary: Builder::new("NullAry").build(), shuffle: Builder::new("Shuffle") .value() .value() .imm(&imm.uimm128) .build(), int_compare: Builder::new("IntCompare") .imm(&imm.intcc) .value() .value() .build(), int_compare_imm: Builder::new("IntCompareImm") .imm(&imm.intcc) .value() .imm(&imm.imm64) .build(), float_compare: Builder::new("FloatCompare") .imm(&imm.floatcc) .value() .value() .build(), jump: Builder::new("Jump").imm(&entities.block).varargs().build(), branch: Builder::new("Branch") .value() .imm(&entities.block) .varargs() .build(), branch_table: Builder::new("BranchTable") .value() .imm(&entities.block) .imm(&entities.jump_table) .build(), call: Builder::new("Call") .imm(&entities.func_ref) .varargs() .build(), call_indirect: Builder::new("CallIndirect") .imm(&entities.sig_ref) .value() .varargs() .build(), func_addr: Builder::new("FuncAddr").imm(&entities.func_ref).build(), atomic_rmw: Builder::new("AtomicRmw") .imm(&imm.memflags) .imm(&imm.atomic_rmw_op) .value() .value() .build(), atomic_cas: Builder::new("AtomicCas") .imm(&imm.memflags) .value() .value() .value() .typevar_operand(2) .build(), load: Builder::new("Load") .imm(&imm.memflags) .value() .imm(&imm.offset32) .build(), load_no_offset: Builder::new("LoadNoOffset") .imm(&imm.memflags) .value() .build(), store: Builder::new("Store") .imm(&imm.memflags) .value() .value() .imm(&imm.offset32) .build(), store_no_offset: Builder::new("StoreNoOffset") .imm(&imm.memflags) .value() .value() .build(), stack_load: Builder::new("StackLoad") .imm(&entities.stack_slot) .imm(&imm.offset32) .build(), stack_store: Builder::new("StackStore") .value() .imm(&entities.stack_slot) .imm(&imm.offset32) .build(), dynamic_stack_load: Builder::new("DynamicStackLoad") .imm(&entities.dynamic_stack_slot) .build(), dynamic_stack_store: Builder::new("DynamicStackStore") .value() .imm(&entities.dynamic_stack_slot) .build(), // Accessing a WebAssembly table. table_addr: Builder::new("TableAddr") .imm(&entities.table) .value() .imm(&imm.offset32) .build(), trap: Builder::new("Trap").imm(&imm.trapcode).build(), cond_trap: Builder::new("CondTrap").value().imm(&imm.trapcode).build(), int_add_trap: Builder::new("IntAddTrap") .value() .value() .imm(&imm.trapcode) .build(), } } }