armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
+ aarch64_32, // AArch64 (little endian) ILP32: aarch64_32
arc, // ARC: Synopsys ARC
avr, // AVR: Atmel AVR microcontroller
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
enum : uint32_t {
// Capability bits used in the definition of cpu_type.
CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits
- CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI
+ CPU_ARCH_ABI64 = 0x01000000, // 64 bit ABI
+ CPU_ARCH_ABI64_32 = 0x02000000, // ILP32 ABI on 64-bit hardware
};
// Constants for the cputype field.
CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC
CPU_TYPE_ARM = 12,
CPU_TYPE_ARM64 = CPU_TYPE_ARM | CPU_ARCH_ABI64,
+ CPU_TYPE_ARM64_32 = CPU_TYPE_ARM | CPU_ARCH_ABI64_32,
CPU_TYPE_SPARC = 14,
CPU_TYPE_POWERPC = 18,
CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
CPU_SUBTYPE_ARM64E = 2,
};
+enum CPUSubTypeARM64_32 { CPU_SUBTYPE_ARM64_32_V8 = 1 };
+
enum CPUSubTypeSPARC { CPU_SUBTYPE_SPARC_ALL = 0 };
enum CPUSubTypePowerPC {
"flavor number " + Twine(nflavor) + " in " +
CmdName + " command");
}
- } else if (cputype == MachO::CPU_TYPE_ARM64) {
+ } else if (cputype == MachO::CPU_TYPE_ARM64 ||
+ cputype == MachO::CPU_TYPE_ARM64_32) {
if (flavor == MachO::ARM_THREAD_STATE64) {
if (count != MachO::ARM_THREAD_STATE64_COUNT)
return malformedError("load command " + Twine(LoadCommandIndex) +
res = Table[RType];
break;
}
- case Triple::aarch64: {
+ case Triple::aarch64:
+ case Triple::aarch64_32: {
static const char *const Table[] = {
"ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
"ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
return "Mach-O 32-bit i386";
case MachO::CPU_TYPE_ARM:
return "Mach-O arm";
+ case MachO::CPU_TYPE_ARM64_32:
+ return "Mach-O arm64 (ILP32)";
case MachO::CPU_TYPE_POWERPC:
return "Mach-O 32-bit ppc";
default:
return Triple::arm;
case MachO::CPU_TYPE_ARM64:
return Triple::aarch64;
+ case MachO::CPU_TYPE_ARM64_32:
+ return Triple::aarch64_32;
case MachO::CPU_TYPE_POWERPC:
return Triple::ppc;
case MachO::CPU_TYPE_POWERPC64:
default:
return Triple();
}
+ case MachO::CPU_TYPE_ARM64_32:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_32_V8:
+ if (McpuDefault)
+ *McpuDefault = "cyclone";
+ if (ArchFlag)
+ *ArchFlag = "arm64_32";
+ return Triple("arm64_32-apple-darwin");
+ default:
+ return Triple();
+ }
case MachO::CPU_TYPE_POWERPC:
switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
case MachO::CPU_SUBTYPE_POWERPC_ALL:
.Case("armv7m", true)
.Case("armv7s", true)
.Case("arm64", true)
+ .Case("arm64_32", true)
.Case("ppc", true)
.Case("ppc64", true)
.Default(false);
return EndianKind::LITTLE;
}
- if (Arch.startswith("aarch64"))
+ if (Arch.startswith("aarch64") || Arch.startswith("aarch64_32"))
return EndianKind::LITTLE;
return EndianKind::INVALID;
StringRef Error = "";
// Begins with "arm" / "thumb", move past it.
- if (A.startswith("arm64"))
+ if (A.startswith("arm64_32"))
+ offset = 8;
+ else if (A.startswith("arm64"))
offset = 5;
+ else if (A.startswith("aarch64_32"))
+ offset = 10;
else if (A.startswith("arm"))
offset = 3;
else if (A.startswith("thumb"))
case aarch64: return "aarch64";
case aarch64_be: return "aarch64_be";
+ case aarch64_32: return "aarch64_32";
case arm: return "arm";
case armeb: return "armeb";
case arc: return "arc";
return StringRef();
case aarch64:
- case aarch64_be: return "aarch64";
+ case aarch64_be:
+ case aarch64_32: return "aarch64";
case arc: return "arc";
return StringSwitch<Triple::ArchType>(Name)
.Case("aarch64", aarch64)
.Case("aarch64_be", aarch64_be)
+ .Case("aarch64_32", aarch64_32)
.Case("arc", arc)
.Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
+ .Case("arm64_32", aarch64_32)
.Case("arm", arm)
.Case("armeb", armeb)
.Case("avr", avr)
.Case("xscaleeb", Triple::armeb)
.Case("aarch64", Triple::aarch64)
.Case("aarch64_be", Triple::aarch64_be)
+ .Case("aarch64_32", Triple::aarch64_32)
.Case("arc", Triple::arc)
.Case("arm64", Triple::aarch64)
+ .Case("arm64_32", Triple::aarch64_32)
.Case("arm", Triple::arm)
.Case("armeb", Triple::armeb)
.Case("thumb", Triple::thumb)
switch (T.getArch()) {
case Triple::UnknownArch:
case Triple::aarch64:
+ case Triple::aarch64_32:
case Triple::arm:
case Triple::thumb:
case Triple::x86:
case llvm::Triple::msp430:
return 16;
+ case llvm::Triple::aarch64_32:
case llvm::Triple::arc:
case llvm::Triple::arm:
case llvm::Triple::armeb:
T.setArch(UnknownArch);
break;
+ case Triple::aarch64_32:
case Triple::amdil:
case Triple::hsail:
case Triple::spir:
// Already 64-bit.
break;
+ case Triple::aarch64_32: T.setArch(Triple::aarch64); break;
case Triple::arm: T.setArch(Triple::aarch64); break;
case Triple::armeb: T.setArch(Triple::aarch64_be); break;
case Triple::le32: T.setArch(Triple::le64); break;
bool Triple::isLittleEndian() const {
switch (getArch()) {
case Triple::aarch64:
+ case Triple::aarch64_32:
case Triple::amdgcn:
case Triple::amdil64:
case Triple::amdil:
RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
+ RegisterMCAsmParser<AArch64AsmParser> W(getTheARM64_32Target());
+ RegisterMCAsmParser<AArch64AsmParser> V(getTheAArch64_32Target());
}
#define GET_REGISTER_MATCHER
createAArch64ExternalSymbolizer);
TargetRegistry::RegisterMCSymbolizer(getTheAArch64beTarget(),
createAArch64ExternalSymbolizer);
+ TargetRegistry::RegisterMCDisassembler(getTheAArch64_32Target(),
+ createAArch64Disassembler);
+ TargetRegistry::RegisterMCSymbolizer(getTheAArch64_32Target(),
+ createAArch64ExternalSymbolizer);
TargetRegistry::RegisterMCDisassembler(getTheARM64Target(),
createAArch64Disassembler);
TargetRegistry::RegisterMCSymbolizer(getTheARM64Target(),
createAArch64ExternalSymbolizer);
+ TargetRegistry::RegisterMCDisassembler(getTheARM64_32Target(),
+ createAArch64Disassembler);
+ TargetRegistry::RegisterMCSymbolizer(getTheARM64_32Target(),
+ createAArch64ExternalSymbolizer);
}
static const unsigned FPR128DecoderTable[] = {
// FIXME: This should be in a separate file.
class DarwinAArch64AsmBackend : public AArch64AsmBackend {
const MCRegisterInfo &MRI;
+ bool IsILP32;
/// Encode compact unwind stack adjustment for frameless functions.
/// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
public:
DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
- const MCRegisterInfo &MRI)
- : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
+ const MCRegisterInfo &MRI, bool IsILP32)
+ : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI),
+ IsILP32(IsILP32) {}
std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override {
- return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
- MachO::CPU_SUBTYPE_ARM64_ALL);
+ if (IsILP32)
+ return createAArch64MachObjectWriter(
+ MachO::CPU_TYPE_ARM64_32, MachO::CPU_SUBTYPE_ARM64_32_V8, true);
+ else
+ return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
+ MachO::CPU_SUBTYPE_ARM64_ALL, false);
}
/// Generate the compact unwind encoding from the CFI directives.
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
const Triple &TheTriple = STI.getTargetTriple();
- if (TheTriple.isOSBinFormatMachO())
- return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
+ if (TheTriple.isOSBinFormatMachO()) {
+ const bool IsILP32 = TheTriple.isArch32Bit();
+ return new DarwinAArch64AsmBackend(T, TheTriple, MRI, IsILP32);
+ }
if (TheTriple.isOSBinFormatCOFF())
return new COFFAArch64AsmBackend(T, TheTriple);
// Force static initialization.
extern "C" void LLVMInitializeAArch64TargetMC() {
for (Target *T : {&getTheAArch64leTarget(), &getTheAArch64beTarget(),
- &getTheARM64Target()}) {
+ &getTheAArch64_32Target(), &getTheARM64Target(),
+ &getTheARM64_32Target()}) {
// Register the MC asm info.
RegisterMCAsmInfoFn X(*T, createAArch64MCAsmInfo);
}
// Register the asm backend.
- for (Target *T : {&getTheAArch64leTarget(), &getTheARM64Target()})
+ for (Target *T : {&getTheAArch64leTarget(), &getTheAArch64_32Target(),
+ &getTheARM64Target(), &getTheARM64_32Target()})
TargetRegistry::RegisterMCAsmBackend(*T, createAArch64leAsmBackend);
TargetRegistry::RegisterMCAsmBackend(getTheAArch64beTarget(),
createAArch64beAsmBackend);
Target &getTheAArch64leTarget();
Target &getTheAArch64beTarget();
+Target &getTheAArch64_32Target();
Target &getTheARM64Target();
+Target &getTheARM64_32Target();
MCCodeEmitter *createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32);
std::unique_ptr<MCObjectTargetWriter>
-createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype);
+createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype,
+ bool IsILP32);
std::unique_ptr<MCObjectTargetWriter> createAArch64WinCOFFObjectWriter();
unsigned &Log2Size, const MCAssembler &Asm);
public:
- AArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype)
- : MCMachObjectTargetWriter(true /* is64Bit */, CPUType, CPUSubtype) {}
+ AArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype, bool IsILP32)
+ : MCMachObjectTargetWriter(!IsILP32 /* is64Bit */, CPUType, CPUSubtype) {}
void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCFragment *Fragment,
}
std::unique_ptr<MCObjectTargetWriter>
-llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype) {
- return llvm::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype);
+llvm::createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype,
+ bool IsILP32) {
+ return llvm::make_unique<AArch64MachObjectWriter>(CPUType, CPUSubtype,
+ IsILP32);
}
static Target TheAArch64beTarget;
return TheAArch64beTarget;
}
+Target &getTheAArch64_32Target() {
+ static Target TheAArch64leTarget;
+ return TheAArch64leTarget;
+}
Target &getTheARM64Target() {
static Target TheARM64Target;
return TheARM64Target;
}
+Target &getTheARM64_32Target() {
+ static Target TheARM64_32Target;
+ return TheARM64_32Target;
+}
} // namespace llvm
extern "C" void LLVMInitializeAArch64TargetInfo() {
// Now register the "arm64" name for use with "-march". We don't want it to
- // take possession of the Triple::aarch64 tag though.
+ // take possession of the Triple::aarch64 tags though.
TargetRegistry::RegisterTarget(getTheARM64Target(), "arm64",
"ARM64 (little endian)", "AArch64",
[](Triple::ArchType) { return false; }, true);
+ TargetRegistry::RegisterTarget(getTheARM64_32Target(), "arm64_32",
+ "ARM64 (little endian ILP32)", "AArch64",
+ [](Triple::ArchType) { return false; }, true);
RegisterTarget<Triple::aarch64, /*HasJIT=*/true> Z(
getTheAArch64leTarget(), "aarch64", "AArch64 (little endian)", "AArch64");
RegisterTarget<Triple::aarch64_be, /*HasJIT=*/true> W(
getTheAArch64beTarget(), "aarch64_be", "AArch64 (big endian)", "AArch64");
+ RegisterTarget<Triple::aarch64_32, /*HasJIT=*/true> X(
+ getTheAArch64_32Target(), "aarch64_32", "AArch64 (little endian ILP32)", "AArch64");
}
--- /dev/null
+RUN: llvm-nm -arch arm64_32 %p/../Inputs/trivial-object-test.macho-arm64_32 \
+RUN: | FileCheck %s
+
+CHECK: 00000000 T _foo
+CHECK: 00000000 t ltmp0
--- /dev/null
+RUN: llvm-objdump -macho -universal-headers %p/Inputs/arm64_32-fat.o | FileCheck %s
+
+CHECK: cputype CPU_TYPE_ARM64_32
+CHECK-NEXT: cpusubtype CPU_SUBTYPE_ARM64_32_V8
+
+CHECK: cputype CPU_TYPE_ARM64
+CHECK-NEXT: cpusubtype CPU_SUBTYPE_ARM64_ALL
--- /dev/null
+// RUN: llvm-mc -triple arm64_32-apple-watchos %s -filetype=obj -o %t
+// RUN: llvm-objdump -macho -d %t | FileCheck %s
+// RUN: llvm-objdump -macho -private-headers %t | FileCheck %s --check-prefix=CHECK-HEADERS
+
+// CHECK: ldr x0, [x2]
+ldr x0, [x2]
+
+// CHECK-HEADERS: MH_MAGIC ARM64_32 V8
--- /dev/null
+RUN: llvm-objdump -macho -private-headers %p/Inputs/thread.macho-arm64_32 | FileCheck %s
+
+CHECK: Load command 0
+CHECK: cmd LC_UNIXTHREAD
+CHECK: cmdsize 288
+CHECK: flavor ARM_THREAD_STATE64
+CHECK: count ARM_THREAD_STATE64_COUNT
+CHECK: x0 0x0000000000000000 x1 0x0000000000000000 x2 0x0000000000000000
+CHECK: x3 0x0000000000000000 x4 0x0000000000000000 x5 0x0000000000000000
+CHECK: x6 0x0000000000000000 x7 0x0000000000000000 x8 0x0000000000000000
+CHECK: x9 0x0000000000000000 x10 0x0000000000000000 x11 0x0000000000000000
+CHECK: x12 0x0000000000000000 x13 0x0000000000000000 x14 0x0000000000000000
+CHECK: x15 0x0000000000000000 x16 0x0000000000000000 x17 0x0000000000000000
+CHECK: x18 0x0000000000000000 x19 0x0000000000000000 x20 0x0000000000000000
+CHECK: x21 0x0000000000000000 x22 0x0000000000000000 x23 0x0000000000000000
+CHECK: x24 0x0000000000000000 x25 0x0000000000000000 x26 0x0000000000000000
+CHECK: x27 0x0000000000000000 x28 0x0000000000000000 fp 0x0000000000000000
+CHECK: lr 0x0000000000000000 sp 0x0000000000000000 pc 0x0000000000007fd4
+CHECK: cpsr 0x00000000
outs() << arm_r_types[r_type];
break;
case MachO::CPU_TYPE_ARM64:
+ case MachO::CPU_TYPE_ARM64_32:
outs() << arm64_r_types[r_type];
break;
default:
// plain: symbolnum/value
if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
- else if (cputype == MachO::CPU_TYPE_ARM64 &&
+ else if ((cputype == MachO::CPU_TYPE_ARM64 ||
+ cputype == MachO::CPU_TYPE_ARM64_32) &&
r_type == MachO::ARM64_RELOC_ADDEND)
outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
else {
break;
}
break;
+ case MachO::CPU_TYPE_ARM64_32:
+ switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_32_V8:
+ outs() << " cputype CPU_TYPE_ARM64_32\n";
+ outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n";
+ break;
+ default:
+ printUnknownCPUType(cputype, cpusubtype);
+ break;
+ }
+ break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
break;
}
break;
+ case MachO::CPU_TYPE_ARM64_32:
+ outs() << " ARM64_32";
+ switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_32_V8:
+ outs() << " V8";
+ break;
+ default:
+ outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
+ break;
+ }
+ break;
case MachO::CPU_TYPE_POWERPC:
outs() << " PPC";
switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
begin += count * sizeof(uint32_t);
}
}
- } else if (cputype == MachO::CPU_TYPE_ARM64) {
+ } else if (cputype == MachO::CPU_TYPE_ARM64 ||
+ cputype == MachO::CPU_TYPE_ARM64_32) {
while (begin < end) {
if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
memcpy((char *)&flavor, begin, sizeof(uint32_t));