[llvm] r347774 - [RISCV] Support .option push and .option pop

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 28 08:39:14 PST 2018


Author: asb
Date: Wed Nov 28 08:39:14 2018
New Revision: 347774

URL: http://llvm.org/viewvc/llvm-project?rev=347774&view=rev
Log:
[RISCV] Support .option push and .option pop

This adds support in the RISCVAsmParser the storing of Subtarget feature bits to a stack so that they can be pushed/popped to enable/disable multiple features at once.

Differential Revision: https://reviews.llvm.org/D46424
Patch by Lewis Revill.

Added:
    llvm/trunk/test/MC/RISCV/option-pushpop.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/RISCVTargetStreamer.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
    llvm/trunk/test/MC/RISCV/option-invalid.s

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=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp Wed Nov 28 08:39:14 2018
@@ -14,6 +14,7 @@
 #include "Utils/RISCVBaseInfo.h"
 #include "Utils/RISCVMatInt.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
@@ -42,6 +43,8 @@ namespace {
 struct RISCVOperand;
 
 class RISCVAsmParser : public MCTargetAsmParser {
+  SmallVector<FeatureBitset, 4> FeatureBitStack;
+
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
   bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
 
@@ -118,6 +121,20 @@ class RISCVAsmParser : public MCTargetAs
     }
   }
 
+  void pushFeatureBits() {
+    FeatureBitStack.push_back(getSTI().getFeatureBits());
+  }
+
+  bool popFeatureBits() {
+    if (FeatureBitStack.empty())
+      return true;
+
+    FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
+    copySTI().setFeatureBits(FeatureBits);
+    setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
+
+    return false;
+  }
 public:
   enum RISCVMatchResultTy {
     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
@@ -1285,6 +1302,33 @@ bool RISCVAsmParser::parseDirectiveOptio
 
   StringRef Option = Tok.getIdentifier();
 
+  if (Option == "push") {
+    getTargetStreamer().emitDirectiveOptionPush();
+
+    Parser.Lex();
+    if (Parser.getTok().isNot(AsmToken::EndOfStatement))
+      return Error(Parser.getTok().getLoc(),
+                   "unexpected token, expected end of statement");
+
+    pushFeatureBits();
+    return false;
+  }
+
+  if (Option == "pop") {
+    SMLoc StartLoc = Parser.getTok().getLoc();
+    getTargetStreamer().emitDirectiveOptionPop();
+
+    Parser.Lex();
+    if (Parser.getTok().isNot(AsmToken::EndOfStatement))
+      return Error(Parser.getTok().getLoc(),
+                   "unexpected token, expected end of statement");
+
+    if (popFeatureBits())
+      return Error(StartLoc, ".option pop with no .option push");
+
+    return false;
+  }
+
   if (Option == "rvc") {
     getTargetStreamer().emitDirectiveOptionRVC();
 
@@ -1335,7 +1379,8 @@ bool RISCVAsmParser::parseDirectiveOptio
 
   // Unknown option.
   Warning(Parser.getTok().getLoc(),
-          "unknown option, expected 'rvc', 'norvc', 'relax' or 'norelax'");
+          "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
+          "'norelax'");
   Parser.eatToEndOfStatement();
   return false;
 }

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=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp Wed Nov 28 08:39:14 2018
@@ -38,6 +38,8 @@ MCELFStreamer &RISCVTargetELFStreamer::g
   return static_cast<MCELFStreamer &>(Streamer);
 }
 
+void RISCVTargetELFStreamer::emitDirectiveOptionPush() {}
+void RISCVTargetELFStreamer::emitDirectiveOptionPop() {}
 void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
 void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
 void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}

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=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h Wed Nov 28 08:39:14 2018
@@ -20,6 +20,8 @@ public:
   MCELFStreamer &getStreamer();
   RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
 
+  virtual void emitDirectiveOptionPush();
+  virtual void emitDirectiveOptionPop();
   virtual void emitDirectiveOptionRVC();
   virtual void emitDirectiveOptionNoRVC();
   virtual void emitDirectiveOptionRelax();

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=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp Wed Nov 28 08:39:14 2018
@@ -23,6 +23,14 @@ RISCVTargetAsmStreamer::RISCVTargetAsmSt
                                                formatted_raw_ostream &OS)
     : RISCVTargetStreamer(S), OS(OS) {}
 
+void RISCVTargetAsmStreamer::emitDirectiveOptionPush() {
+  OS << "\t.option\tpush\n";
+}
+
+void RISCVTargetAsmStreamer::emitDirectiveOptionPop() {
+  OS << "\t.option\tpop\n";
+}
+
 void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() {
   OS << "\t.option\trvc\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=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h Wed Nov 28 08:39:14 2018
@@ -18,6 +18,8 @@ class RISCVTargetStreamer : public MCTar
 public:
   RISCVTargetStreamer(MCStreamer &S);
 
+  virtual void emitDirectiveOptionPush() = 0;
+  virtual void emitDirectiveOptionPop() = 0;
   virtual void emitDirectiveOptionRVC() = 0;
   virtual void emitDirectiveOptionNoRVC() = 0;
   virtual void emitDirectiveOptionRelax() = 0;
@@ -31,6 +33,8 @@ class RISCVTargetAsmStreamer : public RI
 public:
   RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
 
+  void emitDirectiveOptionPush() override;
+  void emitDirectiveOptionPop() override;
   void emitDirectiveOptionRVC() override;
   void emitDirectiveOptionNoRVC() override;
   void emitDirectiveOptionRelax() override;

Modified: llvm/trunk/test/MC/RISCV/option-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/option-invalid.s?rev=347774&r1=347773&r2=347774&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/option-invalid.s (original)
+++ llvm/trunk/test/MC/RISCV/option-invalid.s Wed Nov 28 08:39:14 2018
@@ -13,5 +13,14 @@
 # CHECK: error: unexpected token, expected end of statement
 .option rvc foo
 
-# CHECK: warning: unknown option, expected 'rvc', 'norvc', 'relax' or 'norelax'
+# CHECK: warning: unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or 'norelax'
 .option bar
+
+# CHECK: error: .option pop with no .option push
+.option pop
+
+# CHECK: error: unexpected token, expected end of statement
+.option push 123
+
+# CHECK: error: unexpected token, expected end of statement
+.option pop 123

Added: llvm/trunk/test/MC/RISCV/option-pushpop.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/option-pushpop.s?rev=347774&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/option-pushpop.s (added)
+++ llvm/trunk/test/MC/RISCV/option-pushpop.s Wed Nov 28 08:39:14 2018
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -triple riscv32 -mattr=-relax -riscv-no-aliases < %s \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=CHECK-RELOC %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 riscv64 -mattr=-relax -riscv-no-aliases < %s \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=CHECK-RELOC %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
+
+# Test the operation of the push and pop assembler directives when
+# using .option relax and .option rvc. Checks that using .option pop
+# correctly restores all target features to their state at the point
+# where .option pop was last used.
+
+# CHECK-INST: call foo
+# CHECK-RELOC: R_RISCV_CALL foo 0x0
+# CHECK-RELOC-NOT: R_RISCV_RELAX foo 0x0
+call foo
+
+# CHECK-INST: addi s0, sp, 1020
+# CHECK-BYTES: 13 04 c1 3f
+# CHECK-ALIAS: addi s0, sp, 1020
+addi s0, sp, 1020
+
+.option push    # Push relax=false, rvc=false
+# CHECK-INST: .option push
+
+.option relax
+# CHECK-INST: .option relax
+# CHECK-INST: call bar
+# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
+# CHECK-RELOC-NEXT: R_RISCV_RELAX bar 0x0
+call bar
+
+.option push    # Push relax=true, rvc=false
+# CHECK-INST: .option push
+
+.option rvc
+# CHECK-INST: .option rvc
+# CHECK-INST: c.addi4spn s0, sp, 1020
+# CHECK-BYTES: e0 1f
+# CHECK-ALIAS: addi s0, sp, 1020
+addi s0, sp, 1020
+
+.option pop     # Pop relax=true, rvc=false
+# CHECK-INST: .option pop
+# CHECK-INST: addi s0, sp, 1020
+# CHECK-BYTES: 13 04 c1 3f
+# CHECK-ALIAS: addi s0, sp, 1020
+addi s0, sp, 1020
+
+# CHECK-INST: call bar
+# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
+# CHECK-RELOC-NEXT: R_RISCV_RELAX bar 0x0
+call bar
+
+.option pop     # Pop relax=false, rvc=false
+# CHECK-INST: .option pop
+# CHECK-INST: call baz
+# CHECK-RELOC: R_RISCV_CALL baz 0x0
+# CHECK-RELOC-NOT: R_RISCV_RELAX baz 0x0
+call baz
+
+# CHECK-INST: addi s0, sp, 1020
+# CHECK-BYTES: 13 04 c1 3f
+# CHECK-ALIAS: addi s0, sp, 1020
+addi s0, sp, 1020




More information about the llvm-commits mailing list