diff --git a/cranelift/codegen/meta/src/isa/riscv/encodings.rs b/cranelift/codegen/meta/src/isa/riscv/encodings.rs index a5af1214aa..af5e471a53 100644 --- a/cranelift/codegen/meta/src/isa/riscv/encodings.rs +++ b/cranelift/codegen/meta/src/isa/riscv/encodings.rs @@ -230,8 +230,7 @@ pub fn define<'defs>( -> InstructionPredicateNode { let x = var_pool.create("x"); let y = var_pool.create("y"); - let cc = - Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field); + let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field); Apply::new( bound_inst.clone().into(), vec![Expr::Literal(cc), Expr::Var(x), Expr::Var(y)], @@ -313,8 +312,7 @@ pub fn define<'defs>( let y = var_pool.create("y"); let dest = var_pool.create("dest"); let args = var_pool.create("args"); - let cc = - Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field); + let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field); Apply::new( bound_inst.clone().into(), vec![ diff --git a/cranelift/codegen/meta/src/isa/x86/instructions.rs b/cranelift/codegen/meta/src/isa/x86/instructions.rs index 6464261938..742b632642 100644 --- a/cranelift/codegen/meta/src/isa/x86/instructions.rs +++ b/cranelift/codegen/meta/src/isa/x86/instructions.rs @@ -7,11 +7,13 @@ use crate::cdsl::instructions::{ use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::types::ValueType; use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; -use crate::shared::{immediates, types, OperandKinds}; +use crate::shared::immediates::Immediates; +use crate::shared::types; pub fn define( mut all_instructions: &mut AllInstructions, format_registry: &FormatRegistry, + immediates: &Immediates, ) -> InstructionGroup { let mut ig = InstructionGroupBuilder::new( "x86", @@ -249,8 +251,7 @@ pub fn define( .operands_out(vec![y, rflags]), ); - let immediates = OperandKinds::from(immediates::define()); - let uimm8 = immediates.by_name("uimm8"); + let uimm8 = &immediates.uimm8; let TxN = &TypeVar::new( "TxN", "A SIMD vector type", diff --git a/cranelift/codegen/meta/src/isa/x86/legalize.rs b/cranelift/codegen/meta/src/isa/x86/legalize.rs index a64f631168..158b05e4f1 100644 --- a/cranelift/codegen/meta/src/isa/x86/legalize.rs +++ b/cranelift/codegen/meta/src/isa/x86/legalize.rs @@ -58,12 +58,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou let x86_umulx = x86_instructions.by_name("x86_umulx"); let x86_smulx = x86_instructions.by_name("x86_smulx"); - // List of immediates. - let floatcc = shared.operand_kinds.by_name("floatcc"); - let imm64 = shared.operand_kinds.by_name("imm64"); - let intcc = shared.operand_kinds.by_name("intcc"); - let uimm8 = shared.operand_kinds.by_name("uimm8"); - let ieee64 = shared.operand_kinds.by_name("ieee64"); + let imm = &shared.imm; // Division and remainder. // @@ -99,12 +94,12 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou // `ucomiss` or `ucomisd` instruction. The remaining codes need legalization // patterns. - let floatcc_eq = Literal::enumerator_for(floatcc, "eq"); - let floatcc_ord = Literal::enumerator_for(floatcc, "ord"); - let floatcc_ueq = Literal::enumerator_for(floatcc, "ueq"); - let floatcc_ne = Literal::enumerator_for(floatcc, "ne"); - let floatcc_uno = Literal::enumerator_for(floatcc, "uno"); - let floatcc_one = Literal::enumerator_for(floatcc, "one"); + let floatcc_eq = Literal::enumerator_for(&imm.floatcc, "eq"); + let floatcc_ord = Literal::enumerator_for(&imm.floatcc, "ord"); + let floatcc_ueq = Literal::enumerator_for(&imm.floatcc, "ueq"); + let floatcc_ne = Literal::enumerator_for(&imm.floatcc, "ne"); + let floatcc_uno = Literal::enumerator_for(&imm.floatcc, "uno"); + let floatcc_one = Literal::enumerator_for(&imm.floatcc, "one"); // Equality needs an explicit `ord` test which checks the parity bit. group.legalize( @@ -124,14 +119,14 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou ], ); - let floatcc_lt = &Literal::enumerator_for(floatcc, "lt"); - let floatcc_gt = &Literal::enumerator_for(floatcc, "gt"); - let floatcc_le = &Literal::enumerator_for(floatcc, "le"); - let floatcc_ge = &Literal::enumerator_for(floatcc, "ge"); - let floatcc_ugt = &Literal::enumerator_for(floatcc, "ugt"); - let floatcc_ult = &Literal::enumerator_for(floatcc, "ult"); - let floatcc_uge = &Literal::enumerator_for(floatcc, "uge"); - let floatcc_ule = &Literal::enumerator_for(floatcc, "ule"); + let floatcc_lt = &Literal::enumerator_for(&imm.floatcc, "lt"); + let floatcc_gt = &Literal::enumerator_for(&imm.floatcc, "gt"); + let floatcc_le = &Literal::enumerator_for(&imm.floatcc, "le"); + let floatcc_ge = &Literal::enumerator_for(&imm.floatcc, "ge"); + let floatcc_ugt = &Literal::enumerator_for(&imm.floatcc, "ugt"); + let floatcc_ult = &Literal::enumerator_for(&imm.floatcc, "ult"); + let floatcc_uge = &Literal::enumerator_for(&imm.floatcc, "uge"); + let floatcc_ule = &Literal::enumerator_for(&imm.floatcc, "ule"); // Inequalities that need to be reversed. for &(cc, rev_cc) in &[ @@ -165,9 +160,9 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou let r2flags = var("r2flags"); let index2 = var("index2"); - let intcc_eq = Literal::enumerator_for(intcc, "eq"); - let imm64_minus_one = Literal::constant(imm64, -1); - let imm64_63 = Literal::constant(imm64, 63); + let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq"); + let imm64_minus_one = Literal::constant(&imm.imm64, -1); + let imm64_63 = Literal::constant(&imm.imm64, 63); group.legalize( def!(a = clz.I64(x)), vec![ @@ -179,7 +174,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou ], ); - let imm64_31 = Literal::constant(imm64, 31); + let imm64_31 = Literal::constant(&imm.imm64, 31); group.legalize( def!(a = clz.I32(x)), vec![ @@ -191,7 +186,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou ], ); - let imm64_64 = Literal::constant(imm64, 64); + let imm64_64 = Literal::constant(&imm.imm64, 64); group.legalize( def!(a = ctz.I64(x)), vec![ @@ -201,7 +196,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou ], ); - let imm64_32 = Literal::constant(imm64, 32); + let imm64_32 = Literal::constant(&imm.imm64, 32); group.legalize( def!(a = ctz.I32(x)), vec![ @@ -232,13 +227,13 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou let qc0F = var("qc0F"); let qc01 = var("qc01"); - let imm64_1 = Literal::constant(imm64, 1); - let imm64_4 = Literal::constant(imm64, 4); + let imm64_1 = Literal::constant(&imm.imm64, 1); + let imm64_4 = Literal::constant(&imm.imm64, 4); group.legalize( def!(qv16 = popcnt.I64(qv1)), vec![ def!(qv3 = ushr_imm(qv1, imm64_1)), - def!(qc77 = iconst(Literal::constant(imm64, 0x7777777777777777))), + def!(qc77 = iconst(Literal::constant(&imm.imm64, 0x7777777777777777))), def!(qv4 = band(qv3, qc77)), def!(qv5 = isub(qv1, qv4)), def!(qv6 = ushr_imm(qv4, imm64_1)), @@ -249,11 +244,11 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou def!(qv11 = isub(qv8, qv10)), def!(qv12 = ushr_imm(qv11, imm64_4)), def!(qv13 = iadd(qv11, qv12)), - def!(qc0F = iconst(Literal::constant(imm64, 0x0F0F0F0F0F0F0F0F))), + def!(qc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F0F0F0F0F))), def!(qv14 = band(qv13, qc0F)), - def!(qc01 = iconst(Literal::constant(imm64, 0x0101010101010101))), + def!(qc01 = iconst(Literal::constant(&imm.imm64, 0x0101010101010101))), def!(qv15 = imul(qv14, qc01)), - def!(qv16 = ushr_imm(qv15, Literal::constant(imm64, 56))), + def!(qv16 = ushr_imm(qv15, Literal::constant(&imm.imm64, 56))), ], ); @@ -281,7 +276,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou def!(lv16 = popcnt.I32(lv1)), vec![ def!(lv3 = ushr_imm(lv1, imm64_1)), - def!(lc77 = iconst(Literal::constant(imm64, 0x77777777))), + def!(lc77 = iconst(Literal::constant(&imm.imm64, 0x77777777))), def!(lv4 = band(lv3, lc77)), def!(lv5 = isub(lv1, lv4)), def!(lv6 = ushr_imm(lv4, imm64_1)), @@ -292,11 +287,11 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou def!(lv11 = isub(lv8, lv10)), def!(lv12 = ushr_imm(lv11, imm64_4)), def!(lv13 = iadd(lv11, lv12)), - def!(lc0F = iconst(Literal::constant(imm64, 0x0F0F0F0F))), + def!(lc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F))), def!(lv14 = band(lv13, lc0F)), - def!(lc01 = iconst(Literal::constant(imm64, 0x01010101))), + def!(lc01 = iconst(Literal::constant(&imm.imm64, 0x01010101))), def!(lv15 = imul(lv14, lc01)), - def!(lv16 = ushr_imm(lv15, Literal::constant(imm64, 24))), + def!(lv16 = ushr_imm(lv15, Literal::constant(&imm.imm64, 24))), ], ); @@ -313,9 +308,9 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou .chain_with(shared.transform_groups.by_name("narrow").id); // SIMD - let uimm8_zero = Literal::constant(uimm8, 0x00); - let uimm8_one = Literal::constant(uimm8, 0x01); - let ieee64_zero = Literal::constant(ieee64, 0x00); + let uimm8_zero = Literal::constant(&imm.uimm8, 0x00); + let uimm8_one = Literal::constant(&imm.uimm8, 0x01); + let ieee64_zero = Literal::constant(&imm.ieee64, 0x00); let b = var("b"); let c = var("c"); let d = var("d"); diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index 9f4a4a334a..5122c7b2ad 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -20,6 +20,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = instructions::define( &mut shared_defs.all_instructions, &shared_defs.format_registry, + &shared_defs.imm, ); legalize::define(shared_defs, &inst_group); diff --git a/cranelift/codegen/meta/src/isa/x86/recipes.rs b/cranelift/codegen/meta/src/isa/x86/recipes.rs index 579da62bdd..8eb0fdac6d 100644 --- a/cranelift/codegen/meta/src/isa/x86/recipes.rs +++ b/cranelift/codegen/meta/src/isa/x86/recipes.rs @@ -332,7 +332,7 @@ pub fn define<'shared>( ) -> RecipeGroup<'shared> { // The set of floating point condition codes that are directly supported. // Other condition codes need to be reversed or expressed as two tests. - let floatcc = shared_defs.operand_kinds.by_name("floatcc"); + let floatcc = &shared_defs.imm.floatcc; let supported_floatccs: Vec = ["ord", "uno", "one", "ueq", "gt", "ge", "ult", "ule"] .iter() .map(|name| Literal::enumerator_for(floatcc, name)) diff --git a/cranelift/codegen/meta/src/shared/formats.rs b/cranelift/codegen/meta/src/shared/formats.rs index 2a16f250a1..2f79fdbdf1 100644 --- a/cranelift/codegen/meta/src/shared/formats.rs +++ b/cranelift/codegen/meta/src/shared/formats.rs @@ -1,22 +1,8 @@ use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder}; +use crate::shared::immediates::Immediates; use crate::shared::OperandKinds; -pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegistry { - // Shorthands for immediates. - let uimm8 = immediates.by_name("uimm8"); - let uimm32 = immediates.by_name("uimm32"); - let uimm128 = immediates.by_name("uimm128"); - let imm64 = immediates.by_name("imm64"); - let ieee32 = immediates.by_name("ieee32"); - let ieee64 = immediates.by_name("ieee64"); - let boolean = immediates.by_name("boolean"); - let intcc = immediates.by_name("intcc"); - let floatcc = immediates.by_name("floatcc"); - let memflags = immediates.by_name("memflags"); - let offset32 = immediates.by_name("offset32"); - let trapcode = immediates.by_name("trapcode"); - let regunit = immediates.by_name("regunit"); - +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"); @@ -30,15 +16,15 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis let mut registry = FormatRegistry::new(); registry.insert(Builder::new("Unary").value()); - registry.insert(Builder::new("UnaryImm").imm(imm64)); - registry.insert(Builder::new("UnaryImm128").imm(uimm128)); - registry.insert(Builder::new("UnaryIeee32").imm(ieee32)); - registry.insert(Builder::new("UnaryIeee64").imm(ieee64)); - registry.insert(Builder::new("UnaryBool").imm(boolean)); + registry.insert(Builder::new("UnaryImm").imm(&imm.imm64)); + registry.insert(Builder::new("UnaryImm128").imm(&imm.uimm128)); + 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("Binary").value().value()); - registry.insert(Builder::new("BinaryImm").value().imm(imm64)); + registry.insert(Builder::new("BinaryImm").value().imm(&imm.imm64)); // The select instructions are controlled by the second VALUE operand. // The first VALUE operand is the controlling flag which has a derived type. @@ -60,43 +46,59 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis registry.insert( Builder::new("InsertLane") .value() - .imm_with_name("lane", uimm8) + .imm_with_name("lane", &imm.uimm8) .value(), ); registry.insert( Builder::new("ExtractLane") .value() - .imm_with_name("lane", uimm8), + .imm_with_name("lane", &imm.uimm8), ); - registry.insert(Builder::new("IntCompare").imm(intcc).value().value()); - registry.insert(Builder::new("IntCompareImm").imm(intcc).value().imm(imm64)); - registry.insert(Builder::new("IntCond").imm(intcc).value()); + registry.insert(Builder::new("IntCompare").imm(&imm.intcc).value().value()); + registry.insert( + Builder::new("IntCompareImm") + .imm(&imm.intcc) + .value() + .imm(&imm.imm64), + ); + registry.insert(Builder::new("IntCond").imm(&imm.intcc).value()); - registry.insert(Builder::new("FloatCompare").imm(floatcc).value().value()); - registry.insert(Builder::new("FloatCond").imm(floatcc).value());; + registry.insert( + Builder::new("FloatCompare") + .imm(&imm.floatcc) + .value() + .value(), + ); + registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value());; - registry.insert(Builder::new("IntSelect").imm(intcc).value().value().value()); + registry.insert( + Builder::new("IntSelect") + .imm(&imm.intcc) + .value() + .value() + .value(), + ); registry.insert(Builder::new("Jump").imm(ebb).varargs()); registry.insert(Builder::new("Branch").value().imm(ebb).varargs()); registry.insert( Builder::new("BranchInt") - .imm(intcc) + .imm(&imm.intcc) .value() .imm(ebb) .varargs(), ); registry.insert( Builder::new("BranchFloat") - .imm(floatcc) + .imm(&imm.floatcc) .value() .imm(ebb) .varargs(), ); registry.insert( Builder::new("BranchIcmp") - .imm(intcc) + .imm(&imm.intcc) .value() .value() .imm(ebb) @@ -107,7 +109,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis Builder::new("BranchTableEntry") .value() .value() - .imm(uimm8) + .imm(&imm.uimm8) .imm(jump_table), ); registry.insert(Builder::new("BranchTableBase").imm(jump_table)); @@ -117,74 +119,89 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis registry.insert(Builder::new("CallIndirect").imm(sig_ref).value().varargs()); registry.insert(Builder::new("FuncAddr").imm(func_ref)); - registry.insert(Builder::new("Load").imm(memflags).value().imm(offset32)); + registry.insert( + Builder::new("Load") + .imm(&imm.memflags) + .value() + .imm(&imm.offset32), + ); registry.insert( Builder::new("LoadComplex") - .imm(memflags) + .imm(&imm.memflags) .varargs() - .imm(offset32), + .imm(&imm.offset32), ); registry.insert( Builder::new("Store") - .imm(memflags) + .imm(&imm.memflags) .value() .value() - .imm(offset32), + .imm(&imm.offset32), ); registry.insert( Builder::new("StoreComplex") - .imm(memflags) + .imm(&imm.memflags) .value() .varargs() - .imm(offset32), + .imm(&imm.offset32), ); - registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(offset32)); + registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(&imm.offset32)); registry.insert( Builder::new("StackStore") .value() .imm(stack_slot) - .imm(offset32), + .imm(&imm.offset32), ); // Accessing a WebAssembly heap. - registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(uimm32)); + registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(&imm.uimm32)); // Accessing a WebAssembly table. - registry.insert(Builder::new("TableAddr").imm(table).value().imm(offset32)); + registry.insert( + Builder::new("TableAddr") + .imm(table) + .value() + .imm(&imm.offset32), + ); registry.insert( Builder::new("RegMove") .value() - .imm_with_name("src", regunit) - .imm_with_name("dst", regunit), + .imm_with_name("src", &imm.regunit) + .imm_with_name("dst", &imm.regunit), ); registry.insert( Builder::new("CopySpecial") - .imm_with_name("src", regunit) - .imm_with_name("dst", regunit), + .imm_with_name("src", &imm.regunit) + .imm_with_name("dst", &imm.regunit), ); - registry.insert(Builder::new("CopyToSsa").imm_with_name("src", regunit)); + registry.insert(Builder::new("CopyToSsa").imm_with_name("src", &imm.regunit)); registry.insert( Builder::new("RegSpill") .value() - .imm_with_name("src", regunit) + .imm_with_name("src", &imm.regunit) .imm_with_name("dst", stack_slot), ); registry.insert( Builder::new("RegFill") .value() .imm_with_name("src", stack_slot) - .imm_with_name("dst", regunit), + .imm_with_name("dst", &imm.regunit), ); - registry.insert(Builder::new("Trap").imm(trapcode)); - registry.insert(Builder::new("CondTrap").value().imm(trapcode)); - registry.insert(Builder::new("IntCondTrap").imm(intcc).value().imm(trapcode)); + registry.insert(Builder::new("Trap").imm(&imm.trapcode)); + registry.insert(Builder::new("CondTrap").value().imm(&imm.trapcode)); + registry.insert( + Builder::new("IntCondTrap") + .imm(&imm.intcc) + .value() + .imm(&imm.trapcode), + ); registry.insert( Builder::new("FloatCondTrap") - .imm(floatcc) + .imm(&imm.floatcc) .value() - .imm(trapcode), + .imm(&imm.trapcode), ); registry diff --git a/cranelift/codegen/meta/src/shared/immediates.rs b/cranelift/codegen/meta/src/shared/immediates.rs index 5b8baca898..b7a7f712a2 100644 --- a/cranelift/codegen/meta/src/shared/immediates.rs +++ b/cranelift/codegen/meta/src/shared/immediates.rs @@ -2,154 +2,174 @@ use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder}; use std::collections::HashMap; -pub fn define() -> Vec { - let mut kinds = Vec::new(); +pub struct Immediates { + /// A 64-bit immediate integer operand. + /// + /// This type of immediate integer can interact with SSA values with any IntType type. + pub imm64: OperandKind, - // A 64-bit immediate integer operand. - // - // This type of immediate integer can interact with SSA values with any - // IntType type. - let imm64 = Builder::new_imm("imm64") - .doc("A 64-bit immediate integer.") - .build(); - kinds.push(imm64); + /// An unsigned 8-bit immediate integer operand. + /// + /// This small operand is used to indicate lane indexes in SIMD vectors and immediate bit + /// counts on shift instructions. + pub uimm8: OperandKind, - // An unsigned 8-bit immediate integer operand. - // - // This small operand is used to indicate lane indexes in SIMD vectors and - // immediate bit counts on shift instructions. - let uimm8 = Builder::new_imm("uimm8") - .doc("An 8-bit immediate unsigned integer.") - .build(); - kinds.push(uimm8); + /// An unsigned 32-bit immediate integer operand. + pub uimm32: OperandKind, - // An unsigned 32-bit immediate integer operand. - let uimm32 = Builder::new_imm("uimm32") - .doc("A 32-bit immediate unsigned integer.") - .build(); - kinds.push(uimm32); + /// An unsigned 128-bit immediate integer operand. + /// + /// This operand is used to pass entire 128-bit vectors as immediates to instructions like + /// const. + pub uimm128: OperandKind, - // An unsigned 128-bit immediate integer operand. - // - // This operand is used to pass entire 128-bit vectors as immediates to - // instructions like const. - let uimm128 = Builder::new_imm("uimm128") - .doc("A 128-bit immediate unsigned integer.") - .rust_type("ir::Constant") - .build(); - kinds.push(uimm128); + /// A 32-bit immediate signed offset. + /// + /// This is used to represent an immediate address offset in load/store instructions. + pub offset32: OperandKind, - // A 32-bit immediate signed offset. - // - // This is used to represent an immediate address offset in load/store - // instructions. - let offset32 = Builder::new_imm("offset32") - .doc("A 32-bit immediate signed offset.") - .default_member("offset") - .build(); - kinds.push(offset32); + /// A 32-bit immediate floating point operand. + /// + /// IEEE 754-2008 binary32 interchange format. + pub ieee32: OperandKind, - // A 32-bit immediate floating point operand. - // - // IEEE 754-2008 binary32 interchange format. - let ieee32 = Builder::new_imm("ieee32") - .doc("A 32-bit immediate floating point number.") - .build(); - kinds.push(ieee32); + /// A 64-bit immediate floating point operand. + /// + /// IEEE 754-2008 binary64 interchange format. + pub ieee64: OperandKind, - // A 64-bit immediate floating point operand. - // - // IEEE 754-2008 binary64 interchange format. - let ieee64 = Builder::new_imm("ieee64") - .doc("A 64-bit immediate floating point number.") - .build(); - kinds.push(ieee64); + /// An immediate boolean operand. + /// + /// This type of immediate boolean can interact with SSA values with any BoolType type. + pub boolean: OperandKind, - // An immediate boolean operand. - // - // This type of immediate boolean can interact with SSA values with any - // BoolType type. - let boolean = Builder::new_imm("boolean") - .doc("An immediate boolean.") - .rust_type("bool") - .build(); - kinds.push(boolean); + /// A condition code for comparing integer values. + /// + /// This enumerated operand kind is used for the `icmp` instruction and corresponds to the + /// condcodes::IntCC` Rust type. + pub intcc: OperandKind, - // A condition code for comparing integer values. - // This enumerated operand kind is used for the `icmp` instruction and corresponds to the - // condcodes::IntCC` Rust type. - let mut intcc_values = HashMap::new(); - intcc_values.insert("eq", "Equal"); - intcc_values.insert("ne", "NotEqual"); - intcc_values.insert("sge", "SignedGreaterThanOrEqual"); - intcc_values.insert("sgt", "SignedGreaterThan"); - intcc_values.insert("sle", "SignedLessThanOrEqual"); - intcc_values.insert("slt", "SignedLessThan"); - intcc_values.insert("uge", "UnsignedGreaterThanOrEqual"); - intcc_values.insert("ugt", "UnsignedGreaterThan"); - intcc_values.insert("ule", "UnsignedLessThanOrEqual"); - intcc_values.insert("ult", "UnsignedLessThan"); - let intcc = Builder::new_enum("intcc", intcc_values) - .doc("An integer comparison condition code.") - .default_member("cond") - .rust_type("ir::condcodes::IntCC") - .build(); - kinds.push(intcc); + /// A condition code for comparing floating point values. + /// + /// This enumerated operand kind is used for the `fcmp` instruction and corresponds to the + /// `condcodes::FloatCC` Rust type. + pub floatcc: OperandKind, - // A condition code for comparing floating point values. This enumerated operand kind is used - // for the `fcmp` instruction and corresponds to the `condcodes::FloatCC` Rust type. - let mut floatcc_values = HashMap::new(); - floatcc_values.insert("ord", "Ordered"); - floatcc_values.insert("uno", "Unordered"); - floatcc_values.insert("eq", "Equal"); - floatcc_values.insert("ne", "NotEqual"); - floatcc_values.insert("one", "OrderedNotEqual"); - floatcc_values.insert("ueq", "UnorderedOrEqual"); - floatcc_values.insert("lt", "LessThan"); - floatcc_values.insert("le", "LessThanOrEqual"); - floatcc_values.insert("gt", "GreaterThan"); - floatcc_values.insert("ge", "GreaterThanOrEqual"); - floatcc_values.insert("ult", "UnorderedOrLessThan"); - floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual"); - floatcc_values.insert("ugt", "UnorderedOrGreaterThan"); - floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual"); - let floatcc = Builder::new_enum("floatcc", floatcc_values) - .doc("A floating point comparison condition code") - .default_member("cond") - .rust_type("ir::condcodes::FloatCC") - .build(); - kinds.push(floatcc); + /// Flags for memory operations like `load` and `store`. + pub memflags: OperandKind, - // Flags for memory operations like :clif:inst:`load` and :clif:inst:`store`. - let memflags = Builder::new_imm("memflags") - .doc("Memory operation flags") - .default_member("flags") - .rust_type("ir::MemFlags") - .build(); - kinds.push(memflags); + /// A register unit in the current target ISA. + pub regunit: OperandKind, - // A register unit in the current target ISA. - let regunit = Builder::new_imm("regunit") - .doc("A register unit in the target ISA") - .rust_type("isa::RegUnit") - .build(); - kinds.push(regunit); - - // A trap code indicating the reason for trapping. - // - // The Rust enum type also has a `User(u16)` variant for user-provided trap - // codes. - let mut trapcode_values = HashMap::new(); - trapcode_values.insert("stk_ovf", "StackOverflow"); - trapcode_values.insert("heap_oob", "HeapOutOfBounds"); - trapcode_values.insert("int_ovf", "IntegerOverflow"); - trapcode_values.insert("int_divz", "IntegerDivisionByZero"); - let trapcode = Builder::new_enum("trapcode", trapcode_values) - .doc("A trap reason code.") - .default_member("code") - .rust_type("ir::TrapCode") - .build(); - kinds.push(trapcode); - - return kinds; + /// A trap code indicating the reason for trapping. + /// + /// The Rust enum type also has a `User(u16)` variant for user-provided trap codes. + pub trapcode: OperandKind, +} + +impl Immediates { + pub fn new() -> Self { + Self { + imm64: Builder::new_imm("imm64") + .doc("A 64-bit immediate integer.") + .build(), + + uimm8: Builder::new_imm("uimm8") + .doc("An 8-bit immediate unsigned integer.") + .build(), + + uimm32: Builder::new_imm("uimm32") + .doc("A 32-bit immediate unsigned integer.") + .build(), + + uimm128: Builder::new_imm("uimm128") + .doc("A 128-bit immediate unsigned integer.") + .rust_type("ir::Constant") + .build(), + + offset32: Builder::new_imm("offset32") + .doc("A 32-bit immediate signed offset.") + .default_member("offset") + .build(), + + ieee32: Builder::new_imm("ieee32") + .doc("A 32-bit immediate floating point number.") + .build(), + + ieee64: Builder::new_imm("ieee64") + .doc("A 64-bit immediate floating point number.") + .build(), + + boolean: Builder::new_imm("boolean") + .doc("An immediate boolean.") + .rust_type("bool") + .build(), + + intcc: { + let mut intcc_values = HashMap::new(); + intcc_values.insert("eq", "Equal"); + intcc_values.insert("ne", "NotEqual"); + intcc_values.insert("sge", "SignedGreaterThanOrEqual"); + intcc_values.insert("sgt", "SignedGreaterThan"); + intcc_values.insert("sle", "SignedLessThanOrEqual"); + intcc_values.insert("slt", "SignedLessThan"); + intcc_values.insert("uge", "UnsignedGreaterThanOrEqual"); + intcc_values.insert("ugt", "UnsignedGreaterThan"); + intcc_values.insert("ule", "UnsignedLessThanOrEqual"); + intcc_values.insert("ult", "UnsignedLessThan"); + Builder::new_enum("intcc", intcc_values) + .doc("An integer comparison condition code.") + .default_member("cond") + .rust_type("ir::condcodes::IntCC") + .build() + }, + + floatcc: { + let mut floatcc_values = HashMap::new(); + floatcc_values.insert("ord", "Ordered"); + floatcc_values.insert("uno", "Unordered"); + floatcc_values.insert("eq", "Equal"); + floatcc_values.insert("ne", "NotEqual"); + floatcc_values.insert("one", "OrderedNotEqual"); + floatcc_values.insert("ueq", "UnorderedOrEqual"); + floatcc_values.insert("lt", "LessThan"); + floatcc_values.insert("le", "LessThanOrEqual"); + floatcc_values.insert("gt", "GreaterThan"); + floatcc_values.insert("ge", "GreaterThanOrEqual"); + floatcc_values.insert("ult", "UnorderedOrLessThan"); + floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual"); + floatcc_values.insert("ugt", "UnorderedOrGreaterThan"); + floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual"); + Builder::new_enum("floatcc", floatcc_values) + .doc("A floating point comparison condition code") + .default_member("cond") + .rust_type("ir::condcodes::FloatCC") + .build() + }, + + memflags: Builder::new_imm("memflags") + .doc("Memory operation flags") + .default_member("flags") + .rust_type("ir::MemFlags") + .build(), + + regunit: Builder::new_imm("regunit") + .doc("A register unit in the target ISA") + .rust_type("isa::RegUnit") + .build(), + + trapcode: { + let mut trapcode_values = HashMap::new(); + trapcode_values.insert("stk_ovf", "StackOverflow"); + trapcode_values.insert("heap_oob", "HeapOutOfBounds"); + trapcode_values.insert("int_ovf", "IntegerOverflow"); + trapcode_values.insert("int_divz", "IntegerDivisionByZero"); + Builder::new_enum("trapcode", trapcode_values) + .doc("A trap reason code.") + .default_member("code") + .rust_type("ir::TrapCode") + .build() + }, + } + } } diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 85c39d71b5..ad94efeb80 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -8,12 +8,13 @@ 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}; pub fn define( all_instructions: &mut AllInstructions, format_registry: &FormatRegistry, - immediates: &OperandKinds, + imm: &Immediates, entities: &OperandKinds, ) -> InstructionGroup { let mut ig = InstructionGroupBuilder::new( @@ -24,20 +25,6 @@ pub fn define( ); // Operand kind shorthands. - let intcc = immediates.by_name("intcc"); - let floatcc = immediates.by_name("floatcc"); - let trapcode = immediates.by_name("trapcode"); - let uimm8 = immediates.by_name("uimm8"); - let uimm32 = immediates.by_name("uimm32"); - let imm64 = immediates.by_name("imm64"); - let uimm128 = immediates.by_name("uimm128"); - let offset32 = immediates.by_name("offset32"); - let memflags = immediates.by_name("memflags"); - let ieee32 = immediates.by_name("ieee32"); - let ieee64 = immediates.by_name("ieee64"); - let boolean = immediates.by_name("boolean"); - let regunit = immediates.by_name("regunit"); - let ebb = entities.by_name("ebb"); let jump_table = entities.by_name("jump_table"); let variable_args = entities.by_name("variable_args"); @@ -142,7 +129,7 @@ pub fn define( let addr = &operand("addr", iAddr); let c = &operand_doc("c", Testable, "Controlling value to test"); - let Cond = &operand("Cond", intcc); + 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"); @@ -253,7 +240,7 @@ pub fn define( .is_branch(true), ); - let Cond = &operand("Cond", floatcc); + let Cond = &operand("Cond", &imm.floatcc); let f = &operand("f", fflags); ig.push( @@ -300,7 +287,7 @@ pub fn define( // These are the instructions which br_table legalizes to: they perform address computations, // using pointer-sized integers, so their type variables are more constrained. let x = &operand_doc("x", iAddr, "index into jump table"); - let Size = &operand_doc("Size", uimm8, "Size in bytes"); + let Size = &operand_doc("Size", &imm.uimm8, "Size in bytes"); ig.push( Inst::new( @@ -365,7 +352,7 @@ pub fn define( .can_store(true), ); - let code = &operand("code", trapcode); + let code = &operand("code", &imm.trapcode); ig.push( Inst::new( @@ -418,7 +405,7 @@ pub fn define( .can_trap(true), ); - let Cond = &operand("Cond", intcc); + let Cond = &operand("Cond", &imm.intcc); let f = &operand("f", iflags); ig.push( @@ -432,7 +419,7 @@ pub fn define( .can_trap(true), ); - let Cond = &operand("Cond", floatcc); + let Cond = &operand("Cond", &imm.floatcc); let f = &operand("f", fflags); ig.push( @@ -539,11 +526,11 @@ pub fn define( ); let SS = &operand("SS", stack_slot); - let Offset = &operand_doc("Offset", offset32, "Byte offset from base address"); + 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", memflags); + let MemFlags = &operand("MemFlags", &imm.memflags); let args = &operand_doc("args", variable_args, "Address arguments"); ig.push( @@ -876,7 +863,7 @@ pub fn define( let x = &operand_doc("x", Mem, "Value to be stored"); let a = &operand_doc("a", Mem, "Value loaded"); - let Offset = &operand_doc("Offset", offset32, "In-bounds offset into stack slot"); + let Offset = &operand_doc("Offset", &imm.offset32, "In-bounds offset into stack slot"); ig.push( Inst::new( @@ -962,7 +949,7 @@ pub fn define( let H = &operand("H", heap); let p = &operand("p", HeapOffset); - let Size = &operand_doc("Size", uimm32, "Size in bytes"); + let Size = &operand_doc("Size", &imm.uimm32, "Size in bytes"); ig.push( Inst::new( @@ -990,7 +977,7 @@ pub fn define( ); let T = &operand("T", table); let p = &operand("p", TableOffset); - let Offset = &operand_doc("Offset", offset32, "Byte offset from element address"); + let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from element address"); ig.push( Inst::new( @@ -1013,7 +1000,7 @@ pub fn define( .operands_out(vec![addr]), ); - let N = &operand("N", imm64); + let N = &operand("N", &imm.imm64); let a = &operand_doc("a", Int, "A constant integer scalar or vector value"); ig.push( @@ -1030,7 +1017,7 @@ pub fn define( .operands_out(vec![a]), ); - let N = &operand("N", ieee32); + let N = &operand("N", &imm.ieee32); let a = &operand_doc("a", f32_, "A constant f32 scalar value"); ig.push( @@ -1046,7 +1033,7 @@ pub fn define( .operands_out(vec![a]), ); - let N = &operand("N", ieee64); + let N = &operand("N", &imm.ieee64); let a = &operand_doc("a", f64_, "A constant f64 scalar value"); ig.push( @@ -1062,7 +1049,7 @@ pub fn define( .operands_out(vec![a]), ); - let N = &operand("N", boolean); + let N = &operand("N", &imm.boolean); let a = &operand_doc("a", Bool, "A constant boolean scalar or vector value"); ig.push( @@ -1079,7 +1066,11 @@ pub fn define( .operands_out(vec![a]), ); - let N = &operand_doc("N", uimm128, "The 16 immediate bytes of a 128-bit vector"); + let N = &operand_doc( + "N", + &imm.uimm128, + "The 16 immediate bytes of a 128-bit vector", + ); let a = &operand_doc("a", TxN, "A constant vector value"); ig.push( @@ -1137,7 +1128,7 @@ pub fn define( .operands_out(vec![a]), ); - let cc = &operand_doc("cc", intcc, "Controlling condition code"); + let cc = &operand_doc("cc", &imm.intcc, "Controlling condition code"); let flags = &operand_doc("flags", iflags, "The machine's flag register"); ig.push( @@ -1217,8 +1208,8 @@ pub fn define( .can_load(true), ); - let src = &operand("src", regunit); - let dst = &operand("dst", regunit); + let src = &operand("src", &imm.regunit); + let dst = &operand("dst", &imm.regunit); ig.push( Inst::new( @@ -1302,7 +1293,7 @@ pub fn define( .other_side_effects(true), ); - let Offset = &operand_doc("Offset", imm64, "Offset from current stack pointer"); + let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer"); ig.push( Inst::new( @@ -1319,7 +1310,7 @@ pub fn define( .other_side_effects(true), ); - let Offset = &operand_doc("Offset", imm64, "Offset from current stack pointer"); + let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer"); ig.push( Inst::new( @@ -1498,7 +1489,7 @@ pub fn define( let x = &operand_doc("x", TxN, "SIMD vector to modify"); let y = &operand_doc("y", &TxN.lane_of(), "New lane value"); - let Idx = &operand_doc("Idx", uimm8, "Lane index"); + let Idx = &operand_doc("Idx", &imm.uimm8, "Lane index"); ig.push( Inst::new( @@ -1532,7 +1523,7 @@ pub fn define( ); let a = &operand("a", &Int.as_bool()); - let Cond = &operand("Cond", intcc); + let Cond = &operand("Cond", &imm.intcc); let x = &operand("x", Int); let y = &operand("y", Int); @@ -1566,7 +1557,7 @@ pub fn define( let a = &operand("a", b1); let x = &operand("x", iB); - let Y = &operand("Y", imm64); + let Y = &operand("Y", &imm.imm64); ig.push( Inst::new( @@ -1757,7 +1748,7 @@ pub fn define( let a = &operand("a", iB); let x = &operand("x", iB); - let Y = &operand("Y", imm64); + let Y = &operand("Y", &imm.imm64); ig.push( Inst::new( @@ -2092,7 +2083,7 @@ pub fn define( ); let x = &operand("x", iB); - let Y = &operand("Y", imm64); + let Y = &operand("Y", &imm.imm64); let a = &operand("a", iB); ig.push( @@ -2145,7 +2136,7 @@ pub fn define( let x = &operand_doc("x", Int, "Scalar or vector value to shift"); let y = &operand_doc("y", iB, "Number of bits to shift"); - let Y = &operand("Y", imm64); + let Y = &operand("Y", &imm.imm64); let a = &operand("a", Int); ig.push( @@ -2375,7 +2366,7 @@ pub fn define( .simd_lanes(Interval::All) .build(), ); - let Cond = &operand("Cond", floatcc); + let Cond = &operand("Cond", &imm.floatcc); let x = &operand("x", Float); let y = &operand("y", Float); let a = &operand("a", &Float.as_bool()); @@ -2687,7 +2678,7 @@ pub fn define( .operands_out(vec![a]), ); - let Cond = &operand("Cond", intcc); + let Cond = &operand("Cond", &imm.intcc); let f = &operand("f", iflags); let a = &operand("a", b1); @@ -2705,7 +2696,7 @@ pub fn define( .operands_out(vec![a]), ); - let Cond = &operand("Cond", floatcc); + let Cond = &operand("Cond", &imm.floatcc); let f = &operand("f", fflags); ig.push( diff --git a/cranelift/codegen/meta/src/shared/legalize.rs b/cranelift/codegen/meta/src/shared/legalize.rs index 709dab7962..ce2faa7720 100644 --- a/cranelift/codegen/meta/src/shared/legalize.rs +++ b/cranelift/codegen/meta/src/shared/legalize.rs @@ -2,12 +2,11 @@ use crate::cdsl::ast::{var, ExprBuilder, Literal}; use crate::cdsl::instructions::{Instruction, InstructionGroup}; use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups}; -use crate::shared::OperandKinds; - +use crate::shared::immediates::Immediates; use crate::shared::types::Float::{F32, F64}; use crate::shared::types::Int::{I16, I32, I64, I8}; -pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformGroups { +pub fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGroups { let mut narrow = TransformGroupBuilder::new( "narrow", r#" @@ -139,12 +138,6 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG expand.custom_legalize(insts.by_name("stack_load"), "expand_stack_load"); expand.custom_legalize(insts.by_name("stack_store"), "expand_stack_store"); - // List of immediates. - let imm64 = immediates.by_name("imm64"); - let ieee32 = immediates.by_name("ieee32"); - let ieee64 = immediates.by_name("ieee64"); - let intcc = immediates.by_name("intcc"); - // List of variables to reuse in patterns. let x = var("x"); let y = var("y"); @@ -298,7 +291,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG } for &(int_ty, num) in &[(I8, 24), (I16, 16)] { - let imm = Literal::constant(imm64, -num); + let imm = Literal::constant(&imm.imm64, -num); widen.legalize( def!(a = clz.int_ty(b)), @@ -322,7 +315,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG } for &(int_ty, num) in &[(I8, 1 << 8), (I16, 1 << 16)] { - let num = Literal::constant(imm64, num); + let num = Literal::constant(&imm.imm64, num); widen.legalize( def!(a = ctz.int_ty(b)), vec![ @@ -423,7 +416,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG } for cc in &["eq", "ne", "ugt", "ult", "uge", "ule"] { - let w_cc = Literal::enumerator_for(intcc, cc); + let w_cc = Literal::enumerator_for(&imm.intcc, cc); widen.legalize( def!(a = icmp_imm.int_ty(w_cc, b, c)), vec![def!(x = uextend.I32(b)), def!(a = icmp_imm(w_cc, x, c))], @@ -439,7 +432,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG } for cc in &["sgt", "slt", "sge", "sle"] { - let w_cc = Literal::enumerator_for(intcc, cc); + let w_cc = Literal::enumerator_for(&imm.intcc, cc); widen.legalize( def!(a = icmp_imm.int_ty(w_cc, b, c)), vec![def!(x = sextend.I32(b)), def!(a = icmp_imm(w_cc, x, c))], @@ -534,7 +527,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG } //# Expand bnot using xor. - let minus_one = Literal::constant(imm64, -1); + let minus_one = Literal::constant(&imm.imm64, -1); expand.legalize( def!(a = bnot(x)), vec![def!(y = iconst(minus_one)), def!(a = bxor(x, y))], @@ -543,82 +536,82 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG //# Expand bitrev //# Adapted from Stack Overflow. //# https://stackoverflow.com/questions/746171/most-efficient-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c - let imm64_1 = Literal::constant(imm64, 1); - let imm64_2 = Literal::constant(imm64, 2); - let imm64_4 = Literal::constant(imm64, 4); + let imm64_1 = Literal::constant(&imm.imm64, 1); + let imm64_2 = Literal::constant(&imm.imm64, 2); + let imm64_4 = Literal::constant(&imm.imm64, 4); widen.legalize( def!(a = bitrev.I8(x)), vec![ - def!(a1 = band_imm(x, Literal::constant(imm64, 0xaa))), + def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaa))), def!(a2 = ushr_imm(a1, imm64_1)), - def!(a3 = band_imm(x, Literal::constant(imm64, 0x55))), + def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x55))), def!(a4 = ishl_imm(a3, imm64_1)), def!(b = bor(a2, a4)), - def!(b1 = band_imm(b, Literal::constant(imm64, 0xcc))), + def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcc))), def!(b2 = ushr_imm(b1, imm64_2)), - def!(b3 = band_imm(b, Literal::constant(imm64, 0x33))), + def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x33))), def!(b4 = ishl_imm(b3, imm64_2)), def!(c = bor(b2, b4)), - def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0))), + def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0))), def!(c2 = ushr_imm(c1, imm64_4)), - def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f))), + def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f))), def!(c4 = ishl_imm(c3, imm64_4)), def!(a = bor(c2, c4)), ], ); - let imm64_8 = Literal::constant(imm64, 8); + let imm64_8 = Literal::constant(&imm.imm64, 8); widen.legalize( def!(a = bitrev.I16(x)), vec![ - def!(a1 = band_imm(x, Literal::constant(imm64, 0xaaaa))), + def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaa))), def!(a2 = ushr_imm(a1, imm64_1)), - def!(a3 = band_imm(x, Literal::constant(imm64, 0x5555))), + def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x5555))), def!(a4 = ishl_imm(a3, imm64_1)), def!(b = bor(a2, a4)), - def!(b1 = band_imm(b, Literal::constant(imm64, 0xcccc))), + def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccc))), def!(b2 = ushr_imm(b1, imm64_2)), - def!(b3 = band_imm(b, Literal::constant(imm64, 0x3333))), + def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x3333))), def!(b4 = ishl_imm(b3, imm64_2)), def!(c = bor(b2, b4)), - def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0f0))), + def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0))), def!(c2 = ushr_imm(c1, imm64_4)), - def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f0f))), + def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f))), def!(c4 = ishl_imm(c3, imm64_4)), def!(d = bor(c2, c4)), - def!(d1 = band_imm(d, Literal::constant(imm64, 0xff00))), + def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00))), def!(d2 = ushr_imm(d1, imm64_8)), - def!(d3 = band_imm(d, Literal::constant(imm64, 0x00ff))), + def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff))), def!(d4 = ishl_imm(d3, imm64_8)), def!(a = bor(d2, d4)), ], ); - let imm64_16 = Literal::constant(imm64, 16); + let imm64_16 = Literal::constant(&imm.imm64, 16); expand.legalize( def!(a = bitrev.I32(x)), vec![ - def!(a1 = band_imm(x, Literal::constant(imm64, 0xaaaaaaaa))), + def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaaaaaa))), def!(a2 = ushr_imm(a1, imm64_1)), - def!(a3 = band_imm(x, Literal::constant(imm64, 0x55555555))), + def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x55555555))), def!(a4 = ishl_imm(a3, imm64_1)), def!(b = bor(a2, a4)), - def!(b1 = band_imm(b, Literal::constant(imm64, 0xcccccccc))), + def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccccccc))), def!(b2 = ushr_imm(b1, imm64_2)), - def!(b3 = band_imm(b, Literal::constant(imm64, 0x33333333))), + def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x33333333))), def!(b4 = ishl_imm(b3, imm64_2)), def!(c = bor(b2, b4)), - def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0f0f0f0))), + def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0f0f0))), def!(c2 = ushr_imm(c1, imm64_4)), - def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f0f0f0f))), + def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f0f0f))), def!(c4 = ishl_imm(c3, imm64_4)), def!(d = bor(c2, c4)), - def!(d1 = band_imm(d, Literal::constant(imm64, 0xff00ff00))), + def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00ff00))), def!(d2 = ushr_imm(d1, imm64_8)), - def!(d3 = band_imm(d, Literal::constant(imm64, 0x00ff00ff))), + def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff00ff))), def!(d4 = ishl_imm(d3, imm64_8)), def!(e = bor(d2, d4)), def!(e1 = ushr_imm(e, imm64_16)), @@ -628,21 +621,21 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG ); #[allow(overflowing_literals)] - let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(imm64, 0xaaaaaaaaaaaaaaaa); - let imm64_0x5555555555555555 = Literal::constant(imm64, 0x5555555555555555); + let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(&imm.imm64, 0xaaaaaaaaaaaaaaaa); + let imm64_0x5555555555555555 = Literal::constant(&imm.imm64, 0x5555555555555555); #[allow(overflowing_literals)] - let imm64_0xcccccccccccccccc = Literal::constant(imm64, 0xcccccccccccccccc); - let imm64_0x3333333333333333 = Literal::constant(imm64, 0x3333333333333333); + let imm64_0xcccccccccccccccc = Literal::constant(&imm.imm64, 0xcccccccccccccccc); + let imm64_0x3333333333333333 = Literal::constant(&imm.imm64, 0x3333333333333333); #[allow(overflowing_literals)] - let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(imm64, 0xf0f0f0f0f0f0f0f0); - let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(imm64, 0x0f0f0f0f0f0f0f0f); + let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(&imm.imm64, 0xf0f0f0f0f0f0f0f0); + let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(&imm.imm64, 0x0f0f0f0f0f0f0f0f); #[allow(overflowing_literals)] - let imm64_0xff00ff00ff00ff00 = Literal::constant(imm64, 0xff00ff00ff00ff00); - let imm64_0x00ff00ff00ff00ff = Literal::constant(imm64, 0x00ff00ff00ff00ff); + let imm64_0xff00ff00ff00ff00 = Literal::constant(&imm.imm64, 0xff00ff00ff00ff00); + let imm64_0x00ff00ff00ff00ff = Literal::constant(&imm.imm64, 0x00ff00ff00ff00ff); #[allow(overflowing_literals)] - let imm64_0xffff0000ffff0000 = Literal::constant(imm64, 0xffff0000ffff0000); - let imm64_0x0000ffff0000ffff = Literal::constant(imm64, 0x0000ffff0000ffff); - let imm64_32 = Literal::constant(imm64, 32); + let imm64_0xffff0000ffff0000 = Literal::constant(&imm.imm64, 0xffff0000ffff0000); + let imm64_0x0000ffff0000ffff = Literal::constant(&imm.imm64, 0x0000ffff0000ffff); + let imm64_32 = Literal::constant(&imm.imm64, 32); expand.legalize( def!(a = bitrev.I64(x)), @@ -680,8 +673,12 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG // Floating-point sign manipulations. for &(ty, const_inst, minus_zero) in &[ - (F32, f32const, &Literal::bits(ieee32, 0x80000000)), - (F64, f64const, &Literal::bits(ieee64, 0x8000000000000000)), + (F32, f32const, &Literal::bits(&imm.ieee32, 0x80000000)), + ( + F64, + f64const, + &Literal::bits(&imm.ieee64, 0x8000000000000000), + ), ] { expand.legalize( def!(a = fabs.ty(x)), @@ -724,9 +721,9 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG ) .chain_with(expand_id); - let imm64_0 = Literal::constant(imm64, 0); - let intcc_ne = Literal::enumerator_for(intcc, "ne"); - let intcc_eq = Literal::enumerator_for(intcc, "eq"); + let imm64_0 = Literal::constant(&imm.imm64, 0); + let intcc_ne = Literal::enumerator_for(&imm.intcc, "ne"); + let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq"); expand_flags.legalize( def!(trapnz(x, c)), diff --git a/cranelift/codegen/meta/src/shared/mod.rs b/cranelift/codegen/meta/src/shared/mod.rs index ba1425b844..837bf3c71d 100644 --- a/cranelift/codegen/meta/src/shared/mod.rs +++ b/cranelift/codegen/meta/src/shared/mod.rs @@ -14,11 +14,13 @@ use crate::cdsl::operands::OperandKind; use crate::cdsl::settings::SettingGroup; use crate::cdsl::xform::TransformGroups; +use crate::shared::immediates::Immediates; + pub struct Definitions { pub settings: SettingGroup, pub all_instructions: AllInstructions, pub instructions: InstructionGroup, - pub operand_kinds: OperandKinds, + pub imm: Immediates, pub format_registry: FormatRegistry, pub transform_groups: TransformGroups, } @@ -26,28 +28,12 @@ pub struct Definitions { pub struct OperandKinds(Vec); impl OperandKinds { - pub fn new() -> Self { - Self(Vec::new()) - } - pub fn by_name(&self, name: &'static str) -> &OperandKind { self.0 .iter() .find(|op| op.name == name) .expect(&format!("unknown Operand name: {}", name)) } - - pub fn push(&mut self, operand_kind: OperandKind) { - assert!( - self.0 - .iter() - .find(|existing| existing.name == operand_kind.name) - .is_none(), - "trying to insert operand kind '{}' for the second time", - operand_kind.name - ); - self.0.push(operand_kind); - } } impl From> for OperandKinds { @@ -59,7 +45,7 @@ impl From> for OperandKinds { pub fn define() -> Definitions { let mut all_instructions = AllInstructions::new(); - let immediates = OperandKinds(immediates::define()); + let immediates = Immediates::new(); let entities = OperandKinds(entities::define()); let format_registry = formats::define(&immediates, &entities); let instructions = instructions::define( @@ -74,7 +60,7 @@ pub fn define() -> Definitions { settings: settings::define(), all_instructions, instructions, - operand_kinds: immediates, + imm: immediates, format_registry, transform_groups, }