Skip to content

Commit

Permalink
AArch64: support binutils-like things on arm64_32.
Browse files Browse the repository at this point in the history
This adds support for the arm64_32 watchOS ABI to LLVM's low level tools,
teaching them about the specific MachO choices and constants needed to
disassemble things.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360663 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
TNorthover committed May 14, 2019
1 parent 0f7b4d7 commit 38bc73c
Show file tree
Hide file tree
Showing 20 changed files with 162 additions and 22 deletions.
1 change: 1 addition & 0 deletions include/llvm/ADT/Triple.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Triple {
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)
Expand Down
6 changes: 5 additions & 1 deletion include/llvm/BinaryFormat/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,8 @@ inline void SET_COMM_ALIGN(uint16_t &n_desc, uint8_t align) {
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.
Expand All @@ -1414,6 +1415,7 @@ enum CPUType {
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
Expand Down Expand Up @@ -1487,6 +1489,8 @@ enum CPUSubTypeARM64 {
CPU_SUBTYPE_ARM64E = 2,
};

enum CPUSubTypeARM64_32 { CPU_SUBTYPE_ARM64_32_V8 = 1 };

enum CPUSubTypeSPARC { CPU_SUBTYPE_SPARC_ALL = 0 };

enum CPUSubTypePowerPC {
Expand Down
22 changes: 20 additions & 2 deletions lib/Object/MachOObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,8 @@ static Error checkThreadCommand(const MachOObjectFile &Obj,
"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) +
Expand Down Expand Up @@ -2170,7 +2171,8 @@ void MachOObjectFile::getRelocationTypeName(
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",
Expand Down Expand Up @@ -2498,6 +2500,8 @@ StringRef MachOObjectFile::getFileFormatName() const {
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:
Expand Down Expand Up @@ -2527,6 +2531,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
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:
Expand Down Expand Up @@ -2633,6 +2639,17 @@ Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
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:
Expand Down Expand Up @@ -2676,6 +2693,7 @@ bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
.Case("armv7m", true)
.Case("armv7s", true)
.Case("arm64", true)
.Case("arm64_32", true)
.Case("ppc", true)
.Case("ppc64", true)
.Default(false);
Expand Down
8 changes: 6 additions & 2 deletions lib/Support/ARMTargetParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
return EndianKind::LITTLE;
}

if (Arch.startswith("aarch64"))
if (Arch.startswith("aarch64") || Arch.startswith("aarch64_32"))
return EndianKind::LITTLE;

return EndianKind::INVALID;
Expand Down Expand Up @@ -289,8 +289,12 @@ StringRef ARM::getCanonicalArchName(StringRef Arch) {
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"))
Expand Down
13 changes: 12 additions & 1 deletion lib/Support/Triple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) {

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";
Expand Down Expand Up @@ -80,7 +81,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
return StringRef();

case aarch64:
case aarch64_be: return "aarch64";
case aarch64_be:
case aarch64_32: return "aarch64";

case arc: return "arc";

Expand Down Expand Up @@ -260,8 +262,10 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
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)
Expand Down Expand Up @@ -389,8 +393,10 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.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)
Expand Down Expand Up @@ -636,6 +642,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
switch (T.getArch()) {
case Triple::UnknownArch:
case Triple::aarch64:
case Triple::aarch64_32:
case Triple::arm:
case Triple::thumb:
case Triple::x86:
Expand Down Expand Up @@ -1219,6 +1226,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::msp430:
return 16;

case llvm::Triple::aarch64_32:
case llvm::Triple::arc:
case llvm::Triple::arm:
case llvm::Triple::armeb:
Expand Down Expand Up @@ -1299,6 +1307,7 @@ Triple Triple::get32BitArchVariant() const {
T.setArch(UnknownArch);
break;

case Triple::aarch64_32:
case Triple::amdil:
case Triple::hsail:
case Triple::spir:
Expand Down Expand Up @@ -1390,6 +1399,7 @@ Triple Triple::get64BitArchVariant() const {
// 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;
Expand Down Expand Up @@ -1500,6 +1510,7 @@ Triple Triple::getLittleEndianArchVariant() const {
bool Triple::isLittleEndian() const {
switch (getArch()) {
case Triple::aarch64:
case Triple::aarch64_32:
case Triple::amdgcn:
case Triple::amdil64:
case Triple::amdil:
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5514,6 +5514,8 @@ extern "C" void LLVMInitializeAArch64AsmParser() {
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
Expand Down
8 changes: 8 additions & 0 deletions lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,19 @@ extern "C" void LLVMInitializeAArch64Disassembler() {
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[] = {
Expand Down
20 changes: 14 additions & 6 deletions lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ enum CompactUnwindEncodings {
// 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.
Expand All @@ -522,13 +523,18 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend {

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.
Expand Down Expand Up @@ -710,8 +716,10 @@ MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
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);
Expand Down
6 changes: 4 additions & 2 deletions lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ static MCInstrAnalysis *createAArch64InstrAnalysis(const MCInstrInfo *Info) {
// 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);

Expand Down Expand Up @@ -227,7 +228,8 @@ extern "C" void LLVMInitializeAArch64TargetMC() {
}

// 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);
Expand Down
5 changes: 4 additions & 1 deletion lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ class raw_pwrite_stream;

Target &getTheAArch64leTarget();
Target &getTheAArch64beTarget();
Target &getTheAArch64_32Target();
Target &getTheARM64Target();
Target &getTheARM64_32Target();

MCCodeEmitter *createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
Expand All @@ -56,7 +58,8 @@ std::unique_ptr<MCObjectTargetWriter>
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();

Expand Down
10 changes: 6 additions & 4 deletions lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class AArch64MachObjectWriter : public MCMachObjectTargetWriter {
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,
Expand Down Expand Up @@ -404,6 +404,8 @@ void AArch64MachObjectWriter::recordRelocation(
}

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);
}
15 changes: 14 additions & 1 deletion lib/Target/AArch64/TargetInfo/AArch64TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,34 @@ Target &getTheAArch64beTarget() {
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");
}
5 changes: 5 additions & 0 deletions test/Object/AArch64/nm-trivial-object-arm64_32.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
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
Binary file not shown.
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions test/tools/llvm-objdump/AArch64/arm64_32-fat.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
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
8 changes: 8 additions & 0 deletions test/tools/llvm-objdump/AArch64/arm64_32.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 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
Loading

0 comments on commit 38bc73c

Please sign in to comment.