diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs index 45224ba8f6..12dd4de0e4 100644 --- a/cranelift/codegen/meta/src/isa/x86/encodings.rs +++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs @@ -2179,6 +2179,7 @@ fn define_entity_ref( let formats = &shared_defs.formats; // Shorthands for instructions. + let const_addr = shared.by_name("const_addr"); let func_addr = shared.by_name("func_addr"); let stack_addr = shared.by_name("stack_addr"); let symbol_value = shared.by_name("symbol_value"); @@ -2188,6 +2189,7 @@ fn define_entity_ref( let rec_allones_fnaddr8 = r.template("allones_fnaddr8"); let rec_fnaddr4 = r.template("fnaddr4"); let rec_fnaddr8 = r.template("fnaddr8"); + let rec_const_addr = r.template("const_addr"); let rec_got_fnaddr8 = r.template("got_fnaddr8"); let rec_got_gvaddr8 = r.template("got_gvaddr8"); let rec_gvaddr4 = r.template("gvaddr4"); @@ -2285,6 +2287,10 @@ fn define_entity_ref( // don't get legalized to stack_addr + load/store. e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(&LEA)); e.enc64(stack_addr.bind(I64), rec_spaddr8_id.opcodes(&LEA).rex().w()); + + // Constant addresses (PIC). + e.enc64(const_addr.bind(I64), rec_const_addr.opcodes(&LEA).rex().w()); + e.enc32(const_addr.bind(I32), rec_const_addr.opcodes(&LEA)); } /// Control flow opcodes. diff --git a/cranelift/codegen/meta/src/isa/x86/recipes.rs b/cranelift/codegen/meta/src/isa/x86/recipes.rs index c42979f5ac..0af1dd29a3 100644 --- a/cranelift/codegen/meta/src/isa/x86/recipes.rs +++ b/cranelift/codegen/meta/src/isa/x86/recipes.rs @@ -1463,6 +1463,21 @@ pub(crate) fn define<'shared>( ), ); + // Constant addresses. + + recipes.add_template_recipe( + EncodingRecipeBuilder::new("const_addr", &formats.unary_const, 5) + .operands_out(vec![gpr]) + .clobbers_flags(false) + .emit( + r#" + {{PUT_OP}}(bits, rex2(0, out_reg0), sink); + modrm_riprel(out_reg0, sink); + const_disp4(constant_handle, func, sink); + "#, + ), + ); + // Store recipes. { diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 0666c2456c..c9a1de311b 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -1542,6 +1542,21 @@ pub(crate) fn define( .operands_out(vec![a]), ); + let constant = + &Operand::new("constant", &imm.pool_constant).with_doc("A constant in the constant pool"); + let address = &Operand::new("address", iAddr); + ig.push( + Inst::new( + "const_addr", + r#" + Calculate the base address of a value in the constant pool. + "#, + &formats.unary_const, + ) + .operands_in(vec![constant]) + .operands_out(vec![address]), + ); + let mask = &Operand::new("mask", &imm.uimm128) .with_doc("The 16 immediate bytes used for selecting the elements to shuffle"); let Tx16 = &TypeVar::new( diff --git a/cranelift/filetests/filetests/isa/x86/simd-vconst-binemit.clif b/cranelift/filetests/filetests/isa/x86/simd-vconst-binemit.clif index 7ffe0c8cc5..787c993a81 100644 --- a/cranelift/filetests/filetests/isa/x86/simd-vconst-binemit.clif +++ b/cranelift/filetests/filetests/isa/x86/simd-vconst-binemit.clif @@ -19,3 +19,11 @@ block0: [-, %xmm3] v1 = vconst.i32x4 const43 ; bin: 0f 10 1d 00000011 PCRelRodata4(31) return } + +function %address_of_vconst() { +const42 = i32x4 [1 0 0 0] + +block0: +[-, %rax] v0 = const_addr.i64 const42 ; bin: 48 8d 05 00000001 PCRelRodata4(8) + return +}