mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +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/Compiler.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/SwapByteOrder.h"
|
#include "llvm/Support/SwapByteOrder.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Triple;
|
||||||
|
|
||||||
namespace MachO {
|
namespace MachO {
|
||||||
// Enums from <mach-o/loader.h>
|
// Enums from <mach-o/loader.h>
|
||||||
enum : uint32_t {
|
enum : uint32_t {
|
||||||
@ -1518,6 +1522,9 @@ enum CPUSubTypePowerPC {
|
|||||||
CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601
|
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 {
|
struct x86_thread_state32_t {
|
||||||
uint32_t eax;
|
uint32_t eax;
|
||||||
uint32_t ebx;
|
uint32_t ebx;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
add_llvm_component_library(LLVMBinaryFormat
|
add_llvm_component_library(LLVMBinaryFormat
|
||||||
AMDGPUMetadataVerifier.cpp
|
AMDGPUMetadataVerifier.cpp
|
||||||
Dwarf.cpp
|
Dwarf.cpp
|
||||||
|
MachO.cpp
|
||||||
Magic.cpp
|
Magic.cpp
|
||||||
Minidump.cpp
|
Minidump.cpp
|
||||||
MsgPackDocument.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 {
|
class AArch64AsmBackend : public MCAsmBackend {
|
||||||
static const unsigned PCRelFlagVal =
|
static const unsigned PCRelFlagVal =
|
||||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;
|
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;
|
||||||
|
protected:
|
||||||
Triple TheTriple;
|
Triple TheTriple;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -544,7 +545,6 @@ enum CompactUnwindEncodings {
|
|||||||
// FIXME: This should be in a separate file.
|
// FIXME: This should be in a separate file.
|
||||||
class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
||||||
const MCRegisterInfo &MRI;
|
const MCRegisterInfo &MRI;
|
||||||
bool IsILP32;
|
|
||||||
|
|
||||||
/// Encode compact unwind stack adjustment for frameless functions.
|
/// Encode compact unwind stack adjustment for frameless functions.
|
||||||
/// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
|
/// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
|
||||||
@ -555,18 +555,15 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
|
DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
|
||||||
const MCRegisterInfo &MRI, bool IsILP32)
|
const MCRegisterInfo &MRI)
|
||||||
: AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI),
|
: AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
|
||||||
IsILP32(IsILP32) {}
|
|
||||||
|
|
||||||
std::unique_ptr<MCObjectTargetWriter>
|
std::unique_ptr<MCObjectTargetWriter>
|
||||||
createObjectTargetWriter() const override {
|
createObjectTargetWriter() const override {
|
||||||
if (IsILP32)
|
uint32_t CPUType = cantFail(MachO::getCPUType(TheTriple));
|
||||||
return createAArch64MachObjectWriter(
|
uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TheTriple));
|
||||||
MachO::CPU_TYPE_ARM64_32, MachO::CPU_SUBTYPE_ARM64_32_V8, true);
|
return createAArch64MachObjectWriter(CPUType, CPUSubType,
|
||||||
else
|
TheTriple.isArch32Bit());
|
||||||
return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
|
|
||||||
MachO::CPU_SUBTYPE_ARM64_ALL, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the compact unwind encoding from the CFI directives.
|
/// Generate the compact unwind encoding from the CFI directives.
|
||||||
@ -749,8 +746,7 @@ MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
|
|||||||
const MCTargetOptions &Options) {
|
const MCTargetOptions &Options) {
|
||||||
const Triple &TheTriple = STI.getTargetTriple();
|
const Triple &TheTriple = STI.getTargetTriple();
|
||||||
if (TheTriple.isOSBinFormatMachO()) {
|
if (TheTriple.isOSBinFormatMachO()) {
|
||||||
const bool IsILP32 = TheTriple.isArch32Bit();
|
return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
|
||||||
return new DarwinAArch64AsmBackend(T, TheTriple, MRI, IsILP32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TheTriple.isOSBinFormatCOFF())
|
if (TheTriple.isOSBinFormatCOFF())
|
||||||
|
@ -407,5 +407,5 @@ std::unique_ptr<MCObjectTargetWriter>
|
|||||||
llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype,
|
llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype,
|
||||||
bool IsILP32) {
|
bool IsILP32) {
|
||||||
return std::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype,
|
return std::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype,
|
||||||
IsILP32);
|
IsILP32);
|
||||||
}
|
}
|
||||||
|
@ -1277,35 +1277,6 @@ uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
|
|||||||
return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
|
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,
|
static MCAsmBackend *createARMAsmBackend(const Target &T,
|
||||||
const MCSubtargetInfo &STI,
|
const MCSubtargetInfo &STI,
|
||||||
const MCRegisterInfo &MRI,
|
const MCRegisterInfo &MRI,
|
||||||
@ -1315,10 +1286,8 @@ static MCAsmBackend *createARMAsmBackend(const Target &T,
|
|||||||
switch (TheTriple.getObjectFormat()) {
|
switch (TheTriple.getObjectFormat()) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("unsupported object format");
|
llvm_unreachable("unsupported object format");
|
||||||
case Triple::MachO: {
|
case Triple::MachO:
|
||||||
MachO::CPUSubTypeARM CS = getMachOSubTypeFromArch(TheTriple.getArchName());
|
return new ARMAsmBackendDarwin(T, STI, MRI);
|
||||||
return new ARMAsmBackendDarwin(T, STI, MRI, CS);
|
|
||||||
}
|
|
||||||
case Triple::COFF:
|
case Triple::COFF:
|
||||||
assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
|
assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
|
||||||
return new ARMAsmBackendWinCOFF(T, STI);
|
return new ARMAsmBackendWinCOFF(T, STI);
|
||||||
|
@ -16,16 +16,20 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class ARMAsmBackendDarwin : public ARMAsmBackend {
|
class ARMAsmBackendDarwin : public ARMAsmBackend {
|
||||||
const MCRegisterInfo &MRI;
|
const MCRegisterInfo &MRI;
|
||||||
|
Triple TT;
|
||||||
public:
|
public:
|
||||||
const MachO::CPUSubTypeARM Subtype;
|
const MachO::CPUSubTypeARM Subtype;
|
||||||
ARMAsmBackendDarwin(const Target &T, const MCSubtargetInfo &STI,
|
ARMAsmBackendDarwin(const Target &T, const MCSubtargetInfo &STI,
|
||||||
const MCRegisterInfo &MRI, MachO::CPUSubTypeARM st)
|
const MCRegisterInfo &MRI)
|
||||||
: ARMAsmBackend(T, STI, support::little), MRI(MRI), Subtype(st) {}
|
: ARMAsmBackend(T, STI, support::little), MRI(MRI),
|
||||||
|
TT(STI.getTargetTriple()),
|
||||||
|
Subtype((MachO::CPUSubTypeARM)cantFail(
|
||||||
|
MachO::getCPUSubType(STI.getTargetTriple()))) {}
|
||||||
|
|
||||||
std::unique_ptr<MCObjectTargetWriter>
|
std::unique_ptr<MCObjectTargetWriter>
|
||||||
createObjectTargetWriter() const override {
|
createObjectTargetWriter() const override {
|
||||||
return createARMMachObjectWriter(/*Is64Bit=*/false, MachO::CPU_TYPE_ARM,
|
return createARMMachObjectWriter(
|
||||||
Subtype);
|
/*Is64Bit=*/false, cantFail(MachO::getCPUType(TT)), Subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t generateCompactUnwindEncoding(
|
uint32_t generateCompactUnwindEncoding(
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "llvm/MC/MCSubtargetInfo.h"
|
#include "llvm/MC/MCSubtargetInfo.h"
|
||||||
#include "llvm/MC/MCSymbolELF.h"
|
#include "llvm/MC/MCSymbolELF.h"
|
||||||
#include "llvm/MC/MCValue.h"
|
#include "llvm/MC/MCValue.h"
|
||||||
|
#include "llvm/Object/MachO.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/TargetRegistry.h"
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -207,11 +208,9 @@ public:
|
|||||||
|
|
||||||
std::unique_ptr<MCObjectTargetWriter>
|
std::unique_ptr<MCObjectTargetWriter>
|
||||||
createObjectTargetWriter() const override {
|
createObjectTargetWriter() const override {
|
||||||
bool Is64 = TT.isPPC64();
|
uint32_t CPUType = cantFail(MachO::getCPUType(TT));
|
||||||
return createPPCMachObjectWriter(
|
uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TT));
|
||||||
/*Is64Bit=*/Is64,
|
return createPPCMachObjectWriter(TT.isArch64Bit(), CPUType, CPUSubType);
|
||||||
(Is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC),
|
|
||||||
MachO::CPU_SUBTYPE_POWERPC_ALL);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -811,6 +811,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
|||||||
enum { CU_NUM_SAVED_REGS = 6 };
|
enum { CU_NUM_SAVED_REGS = 6 };
|
||||||
|
|
||||||
mutable unsigned SavedRegs[CU_NUM_SAVED_REGS];
|
mutable unsigned SavedRegs[CU_NUM_SAVED_REGS];
|
||||||
|
Triple TT;
|
||||||
bool Is64Bit;
|
bool Is64Bit;
|
||||||
|
|
||||||
unsigned OffsetSize; ///< Offset of a "push" instruction.
|
unsigned OffsetSize; ///< Offset of a "push" instruction.
|
||||||
@ -838,10 +839,140 @@ protected:
|
|||||||
return 1;
|
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
|
/// Implementation of algorithm to generate the compact unwind encoding
|
||||||
/// for the CFI instructions.
|
/// for the CFI instructions.
|
||||||
uint32_t
|
uint32_t
|
||||||
generateCompactUnwindEncodingImpl(ArrayRef<MCCFIInstruction> Instrs) const {
|
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const override {
|
||||||
if (Instrs.empty()) return 0;
|
if (Instrs.empty()) return 0;
|
||||||
|
|
||||||
// Reset the saved registers.
|
// Reset the saved registers.
|
||||||
@ -991,168 +1122,6 @@ protected:
|
|||||||
|
|
||||||
return CompactUnwindEncoding;
|
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
|
} // end anonymous namespace
|
||||||
@ -1163,7 +1132,7 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
|
|||||||
const MCTargetOptions &Options) {
|
const MCTargetOptions &Options) {
|
||||||
const Triple &TheTriple = STI.getTargetTriple();
|
const Triple &TheTriple = STI.getTargetTriple();
|
||||||
if (TheTriple.isOSBinFormatMachO())
|
if (TheTriple.isOSBinFormatMachO())
|
||||||
return new DarwinX86_32AsmBackend(T, MRI, STI);
|
return new DarwinX86AsmBackend(T, MRI, STI);
|
||||||
|
|
||||||
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
||||||
return new WindowsX86AsmBackend(T, false, STI);
|
return new WindowsX86AsmBackend(T, false, STI);
|
||||||
@ -1181,13 +1150,8 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
|
|||||||
const MCRegisterInfo &MRI,
|
const MCRegisterInfo &MRI,
|
||||||
const MCTargetOptions &Options) {
|
const MCTargetOptions &Options) {
|
||||||
const Triple &TheTriple = STI.getTargetTriple();
|
const Triple &TheTriple = STI.getTargetTriple();
|
||||||
if (TheTriple.isOSBinFormatMachO()) {
|
if (TheTriple.isOSBinFormatMachO())
|
||||||
MachO::CPUSubTypeX86 CS =
|
return new DarwinX86AsmBackend(T, MRI, STI);
|
||||||
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.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
||||||
return new WindowsX86AsmBackend(T, true, STI);
|
return new WindowsX86AsmBackend(T, true, STI);
|
||||||
|
Loading…
Reference in New Issue
Block a user