Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pulley: Implement more of loads/stores #9775

Merged
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions cranelift/codegen/meta/src/pulley.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,31 @@ const EXTENDED_OPS: &[Inst<'_>] = pulley_interpreter::for_each_extended_op!(defi
enum Operand<'a> {
Normal { name: &'a str, ty: &'a str },
Writable { name: &'a str, ty: &'a str },
TrapCode { name: &'a str, ty: &'a str },
Binop { reg: &'a str },
}

impl Inst<'_> {
fn operands(&self) -> impl Iterator<Item = Operand<'_>> {
self.fields.iter().map(|(name, ty)| match (*name, *ty) {
("operands", "BinaryOperands < XReg >") => Operand::Binop { reg: "XReg" },
(name, "RegSet < XReg >") => Operand::Normal {
name,
ty: "VecXReg",
},
("dst", ty) => Operand::Writable { name, ty },
(name, ty) => Operand::Normal { name, ty },
})
self.fields
.iter()
.map(|(name, ty)| match (*name, *ty) {
("operands", "BinaryOperands < XReg >") => Operand::Binop { reg: "XReg" },
(name, "RegSet < XReg >") => Operand::Normal {
name,
ty: "VecXReg",
},
("dst", ty) => Operand::Writable { name, ty },
(name, ty) => Operand::Normal { name, ty },
})
.chain(if self.name.contains("Trap") {
Some(Operand::TrapCode {
name: "code",
ty: "TrapCode",
})
} else {
None
})
}

fn skip(&self) -> bool {
Expand All @@ -54,9 +65,6 @@ impl Inst<'_> {
// Skip special instructions not used in Cranelift.
"XPush32Many" | "XPush64Many" | "XPop32Many" | "XPop64Many" => true,

// The pulley backend has its own trap-with-trap-code.
"Trap" => true,

// Skip more branching-related instructions.
n => n.starts_with("Br"),
}
Expand Down Expand Up @@ -99,6 +107,11 @@ pub fn generate_rust(filename: &str, out_dir: &Path) -> Result<(), Error> {
}
}
}
Operand::TrapCode { name, ty: _ } => {
pat.push_str(name);
pat.push_str(",");
format_string.push_str(&format!(" // trap={{{name}:?}}"));
}
Operand::Binop { reg: _ } => {
pat.push_str("dst, src1, src2,");
format_string.push_str(" {dst}, {src1}, {src2}");
Expand Down Expand Up @@ -150,6 +163,7 @@ pub fn generate_rust(filename: &str, out_dir: &Path) -> Result<(), Error> {
pat.push_str(",");
}
}
Operand::TrapCode { .. } => {}
Operand::Binop { reg: _ } => {
pat.push_str("dst, src1, src2,");
uses.push("src1");
Expand Down Expand Up @@ -195,6 +209,7 @@ pub fn generate_rust(filename: &str, out_dir: &Path) -> Result<(), Error> {

let mut pat = String::new();
let mut args = String::new();
let mut trap = String::new();
for op in inst.operands() {
match op {
Operand::Normal { name, ty: _ } | Operand::Writable { name, ty: _ } => {
Expand All @@ -204,6 +219,11 @@ pub fn generate_rust(filename: &str, out_dir: &Path) -> Result<(), Error> {
args.push_str(name);
args.push_str(",");
}
Operand::TrapCode { name, ty: _ } => {
pat.push_str(name);
pat.push_str(",");
trap.push_str(&format!("sink.add_trap({name});\n"));
}
Operand::Binop { reg: _ } => {
pat.push_str("dst, src1, src2,");
args.push_str(
Expand All @@ -216,6 +236,7 @@ pub fn generate_rust(filename: &str, out_dir: &Path) -> Result<(), Error> {
rust.push_str(&format!(
"
RawInst::{name} {{ {pat} }} => {{
{trap}
pulley_interpreter::encode::{snake_name}(sink, {args})
}}
"
Expand All @@ -241,7 +262,7 @@ pub fn generate_isle(filename: &str, out_dir: &Path) -> Result<(), Error> {
isle.push_str(inst.name);
for op in inst.operands() {
match op {
Operand::Normal { name, ty } => {
Operand::Normal { name, ty } | Operand::TrapCode { name, ty } => {
isle.push_str(&format!("\n ({name} {ty})"));
}
Operand::Writable { name, ty } => {
Expand Down Expand Up @@ -276,7 +297,7 @@ pub fn generate_isle(filename: &str, out_dir: &Path) -> Result<(), Error> {
let mut ops = Vec::new();
for op in inst.operands() {
match op {
Operand::Normal { name, ty } => {
Operand::Normal { name, ty } | Operand::TrapCode { name, ty } => {
isle.push_str(ty);
rule.push_str(name);
ops.push(name);
Expand Down
7 changes: 3 additions & 4 deletions cranelift/codegen/src/isa/pulley_shared/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ where
}

fn gen_load_base_offset(into_reg: Writable<Reg>, base: Reg, offset: i32, ty: Type) -> Self::I {
let offset = i64::from(offset);
let base = XReg::try_from(base).unwrap();
let mem = Amode::RegOffset { base, offset };
Inst::gen_load(into_reg, mem, ty, MemFlags::trusted()).into()
Expand Down Expand Up @@ -365,7 +364,7 @@ where
Inst::gen_load(
writable_fp_reg(),
Amode::SpOffset {
offset: i64::from(incoming_args_diff),
offset: i32::try_from(incoming_args_diff).unwrap(),
},
I64,
MemFlags::trusted(),
Expand Down Expand Up @@ -423,7 +422,7 @@ where
insts.push(
Inst::gen_store(
Amode::SpOffset {
offset: i64::from(stack_size - cur_offset),
offset: i32::try_from(stack_size - cur_offset).unwrap(),
},
Reg::from(reg.to_reg()),
ty,
Expand Down Expand Up @@ -474,7 +473,7 @@ where
Inst::gen_load(
reg.map(Reg::from),
Amode::SpOffset {
offset: i64::from(stack_size - cur_offset),
offset: i32::try_from(stack_size - cur_offset).unwrap(),
},
ty,
MemFlags::trusted(),
Expand Down
48 changes: 28 additions & 20 deletions cranelift/codegen/src/isa/pulley_shared/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@

;;;; Actual Instructions ;;;;

;; Raise a trap.
(Trap (code TrapCode))

;; Trap if `src1 cond src2`.
(TrapIf (cond IntCC) (size OperandSize) (src1 XReg) (src2 XReg) (code TrapCode))

Expand Down Expand Up @@ -77,11 +74,16 @@
;; Load the memory address referenced by `mem` into `dst`.
(LoadAddr (dst WritableXReg) (mem Amode))

;; Loads.
(Load (dst WritableReg) (mem Amode) (ty Type) (flags MemFlags) (ext ExtKind))
;; Load `ty` bytes from memory pointed to by `mem` and store in `dst`.
;;
;; How much is written to the register is defined by `ExtKind`. The `flags`
;; control behavior such as endianness.
(XLoad (dst WritableXReg) (mem Amode) (ty Type) (flags MemFlags) (ext ExtKind))
(FLoad (dst WritableFReg) (mem Amode) (ty Type) (flags MemFlags))

;; Stores.
(Store (mem Amode) (src Reg) (ty Type) (flags MemFlags))
(XStore (mem Amode) (src XReg) (ty Type) (flags MemFlags))
(FStore (mem Amode) (src FReg) (ty Type) (flags MemFlags))

;; A raw pulley instruction generated at compile-time via Pulley's
;; `for_each_op!` macro. This variant has `pulley_*` constructors to
Expand All @@ -104,13 +106,13 @@

(type Amode
(enum
(SpOffset (offset i64))
(RegOffset (base XReg) (offset i64))
(SpOffset (offset i32))
(RegOffset (base XReg) (offset i32))
(Stack (amode StackAMode))
)
)

(type ExtKind (enum None Sign Zero))
(type ExtKind (enum None Sign32 Sign64 Zero32 Zero64))

;;;; Newtypes for Different Register Classes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down Expand Up @@ -345,10 +347,6 @@

;;;; Instruction Constructors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl pulley_trap (TrapCode) SideEffectNoResult)
(rule (pulley_trap code)
(SideEffectNoResult.Inst (MInst.Trap code)))

(decl pulley_trap_if (IntCC OperandSize XReg XReg TrapCode) SideEffectNoResult)
(rule (pulley_trap_if cond size src1 src2 code)
(SideEffectNoResult.Inst (MInst.TrapIf cond size src1 src2 code)))
Expand Down Expand Up @@ -400,15 +398,25 @@
(rule (pulley_br_if_xulteq32 a b taken not_taken)
(SideEffectNoResult.Inst (MInst.BrIfXulteq32 a b taken not_taken)))

(decl pulley_load (Amode Type MemFlags ExtKind) Reg)
(rule (pulley_load amode ty flags ext)
(let ((dst WritableReg (temp_writable_reg ty))
(_ Unit (emit (MInst.Load dst amode ty flags ext))))
(decl pulley_xload (Amode Type MemFlags ExtKind) XReg)
(rule (pulley_xload amode ty flags ext)
(let ((dst WritableXReg (temp_writable_xreg))
(_ Unit (emit (MInst.XLoad dst amode ty flags ext))))
dst))

(decl pulley_xstore (Amode XReg Type MemFlags) SideEffectNoResult)
(rule (pulley_xstore amode src ty flags)
(SideEffectNoResult.Inst (MInst.XStore amode src ty flags)))

(decl pulley_fload (Amode Type MemFlags) FReg)
(rule (pulley_fload amode ty flags)
(let ((dst WritableFReg (temp_writable_freg))
(_ Unit (emit (MInst.FLoad dst amode ty flags))))
dst))

(decl pulley_store (Amode Reg Type MemFlags) SideEffectNoResult)
(rule (pulley_store amode src ty flags)
(SideEffectNoResult.Inst (MInst.Store amode src ty flags)))
(decl pulley_fstore (Amode FReg Type MemFlags) SideEffectNoResult)
(rule (pulley_fstore amode src ty flags)
(SideEffectNoResult.Inst (MInst.FStore amode src ty flags)))

(decl gen_br_table (XReg MachLabel BoxVecMachLabel) Unit)
(rule (gen_br_table idx default labels)
Expand Down
41 changes: 22 additions & 19 deletions cranelift/codegen/src/isa/pulley_shared/inst/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,35 +156,38 @@ impl Amode {
}
}

pub(crate) fn get_base_register(&self) -> Option<Reg> {
pub(crate) fn get_base_register(&self) -> Option<XReg> {
match self {
Amode::RegOffset { base, offset: _ } => Some((*base).into()),
Amode::SpOffset { .. } | Amode::Stack { .. } => Some(stack_reg()),
Amode::SpOffset { .. } | Amode::Stack { .. } => Some(XReg::new(stack_reg()).unwrap()),
}
}

pub(crate) fn get_offset_with_state<P>(&self, state: &EmitState<P>) -> i64
pub(crate) fn get_offset_with_state<P>(&self, state: &EmitState<P>) -> i32
where
P: PulleyTargetKind,
{
match self {
Amode::RegOffset { base: _, offset } | Amode::SpOffset { offset } => *offset,
Amode::Stack { amode } => match amode {
StackAMode::IncomingArg(offset, stack_args_size) => {
let offset = i64::from(*stack_args_size) - *offset;
let frame_layout = state.frame_layout();
let sp_offset = frame_layout.tail_args_size
+ frame_layout.setup_area_size
+ frame_layout.clobber_size
+ frame_layout.fixed_frame_storage_size
+ frame_layout.outgoing_args_size;
i64::from(sp_offset) - offset
}
StackAMode::Slot(offset) => {
offset + i64::from(state.frame_layout().outgoing_args_size)
}
StackAMode::OutgoingArg(offset) => *offset,
},
Amode::Stack { amode } => {
let offset64 = match amode {
StackAMode::IncomingArg(offset, stack_args_size) => {
let offset = i64::from(*stack_args_size) - *offset;
let frame_layout = state.frame_layout();
let sp_offset = frame_layout.tail_args_size
+ frame_layout.setup_area_size
+ frame_layout.clobber_size
+ frame_layout.fixed_frame_storage_size
+ frame_layout.outgoing_args_size;
i64::from(sp_offset) - offset
}
StackAMode::Slot(offset) => {
offset + i64::from(state.frame_layout().outgoing_args_size)
}
StackAMode::OutgoingArg(offset) => *offset,
};
i32::try_from(offset64).unwrap()
}
}
}
}
Expand Down
Loading
Loading