8276563: Undefined Behaviour in class Assembler

Reviewed-by: jvernee, stuefe
This commit is contained in:
Andrew Haley 2022-01-18 15:27:18 +00:00
parent d175d33f44
commit 64c0c0e109
8 changed files with 96 additions and 50 deletions

@ -1726,7 +1726,7 @@ void mvnw(Register Rd, Register Rm,
#define INSN(NAME, op) \
void NAME(Register Rn, Register Rm, int imm, Condition cond) { \
int regNumber = (Rm == zr ? 31 : (uintptr_t)Rm); \
int regNumber = (Rm == zr ? 31 : Rm->encoding()); \
conditional_compare(op, 0, 0, 0, Rn, regNumber, imm, cond); \
} \
\

@ -45,7 +45,7 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const {
const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const {
oop abi_oop = JNIHandles::resolve_non_null(jabi);
ABIDescriptor abi;
const Register (*to_Register)(int) = as_Register;
constexpr Register (*to_Register)(int) = as_Register;
objArrayOop inputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.inputStorage_offset));
loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register);

@ -67,4 +67,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define NOT_R18_RESERVED(code) code
#endif
#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#endif // CPU_AARCH64_GLOBALDEFINITIONS_AARCH64_HPP

@ -186,7 +186,7 @@ VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
if (jvmci_reg < RegisterImpl::number_of_registers) {
return as_Register(jvmci_reg)->as_VMReg();
} else {
jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers_for_jvmci;
jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_declared_registers;
if (floatRegisterNumber >= 0 && floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
return as_FloatRegister(floatRegisterNumber)->as_VMReg();
}

@ -26,6 +26,10 @@
#include "precompiled.hpp"
#include "register_aarch64.hpp"
REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_declared_registers);
REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers);
REGISTER_IMPL_DEFINITION(PRegister, PRegisterImpl, PRegisterImpl::number_of_registers);
const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers *
RegisterImpl::max_slots_per_register;
@ -38,7 +42,7 @@ const int ConcreteRegisterImpl::max_pr
PRegisterImpl::number_of_registers * PRegisterImpl::max_slots_per_register;
const char* RegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
"c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7",
"rscratch1", "rscratch2",
"r10", "r11", "r12", "r13", "r14", "r15", "r16",
@ -50,7 +54,7 @@ const char* RegisterImpl::name() const {
}
const char* FloatRegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
@ -60,7 +64,7 @@ const char* FloatRegisterImpl::name() const {
}
const char* PRegisterImpl::name() const {
const char* names[number_of_registers] = {
static const char *const names[number_of_registers] = {
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15"
};

@ -34,42 +34,42 @@ typedef VMRegImpl* VMReg;
// Use Register as shortcut
class RegisterImpl;
typedef RegisterImpl* Register;
typedef const RegisterImpl* Register;
inline const 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 {
number_of_registers = 32,
number_of_byte_registers = 32,
number_of_registers_for_jvmci = 34, // Including SP and ZR.
number_of_declared_registers = 34, // Including SP and ZR.
max_slots_per_register = 2
};
// derived registers, offsets, and addresses
Register successor() const { return as_Register(encoding() + 1); }
const Register successor() const { return this + 1; }
// construction
inline friend const Register as_Register(int encoding);
inline friend constexpr Register as_Register(int encoding);
VMReg as_VMReg();
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; }
int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); }
bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; }
const char* name() const;
int encoding_nocheck() const { return (intptr_t)this; }
int encoding_nocheck() const { return this - first(); }
};
REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_declared_registers);
// The integer registers of the aarch64 architecture
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
CONSTANT_REGISTER_DECLARATION(Register, r0, (0));
CONSTANT_REGISTER_DECLARATION(Register, r1, (1));
CONSTANT_REGISTER_DECLARATION(Register, r2, (2));
@ -126,15 +126,15 @@ const Register dummy_reg = r31_sp;
// 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 architecture
class FloatRegisterImpl: public AbstractRegisterImpl {
public:
static constexpr FloatRegister first();
public:
enum {
number_of_registers = 32,
max_slots_per_register = 8,
@ -144,21 +144,25 @@ class FloatRegisterImpl: public AbstractRegisterImpl {
};
// construction
inline friend FloatRegister as_FloatRegister(int encoding);
inline friend constexpr FloatRegister as_FloatRegister(int encoding);
VMReg as_VMReg();
VMReg as_VMReg() const;
// derived registers, offsets, and addresses
FloatRegister successor() const { return as_FloatRegister((encoding() + 1) % 32); }
FloatRegister successor() const {
return as_FloatRegister((encoding() + 1) % (unsigned)number_of_registers);
}
// accessors
int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; }
int encoding_nocheck() const { return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); }
bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; }
const char* name() const;
int encoding_nocheck() const { return this - first(); }
};
REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers);
// The float registers of the AARCH64 architecture
CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1));
@ -232,13 +236,13 @@ CONSTANT_REGISTER_DECLARATION(FloatRegister, z31 , (31));
class PRegisterImpl;
typedef PRegisterImpl* PRegister;
inline PRegister as_PRegister(int encoding) {
return (PRegister)(intptr_t)encoding;
}
typedef const PRegisterImpl* PRegister;
inline constexpr PRegister as_PRegister(int encoding);
// The implementation of predicate registers for the architecture
class PRegisterImpl: public AbstractRegisterImpl {
static constexpr PRegister first();
public:
enum {
number_of_registers = 16,
@ -252,21 +256,24 @@ class PRegisterImpl: public AbstractRegisterImpl {
};
// construction
inline friend PRegister as_PRegister(int encoding);
inline friend constexpr PRegister as_PRegister(int encoding);
VMReg as_VMReg();
VMReg as_VMReg() const;
// derived registers, offsets, and addresses
PRegister successor() const { return as_PRegister(encoding() + 1); }
PRegister successor() const { return this + 1; }
// accessors
int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; }
int encoding_nocheck() const { return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
bool is_governing() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_governing_registers; }
int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); }
int encoding_nocheck() const { return this - first(); }
bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; }
bool is_governing() const { return first() <= this && this - first() < number_of_governing_registers; }
const char* name() const;
};
REGISTER_IMPL_DECLARATION(PRegister, PRegisterImpl, PRegisterImpl::number_of_registers);
// The predicate registers of SVE.
CONSTANT_REGISTER_DECLARATION(PRegister, pnoreg, (-1));

@ -26,17 +26,17 @@
#ifndef CPU_AARCH64_VMREG_AARCH64_INLINE_HPP
#define CPU_AARCH64_VMREG_AARCH64_INLINE_HPP
inline VMReg RegisterImpl::as_VMReg() {
inline VMReg RegisterImpl::as_VMReg() const {
if( this==noreg ) return VMRegImpl::Bad();
return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register);
}
inline VMReg FloatRegisterImpl::as_VMReg() {
inline VMReg FloatRegisterImpl::as_VMReg() const {
return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) +
ConcreteRegisterImpl::max_gpr);
}
inline VMReg PRegisterImpl::as_VMReg() {
inline VMReg PRegisterImpl::as_VMReg() const {
return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_fpr);
}

@ -45,15 +45,48 @@ class AbstractRegisterImpl {
int value() const { return (int)(intx)this; }
};
// Macros to help define all kinds of registers
#ifndef USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define AS_REGISTER(type,name) ((type)name##_##type##EnumValue)
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
const type name = ((type)value); \
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
const type name = ((type)value); \
enum { name##_##type##EnumValue = (value) }
#define REGISTER_DECLARATION(type, name, value) \
#else // USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define REGISTER_IMPL_DECLARATION(type, impl_type, reg_count) \
inline constexpr type as_ ## type(int encoding) { \
return impl_type::first() + encoding; \
} \
extern impl_type all_ ## type ## s[reg_count + 1] INTERNAL_VISIBILITY; \
inline constexpr type impl_type::first() { return all_ ## type ## s + 1; }
#define REGISTER_IMPL_DEFINITION(type, impl_type, reg_count) \
impl_type all_ ## type ## s[reg_count + 1];
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
constexpr type name = as_ ## type(value);
#endif // USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define REGISTER_DECLARATION(type, name, value) \
const type name = ((type)value)
// For definitions of RegisterImpl* instances. To be redefined in an
// OS-specific way.
#ifdef __GNUC__
#define INTERNAL_VISIBILITY __attribute__ ((visibility ("internal")))
#else
#define INTERNAL_VISIBILITY
#endif
#define REGISTER_DEFINITION(type, name)
#include CPU_HEADER(register)