From 848baa0aa7486ea2ad1a8541f86c5032fcdf6139 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Wed, 27 Nov 2019 14:16:09 -0600 Subject: [PATCH] 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. --- .../codegen/meta/src/isa/x86/encodings.rs | 5 +++++ cranelift/codegen/meta/src/isa/x86/recipes.rs | 20 +++++++++++++++++++ .../codegen/meta/src/shared/instructions.rs | 18 +++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs index 8baa109e5c..bd86715c6a 100644 --- a/cranelift/codegen/meta/src/isa/x86/encodings.rs +++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs @@ -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); diff --git a/cranelift/codegen/meta/src/isa/x86/recipes.rs b/cranelift/codegen/meta/src/isa/x86/recipes.rs index b2ce9e628e..c512e98467 100644 --- a/cranelift/codegen/meta/src/isa/x86/recipes.rs +++ b/cranelift/codegen/meta/src/isa/x86/recipes.rs @@ -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#" diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 5f9a525353..0161096f64 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -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);