mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[macho][NFC] Extract all CPU_(SUB_)TYPE logic to BinaryFormat
This moves all the logic of converting LLVM Triples to MachO::CPU_(SUB_)TYPE from the specific target (Target)AsmBackend to more convenient functions in lib/BinaryFormat. This also gets rid of the separate two X86AsmBackend classes. The previous attempt was to add it to libObject, but that adds an unnecessary dependency to libObject from all the targets. Differential Revision: https://reviews.llvm.org/D74808
This commit is contained in:
parent
604077c19d
commit
e3adf0fc70
@ -15,9 +15,13 @@
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/SwapByteOrder.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Triple;
|
||||
|
||||
namespace MachO {
|
||||
// Enums from <mach-o/loader.h>
|
||||
enum : uint32_t {
|
||||
@ -1518,6 +1522,9 @@ enum CPUSubTypePowerPC {
|
||||
CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601
|
||||
};
|
||||
|
||||
Expected<uint32_t> getCPUType(const Triple &T);
|
||||
Expected<uint32_t> getCPUSubType(const Triple &T);
|
||||
|
||||
struct x86_thread_state32_t {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
|
@ -1,6 +1,7 @@
|
||||
add_llvm_component_library(LLVMBinaryFormat
|
||||
AMDGPUMetadataVerifier.cpp
|
||||
Dwarf.cpp
|
||||
MachO.cpp
|
||||
Magic.cpp
|
||||
Minidump.cpp
|
||||
MsgPackDocument.cpp
|
||||
|
101
lib/BinaryFormat/MachO.cpp
Normal file
101
lib/BinaryFormat/MachO.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
//===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/ARMTargetParser.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) {
|
||||
assert(T.isX86());
|
||||
if (T.isArch32Bit())
|
||||
return MachO::CPU_SUBTYPE_I386_ALL;
|
||||
|
||||
assert(T.isArch64Bit());
|
||||
if (T.getArchName() == "x86_64h")
|
||||
return MachO::CPU_SUBTYPE_X86_64_H;
|
||||
return MachO::CPU_SUBTYPE_X86_64_ALL;
|
||||
}
|
||||
|
||||
static MachO::CPUSubTypeARM getARMSubType(const Triple &T) {
|
||||
assert(T.isARM() || T.isThumb());
|
||||
StringRef Arch = T.getArchName();
|
||||
ARM::ArchKind AK = ARM::parseArch(Arch);
|
||||
switch (AK) {
|
||||
default:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7;
|
||||
case ARM::ArchKind::ARMV4T:
|
||||
return MachO::CPU_SUBTYPE_ARM_V4T;
|
||||
case ARM::ArchKind::ARMV5T:
|
||||
case ARM::ArchKind::ARMV5TE:
|
||||
case ARM::ArchKind::ARMV5TEJ:
|
||||
return MachO::CPU_SUBTYPE_ARM_V5;
|
||||
case ARM::ArchKind::ARMV6:
|
||||
case ARM::ArchKind::ARMV6K:
|
||||
return MachO::CPU_SUBTYPE_ARM_V6;
|
||||
case ARM::ArchKind::ARMV7A:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7;
|
||||
case ARM::ArchKind::ARMV7S:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7S;
|
||||
case ARM::ArchKind::ARMV7K:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7K;
|
||||
case ARM::ArchKind::ARMV6M:
|
||||
return MachO::CPU_SUBTYPE_ARM_V6M;
|
||||
case ARM::ArchKind::ARMV7M:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7M;
|
||||
case ARM::ArchKind::ARMV7EM:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7EM;
|
||||
}
|
||||
}
|
||||
|
||||
static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {
|
||||
assert(T.isAArch64() || T.getArch() == Triple::aarch64_32);
|
||||
if (T.isArch32Bit())
|
||||
return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;
|
||||
if (T.getArchName() == "arm64e")
|
||||
return MachO::CPU_SUBTYPE_ARM64E;
|
||||
|
||||
return MachO::CPU_SUBTYPE_ARM64_ALL;
|
||||
}
|
||||
|
||||
static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) {
|
||||
return MachO::CPU_SUBTYPE_POWERPC_ALL;
|
||||
}
|
||||
|
||||
Expected<uint32_t> MachO::getCPUType(const Triple &T) {
|
||||
if (T.isX86() && T.isArch32Bit())
|
||||
return MachO::CPU_TYPE_X86;
|
||||
if (T.isX86() && T.isArch64Bit())
|
||||
return MachO::CPU_TYPE_X86_64;
|
||||
if (T.isARM() || T.isThumb())
|
||||
return MachO::CPU_TYPE_ARM;
|
||||
if (T.isAArch64())
|
||||
return MachO::CPU_TYPE_ARM64;
|
||||
if (T.getArch() == Triple::aarch64_32)
|
||||
return MachO::CPU_TYPE_ARM64_32;
|
||||
if (T.getArch() == Triple::ppc)
|
||||
return MachO::CPU_TYPE_POWERPC;
|
||||
if (T.getArch() == Triple::ppc64)
|
||||
return MachO::CPU_TYPE_POWERPC64;
|
||||
return createStringError(std::errc::invalid_argument,
|
||||
"Unsupported triple for mach-o cpu type.");
|
||||
}
|
||||
|
||||
Expected<uint32_t> MachO::getCPUSubType(const Triple &T) {
|
||||
if (T.isX86())
|
||||
return getX86SubType(T);
|
||||
if (T.isARM() || T.isThumb())
|
||||
return getARMSubType(T);
|
||||
if (T.isAArch64() || T.getArch() == Triple::aarch64_32)
|
||||
return getARM64SubType(T);
|
||||
if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64)
|
||||
return getPowerPCSubType(T);
|
||||
return createStringError(std::errc::invalid_argument,
|
||||
"Unsupported triple for mach-o cpu subtype.");
|
||||
}
|
@ -33,6 +33,7 @@ namespace {
|
||||
class AArch64AsmBackend : public MCAsmBackend {
|
||||
static const unsigned PCRelFlagVal =
|
||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;
|
||||
protected:
|
||||
Triple TheTriple;
|
||||
|
||||
public:
|
||||
@ -544,7 +545,6 @@ enum CompactUnwindEncodings {
|
||||
// FIXME: This should be in a separate file.
|
||||
class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
||||
const MCRegisterInfo &MRI;
|
||||
bool IsILP32;
|
||||
|
||||
/// Encode compact unwind stack adjustment for frameless functions.
|
||||
/// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
|
||||
@ -555,18 +555,15 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
||||
|
||||
public:
|
||||
DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
|
||||
const MCRegisterInfo &MRI, bool IsILP32)
|
||||
: AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI),
|
||||
IsILP32(IsILP32) {}
|
||||
const MCRegisterInfo &MRI)
|
||||
: AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
if (IsILP32)
|
||||
return createAArch64MachObjectWriter(
|
||||
MachO::CPU_TYPE_ARM64_32, MachO::CPU_SUBTYPE_ARM64_32_V8, true);
|
||||
else
|
||||
return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
|
||||
MachO::CPU_SUBTYPE_ARM64_ALL, false);
|
||||
uint32_t CPUType = cantFail(MachO::getCPUType(TheTriple));
|
||||
uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TheTriple));
|
||||
return createAArch64MachObjectWriter(CPUType, CPUSubType,
|
||||
TheTriple.isArch32Bit());
|
||||
}
|
||||
|
||||
/// Generate the compact unwind encoding from the CFI directives.
|
||||
@ -749,8 +746,7 @@ MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
|
||||
const MCTargetOptions &Options) {
|
||||
const Triple &TheTriple = STI.getTargetTriple();
|
||||
if (TheTriple.isOSBinFormatMachO()) {
|
||||
const bool IsILP32 = TheTriple.isArch32Bit();
|
||||
return new DarwinAArch64AsmBackend(T, TheTriple, MRI, IsILP32);
|
||||
return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
|
||||
}
|
||||
|
||||
if (TheTriple.isOSBinFormatCOFF())
|
||||
|
@ -407,5 +407,5 @@ std::unique_ptr<MCObjectTargetWriter>
|
||||
llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype,
|
||||
bool IsILP32) {
|
||||
return std::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype,
|
||||
IsILP32);
|
||||
IsILP32);
|
||||
}
|
||||
|
@ -1277,35 +1277,6 @@ uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
|
||||
return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
|
||||
}
|
||||
|
||||
static MachO::CPUSubTypeARM getMachOSubTypeFromArch(StringRef Arch) {
|
||||
ARM::ArchKind AK = ARM::parseArch(Arch);
|
||||
switch (AK) {
|
||||
default:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7;
|
||||
case ARM::ArchKind::ARMV4T:
|
||||
return MachO::CPU_SUBTYPE_ARM_V4T;
|
||||
case ARM::ArchKind::ARMV5T:
|
||||
case ARM::ArchKind::ARMV5TE:
|
||||
case ARM::ArchKind::ARMV5TEJ:
|
||||
return MachO::CPU_SUBTYPE_ARM_V5;
|
||||
case ARM::ArchKind::ARMV6:
|
||||
case ARM::ArchKind::ARMV6K:
|
||||
return MachO::CPU_SUBTYPE_ARM_V6;
|
||||
case ARM::ArchKind::ARMV7A:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7;
|
||||
case ARM::ArchKind::ARMV7S:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7S;
|
||||
case ARM::ArchKind::ARMV7K:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7K;
|
||||
case ARM::ArchKind::ARMV6M:
|
||||
return MachO::CPU_SUBTYPE_ARM_V6M;
|
||||
case ARM::ArchKind::ARMV7M:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7M;
|
||||
case ARM::ArchKind::ARMV7EM:
|
||||
return MachO::CPU_SUBTYPE_ARM_V7EM;
|
||||
}
|
||||
}
|
||||
|
||||
static MCAsmBackend *createARMAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
@ -1315,10 +1286,8 @@ static MCAsmBackend *createARMAsmBackend(const Target &T,
|
||||
switch (TheTriple.getObjectFormat()) {
|
||||
default:
|
||||
llvm_unreachable("unsupported object format");
|
||||
case Triple::MachO: {
|
||||
MachO::CPUSubTypeARM CS = getMachOSubTypeFromArch(TheTriple.getArchName());
|
||||
return new ARMAsmBackendDarwin(T, STI, MRI, CS);
|
||||
}
|
||||
case Triple::MachO:
|
||||
return new ARMAsmBackendDarwin(T, STI, MRI);
|
||||
case Triple::COFF:
|
||||
assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
|
||||
return new ARMAsmBackendWinCOFF(T, STI);
|
||||
|
@ -16,16 +16,20 @@
|
||||
namespace llvm {
|
||||
class ARMAsmBackendDarwin : public ARMAsmBackend {
|
||||
const MCRegisterInfo &MRI;
|
||||
Triple TT;
|
||||
public:
|
||||
const MachO::CPUSubTypeARM Subtype;
|
||||
ARMAsmBackendDarwin(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI, MachO::CPUSubTypeARM st)
|
||||
: ARMAsmBackend(T, STI, support::little), MRI(MRI), Subtype(st) {}
|
||||
const MCRegisterInfo &MRI)
|
||||
: ARMAsmBackend(T, STI, support::little), MRI(MRI),
|
||||
TT(STI.getTargetTriple()),
|
||||
Subtype((MachO::CPUSubTypeARM)cantFail(
|
||||
MachO::getCPUSubType(STI.getTargetTriple()))) {}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
return createARMMachObjectWriter(/*Is64Bit=*/false, MachO::CPU_TYPE_ARM,
|
||||
Subtype);
|
||||
return createARMMachObjectWriter(
|
||||
/*Is64Bit=*/false, cantFail(MachO::getCPUType(TT)), Subtype);
|
||||
}
|
||||
|
||||
uint32_t generateCompactUnwindEncoding(
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
@ -207,11 +208,9 @@ public:
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
bool Is64 = TT.isPPC64();
|
||||
return createPPCMachObjectWriter(
|
||||
/*Is64Bit=*/Is64,
|
||||
(Is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC),
|
||||
MachO::CPU_SUBTYPE_POWERPC_ALL);
|
||||
uint32_t CPUType = cantFail(MachO::getCPUType(TT));
|
||||
uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TT));
|
||||
return createPPCMachObjectWriter(TT.isArch64Bit(), CPUType, CPUSubType);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -811,6 +811,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
||||
enum { CU_NUM_SAVED_REGS = 6 };
|
||||
|
||||
mutable unsigned SavedRegs[CU_NUM_SAVED_REGS];
|
||||
Triple TT;
|
||||
bool Is64Bit;
|
||||
|
||||
unsigned OffsetSize; ///< Offset of a "push" instruction.
|
||||
@ -838,10 +839,140 @@ protected:
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Get the compact unwind number for a given register. The number
|
||||
/// corresponds to the enum lists in compact_unwind_encoding.h.
|
||||
int getCompactUnwindRegNum(unsigned Reg) const {
|
||||
static const MCPhysReg CU32BitRegs[7] = {
|
||||
X86::EBX, X86::ECX, X86::EDX, X86::EDI, X86::ESI, X86::EBP, 0
|
||||
};
|
||||
static const MCPhysReg CU64BitRegs[] = {
|
||||
X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
|
||||
};
|
||||
const MCPhysReg *CURegs = Is64Bit ? CU64BitRegs : CU32BitRegs;
|
||||
for (int Idx = 1; *CURegs; ++CURegs, ++Idx)
|
||||
if (*CURegs == Reg)
|
||||
return Idx;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Return the registers encoded for a compact encoding with a frame
|
||||
/// pointer.
|
||||
uint32_t encodeCompactUnwindRegistersWithFrame() const {
|
||||
// Encode the registers in the order they were saved --- 3-bits per
|
||||
// register. The list of saved registers is assumed to be in reverse
|
||||
// order. The registers are numbered from 1 to CU_NUM_SAVED_REGS.
|
||||
uint32_t RegEnc = 0;
|
||||
for (int i = 0, Idx = 0; i != CU_NUM_SAVED_REGS; ++i) {
|
||||
unsigned Reg = SavedRegs[i];
|
||||
if (Reg == 0) break;
|
||||
|
||||
int CURegNum = getCompactUnwindRegNum(Reg);
|
||||
if (CURegNum == -1) return ~0U;
|
||||
|
||||
// Encode the 3-bit register number in order, skipping over 3-bits for
|
||||
// each register.
|
||||
RegEnc |= (CURegNum & 0x7) << (Idx++ * 3);
|
||||
}
|
||||
|
||||
assert((RegEnc & 0x3FFFF) == RegEnc &&
|
||||
"Invalid compact register encoding!");
|
||||
return RegEnc;
|
||||
}
|
||||
|
||||
/// Create the permutation encoding used with frameless stacks. It is
|
||||
/// passed the number of registers to be saved and an array of the registers
|
||||
/// saved.
|
||||
uint32_t encodeCompactUnwindRegistersWithoutFrame(unsigned RegCount) const {
|
||||
// The saved registers are numbered from 1 to 6. In order to encode the
|
||||
// order in which they were saved, we re-number them according to their
|
||||
// place in the register order. The re-numbering is relative to the last
|
||||
// re-numbered register. E.g., if we have registers {6, 2, 4, 5} saved in
|
||||
// that order:
|
||||
//
|
||||
// Orig Re-Num
|
||||
// ---- ------
|
||||
// 6 6
|
||||
// 2 2
|
||||
// 4 3
|
||||
// 5 3
|
||||
//
|
||||
for (unsigned i = 0; i < RegCount; ++i) {
|
||||
int CUReg = getCompactUnwindRegNum(SavedRegs[i]);
|
||||
if (CUReg == -1) return ~0U;
|
||||
SavedRegs[i] = CUReg;
|
||||
}
|
||||
|
||||
// Reverse the list.
|
||||
std::reverse(&SavedRegs[0], &SavedRegs[CU_NUM_SAVED_REGS]);
|
||||
|
||||
uint32_t RenumRegs[CU_NUM_SAVED_REGS];
|
||||
for (unsigned i = CU_NUM_SAVED_REGS - RegCount; i < CU_NUM_SAVED_REGS; ++i){
|
||||
unsigned Countless = 0;
|
||||
for (unsigned j = CU_NUM_SAVED_REGS - RegCount; j < i; ++j)
|
||||
if (SavedRegs[j] < SavedRegs[i])
|
||||
++Countless;
|
||||
|
||||
RenumRegs[i] = SavedRegs[i] - Countless - 1;
|
||||
}
|
||||
|
||||
// Take the renumbered values and encode them into a 10-bit number.
|
||||
uint32_t permutationEncoding = 0;
|
||||
switch (RegCount) {
|
||||
case 6:
|
||||
permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
|
||||
+ 6 * RenumRegs[2] + 2 * RenumRegs[3]
|
||||
+ RenumRegs[4];
|
||||
break;
|
||||
case 5:
|
||||
permutationEncoding |= 120 * RenumRegs[1] + 24 * RenumRegs[2]
|
||||
+ 6 * RenumRegs[3] + 2 * RenumRegs[4]
|
||||
+ RenumRegs[5];
|
||||
break;
|
||||
case 4:
|
||||
permutationEncoding |= 60 * RenumRegs[2] + 12 * RenumRegs[3]
|
||||
+ 3 * RenumRegs[4] + RenumRegs[5];
|
||||
break;
|
||||
case 3:
|
||||
permutationEncoding |= 20 * RenumRegs[3] + 4 * RenumRegs[4]
|
||||
+ RenumRegs[5];
|
||||
break;
|
||||
case 2:
|
||||
permutationEncoding |= 5 * RenumRegs[4] + RenumRegs[5];
|
||||
break;
|
||||
case 1:
|
||||
permutationEncoding |= RenumRegs[5];
|
||||
break;
|
||||
}
|
||||
|
||||
assert((permutationEncoding & 0x3FF) == permutationEncoding &&
|
||||
"Invalid compact register encoding!");
|
||||
return permutationEncoding;
|
||||
}
|
||||
|
||||
public:
|
||||
DarwinX86AsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI)
|
||||
: X86AsmBackend(T, STI), MRI(MRI), TT(STI.getTargetTriple()),
|
||||
Is64Bit(TT.isArch64Bit()) {
|
||||
memset(SavedRegs, 0, sizeof(SavedRegs));
|
||||
OffsetSize = Is64Bit ? 8 : 4;
|
||||
MoveInstrSize = Is64Bit ? 3 : 2;
|
||||
StackDivide = Is64Bit ? 8 : 4;
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
uint32_t CPUType = cantFail(MachO::getCPUType(TT));
|
||||
uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TT));
|
||||
return createX86MachObjectWriter(Is64Bit, CPUType, CPUSubType);
|
||||
}
|
||||
|
||||
/// Implementation of algorithm to generate the compact unwind encoding
|
||||
/// for the CFI instructions.
|
||||
uint32_t
|
||||
generateCompactUnwindEncodingImpl(ArrayRef<MCCFIInstruction> Instrs) const {
|
||||
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const override {
|
||||
if (Instrs.empty()) return 0;
|
||||
|
||||
// Reset the saved registers.
|
||||
@ -991,168 +1122,6 @@ protected:
|
||||
|
||||
return CompactUnwindEncoding;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Get the compact unwind number for a given register. The number
|
||||
/// corresponds to the enum lists in compact_unwind_encoding.h.
|
||||
int getCompactUnwindRegNum(unsigned Reg) const {
|
||||
static const MCPhysReg CU32BitRegs[7] = {
|
||||
X86::EBX, X86::ECX, X86::EDX, X86::EDI, X86::ESI, X86::EBP, 0
|
||||
};
|
||||
static const MCPhysReg CU64BitRegs[] = {
|
||||
X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
|
||||
};
|
||||
const MCPhysReg *CURegs = Is64Bit ? CU64BitRegs : CU32BitRegs;
|
||||
for (int Idx = 1; *CURegs; ++CURegs, ++Idx)
|
||||
if (*CURegs == Reg)
|
||||
return Idx;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Return the registers encoded for a compact encoding with a frame
|
||||
/// pointer.
|
||||
uint32_t encodeCompactUnwindRegistersWithFrame() const {
|
||||
// Encode the registers in the order they were saved --- 3-bits per
|
||||
// register. The list of saved registers is assumed to be in reverse
|
||||
// order. The registers are numbered from 1 to CU_NUM_SAVED_REGS.
|
||||
uint32_t RegEnc = 0;
|
||||
for (int i = 0, Idx = 0; i != CU_NUM_SAVED_REGS; ++i) {
|
||||
unsigned Reg = SavedRegs[i];
|
||||
if (Reg == 0) break;
|
||||
|
||||
int CURegNum = getCompactUnwindRegNum(Reg);
|
||||
if (CURegNum == -1) return ~0U;
|
||||
|
||||
// Encode the 3-bit register number in order, skipping over 3-bits for
|
||||
// each register.
|
||||
RegEnc |= (CURegNum & 0x7) << (Idx++ * 3);
|
||||
}
|
||||
|
||||
assert((RegEnc & 0x3FFFF) == RegEnc &&
|
||||
"Invalid compact register encoding!");
|
||||
return RegEnc;
|
||||
}
|
||||
|
||||
/// Create the permutation encoding used with frameless stacks. It is
|
||||
/// passed the number of registers to be saved and an array of the registers
|
||||
/// saved.
|
||||
uint32_t encodeCompactUnwindRegistersWithoutFrame(unsigned RegCount) const {
|
||||
// The saved registers are numbered from 1 to 6. In order to encode the
|
||||
// order in which they were saved, we re-number them according to their
|
||||
// place in the register order. The re-numbering is relative to the last
|
||||
// re-numbered register. E.g., if we have registers {6, 2, 4, 5} saved in
|
||||
// that order:
|
||||
//
|
||||
// Orig Re-Num
|
||||
// ---- ------
|
||||
// 6 6
|
||||
// 2 2
|
||||
// 4 3
|
||||
// 5 3
|
||||
//
|
||||
for (unsigned i = 0; i < RegCount; ++i) {
|
||||
int CUReg = getCompactUnwindRegNum(SavedRegs[i]);
|
||||
if (CUReg == -1) return ~0U;
|
||||
SavedRegs[i] = CUReg;
|
||||
}
|
||||
|
||||
// Reverse the list.
|
||||
std::reverse(&SavedRegs[0], &SavedRegs[CU_NUM_SAVED_REGS]);
|
||||
|
||||
uint32_t RenumRegs[CU_NUM_SAVED_REGS];
|
||||
for (unsigned i = CU_NUM_SAVED_REGS - RegCount; i < CU_NUM_SAVED_REGS; ++i){
|
||||
unsigned Countless = 0;
|
||||
for (unsigned j = CU_NUM_SAVED_REGS - RegCount; j < i; ++j)
|
||||
if (SavedRegs[j] < SavedRegs[i])
|
||||
++Countless;
|
||||
|
||||
RenumRegs[i] = SavedRegs[i] - Countless - 1;
|
||||
}
|
||||
|
||||
// Take the renumbered values and encode them into a 10-bit number.
|
||||
uint32_t permutationEncoding = 0;
|
||||
switch (RegCount) {
|
||||
case 6:
|
||||
permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
|
||||
+ 6 * RenumRegs[2] + 2 * RenumRegs[3]
|
||||
+ RenumRegs[4];
|
||||
break;
|
||||
case 5:
|
||||
permutationEncoding |= 120 * RenumRegs[1] + 24 * RenumRegs[2]
|
||||
+ 6 * RenumRegs[3] + 2 * RenumRegs[4]
|
||||
+ RenumRegs[5];
|
||||
break;
|
||||
case 4:
|
||||
permutationEncoding |= 60 * RenumRegs[2] + 12 * RenumRegs[3]
|
||||
+ 3 * RenumRegs[4] + RenumRegs[5];
|
||||
break;
|
||||
case 3:
|
||||
permutationEncoding |= 20 * RenumRegs[3] + 4 * RenumRegs[4]
|
||||
+ RenumRegs[5];
|
||||
break;
|
||||
case 2:
|
||||
permutationEncoding |= 5 * RenumRegs[4] + RenumRegs[5];
|
||||
break;
|
||||
case 1:
|
||||
permutationEncoding |= RenumRegs[5];
|
||||
break;
|
||||
}
|
||||
|
||||
assert((permutationEncoding & 0x3FF) == permutationEncoding &&
|
||||
"Invalid compact register encoding!");
|
||||
return permutationEncoding;
|
||||
}
|
||||
|
||||
public:
|
||||
DarwinX86AsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI, bool Is64Bit)
|
||||
: X86AsmBackend(T, STI), MRI(MRI), Is64Bit(Is64Bit) {
|
||||
memset(SavedRegs, 0, sizeof(SavedRegs));
|
||||
OffsetSize = Is64Bit ? 8 : 4;
|
||||
MoveInstrSize = Is64Bit ? 3 : 2;
|
||||
StackDivide = Is64Bit ? 8 : 4;
|
||||
}
|
||||
};
|
||||
|
||||
class DarwinX86_32AsmBackend : public DarwinX86AsmBackend {
|
||||
public:
|
||||
DarwinX86_32AsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI)
|
||||
: DarwinX86AsmBackend(T, MRI, STI, false) {}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
return createX86MachObjectWriter(/*Is64Bit=*/false,
|
||||
MachO::CPU_TYPE_I386,
|
||||
MachO::CPU_SUBTYPE_I386_ALL);
|
||||
}
|
||||
|
||||
/// Generate the compact unwind encoding for the CFI instructions.
|
||||
uint32_t generateCompactUnwindEncoding(
|
||||
ArrayRef<MCCFIInstruction> Instrs) const override {
|
||||
return generateCompactUnwindEncodingImpl(Instrs);
|
||||
}
|
||||
};
|
||||
|
||||
class DarwinX86_64AsmBackend : public DarwinX86AsmBackend {
|
||||
const MachO::CPUSubTypeX86 Subtype;
|
||||
public:
|
||||
DarwinX86_64AsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI, MachO::CPUSubTypeX86 st)
|
||||
: DarwinX86AsmBackend(T, MRI, STI, true), Subtype(st) {}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override {
|
||||
return createX86MachObjectWriter(/*Is64Bit=*/true, MachO::CPU_TYPE_X86_64,
|
||||
Subtype);
|
||||
}
|
||||
|
||||
/// Generate the compact unwind encoding for the CFI instructions.
|
||||
uint32_t generateCompactUnwindEncoding(
|
||||
ArrayRef<MCCFIInstruction> Instrs) const override {
|
||||
return generateCompactUnwindEncodingImpl(Instrs);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@ -1163,7 +1132,7 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
|
||||
const MCTargetOptions &Options) {
|
||||
const Triple &TheTriple = STI.getTargetTriple();
|
||||
if (TheTriple.isOSBinFormatMachO())
|
||||
return new DarwinX86_32AsmBackend(T, MRI, STI);
|
||||
return new DarwinX86AsmBackend(T, MRI, STI);
|
||||
|
||||
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
||||
return new WindowsX86AsmBackend(T, false, STI);
|
||||
@ -1181,13 +1150,8 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options) {
|
||||
const Triple &TheTriple = STI.getTargetTriple();
|
||||
if (TheTriple.isOSBinFormatMachO()) {
|
||||
MachO::CPUSubTypeX86 CS =
|
||||
StringSwitch<MachO::CPUSubTypeX86>(TheTriple.getArchName())
|
||||
.Case("x86_64h", MachO::CPU_SUBTYPE_X86_64_H)
|
||||
.Default(MachO::CPU_SUBTYPE_X86_64_ALL);
|
||||
return new DarwinX86_64AsmBackend(T, MRI, STI, CS);
|
||||
}
|
||||
if (TheTriple.isOSBinFormatMachO())
|
||||
return new DarwinX86AsmBackend(T, MRI, STI);
|
||||
|
||||
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
||||
return new WindowsX86AsmBackend(T, true, STI);
|
||||
|
Loading…
Reference in New Issue
Block a user