aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZi Xuan Wu <zixuan.wu@linux.alibaba.com>2021-04-20 14:06:36 +0800
committerZi Xuan Wu <zixuan.wu@linux.alibaba.com>2021-04-20 15:36:49 +0800
commit8ba622bae114960ca9b09cd5bd65a921ea99657c (patch)
treeb21b43778881307f5a3a997583689db58d03f218 /llvm/lib/Target
parent[NFC] Restructure code to make it possible to insert other GCs (diff)
downloadllvm-project-8ba622bae114960ca9b09cd5bd65a921ea99657c.tar.gz
llvm-project-8ba622bae114960ca9b09cd5bd65a921ea99657c.tar.bz2
llvm-project-8ba622bae114960ca9b09cd5bd65a921ea99657c.zip
[CSKY 4/n] Add basic CSKYAsmParser and CSKYInstPrinter
This basic parser will handle basic instructions with register or immediate operands. With the addition of CSKYInstPrinter, we can now make use of lit tests. Differential Revision: https://reviews.llvm.org/D93798
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/CSKY/AsmParser/CMakeLists.txt13
-rw-r--r--llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp476
-rw-r--r--llvm/lib/Target/CSKY/CMakeLists.txt8
-rw-r--r--llvm/lib/Target/CSKY/CSKY.td15
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrInfo.td23
-rw-r--r--llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt3
-rw-r--r--llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp101
-rw-r--r--llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h52
-rw-r--r--llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp23
9 files changed, 709 insertions, 5 deletions
diff --git a/llvm/lib/Target/CSKY/AsmParser/CMakeLists.txt b/llvm/lib/Target/CSKY/AsmParser/CMakeLists.txt
new file mode 100644
index 000000000000..e7b5cdbdec71
--- /dev/null
+++ b/llvm/lib/Target/CSKY/AsmParser/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_llvm_component_library(LLVMCSKYAsmParser
+ CSKYAsmParser.cpp
+
+ LINK_COMPONENTS
+ CSKYDesc
+ CSKYInfo
+ MC
+ MCParser
+ Support
+
+ ADD_TO_COMPONENT
+ CSKY
+ )
diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
new file mode 100644
index 000000000000..718b14cc523f
--- /dev/null
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -0,0 +1,476 @@
+//===-- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/CSKYMCTargetDesc.h"
+#include "TargetInfo/CSKYTargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+namespace {
+struct CSKYOperand;
+
+class CSKYAsmParser : public MCTargetAsmParser {
+
+ bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
+ int64_t Lower, int64_t Upper, Twine Msg);
+
+ SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+
+ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands, MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) override;
+
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+
+ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) override;
+
+ bool ParseDirective(AsmToken DirectiveID) override;
+
+ OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) override;
+
+// Auto-generated instruction matching functions
+#define GET_ASSEMBLER_HEADER
+#include "CSKYGenAsmMatcher.inc"
+
+ OperandMatchResultTy parseImmediate(OperandVector &Operands);
+ OperandMatchResultTy parseRegister(OperandVector &Operands);
+
+ bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
+
+public:
+ enum CSKYMatchResultTy {
+ Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
+#define GET_OPERAND_DIAGNOSTIC_TYPES
+#include "CSKYGenAsmMatcher.inc"
+#undef GET_OPERAND_DIAGNOSTIC_TYPES
+ };
+
+ CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
+ const MCInstrInfo &MII, const MCTargetOptions &Options)
+ : MCTargetAsmParser(Options, STI, MII) {
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+ }
+};
+
+/// Instances of this class represent a parsed machine instruction.
+struct CSKYOperand : public MCParsedAsmOperand {
+ enum KindTy {
+ Token,
+ Register,
+ Immediate,
+ } Kind;
+
+ struct RegOp {
+ unsigned RegNum;
+ };
+
+ struct ImmOp {
+ const MCExpr *Val;
+ };
+
+ SMLoc StartLoc, EndLoc;
+ union {
+ StringRef Tok;
+ RegOp Reg;
+ ImmOp Imm;
+ };
+
+ CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+
+public:
+ CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
+ Kind = o.Kind;
+ StartLoc = o.StartLoc;
+ EndLoc = o.EndLoc;
+ switch (Kind) {
+ case Register:
+ Reg = o.Reg;
+ break;
+ case Immediate:
+ Imm = o.Imm;
+ break;
+ case Token:
+ Tok = o.Tok;
+ break;
+ }
+ }
+
+ bool isToken() const override { return Kind == Token; }
+ bool isReg() const override { return Kind == Register; }
+ bool isImm() const override { return Kind == Immediate; }
+ bool isMem() const override { return false; }
+
+ static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
+ if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
+ Imm = CE->getValue();
+ return true;
+ }
+
+ return false;
+ }
+
+ template <unsigned num> bool isUImm() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+ return IsConstantImm && isUInt<num>(Imm);
+ }
+
+ template <unsigned num> bool isOImm() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+ return IsConstantImm && isUInt<num>(Imm - 1);
+ }
+
+ template <unsigned num> bool isSImm() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+ return IsConstantImm && isInt<num>(Imm);
+ }
+
+ bool isUImm5() const { return isUImm<5>(); }
+ bool isUImm12() const { return isUImm<12>(); }
+ bool isOImm12() const { return isOImm<12>(); }
+
+ /// Gets location of the first token of this operand.
+ SMLoc getStartLoc() const override { return StartLoc; }
+ /// Gets location of the last token of this operand.
+ SMLoc getEndLoc() const override { return EndLoc; }
+
+ unsigned getReg() const override {
+ assert(Kind == Register && "Invalid type access!");
+ return Reg.RegNum;
+ }
+
+ const MCExpr *getImm() const {
+ assert(Kind == Immediate && "Invalid type access!");
+ return Imm.Val;
+ }
+
+ StringRef getToken() const {
+ assert(Kind == Token && "Invalid type access!");
+ return Tok;
+ }
+
+ void print(raw_ostream &OS) const override {
+ switch (Kind) {
+ case Immediate:
+ OS << *getImm();
+ break;
+ case Register:
+ OS << "<register x" << getReg() << ">";
+ break;
+ case Token:
+ OS << "'" << getToken() << "'";
+ break;
+ }
+ }
+
+ static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
+ auto Op = std::make_unique<CSKYOperand>(Token);
+ Op->Tok = Str;
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S,
+ SMLoc E) {
+ auto Op = std::make_unique<CSKYOperand>(Register);
+ Op->Reg.RegNum = RegNo;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
+ SMLoc E) {
+ auto Op = std::make_unique<CSKYOperand>(Immediate);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ void addExpr(MCInst &Inst, const MCExpr *Expr) const {
+ assert(Expr && "Expr shouldn't be null!");
+ if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
+ Inst.addOperand(MCOperand::createImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::createExpr(Expr));
+ }
+
+ // Used by the TableGen Code.
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getReg()));
+ }
+
+ void addImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+};
+} // end anonymous namespace.
+
+#define GET_REGISTER_MATCHER
+#define GET_SUBTARGET_FEATURE_NAME
+#define GET_MATCHER_IMPLEMENTATION
+#define GET_MNEMONIC_SPELL_CHECKER
+#include "CSKYGenAsmMatcher.inc"
+
+static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
+ unsigned VariantID = 0);
+
+bool CSKYAsmParser::generateImmOutOfRangeError(
+ OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
+ Twine Msg = "immediate must be an integer in the range") {
+ SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
+}
+
+bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands,
+ MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) {
+ MCInst Inst;
+ FeatureBitset MissingFeatures;
+
+ auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
+ MatchingInlineAsm);
+ switch (Result) {
+ default:
+ break;
+ case Match_Success:
+ Inst.setLoc(IDLoc);
+ Out.emitInstruction(Inst, getSTI());
+ return false;
+ case Match_MissingFeature: {
+ assert(MissingFeatures.any() && "Unknown missing features!");
+ ListSeparator LS;
+ std::string Msg = "instruction requires the following: ";
+ for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
+ if (MissingFeatures[i]) {
+ Msg += LS;
+ Msg += getSubtargetFeatureName(i);
+ }
+ }
+ return Error(IDLoc, Msg);
+ }
+ case Match_MnemonicFail: {
+ FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
+ std::string Suggestion =
+ CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
+ return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
+ }
+ case Match_InvalidOperand: {
+ SMLoc ErrorLoc = IDLoc;
+ if (ErrorInfo != ~0U) {
+ if (ErrorInfo >= Operands.size())
+ return Error(ErrorLoc, "too few operands for instruction");
+
+ ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
+ }
+ return Error(ErrorLoc, "invalid operand for instruction");
+ }
+ }
+
+ // Handle the case when the error message is of specific type
+ // other than the generic Match_InvalidOperand, and the
+ // corresponding operand is missing.
+ if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
+ SMLoc ErrorLoc = IDLoc;
+ if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
+ return Error(ErrorLoc, "too few operands for instruction");
+ }
+
+ switch (Result) {
+ default:
+ break;
+ case Match_InvalidOImm12:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
+ case Match_InvalidUImm12:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
+ case Match_InvalidUImm5:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
+ }
+
+ llvm_unreachable("Unknown match type detected!");
+}
+
+// Attempts to match Name as a register (either using the default name or
+// alternative ABI names), setting RegNo to the matching register. Upon
+// failure, returns true and sets RegNo to 0.
+static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
+ RegNo = MatchRegisterName(Name);
+
+ if (RegNo == CSKY::NoRegister)
+ RegNo = MatchRegisterAltName(Name);
+
+ return RegNo == CSKY::NoRegister;
+}
+
+bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ const AsmToken &Tok = getParser().getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+ StringRef Name = getLexer().getTok().getIdentifier();
+
+ if (!matchRegisterNameHelper((MCRegister &)RegNo, Name)) {
+ getParser().Lex(); // Eat identifier token.
+ return false;
+ }
+
+ return Error(StartLoc, "invalid register name");
+}
+
+OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::Identifier: {
+ StringRef Name = getLexer().getTok().getIdentifier();
+ MCRegister RegNo;
+
+ if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
+ return MatchOperand_NoMatch;
+
+ getLexer().Lex();
+ Operands.push_back(CSKYOperand::createReg(RegNo, S, E));
+
+ return MatchOperand_Success;
+ }
+ }
+}
+
+OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::String:
+ break;
+ }
+
+ const MCExpr *IdVal;
+ SMLoc S = getLoc();
+ if (getParser().parseExpression(IdVal))
+ return MatchOperand_ParseFail;
+
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+ Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
+ return MatchOperand_Success;
+}
+
+/// Looks at a token type and creates the relevant operand from this
+/// information, adding to Operands. If operand was parsed, returns false, else
+/// true.
+bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
+ // Attempt to parse token as register
+ if (parseRegister(Operands) == MatchOperand_Success)
+ return false;
+
+ // Attempt to parse token as a imm.
+ if (parseImmediate(Operands) == MatchOperand_Success)
+ return false;
+
+ // Finally we have exhausted all options and must declare defeat.
+ Error(getLoc(), "unknown operand");
+ return true;
+}
+
+bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) {
+ // First operand is token for instruction.
+ Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
+
+ // If there are no more operands, then finish.
+ if (getLexer().is(AsmToken::EndOfStatement))
+ return false;
+
+ // Parse first operand.
+ if (parseOperand(Operands, Name))
+ return true;
+
+ // Parse until end of statement, consuming commas between operands.
+ while (getLexer().is(AsmToken::Comma)) {
+ // Consume comma token.
+ getLexer().Lex();
+
+ // Parse next operand.
+ if (parseOperand(Operands, Name))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
+ getParser().eatToEndOfStatement();
+ return Error(Loc, "unexpected token");
+ }
+
+ getParser().Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
+ SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ const AsmToken &Tok = getParser().getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+
+ StringRef Name = getLexer().getTok().getIdentifier();
+
+ if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
+ return MatchOperand_NoMatch;
+
+ getParser().Lex(); // Eat identifier token.
+ return MatchOperand_Success;
+}
+
+bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
+ RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
+}
diff --git a/llvm/lib/Target/CSKY/CMakeLists.txt b/llvm/lib/Target/CSKY/CMakeLists.txt
index ec487ed34bbf..c49c2a02e7f0 100644
--- a/llvm/lib/Target/CSKY/CMakeLists.txt
+++ b/llvm/lib/Target/CSKY/CMakeLists.txt
@@ -2,9 +2,12 @@ add_llvm_component_group(CSKY)
set(LLVM_TARGET_DEFINITIONS CSKY.td)
-tablegen(LLVM CSKYGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM CSKYGenAsmMatcher.inc -gen-asm-matcher)
+tablegen(LLVM CSKYGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM CSKYGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM CSKYGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM CSKYGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM CSKYGenSubtargetInfo.inc -gen-subtarget)
add_public_tablegen_target(CSKYCommonTableGen)
@@ -22,5 +25,6 @@ add_llvm_target(CSKYCodeGen
CSKY
)
-add_subdirectory(TargetInfo)
+add_subdirectory(AsmParser)
add_subdirectory(MCTargetDesc)
+add_subdirectory(TargetInfo)
diff --git a/llvm/lib/Target/CSKY/CSKY.td b/llvm/lib/Target/CSKY/CSKY.td
index da6151befa1b..854a8b5f22a2 100644
--- a/llvm/lib/Target/CSKY/CSKY.td
+++ b/llvm/lib/Target/CSKY/CSKY.td
@@ -19,7 +19,7 @@ include "CSKYInstrInfo.td"
// CSKY processors supported.
//===----------------------------------------------------------------------===//
-def : ProcessorModel<"generic-csky", NoSchedModel, []>;
+def : ProcessorModel<"generic", NoSchedModel, []>;
//===----------------------------------------------------------------------===//
// Define the CSKY target.
@@ -27,6 +27,19 @@ def : ProcessorModel<"generic-csky", NoSchedModel, []>;
def CSKYInstrInfo : InstrInfo;
+
+def CSKYAsmParser : AsmParser {
+ let ShouldEmitMatchRegisterAltName = 1;
+ let AllowDuplicateRegisterNames = 1;
+}
+
+def CSKYAsmWriter : AsmWriter {
+ int PassSubtarget = 1;
+}
+
def CSKY : Target {
let InstructionSet = CSKYInstrInfo;
+ let AssemblyParsers = [CSKYAsmParser];
+ let AssemblyWriters = [CSKYAsmWriter];
+ let AllowRegisterRenaming = 1;
}
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index 7add217530e1..88985a968c90 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -21,20 +21,40 @@ include "CSKYInstrFormats.td"
//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
+class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
+ let Name = prefix # "Imm" # width # suffix;
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = !strconcat("Invalid", Name);
+}
+
+class SImmAsmOperand<int width, string suffix = "">
+ : ImmAsmOperand<"S", width, suffix> {
+}
+
+class UImmAsmOperand<int width, string suffix = "">
+ : ImmAsmOperand<"U", width, suffix> {
+}
+
+class OImmAsmOperand<int width, string suffix = "">
+ : ImmAsmOperand<"O", width, suffix> {
+}
class oimm<int num> : Operand<i32>,
ImmLeaf<i32, "return isUInt<"#num#">(Imm - 1);"> {
let EncoderMethod = "getOImmOpValue";
+ let ParserMatchClass = OImmAsmOperand<num>;
}
class uimm<int num, int shift = 0> : Operand<i32>,
ImmLeaf<i32, "return isShiftedUInt<"#num#", "#shift#">(Imm);"> {
let EncoderMethod = "getImmOpValue<"#shift#">";
+ let ParserMatchClass = UImmAsmOperand<num>;
}
class simm<int num, int shift = 0> : Operand<i32>,
ImmLeaf<i32, "return isShiftedInt<"#num#", "#shift#">(Imm);"> {
let EncoderMethod = "getImmOpValue<"#shift#">";
+ let ParserMatchClass = SImmAsmOperand<num>;
}
def nimm_XFORM : SDNodeXForm<imm, [{
@@ -42,6 +62,7 @@ def nimm_XFORM : SDNodeXForm<imm, [{
}]>;
class nimm<int num> : Operand<i32>,
ImmLeaf<i32, "return isUInt<"#num#">(~Imm);", nimm_XFORM> {
+ let ParserMatchClass = UImmAsmOperand<num>;
}
@@ -105,4 +126,4 @@ def DIVU32 : R_YXZ_SP_F1<0x20, 0x1,
BinOpFrag<(udiv node:$LHS, node:$RHS)>, "divu32">;
def NOT32 : R_XXZ<0b001001, 0b00100, (outs GPR:$rz), (ins GPR:$rx),
- "not", [(set GPR:$rz, (not GPR:$rx))]>;
+ "not32", [(set GPR:$rz, (not GPR:$rx))]>;
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
index f5d7df002a88..d084266dd0b2 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
@@ -1,13 +1,14 @@
add_llvm_component_library(LLVMCSKYDesc
CSKYAsmBackend.cpp
CSKYELFObjectWriter.cpp
+ CSKYInstPrinter.cpp
CSKYMCAsmInfo.cpp
CSKYMCTargetDesc.cpp
CSKYMCCodeEmitter.cpp
LINK_COMPONENTS
- MC
CSKYInfo
+ MC
Support
ADD_TO_COMPONENT
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
new file mode 100644
index 000000000000..c8920fbb4b4c
--- /dev/null
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
@@ -0,0 +1,101 @@
+//===-- CSKYInstPrinter.cpp - Convert CSKY MCInst to asm syntax ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints an CSKY MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYInstPrinter.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "csky-asm-printer"
+
+// Include the auto-generated portion of the assembly writer.
+#define PRINT_ALIAS_INSTR
+#include "CSKYGenAsmWriter.inc"
+
+static cl::opt<bool>
+ NoAliases("csky-no-aliases",
+ cl::desc("Disable the emission of assembler pseudo instructions"),
+ cl::init(false), cl::Hidden);
+
+static cl::opt<bool>
+ ArchRegNames("csky-arch-reg-names",
+ cl::desc("Print architectural register names rather than the "
+ "ABI names (such as r14 instead of sp)"),
+ cl::init(false), cl::Hidden);
+
+// The command-line flags above are used by llvm-mc and llc. They can be used by
+// `llvm-objdump`, but we override their values here to handle options passed to
+// `llvm-objdump` with `-M` (which matches GNU objdump). There did not seem to
+// be an easier way to allow these options in all these tools, without doing it
+// this way.
+bool CSKYInstPrinter::applyTargetSpecificCLOption(StringRef Opt) {
+ if (Opt == "no-aliases") {
+ NoAliases = true;
+ return true;
+ }
+ if (Opt == "numeric") {
+ ArchRegNames = true;
+ return true;
+ }
+
+ return false;
+}
+
+void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address,
+ StringRef Annot, const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ const MCInst *NewMI = MI;
+
+ if (NoAliases || !printAliasInstr(NewMI, Address, STI, O))
+ printInstruction(NewMI, Address, STI, O);
+ printAnnotation(O, Annot);
+}
+
+void CSKYInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
+ O << getRegisterName(RegNo);
+}
+
+void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O,
+ const char *Modifier) {
+ assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
+ const MCOperand &MO = MI->getOperand(OpNo);
+
+ if (MO.isReg()) {
+ if (MO.getReg() == CSKY::C)
+ O << "";
+ else
+ printRegName(O, MO.getReg());
+ return;
+ }
+
+ if (MO.isImm()) {
+ O << formatImm(MO.getImm());
+ return;
+ }
+
+ assert(MO.isExpr() && "Unknown operand kind in printOperand");
+ MO.getExpr()->print(O, &MAI);
+}
+
+const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) {
+ return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName
+ : CSKY::ABIRegAltName);
+}
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
new file mode 100644
index 000000000000..a28791a6d8e9
--- /dev/null
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
@@ -0,0 +1,52 @@
+//===-- CSKYInstPrinter.h - Convert CSKY MCInst to asm syntax ---*- C++ -*----//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints a CSKY MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYINSTPRINTER_H
+#define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYINSTPRINTER_H
+
+#include "MCTargetDesc/CSKYMCTargetDesc.h"
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+
+class CSKYInstPrinter : public MCInstPrinter {
+public:
+ CSKYInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI)
+ : MCInstPrinter(MAI, MII, MRI) {}
+
+ bool applyTargetSpecificCLOption(StringRef Opt) override;
+
+ void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &O) override;
+ void printRegName(raw_ostream &O, unsigned RegNo) const override;
+
+ void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+ raw_ostream &O, const char *Modifier = nullptr);
+
+ // Autogenerated by tblgen.
+ std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
+ void printInstruction(const MCInst *MI, uint64_t Address,
+ const MCSubtargetInfo &STI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, uint64_t Address,
+ const MCSubtargetInfo &STI, raw_ostream &O);
+ void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
+ unsigned OpIdx, unsigned PrintMethodIdx,
+ const MCSubtargetInfo &STI, raw_ostream &O);
+
+ static const char *getRegisterName(unsigned RegNo);
+ static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYINSTPRINTER_H
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
index 876000a37004..169e1e14eb0a 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
@@ -12,6 +12,7 @@
#include "CSKYMCTargetDesc.h"
#include "CSKYAsmBackend.h"
+#include "CSKYInstPrinter.h"
#include "CSKYMCAsmInfo.h"
#include "CSKYMCCodeEmitter.h"
#include "TargetInfo/CSKYTargetInfo.h"
@@ -26,6 +27,9 @@
#define GET_REGINFO_MC_DESC
#include "CSKYGenRegisterInfo.inc"
+#define GET_SUBTARGETINFO_MC_DESC
+#include "CSKYGenSubtargetInfo.inc"
+
using namespace llvm;
static MCAsmInfo *createCSKYMCAsmInfo(const MCRegisterInfo &MRI,
@@ -46,12 +50,28 @@ static MCInstrInfo *createCSKYMCInstrInfo() {
return Info;
}
+static MCInstPrinter *createCSKYMCInstPrinter(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) {
+ return new CSKYInstPrinter(MAI, MII, MRI);
+}
+
static MCRegisterInfo *createCSKYMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *Info = new MCRegisterInfo();
InitCSKYMCRegisterInfo(Info, CSKY::R15);
return Info;
}
+static MCSubtargetInfo *createCSKYMCSubtargetInfo(const Triple &TT,
+ StringRef CPU, StringRef FS) {
+ std::string CPUName = std::string(CPU);
+ if (CPUName.empty())
+ CPUName = "generic";
+ return createCSKYMCSubtargetInfoImpl(TT, CPUName, /*TuneCPU=*/CPUName, FS);
+}
+
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() {
auto &CSKYTarget = getTheCSKYTarget();
TargetRegistry::RegisterMCAsmBackend(CSKYTarget, createCSKYAsmBackend);
@@ -59,4 +79,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() {
TargetRegistry::RegisterMCInstrInfo(CSKYTarget, createCSKYMCInstrInfo);
TargetRegistry::RegisterMCRegInfo(CSKYTarget, createCSKYMCRegisterInfo);
TargetRegistry::RegisterMCCodeEmitter(CSKYTarget, createCSKYMCCodeEmitter);
+ TargetRegistry::RegisterMCInstPrinter(CSKYTarget, createCSKYMCInstPrinter);
+ TargetRegistry::RegisterMCSubtargetInfo(CSKYTarget,
+ createCSKYMCSubtargetInfo);
}