#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
-#include "llvm/Support/ARMTargetParser.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
}
}
-static MachO::CPUSubTypeX86 getX86SubTypeFromTriple(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 getARMSubTypeFromTriple(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 getARM64SubTypeFromTriple(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 getPowerPCSubTypeFromTriple(const Triple &T) {
- return MachO::CPU_SUBTYPE_POWERPC_ALL;
-}
-
-Expected<uint32_t> MachOObjectFile::getCPUTypeFromTriple(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> MachOObjectFile::getCPUSubTypeFromTriple(const Triple &T) {
- if (T.isX86())
- return getX86SubTypeFromTriple(T);
- if (T.isARM() || T.isThumb())
- return getARMSubTypeFromTriple(T);
- if (T.isAArch64() || T.getArch() == Triple::aarch64_32)
- return getARM64SubTypeFromTriple(T);
- if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64)
- return getPowerPCSubTypeFromTriple(T);
- return createStringError(std::errc::invalid_argument,
- "Unsupported triple for mach-o cpu subtype.");
-}
-
Triple MachOObjectFile::getHostArch() {
return Triple(sys::getDefaultTargetTriple());
}
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
-#include "llvm/Object/MachO.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
enum { CU_NUM_SAVED_REGS = 6 };
mutable unsigned SavedRegs[CU_NUM_SAVED_REGS];
- Triple TT;
bool Is64Bit;
unsigned OffsetSize; ///< Offset of a "push" instruction.
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(object::MachOObjectFile::getCPUTypeFromTriple(TT));
- uint32_t CPUSubType =
- cantFail(object::MachOObjectFile::getCPUSubTypeFromTriple(TT));
- return createX86MachObjectWriter(Is64Bit, CPUType, CPUSubType);
- }
-
/// Implementation of algorithm to generate the compact unwind encoding
/// for the CFI instructions.
uint32_t
- generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const override {
+ generateCompactUnwindEncodingImpl(ArrayRef<MCCFIInstruction> Instrs) const {
if (Instrs.empty()) return 0;
// Reset the saved registers.
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
const MCTargetOptions &Options) {
const Triple &TheTriple = STI.getTargetTriple();
if (TheTriple.isOSBinFormatMachO())
- return new DarwinX86AsmBackend(T, MRI, STI);
+ return new DarwinX86_32AsmBackend(T, MRI, STI);
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
return new WindowsX86AsmBackend(T, false, STI);
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
const Triple &TheTriple = STI.getTargetTriple();
- if (TheTriple.isOSBinFormatMachO())
- return new DarwinX86AsmBackend(T, MRI, STI);
+ 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.isOSWindows() && TheTriple.isOSBinFormatCOFF())
return new WindowsX86AsmBackend(T, true, STI);