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 @@ -29,10 +29,13 @@ class RISCVAsmBackend : public MCAsmBackend { uint8_t OSABI; bool Is64Bit; + bool HasStdExtC; public: - RISCVAsmBackend(uint8_t OSABI, bool Is64Bit) - : MCAsmBackend(), OSABI(OSABI), Is64Bit(Is64Bit) {} + RISCVAsmBackend(uint8_t OSABI, const Triple &TT, bool Is64Bit) + : MCAsmBackend(), OSABI(OSABI), Is64Bit(Is64Bit) { + HasStdExtC = (TT.getArchName().substr(7).find('c') != std::string::npos); + } ~RISCVAsmBackend() override {} void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, @@ -88,15 +91,25 @@ }; 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; + 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 i = Count; + for (; i >= 4; i -= 4) OW->write32(0x13); + // The canonical nop on RVC is c.nop + if (HasStdExtC) { + uint64_t NumNops = i / 2; + for (uint64_t i = 0; i != NumNops; ++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(OSABI, TT, TT.isArch64Bit()); } 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