Skip to content

Commit b93e8c2

Browse files
committed
Initial reftype support in aarch64, modulo safepoints.
This commit adds the inital support to allow reftypes to flow through the program when targetting aarch64. It also adds a fix to the `ModuleTranslationState` needed to send R32/R64 types over from the SpiderMonkey embedding. This commit does not include any support for safepoints in aarch64 or the `MachInst` infrastructure; that is in the next commit. This commit also makes a drive-by improvement to `Bint`, avoiding an unneeded zero-extension op when the extended value comes directly from a conditional-set (which produces a full-width 0 or 1).
1 parent 4edd165 commit b93e8c2

File tree

6 files changed

+114
-11
lines changed

6 files changed

+114
-11
lines changed

cranelift/codegen/src/isa/aarch64/abi.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ fn in_int_reg(ty: ir::Type) -> bool {
400400
match ty {
401401
types::I8 | types::I16 | types::I32 | types::I64 => true,
402402
types::B1 | types::B8 | types::B16 | types::B32 | types::B64 => true,
403+
types::R32 | types::R64 => true,
403404
_ => false,
404405
}
405406
}
@@ -653,12 +654,12 @@ fn load_stack(mem: MemArg, into_reg: Writable<Reg>, ty: Type) -> Inst {
653654
mem,
654655
srcloc: None,
655656
},
656-
types::B32 | types::I32 => Inst::ULoad32 {
657+
types::B32 | types::I32 | types::R32 => Inst::ULoad32 {
657658
rd: into_reg,
658659
mem,
659660
srcloc: None,
660661
},
661-
types::B64 | types::I64 => Inst::ULoad64 {
662+
types::B64 | types::I64 | types::R64 => Inst::ULoad64 {
662663
rd: into_reg,
663664
mem,
664665
srcloc: None,
@@ -689,12 +690,12 @@ fn store_stack(mem: MemArg, from_reg: Reg, ty: Type) -> Inst {
689690
mem,
690691
srcloc: None,
691692
},
692-
types::B32 | types::I32 => Inst::Store32 {
693+
types::B32 | types::I32 | types::R32 => Inst::Store32 {
693694
rd: from_reg,
694695
mem,
695696
srcloc: None,
696697
},
697-
types::B64 | types::I64 => Inst::Store64 {
698+
types::B64 | types::I64 | types::R64 => Inst::Store64 {
698699
rd: from_reg,
699700
mem,
700701
srcloc: None,

cranelift/codegen/src/isa/aarch64/inst/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use crate::binemit::CodeOffset;
77
use crate::ir::types::{
88
B1, B16, B16X8, B32, B32X4, B64, B64X2, B8, B8X16, F32, F32X2, F32X4, F64, F64X2, FFLAGS, I16,
9-
I16X4, I16X8, I32, I32X2, I32X4, I64, I64X2, I8, I8X16, I8X8, IFLAGS,
9+
I16X4, I16X8, I32, I32X2, I32X4, I64, I64X2, I8, I8X16, I8X8, IFLAGS, R32, R64,
1010
};
1111
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
1212
use crate::machinst::*;
@@ -2081,6 +2081,8 @@ impl MachInst for Inst {
20812081
|| ty == B32
20822082
|| ty == I64
20832083
|| ty == B64
2084+
|| ty == R32
2085+
|| ty == R64
20842086
);
20852087
Inst::load_constant(to_reg, value)
20862088
}
@@ -2102,7 +2104,7 @@ impl MachInst for Inst {
21022104

21032105
fn rc_for_type(ty: Type) -> CodegenResult<RegClass> {
21042106
match ty {
2105-
I8 | I16 | I32 | I64 | B1 | B8 | B16 | B32 | B64 => Ok(RegClass::I64),
2107+
I8 | I16 | I32 | I64 | B1 | B8 | B16 | B32 | B64 | R32 | R64 => Ok(RegClass::I64),
21062108
F32 | F64 => Ok(RegClass::V128),
21072109
IFLAGS | FFLAGS => Ok(RegClass::I64),
21082110
B8X16 | I8X16 | B16X8 | I16X8 | B32X4 | I32X4 | B64X2 | I64X2 | F32X4 | F64X2 => {

cranelift/codegen/src/isa/aarch64/lower.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,8 @@ pub fn ty_bits(ty: Type) -> usize {
829829
B1 => 1,
830830
B8 | I8 => 8,
831831
B16 | I16 => 16,
832-
B32 | I32 | F32 => 32,
833-
B64 | I64 | F64 => 64,
832+
B32 | I32 | F32 | R32 => 32,
833+
B64 | I64 | F64 | R64 => 64,
834834
B128 | I128 => 128,
835835
IFLAGS | FFLAGS => 32,
836836
B8X8 | I8X8 | B16X4 | I16X4 | B32X2 | I32X2 => 64,
@@ -842,7 +842,7 @@ pub fn ty_bits(ty: Type) -> usize {
842842

843843
pub(crate) fn ty_is_int(ty: Type) -> bool {
844844
match ty {
845-
B1 | B8 | I8 | B16 | I16 | B32 | I32 | B64 | I64 => true,
845+
B1 | B8 | I8 | B16 | I16 | B32 | I32 | B64 | I64 | R32 | R64 => true,
846846
F32 | F64 | B128 | I128 | I8X8 | I8X16 | I16X4 | I16X8 | I32X2 | I32X4 | I64X2 => false,
847847
IFLAGS | FFLAGS => panic!("Unexpected flags type"),
848848
_ => panic!("ty_is_int() on unknown type: {:?}", ty),

cranelift/codegen/src/isa/aarch64/lower_inst.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,26 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
12041204
}
12051205

12061206
Opcode::IsNull | Opcode::IsInvalid => {
1207-
panic!("Reference types not supported");
1207+
// Null references are represented by the constant value 0; invalid references are
1208+
// represented by the constant value -1. See `define_reftypes()` in
1209+
// `meta/src/isa/x86/encodings.rs` to confirm.
1210+
let rd = get_output_reg(ctx, outputs[0]);
1211+
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
1212+
let ty = ctx.input_ty(insn, 0);
1213+
let (alu_op, const_value) = match op {
1214+
Opcode::IsNull => {
1215+
// cmp rn, #0
1216+
(choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64), 0)
1217+
}
1218+
Opcode::IsInvalid => {
1219+
// cmn rn, #1
1220+
(choose_32_64(ty, ALUOp::AddS32, ALUOp::AddS64), 1)
1221+
}
1222+
_ => unreachable!(),
1223+
};
1224+
let const_value = ResultRSEImm12::Imm12(Imm12::maybe_from_u64(const_value).unwrap());
1225+
ctx.emit(alu_inst_imm12(alu_op, writable_zero_reg(), rn, const_value));
1226+
ctx.emit(Inst::CSet { rd, cond: Cond::Eq });
12081227
}
12091228

12101229
Opcode::Copy => {
@@ -1215,6 +1234,21 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
12151234
}
12161235

12171236
Opcode::Bint | Opcode::Breduce | Opcode::Bextend | Opcode::Ireduce => {
1237+
// If this is a Bint from a Trueif/Trueff/IsNull/IsInvalid, then the result is already
1238+
// 64-bit-zero-extended, even if the CLIF type doesn't say so, because it was produced
1239+
// by a CSet. In this case, we do not need to do any zero-extension.
1240+
let input_info = ctx.get_input(insn, 0);
1241+
let src_op = input_info
1242+
.inst
1243+
.map(|(src_inst, _)| ctx.data(src_inst).opcode());
1244+
let narrow_mode = match (src_op, op) {
1245+
(Some(Opcode::Trueif), Opcode::Bint)
1246+
| (Some(Opcode::Trueff), Opcode::Bint)
1247+
| (Some(Opcode::IsNull), Opcode::Bint)
1248+
| (Some(Opcode::IsInvalid), Opcode::Bint) => NarrowValueMode::None,
1249+
_ => NarrowValueMode::ZeroExtend64,
1250+
};
1251+
12181252
// All of these ops are simply a move from a zero-extended source.
12191253
// Here is why this works, in each case:
12201254
//
@@ -1227,7 +1261,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
12271261
// - Ireduce: changing width of an integer. Smaller ints are stored
12281262
// with undefined high-order bits, so we can simply do a copy.
12291263

1230-
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
1264+
let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
12311265
let rd = get_output_reg(ctx, outputs[0]);
12321266
let ty = ctx.input_ty(insn, 0);
12331267
ctx.emit(Inst::gen_move(rd, rn, ty));
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
test compile
2+
target aarch64
3+
4+
function %f0(r64) -> r64 {
5+
block0(v0: r64):
6+
return v0
7+
}
8+
9+
; check: stp fp, lr, [sp, #-16]!
10+
; nextln: mov fp, sp
11+
; nextln: mov sp, fp
12+
; nextln: ldp fp, lr, [sp], #16
13+
; nextln: ret
14+
15+
function %f1(r32) -> r32 {
16+
block0(v0: r32):
17+
return v0
18+
}
19+
20+
; check: stp fp, lr, [sp, #-16]!
21+
; nextln: mov fp, sp
22+
; nextln: mov sp, fp
23+
; nextln: ldp fp, lr, [sp], #16
24+
; nextln: ret
25+
26+
function %f2(r64) -> b1 {
27+
block0(v0: r64):
28+
v1 = is_null v0
29+
return v1
30+
}
31+
32+
; check: stp fp, lr, [sp, #-16]!
33+
; nextln: mov fp, sp
34+
; nextln: subs xzr, x0, #0
35+
; nextln: cset x0, eq
36+
; nextln: mov sp, fp
37+
; nextln: ldp fp, lr, [sp], #16
38+
; nextln: ret
39+
40+
function %f3(r64) -> b1 {
41+
block0(v0: r64):
42+
v1 = is_invalid v0
43+
return v1
44+
}
45+
46+
; check: stp fp, lr, [sp, #-16]!
47+
; nextln: mov fp, sp
48+
; nextln: adds xzr, x0, #1
49+
; nextln: cset x0, eq
50+
; nextln: mov sp, fp
51+
; nextln: ldp fp, lr, [sp], #16
52+
; nextln: ret
53+
54+
function %f4() -> r64 {
55+
block0:
56+
v0 = null.r64
57+
return v0
58+
}
59+
60+
; check: stp fp, lr, [sp, #-16]!
61+
; nextln: mov fp, sp
62+
; nextln: movz x0, #0
63+
; nextln: mov sp, fp
64+
; nextln: ldp fp, lr, [sp], #16
65+
; nextln: ret

cranelift/wasm/src/state/module_state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn cranelift_to_wasmparser_type(ty: Type) -> WasmResult<wasmparser::Type> {
3030
types::I64 => wasmparser::Type::I64,
3131
types::F32 => wasmparser::Type::F32,
3232
types::F64 => wasmparser::Type::F64,
33+
types::R32 | types::R64 => wasmparser::Type::ExternRef,
3334
_ => {
3435
return Err(WasmError::Unsupported(format!(
3536
"Cannot convert Cranelift type to Wasm signature: {:?}",

0 commit comments

Comments
 (0)