Files
Alessandro Di Federico 1429b526ab Introduce libtcg
This commit drops libptc in favor of its new form libtcg.

It brings several improvements, among which:

* The QEMU version we work on has been upgraded.
* CPUStateAccessAnalysis has been reimplemented in a way that makes it
  easier to debug and solves some limitations (e.g., tracking leaking
  pointers).
* Identification of pieces of the CPU state that are read by each helper
  and fixing access to the CPU state is now performed at build-time.
* We no longer mmap the code we need to translate, dropping all the
  issues related to code that needed to be mapped where something is
  already present.
* We now have two distinct flavors of helper modules: the full one and
  the "slim" one. The latter contains the definition only of functions
  we intend to inline. It is used in most of the pipeline, a good thing
  since we spend less time optimizing code we don't really care about.
  The full module is only used on the re-compilation branch of the
  pipeline.
* We no longer split the `cpu_loop` function.
* We change MetaAddress to rely on architectures from `model::` as
  opposed to the LLVM ones.
* We no longer attach debug info to LLVM IR containing the original
  assembly.
* We now verify that the lifted code only contains code we expect.
2025-10-31 17:25:03 +01:00

294 lines
6.4 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "revng/Support/Debug.h"
namespace aua {
using llvm::SmallVector;
class Function;
class Value {
friend class Context;
public:
enum class Kind {
Invalid,
AnyOf,
Argument,
Constant,
BinaryOperator,
FunctionOf
};
protected:
Kind TheKind = Kind::Invalid;
SmallVector<const Value *, 2> Operands;
protected:
Value(Kind TheKind, SmallVector<const Value *, 2> &&Values) :
TheKind(TheKind), Operands(std::move(Values)) {}
public:
~Value() = default;
private:
void deleteValue();
protected:
void deduplicate() {
llvm::sort(Operands);
Operands.erase(std::unique(Operands.begin(), Operands.end()),
Operands.end());
}
public:
std::strong_ordering operator<=>(const Value &Other) const;
bool operator==(const Value &Other) const = default;
public:
template<typename T>
SmallVector<const T *, 2> collect() const {
SmallVector<const T *, 2> Result;
SmallVector<const Value *, 2> Queue{ this };
while (not Queue.empty()) {
const Value *Current = Queue.pop_back_val();
if (const T *Upcasted = llvm::dyn_cast<T>(Current))
Result.push_back(Upcasted);
for (const Value *Value : Current->Operands)
Queue.push_back(Value);
}
return Result;
}
llvm::DenseSet<unsigned> collectArguments() const;
public:
std::string toString() const;
public:
auto kind() const { return TheKind; }
const auto &operands() const { return Operands; }
public:
void setOperands(SmallVector<const Value *, 2> &&NewOperands) {
Operands = std::move(NewOperands);
}
public:
auto upcast(auto &&Handler);
auto upcast(auto &&Handler) const;
public:
std::size_t hash() const;
protected:
std::strong_ordering compare(const Value &Other) const;
protected:
std::string nodeName() const {
return std::to_string(reinterpret_cast<uintptr_t>(this));
}
std::string node(const std::string &Label) const {
return " " + nodeName() + "[label=\"" + Label + "\"];\n";
}
std::string edgeTo(const Value &Other) const {
return " " + nodeName() + " -> " + Other.nodeName() + "\n";
}
public:
std::string toGraphPart() const;
std::string toGraph() const;
};
class AnyOfValue : public Value {
friend class Context;
private:
AnyOfValue(SmallVector<const Value *, 2> &&Values) :
Value(Kind::AnyOf, std::move(Values)) {
deduplicate();
}
public:
static bool classof(const Value *B) { return B->kind() == Kind::AnyOf; }
public:
std::strong_ordering operator<=>(const AnyOfValue &Other) const;
public:
auto operands() const { return Operands; }
public:
std::string toString() const;
std::string toGraphPart() const;
};
class ArgumentValue : public Value {
friend class Context;
private:
unsigned Index = 0;
private:
ArgumentValue(unsigned Index) : Value(Kind::Argument, {}), Index(Index) {}
public:
static bool classof(const Value *B) { return B->kind() == Kind::Argument; }
public:
std::strong_ordering operator<=>(const ArgumentValue &Other) const;
public:
auto index() const { return Index; }
std::size_t hash() const;
public:
std::string toString() const { return "Argument" + std::to_string(Index); }
std::string toGraphPart() const { return node(toString()); }
};
class ConstantValue : public Value {
friend class Context;
private:
uint64_t TheValue = 0;
public:
ConstantValue(uint64_t TheValue) :
Value(Kind::Constant, {}), TheValue(TheValue) {}
public:
static bool classof(const Value *B) { return B->kind() == Kind::Constant; }
public:
std::strong_ordering operator<=>(const ConstantValue &Other) const;
std::size_t hash() const;
public:
auto value() const { return TheValue; }
public:
std::string toString() const { return std::to_string(TheValue); }
std::string toGraphPart() const { return node(toString()); }
};
class BinaryOperatorValue : public Value {
friend class Context;
public:
enum Operator {
Invalid,
Add,
Subtract,
Multiply
};
private:
Operator Type = Invalid;
private:
BinaryOperatorValue(Operator Type,
const Value &FirstValue,
const Value &SecondValue) :
Value(Kind::BinaryOperator, { &FirstValue, &SecondValue }), Type(Type) {}
public:
static bool classof(const Value *B) {
return B->kind() == Kind::BinaryOperator;
}
public:
std::strong_ordering operator<=>(const BinaryOperatorValue &Other) const;
public:
auto type() const { return Type; }
const Value &firstOperand() const { return *Operands[0]; }
const Value &secondOperand() const { return *Operands[1]; }
public:
std::size_t hash() const;
public:
std::string toString() const;
std::string toGraphPart() const;
private:
const char *symbol() const;
};
class FunctionOfValue : public Value {
friend class Context;
private:
FunctionOfValue(SmallVector<const Value *, 2> &&Values) :
Value(Kind::FunctionOf, std::move(Values)) {}
public:
static bool classof(const Value *B) { return B->kind() == Kind::FunctionOf; }
public:
std::strong_ordering operator<=>(const FunctionOfValue &Other) const;
bool isUnknown() const { return Operands.size() == 0; }
public:
std::string toString() const;
std::string toGraphPart() const;
};
inline auto Value::upcast(auto &&Handler) {
switch (TheKind) {
revng_abort();
case Kind::AnyOf:
return Handler(*llvm::cast<AnyOfValue>(this));
case Kind::Argument:
return Handler(*llvm::cast<ArgumentValue>(this));
case Kind::Constant:
return Handler(*llvm::cast<ConstantValue>(this));
case Kind::BinaryOperator:
return Handler(*llvm::cast<BinaryOperatorValue>(this));
case Kind::FunctionOf:
return Handler(*llvm::cast<FunctionOfValue>(this));
case Kind::Invalid:
default:
revng_abort();
}
}
auto Value::upcast(auto &&Handler) const {
switch (TheKind) {
case Kind::AnyOf:
return Handler(*llvm::cast<const AnyOfValue>(this));
case Kind::Argument:
return Handler(*llvm::cast<const ArgumentValue>(this));
case Kind::Constant:
return Handler(*llvm::cast<const ConstantValue>(this));
case Kind::BinaryOperator:
return Handler(*llvm::cast<const BinaryOperatorValue>(this));
case Kind::FunctionOf:
return Handler(*llvm::cast<const FunctionOfValue>(this));
case Kind::Invalid:
default:
revng_abort();
}
}
} // namespace aua