Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ 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 @@ 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(TS); + } + unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; @@ -67,6 +73,23 @@ bool parseOperand(OperandVector &Operands); + 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, @@ -967,7 +990,62 @@ 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 X(getTheRISCV32Target()); Index: lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -77,6 +77,13 @@ return new RISCVTargetStreamer(S); } +static MCTargetStreamer *createRISCVAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new RISCVTargetAsmStreamer(S, OS); +} + extern "C" void LLVMInitializeRISCVTargetMC() { for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) { TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo); @@ -88,5 +95,8 @@ TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); TargetRegistry::RegisterObjectTargetStreamer( *T, createRISCVObjectTargetStreamer); + + // Register the asm target streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer); } } Index: lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -17,6 +17,21 @@ class RISCVTargetStreamer : public MCTargetStreamer { public: RISCVTargetStreamer(MCStreamer &S); + + virtual void emitDirectiveOptionRVC(); + virtual void emitDirectiveOptionNoRVC(); }; + +// 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 Index: lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -12,7 +12,23 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetStreamer.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} +void RISCVTargetStreamer::emitDirectiveOptionRVC() {} +void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {} + +// 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"; +} Index: test/MC/RISCV/option-rvc.s =================================================================== --- /dev/null +++ test/MC/RISCV/option-rvc.s @@ -0,0 +1,53 @@ +# 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 -mattr=+c -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 -mattr=+c -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 -mattr=+c -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 -mattr=+c -filetype=obj < %s \ +# RUN: | llvm-objdump -triple riscv64 -mattr=+c -d -riscv-no-aliases - \ +# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s + +# 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: .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: .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: .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