1 //===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/BinaryFormat/MachO.h"
10 #include "llvm/ADT/Triple.h"
11 #include "llvm/Support/ARMTargetParser.h"
12
13 using namespace llvm;
14
getX86SubType(const Triple & T)15 static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) {
16 assert(T.isX86());
17 if (T.isArch32Bit())
18 return MachO::CPU_SUBTYPE_I386_ALL;
19
20 assert(T.isArch64Bit());
21 if (T.getArchName() == "x86_64h")
22 return MachO::CPU_SUBTYPE_X86_64_H;
23 return MachO::CPU_SUBTYPE_X86_64_ALL;
24 }
25
getARMSubType(const Triple & T)26 static MachO::CPUSubTypeARM getARMSubType(const Triple &T) {
27 assert(T.isARM() || T.isThumb());
28 StringRef Arch = T.getArchName();
29 ARM::ArchKind AK = ARM::parseArch(Arch);
30 switch (AK) {
31 default:
32 return MachO::CPU_SUBTYPE_ARM_V7;
33 case ARM::ArchKind::ARMV4T:
34 return MachO::CPU_SUBTYPE_ARM_V4T;
35 case ARM::ArchKind::ARMV5T:
36 case ARM::ArchKind::ARMV5TE:
37 case ARM::ArchKind::ARMV5TEJ:
38 return MachO::CPU_SUBTYPE_ARM_V5;
39 case ARM::ArchKind::ARMV6:
40 case ARM::ArchKind::ARMV6K:
41 return MachO::CPU_SUBTYPE_ARM_V6;
42 case ARM::ArchKind::ARMV7A:
43 return MachO::CPU_SUBTYPE_ARM_V7;
44 case ARM::ArchKind::ARMV7S:
45 return MachO::CPU_SUBTYPE_ARM_V7S;
46 case ARM::ArchKind::ARMV7K:
47 return MachO::CPU_SUBTYPE_ARM_V7K;
48 case ARM::ArchKind::ARMV6M:
49 return MachO::CPU_SUBTYPE_ARM_V6M;
50 case ARM::ArchKind::ARMV7M:
51 return MachO::CPU_SUBTYPE_ARM_V7M;
52 case ARM::ArchKind::ARMV7EM:
53 return MachO::CPU_SUBTYPE_ARM_V7EM;
54 }
55 }
56
getARM64SubType(const Triple & T)57 static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {
58 assert(T.isAArch64());
59 if (T.isArch32Bit())
60 return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;
61 if (T.isArm64e())
62 return MachO::CPU_SUBTYPE_ARM64E;
63
64 return MachO::CPU_SUBTYPE_ARM64_ALL;
65 }
66
getPowerPCSubType(const Triple & T)67 static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) {
68 return MachO::CPU_SUBTYPE_POWERPC_ALL;
69 }
70
unsupported(const char * Str,const Triple & T)71 static Error unsupported(const char *Str, const Triple &T) {
72 return createStringError(std::errc::invalid_argument,
73 "Unsupported triple for mach-o cpu %s: %s", Str,
74 T.str().c_str());
75 }
76
getCPUType(const Triple & T)77 Expected<uint32_t> MachO::getCPUType(const Triple &T) {
78 if (!T.isOSBinFormatMachO())
79 return unsupported("type", T);
80 if (T.isX86() && T.isArch32Bit())
81 return MachO::CPU_TYPE_X86;
82 if (T.isX86() && T.isArch64Bit())
83 return MachO::CPU_TYPE_X86_64;
84 if (T.isARM() || T.isThumb())
85 return MachO::CPU_TYPE_ARM;
86 if (T.isAArch64())
87 return T.isArch32Bit() ? MachO::CPU_TYPE_ARM64_32 : MachO::CPU_TYPE_ARM64;
88 if (T.getArch() == Triple::ppc)
89 return MachO::CPU_TYPE_POWERPC;
90 if (T.getArch() == Triple::ppc64)
91 return MachO::CPU_TYPE_POWERPC64;
92 return unsupported("type", T);
93 }
94
getCPUSubType(const Triple & T)95 Expected<uint32_t> MachO::getCPUSubType(const Triple &T) {
96 if (!T.isOSBinFormatMachO())
97 return unsupported("subtype", T);
98 if (T.isX86())
99 return getX86SubType(T);
100 if (T.isARM() || T.isThumb())
101 return getARMSubType(T);
102 if (T.isAArch64() || T.getArch() == Triple::aarch64_32)
103 return getARM64SubType(T);
104 if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64)
105 return getPowerPCSubType(T);
106 return unsupported("subtype", T);
107 }
108