mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
155 lines
4.5 KiB
C++
155 lines
4.5 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "revng/Support/Debug.h"
|
|
#include "revng/Support/MetaAddress.h"
|
|
|
|
namespace llvm {
|
|
class Type;
|
|
}
|
|
|
|
/// Class representing either a constant value or an offset from a symbol
|
|
class MaterializedValue {
|
|
public:
|
|
class MemoryRange {
|
|
public:
|
|
MetaAddress Address;
|
|
unsigned Size = 0;
|
|
};
|
|
|
|
private:
|
|
bool IsValid = false;
|
|
std::optional<std::string> SymbolName;
|
|
llvm::APInt Value;
|
|
llvm::SmallVector<MemoryRange, 1> AffectedBy;
|
|
bool IsMutable = false;
|
|
|
|
private:
|
|
MaterializedValue(const llvm::APInt &Value, bool IsMutable) :
|
|
IsValid(true), Value(Value), IsMutable(IsMutable) {}
|
|
MaterializedValue(llvm::StringRef SymbolName, const llvm::APInt &Offset) :
|
|
IsValid(true), SymbolName(SymbolName.str()), Value(Offset) {}
|
|
|
|
public:
|
|
MaterializedValue() = default;
|
|
MaterializedValue(const MaterializedValue &) = default;
|
|
MaterializedValue(MaterializedValue &&) = default;
|
|
MaterializedValue &operator=(const MaterializedValue &) = default;
|
|
MaterializedValue &operator=(MaterializedValue &&) = default;
|
|
|
|
public:
|
|
static MaterializedValue invalid() { return MaterializedValue(); }
|
|
|
|
static MaterializedValue fromMutable(const llvm::APInt &API) {
|
|
return MaterializedValue(API, true);
|
|
}
|
|
|
|
static MaterializedValue fromMutable(llvm::ConstantInt *CI);
|
|
|
|
static MaterializedValue fromConstant(const llvm::APInt &API) {
|
|
return MaterializedValue(API, false);
|
|
}
|
|
|
|
static MaterializedValue fromConstant(llvm::ConstantInt *CI);
|
|
|
|
static MaterializedValue fromSymbol(llvm::StringRef SymbolName,
|
|
const llvm::APInt &Offset) {
|
|
return MaterializedValue(SymbolName, Offset);
|
|
}
|
|
|
|
static MaterializedValue apply(llvm::Instruction *Operation,
|
|
llvm::ArrayRef<MaterializedValue> Operands);
|
|
|
|
public:
|
|
template<typename T>
|
|
MaterializedValue load(T &MemoryOracle, unsigned Size) const {
|
|
// Cannot load symbols or invalid values
|
|
if (hasSymbol() or not IsValid)
|
|
return MaterializedValue::invalid();
|
|
|
|
return MemoryOracle.load(Value.getLimitedValue(), Size);
|
|
}
|
|
|
|
MaterializedValue byteSwap() const {
|
|
MaterializedValue Result = *this;
|
|
Result.Value = Value.byteSwap();
|
|
return Result;
|
|
}
|
|
|
|
public:
|
|
bool operator==(const MaterializedValue &Other) const {
|
|
auto MaxBitWidth = std::max(Value.getBitWidth(), Other.Value.getBitWidth());
|
|
auto ZExtValue = Value.zext(MaxBitWidth);
|
|
auto ZExtOther = Other.Value.zext(MaxBitWidth);
|
|
auto This = std::tie(IsValid, SymbolName, ZExtValue, IsMutable);
|
|
auto That = std::tie(Other.IsValid,
|
|
Other.SymbolName,
|
|
ZExtOther,
|
|
Other.IsMutable);
|
|
return This == That;
|
|
}
|
|
|
|
bool operator<(const MaterializedValue &Other) const {
|
|
auto MaxBitWidth = std::max(Value.getBitWidth(), Other.Value.getBitWidth());
|
|
if (Value.zext(MaxBitWidth).ult(Other.Value.zext(MaxBitWidth)))
|
|
return true;
|
|
auto This = std::tie(IsValid, SymbolName, IsMutable);
|
|
auto That = std::tie(Other.IsValid, Other.SymbolName, Other.IsMutable);
|
|
return This < That;
|
|
}
|
|
|
|
const llvm::APInt &value() const {
|
|
revng_assert(isValid());
|
|
return Value;
|
|
}
|
|
|
|
bool isMutable() const { return IsMutable; }
|
|
bool isValid() const { return IsValid; }
|
|
bool hasSymbol() const { return SymbolName.has_value(); }
|
|
std::string symbolName() const {
|
|
revng_assert(isValid());
|
|
revng_assert(hasSymbol());
|
|
revng_assert(not llvm::StringRef(*SymbolName).contains('\0'));
|
|
return *SymbolName;
|
|
}
|
|
|
|
llvm::Constant *toConstant(llvm::LLVMContext &Context) const;
|
|
|
|
llvm::Constant *toConstant(llvm::Type *DestinationType) const;
|
|
|
|
void dump() const debug_function { dump(dbg); }
|
|
|
|
template<typename T>
|
|
void dump(T &Output) const {
|
|
if (not isValid()) {
|
|
Output << "(invalid)";
|
|
} else {
|
|
if (hasSymbol())
|
|
Output << symbolName().data() << "+";
|
|
llvm::SmallString<40> String;
|
|
value().toStringUnsigned(String, 16);
|
|
Output << "0x" << String.c_str();
|
|
|
|
if (Value.getBitWidth() == 128) {
|
|
Output << " (" << MetaAddress::decomposeIntegerPC(Value).toString()
|
|
<< ")";
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
using MaterializedValues = std::vector<MaterializedValue>;
|
|
|
|
template<typename O>
|
|
void dumpMaterializedValues(O &Output,
|
|
llvm::StringRef Prefix,
|
|
const MaterializedValues &Values) {
|
|
for (const MaterializedValue &Value : Values) {
|
|
Output << Prefix.str();
|
|
Value.dump(Output);
|
|
}
|
|
}
|