Codegen: Add ref.is_invalid instruction
Spidermonkey returns a sentinel ref value of '-1' from some VM functions to indicate failure. This commit adds an instruction analagous to ref.is_null that checks for this value.
This commit is contained in:
@@ -2329,10 +2329,12 @@ fn define_reftypes(e: &mut PerCpuModeEncodings, shared_defs: &SharedDefinitions,
|
||||
let shared = &shared_defs.instructions;
|
||||
|
||||
let is_null = shared.by_name("is_null");
|
||||
let is_invalid = shared.by_name("is_invalid");
|
||||
let null = shared.by_name("null");
|
||||
let safepoint = shared.by_name("safepoint");
|
||||
|
||||
let rec_is_zero = r.template("is_zero");
|
||||
let rec_is_invalid = r.template("is_invalid");
|
||||
let rec_pu_id_ref = r.template("pu_id_ref");
|
||||
let rec_safepoint = r.recipe("safepoint");
|
||||
|
||||
@@ -2345,6 +2347,9 @@ fn define_reftypes(e: &mut PerCpuModeEncodings, shared_defs: &SharedDefinitions,
|
||||
// is_null, implemented by testing whether the value is 0.
|
||||
e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(&TEST_REG));
|
||||
|
||||
// is_invalid, implemented by testing whether the value is -1.
|
||||
e.enc_r32_r64_rex_only(is_invalid, rec_is_invalid.opcodes(&CMP_IMM8).rrr(7));
|
||||
|
||||
// safepoint instruction calls sink, no actual encoding.
|
||||
e.enc32_rec(safepoint, rec_safepoint, 0);
|
||||
e.enc64_rec(safepoint, rec_safepoint, 0);
|
||||
|
||||
@@ -3222,6 +3222,26 @@ pub(crate) fn define<'shared>(
|
||||
),
|
||||
);
|
||||
|
||||
recipes.add_template_recipe(
|
||||
EncodingRecipeBuilder::new("is_invalid", &formats.unary, 2 + 3)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![abcd])
|
||||
.emit(
|
||||
r#"
|
||||
// Comparison instruction.
|
||||
{{PUT_OP}}(bits, rex1(in_reg0), sink);
|
||||
modrm_r_bits(in_reg0, bits, sink);
|
||||
sink.put1(0xff);
|
||||
// `setCC` instruction, no REX.
|
||||
use crate::ir::condcodes::IntCC::*;
|
||||
let setcc = 0x90 | icc2opc(Equal);
|
||||
sink.put1(0x0f);
|
||||
sink.put1(setcc as u8);
|
||||
modrm_rr(out_reg0, 0, sink);
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
recipes.add_recipe(
|
||||
EncodingRecipeBuilder::new("safepoint", &formats.multiary, 0).emit(
|
||||
r#"
|
||||
|
||||
@@ -3190,6 +3190,24 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let a = &Operand::new("a", b1);
|
||||
let x = &Operand::new("x", Ref);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"is_invalid",
|
||||
r#"
|
||||
Reference verification.
|
||||
|
||||
The condition code determines if the reference type in question is
|
||||
invalid or not.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Cond = &Operand::new("Cond", &imm.intcc);
|
||||
let f = &Operand::new("f", iflags);
|
||||
let a = &Operand::new("a", b1);
|
||||
|
||||
Reference in New Issue
Block a user