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

This commit is contained in:
Benjamin Bouvier
2019-09-04 16:26:55 +02:00
parent bafd79330d
commit 29e3ec51c1
10 changed files with 369 additions and 363 deletions

View File

@@ -230,8 +230,7 @@ pub fn define<'defs>(
-> InstructionPredicateNode { -> InstructionPredicateNode {
let x = var_pool.create("x"); let x = var_pool.create("x");
let y = var_pool.create("y"); let y = var_pool.create("y");
let cc = let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field);
Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field);
Apply::new( Apply::new(
bound_inst.clone().into(), bound_inst.clone().into(),
vec![Expr::Literal(cc), Expr::Var(x), Expr::Var(y)], 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 y = var_pool.create("y");
let dest = var_pool.create("dest"); let dest = var_pool.create("dest");
let args = var_pool.create("args"); let args = var_pool.create("args");
let cc = let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field);
Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field);
Apply::new( Apply::new(
bound_inst.clone().into(), bound_inst.clone().into(),
vec![ vec![

View File

@@ -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::operands::{create_operand as operand, create_operand_doc as operand_doc};
use crate::cdsl::types::ValueType; use crate::cdsl::types::ValueType;
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; 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( pub fn define(
mut all_instructions: &mut AllInstructions, mut all_instructions: &mut AllInstructions,
format_registry: &FormatRegistry, format_registry: &FormatRegistry,
immediates: &Immediates,
) -> InstructionGroup { ) -> InstructionGroup {
let mut ig = InstructionGroupBuilder::new( let mut ig = InstructionGroupBuilder::new(
"x86", "x86",
@@ -249,8 +251,7 @@ pub fn define(
.operands_out(vec![y, rflags]), .operands_out(vec![y, rflags]),
); );
let immediates = OperandKinds::from(immediates::define()); let uimm8 = &immediates.uimm8;
let uimm8 = immediates.by_name("uimm8");
let TxN = &TypeVar::new( let TxN = &TypeVar::new(
"TxN", "TxN",
"A SIMD vector type", "A SIMD vector type",

View File

@@ -58,12 +58,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
let x86_umulx = x86_instructions.by_name("x86_umulx"); let x86_umulx = x86_instructions.by_name("x86_umulx");
let x86_smulx = x86_instructions.by_name("x86_smulx"); let x86_smulx = x86_instructions.by_name("x86_smulx");
// List of immediates. let imm = &shared.imm;
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");
// Division and remainder. // 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 // `ucomiss` or `ucomisd` instruction. The remaining codes need legalization
// patterns. // patterns.
let floatcc_eq = Literal::enumerator_for(floatcc, "eq"); let floatcc_eq = Literal::enumerator_for(&imm.floatcc, "eq");
let floatcc_ord = Literal::enumerator_for(floatcc, "ord"); let floatcc_ord = Literal::enumerator_for(&imm.floatcc, "ord");
let floatcc_ueq = Literal::enumerator_for(floatcc, "ueq"); let floatcc_ueq = Literal::enumerator_for(&imm.floatcc, "ueq");
let floatcc_ne = Literal::enumerator_for(floatcc, "ne"); let floatcc_ne = Literal::enumerator_for(&imm.floatcc, "ne");
let floatcc_uno = Literal::enumerator_for(floatcc, "uno"); let floatcc_uno = Literal::enumerator_for(&imm.floatcc, "uno");
let floatcc_one = Literal::enumerator_for(floatcc, "one"); let floatcc_one = Literal::enumerator_for(&imm.floatcc, "one");
// Equality needs an explicit `ord` test which checks the parity bit. // Equality needs an explicit `ord` test which checks the parity bit.
group.legalize( 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_lt = &Literal::enumerator_for(&imm.floatcc, "lt");
let floatcc_gt = &Literal::enumerator_for(floatcc, "gt"); let floatcc_gt = &Literal::enumerator_for(&imm.floatcc, "gt");
let floatcc_le = &Literal::enumerator_for(floatcc, "le"); let floatcc_le = &Literal::enumerator_for(&imm.floatcc, "le");
let floatcc_ge = &Literal::enumerator_for(floatcc, "ge"); let floatcc_ge = &Literal::enumerator_for(&imm.floatcc, "ge");
let floatcc_ugt = &Literal::enumerator_for(floatcc, "ugt"); let floatcc_ugt = &Literal::enumerator_for(&imm.floatcc, "ugt");
let floatcc_ult = &Literal::enumerator_for(floatcc, "ult"); let floatcc_ult = &Literal::enumerator_for(&imm.floatcc, "ult");
let floatcc_uge = &Literal::enumerator_for(floatcc, "uge"); let floatcc_uge = &Literal::enumerator_for(&imm.floatcc, "uge");
let floatcc_ule = &Literal::enumerator_for(floatcc, "ule"); let floatcc_ule = &Literal::enumerator_for(&imm.floatcc, "ule");
// Inequalities that need to be reversed. // Inequalities that need to be reversed.
for &(cc, rev_cc) in &[ for &(cc, rev_cc) in &[
@@ -165,9 +160,9 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
let r2flags = var("r2flags"); let r2flags = var("r2flags");
let index2 = var("index2"); let index2 = var("index2");
let intcc_eq = Literal::enumerator_for(intcc, "eq"); let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
let imm64_minus_one = Literal::constant(imm64, -1); let imm64_minus_one = Literal::constant(&imm.imm64, -1);
let imm64_63 = Literal::constant(imm64, 63); let imm64_63 = Literal::constant(&imm.imm64, 63);
group.legalize( group.legalize(
def!(a = clz.I64(x)), def!(a = clz.I64(x)),
vec![ 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( group.legalize(
def!(a = clz.I32(x)), def!(a = clz.I32(x)),
vec![ 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( group.legalize(
def!(a = ctz.I64(x)), def!(a = ctz.I64(x)),
vec![ 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( group.legalize(
def!(a = ctz.I32(x)), def!(a = ctz.I32(x)),
vec![ vec![
@@ -232,13 +227,13 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
let qc0F = var("qc0F"); let qc0F = var("qc0F");
let qc01 = var("qc01"); let qc01 = var("qc01");
let imm64_1 = Literal::constant(imm64, 1); let imm64_1 = Literal::constant(&imm.imm64, 1);
let imm64_4 = Literal::constant(imm64, 4); let imm64_4 = Literal::constant(&imm.imm64, 4);
group.legalize( group.legalize(
def!(qv16 = popcnt.I64(qv1)), def!(qv16 = popcnt.I64(qv1)),
vec![ vec![
def!(qv3 = ushr_imm(qv1, imm64_1)), 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!(qv4 = band(qv3, qc77)),
def!(qv5 = isub(qv1, qv4)), def!(qv5 = isub(qv1, qv4)),
def!(qv6 = ushr_imm(qv4, imm64_1)), 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!(qv11 = isub(qv8, qv10)),
def!(qv12 = ushr_imm(qv11, imm64_4)), def!(qv12 = ushr_imm(qv11, imm64_4)),
def!(qv13 = iadd(qv11, qv12)), 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!(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!(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)), def!(lv16 = popcnt.I32(lv1)),
vec![ vec![
def!(lv3 = ushr_imm(lv1, imm64_1)), 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!(lv4 = band(lv3, lc77)),
def!(lv5 = isub(lv1, lv4)), def!(lv5 = isub(lv1, lv4)),
def!(lv6 = ushr_imm(lv4, imm64_1)), 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!(lv11 = isub(lv8, lv10)),
def!(lv12 = ushr_imm(lv11, imm64_4)), def!(lv12 = ushr_imm(lv11, imm64_4)),
def!(lv13 = iadd(lv11, lv12)), 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!(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!(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); .chain_with(shared.transform_groups.by_name("narrow").id);
// SIMD // SIMD
let uimm8_zero = Literal::constant(uimm8, 0x00); let uimm8_zero = Literal::constant(&imm.uimm8, 0x00);
let uimm8_one = Literal::constant(uimm8, 0x01); let uimm8_one = Literal::constant(&imm.uimm8, 0x01);
let ieee64_zero = Literal::constant(ieee64, 0x00); let ieee64_zero = Literal::constant(&imm.ieee64, 0x00);
let b = var("b"); let b = var("b");
let c = var("c"); let c = var("c");
let d = var("d"); let d = var("d");

View File

@@ -20,6 +20,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let inst_group = instructions::define( let inst_group = instructions::define(
&mut shared_defs.all_instructions, &mut shared_defs.all_instructions,
&shared_defs.format_registry, &shared_defs.format_registry,
&shared_defs.imm,
); );
legalize::define(shared_defs, &inst_group); legalize::define(shared_defs, &inst_group);

View File

@@ -332,7 +332,7 @@ pub fn define<'shared>(
) -> RecipeGroup<'shared> { ) -> RecipeGroup<'shared> {
// The set of floating point condition codes that are directly supported. // The set of floating point condition codes that are directly supported.
// Other condition codes need to be reversed or expressed as two tests. // 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<Literal> = ["ord", "uno", "one", "ueq", "gt", "ge", "ult", "ule"] let supported_floatccs: Vec<Literal> = ["ord", "uno", "one", "ueq", "gt", "ge", "ult", "ule"]
.iter() .iter()
.map(|name| Literal::enumerator_for(floatcc, name)) .map(|name| Literal::enumerator_for(floatcc, name))

View File

@@ -1,22 +1,8 @@
use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder}; use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder};
use crate::shared::immediates::Immediates;
use crate::shared::OperandKinds; use crate::shared::OperandKinds;
pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegistry { pub fn define(imm: &Immediates, 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");
// Shorthands for entities. // Shorthands for entities.
let global_value = entities.by_name("global_value"); let global_value = entities.by_name("global_value");
let ebb = entities.by_name("ebb"); let ebb = entities.by_name("ebb");
@@ -30,15 +16,15 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
let mut registry = FormatRegistry::new(); let mut registry = FormatRegistry::new();
registry.insert(Builder::new("Unary").value()); registry.insert(Builder::new("Unary").value());
registry.insert(Builder::new("UnaryImm").imm(imm64)); registry.insert(Builder::new("UnaryImm").imm(&imm.imm64));
registry.insert(Builder::new("UnaryImm128").imm(uimm128)); registry.insert(Builder::new("UnaryImm128").imm(&imm.uimm128));
registry.insert(Builder::new("UnaryIeee32").imm(ieee32)); registry.insert(Builder::new("UnaryIeee32").imm(&imm.ieee32));
registry.insert(Builder::new("UnaryIeee64").imm(ieee64)); registry.insert(Builder::new("UnaryIeee64").imm(&imm.ieee64));
registry.insert(Builder::new("UnaryBool").imm(boolean)); registry.insert(Builder::new("UnaryBool").imm(&imm.boolean));
registry.insert(Builder::new("UnaryGlobalValue").imm(global_value)); registry.insert(Builder::new("UnaryGlobalValue").imm(global_value));
registry.insert(Builder::new("Binary").value().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 select instructions are controlled by the second VALUE operand.
// The first VALUE operand is the controlling flag which has a derived type. // 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( registry.insert(
Builder::new("InsertLane") Builder::new("InsertLane")
.value() .value()
.imm_with_name("lane", uimm8) .imm_with_name("lane", &imm.uimm8)
.value(), .value(),
); );
registry.insert( registry.insert(
Builder::new("ExtractLane") Builder::new("ExtractLane")
.value() .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("IntCompare").imm(&imm.intcc).value().value());
registry.insert(Builder::new("IntCompareImm").imm(intcc).value().imm(imm64)); registry.insert(
registry.insert(Builder::new("IntCond").imm(intcc).value()); 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(
registry.insert(Builder::new("FloatCond").imm(floatcc).value());; 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("Jump").imm(ebb).varargs());
registry.insert(Builder::new("Branch").value().imm(ebb).varargs()); registry.insert(Builder::new("Branch").value().imm(ebb).varargs());
registry.insert( registry.insert(
Builder::new("BranchInt") Builder::new("BranchInt")
.imm(intcc) .imm(&imm.intcc)
.value() .value()
.imm(ebb) .imm(ebb)
.varargs(), .varargs(),
); );
registry.insert( registry.insert(
Builder::new("BranchFloat") Builder::new("BranchFloat")
.imm(floatcc) .imm(&imm.floatcc)
.value() .value()
.imm(ebb) .imm(ebb)
.varargs(), .varargs(),
); );
registry.insert( registry.insert(
Builder::new("BranchIcmp") Builder::new("BranchIcmp")
.imm(intcc) .imm(&imm.intcc)
.value() .value()
.value() .value()
.imm(ebb) .imm(ebb)
@@ -107,7 +109,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
Builder::new("BranchTableEntry") Builder::new("BranchTableEntry")
.value() .value()
.value() .value()
.imm(uimm8) .imm(&imm.uimm8)
.imm(jump_table), .imm(jump_table),
); );
registry.insert(Builder::new("BranchTableBase").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("CallIndirect").imm(sig_ref).value().varargs());
registry.insert(Builder::new("FuncAddr").imm(func_ref)); 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( registry.insert(
Builder::new("LoadComplex") Builder::new("LoadComplex")
.imm(memflags) .imm(&imm.memflags)
.varargs() .varargs()
.imm(offset32), .imm(&imm.offset32),
); );
registry.insert( registry.insert(
Builder::new("Store") Builder::new("Store")
.imm(memflags) .imm(&imm.memflags)
.value() .value()
.value() .value()
.imm(offset32), .imm(&imm.offset32),
); );
registry.insert( registry.insert(
Builder::new("StoreComplex") Builder::new("StoreComplex")
.imm(memflags) .imm(&imm.memflags)
.value() .value()
.varargs() .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( registry.insert(
Builder::new("StackStore") Builder::new("StackStore")
.value() .value()
.imm(stack_slot) .imm(stack_slot)
.imm(offset32), .imm(&imm.offset32),
); );
// Accessing a WebAssembly heap. // 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. // 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( registry.insert(
Builder::new("RegMove") Builder::new("RegMove")
.value() .value()
.imm_with_name("src", regunit) .imm_with_name("src", &imm.regunit)
.imm_with_name("dst", regunit), .imm_with_name("dst", &imm.regunit),
); );
registry.insert( registry.insert(
Builder::new("CopySpecial") Builder::new("CopySpecial")
.imm_with_name("src", regunit) .imm_with_name("src", &imm.regunit)
.imm_with_name("dst", 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( registry.insert(
Builder::new("RegSpill") Builder::new("RegSpill")
.value() .value()
.imm_with_name("src", regunit) .imm_with_name("src", &imm.regunit)
.imm_with_name("dst", stack_slot), .imm_with_name("dst", stack_slot),
); );
registry.insert( registry.insert(
Builder::new("RegFill") Builder::new("RegFill")
.value() .value()
.imm_with_name("src", stack_slot) .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("Trap").imm(&imm.trapcode));
registry.insert(Builder::new("CondTrap").value().imm(trapcode)); registry.insert(Builder::new("CondTrap").value().imm(&imm.trapcode));
registry.insert(Builder::new("IntCondTrap").imm(intcc).value().imm(trapcode)); registry.insert(
Builder::new("IntCondTrap")
.imm(&imm.intcc)
.value()
.imm(&imm.trapcode),
);
registry.insert( registry.insert(
Builder::new("FloatCondTrap") Builder::new("FloatCondTrap")
.imm(floatcc) .imm(&imm.floatcc)
.value() .value()
.imm(trapcode), .imm(&imm.trapcode),
); );
registry registry

View File

@@ -2,82 +2,110 @@ use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder};
use std::collections::HashMap; use std::collections::HashMap;
pub fn define() -> Vec<OperandKind> { pub struct Immediates {
let mut kinds = Vec::new(); /// 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. /// An unsigned 8-bit immediate integer operand.
// ///
// This type of immediate integer can interact with SSA values with any /// This small operand is used to indicate lane indexes in SIMD vectors and immediate bit
// IntType type. /// counts on shift instructions.
let imm64 = Builder::new_imm("imm64") pub uimm8: OperandKind,
/// An unsigned 32-bit immediate integer operand.
pub uimm32: OperandKind,
/// 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,
/// 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 floating point operand.
///
/// IEEE 754-2008 binary32 interchange format.
pub ieee32: OperandKind,
/// A 64-bit immediate floating point operand.
///
/// IEEE 754-2008 binary64 interchange format.
pub ieee64: OperandKind,
/// An immediate boolean operand.
///
/// This type of immediate boolean can interact with SSA values with any BoolType type.
pub boolean: 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.
pub intcc: 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.
pub floatcc: OperandKind,
/// Flags for memory operations like `load` and `store`.
pub memflags: OperandKind,
/// A register unit in the current target ISA.
pub regunit: OperandKind,
/// 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.") .doc("A 64-bit immediate integer.")
.build(); .build(),
kinds.push(imm64);
// An unsigned 8-bit immediate integer operand. uimm8: Builder::new_imm("uimm8")
//
// 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.") .doc("An 8-bit immediate unsigned integer.")
.build(); .build(),
kinds.push(uimm8);
// An unsigned 32-bit immediate integer operand. uimm32: Builder::new_imm("uimm32")
let uimm32 = Builder::new_imm("uimm32")
.doc("A 32-bit immediate unsigned integer.") .doc("A 32-bit immediate unsigned integer.")
.build(); .build(),
kinds.push(uimm32);
// An unsigned 128-bit immediate integer operand. uimm128: Builder::new_imm("uimm128")
//
// 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.") .doc("A 128-bit immediate unsigned integer.")
.rust_type("ir::Constant") .rust_type("ir::Constant")
.build(); .build(),
kinds.push(uimm128);
// A 32-bit immediate signed offset. offset32: Builder::new_imm("offset32")
//
// 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.") .doc("A 32-bit immediate signed offset.")
.default_member("offset") .default_member("offset")
.build(); .build(),
kinds.push(offset32);
// A 32-bit immediate floating point operand. ieee32: Builder::new_imm("ieee32")
//
// IEEE 754-2008 binary32 interchange format.
let ieee32 = Builder::new_imm("ieee32")
.doc("A 32-bit immediate floating point number.") .doc("A 32-bit immediate floating point number.")
.build(); .build(),
kinds.push(ieee32);
// A 64-bit immediate floating point operand. ieee64: Builder::new_imm("ieee64")
//
// IEEE 754-2008 binary64 interchange format.
let ieee64 = Builder::new_imm("ieee64")
.doc("A 64-bit immediate floating point number.") .doc("A 64-bit immediate floating point number.")
.build(); .build(),
kinds.push(ieee64);
// An immediate boolean operand. boolean: Builder::new_imm("boolean")
//
// This type of immediate boolean can interact with SSA values with any
// BoolType type.
let boolean = Builder::new_imm("boolean")
.doc("An immediate boolean.") .doc("An immediate boolean.")
.rust_type("bool") .rust_type("bool")
.build(); .build(),
kinds.push(boolean);
// A condition code for comparing integer values. intcc: {
// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
// condcodes::IntCC` Rust type.
let mut intcc_values = HashMap::new(); let mut intcc_values = HashMap::new();
intcc_values.insert("eq", "Equal"); intcc_values.insert("eq", "Equal");
intcc_values.insert("ne", "NotEqual"); intcc_values.insert("ne", "NotEqual");
@@ -89,15 +117,14 @@ pub fn define() -> Vec<OperandKind> {
intcc_values.insert("ugt", "UnsignedGreaterThan"); intcc_values.insert("ugt", "UnsignedGreaterThan");
intcc_values.insert("ule", "UnsignedLessThanOrEqual"); intcc_values.insert("ule", "UnsignedLessThanOrEqual");
intcc_values.insert("ult", "UnsignedLessThan"); intcc_values.insert("ult", "UnsignedLessThan");
let intcc = Builder::new_enum("intcc", intcc_values) Builder::new_enum("intcc", intcc_values)
.doc("An integer comparison condition code.") .doc("An integer comparison condition code.")
.default_member("cond") .default_member("cond")
.rust_type("ir::condcodes::IntCC") .rust_type("ir::condcodes::IntCC")
.build(); .build()
kinds.push(intcc); },
// A condition code for comparing floating point values. This enumerated operand kind is used floatcc: {
// for the `fcmp` instruction and corresponds to the `condcodes::FloatCC` Rust type.
let mut floatcc_values = HashMap::new(); let mut floatcc_values = HashMap::new();
floatcc_values.insert("ord", "Ordered"); floatcc_values.insert("ord", "Ordered");
floatcc_values.insert("uno", "Unordered"); floatcc_values.insert("uno", "Unordered");
@@ -113,43 +140,36 @@ pub fn define() -> Vec<OperandKind> {
floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual"); floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
floatcc_values.insert("ugt", "UnorderedOrGreaterThan"); floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual"); floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
let floatcc = Builder::new_enum("floatcc", floatcc_values) Builder::new_enum("floatcc", floatcc_values)
.doc("A floating point comparison condition code") .doc("A floating point comparison condition code")
.default_member("cond") .default_member("cond")
.rust_type("ir::condcodes::FloatCC") .rust_type("ir::condcodes::FloatCC")
.build(); .build()
kinds.push(floatcc); },
// Flags for memory operations like :clif:inst:`load` and :clif:inst:`store`. memflags: Builder::new_imm("memflags")
let memflags = Builder::new_imm("memflags")
.doc("Memory operation flags") .doc("Memory operation flags")
.default_member("flags") .default_member("flags")
.rust_type("ir::MemFlags") .rust_type("ir::MemFlags")
.build(); .build(),
kinds.push(memflags);
// A register unit in the current target ISA. regunit: Builder::new_imm("regunit")
let regunit = Builder::new_imm("regunit")
.doc("A register unit in the target ISA") .doc("A register unit in the target ISA")
.rust_type("isa::RegUnit") .rust_type("isa::RegUnit")
.build(); .build(),
kinds.push(regunit);
// A trap code indicating the reason for trapping. trapcode: {
//
// The Rust enum type also has a `User(u16)` variant for user-provided trap
// codes.
let mut trapcode_values = HashMap::new(); let mut trapcode_values = HashMap::new();
trapcode_values.insert("stk_ovf", "StackOverflow"); trapcode_values.insert("stk_ovf", "StackOverflow");
trapcode_values.insert("heap_oob", "HeapOutOfBounds"); trapcode_values.insert("heap_oob", "HeapOutOfBounds");
trapcode_values.insert("int_ovf", "IntegerOverflow"); trapcode_values.insert("int_ovf", "IntegerOverflow");
trapcode_values.insert("int_divz", "IntegerDivisionByZero"); trapcode_values.insert("int_divz", "IntegerDivisionByZero");
let trapcode = Builder::new_enum("trapcode", trapcode_values) Builder::new_enum("trapcode", trapcode_values)
.doc("A trap reason code.") .doc("A trap reason code.")
.default_member("code") .default_member("code")
.rust_type("ir::TrapCode") .rust_type("ir::TrapCode")
.build(); .build()
kinds.push(trapcode); },
}
return kinds; }
} }

View File

@@ -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::type_inference::Constraint::WiderOrEq;
use crate::cdsl::types::{LaneType, ValueType}; use crate::cdsl::types::{LaneType, ValueType};
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
use crate::shared::immediates::Immediates;
use crate::shared::{types, OperandKinds}; use crate::shared::{types, OperandKinds};
pub fn define( pub fn define(
all_instructions: &mut AllInstructions, all_instructions: &mut AllInstructions,
format_registry: &FormatRegistry, format_registry: &FormatRegistry,
immediates: &OperandKinds, imm: &Immediates,
entities: &OperandKinds, entities: &OperandKinds,
) -> InstructionGroup { ) -> InstructionGroup {
let mut ig = InstructionGroupBuilder::new( let mut ig = InstructionGroupBuilder::new(
@@ -24,20 +25,6 @@ pub fn define(
); );
// Operand kind shorthands. // 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 ebb = entities.by_name("ebb");
let jump_table = entities.by_name("jump_table"); let jump_table = entities.by_name("jump_table");
let variable_args = entities.by_name("variable_args"); let variable_args = entities.by_name("variable_args");
@@ -142,7 +129,7 @@ pub fn define(
let addr = &operand("addr", iAddr); let addr = &operand("addr", iAddr);
let c = &operand_doc("c", Testable, "Controlling value to test"); 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 x = &operand("x", iB);
let y = &operand("y", iB); let y = &operand("y", iB);
let EBB = &operand_doc("EBB", ebb, "Destination extended basic block"); let EBB = &operand_doc("EBB", ebb, "Destination extended basic block");
@@ -253,7 +240,7 @@ pub fn define(
.is_branch(true), .is_branch(true),
); );
let Cond = &operand("Cond", floatcc); let Cond = &operand("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &operand("f", fflags);
ig.push( ig.push(
@@ -300,7 +287,7 @@ pub fn define(
// These are the instructions which br_table legalizes to: they perform address computations, // These are the instructions which br_table legalizes to: they perform address computations,
// using pointer-sized integers, so their type variables are more constrained. // using pointer-sized integers, so their type variables are more constrained.
let x = &operand_doc("x", iAddr, "index into jump table"); 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( ig.push(
Inst::new( Inst::new(
@@ -365,7 +352,7 @@ pub fn define(
.can_store(true), .can_store(true),
); );
let code = &operand("code", trapcode); let code = &operand("code", &imm.trapcode);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -418,7 +405,7 @@ pub fn define(
.can_trap(true), .can_trap(true),
); );
let Cond = &operand("Cond", intcc); let Cond = &operand("Cond", &imm.intcc);
let f = &operand("f", iflags); let f = &operand("f", iflags);
ig.push( ig.push(
@@ -432,7 +419,7 @@ pub fn define(
.can_trap(true), .can_trap(true),
); );
let Cond = &operand("Cond", floatcc); let Cond = &operand("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &operand("f", fflags);
ig.push( ig.push(
@@ -539,11 +526,11 @@ pub fn define(
); );
let SS = &operand("SS", stack_slot); 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 x = &operand_doc("x", Mem, "Value to be stored");
let a = &operand_doc("a", Mem, "Value loaded"); let a = &operand_doc("a", Mem, "Value loaded");
let p = &operand("p", iAddr); 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"); let args = &operand_doc("args", variable_args, "Address arguments");
ig.push( ig.push(
@@ -876,7 +863,7 @@ pub fn define(
let x = &operand_doc("x", Mem, "Value to be stored"); let x = &operand_doc("x", Mem, "Value to be stored");
let a = &operand_doc("a", Mem, "Value loaded"); 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( ig.push(
Inst::new( Inst::new(
@@ -962,7 +949,7 @@ pub fn define(
let H = &operand("H", heap); let H = &operand("H", heap);
let p = &operand("p", HeapOffset); 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( ig.push(
Inst::new( Inst::new(
@@ -990,7 +977,7 @@ pub fn define(
); );
let T = &operand("T", table); let T = &operand("T", table);
let p = &operand("p", TableOffset); 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( ig.push(
Inst::new( Inst::new(
@@ -1013,7 +1000,7 @@ pub fn define(
.operands_out(vec![addr]), .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"); let a = &operand_doc("a", Int, "A constant integer scalar or vector value");
ig.push( ig.push(
@@ -1030,7 +1017,7 @@ pub fn define(
.operands_out(vec![a]), .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"); let a = &operand_doc("a", f32_, "A constant f32 scalar value");
ig.push( ig.push(
@@ -1046,7 +1033,7 @@ pub fn define(
.operands_out(vec![a]), .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"); let a = &operand_doc("a", f64_, "A constant f64 scalar value");
ig.push( ig.push(
@@ -1062,7 +1049,7 @@ pub fn define(
.operands_out(vec![a]), .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"); let a = &operand_doc("a", Bool, "A constant boolean scalar or vector value");
ig.push( ig.push(
@@ -1079,7 +1066,11 @@ pub fn define(
.operands_out(vec![a]), .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"); let a = &operand_doc("a", TxN, "A constant vector value");
ig.push( ig.push(
@@ -1137,7 +1128,7 @@ pub fn define(
.operands_out(vec![a]), .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"); let flags = &operand_doc("flags", iflags, "The machine's flag register");
ig.push( ig.push(
@@ -1217,8 +1208,8 @@ pub fn define(
.can_load(true), .can_load(true),
); );
let src = &operand("src", regunit); let src = &operand("src", &imm.regunit);
let dst = &operand("dst", regunit); let dst = &operand("dst", &imm.regunit);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1302,7 +1293,7 @@ pub fn define(
.other_side_effects(true), .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( ig.push(
Inst::new( Inst::new(
@@ -1319,7 +1310,7 @@ pub fn define(
.other_side_effects(true), .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( ig.push(
Inst::new( Inst::new(
@@ -1498,7 +1489,7 @@ pub fn define(
let x = &operand_doc("x", TxN, "SIMD vector to modify"); let x = &operand_doc("x", TxN, "SIMD vector to modify");
let y = &operand_doc("y", &TxN.lane_of(), "New lane value"); 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( ig.push(
Inst::new( Inst::new(
@@ -1532,7 +1523,7 @@ pub fn define(
); );
let a = &operand("a", &Int.as_bool()); let a = &operand("a", &Int.as_bool());
let Cond = &operand("Cond", intcc); let Cond = &operand("Cond", &imm.intcc);
let x = &operand("x", Int); let x = &operand("x", Int);
let y = &operand("y", Int); let y = &operand("y", Int);
@@ -1566,7 +1557,7 @@ pub fn define(
let a = &operand("a", b1); let a = &operand("a", b1);
let x = &operand("x", iB); let x = &operand("x", iB);
let Y = &operand("Y", imm64); let Y = &operand("Y", &imm.imm64);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1757,7 +1748,7 @@ pub fn define(
let a = &operand("a", iB); let a = &operand("a", iB);
let x = &operand("x", iB); let x = &operand("x", iB);
let Y = &operand("Y", imm64); let Y = &operand("Y", &imm.imm64);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2092,7 +2083,7 @@ pub fn define(
); );
let x = &operand("x", iB); let x = &operand("x", iB);
let Y = &operand("Y", imm64); let Y = &operand("Y", &imm.imm64);
let a = &operand("a", iB); let a = &operand("a", iB);
ig.push( ig.push(
@@ -2145,7 +2136,7 @@ pub fn define(
let x = &operand_doc("x", Int, "Scalar or vector value to shift"); 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_doc("y", iB, "Number of bits to shift");
let Y = &operand("Y", imm64); let Y = &operand("Y", &imm.imm64);
let a = &operand("a", Int); let a = &operand("a", Int);
ig.push( ig.push(
@@ -2375,7 +2366,7 @@ pub fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let Cond = &operand("Cond", floatcc); let Cond = &operand("Cond", &imm.floatcc);
let x = &operand("x", Float); let x = &operand("x", Float);
let y = &operand("y", Float); let y = &operand("y", Float);
let a = &operand("a", &Float.as_bool()); let a = &operand("a", &Float.as_bool());
@@ -2687,7 +2678,7 @@ pub fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let Cond = &operand("Cond", intcc); let Cond = &operand("Cond", &imm.intcc);
let f = &operand("f", iflags); let f = &operand("f", iflags);
let a = &operand("a", b1); let a = &operand("a", b1);
@@ -2705,7 +2696,7 @@ pub fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let Cond = &operand("Cond", floatcc); let Cond = &operand("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &operand("f", fflags);
ig.push( ig.push(

View File

@@ -2,12 +2,11 @@ use crate::cdsl::ast::{var, ExprBuilder, Literal};
use crate::cdsl::instructions::{Instruction, InstructionGroup}; use crate::cdsl::instructions::{Instruction, InstructionGroup};
use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups}; 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::Float::{F32, F64};
use crate::shared::types::Int::{I16, I32, I64, I8}; 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( let mut narrow = TransformGroupBuilder::new(
"narrow", "narrow",
r#" 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_load"), "expand_stack_load");
expand.custom_legalize(insts.by_name("stack_store"), "expand_stack_store"); 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. // List of variables to reuse in patterns.
let x = var("x"); let x = var("x");
let y = var("y"); 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)] { for &(int_ty, num) in &[(I8, 24), (I16, 16)] {
let imm = Literal::constant(imm64, -num); let imm = Literal::constant(&imm.imm64, -num);
widen.legalize( widen.legalize(
def!(a = clz.int_ty(b)), 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)] { 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( widen.legalize(
def!(a = ctz.int_ty(b)), def!(a = ctz.int_ty(b)),
vec![ vec![
@@ -423,7 +416,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
} }
for cc in &["eq", "ne", "ugt", "ult", "uge", "ule"] { 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( widen.legalize(
def!(a = icmp_imm.int_ty(w_cc, b, c)), def!(a = icmp_imm.int_ty(w_cc, b, c)),
vec![def!(x = uextend.I32(b)), def!(a = icmp_imm(w_cc, x, 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"] { 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( widen.legalize(
def!(a = icmp_imm.int_ty(w_cc, b, c)), def!(a = icmp_imm.int_ty(w_cc, b, c)),
vec![def!(x = sextend.I32(b)), def!(a = icmp_imm(w_cc, x, 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. //# Expand bnot using xor.
let minus_one = Literal::constant(imm64, -1); let minus_one = Literal::constant(&imm.imm64, -1);
expand.legalize( expand.legalize(
def!(a = bnot(x)), def!(a = bnot(x)),
vec![def!(y = iconst(minus_one)), def!(a = bxor(x, y))], 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 //# Expand bitrev
//# Adapted from Stack Overflow. //# Adapted from Stack Overflow.
//# https://stackoverflow.com/questions/746171/most-efficient-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c //# 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_1 = Literal::constant(&imm.imm64, 1);
let imm64_2 = Literal::constant(imm64, 2); let imm64_2 = Literal::constant(&imm.imm64, 2);
let imm64_4 = Literal::constant(imm64, 4); let imm64_4 = Literal::constant(&imm.imm64, 4);
widen.legalize( widen.legalize(
def!(a = bitrev.I8(x)), def!(a = bitrev.I8(x)),
vec![ 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!(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!(a4 = ishl_imm(a3, imm64_1)),
def!(b = bor(a2, a4)), 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!(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!(b4 = ishl_imm(b3, imm64_2)),
def!(c = bor(b2, b4)), 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!(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!(c4 = ishl_imm(c3, imm64_4)),
def!(a = bor(c2, c4)), def!(a = bor(c2, c4)),
], ],
); );
let imm64_8 = Literal::constant(imm64, 8); let imm64_8 = Literal::constant(&imm.imm64, 8);
widen.legalize( widen.legalize(
def!(a = bitrev.I16(x)), def!(a = bitrev.I16(x)),
vec![ 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!(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!(a4 = ishl_imm(a3, imm64_1)),
def!(b = bor(a2, a4)), 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!(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!(b4 = ishl_imm(b3, imm64_2)),
def!(c = bor(b2, b4)), 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!(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!(c4 = ishl_imm(c3, imm64_4)),
def!(d = bor(c2, c4)), 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!(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!(d4 = ishl_imm(d3, imm64_8)),
def!(a = bor(d2, d4)), def!(a = bor(d2, d4)),
], ],
); );
let imm64_16 = Literal::constant(imm64, 16); let imm64_16 = Literal::constant(&imm.imm64, 16);
expand.legalize( expand.legalize(
def!(a = bitrev.I32(x)), def!(a = bitrev.I32(x)),
vec![ 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!(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!(a4 = ishl_imm(a3, imm64_1)),
def!(b = bor(a2, a4)), 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!(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!(b4 = ishl_imm(b3, imm64_2)),
def!(c = bor(b2, b4)), 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!(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!(c4 = ishl_imm(c3, imm64_4)),
def!(d = bor(c2, c4)), 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!(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!(d4 = ishl_imm(d3, imm64_8)),
def!(e = bor(d2, d4)), def!(e = bor(d2, d4)),
def!(e1 = ushr_imm(e, imm64_16)), def!(e1 = ushr_imm(e, imm64_16)),
@@ -628,21 +621,21 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
); );
#[allow(overflowing_literals)] #[allow(overflowing_literals)]
let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(imm64, 0xaaaaaaaaaaaaaaaa); let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(&imm.imm64, 0xaaaaaaaaaaaaaaaa);
let imm64_0x5555555555555555 = Literal::constant(imm64, 0x5555555555555555); let imm64_0x5555555555555555 = Literal::constant(&imm.imm64, 0x5555555555555555);
#[allow(overflowing_literals)] #[allow(overflowing_literals)]
let imm64_0xcccccccccccccccc = Literal::constant(imm64, 0xcccccccccccccccc); let imm64_0xcccccccccccccccc = Literal::constant(&imm.imm64, 0xcccccccccccccccc);
let imm64_0x3333333333333333 = Literal::constant(imm64, 0x3333333333333333); let imm64_0x3333333333333333 = Literal::constant(&imm.imm64, 0x3333333333333333);
#[allow(overflowing_literals)] #[allow(overflowing_literals)]
let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(imm64, 0xf0f0f0f0f0f0f0f0); let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(&imm.imm64, 0xf0f0f0f0f0f0f0f0);
let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(imm64, 0x0f0f0f0f0f0f0f0f); let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(&imm.imm64, 0x0f0f0f0f0f0f0f0f);
#[allow(overflowing_literals)] #[allow(overflowing_literals)]
let imm64_0xff00ff00ff00ff00 = Literal::constant(imm64, 0xff00ff00ff00ff00); let imm64_0xff00ff00ff00ff00 = Literal::constant(&imm.imm64, 0xff00ff00ff00ff00);
let imm64_0x00ff00ff00ff00ff = Literal::constant(imm64, 0x00ff00ff00ff00ff); let imm64_0x00ff00ff00ff00ff = Literal::constant(&imm.imm64, 0x00ff00ff00ff00ff);
#[allow(overflowing_literals)] #[allow(overflowing_literals)]
let imm64_0xffff0000ffff0000 = Literal::constant(imm64, 0xffff0000ffff0000); let imm64_0xffff0000ffff0000 = Literal::constant(&imm.imm64, 0xffff0000ffff0000);
let imm64_0x0000ffff0000ffff = Literal::constant(imm64, 0x0000ffff0000ffff); let imm64_0x0000ffff0000ffff = Literal::constant(&imm.imm64, 0x0000ffff0000ffff);
let imm64_32 = Literal::constant(imm64, 32); let imm64_32 = Literal::constant(&imm.imm64, 32);
expand.legalize( expand.legalize(
def!(a = bitrev.I64(x)), def!(a = bitrev.I64(x)),
@@ -680,8 +673,12 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
// Floating-point sign manipulations. // Floating-point sign manipulations.
for &(ty, const_inst, minus_zero) in &[ for &(ty, const_inst, minus_zero) in &[
(F32, f32const, &Literal::bits(ieee32, 0x80000000)), (F32, f32const, &Literal::bits(&imm.ieee32, 0x80000000)),
(F64, f64const, &Literal::bits(ieee64, 0x8000000000000000)), (
F64,
f64const,
&Literal::bits(&imm.ieee64, 0x8000000000000000),
),
] { ] {
expand.legalize( expand.legalize(
def!(a = fabs.ty(x)), def!(a = fabs.ty(x)),
@@ -724,9 +721,9 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
) )
.chain_with(expand_id); .chain_with(expand_id);
let imm64_0 = Literal::constant(imm64, 0); let imm64_0 = Literal::constant(&imm.imm64, 0);
let intcc_ne = Literal::enumerator_for(intcc, "ne"); let intcc_ne = Literal::enumerator_for(&imm.intcc, "ne");
let intcc_eq = Literal::enumerator_for(intcc, "eq"); let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
expand_flags.legalize( expand_flags.legalize(
def!(trapnz(x, c)), def!(trapnz(x, c)),

View File

@@ -14,11 +14,13 @@ use crate::cdsl::operands::OperandKind;
use crate::cdsl::settings::SettingGroup; use crate::cdsl::settings::SettingGroup;
use crate::cdsl::xform::TransformGroups; use crate::cdsl::xform::TransformGroups;
use crate::shared::immediates::Immediates;
pub struct Definitions { pub struct Definitions {
pub settings: SettingGroup, pub settings: SettingGroup,
pub all_instructions: AllInstructions, pub all_instructions: AllInstructions,
pub instructions: InstructionGroup, pub instructions: InstructionGroup,
pub operand_kinds: OperandKinds, pub imm: Immediates,
pub format_registry: FormatRegistry, pub format_registry: FormatRegistry,
pub transform_groups: TransformGroups, pub transform_groups: TransformGroups,
} }
@@ -26,28 +28,12 @@ pub struct Definitions {
pub struct OperandKinds(Vec<OperandKind>); pub struct OperandKinds(Vec<OperandKind>);
impl OperandKinds { impl OperandKinds {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn by_name(&self, name: &'static str) -> &OperandKind { pub fn by_name(&self, name: &'static str) -> &OperandKind {
self.0 self.0
.iter() .iter()
.find(|op| op.name == name) .find(|op| op.name == name)
.expect(&format!("unknown Operand 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<Vec<OperandKind>> for OperandKinds { impl From<Vec<OperandKind>> for OperandKinds {
@@ -59,7 +45,7 @@ impl From<Vec<OperandKind>> for OperandKinds {
pub fn define() -> Definitions { pub fn define() -> Definitions {
let mut all_instructions = AllInstructions::new(); let mut all_instructions = AllInstructions::new();
let immediates = OperandKinds(immediates::define()); let immediates = Immediates::new();
let entities = OperandKinds(entities::define()); let entities = OperandKinds(entities::define());
let format_registry = formats::define(&immediates, &entities); let format_registry = formats::define(&immediates, &entities);
let instructions = instructions::define( let instructions = instructions::define(
@@ -74,7 +60,7 @@ pub fn define() -> Definitions {
settings: settings::define(), settings: settings::define(),
all_instructions, all_instructions,
instructions, instructions,
operand_kinds: immediates, imm: immediates,
format_registry, format_registry,
transform_groups, transform_groups,
} }