Apple is adding Mach-O's riscv32 support to LLVM

4 months ago 24
diff --git a/llvm/lib/BinaryFormat/MachO.cpp b/llvm/lib/BinaryFormat/MachO.cpp index f46b9d5147ff1..369b5ba927136 100644 --- a/llvm/lib/BinaryFormat/MachO.cpp +++ b/llvm/lib/BinaryFormat/MachO.cpp @@ -74,6 +74,10 @@ static Error unsupported(const char *Str, const Triple &T) { T.str().c_str()); } +static MachO::CPUSubTypeRISCV getRISCVSubType(const Triple &T) { + return MachO::CPU_SUBTYPE_RISCV_ALL; +} + Expected<uint32_t> MachO::getCPUType(const Triple &T) { if (!T.isOSBinFormatMachO()) return unsupported("type", T); @@ -89,6 +93,8 @@ Expected<uint32_t> MachO::getCPUType(const Triple &T) { return MachO::CPU_TYPE_POWERPC; if (T.getArch() == Triple::ppc64) return MachO::CPU_TYPE_POWERPC64; + if (T.getArch() == Triple::riscv32) + return MachO::CPU_TYPE_RISCV; return unsupported("type", T); } @@ -103,6 +109,8 @@ Expected<uint32_t> MachO::getCPUSubType(const Triple &T) { return getARM64SubType(T); if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64) return getPowerPCSubType(T); + if (T.getArch() == Triple::riscv32) + return getRISCVSubType(T); return unsupported("subtype", T); } diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 5db264207ffb7..d0713dc77303b 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -2668,6 +2668,8 @@ StringRef MachOObjectFile::getFileFormatName() const { return "Mach-O arm64 (ILP32)"; case MachO::CPU_TYPE_POWERPC: return "Mach-O 32-bit ppc"; + case MachO::CPU_TYPE_RISCV: + return "Mach-O 32-bit RISC-V"; default: return "Mach-O 32-bit unknown"; } @@ -2701,6 +2703,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) return Triple::ppc; case MachO::CPU_TYPE_POWERPC64: return Triple::ppc64; + case MachO::CPU_TYPE_RISCV: + return Triple::riscv32; default: return Triple::UnknownArch; } @@ -2838,6 +2842,15 @@ Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, default: return Triple(); } + case MachO::CPU_TYPE_RISCV: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_RISCV_ALL: + if (ArchFlag) + *ArchFlag = "riscv32"; + return Triple("riscv32-apple-macho"); + default: + return Triple(); + } default: return Triple(); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt index e68c956f888e4..1a8dd50327dde 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_component_library(LLVMRISCVDesc RISCVBaseInfo.cpp RISCVELFObjectWriter.cpp RISCVInstPrinter.cpp + RISCVMachObjectWriter.cpp RISCVMCAsmInfo.cpp RISCVMCCodeEmitter.cpp RISCVMCExpr.cpp diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index f7f39439249e8..19f05522755c4 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" @@ -757,11 +758,28 @@ RISCVAsmBackend::createObjectTargetWriter() const { return createRISCVELFObjectWriter(OSABI, Is64Bit); } +class DarwinRISCVAsmBackend : public RISCVAsmBackend { +public: + DarwinRISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, + const MCTargetOptions &Options) + : RISCVAsmBackend(STI, OSABI, Is64Bit, Options) {} + + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { + const Triple &TT = STI.getTargetTriple(); + uint32_t CPUType = cantFail(MachO::getCPUType(TT)); + uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TT)); + return createRISCVMachObjectWriter(CPUType, CPUSubType); + } +}; + MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options) { const Triple &TT = STI.getTargetTriple(); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); + if (TT.isOSBinFormatMachO()) + return new DarwinRISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options); return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 4dffbb82e07c7..061332796e78c 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -22,6 +22,7 @@ class MCObjectTargetWriter; class raw_ostream; class RISCVAsmBackend : public MCAsmBackend { +protected: const MCSubtargetInfo &STI; uint8_t OSABI; bool Is64Bit; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp index e75bc521d47ca..4b9402391fe2c 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -47,3 +47,16 @@ const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, assert(Encoding & dwarf::DW_EH_PE_sdata4 && "Unexpected encoding"); return RISCVMCExpr::create(ME, ELF::R_RISCV_32_PCREL, Ctx); } + +RISCVMCAsmInfoDarwin::RISCVMCAsmInfoDarwin() { + CodePointerSize = 4; + PrivateGlobalPrefix = "L"; + PrivateLabelPrefix = "L"; + SeparatorString = "%%"; + CommentString = ";"; + AlignmentIsInBytes = false; + SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::DwarfCFI; + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; +} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h index bceeb1256471d..73271f6278f5f 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H +#include "llvm/MC/MCAsmInfoDarwin.h" #include "llvm/MC/MCAsmInfoELF.h" namespace llvm { @@ -28,6 +29,11 @@ class RISCVMCAsmInfo : public MCAsmInfoELF { MCStreamer &Streamer) const override; }; +class RISCVMCAsmInfoDarwin : public MCAsmInfoDarwin { +public: + explicit RISCVMCAsmInfoDarwin(); +}; + } // namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp index d1bc6aa9a1e33..9d2caa1106ef5 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -58,7 +58,11 @@ static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) { static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT, const MCTargetOptions &Options) { - MCAsmInfo *MAI = new RISCVMCAsmInfo(TT); + MCAsmInfo *MAI = nullptr; + if (TT.isOSBinFormatELF()) + MAI = new RISCVMCAsmInfo(TT); + else if (TT.isOSBinFormatMachO()) + MAI = new RISCVMCAsmInfoDarwin(); unsigned SP = MRI.getDwarfRegNum(RISCV::X2, true); MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h index bdee7ed4f011e..2a4afdb05d0f1 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h @@ -36,6 +36,9 @@ MCAsmBackend *createRISCVAsmBackend(const Target &T, const MCSubtargetInfo &STI, std::unique_ptr<MCObjectTargetWriter> createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); +std::unique_ptr<MCObjectTargetWriter> +createRISCVMachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype); + } // namespace llvm // Defines symbolic names for RISC-V registers. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp new file mode 100644 index 0000000000000..aa1f6122f6992 --- /dev/null +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp @@ -0,0 +1,57 @@ +//===-- RISCVMachObjectWriter.cpp - RISC-V Mach Object Writer -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/RISCVFixupKinds.h" +#include "MCTargetDesc/RISCVMCExpr.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/MCAsmInfo.h" +// #include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstdint> + +using namespace llvm; + +namespace { + +class RISCVMachObjectWriter : public MCMachObjectTargetWriter { +public: + RISCVMachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype) + : MCMachObjectTargetWriter(false, CPUType, CPUSubtype) {} + + void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) override; +}; + +} // end anonymous namespace + +void RISCVMachObjectWriter::recordRelocation( + MachObjectWriter *Writer, MCAssembler &Asm, const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { + llvm_unreachable("unimplemented"); +} + +std::unique_ptr<MCObjectTargetWriter> +llvm::createRISCVMachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype) { + return std::make_unique<RISCVMachObjectWriter>(CPUType, CPUSubtype); +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 15dd4d57727dd..779a2bde1166a 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -156,6 +156,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { static StringRef computeDataLayout(const Triple &TT, const TargetOptions &Options) { StringRef ABIName = Options.MCOptions.getABIName(); + if (TT.isOSBinFormatMachO()) + return "e-m:o-p:32:32-i64:64-n32-S128"; + if (TT.isArch64Bit()) { if (ABIName == "lp64e") return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"; @@ -175,6 +178,15 @@ static Reloc::Model getEffectiveRelocModel(const Triple &TT, return RM.value_or(Reloc::Static); } +static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { + if (TT.isOSBinFormatELF()) + return std::make_unique<RISCVELFTargetObjectFile>(); + else if (TT.isOSBinFormatMachO()) + return std::make_unique<TargetLoweringObjectFileMachO>(); + else + return std::unique_ptr<TargetLoweringObjectFile>(); +} + RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -184,7 +196,7 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, : CodeGenTargetMachineImpl(T, computeDataLayout(TT, Options), TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM), getEffectiveCodeModel(CM, CodeModel::Small), OL), - TLOF(std::make_unique<RISCVELFTargetObjectFile>()) { + TLOF(createTLOF(TT)) { initAsmInfo(); // RISC-V supports the MachineOutliner. diff --git a/llvm/test/CodeGen/RISCV/riscv-macho.ll b/llvm/test/CodeGen/RISCV/riscv-macho.ll new file mode 100644 index 0000000000000..19d5fc026bbee --- /dev/null +++ b/llvm/test/CodeGen/RISCV/riscv-macho.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=riscv32-apple-macho %s -o - | FileCheck %s +; RUN: llc -mtriple=riscv32-apple-macho -filetype=obj %s -o %t.o +; RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=CHECK-OBJ + +; CHECK-LABEL: _main: +; CHECK: li a0, 0 +; CHECK: ret + +; CHECK-OBJ: li a0, 0 +; CHECK-OBJ: ret +define i32 @main() nounwind { + ret i32 0 +} diff --git a/llvm/test/MC/RISCV/riscv-macho.s b/llvm/test/MC/RISCV/riscv-macho.s new file mode 100644 index 0000000000000..f2cec7bf08ebb --- /dev/null +++ b/llvm/test/MC/RISCV/riscv-macho.s @@ -0,0 +1,26 @@ +; RUN: llvm-mc -triple riscv32-apple-macho %s -o - | FileCheck %s +; RUN: llvm-mc -triple riscv32-apple-macho -filetype=obj %s -o %t.o +; RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=CHECK-DIS +; RUN: llvm-nm %t.o | FileCheck %s --check-prefix=CHECK-SYMS + + nop + .half 42 + .word 42 +Lfoo: +lfoo: +foo: + +; CHECK: nop +; CHECK: .half 42 +; CHECK: .word 42 + +; CHECK-DIS: file format mach-o 32-bit risc-v +; CHECK-DIS: Disassembly of section __TEXT,__text: +; CHECK-DIS: nop +; CHECK-DIS: 002a <unknown> +; CHECK-DIS: 002a <unknown> +; CHECK-DIS: 0000 <unknown> + +; CHECK-SYMS-NOT: Lfoo +; CHECK-SYMS: foo +; CHECK-SYMS: lfoo
Read Entire Article