8289046: Undefined Behaviour in x86 class Assembler

Reviewed-by: shade, kvn
This commit is contained in:
Andrew Haley 2022-08-01 08:57:49 +00:00
parent d61c0c79cf
commit 86ef7b20eb
7 changed files with 105 additions and 49 deletions

View File

@ -534,18 +534,25 @@ static bool is_valid_encoding(int reg_enc) {
static int raw_encode(Register reg) {
assert(reg == noreg || reg->is_valid(), "sanity");
int reg_enc = (intptr_t)reg;
int reg_enc = reg->raw_encoding();
assert(reg_enc == -1 || is_valid_encoding(reg_enc), "sanity");
return reg_enc;
}
static int raw_encode(XMMRegister xmmreg) {
assert(xmmreg == xnoreg || xmmreg->is_valid(), "sanity");
int xmmreg_enc = (intptr_t)xmmreg;
int xmmreg_enc = xmmreg->raw_encoding();
assert(xmmreg_enc == -1 || is_valid_encoding(xmmreg_enc), "sanity");
return xmmreg_enc;
}
static int raw_encode(KRegister kreg) {
assert(kreg == knoreg || kreg->is_valid(), "sanity");
int kreg_enc = kreg->raw_encoding();
assert(kreg_enc == -1 || is_valid_encoding(kreg_enc), "sanity");
return kreg_enc;
}
static int modrm_encoding(int mod, int dst_enc, int src_enc) {
return (mod & 3) << 6 | (dst_enc & 7) << 3 | (src_enc & 7);
}
@ -719,6 +726,22 @@ void Assembler::emit_operand(XMMRegister xmmreg, Register base, XMMRegister xmmi
scale, disp, rspec, /* rip_relative_correction */ 0);
}
void Assembler::emit_operand(KRegister kreg, Address adr,
int rip_relative_correction) {
emit_operand(kreg, adr._base, adr._index, adr._scale, adr._disp,
adr._rspec,
rip_relative_correction);
}
void Assembler::emit_operand(KRegister kreg, Register base, Register index,
Address::ScaleFactor scale, int disp,
RelocationHolder const& rspec,
int rip_relative_correction) {
assert(!index->is_valid() || index != rsp, "illegal addressing mode");
emit_operand_helper(raw_encode(kreg), raw_encode(base), raw_encode(index),
scale, disp, rspec, rip_relative_correction);
}
// Secret local extension to Assembler::WhichOperand:
#define end_pc_operand (_WhichOperand_limit)
@ -2589,7 +2612,7 @@ void Assembler::kmovwl(KRegister dst, Address src) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0x90);
emit_operand((Register)dst, src);
emit_operand(dst, src);
}
void Assembler::kmovwl(Address dst, KRegister src) {
@ -2598,7 +2621,7 @@ void Assembler::kmovwl(Address dst, KRegister src) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false);
vex_prefix(dst, 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0x91);
emit_operand((Register)src, dst);
emit_operand(src, dst);
}
void Assembler::kmovwl(KRegister dst, KRegister src) {
@ -2635,7 +2658,7 @@ void Assembler::kmovql(KRegister dst, Address src) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0x90);
emit_operand((Register)dst, src);
emit_operand(dst, src);
}
void Assembler::kmovql(Address dst, KRegister src) {
@ -2644,7 +2667,7 @@ void Assembler::kmovql(Address dst, KRegister src) {
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false);
vex_prefix(dst, 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes);
emit_int8((unsigned char)0x91);
emit_operand((Register)src, dst);
emit_operand(src, dst);
}
void Assembler::kmovql(KRegister dst, Register src) {

View File

@ -781,6 +781,21 @@ private:
int disp,
RelocationHolder const& rspec);
void emit_operand_helper(KRegister kreg,
int base_enc, int index_enc, Address::ScaleFactor scale,
int disp,
RelocationHolder const& rspec,
int rip_relative_correction = 0);
void emit_operand(KRegister kreg, Address adr,
int rip_relative_correction = 0);
void emit_operand(KRegister kreg,
Register base, Register index, Address::ScaleFactor scale,
int disp,
RelocationHolder const& rspec,
int rip_relative_correction = 0);
void emit_operand(XMMRegister reg, Address adr);
// Immediate-to-memory forms

View File

@ -77,4 +77,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false
#endif
#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#endif // CPU_X86_GLOBALDEFINITIONS_X86_HPP

View File

@ -783,7 +783,7 @@ void MacroAssembler::avx_ghash(Register input_state, Register htbl,
void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Register key, Register counter,
Register len_reg, Register used, Register used_addr, Register saved_encCounter_start) {
const Register rounds = 0;
const Register rounds = rax;
const Register pos = r12;
Label PRELOOP_START, EXIT_PRELOOP, REMAINDER, REMAINDER_16, LOOP, END, EXIT, END_LOOP,

View File

@ -26,6 +26,11 @@
#include "register_x86.hpp"
REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_registers);
REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers);
REGISTER_IMPL_DEFINITION(XMMRegister, XMMRegisterImpl, XMMRegisterImpl::number_of_registers);
REGISTER_IMPL_DEFINITION(KRegister, KRegisterImpl, KRegisterImpl::number_of_registers);
#ifndef AMD64
const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers;
#else
@ -40,7 +45,7 @@ const int ConcreteRegisterImpl::max_kpr = ConcreteRegisterImpl::max_xmm +
KRegisterImpl::max_slots_per_register * KRegisterImpl::number_of_registers;
const char* RegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
#ifndef AMD64
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
#else
@ -52,14 +57,14 @@ const char* RegisterImpl::name() const {
}
const char* FloatRegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
};
return is_valid() ? names[encoding()] : "noreg";
}
const char* XMMRegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
#ifdef AMD64
,"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"

View File

@ -37,14 +37,14 @@ typedef VMRegImpl* VMReg;
class RegisterImpl;
typedef RegisterImpl* Register;
// The implementation of integer registers for the ia32 architecture
inline Register as_Register(int encoding) {
return (Register)(intptr_t) encoding;
}
inline constexpr Register as_Register(int encoding);
class RegisterImpl: public AbstractRegisterImpl {
public:
static constexpr Register first();
public:
enum {
#ifndef AMD64
number_of_registers = 8,
@ -61,17 +61,20 @@ class RegisterImpl: public AbstractRegisterImpl {
Register successor() const { return as_Register(encoding() + 1); }
// construction
inline friend Register as_Register(int encoding);
inline constexpr friend Register as_Register(int encoding);
inline VMReg as_VMReg();
inline VMReg as_VMReg() const;
// accessors
int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
bool has_byte_register() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_byte_registers; }
const char* name() const;
int raw_encoding() const { return this - first(); }
int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
bool has_byte_register() const { return 0 <= raw_encoding() && raw_encoding() < number_of_byte_registers; }
const char *name() const;
};
REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_registers);
// The integer registers of the ia32/amd64 architecture
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
@ -98,48 +101,50 @@ CONSTANT_REGISTER_DECLARATION(Register, r15, (15));
// Use FloatRegister as shortcut
class FloatRegisterImpl;
typedef FloatRegisterImpl* FloatRegister;
typedef const FloatRegisterImpl* FloatRegister;
inline FloatRegister as_FloatRegister(int encoding) {
return (FloatRegister)(intptr_t) encoding;
}
inline constexpr FloatRegister as_FloatRegister(int encoding);
// The implementation of floating point registers for the ia32 architecture
class FloatRegisterImpl: public AbstractRegisterImpl {
public:
static constexpr FloatRegister first();
public:
enum {
number_of_registers = 8
};
// construction
inline friend FloatRegister as_FloatRegister(int encoding);
inline friend constexpr FloatRegister as_FloatRegister(int encoding);
inline VMReg as_VMReg();
inline VMReg as_VMReg() const;
// derived registers, offsets, and addresses
FloatRegister successor() const { return as_FloatRegister(encoding() + 1); }
// accessors
int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
int raw_encoding() const { return this - first(); }
int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
const char* name() const;
};
REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers);
CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg, (-1));
// Use XMMRegister as shortcut
class XMMRegisterImpl;
typedef XMMRegisterImpl* XMMRegister;
inline XMMRegister as_XMMRegister(int encoding) {
return (XMMRegister)(intptr_t)encoding;
}
inline constexpr XMMRegister as_XMMRegister(int encoding);
// The implementation of XMM registers.
class XMMRegisterImpl: public AbstractRegisterImpl {
static constexpr XMMRegister first();
public:
enum {
#ifndef AMD64
@ -152,16 +157,17 @@ class XMMRegisterImpl: public AbstractRegisterImpl {
};
// construction
friend XMMRegister as_XMMRegister(int encoding);
friend constexpr XMMRegister as_XMMRegister(int encoding);
inline VMReg as_VMReg();
inline VMReg as_VMReg() const;
// derived registers, offsets, and addresses
XMMRegister successor() const { return as_XMMRegister(encoding() + 1); }
// accessors
int encoding() const { assert(is_valid(), "invalid register (%d)", (int)(intptr_t)this ); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
int raw_encoding() const { return this - first(); }
int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
const char* name() const;
const char* sub_word_name(int offset) const;
@ -179,6 +185,8 @@ class XMMRegisterImpl: public AbstractRegisterImpl {
};
REGISTER_IMPL_DECLARATION(XMMRegister, XMMRegisterImpl, XMMRegisterImpl::number_of_registers);
// The XMM registers, for P3 and up chips
CONSTANT_REGISTER_DECLARATION(XMMRegister, xnoreg , (-1));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm0 , ( 0));
@ -220,12 +228,12 @@ CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm31, (31));
class KRegisterImpl;
typedef KRegisterImpl* KRegister;
inline KRegister as_KRegister(int encoding) {
return (KRegister)(intptr_t)encoding;
}
inline constexpr KRegister as_KRegister(int encoding);
// The implementation of AVX-3 (AVX-512) opmask registers.
class KRegisterImpl : public AbstractRegisterImpl {
static constexpr KRegister first();
public:
enum {
number_of_registers = 8,
@ -235,19 +243,22 @@ public:
};
// construction
friend KRegister as_KRegister(int encoding);
friend constexpr KRegister as_KRegister(int encoding);
inline VMReg as_VMReg();
inline VMReg as_VMReg() const;
// derived registers, offsets, and addresses
KRegister successor() const { return as_KRegister(encoding() + 1); }
// accessors
int encoding() const { assert(is_valid(), "invalid register (%d)", (int)(intptr_t)this); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
int raw_encoding() const { return this - first(); }
int encoding() const { assert(is_valid(), "invalid register (%d)", (int)raw_encoding()); return raw_encoding(); }
bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
const char* name() const;
};
REGISTER_IMPL_DECLARATION(KRegister, KRegisterImpl, KRegisterImpl::number_of_registers);
// The Mask registers, for AVX3 enabled and up chips
CONSTANT_REGISTER_DECLARATION(KRegister, knoreg, (-1));
CONSTANT_REGISTER_DECLARATION(KRegister, k0, (0));

View File

@ -25,7 +25,7 @@
#ifndef CPU_X86_VMREG_X86_INLINE_HPP
#define CPU_X86_VMREG_X86_INLINE_HPP
inline VMReg RegisterImpl::as_VMReg() {
inline VMReg RegisterImpl::as_VMReg() const {
if( this==noreg ) return VMRegImpl::Bad();
#ifdef AMD64
return VMRegImpl::as_VMReg(encoding() << 1 );
@ -34,15 +34,15 @@ inline VMReg RegisterImpl::as_VMReg() {
#endif // AMD64
}
inline VMReg FloatRegisterImpl::as_VMReg() {
inline VMReg FloatRegisterImpl::as_VMReg() const {
return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr);
}
inline VMReg XMMRegisterImpl::as_VMReg() {
inline VMReg XMMRegisterImpl::as_VMReg() const {
return VMRegImpl::as_VMReg((encoding() << 4) + ConcreteRegisterImpl::max_fpr);
}
inline VMReg KRegisterImpl::as_VMReg() {
inline VMReg KRegisterImpl::as_VMReg() const {
return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_xmm);
}