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 MachO::getCPUType(const Triple &T) { if (!T.isOSBinFormatMachO()) return unsupported("type", T); @@ -89,6 +93,8 @@ Expected 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 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 e09dc947c2779..da6cc45b2cf16 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..7829b6e4bcd18 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_component_library(LLVMRISCVDesc RISCVMCExpr.cpp RISCVMCObjectFileInfo.cpp RISCVMCTargetDesc.cpp + RISCVMachObjectWriter.cpp RISCVMatInt.cpp RISCVTargetStreamer.cpp RISCVELFStreamer.cpp diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 41a9c92cf99c3..32c7e76f8565a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" @@ -954,12 +955,30 @@ RISCVAsmBackend::createObjectTargetWriter() const { return createRISCVELFObjectWriter(OSABI, Is64Bit); } +class DarwinRISCVAsmBackend : public RISCVAsmBackend { +public: + DarwinRISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, + bool IsLittleEndian, const MCTargetOptions &Options) + : RISCVAsmBackend(STI, OSABI, Is64Bit, IsLittleEndian, Options) {} + + std::unique_ptr + 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(), + TT.isLittleEndian(), Options); return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), TT.isLittleEndian(), Options); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 5152d054cb177..b5b1ab901d534 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 77f65d814ce7a..ea8d9e0b9e600 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -58,3 +58,16 @@ void RISCVMCAsmInfo::printSpecifierExpr(raw_ostream &OS, if (HasSpecifier) OS << ')'; } + +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 097e94b6117c7..568ef1998d4d2 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" #include "llvm/MC/MCFixup.h" @@ -50,6 +51,11 @@ Specifier parseSpecifierName(StringRef name); StringRef getSpecifierName(Specifier Kind); } // namespace RISCV +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 d917ef4129791..9b20ff829371e 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -60,7 +60,13 @@ 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(); + else + reportFatalUsageError("unsupported object format"); unsigned SP = MRI.getDwarfRegNum(RISCV::X2, true); MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); @@ -116,6 +122,16 @@ createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { return nullptr; } +static MCStreamer * +createMachOStreamer(MCContext &Ctx, std::unique_ptr &&TAB, + std::unique_ptr &&OW, + std::unique_ptr &&Emitter) { + return createMachOStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), + /*DWARFMustBeAtTheEnd*/ false, + /*LabelSections*/ true); +} + static MCTargetStreamer * createRISCVAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint) { @@ -387,6 +403,7 @@ LLVMInitializeRISCVTargetMC() { TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter); TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer); + TargetRegistry::RegisterMachOStreamer(*T, createMachOStreamer); TargetRegistry::RegisterObjectTargetStreamer( *T, createRISCVObjectTargetStreamer); TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis); 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 createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); +std::unique_ptr +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..ae33d5dc78062 --- /dev/null +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp @@ -0,0 +1,54 @@ +//===-- 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/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/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.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 +#include + +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 +llvm::createRISCVMachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype) { + return std::make_unique(CPUType, CPUSubtype); +} diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index cea246e9527bd..25df11233423f 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -275,6 +275,13 @@ static std::string computeAMDDataLayout(const Triple &TT) { } static std::string computeRISCVDataLayout(const Triple &TT, StringRef ABIName) { + if (TT.isOSBinFormatMachO()) { + assert(TT.isLittleEndian() && "Invalid endianness"); + assert(TT.isArch32Bit() && "Invalid triple"); + assert((ABIName != "ilp32e") && "Invalid ABI."); + return "e-m:o-p:32:32-i64:64-n32-S128"; + } + std::string Ret; if (TT.isLittleEndian()) diff --git a/llvm/test/CodeGen/RISCV/riscv-macho.ll b/llvm/test/CodeGen/RISCV/riscv-macho.ll new file mode 100644 index 0000000000000..624321b259a73 --- /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/macho-local-symbol.s b/llvm/test/MC/RISCV/macho-local-symbol.s new file mode 100644 index 0000000000000..ee7c409f34abf --- /dev/null +++ b/llvm/test/MC/RISCV/macho-local-symbol.s @@ -0,0 +1,7 @@ +;; RUN: llvm-mc -triple riscv32-apple-macho %s -filetype=obj -o - | \ +;; RUN: llvm-objdump - -d | FileCheck %s + +Ltmp0: + addi a0, a0, 1 + + ;; CHECK: 00000000 : diff --git a/llvm/test/MC/RISCV/macho.s b/llvm/test/MC/RISCV/macho.s new file mode 100644 index 0000000000000..f2cec7bf08ebb --- /dev/null +++ b/llvm/test/MC/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 +; CHECK-DIS: 002a +; CHECK-DIS: 0000 + +; CHECK-SYMS-NOT: Lfoo +; CHECK-SYMS: foo +; CHECK-SYMS: lfoo