[meta] Remove the OperandBuilder, replace it with Operand ctors;

This commit is contained in:
Benjamin Bouvier
2019-10-29 14:44:25 +01:00
parent 2bebc40c16
commit 4632d35196
4 changed files with 263 additions and 310 deletions

View File

@@ -1292,7 +1292,7 @@ impl Into<InstSpec> for BoundInstruction {
mod test { mod test {
use super::*; use super::*;
use crate::cdsl::formats::InstructionFormatBuilder; use crate::cdsl::formats::InstructionFormatBuilder;
use crate::cdsl::operands::{OperandBuilder, OperandKindBuilder, OperandKindFields}; use crate::cdsl::operands::{OperandKindBuilder, OperandKindFields};
use crate::cdsl::typevar::TypeSetBuilder; use crate::cdsl::typevar::TypeSetBuilder;
use crate::shared::types::Int::{I32, I64}; use crate::shared::types::Int::{I32, I64};
@@ -1300,7 +1300,7 @@ mod test {
// Pretend the index string is &'static. // Pretend the index string is &'static.
let name = Box::leak(index.to_string().into_boxed_str()); let name = Box::leak(index.to_string().into_boxed_str());
let kind = OperandKindBuilder::new(name, field).build(); let kind = OperandKindBuilder::new(name, field).build();
let operand = OperandBuilder::new(name, kind).build(); let operand = Operand::new(name, kind);
operand operand
} }

View File

@@ -19,18 +19,30 @@ use crate::cdsl::typevar::TypeVar;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Operand { pub(crate) struct Operand {
pub name: &'static str, pub name: &'static str,
doc: Option<String>, doc: Option<&'static str>,
pub kind: OperandKind, pub kind: OperandKind,
} }
impl Operand { impl Operand {
pub fn new(name: &'static str, kind: impl Into<OperandKind>) -> Self {
Self {
name,
doc: None,
kind: kind.into(),
}
}
pub fn with_doc(mut self, doc: &'static str) -> Self {
self.doc = Some(doc);
self
}
pub fn doc(&self) -> Option<&str> { pub fn doc(&self) -> Option<&str> {
match &self.doc { if let Some(doc) = &self.doc {
Some(doc) => Some(doc), return Some(doc);
None => match &self.kind.fields { }
match &self.kind.fields {
OperandKindFields::TypeVar(tvar) => Some(&tvar.doc), OperandKindFields::TypeVar(tvar) => Some(&tvar.doc),
_ => self.kind.doc(), _ => self.kind.doc(),
},
} }
} }
@@ -85,34 +97,6 @@ impl Operand {
} }
} }
pub(crate) struct OperandBuilder {
name: &'static str,
doc: Option<String>,
kind: OperandKind,
}
impl OperandBuilder {
pub fn new(name: &'static str, kind: OperandKind) -> Self {
Self {
name,
doc: None,
kind,
}
}
pub fn doc(mut self, doc: impl Into<String>) -> Self {
assert!(self.doc.is_none());
self.doc = Some(doc.into());
self
}
pub fn build(self) -> Operand {
Operand {
name: self.name,
doc: self.doc,
kind: self.kind,
}
}
}
type EnumValues = HashMap<&'static str, &'static str>; type EnumValues = HashMap<&'static str, &'static str>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -140,15 +124,15 @@ pub(crate) struct OperandKind {
impl OperandKind { impl OperandKind {
fn doc(&self) -> Option<&str> { fn doc(&self) -> Option<&str> {
match &self.doc { if let Some(doc) = &self.doc {
Some(doc) => Some(&doc), return Some(doc);
None => match &self.fields { }
match &self.fields {
OperandKindFields::TypeVar(type_var) => Some(&type_var.doc), OperandKindFields::TypeVar(type_var) => Some(&type_var.doc),
OperandKindFields::ImmEnum(_) OperandKindFields::ImmEnum(_)
| OperandKindFields::ImmValue | OperandKindFields::ImmValue
| OperandKindFields::EntityRef | OperandKindFields::EntityRef
| OperandKindFields::VariableArgs => None, | OperandKindFields::VariableArgs => None,
},
} }
} }
@@ -265,17 +249,3 @@ impl Into<OperandKind> for &OperandKind {
self.clone() self.clone()
} }
} }
/// Helper to create an operand in definitions files.
pub(crate) fn create_operand(name: &'static str, kind: impl Into<OperandKind>) -> Operand {
OperandBuilder::new(name, kind.into()).build()
}
/// Helper to create an operand with a documentation in definitions files.
pub(crate) fn create_operand_doc(
name: &'static str,
kind: impl Into<OperandKind>,
doc: &'static str,
) -> Operand {
OperandBuilder::new(name, kind.into()).doc(doc).build()
}

View File

@@ -3,7 +3,7 @@
use crate::cdsl::instructions::{ use crate::cdsl::instructions::{
AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder,
}; };
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::operands::Operand;
use crate::cdsl::types::ValueType; use crate::cdsl::types::ValueType;
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
@@ -26,11 +26,11 @@ pub(crate) fn define(
"A scalar integer machine word", "A scalar integer machine word",
TypeSetBuilder::new().ints(32..64).build(), TypeSetBuilder::new().ints(32..64).build(),
); );
let nlo = &operand_doc("nlo", iWord, "Low part of numerator"); let nlo = &Operand::new("nlo", iWord).with_doc("Low part of numerator");
let nhi = &operand_doc("nhi", iWord, "High part of numerator"); let nhi = &Operand::new("nhi", iWord).with_doc("High part of numerator");
let d = &operand_doc("d", iWord, "Denominator"); let d = &Operand::new("d", iWord).with_doc("Denominator");
let q = &operand_doc("q", iWord, "Quotient"); let q = &Operand::new("q", iWord).with_doc("Quotient");
let r = &operand_doc("r", iWord, "Remainder"); let r = &Operand::new("r", iWord).with_doc("Remainder");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -72,10 +72,10 @@ pub(crate) fn define(
.can_trap(true), .can_trap(true),
); );
let argL = &operand("argL", iWord); let argL = &Operand::new("argL", iWord);
let argR = &operand("argR", iWord); let argR = &Operand::new("argR", iWord);
let resLo = &operand("resLo", iWord); let resLo = &Operand::new("resLo", iWord);
let resHi = &operand("resHi", iWord); let resHi = &Operand::new("resHi", iWord);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -123,8 +123,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let a = &operand("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -144,9 +144,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let a = &operand("a", Float); let a = &Operand::new("a", Float);
let y = &operand("y", Float); let y = &Operand::new("y", Float);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -186,7 +186,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", iWord); let x = &Operand::new("x", iWord);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -225,8 +225,8 @@ pub(crate) fn define(
.can_load(true), .can_load(true),
); );
let y = &operand("y", iWord); let y = &Operand::new("y", iWord);
let rflags = &operand("rflags", iflags); let rflags = &Operand::new("rflags", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -271,9 +271,9 @@ pub(crate) fn define(
.includes_scalars(false) .includes_scalars(false)
.build(), .build(),
); );
let a = &operand_doc("a", TxN, "A vector value (i.e. held in an XMM register)"); let a = &Operand::new("a", TxN).with_doc("A vector value (i.e. held in an XMM register)");
let b = &operand_doc("b", TxN, "A vector value (i.e. held in an XMM register)"); let b = &Operand::new("b", TxN).with_doc("A vector value (i.e. held in an XMM register)");
let i = &operand_doc("i", uimm8, "An ordering operand controlling the copying of data from the source to the destination; see PSHUFD in Intel manual for details"); let i = &Operand::new("i", uimm8,).with_doc( "An ordering operand controlling the copying of data from the source to the destination; see PSHUFD in Intel manual for details");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -301,9 +301,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let Idx = &operand_doc("Idx", uimm8, "Lane index"); let Idx = &Operand::new("Idx", uimm8).with_doc("Lane index");
let x = &operand("x", TxN); let x = &Operand::new("x", TxN);
let a = &operand("a", &TxN.lane_of()); let a = &Operand::new("a", &TxN.lane_of());
ig.push( ig.push(
Inst::new( Inst::new(
@@ -329,9 +329,9 @@ pub(crate) fn define(
.includes_scalars(false) .includes_scalars(false)
.build(), .build(),
); );
let x = &operand("x", IBxN); let x = &Operand::new("x", IBxN);
let y = &operand_doc("y", &IBxN.lane_of(), "New lane value"); let y = &Operand::new("y", &IBxN.lane_of()).with_doc("New lane value");
let a = &operand("a", IBxN); let a = &Operand::new("a", IBxN);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -356,9 +356,9 @@ pub(crate) fn define(
.includes_scalars(false) .includes_scalars(false)
.build(), .build(),
); );
let x = &operand("x", FxN); let x = &Operand::new("x", FxN);
let y = &operand_doc("y", &FxN.lane_of(), "New lane value"); let y = &Operand::new("y", &FxN.lane_of()).with_doc("New lane value");
let a = &operand("a", FxN); let a = &Operand::new("a", FxN);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -374,9 +374,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", FxN); let x = &Operand::new("x", FxN);
let y = &operand("y", FxN); let y = &Operand::new("y", FxN);
let a = &operand("a", FxN); let a = &Operand::new("a", FxN);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -422,9 +422,9 @@ pub(crate) fn define(
.build(), .build(),
); );
let x = &operand_doc("x", IxN, "Vector value to shift"); let x = &Operand::new("x", IxN).with_doc("Vector value to shift");
let y = &operand_doc("y", I64x2, "Number of bits to shift"); let y = &Operand::new("y", I64x2).with_doc("Number of bits to shift");
let a = &operand("a", IxN); let a = &Operand::new("a", IxN);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -468,9 +468,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", TxN); let x = &Operand::new("x", TxN);
let y = &operand("y", TxN); let y = &Operand::new("y", TxN);
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
"x86_ptest", "x86_ptest",

View File

@@ -3,7 +3,7 @@
use crate::cdsl::instructions::{ use crate::cdsl::instructions::{
AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder,
}; };
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::operands::Operand;
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};
@@ -113,13 +113,13 @@ pub(crate) fn define(
let MemTo = &TypeVar::copy_from(Mem, "MemTo".to_string()); let MemTo = &TypeVar::copy_from(Mem, "MemTo".to_string());
let addr = &operand("addr", iAddr); let addr = &Operand::new("addr", iAddr);
let c = &operand_doc("c", Testable, "Controlling value to test"); let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
let Cond = &operand("Cond", &imm.intcc); let Cond = &Operand::new("Cond", &imm.intcc);
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let y = &operand("y", iB); let y = &Operand::new("y", iB);
let EBB = &operand_doc("EBB", &entities.ebb, "Destination extended basic block"); let EBB = &Operand::new("EBB", &entities.ebb).with_doc("Destination extended basic block");
let args = &operand_doc("args", &entities.varargs, "EBB arguments"); let args = &Operand::new("args", &entities.varargs).with_doc("EBB arguments");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -218,7 +218,7 @@ pub(crate) fn define(
.is_branch(true), .is_branch(true),
); );
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -232,8 +232,8 @@ pub(crate) fn define(
.is_branch(true), .is_branch(true),
); );
let Cond = &operand("Cond", &imm.floatcc); let Cond = &Operand::new("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &Operand::new("f", fflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -248,9 +248,9 @@ pub(crate) fn define(
); );
// The index into the br_table can be any type; legalizer will convert it to the right type. // The index into the br_table can be any type; legalizer will convert it to the right type.
let x = &operand_doc("x", iB, "index into jump table"); let x = &Operand::new("x", iB).with_doc("index into jump table");
let entry = &operand_doc("entry", iAddr, "entry of jump table"); let entry = &Operand::new("entry", iAddr).with_doc("entry of jump table");
let JT = &operand("JT", &entities.jump_table); let JT = &Operand::new("JT", &entities.jump_table);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -280,8 +280,8 @@ pub(crate) 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::new("x", iAddr).with_doc("index into jump table");
let Size = &operand_doc("Size", &imm.uimm8, "Size in bytes"); let Size = &Operand::new("Size", &imm.uimm8).with_doc("Size in bytes");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -350,7 +350,7 @@ pub(crate) fn define(
.can_store(true), .can_store(true),
); );
let code = &operand("code", &imm.trapcode); let code = &Operand::new("code", &imm.trapcode);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -407,8 +407,8 @@ pub(crate) fn define(
.can_trap(true), .can_trap(true),
); );
let Cond = &operand("Cond", &imm.intcc); let Cond = &Operand::new("Cond", &imm.intcc);
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -422,8 +422,8 @@ pub(crate) fn define(
.can_trap(true), .can_trap(true),
); );
let Cond = &operand("Cond", &imm.floatcc); let Cond = &Operand::new("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &Operand::new("f", fflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -437,7 +437,7 @@ pub(crate) fn define(
.can_trap(true), .can_trap(true),
); );
let rvals = &operand_doc("rvals", &entities.varargs, "return values"); let rvals = &Operand::new("rvals", &entities.varargs).with_doc("return values");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -473,12 +473,9 @@ pub(crate) fn define(
.is_terminator(true), .is_terminator(true),
); );
let FN = &operand_doc( let FN = &Operand::new("FN", &entities.func_ref)
"FN", .with_doc("function to call, declared by `function`");
&entities.func_ref, let args = &Operand::new("args", &entities.varargs).with_doc("call arguments");
"function to call, declared by `function`",
);
let args = &operand_doc("args", &entities.varargs, "call arguments");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -496,8 +493,8 @@ pub(crate) fn define(
.is_call(true), .is_call(true),
); );
let SIG = &operand_doc("SIG", &entities.sig_ref, "function signature"); let SIG = &Operand::new("SIG", &entities.sig_ref).with_doc("function signature");
let callee = &operand_doc("callee", iAddr, "address of function to call"); let callee = &Operand::new("callee", iAddr).with_doc("address of function to call");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -538,13 +535,13 @@ pub(crate) fn define(
.operands_out(vec![addr]), .operands_out(vec![addr]),
); );
let SS = &operand("SS", &entities.stack_slot); let SS = &Operand::new("SS", &entities.stack_slot);
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from base address"); let Offset = &Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address");
let x = &operand_doc("x", Mem, "Value to be stored"); let x = &Operand::new("x", Mem).with_doc("Value to be stored");
let a = &operand_doc("a", Mem, "Value loaded"); let a = &Operand::new("a", Mem).with_doc("Value loaded");
let p = &operand("p", iAddr); let p = &Operand::new("p", iAddr);
let MemFlags = &operand("MemFlags", &imm.memflags); let MemFlags = &Operand::new("MemFlags", &imm.memflags);
let args = &operand_doc("args", &entities.varargs, "Address arguments"); let args = &Operand::new("args", &entities.varargs).with_doc("Address arguments");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -613,8 +610,8 @@ pub(crate) fn define(
"An integer type with more than 8 bits", "An integer type with more than 8 bits",
TypeSetBuilder::new().ints(16..64).build(), TypeSetBuilder::new().ints(16..64).build(),
); );
let x = &operand("x", iExt8); let x = &Operand::new("x", iExt8);
let a = &operand("a", iExt8); let a = &Operand::new("a", iExt8);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -709,8 +706,8 @@ pub(crate) fn define(
"An integer type with more than 16 bits", "An integer type with more than 16 bits",
TypeSetBuilder::new().ints(32..64).build(), TypeSetBuilder::new().ints(32..64).build(),
); );
let x = &operand("x", iExt16); let x = &Operand::new("x", iExt16);
let a = &operand("a", iExt16); let a = &Operand::new("a", iExt16);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -805,8 +802,8 @@ pub(crate) fn define(
"An integer type with more than 32 bits", "An integer type with more than 32 bits",
TypeSetBuilder::new().ints(64..64).build(), TypeSetBuilder::new().ints(64..64).build(),
); );
let x = &operand("x", iExt32); let x = &Operand::new("x", iExt32);
let a = &operand("a", iExt32); let a = &Operand::new("a", iExt32);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -896,9 +893,10 @@ pub(crate) fn define(
.can_store(true), .can_store(true),
); );
let x = &operand_doc("x", Mem, "Value to be stored"); let x = &Operand::new("x", Mem).with_doc("Value to be stored");
let a = &operand_doc("a", Mem, "Value loaded"); let a = &Operand::new("a", Mem).with_doc("Value loaded");
let Offset = &operand_doc("Offset", &imm.offset32, "In-bounds offset into stack slot"); let Offset =
&Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -955,7 +953,7 @@ pub(crate) fn define(
.operands_out(vec![addr]), .operands_out(vec![addr]),
); );
let GV = &operand("GV", &entities.global_value); let GV = &Operand::new("GV", &entities.global_value);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -987,9 +985,9 @@ pub(crate) fn define(
TypeSetBuilder::new().ints(32..64).build(), TypeSetBuilder::new().ints(32..64).build(),
); );
let H = &operand("H", &entities.heap); let H = &Operand::new("H", &entities.heap);
let p = &operand("p", HeapOffset); let p = &Operand::new("p", HeapOffset);
let Size = &operand_doc("Size", &imm.uimm32, "Size in bytes"); let Size = &Operand::new("Size", &imm.uimm32).with_doc("Size in bytes");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1046,9 +1044,10 @@ pub(crate) fn define(
"An unsigned table offset", "An unsigned table offset",
TypeSetBuilder::new().ints(32..64).build(), TypeSetBuilder::new().ints(32..64).build(),
); );
let T = &operand("T", &entities.table); let T = &Operand::new("T", &entities.table);
let p = &operand("p", TableOffset); let p = &Operand::new("p", TableOffset);
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from element address"); let Offset =
&Operand::new("Offset", &imm.offset32).with_doc("Byte offset from element address");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1072,8 +1071,8 @@ pub(crate) fn define(
.operands_out(vec![addr]), .operands_out(vec![addr]),
); );
let N = &operand("N", &imm.imm64); let N = &Operand::new("N", &imm.imm64);
let a = &operand_doc("a", Int, "A constant integer scalar or vector value"); let a = &Operand::new("a", Int).with_doc("A constant integer scalar or vector value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1090,8 +1089,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let N = &operand("N", &imm.ieee32); let N = &Operand::new("N", &imm.ieee32);
let a = &operand_doc("a", f32_, "A constant f32 scalar value"); let a = &Operand::new("a", f32_).with_doc("A constant f32 scalar value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1107,8 +1106,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let N = &operand("N", &imm.ieee64); let N = &Operand::new("N", &imm.ieee64);
let a = &operand_doc("a", f64_, "A constant f64 scalar value"); let a = &Operand::new("a", f64_).with_doc("A constant f64 scalar value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1124,8 +1123,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let N = &operand("N", &imm.boolean); let N = &Operand::new("N", &imm.boolean);
let a = &operand_doc("a", Bool, "A constant boolean scalar or vector value"); let a = &Operand::new("a", Bool).with_doc("A constant boolean scalar or vector value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1142,12 +1141,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let N = &operand_doc( let N = &Operand::new("N", &imm.pool_constant)
"N", .with_doc("The 16 immediate bytes of a 128-bit vector");
&imm.pool_constant, let a = &Operand::new("a", TxN).with_doc("A constant vector value");
"The 16 immediate bytes of a 128-bit vector",
);
let a = &operand_doc("a", TxN, "A constant vector value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1163,11 +1159,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let mask = &operand_doc( let mask = &Operand::new("mask", &imm.uimm128)
"mask", .with_doc("The 16 immediate bytes used for selecting the elements to shuffle");
&imm.uimm128,
"The 16 immediate bytes used for selecting the elements to shuffle",
);
let Tx16 = &TypeVar::new( let Tx16 = &TypeVar::new(
"Tx16", "Tx16",
"A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \ "A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \
@@ -1179,8 +1172,8 @@ pub(crate) fn define(
.includes_scalars(false) .includes_scalars(false)
.build(), .build(),
); );
let a = &operand_doc("a", Tx16, "A vector value"); let a = &Operand::new("a", Tx16).with_doc("A vector value");
let b = &operand_doc("b", Tx16, "A vector value"); let b = &Operand::new("b", Tx16).with_doc("A vector value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1199,7 +1192,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Ref, "A constant reference null value"); let a = &Operand::new("a", Ref).with_doc("A constant reference null value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1224,10 +1217,10 @@ pub(crate) fn define(
&formats.nullary, &formats.nullary,
)); ));
let c = &operand_doc("c", Testable, "Controlling value to test"); let c = &Operand::new("c", Testable).with_doc("Controlling value to test");
let x = &operand_doc("x", Any, "Value to use when `c` is true"); let x = &Operand::new("x", Any).with_doc("Value to use when `c` is true");
let y = &operand_doc("y", Any, "Value to use when `c` is false"); let y = &Operand::new("y", Any).with_doc("Value to use when `c` is false");
let a = &operand("a", Any); let a = &Operand::new("a", Any);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1244,8 +1237,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let cc = &operand_doc("cc", &imm.intcc, "Controlling condition code"); let cc = &Operand::new("cc", &imm.intcc).with_doc("Controlling condition code");
let flags = &operand_doc("flags", iflags, "The machine's flag register"); let flags = &Operand::new("flags", iflags).with_doc("The machine's flag register");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1259,7 +1252,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let c = &operand_doc("c", Any, "Controlling value to test"); let c = &Operand::new("c", Any).with_doc("Controlling value to test");
ig.push( ig.push(
Inst::new( Inst::new(
"bitselect", "bitselect",
@@ -1276,7 +1269,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", Any); let x = &Operand::new("x", Any);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1346,8 +1339,8 @@ pub(crate) fn define(
.can_load(true), .can_load(true),
); );
let src = &operand("src", &imm.regunit); let src = &Operand::new("src", &imm.regunit);
let dst = &operand("dst", &imm.regunit); let dst = &Operand::new("dst", &imm.regunit);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1420,7 +1413,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let delta = &operand("delta", Int); let delta = &Operand::new("delta", Int);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1436,7 +1429,7 @@ pub(crate) fn define(
.other_side_effects(true), .other_side_effects(true),
); );
let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer"); let Offset = &Operand::new("Offset", &imm.imm64).with_doc("Offset from current stack pointer");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1454,7 +1447,7 @@ pub(crate) fn define(
.other_side_effects(true), .other_side_effects(true),
); );
let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer"); let Offset = &Operand::new("Offset", &imm.imm64).with_doc("Offset from current stack pointer");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1473,7 +1466,7 @@ pub(crate) fn define(
.other_side_effects(true), .other_side_effects(true),
); );
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1528,11 +1521,8 @@ pub(crate) fn define(
.other_side_effects(true), .other_side_effects(true),
); );
let N = &operand_doc( let N =
"args", &Operand::new("args", &entities.varargs).with_doc("Variable number of args for Stackmap");
&entities.varargs,
"Variable number of args for Stackmap",
);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1547,9 +1537,9 @@ pub(crate) fn define(
.other_side_effects(true), .other_side_effects(true),
); );
let x = &operand_doc("x", TxN, "Vector to split"); let x = &Operand::new("x", TxN).with_doc("Vector to split");
let lo = &operand_doc("lo", &TxN.half_vector(), "Low-numbered lanes of `x`"); let lo = &Operand::new("lo", &TxN.half_vector()).with_doc("Low-numbered lanes of `x`");
let hi = &operand_doc("hi", &TxN.half_vector(), "High-numbered lanes of `x`"); let hi = &Operand::new("hi", &TxN.half_vector()).with_doc("High-numbered lanes of `x`");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1580,9 +1570,9 @@ pub(crate) fn define(
.build(), .build(),
); );
let x = &operand_doc("x", Any128, "Low-numbered lanes"); let x = &Operand::new("x", Any128).with_doc("Low-numbered lanes");
let y = &operand_doc("y", Any128, "High-numbered lanes"); let y = &Operand::new("y", Any128).with_doc("High-numbered lanes");
let a = &operand_doc("a", &Any128.double_vector(), "Concatenation of `x` and `y`"); let a = &Operand::new("a", &Any128.double_vector()).with_doc("Concatenation of `x` and `y`");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1604,10 +1594,10 @@ pub(crate) fn define(
.is_ghost(true), .is_ghost(true),
); );
let c = &operand_doc("c", &TxN.as_bool(), "Controlling vector"); let c = &Operand::new("c", &TxN.as_bool()).with_doc("Controlling vector");
let x = &operand_doc("x", TxN, "Value to use where `c` is true"); let x = &Operand::new("x", TxN).with_doc("Value to use where `c` is true");
let y = &operand_doc("y", TxN, "Value to use where `c` is false"); let y = &Operand::new("y", TxN).with_doc("Value to use where `c` is false");
let a = &operand("a", TxN); let a = &Operand::new("a", TxN);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1624,7 +1614,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let s = &operand("s", b1); let s = &Operand::new("s", b1);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1654,7 +1644,7 @@ pub(crate) fn define(
.operands_out(vec![s]), .operands_out(vec![s]),
); );
let x = &operand("x", &TxN.lane_of()); let x = &Operand::new("x", &TxN.lane_of());
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1670,9 +1660,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand_doc("x", TxN, "SIMD vector to modify"); let x = &Operand::new("x", TxN).with_doc("SIMD vector to modify");
let y = &operand_doc("y", &TxN.lane_of(), "New lane value"); let y = &Operand::new("y", &TxN.lane_of()).with_doc("New lane value");
let Idx = &operand_doc("Idx", &imm.uimm8, "Lane index"); let Idx = &Operand::new("Idx", &imm.uimm8).with_doc("Lane index");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1689,8 +1679,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", TxN); let x = &Operand::new("x", TxN);
let a = &operand("a", &TxN.lane_of()); let a = &Operand::new("a", &TxN.lane_of());
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1709,10 +1699,10 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand("a", &Int.as_bool()); let a = &Operand::new("a", &Int.as_bool());
let Cond = &operand("Cond", &imm.intcc); let Cond = &Operand::new("Cond", &imm.intcc);
let x = &operand("x", Int); let x = &Operand::new("x", Int);
let y = &operand("y", Int); let y = &Operand::new("y", Int);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1748,9 +1738,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand("a", b1); let a = &Operand::new("a", b1);
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let Y = &operand("Y", &imm.imm64); let Y = &Operand::new("Y", &imm.imm64);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1770,9 +1760,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let y = &operand("y", iB); let y = &Operand::new("y", iB);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -1804,9 +1794,9 @@ pub(crate) fn define(
.operands_out(vec![f]), .operands_out(vec![f]),
); );
let a = &operand("a", Int); let a = &Operand::new("a", Int);
let x = &operand("x", Int); let x = &Operand::new("x", Int);
let y = &operand("y", Int); let y = &Operand::new("y", Int);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2028,9 +2018,9 @@ pub(crate) fn define(
.can_trap(true), .can_trap(true),
); );
let a = &operand("a", iB); let a = &Operand::new("a", iB);
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let Y = &operand("Y", &imm.imm64); let Y = &Operand::new("Y", &imm.imm64);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2141,19 +2131,19 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand("a", iB); let a = &Operand::new("a", iB);
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let y = &operand("y", iB); let y = &Operand::new("y", iB);
let c_in = &operand_doc("c_in", b1, "Input carry flag"); let c_in = &Operand::new("c_in", b1).with_doc("Input carry flag");
let c_out = &operand_doc("c_out", b1, "Output carry flag"); let c_out = &Operand::new("c_out", b1).with_doc("Output carry flag");
let b_in = &operand_doc("b_in", b1, "Input borrow flag"); let b_in = &Operand::new("b_in", b1).with_doc("Input borrow flag");
let b_out = &operand_doc("b_out", b1, "Output borrow flag"); let b_out = &Operand::new("b_out", b1).with_doc("Output borrow flag");
let c_if_in = &operand("c_in", iflags); let c_if_in = &Operand::new("c_in", iflags);
let c_if_out = &operand("c_out", iflags); let c_if_out = &Operand::new("c_out", iflags);
let b_if_in = &operand("b_in", iflags); let b_if_in = &Operand::new("b_in", iflags);
let b_if_out = &operand("b_out", iflags); let b_if_out = &Operand::new("b_out", iflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2426,9 +2416,9 @@ pub(crate) fn define(
.includes_scalars(true) .includes_scalars(true)
.build(), .build(),
); );
let x = &operand("x", bits); let x = &Operand::new("x", bits);
let y = &operand("y", bits); let y = &Operand::new("y", bits);
let a = &operand("a", bits); let a = &Operand::new("a", bits);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2520,9 +2510,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let Y = &operand("Y", &imm.imm64); let Y = &Operand::new("Y", &imm.imm64);
let a = &operand("a", iB); let a = &Operand::new("a", iB);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2575,10 +2565,10 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand_doc("x", Int, "Scalar or vector value to shift"); let x = &Operand::new("x", Int).with_doc("Scalar or vector value to shift");
let y = &operand_doc("y", iB, "Number of bits to shift"); let y = &Operand::new("y", iB).with_doc("Number of bits to shift");
let Y = &operand("Y", &imm.imm64); let Y = &Operand::new("Y", &imm.imm64);
let a = &operand("a", Int); let a = &Operand::new("a", Int);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2735,8 +2725,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", iB); let x = &Operand::new("x", iB);
let a = &operand("a", iB); let a = &Operand::new("a", iB);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2822,10 +2812,10 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let Cond = &operand("Cond", &imm.floatcc); let Cond = &Operand::new("Cond", &imm.floatcc);
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let y = &operand("y", Float); let y = &Operand::new("y", Float);
let a = &operand("a", &Float.as_bool()); let a = &Operand::new("a", &Float.as_bool());
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2897,7 +2887,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let f = &operand("f", fflags); let f = &Operand::new("f", fflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2914,10 +2904,10 @@ pub(crate) fn define(
.operands_out(vec![f]), .operands_out(vec![f]),
); );
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let y = &operand("y", Float); let y = &Operand::new("y", Float);
let z = &operand("z", Float); let z = &Operand::new("z", Float);
let a = &operand_doc("a", Float, "Result of applying operator to each lane"); let a = &Operand::new("a", Float).with_doc("Result of applying operator to each lane");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -2998,7 +2988,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Float, "``x`` with its sign bit inverted"); let a = &Operand::new("a", Float).with_doc("``x`` with its sign bit inverted");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3014,7 +3004,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Float, "``x`` with its sign bit cleared"); let a = &Operand::new("a", Float).with_doc("``x`` with its sign bit cleared");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3030,11 +3020,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc( let a = &Operand::new("a", Float).with_doc("``x`` with its sign bit changed to that of ``y``");
"a",
Float,
"``x`` with its sign bit changed to that of ``y``",
);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3051,7 +3037,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Float, "The smaller of ``x`` and ``y``"); let a = &Operand::new("a", Float).with_doc("The smaller of ``x`` and ``y``");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3067,7 +3053,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Float, "The larger of ``x`` and ``y``"); let a = &Operand::new("a", Float).with_doc("The larger of ``x`` and ``y``");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3083,7 +3069,7 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", Float, "``x`` rounded to integral value"); let a = &Operand::new("a", Float).with_doc("``x`` rounded to integral value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3134,8 +3120,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand("a", b1); let a = &Operand::new("a", b1);
let x = &operand("x", Ref); let x = &Operand::new("x", Ref);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3152,9 +3138,9 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let Cond = &operand("Cond", &imm.intcc); let Cond = &Operand::new("Cond", &imm.intcc);
let f = &operand("f", iflags); let f = &Operand::new("f", iflags);
let a = &operand("a", b1); let a = &Operand::new("a", b1);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3171,8 +3157,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let Cond = &operand("Cond", &imm.floatcc); let Cond = &Operand::new("Cond", &imm.floatcc);
let f = &operand("f", fflags); let f = &Operand::new("f", fflags);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3189,8 +3175,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", Mem); let x = &Operand::new("x", Mem);
let a = &operand_doc("a", MemTo, "Bits of `x` reinterpreted"); let a = &Operand::new("a", MemTo).with_doc("Bits of `x` reinterpreted");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3208,8 +3194,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", Any); let x = &Operand::new("x", Any);
let a = &operand_doc("a", AnyTo, "Bits of `x` reinterpreted"); let a = &Operand::new("a", AnyTo).with_doc("Bits of `x` reinterpreted");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3231,8 +3217,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let a = &operand_doc("a", TxN, "A vector value"); let a = &Operand::new("a", TxN).with_doc("A vector value");
let s = &operand_doc("s", &TxN.lane_of(), "A scalar value"); let s = &Operand::new("s", &TxN.lane_of()).with_doc("A scalar value");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3268,8 +3254,8 @@ pub(crate) fn define(
.build(), .build(),
); );
let x = &operand("x", Bool); let x = &Operand::new("x", Bool);
let a = &operand("a", BoolTo); let a = &Operand::new("a", BoolTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3296,8 +3282,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Bool); let x = &Operand::new("x", Bool);
let a = &operand("a", BoolTo); let a = &Operand::new("a", BoolTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3324,8 +3310,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Bool); let x = &Operand::new("x", Bool);
let a = &operand("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3374,8 +3360,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Int); let x = &Operand::new("x", Int);
let a = &operand("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3406,8 +3392,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Int); let x = &Operand::new("x", Int);
let a = &operand("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3459,8 +3445,8 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let a = &operand("a", FloatTo); let a = &Operand::new("a", FloatTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3508,8 +3494,8 @@ pub(crate) fn define(
.constraints(vec![WiderOrEq(Float.clone(), FloatTo.clone())]), .constraints(vec![WiderOrEq(Float.clone(), FloatTo.clone())]),
); );
let x = &operand("x", Float); let x = &Operand::new("x", Float);
let a = &operand("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3576,8 +3562,8 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let x = &operand("x", Int); let x = &Operand::new("x", Int);
let a = &operand("a", FloatTo); let a = &Operand::new("a", FloatTo);
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3621,9 +3607,9 @@ pub(crate) fn define(
.simd_lanes(Interval::All) .simd_lanes(Interval::All)
.build(), .build(),
); );
let x = &operand("x", WideInt); let x = &Operand::new("x", WideInt);
let lo = &operand_doc("lo", &WideInt.half_width(), "The low bits of `x`"); let lo = &Operand::new("lo", &WideInt.half_width()).with_doc("The low bits of `x`");
let hi = &operand_doc("hi", &WideInt.half_width(), "The high bits of `x`"); let hi = &Operand::new("hi", &WideInt.half_width()).with_doc("The high bits of `x`");
ig.push( ig.push(
Inst::new( Inst::new(
@@ -3653,13 +3639,10 @@ pub(crate) fn define(
.build(), .build(),
); );
let lo = &operand("lo", NarrowInt); let lo = &Operand::new("lo", NarrowInt);
let hi = &operand("hi", NarrowInt); let hi = &Operand::new("hi", NarrowInt);
let a = &operand_doc( let a = &Operand::new("a", &NarrowInt.double_width())
"a", .with_doc("The concatenation of `lo` and `hi`");
&NarrowInt.double_width(),
"The concatenation of `lo` and `hi`",
);
ig.push( ig.push(
Inst::new( Inst::new(