Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -378,6 +378,19 @@ return arch; } +// Recognize riscv triple with feature suffix +// E.g. riscv32imac +static Triple::ArchType parseRISCVArch(StringRef ArchName) { + Triple::ArchType arch = Triple::UnknownArch; + + if (ArchName.startswith("riscv32")) { + arch = Triple::riscv32; + } else if (ArchName.startswith("riscv64")) { + arch = Triple::riscv64; + } + return arch; +} + static Triple::ArchType parseArch(StringRef ArchName) { auto AT = StringSwitch(ArchName) .Cases("i386", "i486", "i586", "i686", Triple::x86) @@ -443,6 +456,8 @@ return parseARMArch(ArchName); if (ArchName.startswith("bpf")) return parseBPFArch(ArchName); + if (ArchName.startswith("riscv")) + return parseRISCVArch(ArchName); } return AT; Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -27,12 +27,14 @@ namespace { class RISCVAsmBackend : public MCAsmBackend { + const MCSubtargetInfo *STI; uint8_t OSABI; bool Is64Bit; public: - RISCVAsmBackend(uint8_t OSABI, bool Is64Bit) - : MCAsmBackend(), OSABI(OSABI), Is64Bit(Is64Bit) {} + RISCVAsmBackend(const Triple &TT, uint8_t OSABI, bool Is64Bit) + : MCAsmBackend(), STI(RISCV::createRISCVMCSubtargetInfo(TT, "", "")), + OSABI(OSABI), Is64Bit(Is64Bit) {} ~RISCVAsmBackend() override {} void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, @@ -88,15 +90,26 @@ }; bool RISCVAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { - // Once support for the compressed instruction set is added, we will be able - // to conditionally support 16-bit NOPs - if ((Count % 4) != 0) - return false; + bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC]; + if (HasStdExtC) { + if ((Count % 2) != 0) + return false; + } else { + if ((Count % 4) != 0) + return false; + } // The canonical nop on RISC-V is addi x0, x0, 0 - for (uint64_t i = 0; i < Count; i += 4) + uint64_t Nop32Count = Count / 4; + for (uint64_t i = Nop32Count; i != 0; --i) OW->write32(0x13); + // The canonical nop on RVC is c.nop + if (HasStdExtC) { + uint64_t Nop16Count = (Count - Nop32Count * 4) / 2; + for (uint64_t i = Nop16Count; i != 0; --i) + OW->write16(0x01); + } return true; } @@ -234,5 +247,5 @@ const Triple &TT, StringRef CPU, const MCTargetOptions &Options) { uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); - return new RISCVAsmBackend(OSABI, TT.isArch64Bit()); + return new RISCVAsmBackend(TT, OSABI, TT.isArch64Bit()); } Index: lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h +++ lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h @@ -46,8 +46,15 @@ std::unique_ptr createRISCVELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, bool Is64Bit); -} +namespace RISCV { +std::string parseRISCVTriple(const Triple &TT, StringRef CPU); +MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT, StringRef CPU, + StringRef FS); +} // end namespace RISCV +} // end namespace llvm + + // Defines symbolic names for RISC-V registers. #define GET_REGINFO_ENUM #include "RISCVGenRegisterInfo.inc" Index: lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -51,12 +51,57 @@ return new RISCVMCAsmInfo(TT); } -static MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT, +/// Select the RISCV feature for the given triple. +std::string RISCV::parseRISCVTriple(const Triple &TT, StringRef CPU) { + StringRef MArch = TT.getArchName(); + StringRef Ext = MArch.substr(7); + std::string RISCVFeature; + + if (MArch.startswith("riscv64")) { + RISCVFeature = "+64bit"; + } + + for (char ext : Ext) { + if (!RISCVFeature.empty()) + RISCVFeature += ","; + switch (ext) { + case 'm': + RISCVFeature += "+m"; + break; + case 'a': + RISCVFeature += "+a"; + break; + case 'c': + RISCVFeature += "+c"; + break; + case 'f': + RISCVFeature += "+f"; + break; + case 'd': + RISCVFeature += "+d"; + break; + default: + break; + } + } + return RISCVFeature; +} + +MCSubtargetInfo *RISCV::createRISCVMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + std::string ArchFS = RISCV::parseRISCVTriple(TT, CPU); std::string CPUName = CPU; if (CPUName.empty()) CPUName = TT.isArch64Bit() ? "generic-rv64" : "generic-rv32"; - return createRISCVMCSubtargetInfoImpl(TT, CPUName, FS); + + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = (Twine(ArchFS) + "," + FS).str(); + else + ArchFS = FS; + } + + return createRISCVMCSubtargetInfoImpl(TT, CPUName, ArchFS); } static MCInstPrinter *createRISCVMCInstPrinter(const Triple &T, @@ -75,6 +120,7 @@ TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend); TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter); TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter); - TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo( + *T, RISCV::createRISCVMCSubtargetInfo); } } Index: test/MC/RISCV/cnop.s =================================================================== --- /dev/null +++ test/MC/RISCV/cnop.s @@ -0,0 +1,26 @@ +# RUN: llvm-mc -filetype=obj -triple riscv32imac -mattr=+c < %s \ +# RUN: | llvm-objdump -mattr=+c -d - | FileCheck -check-prefix=CHECK-INST %s + +# alpha and main are 8 byte alignment +# but the alpha function's size is 6 +# So assembler will insert a c.nop to make sure 8 byte alignment. + + .text + .p2align 3 + .type alpha,@function +alpha: +# BB#0: + addi sp, sp, -16 + c.lw a0, 0(a0) +# CHECK-INST: c.nop +.Lfunc_end0: + .size alpha, .Lfunc_end0-alpha + # -- End function + .globl main + .p2align 3 + .type main,@function +main: # @main +# BB#0: +.Lfunc_end1: + .size main, .Lfunc_end1-main + # -- End function