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.
This commit is contained in:
Alessandro Di Federico
2025-10-24 15:56:15 +02:00
parent 8f21f3b5e1
commit b1feb5b989
94 changed files with 7135 additions and 6110 deletions
+61 -44
View File
@@ -5,8 +5,10 @@
//
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/ModRef.h"
#include "revng/Model/Architecture.h"
#include "revng/Model/FunctionTags.h"
#include "revng/Model/ProgramCounterHandler.h"
#include "revng/Support/Assert.h"
@@ -28,8 +30,9 @@ public:
auto Result = std::make_unique<PCOnlyProgramCounterHandler>(Alignment);
// Create and register the pc CSV
Result->AddressCSV = Factory(PCAffectingCSV::PC, AddressName);
Result->AddressCSV = Factory(PCAffectingCSV::PC);
Result->CSVsAffectingPC.insert(Result->AddressCSV);
revng_assert(Result->AddressCSV != nullptr);
// Create the other variables (non-CSV)
Result->createMissingVariables(M);
@@ -37,12 +40,15 @@ public:
return Result;
}
static std::unique_ptr<ProgramCounterHandler> fromModule(Module *M,
unsigned Alignment) {
static std::unique_ptr<ProgramCounterHandler>
fromModule(model::Architecture::Values Architecture,
Module *M,
unsigned Alignment) {
auto Result = std::make_unique<PCOnlyProgramCounterHandler>(Alignment);
// Initialize the standard variables
Result->setMissingVariables(M);
using namespace model::Architecture;
Result->setMissingVariables(M, getPCCSVName(Architecture));
// Register pc as a CSV affecting the program counter
Result->CSVsAffectingPC.insert(Result->AddressCSV);
@@ -61,16 +67,17 @@ public:
return createLoad(Builder, AddressCSV);
}
std::array<Value *, 4> dissectJumpablePC(revng::IRBuilder &Builder,
Value *ToDissect,
Triple::ArchType Arch) const final {
std::array<Value *, 4>
dissectJumpablePC(revng::IRBuilder &Builder,
Value *ToDissect,
model::Architecture::Values Architecture) const final {
IntegerType *Ty = getCSVType(TypeCSV);
Value *Address = align(Builder, ToDissect);
Value *Epoch = ConstantInt::get(Ty, 0);
Value *AddressSpace = ConstantInt::get(Ty, 0);
Value *Type = ConstantInt::get(Ty,
MetaAddressType::defaultCodeFromArch(Arch));
auto DefaultType = MetaAddressType::defaultCodeFromArch(Architecture);
Value *Type = ConstantInt::get(Ty, DefaultType);
return { Address, Epoch, AddressSpace, Type };
}
@@ -87,7 +94,7 @@ protected:
class ARMProgramCounterHandler : public ProgramCounterHandler {
private:
static constexpr const char *IsThumbName = "is_thumb";
static constexpr const char *IsThumbName = "_thumb";
private:
GlobalVariable *IsThumb = nullptr;
@@ -101,10 +108,10 @@ public:
auto Result = std::make_unique<ARMProgramCounterHandler>();
// Create and register the pc and is_thumb CSV
Result->AddressCSV = Factory(PCAffectingCSV::PC, AddressName);
Result->AddressCSV = Factory(PCAffectingCSV::PC);
Result->CSVsAffectingPC.insert(Result->AddressCSV);
Result->IsThumb = Factory(PCAffectingCSV::IsThumb, IsThumbName);
Result->IsThumb = Factory(PCAffectingCSV::IsThumb);
Result->CSVsAffectingPC.insert(Result->IsThumb);
Result->createMissingVariables(M);
@@ -115,8 +122,11 @@ public:
static std::unique_ptr<ProgramCounterHandler> fromModule(Module *M) {
auto Result = std::make_unique<ARMProgramCounterHandler>();
// Initialize the standard variablesx
Result->setMissingVariables(M);
// Initialize the standard variables
using namespace model::Architecture;
Result->setMissingVariables(M,
getPCCSVName(arm));
// Get is_thumb
Result->IsThumb = M->getGlobalVariable(IsThumbName, true);
@@ -155,9 +165,10 @@ private:
AddressType));
}
std::array<Value *, 4> dissectJumpablePC(revng::IRBuilder &Builder,
Value *ToDissect,
Triple::ArchType Arch) const final {
std::array<Value *, 4>
dissectJumpablePC(revng::IRBuilder &Builder,
Value *ToDissect,
model::Architecture::Values Architecture) const final {
constexpr uint32_t ThumbMask = 0x1;
constexpr uint32_t AddressMask = 0xFFFFFFFE;
IntegerType *Ty = getCSVType(TypeCSV);
@@ -211,8 +222,13 @@ private:
auto *ThumbCode = CI::get(TypeType, Code_arm_thumb);
// We don't use select here, SCEV can't handle it
// NewType = ARM + IsThumb * (Thumb - ARM)
unsigned ThumbSize = cast<IntegerType>(IsThumb->getType())->getBitWidth();
unsigned TypeSize = cast<IntegerType>(TypeType)->getBitWidth();
auto *CastedThumb = (ThumbSize < TypeSize) ?
B.CreateZExt(IsThumb, TypeType) :
B.CreateTrunc(IsThumb, TypeType);
auto *NewType = B.CreateAdd(ArmCode,
B.CreateMul(B.CreateTrunc(IsThumb, TypeType),
B.CreateMul(CastedThumb,
B.CreateSub(ThumbCode, ArmCode)));
return NewType;
}
@@ -353,7 +369,7 @@ bool PCH::isPCAffectingHelper(Instruction *I) const {
if (HelperCall == nullptr)
return false;
auto MaybeUsedCSVs = getCSVUsedByHelperCallIfAvailable(HelperCall);
auto MaybeUsedCSVs = tryGetCSVUsedByHelperCall(HelperCall);
// If CSAA didn't consider this helper, be conservative
if (not MaybeUsedCSVs)
@@ -866,17 +882,18 @@ PCH::buildDispatcher(DispatcherTargets &Targets,
return Result;
}
static unsigned getMinimumPCAlignment(Triple::ArchType Architecture) {
static unsigned
getMinimumPCAlignment(model::Architecture::Values Architecture) {
switch (Architecture) {
case Triple::x86:
case Triple::x86_64:
case model::Architecture::x86:
case model::Architecture::x86_64:
return 1;
case Triple::arm:
case Triple::systemz:
case model::Architecture::arm:
case model::Architecture::systemz:
return 2;
case Triple::mips:
case Triple::mipsel:
case Triple::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
case model::Architecture::aarch64:
return 4;
default:
revng_abort();
@@ -884,21 +901,21 @@ static unsigned getMinimumPCAlignment(Triple::ArchType Architecture) {
}
std::unique_ptr<ProgramCounterHandler>
PCH::create(Triple::ArchType Architecture,
PCH::create(model::Architecture::Values Architecture,
Module *M,
const CSVFactory &Factory) {
auto Alignment = getMinimumPCAlignment(Architecture);
switch (Architecture) {
case Triple::arm:
case model::Architecture::arm:
return ARMProgramCounterHandler::create(M, Factory);
case Triple::x86_64:
case Triple::mips:
case Triple::mipsel:
case Triple::aarch64:
case Triple::systemz:
case Triple::x86:
case model::Architecture::x86_64:
case model::Architecture::mips:
case model::Architecture::mipsel:
case model::Architecture::aarch64:
case model::Architecture::systemz:
case model::Architecture::x86:
return PCOnlyProgramCounterHandler::create(M, Factory, Alignment);
default:
@@ -909,20 +926,20 @@ PCH::create(Triple::ArchType Architecture,
}
std::unique_ptr<ProgramCounterHandler>
PCH::fromModule(Triple::ArchType Architecture, Module *M) {
PCH::fromModule(model::Architecture::Values Architecture, Module *M) {
auto Alignment = getMinimumPCAlignment(Architecture);
switch (Architecture) {
case Triple::arm:
case model::Architecture::arm:
return ARMProgramCounterHandler::fromModule(M);
case Triple::x86_64:
case Triple::mips:
case Triple::mipsel:
case Triple::aarch64:
case Triple::systemz:
case Triple::x86:
return PCOnlyProgramCounterHandler::fromModule(M, Alignment);
case model::Architecture::x86_64:
case model::Architecture::mips:
case model::Architecture::mipsel:
case model::Architecture::aarch64:
case model::Architecture::systemz:
case model::Architecture::x86:
return PCOnlyProgramCounterHandler::fromModule(Architecture, M, Alignment);
default:
revng_abort("Unsupported architecture");