#include "../Target.h"
#include "../Error.h"
#include "../MmapUtils.h"
#include "../ParallelSnippetGenerator.h"
#include "../SerialSnippetGenerator.h"
#include "../SnippetGenerator.h"
#include "../SubprocessMemory.h"
#include "MCTargetDesc/X86BaseInfo.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "X86.h"
#include "X86Counter.h"
#include "X86RegisterInfo.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TargetParser/Host.h"
#include <memory>
#include <string>
#include <vector>
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#include <immintrin.h>
#include <intrin.h>
#endif
#if defined(_MSC_VER) && defined(_M_X64)
#include <float.h>
#endif
#ifdef __linux__
#ifdef __x86_64__
#include <asm/prctl.h>
#endif
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
#ifdef HAVE_LIBPFM
#include <perfmon/perf_event.h>
#endif
#endif
#define GET_AVAILABLE_OPCODE_CHECKER
#include "X86GenInstrInfo.inc"
namespace llvm {
namespace exegesis {
static cl::opt<unsigned> LbrSamplingPeriod(
"x86-lbr-sample-period",
cl::desc("The sample period (nbranches/sample), used for LBR sampling"),
cl::cat(BenchmarkOptions), cl::init(0));
static cl::opt<bool>
DisableUpperSSERegisters("x86-disable-upper-sse-registers",
cl::desc("Disable XMM8-XMM15 register usage"),
cl::cat(BenchmarkOptions), cl::init(false));
static const char *isInvalidMemoryInstr(const Instruction &Instr) { … }
static const char *isInvalidOpcode(const Instruction &Instr) { … }
static unsigned getX86FPFlags(const Instruction &Instr) { … }
static void setMemOp(InstructionTemplate &IT, int OpIdx,
const MCOperand &OpVal) { … }
static Expected<std::vector<CodeTemplate>> generateLEATemplatesCommon(
const Instruction &Instr, const BitVector &ForbiddenRegisters,
const LLVMState &State, const SnippetGenerator::Options &Opts,
std::function<void(unsigned, unsigned, BitVector &CandidateDestRegs)>
RestrictDestRegs) { … }
namespace {
class X86SerialSnippetGenerator : public SerialSnippetGenerator { … };
}
Expected<std::vector<CodeTemplate>>
X86SerialSnippetGenerator::generateCodeTemplates(
InstructionTemplate Variant, const BitVector &ForbiddenRegisters) const { … }
namespace {
class X86ParallelSnippetGenerator : public ParallelSnippetGenerator { … };
}
Expected<std::vector<CodeTemplate>>
X86ParallelSnippetGenerator::generateCodeTemplates(
InstructionTemplate Variant, const BitVector &ForbiddenRegisters) const { … }
static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) { … }
static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
const APInt &Value) { … }
static MCInst allocateStackSpace(unsigned Bytes) { … }
static MCInst fillStackSpace(unsigned MovOpcode, unsigned OffsetBytes,
uint64_t Imm) { … }
static MCInst loadToReg(unsigned Reg, unsigned RMOpcode) { … }
static MCInst releaseStackSpace(unsigned Bytes) { … }
namespace {
struct ConstantInliner { … };
}
std::vector<MCInst> ConstantInliner::loadAndFinalize(unsigned Reg,
unsigned RegBitWidth,
unsigned Opcode) { … }
std::vector<MCInst> ConstantInliner::loadX87STAndFinalize(unsigned Reg) { … }
std::vector<MCInst> ConstantInliner::loadX87FPAndFinalize(unsigned Reg) { … }
std::vector<MCInst> ConstantInliner::popFlagAndFinalize() { … }
std::vector<MCInst>
ConstantInliner::loadImplicitRegAndFinalize(unsigned Opcode, unsigned Value) { … }
void ConstantInliner::initStack(unsigned Bytes) { … }
#include "X86GenExegesis.inc"
namespace {
class X86SavedState : public ExegesisTarget::SavedState { … };
class ExegesisX86Target : public ExegesisTarget { … };
const unsigned ExegesisX86Target::kUnavailableRegisters[4] = …;
const unsigned ExegesisX86Target::kUnavailableRegistersSSE[12] = …;
constexpr const unsigned kDefaultLoopCounterReg = …;
}
void ExegesisX86Target::addTargetSpecificPasses(PassManagerBase &PM) const { … }
unsigned ExegesisX86Target::getScratchMemoryRegister(const Triple &TT) const { … }
unsigned
ExegesisX86Target::getDefaultLoopCounterRegister(const Triple &TT) const { … }
Error ExegesisX86Target::randomizeTargetMCOperand(
const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue,
const BitVector &ForbiddenRegs) const { … }
void ExegesisX86Target::fillMemoryOperands(InstructionTemplate &IT,
unsigned Reg,
unsigned Offset) const { … }
void ExegesisX86Target::decrementLoopCounterAndJump(
MachineBasicBlock &MBB, MachineBasicBlock &TargetMBB,
const MCInstrInfo &MII, unsigned LoopRegister) const { … }
void generateRegisterStackPush(unsigned int Register,
std::vector<MCInst> &GeneratedCode) { … }
void generateRegisterStackPop(unsigned int Register,
std::vector<MCInst> &GeneratedCode) { … }
void generateSyscall(long SyscallNumber, std::vector<MCInst> &GeneratedCode) { … }
#ifdef __linux__
constexpr std::array<unsigned, 6> SyscallArgumentRegisters{ … };
static void saveSyscallRegisters(std::vector<MCInst> &GeneratedCode,
unsigned ArgumentCount) { … }
static void restoreSyscallRegisters(std::vector<MCInst> &GeneratedCode,
unsigned ArgumentCount) { … }
#endif
static std::vector<MCInst> loadImmediateSegmentRegister(unsigned Reg,
const APInt &Value) { … }
std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
unsigned Reg,
const APInt &Value) const { … }
#ifdef __linux__
#ifdef __arm__
static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000;
#else
static constexpr const uintptr_t VAddressSpaceCeiling = …;
#endif
void generateRoundToNearestPage(unsigned int Register,
std::vector<MCInst> &GeneratedCode) { … }
void generateGetInstructionPointer(unsigned int ResultRegister,
std::vector<MCInst> &GeneratedCode) { … }
void ExegesisX86Target::generateLowerMunmap(
std::vector<MCInst> &GeneratedCode) const { … }
void ExegesisX86Target::generateUpperMunmap(
std::vector<MCInst> &GeneratedCode) const { … }
std::vector<MCInst>
ExegesisX86Target::generateExitSyscall(unsigned ExitCode) const { … }
std::vector<MCInst>
ExegesisX86Target::generateMmap(uintptr_t Address, size_t Length,
uintptr_t FileDescriptorAddress) const { … }
void ExegesisX86Target::generateMmapAuxMem(
std::vector<MCInst> &GeneratedCode) const { … }
void ExegesisX86Target::moveArgumentRegisters(
std::vector<MCInst> &GeneratedCode) const { … }
std::vector<MCInst> ExegesisX86Target::generateMemoryInitialSetup() const { … }
std::vector<MCInst> ExegesisX86Target::setStackRegisterToAuxMem() const { … }
uintptr_t ExegesisX86Target::getAuxiliaryMemoryStartAddress() const { … }
std::vector<MCInst>
ExegesisX86Target::configurePerfCounter(long Request, bool SaveRegisters) const { … }
std::vector<unsigned> ExegesisX86Target::getArgumentRegisters() const { … }
std::vector<unsigned> ExegesisX86Target::getRegistersNeedSaving() const { … }
#endif
std::vector<InstructionTemplate> ExegesisX86Target::generateInstructionVariants(
const Instruction &Instr, unsigned MaxConfigsPerOpcode) const { … }
static ExegesisTarget *getTheExegesisX86Target() { … }
void InitializeX86ExegesisTarget() { … }
}
}