mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-27 21:50:29 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@347774 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e666b9ba92
commit
d888610319
@ -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;
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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();
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
74
test/MC/RISCV/option-pushpop.s
Normal file
74
test/MC/RISCV/option-pushpop.s
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user