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:
Ryan Hunt
2019-11-27 14:16:09 -06:00
parent a15bb9cfcb
commit 848baa0aa7
3 changed files with 43 additions and 0 deletions

View File

@@ -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);

View File

@@ -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#"

View File

@@ -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);