diff options
| author | Alex Bradbury <asb@lowrisc.org> | 2018-11-28 16:39:14 +0000 |
|---|---|---|
| committer | Alex Bradbury <asb@lowrisc.org> | 2018-11-28 16:39:14 +0000 |
| commit | 893e5bc77484e93d7219eb5aef3534cbe6a14bb5 (patch) | |
| tree | f03fee86fe12d19d6e87f481c6fe03842585d687 /llvm | |
| parent | 8d63aed45941eb40ee30cf80584d6fd024d56b53 (diff) | |
| download | bcm5719-llvm-893e5bc77484e93d7219eb5aef3534cbe6a14bb5.tar.gz bcm5719-llvm-893e5bc77484e93d7219eb5aef3534cbe6a14bb5.zip | |
[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.
llvm-svn: 347774
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 47 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h | 4 | ||||
| -rw-r--r-- | llvm/test/MC/RISCV/option-invalid.s | 11 | ||||
| -rw-r--r-- | llvm/test/MC/RISCV/option-pushpop.s | 74 |
7 files changed, 146 insertions, 2 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 331eb2b361c..4e70ea402d8 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -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 MCTargetAsmParser { } } + 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::parseDirectiveOption() { 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::parseDirectiveOption() { // 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; } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 62a087fb2e7..a6ba1e41e96 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -38,6 +38,8 @@ MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { return static_cast<MCELFStreamer &>(Streamer); } +void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} +void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h index 3e050c8b530..1f36bbc4388 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -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(); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp index 33c59f839ef..8d5ef3dbd17 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -23,6 +23,14 @@ RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S, 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"; } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h index 365388ef85f..74ec9e30393 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -18,6 +18,8 @@ class RISCVTargetStreamer : public MCTargetStreamer { 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 RISCVTargetStreamer { public: RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); + void emitDirectiveOptionPush() override; + void emitDirectiveOptionPop() override; void emitDirectiveOptionRVC() override; void emitDirectiveOptionNoRVC() override; void emitDirectiveOptionRelax() override; diff --git a/llvm/test/MC/RISCV/option-invalid.s b/llvm/test/MC/RISCV/option-invalid.s index 904a50cdaed..8333f1c1997 100644 --- a/llvm/test/MC/RISCV/option-invalid.s +++ b/llvm/test/MC/RISCV/option-invalid.s @@ -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 diff --git a/llvm/test/MC/RISCV/option-pushpop.s b/llvm/test/MC/RISCV/option-pushpop.s new file mode 100644 index 00000000000..9e3ae4156a4 --- /dev/null +++ b/llvm/test/MC/RISCV/option-pushpop.s @@ -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 |

