1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +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:
Francis Visoiu Mistrih 2020-02-18 16:39:05 -08:00
parent 604077c19d
commit e3adf0fc70
9 changed files with 267 additions and 226 deletions

View File

@ -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;

View File

@ -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
View 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.");
}

View File

@ -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())

View File

@ -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);
} }

View File

@ -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);

View File

@ -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(

View File

@ -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);
} }
}; };

View File

@ -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);