diff options
-rw-r--r-- | llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 78 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h | 3 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h | 15 | ||||
-rw-r--r-- | llvm/test/CodeGen/RISCV/option-norvc.ll | 15 | ||||
-rw-r--r-- | llvm/test/CodeGen/RISCV/option-rvc.ll | 15 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/option-invalid.s | 17 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/option-rvc.s | 90 |
10 files changed, 260 insertions, 2 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index b5e46b63756..487eea14b16 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -10,6 +10,7 @@ #include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVMCExpr.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "MCTargetDesc/RISCVTargetStreamer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" @@ -37,6 +38,11 @@ class RISCVAsmParser : public MCTargetAsmParser { SMLoc getLoc() const { return getParser().getTok().getLoc(); } bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); } + RISCVTargetStreamer &getTargetStreamer() { + MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); + return static_cast<RISCVTargetStreamer &>(TS); + } + unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; @@ -67,6 +73,23 @@ class RISCVAsmParser : public MCTargetAsmParser { bool parseOperand(OperandVector &Operands, bool ForceImmediate); + bool parseDirectiveOption(); + + void setFeatureBits(uint64_t Feature, StringRef FeatureString) { + if (!(getSTI().getFeatureBits()[Feature])) { + MCSubtargetInfo &STI = copySTI(); + setAvailableFeatures( + ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); + } + } + + void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { + if (getSTI().getFeatureBits()[Feature]) { + MCSubtargetInfo &STI = copySTI(); + setAvailableFeatures( + ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); + } + } public: enum RISCVMatchResultTy { Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, @@ -984,7 +1007,60 @@ bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr, return Kind != RISCVMCExpr::VK_RISCV_Invalid; } -bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } +bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { + // This returns false if this function recognizes the directive + // regardless of whether it is successfully handles or reports an + // error. Otherwise it returns true to give the generic parser a + // chance at recognizing it. + StringRef IDVal = DirectiveID.getString(); + + if (IDVal == ".option") + return parseDirectiveOption(); + + return true; +} + +bool RISCVAsmParser::parseDirectiveOption() { + MCAsmParser &Parser = getParser(); + // Get the option token. + AsmToken Tok = Parser.getTok(); + // At the moment only identifiers are supported. + if (Tok.isNot(AsmToken::Identifier)) + return Error(Parser.getTok().getLoc(), + "unexpected token, expected identifier"); + + StringRef Option = Tok.getIdentifier(); + + if (Option == "rvc") { + getTargetStreamer().emitDirectiveOptionRVC(); + + Parser.Lex(); + if (Parser.getTok().isNot(AsmToken::EndOfStatement)) + return Error(Parser.getTok().getLoc(), + "unexpected token, expected end of statement"); + + setFeatureBits(RISCV::FeatureStdExtC, "c"); + return false; + } + + if (Option == "norvc") { + getTargetStreamer().emitDirectiveOptionNoRVC(); + + Parser.Lex(); + if (Parser.getTok().isNot(AsmToken::EndOfStatement)) + return Error(Parser.getTok().getLoc(), + "unexpected token, expected end of statement"); + + clearFeatureBits(RISCV::FeatureStdExtC, "c"); + return false; + } + + // Unknown option. + Warning(Parser.getTok().getLoc(), + "unknown option, expected 'rvc' or 'norvc'"); + Parser.eatToEndOfStatement(); + return false; +} extern "C" void LLVMInitializeRISCVAsmParser() { RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target()); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 243f8ed7fb5..6428b11cfe9 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -37,3 +37,6 @@ RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { return static_cast<MCELFStreamer &>(Streamer); } + +void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} +void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h index d3cfbe3e83c..daa7abfe133 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -19,6 +19,9 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer { public: MCELFStreamer &getStreamer(); RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); + + virtual void emitDirectiveOptionRVC(); + virtual void emitDirectiveOptionNoRVC(); }; } #endif diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp index b1fc7c0c678..133f3cd3d39 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -74,7 +74,14 @@ createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { const Triple &TT = STI.getTargetTriple(); if (TT.isOSBinFormatELF()) return new RISCVTargetELFStreamer(S, STI); - return new RISCVTargetStreamer(S); + return nullptr; +} + +static MCTargetStreamer *createRISCVAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new RISCVTargetAsmStreamer(S, OS); } extern "C" void LLVMInitializeRISCVTargetMC() { @@ -88,5 +95,8 @@ extern "C" void LLVMInitializeRISCVTargetMC() { TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); TargetRegistry::RegisterObjectTargetStreamer( *T, createRISCVObjectTargetStreamer); + + // Register the asm target streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer); } } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp index e72b0243b2e..2d5205aa7ef 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -12,7 +12,21 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetStreamer.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + +// This part is for ascii assembly output +RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : RISCVTargetStreamer(S), OS(OS) {} + +void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() { + OS << "\t.option\trvc\n"; +} + +void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() { + OS << "\t.option\tnorvc\n"; +} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h index 3f395405b59..525c20810f2 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -17,6 +17,21 @@ namespace llvm { class RISCVTargetStreamer : public MCTargetStreamer { public: RISCVTargetStreamer(MCStreamer &S); + + virtual void emitDirectiveOptionRVC() = 0; + virtual void emitDirectiveOptionNoRVC() = 0; }; + +// This part is for ascii assembly output +class RISCVTargetAsmStreamer : public RISCVTargetStreamer { + formatted_raw_ostream &OS; + +public: + RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); + + void emitDirectiveOptionRVC() override; + void emitDirectiveOptionNoRVC() override; +}; + } #endif diff --git a/llvm/test/CodeGen/RISCV/option-norvc.ll b/llvm/test/CodeGen/RISCV/option-norvc.ll new file mode 100644 index 00000000000..381fb37735d --- /dev/null +++ b/llvm/test/CodeGen/RISCV/option-norvc.ll @@ -0,0 +1,15 @@ +; RUN: llc -mtriple=riscv32 -mattr=+c -filetype=obj < %s\ +; RUN: | llvm-objdump -triple=riscv32 -mattr=+c -d -riscv-no-aliases -\ +; RUN: | FileCheck -check-prefix=CHECK %s + +; This test demonstrates that .option norvc has no effect on codegen when +; emitting an ELF directly. + +define i32 @add(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: add: +; CHECK: c.add a0, a1 +; CHECK-NEXT: c.jr ra + tail call void asm sideeffect ".option norvc", ""() + %add = add nsw i32 %b, %a + ret i32 %add +} diff --git a/llvm/test/CodeGen/RISCV/option-rvc.ll b/llvm/test/CodeGen/RISCV/option-rvc.ll new file mode 100644 index 00000000000..3c207bd424f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/option-rvc.ll @@ -0,0 +1,15 @@ +; RUN: llc -mtriple=riscv32 -filetype=obj < %s\ +; RUN: | llvm-objdump -triple=riscv32 -mattr=+c -d -riscv-no-aliases -\ +; RUN: | FileCheck -check-prefix=CHECK %s + +; This test demonstrates that .option norvc has no effect on codegen when +; emitting an ELF directly. + +define i32 @add(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: add: +; CHECK: add a0, a1, a0 +; CHECK-NEXT: jalr zero, ra, 0 + tail call void asm sideeffect ".option rvc", ""() + %add = add nsw i32 %b, %a + ret i32 %add +} diff --git a/llvm/test/MC/RISCV/option-invalid.s b/llvm/test/MC/RISCV/option-invalid.s new file mode 100644 index 00000000000..ec9e8e030d7 --- /dev/null +++ b/llvm/test/MC/RISCV/option-invalid.s @@ -0,0 +1,17 @@ +# RUN: not llvm-mc -triple riscv32 < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK %s + +# CHECK: error: unexpected token, expected identifier +.option + +# CHECK: error: unexpected token, expected identifier +.option 123 + +# CHECK: error: unexpected token, expected identifier +.option "str" + +# CHECK: error: unexpected token, expected end of statement +.option rvc foo + +# CHECK: warning: unknown option, expected 'rvc' or 'norvc' +.option bar diff --git a/llvm/test/MC/RISCV/option-rvc.s b/llvm/test/MC/RISCV/option-rvc.s new file mode 100644 index 00000000000..129eae5bf79 --- /dev/null +++ b/llvm/test/MC/RISCV/option-rvc.s @@ -0,0 +1,90 @@ +# RUN: llvm-mc -triple riscv32 -show-encoding < %s \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-ALIAS %s +# RUN: llvm-mc -triple riscv32 -show-encoding \ +# RUN: -riscv-no-aliases <%s | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -triple riscv32 -filetype=obj < %s \ +# RUN: | llvm-objdump -triple riscv32 -mattr=+c -d - \ +# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s +# RUN: llvm-mc -triple riscv32 -filetype=obj < %s \ +# RUN: | llvm-objdump -triple riscv32 -mattr=+c -d -riscv-no-aliases - \ +# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s + +# RUN: llvm-mc -triple riscv64 -show-encoding < %s \ +# RUN: | FileCheck -check-prefixes=CHECK-ALIAS %s +# RUN: llvm-mc -triple riscv64 -show-encoding \ +# RUN: -riscv-no-aliases <%s | FileCheck -check-prefixes=CHECK-INST %s +# RUN: llvm-mc -triple riscv64 -filetype=obj < %s \ +# RUN: | llvm-objdump -triple riscv64 -mattr=+c -d - \ +# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s +# RUN: llvm-mc -triple riscv64 -filetype=obj < %s \ +# RUN: | llvm-objdump -triple riscv64 -mattr=+c -d -riscv-no-aliases - \ +# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s + +# CHECK-BYTES: 13 85 05 00 +# CHECK-ALIAS: mv a0, a1 +# CHECK-INST: addi a0, a1, 0 +# CHECK: # encoding: [0x13,0x85,0x05,0x00] +addi a0, a1, 0 + +# CHECK-BYTES: 13 04 c1 3f +# CHECK-ALIAS: addi s0, sp, 1020 +# CHECK-INST: addi s0, sp, 1020 +# CHECK: # encoding: [0x13,0x04,0xc1,0x3f] +addi s0, sp, 1020 + + +# CHECK: .option rvc +.option rvc +# CHECK-BYTES: 2e 85 +# CHECK-ALIAS: add a0, zero, a1 +# CHECK-INST: c.mv a0, a1 +# CHECK: # encoding: [0x2e,0x85] +addi a0, a1, 0 + +# CHECK-BYTES: e0 1f +# CHECK-ALIAS: addi s0, sp, 1020 +# CHECK-INST: c.addi4spn s0, sp, 1020 +# CHECK: # encoding: [0xe0,0x1f] +addi s0, sp, 1020 + +# CHECK: .option norvc +.option norvc +# CHECK-BYTES: 13 85 05 00 +# CHECK-ALIAS: mv a0, a1 +# CHECK-INST: addi a0, a1, 0 +# CHECK: # encoding: [0x13,0x85,0x05,0x00] +addi a0, a1, 0 + +# CHECK-BYTES: 13 04 c1 3f +# CHECK-ALIAS: addi s0, sp, 1020 +# CHECK-INST: addi s0, sp, 1020 +# CHECK: # encoding: [0x13,0x04,0xc1,0x3f] +addi s0, sp, 1020 + +# CHECK: .option rvc +.option rvc +# CHECK-BYTES: 2e 85 +# CHECK-ALIAS: add a0, zero, a1 +# CHECK-INST: c.mv a0, a1 +# CHECK: # encoding: [0x2e,0x85] +addi a0, a1, 0 + +# CHECK-BYTES: e0 1f +# CHECK-ALIAS: addi s0, sp, 1020 +# CHECK-INST: c.addi4spn s0, sp, 1020 +# CHECK: # encoding: [0xe0,0x1f] +addi s0, sp, 1020 + +# CHECK: .option norvc +.option norvc +# CHECK-BYTES: 13 85 05 00 +# CHECK-ALIAS: mv a0, a1 +# CHECK-INST: addi a0, a1, 0 +# CHECK: # encoding: [0x13,0x85,0x05,0x00] +addi a0, a1, 0 + +# CHECK-BYTES: 13 04 c1 3f +# CHECK-ALIAS: addi s0, sp, 1020 +# CHECK-INST: addi s0, sp, 1020 +# CHECK: # encoding: [0x13,0x04,0xc1,0x3f] +addi s0, sp, 1020 |