mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
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:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user