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 
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 
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 
57 static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {
58   assert(T.isAArch64() || T.getArch() == Triple::aarch64_32);
59   if (T.isArch32Bit())
60     return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;
61   if (T.getArchName() == "arm64e")
62     return MachO::CPU_SUBTYPE_ARM64E;
63 
64   return MachO::CPU_SUBTYPE_ARM64_ALL;
65 }
66 
67 static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) {
68   return MachO::CPU_SUBTYPE_POWERPC_ALL;
69 }
70 
71 Expected<uint32_t> MachO::getCPUType(const Triple &T) {
72   if (T.isX86() && T.isArch32Bit())
73     return MachO::CPU_TYPE_X86;
74   if (T.isX86() && T.isArch64Bit())
75     return MachO::CPU_TYPE_X86_64;
76   if (T.isARM() || T.isThumb())
77     return MachO::CPU_TYPE_ARM;
78   if (T.isAArch64())
79     return MachO::CPU_TYPE_ARM64;
80   if (T.getArch() == Triple::aarch64_32)
81     return MachO::CPU_TYPE_ARM64_32;
82   if (T.getArch() == Triple::ppc)
83     return MachO::CPU_TYPE_POWERPC;
84   if (T.getArch() == Triple::ppc64)
85     return MachO::CPU_TYPE_POWERPC64;
86   return createStringError(std::errc::invalid_argument,
87                            "Unsupported triple for mach-o cpu type.");
88 }
89 
90 Expected<uint32_t> MachO::getCPUSubType(const Triple &T) {
91   if (T.isX86())
92     return getX86SubType(T);
93   if (T.isARM() || T.isThumb())
94     return getARMSubType(T);
95   if (T.isAArch64() || T.getArch() == Triple::aarch64_32)
96     return getARM64SubType(T);
97   if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64)
98     return getPowerPCSubType(T);
99   return createStringError(std::errc::invalid_argument,
100                            "Unsupported triple for mach-o cpu subtype.");
101 }
102