Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
62 changes: 62 additions & 0 deletions cranelift/codegen/meta/src/gen_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,66 @@ fn gen_bitwise_not_builders(fmt: &mut Formatter) {
}
}

/// Emit the `uload8`, `uload16`, `uload32`, `sload8`, `sload16`, `sload32`,
/// `istore8`, `istore16`, and `istore32` `InstBuilder`
/// backwards-compat/convenience methods.
fn gen_extending_load_store_builders(fmt: &mut Formatter) {
for (bits, ty) in [(8, "I8"), (16, "I16"), (32, "I32")] {
for (prefix, ext_method, ext_doc) in [
("u", "uextend", "zero-extend"),
("s", "sextend", "sign-extend"),
] {
// `{u,s}loadN` => `load` + `{u,s}extend`.
let method = format!("{prefix}load{bits}");
let tyvar = format!("iExt{bits}");
fmt.doc_comment(format!(
"Load {bits} bits from memory at ``p + Offset`` and {ext_doc}.\
\n\nThis emits a `load` of the narrow type followed by a \
`{ext_method}`.",
));
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
&format!(
"fn {method}<T1: Into<ir::MemFlagsData>, T2: Into<ir::immediates::Offset32>>(mut self, {tyvar}: crate::ir::Type, MemFlags: T1, p: ir::Value, Offset: T2) -> Value"
),
|fmt| {
fmt.line("let MemFlags = MemFlags.into();");
fmt.line("let Offset = Offset.into();");
fmt.line("let MemFlags = self.data_flow_graph_mut().mem_flags.insert(MemFlags).unwrap();");
fmtln!(
fmt,
"let load = self.build_aux_inst(InstructionData::Load {{ opcode: Opcode::Load, arg: p, flags: MemFlags, offset: Offset }}, types::{ty});"
);
fmt.line("let load = self.data_flow_graph().first_result(load);");
fmtln!(fmt, "self.{ext_method}({tyvar}, load)");
},
);
fmt.empty_line();
}

// `istoreN` => `ireduce` + `store`.
fmt.doc_comment(format!(
"Store the low {bits} bits of ``x`` to memory at ``p + Offset``.\
\n\nThis emits an `ireduce` to the narrow type followed by a `store`.",
));
fmt.line("#[allow(non_snake_case, reason = \"generated code\")]");
fmt.add_block(
&format!(
"fn istore{bits}<T1: Into<ir::MemFlagsData>, T2: Into<ir::immediates::Offset32>>(mut self, MemFlags: T1, x: ir::Value, p: ir::Value, Offset: T2) -> Inst"
),
|fmt| {
fmtln!(
fmt,
"let narrow = self.build_aux_inst(InstructionData::Unary {{ opcode: Opcode::Ireduce, arg: x }}, types::{ty});"
);
fmt.line("let narrow = self.data_flow_graph().first_result(narrow);");
fmt.line("self.store(MemFlags, narrow, p, Offset)");
},
);
fmt.empty_line();
}
}

/// Generate a Builder trait with methods for all instructions.
fn gen_builder(
instructions: &AllInstructions,
Expand Down Expand Up @@ -1631,6 +1691,8 @@ fn gen_builder(
gen_stack_access_builders(fmt);
fmt.empty_line();
gen_bitwise_not_builders(fmt);
fmt.empty_line();
gen_extending_load_store_builders(fmt);
for (i, format) in formats.iter().enumerate() {
gen_format_constructor(format, fmt);
if i + 1 != formats.len() {
Expand Down
188 changes: 0 additions & 188 deletions cranelift/codegen/meta/src/shared/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,194 +788,6 @@ pub(crate) fn define(
.can_store(),
);

let iExt8 = &TypeVar::new(
"iExt8",
"An integer type with more than 8 bits",
TypeSetBuilder::new().ints(16..64).build(),
);

ig.push(
Inst::new(
"uload8",
r#"
Load 8 bits from memory at ``p + Offset`` and zero-extend.

This is equivalent to ``load.i8`` followed by ``uextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt8)])
.can_load(),
);

ig.push(
Inst::new(
"sload8",
r#"
Load 8 bits from memory at ``p + Offset`` and sign-extend.

This is equivalent to ``load.i8`` followed by ``sextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt8)])
.can_load(),
);

ig.push(
Inst::new(
"istore8",
r#"
Store the low 8 bits of ``x`` to memory at ``p + Offset``.

This is equivalent to ``ireduce.i8`` followed by ``store.i8``.
"#,
&formats.store,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("x", iExt8),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.can_store(),
);

let iExt16 = &TypeVar::new(
"iExt16",
"An integer type with more than 16 bits",
TypeSetBuilder::new().ints(32..64).build(),
);

ig.push(
Inst::new(
"uload16",
r#"
Load 16 bits from memory at ``p + Offset`` and zero-extend.

This is equivalent to ``load.i16`` followed by ``uextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt16)])
.can_load(),
);

ig.push(
Inst::new(
"sload16",
r#"
Load 16 bits from memory at ``p + Offset`` and sign-extend.

This is equivalent to ``load.i16`` followed by ``sextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt16)])
.can_load(),
);

ig.push(
Inst::new(
"istore16",
r#"
Store the low 16 bits of ``x`` to memory at ``p + Offset``.

This is equivalent to ``ireduce.i16`` followed by ``store.i16``.
"#,
&formats.store,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("x", iExt16),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.can_store(),
);

let iExt32 = &TypeVar::new(
"iExt32",
"An integer type with more than 32 bits",
TypeSetBuilder::new().ints(64..64).build(),
);

ig.push(
Inst::new(
"uload32",
r#"
Load 32 bits from memory at ``p + Offset`` and zero-extend.

This is equivalent to ``load.i32`` followed by ``uextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt32)])
.can_load(),
);

ig.push(
Inst::new(
"sload32",
r#"
Load 32 bits from memory at ``p + Offset`` and sign-extend.

This is equivalent to ``load.i32`` followed by ``sextend``.
"#,
&formats.load,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.operands_out(&[Operand::new("a", iExt32)])
.can_load(),
);

ig.push(
Inst::new(
"istore32",
r#"
Store the low 32 bits of ``x`` to memory at ``p + Offset``.

This is equivalent to ``ireduce.i32`` followed by ``store.i32``.
"#,
&formats.store,
)
.operands_in(&[
Operand::new("MemFlags", &imm.memflags),
Operand::new("x", iExt32),
Operand::new("p", iAddr),
Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
])
.can_store(),
);
ig.push(
Inst::new(
"stack_switch",
Expand Down
Loading
Loading