blob: 4211b0a5999213e70b854094cf576104bc0aa624 [file] [log] [blame]
//===-- RegisterValue.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_UTILITY_REGISTERVALUE_H
#define LLDB_UTILITY_REGISTERVALUE_H
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/StringRef.h"
#include <cstdint>
#include <cstring>
#include <utility>
namespace lldb_private {
class DataExtractor;
class Stream;
struct RegisterInfo;
class RegisterValue {
public:
// big enough to support up to 256 byte AArch64 SVE
enum { kMaxRegisterByteSize = 256u };
enum Type {
eTypeInvalid,
eTypeUInt8,
eTypeUInt16,
eTypeUInt32,
eTypeUInt64,
eTypeUInt128,
eTypeFloat,
eTypeDouble,
eTypeLongDouble,
eTypeBytes
};
RegisterValue()
: m_type(eTypeInvalid), m_scalar(static_cast<unsigned long>(0)) {}
explicit RegisterValue(uint8_t inst) : m_type(eTypeUInt8) { m_scalar = inst; }
explicit RegisterValue(uint16_t inst) : m_type(eTypeUInt16) {
m_scalar = inst;
}
explicit RegisterValue(uint32_t inst) : m_type(eTypeUInt32) {
m_scalar = inst;
}
explicit RegisterValue(uint64_t inst) : m_type(eTypeUInt64) {
m_scalar = inst;
}
explicit RegisterValue(llvm::APInt inst) : m_type(eTypeUInt128) {
m_scalar = llvm::APInt(std::move(inst));
}
explicit RegisterValue(float value) : m_type(eTypeFloat) { m_scalar = value; }
explicit RegisterValue(double value) : m_type(eTypeDouble) {
m_scalar = value;
}
explicit RegisterValue(long double value) : m_type(eTypeLongDouble) {
m_scalar = value;
}
explicit RegisterValue(llvm::ArrayRef<uint8_t> bytes,
lldb::ByteOrder byte_order) {
SetBytes(bytes.data(), bytes.size(), byte_order);
}
RegisterValue::Type GetType() const { return m_type; }
bool CopyValue(const RegisterValue &rhs);
void SetType(RegisterValue::Type type) { m_type = type; }
RegisterValue::Type SetType(const RegisterInfo *reg_info);
bool GetData(DataExtractor &data) const;
// Copy the register value from this object into a buffer in "dst" and obey
// the "dst_byte_order" when copying the data. Also watch out in case
// "dst_len" is longer or shorter than the register value described by
// "reg_info" and only copy the least significant bytes of the register
// value, or pad the destination with zeroes if the register byte size is
// shorter that "dst_len" (all while correctly abiding the "dst_byte_order").
// Returns the number of bytes copied into "dst".
uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst,
uint32_t dst_len, lldb::ByteOrder dst_byte_order,
Status &error) const;
uint32_t SetFromMemoryData(const RegisterInfo *reg_info, const void *src,
uint32_t src_len, lldb::ByteOrder src_byte_order,
Status &error);
bool GetScalarValue(Scalar &scalar) const;
uint8_t GetAsUInt8(uint8_t fail_value = UINT8_MAX,
bool *success_ptr = nullptr) const {
if (m_type == eTypeUInt8) {
if (success_ptr)
*success_ptr = true;
return m_scalar.UChar(fail_value);
}
if (success_ptr)
*success_ptr = true;
return fail_value;
}
uint16_t GetAsUInt16(uint16_t fail_value = UINT16_MAX,
bool *success_ptr = nullptr) const;
uint32_t GetAsUInt32(uint32_t fail_value = UINT32_MAX,
bool *success_ptr = nullptr) const;
uint64_t GetAsUInt64(uint64_t fail_value = UINT64_MAX,
bool *success_ptr = nullptr) const;
llvm::APInt GetAsUInt128(const llvm::APInt &fail_value,
bool *success_ptr = nullptr) const;
float GetAsFloat(float fail_value = 0.0f, bool *success_ptr = nullptr) const;
double GetAsDouble(double fail_value = 0.0,
bool *success_ptr = nullptr) const;
long double GetAsLongDouble(long double fail_value = 0.0,
bool *success_ptr = nullptr) const;
void SetValueToInvalid() { m_type = eTypeInvalid; }
bool ClearBit(uint32_t bit);
bool SetBit(uint32_t bit);
bool operator==(const RegisterValue &rhs) const;
bool operator!=(const RegisterValue &rhs) const;
void operator=(uint8_t uint) {
m_type = eTypeUInt8;
m_scalar = uint;
}
void operator=(uint16_t uint) {
m_type = eTypeUInt16;
m_scalar = uint;
}
void operator=(uint32_t uint) {
m_type = eTypeUInt32;
m_scalar = uint;
}
void operator=(uint64_t uint) {
m_type = eTypeUInt64;
m_scalar = uint;
}
void operator=(llvm::APInt uint) {
m_type = eTypeUInt128;
m_scalar = llvm::APInt(std::move(uint));
}
void operator=(float f) {
m_type = eTypeFloat;
m_scalar = f;
}
void operator=(double f) {
m_type = eTypeDouble;
m_scalar = f;
}
void operator=(long double f) {
m_type = eTypeLongDouble;
m_scalar = f;
}
void SetUInt8(uint8_t uint) {
m_type = eTypeUInt8;
m_scalar = uint;
}
void SetUInt16(uint16_t uint) {
m_type = eTypeUInt16;
m_scalar = uint;
}
void SetUInt32(uint32_t uint, Type t = eTypeUInt32) {
m_type = t;
m_scalar = uint;
}
void SetUInt64(uint64_t uint, Type t = eTypeUInt64) {
m_type = t;
m_scalar = uint;
}
void SetUInt128(llvm::APInt uint) {
m_type = eTypeUInt128;
m_scalar = std::move(uint);
}
bool SetUInt(uint64_t uint, uint32_t byte_size);
void SetFloat(float f) {
m_type = eTypeFloat;
m_scalar = f;
}
void SetDouble(double f) {
m_type = eTypeDouble;
m_scalar = f;
}
void SetLongDouble(long double f) {
m_type = eTypeLongDouble;
m_scalar = f;
}
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order);
bool SignExtend(uint32_t sign_bitpos);
Status SetValueFromString(const RegisterInfo *reg_info,
llvm::StringRef value_str);
Status SetValueFromString(const RegisterInfo *reg_info,
const char *value_str) = delete;
Status SetValueFromData(const RegisterInfo *reg_info, DataExtractor &data,
lldb::offset_t offset, bool partial_data_ok);
const void *GetBytes() const;
lldb::ByteOrder GetByteOrder() const {
if (m_type == eTypeBytes)
return buffer.byte_order;
return endian::InlHostByteOrder();
}
uint32_t GetByteSize() const;
static uint32_t GetMaxByteSize() { return kMaxRegisterByteSize; }
void Clear();
protected:
RegisterValue::Type m_type;
Scalar m_scalar;
struct {
mutable uint8_t
bytes[kMaxRegisterByteSize]; // This must be big enough to hold any
// register for any supported target.
uint16_t length;
lldb::ByteOrder byte_order;
} buffer;
};
} // namespace lldb_private
#endif // LLDB_UTILITY_REGISTERVALUE_H