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

411 lines
8.6 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/ADT/Triple.h"
#include "revng/Model/Generated/Early/Architecture.h"
namespace model::Architecture {
inline bool isLittleEndian(Values V) {
switch (V) {
case model::Architecture::x86:
case model::Architecture::x86_64:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mipsel:
return true;
case model::Architecture::mips:
case model::Architecture::systemz:
return false;
default:
revng_abort();
}
}
inline Values fromLLVMArchitecture(llvm::Triple::ArchType A) {
switch (A) {
case llvm::Triple::x86:
return model::Architecture::x86;
case llvm::Triple::x86_64:
return model::Architecture::x86_64;
case llvm::Triple::arm:
return model::Architecture::arm;
case llvm::Triple::aarch64:
return model::Architecture::aarch64;
case llvm::Triple::mips:
return model::Architecture::mips;
case llvm::Triple::mipsel:
return model::Architecture::mipsel;
case llvm::Triple::systemz:
return model::Architecture::systemz;
default:
return model::Architecture::Invalid;
}
}
inline llvm::Triple::ArchType toLLVMArchitecture(Values V) {
switch (V) {
case model::Architecture::x86:
return llvm::Triple::x86;
case model::Architecture::x86_64:
return llvm::Triple::x86_64;
case model::Architecture::arm:
return llvm::Triple::arm;
case model::Architecture::aarch64:
return llvm::Triple::aarch64;
case model::Architecture::mips:
return llvm::Triple::mips;
case model::Architecture::mipsel:
return llvm::Triple::mipsel;
case model::Architecture::systemz:
return llvm::Triple::systemz;
default:
revng_abort();
}
}
/// Return the size of the pointer in bytes
constexpr inline uint64_t getPointerSize(Values V) {
switch (V) {
case model::Architecture::x86:
case model::Architecture::arm:
case model::Architecture::mips:
case model::Architecture::mipsel:
return 4;
case model::Architecture::x86_64:
case model::Architecture::aarch64:
case model::Architecture::systemz:
return 8;
default:
revng_abort();
}
}
constexpr inline uint64_t getCallPushSize(Values V) {
switch (V) {
case x86:
return 4;
case x86_64:
return 8;
case arm:
case mips:
case mipsel:
case aarch64:
case systemz:
return 0;
default:
revng_abort();
}
}
constexpr inline llvm::ArrayRef<char> getBasicBlockEndingPattern(Values V) {
switch (V) {
case x86:
case x86_64:
return "\xcc";
case arm:
// bx lr
return "\x1e\xff\x2f\xe1";
case mips:
// jr ra
return "\x08\x00\xe0\x03";
case mipsel:
// jr ra
return "\x03\xe0\x00\x08";
case aarch64:
// ret
return "\xc0\x03\x5f\xd6";
case systemz:
// TODO
return "";
default:
revng_abort();
}
}
// TODO: this is libtinycode-specific
constexpr inline llvm::StringRef getSyscallHelper(Values V) {
switch (V) {
case x86:
return "helper_raise_interrupt";
case x86_64:
return "helper_syscall";
case arm:
case aarch64:
return "helper_exception_with_syndrome";
case mips:
case mipsel:
return "helper_raise_exception";
case systemz:
return "helper_exception";
default:
revng_abort();
}
}
// TODO: this is libtinycode-specific
inline llvm::ArrayRef<uint64_t> getNoReturnSyscallNumbers(Values V) {
switch (V) {
case x86: {
static uint64_t NoReturnSyscalls[] = {
0xfc, // exit_group
0x01, // exit
0x0b // execve
};
return NoReturnSyscalls;
}
case x86_64: {
static uint64_t NoReturnSyscalls[] = {
0xe7, // exit_group
0x3c, // exit
0x3b // execve
};
return NoReturnSyscalls;
}
case arm: {
static uint64_t NoReturnSyscalls[] = {
0xf8, // exit_group
0x1, // exit
0xb // execve
};
return NoReturnSyscalls;
}
case aarch64: {
static uint64_t NoReturnSyscalls[] = {
0x5e, // exit_group
0x5d, // exit
0xdd // execve
};
return NoReturnSyscalls;
}
case mips:
case mipsel: {
static uint64_t NoReturnSyscalls[] = {
0x1096, // exit_group
0xfa1, // exit
0xfab // execve
};
return NoReturnSyscalls;
}
case systemz: {
static uint64_t NoReturnSyscalls[] = {
0xf8, // exit_group
0x1, // exit
0xb, // execve
};
return NoReturnSyscalls;
}
default:
revng_abort();
}
}
inline bool hasELFRelocationAddend(Values V) {
switch (V) {
case model::Architecture::x86_64:
case model::Architecture::systemz:
return true;
case model::Architecture::x86:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
return false;
default:
revng_abort();
}
}
inline llvm::StringRef getReadRegisterAssembly(Values V) {
switch (V) {
case model::Architecture::x86_64:
return "movq %REGISTER, $0";
case model::Architecture::systemz:
case model::Architecture::x86:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
return "";
default:
revng_abort();
}
}
inline llvm::StringRef getWriteRegisterAssembly(Values V) {
switch (V) {
case model::Architecture::x86_64:
return "movq $0, %REGISTER";
case model::Architecture::systemz:
case model::Architecture::x86:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
return "";
default:
revng_abort();
}
}
inline llvm::StringRef getJumpAssembly(Values V) {
switch (V) {
case model::Architecture::x86_64:
return "jmpq *$0";
case model::Architecture::systemz:
case model::Architecture::x86:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
return "";
default:
revng_abort();
}
}
llvm::StringRef getPCCSVName(Values V);
inline llvm::StringRef getQEMUName(Values V) {
switch (V) {
case model::Architecture::x86_64:
return "x86_64";
case model::Architecture::systemz:
return "s390x";
case model::Architecture::x86:
return "i386";
case model::Architecture::arm:
return "arm";
case model::Architecture::aarch64:
return "aarch64";
case model::Architecture::mips:
return "mips";
case model::Architecture::mipsel:
return "mipsel";
default:
revng_abort();
}
}
inline Values fromQEMUName(llvm::StringRef Name) {
if (Name == "x86_64")
return model::Architecture::x86_64;
else if (Name == "s390x")
return model::Architecture::systemz;
else if (Name == "i386")
return model::Architecture::x86;
else if (Name == "arm")
return model::Architecture::arm;
else if (Name == "aarch64")
return model::Architecture::aarch64;
else if (Name == "mips")
return model::Architecture::mips;
else if (Name == "mipsel")
return model::Architecture::mipsel;
else
revng_abort();
}
inline unsigned getMinimalFinalStackOffset(Values V) {
switch (V) {
case model::Architecture::x86_64:
return 8;
case model::Architecture::x86:
return 4;
case model::Architecture::systemz:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
return 0;
default:
revng_abort();
}
}
inline constexpr llvm::StringRef getAssemblyCommentIndicator(Values V) {
switch (V) {
case model::Architecture::x86:
case model::Architecture::x86_64:
case model::Architecture::mips:
case model::Architecture::mipsel:
case model::Architecture::systemz:
return "#";
case model::Architecture::arm:
return "@";
case model::Architecture::aarch64:
return "//";
default:
revng_abort();
}
}
inline constexpr llvm::StringRef getAssemblyLabelIndicator(Values V) {
switch (V) {
case model::Architecture::x86:
case model::Architecture::x86_64:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::mips:
case model::Architecture::mipsel:
case model::Architecture::systemz:
return ":";
default:
revng_abort();
}
}
inline constexpr bool hasDelaySlot(Values V) {
switch (V) {
case model::Architecture::x86:
case model::Architecture::x86_64:
case model::Architecture::arm:
case model::Architecture::aarch64:
case model::Architecture::systemz:
return false;
case model::Architecture::mips:
case model::Architecture::mipsel:
return true;
default:
revng_abort();
}
}
} // namespace model::Architecture
#include "revng/Model/Generated/Late/Architecture.h"