diff options
author | Alex Bradbury <asb@lowrisc.org> | 2018-05-11 17:30:28 +0000 |
---|---|---|
committer | Alex Bradbury <asb@lowrisc.org> | 2018-05-11 17:30:28 +0000 |
commit | bca0c3cdb6d49822dbfbcac0bd2719e17e08f309 (patch) | |
tree | 7304ed476ecdabf44c65567bd77fde8a98deb0b3 /llvm/lib/Target/RISCV | |
parent | 0d7c37756bc3609d9a1f3a9d9ba79842acca1e4a (diff) | |
download | bcm5719-llvm-bca0c3cdb6d49822dbfbcac0bd2719e17e08f309.tar.gz bcm5719-llvm-bca0c3cdb6d49822dbfbcac0bd2719e17e08f309.zip |
[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
llvm-svn: 332107
Diffstat (limited to 'llvm/lib/Target/RISCV')
6 files changed, 123 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 |