[llvm] r332107 - [RISCV] Support .option rvc and norvc assembler directives

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Fri May 11 10:30:29 PDT 2018


Author: asb
Date: Fri May 11 10:30:28 2018
New Revision: 332107

URL: http://llvm.org/viewvc/llvm-project?rev=332107&view=rev
Log:
[RISCV] Support .option rvc and norvc assembler directives

These directives allow the 'C' (compressed) extension to be enabled/disabled 
within a single file.

Differential Revision: https://reviews.llvm.org/D45864
Patch by Kito Cheng

Added:
    llvm/trunk/test/CodeGen/RISCV/option-norvc.ll
    llvm/trunk/test/CodeGen/RISCV/option-rvc.ll
    llvm/trunk/test/MC/RISCV/option-invalid.s
    llvm/trunk/test/MC/RISCV/option-rvc.s
Modified:
    llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h

Modified: llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp Fri May 11 10:30:28 2018
@@ -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 MCTargetAs
   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 MCTargetAs
 
   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(c
   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());

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp Fri May 11 10:30:28 2018
@@ -37,3 +37,6 @@ RISCVTargetELFStreamer::RISCVTargetELFSt
 MCELFStreamer &RISCVTargetELFStreamer::getStreamer() {
   return static_cast<MCELFStreamer &>(Streamer);
 }
+
+void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
+void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h Fri May 11 10:30:28 2018
@@ -19,6 +19,9 @@ class RISCVTargetELFStreamer : public RI
 public:
   MCELFStreamer &getStreamer();
   RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
+
+  virtual void emitDirectiveOptionRVC();
+  virtual void emitDirectiveOptionNoRVC();
 };
 }
 #endif

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp Fri May 11 10:30:28 2018
@@ -74,7 +74,14 @@ createRISCVObjectTargetStreamer(MCStream
   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 LLVMInitializeRISCVTarge
     TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo);
     TargetRegistry::RegisterObjectTargetStreamer(
         *T, createRISCVObjectTargetStreamer);
+
+    // Register the asm target streamer.
+    TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);
   }
 }

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp Fri May 11 10:30:28 2018
@@ -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";
+}

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h?rev=332107&r1=332106&r2=332107&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h Fri May 11 10:30:28 2018
@@ -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

Added: llvm/trunk/test/CodeGen/RISCV/option-norvc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/option-norvc.ll?rev=332107&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/option-norvc.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/option-norvc.ll Fri May 11 10:30:28 2018
@@ -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
+}

Added: llvm/trunk/test/CodeGen/RISCV/option-rvc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/option-rvc.ll?rev=332107&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/option-rvc.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/option-rvc.ll Fri May 11 10:30:28 2018
@@ -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
+}

Added: llvm/trunk/test/MC/RISCV/option-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/option-invalid.s?rev=332107&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/option-invalid.s (added)
+++ llvm/trunk/test/MC/RISCV/option-invalid.s Fri May 11 10:30:28 2018
@@ -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

Added: llvm/trunk/test/MC/RISCV/option-rvc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/option-rvc.s?rev=332107&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/option-rvc.s (added)
+++ llvm/trunk/test/MC/RISCV/option-rvc.s Fri May 11 10:30:28 2018
@@ -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




More information about the llvm-commits mailing list