LLVM  14.0.0git
RISCVAsmParser.cpp
Go to the documentation of this file.
1 //===-- RISCVAsmParser.cpp - Parse RISCV assembly to MCInst instructions --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
17 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/MC/MCAssembler.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCInstBuilder.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCValue.h"
35 #include "llvm/MC/TargetRegistry.h"
36 #include "llvm/Support/Casting.h"
40 
41 #include <limits>
42 
43 using namespace llvm;
44 
45 #define DEBUG_TYPE "riscv-asm-parser"
46 
47 // Include the auto-generated portion of the compress emitter.
48 #define GEN_COMPRESS_INSTR
49 #include "RISCVGenCompressInstEmitter.inc"
50 
51 STATISTIC(RISCVNumInstrsCompressed,
52  "Number of RISC-V Compressed instructions emitted");
53 
54 namespace llvm {
55 extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
56 } // namespace llvm
57 
58 namespace {
59 struct RISCVOperand;
60 
61 struct ParserOptionsSet {
62  bool IsPicEnabled;
63 };
64 
65 class RISCVAsmParser : public MCTargetAsmParser {
66  SmallVector<FeatureBitset, 4> FeatureBitStack;
67 
68  SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
69  ParserOptionsSet ParserOptions;
70 
71  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
72  bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
73  bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); }
74 
75  RISCVTargetStreamer &getTargetStreamer() {
76  MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
77  return static_cast<RISCVTargetStreamer &>(TS);
78  }
79 
80  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
81  unsigned Kind) override;
82 
83  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
84  int64_t Lower, int64_t Upper, Twine Msg);
85 
86  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
89  bool MatchingInlineAsm) override;
90 
91  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
92  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
93  SMLoc &EndLoc) override;
94 
95  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
96  SMLoc NameLoc, OperandVector &Operands) override;
97 
98  bool ParseDirective(AsmToken DirectiveID) override;
99 
100  // Helper to actually emit an instruction to the MCStreamer. Also, when
101  // possible, compression of the instruction is performed.
102  void emitToStreamer(MCStreamer &S, const MCInst &Inst);
103 
104  // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
105  // synthesize the desired immedate value into the destination register.
106  void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
107 
108  // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
109  // helpers such as emitLoadLocalAddress and emitLoadAddress.
110  void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
112  unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
113 
114  // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
115  void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
116 
117  // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
118  void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
119 
120  // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
121  // addressing.
122  void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
123 
124  // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
125  // addressing.
126  void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
127 
128  // Helper to emit pseudo load/store instruction with a symbol.
129  void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
130  MCStreamer &Out, bool HasTmpReg);
131 
132  // Helper to emit pseudo sign/zero extend instruction.
133  void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
134  SMLoc IDLoc, MCStreamer &Out);
135 
136  // Helper to emit pseudo vmsge{u}.vx instruction.
137  void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
138 
139  // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
140  // Enforcing this using a restricted register class for the second input
141  // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
142  // 'add' is an overloaded mnemonic.
143  bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
144 
145  // Check instruction constraints.
146  bool validateInstruction(MCInst &Inst, OperandVector &Operands);
147 
148  /// Helper for processing MC instructions that have been successfully matched
149  /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
150  /// like the expansion of pseudo instructions (e.g., "li"), can be performed
151  /// in this method.
152  bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
153  MCStreamer &Out);
154 
155 // Auto-generated instruction matching functions
156 #define GET_ASSEMBLER_HEADER
157 #include "RISCVGenAsmMatcher.inc"
158 
159  OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
162  bool AllowParens = false);
163  OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
164  OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands);
165  OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
166  OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
167  OperandMatchResultTy parseCallSymbol(OperandVector &Operands);
168  OperandMatchResultTy parsePseudoJumpSymbol(OperandVector &Operands);
172  OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
173 
174  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
175 
176  bool parseDirectiveOption();
177  bool parseDirectiveAttribute();
178  bool parseDirectiveInsn(SMLoc L);
179 
180  void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
181  if (!(getSTI().getFeatureBits()[Feature])) {
182  MCSubtargetInfo &STI = copySTI();
183  setAvailableFeatures(
184  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
185  }
186  }
187 
188  bool getFeatureBits(uint64_t Feature) {
189  return getSTI().getFeatureBits()[Feature];
190  }
191 
192  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
193  if (getSTI().getFeatureBits()[Feature]) {
194  MCSubtargetInfo &STI = copySTI();
195  setAvailableFeatures(
196  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
197  }
198  }
199 
200  void pushFeatureBits() {
201  assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
202  "These two stacks must be kept synchronized");
203  FeatureBitStack.push_back(getSTI().getFeatureBits());
204  ParserOptionsStack.push_back(ParserOptions);
205  }
206 
207  bool popFeatureBits() {
208  assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
209  "These two stacks must be kept synchronized");
210  if (FeatureBitStack.empty())
211  return true;
212 
213  FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
214  copySTI().setFeatureBits(FeatureBits);
215  setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
216 
217  ParserOptions = ParserOptionsStack.pop_back_val();
218 
219  return false;
220  }
221 
222  std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
223 
224 public:
225  enum RISCVMatchResultTy {
226  Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
227 #define GET_OPERAND_DIAGNOSTIC_TYPES
228 #include "RISCVGenAsmMatcher.inc"
229 #undef GET_OPERAND_DIAGNOSTIC_TYPES
230  };
231 
232  static bool classifySymbolRef(const MCExpr *Expr,
234 
235  RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
236  const MCInstrInfo &MII, const MCTargetOptions &Options)
237  : MCTargetAsmParser(Options, STI, MII) {
238  Parser.addAliasForDirective(".half", ".2byte");
239  Parser.addAliasForDirective(".hword", ".2byte");
240  Parser.addAliasForDirective(".word", ".4byte");
241  Parser.addAliasForDirective(".dword", ".8byte");
242  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
243 
244  auto ABIName = StringRef(Options.ABIName);
245  if (ABIName.endswith("f") &&
246  !getSTI().getFeatureBits()[RISCV::FeatureStdExtF]) {
247  errs() << "Hard-float 'f' ABI can't be used for a target that "
248  "doesn't support the F instruction set extension (ignoring "
249  "target-abi)\n";
250  } else if (ABIName.endswith("d") &&
251  !getSTI().getFeatureBits()[RISCV::FeatureStdExtD]) {
252  errs() << "Hard-float 'd' ABI can't be used for a target that "
253  "doesn't support the D instruction set extension (ignoring "
254  "target-abi)\n";
255  }
256 
257  const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
258  ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
259  }
260 };
261 
262 /// RISCVOperand - Instances of this class represent a parsed machine
263 /// instruction
264 struct RISCVOperand : public MCParsedAsmOperand {
265 
266  enum class KindTy {
267  Token,
268  Register,
269  Immediate,
270  SystemRegister,
271  VType,
272  } Kind;
273 
274  bool IsRV64;
275 
276  struct RegOp {
277  MCRegister RegNum;
278  };
279 
280  struct ImmOp {
281  const MCExpr *Val;
282  };
283 
284  struct SysRegOp {
285  const char *Data;
286  unsigned Length;
287  unsigned Encoding;
288  // FIXME: Add the Encoding parsed fields as needed for checks,
289  // e.g.: read/write or user/supervisor/machine privileges.
290  };
291 
292  struct VTypeOp {
293  unsigned Val;
294  };
295 
296  SMLoc StartLoc, EndLoc;
297  union {
298  StringRef Tok;
299  RegOp Reg;
300  ImmOp Imm;
301  struct SysRegOp SysReg;
302  struct VTypeOp VType;
303  };
304 
305  RISCVOperand(KindTy K) : Kind(K) {}
306 
307 public:
308  RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
309  Kind = o.Kind;
310  IsRV64 = o.IsRV64;
311  StartLoc = o.StartLoc;
312  EndLoc = o.EndLoc;
313  switch (Kind) {
314  case KindTy::Register:
315  Reg = o.Reg;
316  break;
317  case KindTy::Immediate:
318  Imm = o.Imm;
319  break;
320  case KindTy::Token:
321  Tok = o.Tok;
322  break;
323  case KindTy::SystemRegister:
324  SysReg = o.SysReg;
325  break;
326  case KindTy::VType:
327  VType = o.VType;
328  break;
329  }
330  }
331 
332  bool isToken() const override { return Kind == KindTy::Token; }
333  bool isReg() const override { return Kind == KindTy::Register; }
334  bool isV0Reg() const {
335  return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
336  }
337  bool isImm() const override { return Kind == KindTy::Immediate; }
338  bool isMem() const override { return false; }
339  bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
340 
341  bool isGPR() const {
342  return Kind == KindTy::Register &&
343  RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
344  }
345 
346  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
348  if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
349  VK = RE->getKind();
350  return RE->evaluateAsConstant(Imm);
351  }
352 
353  if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
355  Imm = CE->getValue();
356  return true;
357  }
358 
359  return false;
360  }
361 
362  // True if operand is a symbol with no modifiers, or a constant with no
363  // modifiers and isShiftedInt<N-1, 1>(Op).
364  template <int N> bool isBareSimmNLsb0() const {
365  int64_t Imm;
367  if (!isImm())
368  return false;
369  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
370  bool IsValid;
371  if (!IsConstantImm)
372  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
373  else
374  IsValid = isShiftedInt<N - 1, 1>(Imm);
375  return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
376  }
377 
378  // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
379 
380  bool isBareSymbol() const {
381  int64_t Imm;
383  // Must be of 'immediate' type but not a constant.
384  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
385  return false;
386  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
388  }
389 
390  bool isCallSymbol() const {
391  int64_t Imm;
393  // Must be of 'immediate' type but not a constant.
394  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
395  return false;
396  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
399  }
400 
401  bool isPseudoJumpSymbol() const {
402  int64_t Imm;
404  // Must be of 'immediate' type but not a constant.
405  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
406  return false;
407  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
409  }
410 
411  bool isTPRelAddSymbol() const {
412  int64_t Imm;
414  // Must be of 'immediate' type but not a constant.
415  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
416  return false;
417  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
419  }
420 
421  bool isCSRSystemRegister() const { return isSystemRegister(); }
422 
423  bool isVTypeImm(unsigned N) const {
424  int64_t Imm;
426  if (!isImm())
427  return false;
428  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
429  return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
430  }
431 
432  // If the last operand of the vsetvli/vsetvli instruction is a constant
433  // expression, KindTy is Immediate.
434  bool isVTypeI10() const {
435  if (Kind == KindTy::Immediate)
436  return isVTypeImm(10);
437  return Kind == KindTy::VType;
438  }
439  bool isVTypeI11() const {
440  if (Kind == KindTy::Immediate)
441  return isVTypeImm(11);
442  return Kind == KindTy::VType;
443  }
444 
445  /// Return true if the operand is a valid for the fence instruction e.g.
446  /// ('iorw').
447  bool isFenceArg() const {
448  if (!isImm())
449  return false;
450  const MCExpr *Val = getImm();
451  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
452  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
453  return false;
454 
455  StringRef Str = SVal->getSymbol().getName();
456  // Letters must be unique, taken from 'iorw', and in ascending order. This
457  // holds as long as each individual character is one of 'iorw' and is
458  // greater than the previous character.
459  char Prev = '\0';
460  for (char c : Str) {
461  if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
462  return false;
463  if (c <= Prev)
464  return false;
465  Prev = c;
466  }
467  return true;
468  }
469 
470  /// Return true if the operand is a valid floating point rounding mode.
471  bool isFRMArg() const {
472  if (!isImm())
473  return false;
474  const MCExpr *Val = getImm();
475  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
476  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
477  return false;
478 
479  StringRef Str = SVal->getSymbol().getName();
480 
482  }
483 
484  bool isImmXLenLI() const {
485  int64_t Imm;
487  if (!isImm())
488  return false;
489  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
491  return true;
492  // Given only Imm, ensuring that the actually specified constant is either
493  // a signed or unsigned 64-bit number is unfortunately impossible.
494  return IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None &&
495  (isRV64() || (isInt<32>(Imm) || isUInt<32>(Imm)));
496  }
497 
498  bool isUImmLog2XLen() const {
499  int64_t Imm;
501  if (!isImm())
502  return false;
503  if (!evaluateConstantImm(getImm(), Imm, VK) ||
505  return false;
506  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
507  }
508 
509  bool isUImmLog2XLenNonZero() const {
510  int64_t Imm;
512  if (!isImm())
513  return false;
514  if (!evaluateConstantImm(getImm(), Imm, VK) ||
516  return false;
517  if (Imm == 0)
518  return false;
519  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
520  }
521 
522  bool isUImmLog2XLenHalf() const {
523  int64_t Imm;
525  if (!isImm())
526  return false;
527  if (!evaluateConstantImm(getImm(), Imm, VK) ||
529  return false;
530  return (isRV64() && isUInt<5>(Imm)) || isUInt<4>(Imm);
531  }
532 
533  bool isUImm2() const {
534  int64_t Imm;
536  if (!isImm())
537  return false;
538  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
539  return IsConstantImm && isUInt<2>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
540  }
541 
542  bool isUImm3() const {
543  int64_t Imm;
545  if (!isImm())
546  return false;
547  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
548  return IsConstantImm && isUInt<3>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
549  }
550 
551  bool isUImm5() const {
552  int64_t Imm;
554  if (!isImm())
555  return false;
556  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
557  return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
558  }
559 
560  bool isUImm7() const {
561  int64_t Imm;
563  if (!isImm())
564  return false;
565  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
566  return IsConstantImm && isUInt<7>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
567  }
568 
569  bool isRnumArg() const {
570  int64_t Imm;
572  if (!isImm())
573  return false;
574  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
575  return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
577  }
578 
579  bool isSImm5() const {
580  if (!isImm())
581  return false;
583  int64_t Imm;
584  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
585  return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
586  }
587 
588  bool isSImm6() const {
589  if (!isImm())
590  return false;
592  int64_t Imm;
593  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
594  return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
595  }
596 
597  bool isSImm6NonZero() const {
598  if (!isImm())
599  return false;
601  int64_t Imm;
602  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
603  return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
605  }
606 
607  bool isCLUIImm() const {
608  if (!isImm())
609  return false;
610  int64_t Imm;
612  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
613  return IsConstantImm && (Imm != 0) &&
614  (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
616  }
617 
618  bool isUImm7Lsb00() const {
619  if (!isImm())
620  return false;
621  int64_t Imm;
623  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
624  return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
626  }
627 
628  bool isUImm8Lsb00() const {
629  if (!isImm())
630  return false;
631  int64_t Imm;
633  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
634  return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
636  }
637 
638  bool isUImm8Lsb000() const {
639  if (!isImm())
640  return false;
641  int64_t Imm;
643  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
644  return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
646  }
647 
648  bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
649 
650  bool isUImm9Lsb000() const {
651  if (!isImm())
652  return false;
653  int64_t Imm;
655  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
656  return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
658  }
659 
660  bool isUImm10Lsb00NonZero() const {
661  if (!isImm())
662  return false;
663  int64_t Imm;
665  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
666  return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
668  }
669 
670  bool isSImm12() const {
672  int64_t Imm;
673  bool IsValid;
674  if (!isImm())
675  return false;
676  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
677  if (!IsConstantImm)
678  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
679  else
680  IsValid = isInt<12>(Imm);
681  return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
682  VK == RISCVMCExpr::VK_RISCV_LO ||
685  }
686 
687  bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
688 
689  bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
690 
691  bool isSImm10Lsb0000NonZero() const {
692  if (!isImm())
693  return false;
694  int64_t Imm;
696  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
697  return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
699  }
700 
701  bool isUImm20LUI() const {
703  int64_t Imm;
704  bool IsValid;
705  if (!isImm())
706  return false;
707  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
708  if (!IsConstantImm) {
709  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
710  return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
712  } else {
713  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
714  VK == RISCVMCExpr::VK_RISCV_HI ||
716  }
717  }
718 
719  bool isUImm20AUIPC() const {
721  int64_t Imm;
722  bool IsValid;
723  if (!isImm())
724  return false;
725  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
726  if (!IsConstantImm) {
727  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
728  return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
732  } else {
733  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
738  }
739  }
740 
741  bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
742 
743  bool isImmZero() const {
744  if (!isImm())
745  return false;
746  int64_t Imm;
748  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
749  return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
750  }
751 
752  bool isSImm5Plus1() const {
753  if (!isImm())
754  return false;
756  int64_t Imm;
757  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
758  return IsConstantImm && isInt<5>(Imm - 1) &&
760  }
761 
762  /// getStartLoc - Gets location of the first token of this operand
763  SMLoc getStartLoc() const override { return StartLoc; }
764  /// getEndLoc - Gets location of the last token of this operand
765  SMLoc getEndLoc() const override { return EndLoc; }
766  /// True if this operand is for an RV64 instruction
767  bool isRV64() const { return IsRV64; }
768 
769  unsigned getReg() const override {
770  assert(Kind == KindTy::Register && "Invalid type access!");
771  return Reg.RegNum.id();
772  }
773 
774  StringRef getSysReg() const {
775  assert(Kind == KindTy::SystemRegister && "Invalid type access!");
776  return StringRef(SysReg.Data, SysReg.Length);
777  }
778 
779  const MCExpr *getImm() const {
780  assert(Kind == KindTy::Immediate && "Invalid type access!");
781  return Imm.Val;
782  }
783 
784  StringRef getToken() const {
785  assert(Kind == KindTy::Token && "Invalid type access!");
786  return Tok;
787  }
788 
789  unsigned getVType() const {
790  assert(Kind == KindTy::VType && "Invalid type access!");
791  return VType.Val;
792  }
793 
794  void print(raw_ostream &OS) const override {
795  auto RegName = [](unsigned Reg) {
796  if (Reg)
798  else
799  return "noreg";
800  };
801 
802  switch (Kind) {
803  case KindTy::Immediate:
804  OS << *getImm();
805  break;
806  case KindTy::Register:
807  OS << "<register " << RegName(getReg()) << ">";
808  break;
809  case KindTy::Token:
810  OS << "'" << getToken() << "'";
811  break;
812  case KindTy::SystemRegister:
813  OS << "<sysreg: " << getSysReg() << '>';
814  break;
815  case KindTy::VType:
816  OS << "<vtype: ";
817  RISCVVType::printVType(getVType(), OS);
818  OS << '>';
819  break;
820  }
821  }
822 
823  static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
824  bool IsRV64) {
825  auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
826  Op->Tok = Str;
827  Op->StartLoc = S;
828  Op->EndLoc = S;
829  Op->IsRV64 = IsRV64;
830  return Op;
831  }
832 
833  static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
834  SMLoc E, bool IsRV64) {
835  auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
836  Op->Reg.RegNum = RegNo;
837  Op->StartLoc = S;
838  Op->EndLoc = E;
839  Op->IsRV64 = IsRV64;
840  return Op;
841  }
842 
843  static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
844  SMLoc E, bool IsRV64) {
845  auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
846  Op->Imm.Val = Val;
847  Op->StartLoc = S;
848  Op->EndLoc = E;
849  Op->IsRV64 = IsRV64;
850  return Op;
851  }
852 
853  static std::unique_ptr<RISCVOperand>
854  createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
855  auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
856  Op->SysReg.Data = Str.data();
857  Op->SysReg.Length = Str.size();
858  Op->SysReg.Encoding = Encoding;
859  Op->StartLoc = S;
860  Op->EndLoc = S;
861  Op->IsRV64 = IsRV64;
862  return Op;
863  }
864 
865  static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S,
866  bool IsRV64) {
867  auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
868  Op->VType.Val = VTypeI;
869  Op->StartLoc = S;
870  Op->EndLoc = S;
871  Op->IsRV64 = IsRV64;
872  return Op;
873  }
874 
875  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
876  assert(Expr && "Expr shouldn't be null!");
877  int64_t Imm = 0;
878  RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
879  bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
880 
881  if (IsConstant)
882  Inst.addOperand(MCOperand::createImm(Imm));
883  else
884  Inst.addOperand(MCOperand::createExpr(Expr));
885  }
886 
887  // Used by the TableGen Code
888  void addRegOperands(MCInst &Inst, unsigned N) const {
889  assert(N == 1 && "Invalid number of operands!");
890  Inst.addOperand(MCOperand::createReg(getReg()));
891  }
892 
893  void addImmOperands(MCInst &Inst, unsigned N) const {
894  assert(N == 1 && "Invalid number of operands!");
895  addExpr(Inst, getImm());
896  }
897 
898  void addFenceArgOperands(MCInst &Inst, unsigned N) const {
899  assert(N == 1 && "Invalid number of operands!");
900  // isFenceArg has validated the operand, meaning this cast is safe
901  auto SE = cast<MCSymbolRefExpr>(getImm());
902 
903  unsigned Imm = 0;
904  for (char c : SE->getSymbol().getName()) {
905  switch (c) {
906  default:
907  llvm_unreachable("FenceArg must contain only [iorw]");
908  case 'i':
909  Imm |= RISCVFenceField::I;
910  break;
911  case 'o':
912  Imm |= RISCVFenceField::O;
913  break;
914  case 'r':
915  Imm |= RISCVFenceField::R;
916  break;
917  case 'w':
918  Imm |= RISCVFenceField::W;
919  break;
920  }
921  }
922  Inst.addOperand(MCOperand::createImm(Imm));
923  }
924 
925  void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
926  assert(N == 1 && "Invalid number of operands!");
927  Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
928  }
929 
930  // Support non-canonical syntax:
931  // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
932  // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
933  void addVTypeIOperands(MCInst &Inst, unsigned N) const {
934  assert(N == 1 && "Invalid number of operands!");
935  int64_t Imm = 0;
936  if (Kind == KindTy::Immediate) {
937  RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
938  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
939  (void)IsConstantImm;
940  assert(IsConstantImm && "Invalid VTypeI Operand!");
941  } else {
942  Imm = getVType();
943  }
944  Inst.addOperand(MCOperand::createImm(Imm));
945  }
946 
947  // Returns the rounding mode represented by this RISCVOperand. Should only
948  // be called after checking isFRMArg.
949  RISCVFPRndMode::RoundingMode getRoundingMode() const {
950  // isFRMArg has validated the operand, meaning this cast is safe.
951  auto SE = cast<MCSymbolRefExpr>(getImm());
952  RISCVFPRndMode::RoundingMode FRM =
953  RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
954  assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
955  return FRM;
956  }
957 
958  void addFRMArgOperands(MCInst &Inst, unsigned N) const {
959  assert(N == 1 && "Invalid number of operands!");
960  Inst.addOperand(MCOperand::createImm(getRoundingMode()));
961  }
962 };
963 } // end anonymous namespace.
964 
965 #define GET_REGISTER_MATCHER
966 #define GET_SUBTARGET_FEATURE_NAME
967 #define GET_MATCHER_IMPLEMENTATION
968 #define GET_MNEMONIC_SPELL_CHECKER
969 #include "RISCVGenAsmMatcher.inc"
970 
971 static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
972  assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
973  return Reg - RISCV::F0_D + RISCV::F0_H;
974 }
975 
976 static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
977  assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
978  return Reg - RISCV::F0_D + RISCV::F0_F;
979 }
980 
981 static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
982  unsigned Kind) {
983  unsigned RegClassID;
984  if (Kind == MCK_VRM2)
985  RegClassID = RISCV::VRM2RegClassID;
986  else if (Kind == MCK_VRM4)
987  RegClassID = RISCV::VRM4RegClassID;
988  else if (Kind == MCK_VRM8)
989  RegClassID = RISCV::VRM8RegClassID;
990  else
991  return 0;
992  return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
993  &RISCVMCRegisterClasses[RegClassID]);
994 }
995 
996 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
997  unsigned Kind) {
998  RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
999  if (!Op.isReg())
1000  return Match_InvalidOperand;
1001 
1002  MCRegister Reg = Op.getReg();
1003  bool IsRegFPR64 =
1004  RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1005  bool IsRegFPR64C =
1006  RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1007  bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1008 
1009  // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1010  // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1011  if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1012  (IsRegFPR64C && Kind == MCK_FPR32C)) {
1013  Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1014  return Match_Success;
1015  }
1016  // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1017  // register from FPR64 to FPR16 if necessary.
1018  if (IsRegFPR64 && Kind == MCK_FPR16) {
1019  Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1020  return Match_Success;
1021  }
1022  // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1023  // the register from VR to VRM2/VRM4/VRM8 if necessary.
1024  if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1025  Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1026  if (Op.Reg.RegNum == 0)
1027  return Match_InvalidOperand;
1028  return Match_Success;
1029  }
1030  return Match_InvalidOperand;
1031 }
1032 
1033 bool RISCVAsmParser::generateImmOutOfRangeError(
1034  OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1035  Twine Msg = "immediate must be an integer in the range") {
1036  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1037  return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1038 }
1039 
1040 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1041  OperandVector &Operands,
1042  MCStreamer &Out,
1043  uint64_t &ErrorInfo,
1044  bool MatchingInlineAsm) {
1045  MCInst Inst;
1046  FeatureBitset MissingFeatures;
1047 
1048  auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1049  MatchingInlineAsm);
1050  switch (Result) {
1051  default:
1052  break;
1053  case Match_Success:
1054  if (validateInstruction(Inst, Operands))
1055  return true;
1056  return processInstruction(Inst, IDLoc, Operands, Out);
1057  case Match_MissingFeature: {
1058  assert(MissingFeatures.any() && "Unknown missing features!");
1059  bool FirstFeature = true;
1060  std::string Msg = "instruction requires the following:";
1061  for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1062  if (MissingFeatures[i]) {
1063  Msg += FirstFeature ? " " : ", ";
1064  Msg += getSubtargetFeatureName(i);
1065  FirstFeature = false;
1066  }
1067  }
1068  return Error(IDLoc, Msg);
1069  }
1070  case Match_MnemonicFail: {
1071  FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1072  std::string Suggestion = RISCVMnemonicSpellCheck(
1073  ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1074  return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1075  }
1076  case Match_InvalidOperand: {
1077  SMLoc ErrorLoc = IDLoc;
1078  if (ErrorInfo != ~0ULL) {
1079  if (ErrorInfo >= Operands.size())
1080  return Error(ErrorLoc, "too few operands for instruction");
1081 
1082  ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1083  if (ErrorLoc == SMLoc())
1084  ErrorLoc = IDLoc;
1085  }
1086  return Error(ErrorLoc, "invalid operand for instruction");
1087  }
1088  }
1089 
1090  // Handle the case when the error message is of specific type
1091  // other than the generic Match_InvalidOperand, and the
1092  // corresponding operand is missing.
1093  if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1094  SMLoc ErrorLoc = IDLoc;
1095  if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1096  return Error(ErrorLoc, "too few operands for instruction");
1097  }
1098 
1099  switch (Result) {
1100  default:
1101  break;
1102  case Match_InvalidImmXLenLI:
1103  if (isRV64()) {
1104  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1105  return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1106  }
1107  return generateImmOutOfRangeError(Operands, ErrorInfo,
1108  std::numeric_limits<int32_t>::min(),
1109  std::numeric_limits<uint32_t>::max());
1110  case Match_InvalidImmZero: {
1111  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1112  return Error(ErrorLoc, "immediate must be zero");
1113  }
1114  case Match_InvalidUImmLog2XLen:
1115  if (isRV64())
1116  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1117  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1118  case Match_InvalidUImmLog2XLenNonZero:
1119  if (isRV64())
1120  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1121  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1122  case Match_InvalidUImmLog2XLenHalf:
1123  if (isRV64())
1124  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1125  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1126  case Match_InvalidUImm2:
1127  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1128  case Match_InvalidUImm3:
1129  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1130  case Match_InvalidUImm5:
1131  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1132  case Match_InvalidUImm7:
1133  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1134  case Match_InvalidSImm5:
1135  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1136  (1 << 4) - 1);
1137  case Match_InvalidSImm6:
1138  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1139  (1 << 5) - 1);
1140  case Match_InvalidSImm6NonZero:
1141  return generateImmOutOfRangeError(
1142  Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1143  "immediate must be non-zero in the range");
1144  case Match_InvalidCLUIImm:
1145  return generateImmOutOfRangeError(
1146  Operands, ErrorInfo, 1, (1 << 5) - 1,
1147  "immediate must be in [0xfffe0, 0xfffff] or");
1148  case Match_InvalidUImm7Lsb00:
1149  return generateImmOutOfRangeError(
1150  Operands, ErrorInfo, 0, (1 << 7) - 4,
1151  "immediate must be a multiple of 4 bytes in the range");
1152  case Match_InvalidUImm8Lsb00:
1153  return generateImmOutOfRangeError(
1154  Operands, ErrorInfo, 0, (1 << 8) - 4,
1155  "immediate must be a multiple of 4 bytes in the range");
1156  case Match_InvalidUImm8Lsb000:
1157  return generateImmOutOfRangeError(
1158  Operands, ErrorInfo, 0, (1 << 8) - 8,
1159  "immediate must be a multiple of 8 bytes in the range");
1160  case Match_InvalidSImm9Lsb0:
1161  return generateImmOutOfRangeError(
1162  Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1163  "immediate must be a multiple of 2 bytes in the range");
1164  case Match_InvalidUImm9Lsb000:
1165  return generateImmOutOfRangeError(
1166  Operands, ErrorInfo, 0, (1 << 9) - 8,
1167  "immediate must be a multiple of 8 bytes in the range");
1168  case Match_InvalidUImm10Lsb00NonZero:
1169  return generateImmOutOfRangeError(
1170  Operands, ErrorInfo, 4, (1 << 10) - 4,
1171  "immediate must be a multiple of 4 bytes in the range");
1172  case Match_InvalidSImm10Lsb0000NonZero:
1173  return generateImmOutOfRangeError(
1174  Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1175  "immediate must be a multiple of 16 bytes and non-zero in the range");
1176  case Match_InvalidSImm12:
1177  return generateImmOutOfRangeError(
1178  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1179  "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1180  "integer in the range");
1181  case Match_InvalidSImm12Lsb0:
1182  return generateImmOutOfRangeError(
1183  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1184  "immediate must be a multiple of 2 bytes in the range");
1185  case Match_InvalidSImm13Lsb0:
1186  return generateImmOutOfRangeError(
1187  Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1188  "immediate must be a multiple of 2 bytes in the range");
1189  case Match_InvalidUImm20LUI:
1190  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1191  "operand must be a symbol with "
1192  "%hi/%tprel_hi modifier or an integer in "
1193  "the range");
1194  case Match_InvalidUImm20AUIPC:
1195  return generateImmOutOfRangeError(
1196  Operands, ErrorInfo, 0, (1 << 20) - 1,
1197  "operand must be a symbol with a "
1198  "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1199  "an integer in the range");
1200  case Match_InvalidSImm21Lsb0JAL:
1201  return generateImmOutOfRangeError(
1202  Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1203  "immediate must be a multiple of 2 bytes in the range");
1204  case Match_InvalidCSRSystemRegister: {
1205  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1206  "operand must be a valid system register "
1207  "name or an integer in the range");
1208  }
1209  case Match_InvalidFenceArg: {
1210  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1211  return Error(
1212  ErrorLoc,
1213  "operand must be formed of letters selected in-order from 'iorw'");
1214  }
1215  case Match_InvalidFRMArg: {
1216  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1217  return Error(
1218  ErrorLoc,
1219  "operand must be a valid floating point rounding mode mnemonic");
1220  }
1221  case Match_InvalidBareSymbol: {
1222  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1223  return Error(ErrorLoc, "operand must be a bare symbol name");
1224  }
1225  case Match_InvalidPseudoJumpSymbol: {
1226  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1227  return Error(ErrorLoc, "operand must be a valid jump target");
1228  }
1229  case Match_InvalidCallSymbol: {
1230  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1231  return Error(ErrorLoc, "operand must be a bare symbol name");
1232  }
1233  case Match_InvalidTPRelAddSymbol: {
1234  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1235  return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1236  }
1237  case Match_InvalidVTypeI: {
1238  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1239  return Error(
1240  ErrorLoc,
1241  "operand must be "
1242  "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
1243  }
1244  case Match_InvalidVMaskRegister: {
1245  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1246  return Error(ErrorLoc, "operand must be v0.t");
1247  }
1248  case Match_InvalidSImm5Plus1: {
1249  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1250  (1 << 4),
1251  "immediate must be in the range");
1252  }
1253  case Match_InvalidRnumArg: {
1254  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1255  }
1256  }
1257 
1258  llvm_unreachable("Unknown match type detected!");
1259 }
1260 
1261 // Attempts to match Name as a register (either using the default name or
1262 // alternative ABI names), setting RegNo to the matching register. Upon
1263 // failure, returns true and sets RegNo to 0. If IsRV32E then registers
1264 // x16-x31 will be rejected.
1265 static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo,
1266  StringRef Name) {
1267  RegNo = MatchRegisterName(Name);
1268  // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1269  // match always matches the 64-bit variant, and not the 16/32-bit one.
1270  assert(!(RegNo >= RISCV::F0_H && RegNo <= RISCV::F31_H));
1271  assert(!(RegNo >= RISCV::F0_F && RegNo <= RISCV::F31_F));
1272  // The default FPR register class is based on the tablegen enum ordering.
1273  static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1274  static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1275  if (RegNo == RISCV::NoRegister)
1276  RegNo = MatchRegisterAltName(Name);
1277  if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
1278  RegNo = RISCV::NoRegister;
1279  return RegNo == RISCV::NoRegister;
1280 }
1281 
1282 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1283  SMLoc &EndLoc) {
1284  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
1285  return Error(StartLoc, "invalid register name");
1286  return false;
1287 }
1288 
1289 OperandMatchResultTy RISCVAsmParser::tryParseRegister(unsigned &RegNo,
1290  SMLoc &StartLoc,
1291  SMLoc &EndLoc) {
1292  const AsmToken &Tok = getParser().getTok();
1293  StartLoc = Tok.getLoc();
1294  EndLoc = Tok.getEndLoc();
1295  RegNo = 0;
1296  StringRef Name = getLexer().getTok().getIdentifier();
1297 
1298  if (matchRegisterNameHelper(isRV32E(), (MCRegister &)RegNo, Name))
1299  return MatchOperand_NoMatch;
1300 
1301  getParser().Lex(); // Eat identifier token.
1302  return MatchOperand_Success;
1303 }
1304 
1305 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
1306  bool AllowParens) {
1307  SMLoc FirstS = getLoc();
1308  bool HadParens = false;
1309  AsmToken LParen;
1310 
1311  // If this is an LParen and a parenthesised register name is allowed, parse it
1312  // atomically.
1313  if (AllowParens && getLexer().is(AsmToken::LParen)) {
1314  AsmToken Buf[2];
1315  size_t ReadCount = getLexer().peekTokens(Buf);
1316  if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1317  HadParens = true;
1318  LParen = getParser().getTok();
1319  getParser().Lex(); // Eat '('
1320  }
1321  }
1322 
1323  switch (getLexer().getKind()) {
1324  default:
1325  if (HadParens)
1326  getLexer().UnLex(LParen);
1327  return MatchOperand_NoMatch;
1328  case AsmToken::Identifier:
1329  StringRef Name = getLexer().getTok().getIdentifier();
1330  MCRegister RegNo;
1331  matchRegisterNameHelper(isRV32E(), RegNo, Name);
1332 
1333  if (RegNo == RISCV::NoRegister) {
1334  if (HadParens)
1335  getLexer().UnLex(LParen);
1336  return MatchOperand_NoMatch;
1337  }
1338  if (HadParens)
1339  Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
1340  SMLoc S = getLoc();
1341  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
1342  getLexer().Lex();
1343  Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
1344  }
1345 
1346  if (HadParens) {
1347  getParser().Lex(); // Eat ')'
1348  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
1349  }
1350 
1351  return MatchOperand_Success;
1352 }
1353 
1354 OperandMatchResultTy
1355 RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1356  SMLoc S = getLoc();
1357  SMLoc E;
1358  const MCExpr *Res;
1359 
1360  switch (getLexer().getKind()) {
1361  default:
1362  return MatchOperand_NoMatch;
1363  case AsmToken::LParen:
1364  case AsmToken::Minus:
1365  case AsmToken::Plus:
1366  case AsmToken::Exclaim:
1367  case AsmToken::Tilde:
1368  case AsmToken::Integer:
1369  case AsmToken::String: {
1370  if (getParser().parseExpression(Res, E))
1371  return MatchOperand_ParseFail;
1372 
1373  auto *CE = dyn_cast<MCConstantExpr>(Res);
1374  if (CE) {
1375  int64_t Imm = CE->getValue();
1376  if (isUInt<7>(Imm)) {
1377  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1378  return MatchOperand_Success;
1379  }
1380  }
1381 
1382  Twine Msg = "immediate must be an integer in the range";
1383  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1384  return MatchOperand_ParseFail;
1385  }
1386  case AsmToken::Identifier: {
1387  StringRef Identifier;
1388  if (getParser().parseIdentifier(Identifier))
1389  return MatchOperand_ParseFail;
1390 
1391  auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1392  if (Opcode) {
1393  Res = MCConstantExpr::create(Opcode->Value, getContext());
1394  E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1395  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1396  return MatchOperand_Success;
1397  }
1398 
1399  Twine Msg = "operand must be a valid opcode name or an "
1400  "integer in the range";
1401  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1402  return MatchOperand_ParseFail;
1403  }
1404  case AsmToken::Percent: {
1405  // Discard operand with modifier.
1406  Twine Msg = "immediate must be an integer in the range";
1407  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1408  return MatchOperand_ParseFail;
1409  }
1410  }
1411 
1412  return MatchOperand_NoMatch;
1413 }
1414 
1415 OperandMatchResultTy
1416 RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1417  SMLoc S = getLoc();
1418  const MCExpr *Res;
1419 
1420  switch (getLexer().getKind()) {
1421  default:
1422  return MatchOperand_NoMatch;
1423  case AsmToken::LParen:
1424  case AsmToken::Minus:
1425  case AsmToken::Plus:
1426  case AsmToken::Exclaim:
1427  case AsmToken::Tilde:
1428  case AsmToken::Integer:
1429  case AsmToken::String: {
1430  if (getParser().parseExpression(Res))
1431  return MatchOperand_ParseFail;
1432 
1433  auto *CE = dyn_cast<MCConstantExpr>(Res);
1434  if (CE) {
1435  int64_t Imm = CE->getValue();
1436  if (isUInt<12>(Imm)) {
1437  auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1438  // Accept an immediate representing a named or un-named Sys Reg
1439  // if the range is valid, regardless of the required features.
1440  Operands.push_back(RISCVOperand::createSysReg(
1441  SysReg ? SysReg->Name : "", S, Imm, isRV64()));
1442  return MatchOperand_Success;
1443  }
1444  }
1445 
1446  Twine Msg = "immediate must be an integer in the range";
1447  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1448  return MatchOperand_ParseFail;
1449  }
1450  case AsmToken::Identifier: {
1451  StringRef Identifier;
1452  if (getParser().parseIdentifier(Identifier))
1453  return MatchOperand_ParseFail;
1454 
1455  auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1456  if (!SysReg)
1457  SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1458  if (!SysReg)
1459  if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1460  Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1461  SysReg->Name + "'");
1462 
1463  // Accept a named Sys Reg if the required features are present.
1464  if (SysReg) {
1465  if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1466  Error(S, "system register use requires an option to be enabled");
1467  return MatchOperand_ParseFail;
1468  }
1469  Operands.push_back(RISCVOperand::createSysReg(
1470  Identifier, S, SysReg->Encoding, isRV64()));
1471  return MatchOperand_Success;
1472  }
1473 
1474  Twine Msg = "operand must be a valid system register name "
1475  "or an integer in the range";
1476  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1477  return MatchOperand_ParseFail;
1478  }
1479  case AsmToken::Percent: {
1480  // Discard operand with modifier.
1481  Twine Msg = "immediate must be an integer in the range";
1482  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1483  return MatchOperand_ParseFail;
1484  }
1485  }
1486 
1487  return MatchOperand_NoMatch;
1488 }
1489 
1490 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1491  SMLoc S = getLoc();
1492  SMLoc E;
1493  const MCExpr *Res;
1494 
1495  switch (getLexer().getKind()) {
1496  default:
1497  return MatchOperand_NoMatch;
1498  case AsmToken::LParen:
1499  case AsmToken::Dot:
1500  case AsmToken::Minus:
1501  case AsmToken::Plus:
1502  case AsmToken::Exclaim:
1503  case AsmToken::Tilde:
1504  case AsmToken::Integer:
1505  case AsmToken::String:
1506  case AsmToken::Identifier:
1507  if (getParser().parseExpression(Res, E))
1508  return MatchOperand_ParseFail;
1509  break;
1510  case AsmToken::Percent:
1511  return parseOperandWithModifier(Operands);
1512  }
1513 
1514  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1515  return MatchOperand_Success;
1516 }
1517 
1518 OperandMatchResultTy
1519 RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1520  SMLoc S = getLoc();
1521  SMLoc E;
1522 
1523  if (getLexer().getKind() != AsmToken::Percent) {
1524  Error(getLoc(), "expected '%' for operand modifier");
1525  return MatchOperand_ParseFail;
1526  }
1527 
1528  getParser().Lex(); // Eat '%'
1529 
1530  if (getLexer().getKind() != AsmToken::Identifier) {
1531  Error(getLoc(), "expected valid identifier for operand modifier");
1532  return MatchOperand_ParseFail;
1533  }
1534  StringRef Identifier = getParser().getTok().getIdentifier();
1535  RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1536  if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1537  Error(getLoc(), "unrecognized operand modifier");
1538  return MatchOperand_ParseFail;
1539  }
1540 
1541  getParser().Lex(); // Eat the identifier
1542  if (getLexer().getKind() != AsmToken::LParen) {
1543  Error(getLoc(), "expected '('");
1544  return MatchOperand_ParseFail;
1545  }
1546  getParser().Lex(); // Eat '('
1547 
1548  const MCExpr *SubExpr;
1549  if (getParser().parseParenExpression(SubExpr, E)) {
1550  return MatchOperand_ParseFail;
1551  }
1552 
1553  const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1554  Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1555  return MatchOperand_Success;
1556 }
1557 
1558 OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1559  SMLoc S = getLoc();
1560  const MCExpr *Res;
1561 
1562  if (getLexer().getKind() != AsmToken::Identifier)
1563  return MatchOperand_NoMatch;
1564 
1565  StringRef Identifier;
1566  AsmToken Tok = getLexer().getTok();
1567 
1568  if (getParser().parseIdentifier(Identifier))
1569  return MatchOperand_ParseFail;
1570 
1571  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1572 
1573  if (Identifier.consume_back("@plt")) {
1574  Error(getLoc(), "'@plt' operand not valid for instruction");
1575  return MatchOperand_ParseFail;
1576  }
1577 
1578  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1579 
1580  if (Sym->isVariable()) {
1581  const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1582  if (!isa<MCSymbolRefExpr>(V)) {
1583  getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1584  return MatchOperand_NoMatch;
1585  }
1586  Res = V;
1587  } else
1588  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1589 
1590  MCBinaryExpr::Opcode Opcode;
1591  switch (getLexer().getKind()) {
1592  default:
1593  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1594  return MatchOperand_Success;
1595  case AsmToken::Plus:
1596  Opcode = MCBinaryExpr::Add;
1597  break;
1598  case AsmToken::Minus:
1599  Opcode = MCBinaryExpr::Sub;
1600  break;
1601  }
1602 
1603  const MCExpr *Expr;
1604  if (getParser().parseExpression(Expr, E))
1605  return MatchOperand_ParseFail;
1606  Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1607  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1608  return MatchOperand_Success;
1609 }
1610 
1611 OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
1612  SMLoc S = getLoc();
1613  const MCExpr *Res;
1614 
1615  if (getLexer().getKind() != AsmToken::Identifier)
1616  return MatchOperand_NoMatch;
1617 
1618  // Avoid parsing the register in `call rd, foo` as a call symbol.
1619  if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
1620  return MatchOperand_NoMatch;
1621 
1622  StringRef Identifier;
1623  if (getParser().parseIdentifier(Identifier))
1624  return MatchOperand_ParseFail;
1625 
1626  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1627 
1628  RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL;
1629  if (Identifier.consume_back("@plt"))
1630  Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
1631 
1632  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1633  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1634  Res = RISCVMCExpr::create(Res, Kind, getContext());
1635  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1636  return MatchOperand_Success;
1637 }
1638 
1639 OperandMatchResultTy
1640 RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
1641  SMLoc S = getLoc();
1642  SMLoc E;
1643  const MCExpr *Res;
1644 
1645  if (getParser().parseExpression(Res, E))
1646  return MatchOperand_ParseFail;
1647 
1648  if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
1649  cast<MCSymbolRefExpr>(Res)->getKind() ==
1650  MCSymbolRefExpr::VariantKind::VK_PLT) {
1651  Error(S, "operand must be a valid jump target");
1652  return MatchOperand_ParseFail;
1653  }
1654 
1655  Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
1656  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1657  return MatchOperand_Success;
1658 }
1659 
1660 OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1661  // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1662  // both being acceptable forms. When parsing `jal ra, foo` this function
1663  // will be called for the `ra` register operand in an attempt to match the
1664  // single-operand alias. parseJALOffset must fail for this case. It would
1665  // seem logical to try parse the operand using parseImmediate and return
1666  // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1667  // the second form rather than the first). We can't do this as there's no
1668  // way of rewinding the lexer state. Instead, return NoMatch if this operand
1669  // is an identifier and is followed by a comma.
1670  if (getLexer().is(AsmToken::Identifier) &&
1671  getLexer().peekTok().is(AsmToken::Comma))
1672  return MatchOperand_NoMatch;
1673 
1674  return parseImmediate(Operands);
1675 }
1676 
1677 OperandMatchResultTy RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
1678  SMLoc S = getLoc();
1679  if (getLexer().isNot(AsmToken::Identifier))
1680  return MatchOperand_NoMatch;
1681 
1682  SmallVector<AsmToken, 7> VTypeIElements;
1683  // Put all the tokens for vtypei operand into VTypeIElements vector.
1684  while (getLexer().isNot(AsmToken::EndOfStatement)) {
1685  VTypeIElements.push_back(getLexer().getTok());
1686  getLexer().Lex();
1687  if (getLexer().is(AsmToken::EndOfStatement))
1688  break;
1689  if (getLexer().isNot(AsmToken::Comma))
1690  goto MatchFail;
1691  AsmToken Comma = getLexer().getTok();
1692  VTypeIElements.push_back(Comma);
1693  getLexer().Lex();
1694  }
1695 
1696  if (VTypeIElements.size() == 7) {
1697  // The VTypeIElements layout is:
1698  // SEW comma LMUL comma TA comma MA
1699  // 0 1 2 3 4 5 6
1700  StringRef Name = VTypeIElements[0].getIdentifier();
1701  if (!Name.consume_front("e"))
1702  goto MatchFail;
1703  unsigned Sew;
1704  if (Name.getAsInteger(10, Sew))
1705  goto MatchFail;
1706  if (!RISCVVType::isValidSEW(Sew))
1707  goto MatchFail;
1708 
1709  Name = VTypeIElements[2].getIdentifier();
1710  if (!Name.consume_front("m"))
1711  goto MatchFail;
1712  // "m" or "mf"
1713  bool Fractional = Name.consume_front("f");
1714  unsigned Lmul;
1715  if (Name.getAsInteger(10, Lmul))
1716  goto MatchFail;
1717  if (!RISCVVType::isValidLMUL(Lmul, Fractional))
1718  goto MatchFail;
1719 
1720  // ta or tu
1721  Name = VTypeIElements[4].getIdentifier();
1722  bool TailAgnostic;
1723  if (Name == "ta")
1724  TailAgnostic = true;
1725  else if (Name == "tu")
1726  TailAgnostic = false;
1727  else
1728  goto MatchFail;
1729 
1730  // ma or mu
1731  Name = VTypeIElements[6].getIdentifier();
1732  bool MaskAgnostic;
1733  if (Name == "ma")
1734  MaskAgnostic = true;
1735  else if (Name == "mu")
1736  MaskAgnostic = false;
1737  else
1738  goto MatchFail;
1739 
1740  unsigned LmulLog2 = Log2_32(Lmul);
1741  RISCVII::VLMUL VLMUL =
1742  static_cast<RISCVII::VLMUL>(Fractional ? 8 - LmulLog2 : LmulLog2);
1743 
1744  unsigned VTypeI =
1745  RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
1746  Operands.push_back(RISCVOperand::createVType(VTypeI, S, isRV64()));
1747  return MatchOperand_Success;
1748  }
1749 
1750 // If NoMatch, unlex all the tokens that comprise a vtypei operand
1751 MatchFail:
1752  while (!VTypeIElements.empty())
1753  getLexer().UnLex(VTypeIElements.pop_back_val());
1754  return MatchOperand_NoMatch;
1755 }
1756 
1757 OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
1758  switch (getLexer().getKind()) {
1759  default:
1760  return MatchOperand_NoMatch;
1761  case AsmToken::Identifier:
1762  StringRef Name = getLexer().getTok().getIdentifier();
1763  if (!Name.consume_back(".t")) {
1764  Error(getLoc(), "expected '.t' suffix");
1765  return MatchOperand_ParseFail;
1766  }
1767  MCRegister RegNo;
1768  matchRegisterNameHelper(isRV32E(), RegNo, Name);
1769 
1770  if (RegNo == RISCV::NoRegister)
1771  return MatchOperand_NoMatch;
1772  if (RegNo != RISCV::V0)
1773  return MatchOperand_NoMatch;
1774  SMLoc S = getLoc();
1775  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
1776  getLexer().Lex();
1777  Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
1778  }
1779 
1780  return MatchOperand_Success;
1781 }
1782 
1783 OperandMatchResultTy
1784 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1785  if (getLexer().isNot(AsmToken::LParen)) {
1786  Error(getLoc(), "expected '('");
1787  return MatchOperand_ParseFail;
1788  }
1789 
1790  getParser().Lex(); // Eat '('
1791  Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
1792 
1793  if (parseRegister(Operands) != MatchOperand_Success) {
1794  Error(getLoc(), "expected register");
1795  return MatchOperand_ParseFail;
1796  }
1797 
1798  if (getLexer().isNot(AsmToken::RParen)) {
1799  Error(getLoc(), "expected ')'");
1800  return MatchOperand_ParseFail;
1801  }
1802 
1803  getParser().Lex(); // Eat ')'
1804  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
1805 
1806  return MatchOperand_Success;
1807 }
1808 
1809 OperandMatchResultTy RISCVAsmParser::parseAtomicMemOp(OperandVector &Operands) {
1810  // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
1811  // as one of their register operands, such as `(a0)`. This just denotes that
1812  // the register (in this case `a0`) contains a memory address.
1813  //
1814  // Normally, we would be able to parse these by putting the parens into the
1815  // instruction string. However, GNU as also accepts a zero-offset memory
1816  // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
1817  // with parseImmediate followed by parseMemOpBaseReg, but these instructions
1818  // do not accept an immediate operand, and we do not want to add a "dummy"
1819  // operand that is silently dropped.
1820  //
1821  // Instead, we use this custom parser. This will: allow (and discard) an
1822  // offset if it is zero; require (and discard) parentheses; and add only the
1823  // parsed register operand to `Operands`.
1824  //
1825  // These operands are printed with RISCVInstPrinter::printAtomicMemOp, which
1826  // will only print the register surrounded by parentheses (which GNU as also
1827  // uses as its canonical representation for these operands).
1828  std::unique_ptr<RISCVOperand> OptionalImmOp;
1829 
1830  if (getLexer().isNot(AsmToken::LParen)) {
1831  // Parse an Integer token. We do not accept arbritrary constant expressions
1832  // in the offset field (because they may include parens, which complicates
1833  // parsing a lot).
1834  int64_t ImmVal;
1835  SMLoc ImmStart = getLoc();
1836  if (getParser().parseIntToken(ImmVal,
1837  "expected '(' or optional integer offset"))
1838  return MatchOperand_ParseFail;
1839 
1840  // Create a RISCVOperand for checking later (so the error messages are
1841  // nicer), but we don't add it to Operands.
1842  SMLoc ImmEnd = getLoc();
1843  OptionalImmOp =
1844  RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
1845  ImmStart, ImmEnd, isRV64());
1846  }
1847 
1848  if (getLexer().isNot(AsmToken::LParen)) {
1849  Error(getLoc(), OptionalImmOp ? "expected '(' after optional integer offset"
1850  : "expected '(' or optional integer offset");
1851  return MatchOperand_ParseFail;
1852  }
1853  getParser().Lex(); // Eat '('
1854 
1855  if (parseRegister(Operands) != MatchOperand_Success) {
1856  Error(getLoc(), "expected register");
1857  return MatchOperand_ParseFail;
1858  }
1859 
1860  if (getLexer().isNot(AsmToken::RParen)) {
1861  Error(getLoc(), "expected ')'");
1862  return MatchOperand_ParseFail;
1863  }
1864  getParser().Lex(); // Eat ')'
1865 
1866  // Deferred Handling of non-zero offsets. This makes the error messages nicer.
1867  if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
1868  Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
1869  SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
1870  return MatchOperand_ParseFail;
1871  }
1872 
1873  return MatchOperand_Success;
1874 }
1875 
1876 /// Looks at a token type and creates the relevant operand from this
1877 /// information, adding to Operands. If operand was parsed, returns false, else
1878 /// true.
1879 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1880  // Check if the current operand has a custom associated parser, if so, try to
1881  // custom parse the operand, or fallback to the general approach.
1882  OperandMatchResultTy Result =
1883  MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1884  if (Result == MatchOperand_Success)
1885  return false;
1886  if (Result == MatchOperand_ParseFail)
1887  return true;
1888 
1889  // Attempt to parse token as a register.
1890  if (parseRegister(Operands, true) == MatchOperand_Success)
1891  return false;
1892 
1893  // Attempt to parse token as an immediate
1894  if (parseImmediate(Operands) == MatchOperand_Success) {
1895  // Parse memory base register if present
1896  if (getLexer().is(AsmToken::LParen))
1897  return parseMemOpBaseReg(Operands) != MatchOperand_Success;
1898  return false;
1899  }
1900 
1901  // Finally we have exhausted all options and must declare defeat.
1902  Error(getLoc(), "unknown operand");
1903  return true;
1904 }
1905 
1906 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1907  StringRef Name, SMLoc NameLoc,
1908  OperandVector &Operands) {
1909  // Ensure that if the instruction occurs when relaxation is enabled,
1910  // relocations are forced for the file. Ideally this would be done when there
1911  // is enough information to reliably determine if the instruction itself may
1912  // cause relaxations. Unfortunately instruction processing stage occurs in the
1913  // same pass as relocation emission, so it's too late to set a 'sticky bit'
1914  // for the entire file.
1915  if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1916  auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1917  if (Assembler != nullptr) {
1918  RISCVAsmBackend &MAB =
1919  static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1920  MAB.setForceRelocs();
1921  }
1922  }
1923 
1924  // First operand is token for instruction
1925  Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
1926 
1927  // If there are no more operands, then finish
1928  if (getLexer().is(AsmToken::EndOfStatement)) {
1929  getParser().Lex(); // Consume the EndOfStatement.
1930  return false;
1931  }
1932 
1933  // Parse first operand
1934  if (parseOperand(Operands, Name))
1935  return true;
1936 
1937  // Parse until end of statement, consuming commas between operands
1938  unsigned OperandIdx = 1;
1939  while (getLexer().is(AsmToken::Comma)) {
1940  // Consume comma token
1941  getLexer().Lex();
1942 
1943  // Parse next operand
1944  if (parseOperand(Operands, Name))
1945  return true;
1946 
1947  ++OperandIdx;
1948  }
1949 
1950  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1951  SMLoc Loc = getLexer().getLoc();
1952  getParser().eatToEndOfStatement();
1953  return Error(Loc, "unexpected token");
1954  }
1955 
1956  getParser().Lex(); // Consume the EndOfStatement.
1957  return false;
1958 }
1959 
1960 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1961  RISCVMCExpr::VariantKind &Kind) {
1962  Kind = RISCVMCExpr::VK_RISCV_None;
1963 
1964  if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1965  Kind = RE->getKind();
1966  Expr = RE->getSubExpr();
1967  }
1968 
1969  MCValue Res;
1970  MCFixup Fixup;
1971  if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
1972  return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
1973  return false;
1974 }
1975 
1976 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1977  // This returns false if this function recognizes the directive
1978  // regardless of whether it is successfully handles or reports an
1979  // error. Otherwise it returns true to give the generic parser a
1980  // chance at recognizing it.
1981  StringRef IDVal = DirectiveID.getString();
1982 
1983  if (IDVal == ".option")
1984  return parseDirectiveOption();
1985  if (IDVal == ".attribute")
1986  return parseDirectiveAttribute();
1987  if (IDVal == ".insn")
1988  return parseDirectiveInsn(DirectiveID.getLoc());
1989 
1990  return true;
1991 }
1992 
1993 bool RISCVAsmParser::parseDirectiveOption() {
1994  MCAsmParser &Parser = getParser();
1995  // Get the option token.
1996  AsmToken Tok = Parser.getTok();
1997  // At the moment only identifiers are supported.
1998  if (Tok.isNot(AsmToken::Identifier))
1999  return Error(Parser.getTok().getLoc(),
2000  "unexpected token, expected identifier");
2001 
2002  StringRef Option = Tok.getIdentifier();
2003 
2004  if (Option == "push") {
2005  getTargetStreamer().emitDirectiveOptionPush();
2006 
2007  Parser.Lex();
2008  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2009  return Error(Parser.getTok().getLoc(),
2010  "unexpected token, expected end of statement");
2011 
2012  pushFeatureBits();
2013  return false;
2014  }
2015 
2016  if (Option == "pop") {
2017  SMLoc StartLoc = Parser.getTok().getLoc();
2018  getTargetStreamer().emitDirectiveOptionPop();
2019 
2020  Parser.Lex();
2021  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2022  return Error(Parser.getTok().getLoc(),
2023  "unexpected token, expected end of statement");
2024 
2025  if (popFeatureBits())
2026  return Error(StartLoc, ".option pop with no .option push");
2027 
2028  return false;
2029  }
2030 
2031  if (Option == "rvc") {
2032  getTargetStreamer().emitDirectiveOptionRVC();
2033 
2034  Parser.Lex();
2035  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2036  return Error(Parser.getTok().getLoc(),
2037  "unexpected token, expected end of statement");
2038 
2039  setFeatureBits(RISCV::FeatureStdExtC, "c");
2040  return false;
2041  }
2042 
2043  if (Option == "norvc") {
2044  getTargetStreamer().emitDirectiveOptionNoRVC();
2045 
2046  Parser.Lex();
2047  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2048  return Error(Parser.getTok().getLoc(),
2049  "unexpected token, expected end of statement");
2050 
2051  clearFeatureBits(RISCV::FeatureStdExtC, "c");
2052  return false;
2053  }
2054 
2055  if (Option == "pic") {
2056  getTargetStreamer().emitDirectiveOptionPIC();
2057 
2058  Parser.Lex();
2059  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2060  return Error(Parser.getTok().getLoc(),
2061  "unexpected token, expected end of statement");
2062 
2063  ParserOptions.IsPicEnabled = true;
2064  return false;
2065  }
2066 
2067  if (Option == "nopic") {
2068  getTargetStreamer().emitDirectiveOptionNoPIC();
2069 
2070  Parser.Lex();
2071  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2072  return Error(Parser.getTok().getLoc(),
2073  "unexpected token, expected end of statement");
2074 
2075  ParserOptions.IsPicEnabled = false;
2076  return false;
2077  }
2078 
2079  if (Option == "relax") {
2080  getTargetStreamer().emitDirectiveOptionRelax();
2081 
2082  Parser.Lex();
2083  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2084  return Error(Parser.getTok().getLoc(),
2085  "unexpected token, expected end of statement");
2086 
2087  setFeatureBits(RISCV::FeatureRelax, "relax");
2088  return false;
2089  }
2090 
2091  if (Option == "norelax") {
2092  getTargetStreamer().emitDirectiveOptionNoRelax();
2093 
2094  Parser.Lex();
2095  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
2096  return Error(Parser.getTok().getLoc(),
2097  "unexpected token, expected end of statement");
2098 
2099  clearFeatureBits(RISCV::FeatureRelax, "relax");
2100  return false;
2101  }
2102 
2103  // Unknown option.
2104  Warning(Parser.getTok().getLoc(),
2105  "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
2106  "'norelax'");
2107  Parser.eatToEndOfStatement();
2108  return false;
2109 }
2110 
2111 /// parseDirectiveAttribute
2112 /// ::= .attribute expression ',' ( expression | "string" )
2113 /// ::= .attribute identifier ',' ( expression | "string" )
2114 bool RISCVAsmParser::parseDirectiveAttribute() {
2115  MCAsmParser &Parser = getParser();
2116  int64_t Tag;
2117  SMLoc TagLoc;
2118  TagLoc = Parser.getTok().getLoc();
2119  if (Parser.getTok().is(AsmToken::Identifier)) {
2120  StringRef Name = Parser.getTok().getIdentifier();
2121  Optional<unsigned> Ret =
2122  ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
2123  if (!Ret.hasValue()) {
2124  Error(TagLoc, "attribute name not recognised: " + Name);
2125  return false;
2126  }
2127  Tag = Ret.getValue();
2128  Parser.Lex();
2129  } else {
2130  const MCExpr *AttrExpr;
2131 
2132  TagLoc = Parser.getTok().getLoc();
2133  if (Parser.parseExpression(AttrExpr))
2134  return true;
2135 
2136  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
2137  if (check(!CE, TagLoc, "expected numeric constant"))
2138  return true;
2139 
2140  Tag = CE->getValue();
2141  }
2142 
2143  if (Parser.parseToken(AsmToken::Comma, "comma expected"))
2144  return true;
2145 
2146  StringRef StringValue;
2147  int64_t IntegerValue = 0;
2148  bool IsIntegerValue = true;
2149 
2150  // RISC-V attributes have a string value if the tag number is odd
2151  // and an integer value if the tag number is even.
2152  if (Tag % 2)
2153  IsIntegerValue = false;
2154 
2155  SMLoc ValueExprLoc = Parser.getTok().getLoc();
2156  if (IsIntegerValue) {
2157  const MCExpr *ValueExpr;
2158  if (Parser.parseExpression(ValueExpr))
2159  return true;
2160 
2161  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
2162  if (!CE)
2163  return Error(ValueExprLoc, "expected numeric constant");
2164  IntegerValue = CE->getValue();
2165  } else {
2166  if (Parser.getTok().isNot(AsmToken::String))
2167  return Error(Parser.getTok().getLoc(), "expected string constant");
2168 
2169  StringValue = Parser.getTok().getStringContents();
2170  Parser.Lex();
2171  }
2172 
2173  if (Parser.parseToken(AsmToken::EndOfStatement,
2174  "unexpected token in '.attribute' directive"))
2175  return true;
2176 
2177  if (IsIntegerValue)
2178  getTargetStreamer().emitAttribute(Tag, IntegerValue);
2179  else if (Tag != RISCVAttrs::ARCH)
2180  getTargetStreamer().emitTextAttribute(Tag, StringValue);
2181  else {
2182  StringRef Arch = StringValue;
2183  for (auto Feature : RISCVFeatureKV)
2184  if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2185  clearFeatureBits(Feature.Value, Feature.Key);
2186 
2187  auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2188  StringValue, /*EnableExperimentalExtension=*/true,
2189  /*ExperimentalExtensionVersionCheck=*/true);
2190  if (!ParseResult) {
2191  std::string Buffer;
2192  raw_string_ostream OutputErrMsg(Buffer);
2193  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2194  OutputErrMsg << "invalid arch name '" << Arch << "', "
2195  << ErrMsg.getMessage();
2196  });
2197 
2198  return Error(ValueExprLoc, OutputErrMsg.str());
2199  }
2200  auto &ISAInfo = *ParseResult;
2201 
2202  for (auto Feature : RISCVFeatureKV)
2203  if (ISAInfo->hasExtension(Feature.Key))
2204  setFeatureBits(Feature.Value, Feature.Key);
2205 
2206  if (ISAInfo->getXLen() == 32)
2207  clearFeatureBits(RISCV::Feature64Bit, "64bit");
2208  else if (ISAInfo->getXLen() == 64)
2209  setFeatureBits(RISCV::Feature64Bit, "64bit");
2210  else
2211  return Error(ValueExprLoc, "bad arch string " + Arch);
2212 
2213  // Then emit the arch string.
2214  getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
2215  }
2216 
2217  return false;
2218 }
2219 
2220 /// parseDirectiveInsn
2221 /// ::= .insn [ format encoding, (operands (, operands)*) ]
2222 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
2223  MCAsmParser &Parser = getParser();
2224 
2225  // Expect instruction format as identifier.
2226  StringRef Format;
2227  SMLoc ErrorLoc = Parser.getTok().getLoc();
2228  if (Parser.parseIdentifier(Format))
2229  return Error(ErrorLoc, "expected instruction format");
2230 
2231  if (Format != "r" && Format != "r4" && Format != "i" && Format != "b" &&
2232  Format != "sb" && Format != "u" && Format != "j" && Format != "uj" &&
2233  Format != "s")
2234  return Error(ErrorLoc, "invalid instruction format");
2235 
2236  std::string FormatName = (".insn_" + Format).str();
2237 
2238  ParseInstructionInfo Info;
2239  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
2240 
2241  if (ParseInstruction(Info, FormatName, L, Operands))
2242  return true;
2243 
2244  unsigned Opcode;
2245  uint64_t ErrorInfo;
2246  return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
2247  ErrorInfo,
2248  /*MatchingInlineAsm=*/false);
2249 }
2250 
2251 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
2252  MCInst CInst;
2253  bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
2254  if (Res)
2255  ++RISCVNumInstrsCompressed;
2256  S.emitInstruction((Res ? CInst : Inst), getSTI());
2257 }
2258 
2259 void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
2260  MCStreamer &Out) {
2261  RISCVMatInt::InstSeq Seq =
2262  RISCVMatInt::generateInstSeq(Value, getSTI().getFeatureBits());
2263 
2264  MCRegister SrcReg = RISCV::X0;
2265  for (RISCVMatInt::Inst &Inst : Seq) {
2266  if (Inst.Opc == RISCV::LUI) {
2267  emitToStreamer(
2268  Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
2269  } else if (Inst.Opc == RISCV::ADDUW) {
2270  emitToStreamer(Out, MCInstBuilder(RISCV::ADDUW)
2271  .addReg(DestReg)
2272  .addReg(SrcReg)
2273  .addReg(RISCV::X0));
2274  } else if (Inst.Opc == RISCV::SH1ADD || Inst.Opc == RISCV::SH2ADD ||
2275  Inst.Opc == RISCV::SH3ADD) {
2276  emitToStreamer(
2277  Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addReg(
2278  SrcReg));
2279  } else {
2280  emitToStreamer(
2281  Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
2282  Inst.Imm));
2283  }
2284 
2285  // Only the first instruction has X0 as its source.
2286  SrcReg = DestReg;
2287  }
2288 }
2289 
2290 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
2291  const MCExpr *Symbol,
2292  RISCVMCExpr::VariantKind VKHi,
2293  unsigned SecondOpcode, SMLoc IDLoc,
2294  MCStreamer &Out) {
2295  // A pair of instructions for PC-relative addressing; expands to
2296  // TmpLabel: AUIPC TmpReg, VKHi(symbol)
2297  // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
2298  MCContext &Ctx = getContext();
2299 
2300  MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
2301  Out.emitLabel(TmpLabel);
2302 
2303  const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
2304  emitToStreamer(
2305  Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
2306 
2307  const MCExpr *RefToLinkTmpLabel =
2308  RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
2309  RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
2310 
2311  emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2312  .addOperand(DestReg)
2313  .addOperand(TmpReg)
2314  .addExpr(RefToLinkTmpLabel));
2315 }
2316 
2317 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
2318  MCStreamer &Out) {
2319  // The load local address pseudo-instruction "lla" is used in PC-relative
2320  // addressing of local symbols:
2321  // lla rdest, symbol
2322  // expands to
2323  // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2324  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2325  MCOperand DestReg = Inst.getOperand(0);
2326  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2327  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2328  RISCV::ADDI, IDLoc, Out);
2329 }
2330 
2331 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
2332  MCStreamer &Out) {
2333  // The load address pseudo-instruction "la" is used in PC-relative and
2334  // GOT-indirect addressing of global symbols:
2335  // la rdest, symbol
2336  // expands to either (for non-PIC)
2337  // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2338  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2339  // or (for PIC)
2340  // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
2341  // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2342  MCOperand DestReg = Inst.getOperand(0);
2343  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2344  unsigned SecondOpcode;
2345  RISCVMCExpr::VariantKind VKHi;
2346  if (ParserOptions.IsPicEnabled) {
2347  SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2348  VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
2349  } else {
2350  SecondOpcode = RISCV::ADDI;
2351  VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
2352  }
2353  emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
2354 }
2355 
2356 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
2357  MCStreamer &Out) {
2358  // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
2359  // initial-exec TLS model addressing of global symbols:
2360  // la.tls.ie rdest, symbol
2361  // expands to
2362  // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
2363  // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2364  MCOperand DestReg = Inst.getOperand(0);
2365  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2366  unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2367  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
2368  SecondOpcode, IDLoc, Out);
2369 }
2370 
2371 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
2372  MCStreamer &Out) {
2373  // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
2374  // global-dynamic TLS model addressing of global symbols:
2375  // la.tls.gd rdest, symbol
2376  // expands to
2377  // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
2378  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2379  MCOperand DestReg = Inst.getOperand(0);
2380  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2381  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
2382  RISCV::ADDI, IDLoc, Out);
2383 }
2384 
2385 void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
2386  SMLoc IDLoc, MCStreamer &Out,
2387  bool HasTmpReg) {
2388  // The load/store pseudo-instruction does a pc-relative load with
2389  // a symbol.
2390  //
2391  // The expansion looks like this
2392  //
2393  // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
2394  // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
2395  unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
2396  MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
2397  unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
2398  MCOperand TmpReg = Inst.getOperand(0);
2399  const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
2400  emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2401  Opcode, IDLoc, Out);
2402 }
2403 
2404 void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
2405  int64_t Width, SMLoc IDLoc,
2406  MCStreamer &Out) {
2407  // The sign/zero extend pseudo-instruction does two shifts, with the shift
2408  // amounts dependent on the XLEN.
2409  //
2410  // The expansion looks like this
2411  //
2412  // SLLI rd, rs, XLEN - Width
2413  // SR[A|R]I rd, rd, XLEN - Width
2414  MCOperand DestReg = Inst.getOperand(0);
2415  MCOperand SourceReg = Inst.getOperand(1);
2416 
2417  unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
2418  int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
2419 
2420  assert(ShAmt > 0 && "Shift amount must be non-zero.");
2421 
2422  emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
2423  .addOperand(DestReg)
2424  .addOperand(SourceReg)
2425  .addImm(ShAmt));
2426 
2427  emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2428  .addOperand(DestReg)
2429  .addOperand(DestReg)
2430  .addImm(ShAmt));
2431 }
2432 
2433 void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
2434  MCStreamer &Out) {
2435  if (Inst.getNumOperands() == 3) {
2436  // unmasked va >= x
2437  //
2438  // pseudoinstruction: vmsge{u}.vx vd, va, x
2439  // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
2440  emitToStreamer(Out, MCInstBuilder(Opcode)
2441  .addOperand(Inst.getOperand(0))
2442  .addOperand(Inst.getOperand(1))
2443  .addOperand(Inst.getOperand(2))
2444  .addReg(RISCV::NoRegister));
2445  emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
2446  .addOperand(Inst.getOperand(0))
2447  .addOperand(Inst.getOperand(0))
2448  .addOperand(Inst.getOperand(0)));
2449  } else if (Inst.getNumOperands() == 4) {
2450  // masked va >= x, vd != v0
2451  //
2452  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
2453  // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
2454  assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
2455  "The destination register should not be V0.");
2456  emitToStreamer(Out, MCInstBuilder(Opcode)
2457  .addOperand(Inst.getOperand(0))
2458  .addOperand(Inst.getOperand(1))
2459  .addOperand(Inst.getOperand(2))
2460  .addOperand(Inst.getOperand(3)));
2461  emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
2462  .addOperand(Inst.getOperand(0))
2463  .addOperand(Inst.getOperand(0))
2464  .addReg(RISCV::V0));
2465  } else if (Inst.getNumOperands() == 5 &&
2466  Inst.getOperand(0).getReg() == RISCV::V0) {
2467  // masked va >= x, vd == v0
2468  //
2469  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2470  // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
2471  assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
2472  "The destination register should be V0.");
2473  assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2474  "The temporary vector register should not be V0.");
2475  emitToStreamer(Out, MCInstBuilder(Opcode)
2476  .addOperand(Inst.getOperand(1))
2477  .addOperand(Inst.getOperand(2))
2478  .addOperand(Inst.getOperand(3))
2479  .addOperand(Inst.getOperand(4)));
2480  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2481  .addOperand(Inst.getOperand(0))
2482  .addOperand(Inst.getOperand(0))
2483  .addOperand(Inst.getOperand(1)));
2484  } else if (Inst.getNumOperands() == 5) {
2485  // masked va >= x, any vd
2486  //
2487  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2488  // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt; vmandn.mm vd,
2489  // vd, v0; vmor.mm vd, vt, vd
2490  assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2491  "The temporary vector register should not be V0.");
2492  emitToStreamer(Out, MCInstBuilder(Opcode)
2493  .addOperand(Inst.getOperand(1))
2494  .addOperand(Inst.getOperand(2))
2495  .addOperand(Inst.getOperand(3))
2496  .addReg(RISCV::NoRegister));
2497  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2498  .addOperand(Inst.getOperand(1))
2499  .addReg(RISCV::V0)
2500  .addOperand(Inst.getOperand(1)));
2501  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2502  .addOperand(Inst.getOperand(0))
2503  .addOperand(Inst.getOperand(0))
2504  .addReg(RISCV::V0));
2505  emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
2506  .addOperand(Inst.getOperand(0))
2507  .addOperand(Inst.getOperand(1))
2508  .addOperand(Inst.getOperand(0)));
2509  }
2510 }
2511 
2512 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
2513  OperandVector &Operands) {
2514  assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
2515  assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
2516  if (Inst.getOperand(2).getReg() != RISCV::X4) {
2517  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
2518  return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
2519  "%tprel_add modifier");
2520  }
2521 
2522  return false;
2523 }
2524 
2525 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
2526  return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
2527  llvm::SMLoc(), isRV64());
2528 }
2529 
2530 bool RISCVAsmParser::validateInstruction(MCInst &Inst,
2531  OperandVector &Operands) {
2532  if (Inst.getOpcode() == RISCV::PseudoVMSGEU_VX_M_T ||
2533  Inst.getOpcode() == RISCV::PseudoVMSGE_VX_M_T) {
2534  unsigned DestReg = Inst.getOperand(0).getReg();
2535  unsigned TempReg = Inst.getOperand(1).getReg();
2536  if (DestReg == TempReg) {
2537  SMLoc Loc = Operands.back()->getStartLoc();
2538  return Error(Loc, "The temporary vector register cannot be the same as "
2539  "the destination register.");
2540  }
2541  }
2542 
2543  const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
2544  RISCVII::VConstraintType Constraints =
2545  RISCVII::getConstraint(MCID.TSFlags);
2546  if (Constraints == RISCVII::NoConstraint)
2547  return false;
2548 
2549  unsigned DestReg = Inst.getOperand(0).getReg();
2550  // Operands[1] will be the first operand, DestReg.
2551  SMLoc Loc = Operands[1]->getStartLoc();
2552  if (Constraints & RISCVII::VS2Constraint) {
2553  unsigned CheckReg = Inst.getOperand(1).getReg();
2554  if (DestReg == CheckReg)
2555  return Error(Loc, "The destination vector register group cannot overlap"
2556  " the source vector register group.");
2557  }
2558  if ((Constraints & RISCVII::VS1Constraint) && (Inst.getOperand(2).isReg())) {
2559  unsigned CheckReg = Inst.getOperand(2).getReg();
2560  if (DestReg == CheckReg)
2561  return Error(Loc, "The destination vector register group cannot overlap"
2562  " the source vector register group.");
2563  }
2564  if ((Constraints & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
2565  // vadc, vsbc are special cases. These instructions have no mask register.
2566  // The destination register could not be V0.
2567  unsigned Opcode = Inst.getOpcode();
2568  if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
2569  Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
2570  Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
2571  Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
2572  Opcode == RISCV::VMERGE_VXM)
2573  return Error(Loc, "The destination vector register group cannot be V0.");
2574 
2575  // Regardless masked or unmasked version, the number of operands is the
2576  // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
2577  // actually. We need to check the last operand to ensure whether it is
2578  // masked or not.
2579  unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
2580  assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
2581  "Unexpected register for mask operand");
2582 
2583  if (DestReg == CheckReg)
2584  return Error(Loc, "The destination vector register group cannot overlap"
2585  " the mask register.");
2586  }
2587  return false;
2588 }
2589 
2590 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
2591  OperandVector &Operands,
2592  MCStreamer &Out) {
2593  Inst.setLoc(IDLoc);
2594 
2595  switch (Inst.getOpcode()) {
2596  default:
2597  break;
2598  case RISCV::PseudoLI: {
2599  MCRegister Reg = Inst.getOperand(0).getReg();
2600  const MCOperand &Op1 = Inst.getOperand(1);
2601  if (Op1.isExpr()) {
2602  // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
2603  // Just convert to an addi. This allows compatibility with gas.
2604  emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
2605  .addReg(Reg)
2606  .addReg(RISCV::X0)
2607  .addExpr(Op1.getExpr()));
2608  return false;
2609  }
2610  int64_t Imm = Inst.getOperand(1).getImm();
2611  // On RV32 the immediate here can either be a signed or an unsigned
2612  // 32-bit number. Sign extension has to be performed to ensure that Imm
2613  // represents the expected signed 64-bit number.
2614  if (!isRV64())
2615  Imm = SignExtend64<32>(Imm);
2616  emitLoadImm(Reg, Imm, Out);
2617  return false;
2618  }
2619  case RISCV::PseudoLLA:
2620  emitLoadLocalAddress(Inst, IDLoc, Out);
2621  return false;
2622  case RISCV::PseudoLA:
2623  emitLoadAddress(Inst, IDLoc, Out);
2624  return false;
2625  case RISCV::PseudoLA_TLS_IE:
2626  emitLoadTLSIEAddress(Inst, IDLoc, Out);
2627  return false;
2628  case RISCV::PseudoLA_TLS_GD:
2629  emitLoadTLSGDAddress(Inst, IDLoc, Out);
2630  return false;
2631  case RISCV::PseudoLB:
2632  emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
2633  return false;
2634  case RISCV::PseudoLBU:
2635  emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
2636  return false;
2637  case RISCV::PseudoLH:
2638  emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
2639  return false;
2640  case RISCV::PseudoLHU:
2641  emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
2642  return false;
2643  case RISCV::PseudoLW:
2644  emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
2645  return false;
2646  case RISCV::PseudoLWU:
2647  emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
2648  return false;
2649  case RISCV::PseudoLD:
2650  emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
2651  return false;
2652  case RISCV::PseudoFLH:
2653  emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
2654  return false;
2655  case RISCV::PseudoFLW:
2656  emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
2657  return false;
2658  case RISCV::PseudoFLD:
2659  emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
2660  return false;
2661  case RISCV::PseudoSB:
2662  emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
2663  return false;
2664  case RISCV::PseudoSH:
2665  emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
2666  return false;
2667  case RISCV::PseudoSW:
2668  emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
2669  return false;
2670  case RISCV::PseudoSD:
2671  emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
2672  return false;
2673  case RISCV::PseudoFSH:
2674  emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
2675  return false;
2676  case RISCV::PseudoFSW:
2677  emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
2678  return false;
2679  case RISCV::PseudoFSD:
2680  emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
2681  return false;
2682  case RISCV::PseudoAddTPRel:
2683  if (checkPseudoAddTPRel(Inst, Operands))
2684  return true;
2685  break;
2686  case RISCV::PseudoSEXT_B:
2687  emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
2688  return false;
2689  case RISCV::PseudoSEXT_H:
2690  emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
2691  return false;
2692  case RISCV::PseudoZEXT_H:
2693  emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
2694  return false;
2695  case RISCV::PseudoZEXT_W:
2696  emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
2697  return false;
2698  case RISCV::PseudoVMSGEU_VX:
2699  case RISCV::PseudoVMSGEU_VX_M:
2700  case RISCV::PseudoVMSGEU_VX_M_T:
2701  emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
2702  return false;
2703  case RISCV::PseudoVMSGE_VX:
2704  case RISCV::PseudoVMSGE_VX_M:
2705  case RISCV::PseudoVMSGE_VX_M_T:
2706  emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
2707  return false;
2708  case RISCV::PseudoVMSGE_VI:
2709  case RISCV::PseudoVMSLT_VI: {
2710  // These instructions are signed and so is immediate so we can subtract one
2711  // and change the opcode.
2712  int64_t Imm = Inst.getOperand(2).getImm();
2713  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
2714  : RISCV::VMSLE_VI;
2715  emitToStreamer(Out, MCInstBuilder(Opc)
2716  .addOperand(Inst.getOperand(0))
2717  .addOperand(Inst.getOperand(1))
2718  .addImm(Imm - 1)
2719  .addOperand(Inst.getOperand(3)));
2720  return false;
2721  }
2722  case RISCV::PseudoVMSGEU_VI:
2723  case RISCV::PseudoVMSLTU_VI: {
2724  int64_t Imm = Inst.getOperand(2).getImm();
2725  // Unsigned comparisons are tricky because the immediate is signed. If the
2726  // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
2727  // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
2728  // vmsne v0, v1, v1 which is always false.
2729  if (Imm == 0) {
2730  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2731  ? RISCV::VMSEQ_VV
2732  : RISCV::VMSNE_VV;
2733  emitToStreamer(Out, MCInstBuilder(Opc)
2734  .addOperand(Inst.getOperand(0))
2735  .addOperand(Inst.getOperand(1))
2736  .addOperand(Inst.getOperand(1))
2737  .addOperand(Inst.getOperand(3)));
2738  } else {
2739  // Other immediate values can subtract one like signed.
2740  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2741  ? RISCV::VMSGTU_VI
2742  : RISCV::VMSLEU_VI;
2743  emitToStreamer(Out, MCInstBuilder(Opc)
2744  .addOperand(Inst.getOperand(0))
2745  .addOperand(Inst.getOperand(1))
2746  .addImm(Imm - 1)
2747  .addOperand(Inst.getOperand(3)));
2748  }
2749 
2750  return false;
2751  }
2752  }
2753 
2754  emitToStreamer(Out, Inst);
2755  return false;
2756 }
2757 
2758 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
2759  RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
2760  RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
2761 }
llvm::MCTargetStreamer::getStreamer
MCStreamer & getStreamer()
Definition: MCStreamer.h:99
i
i
Definition: README.txt:29
use
Move duplicate certain instructions close to their use
Definition: Localizer.cpp:31
llvm::MCAsmParser
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:124
llvm::MCContext::getObjectFileInfo
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:427
is
should just be implemented with a CLZ instruction Since there are other e that share this it would be best to implement this in a target independent as zero is the default value for the binary encoder e add r0 add r5 Register operands should be distinct That is
Definition: README.txt:725
as
compiles conv shl5 shl ret i32 or10 it would be better as
Definition: README.txt:615
MathExtras.h
constant
we should consider alternate ways to model stack dependencies Lots of things could be done in WebAssemblyTargetTransformInfo cpp there are numerous optimization related hooks that can be overridden in WebAssemblyTargetLowering Instead of the OptimizeReturned which should consider preserving the returned attribute through to MachineInstrs and extending the MemIntrinsicResults pass to do this optimization on calls too That would also let the WebAssemblyPeephole pass clean up dead defs for such as it does for stores Consider implementing and or getMachineCombinerPatterns Find a clean way to fix the problem which leads to the Shrink Wrapping pass being run after the WebAssembly PEI pass When setting multiple variables to the same constant
Definition: README.txt:91
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:22
type
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:148
zero
We currently generate a but we really shouldn eax ecx xorl edx divl ecx eax divl ecx movl eax ret A similar code sequence works for division We currently compile i32 v2 eax eax jo LBB1_2 atomic and others It is also currently not done for read modify write instructions It is also current not done if the OF or CF flags are needed The shift operators have the complication that when the shift count is zero
Definition: README.txt:1277
llvm::MCParsedAsmOperand
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Definition: MCParsedAsmOperand.h:25
llvm::RISCVMCExpr::VK_RISCV_TLS_GD_HI
@ VK_RISCV_TLS_GD_HI
Definition: RISCVMCExpr.h:36
llvm::RISCVMCExpr::VK_RISCV_TPREL_ADD
@ VK_RISCV_TPREL_ADD
Definition: RISCVMCExpr.h:34
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1175
Statistic.h
MCParsedAsmOperand.h
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
push
static void push(SmallVectorImpl< uint64_t > &R, StringRef Str)
Definition: BitstreamRemarkSerializer.cpp:23
MCInstBuilder.h
MCAssembler.h
to
Should compile to
Definition: README.txt:449
MCObjectFileInfo.h
Shift
bool Shift
Definition: README.txt:468
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:236
RISCVMCExpr.h
llvm::RISCVMCExpr::VK_RISCV_TPREL_LO
@ VK_RISCV_TPREL_LO
Definition: RISCVMCExpr.h:32
FPR
static const MCPhysReg FPR[]
FPR - The set of FP registers that should be allocated for arguments on Darwin and AIX.
Definition: PPCISelLowering.cpp:3840
llvm::FeatureBitset
Container class for subtarget features.
Definition: SubtargetFeature.h:41
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:893
RISCVAttributes.h
llvm::RISCVMCExpr::VK_RISCV_HI
@ VK_RISCV_HI
Definition: RISCVMCExpr.h:28
STLExtras.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:642
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::RISCVMCExpr::VK_RISCV_TPREL_HI
@ VK_RISCV_TPREL_HI
Definition: RISCVMCExpr.h:33
llvm::RISCVFPRndMode::stringToRoundingMode
static RoundingMode stringToRoundingMode(StringRef Str)
Definition: RISCVBaseInfo.h:244
RISCVMatInt.h
and
We currently generate a but we really shouldn eax ecx xorl edx divl ecx eax divl ecx movl eax ret A similar code sequence works for division We currently compile i32 v2 eax eax jo LBB1_2 and
Definition: README.txt:1271
MCTargetAsmParser.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::AsmToken
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
RISCVInstPrinter.h
a
=0.0 ? 0.0 :(a > 0.0 ? 1.0 :-1.0) a
Definition: README.txt:489
llvm::RISCVMCExpr::VK_RISCV_TLS_GOT_HI
@ VK_RISCV_TLS_GOT_HI
Definition: RISCVMCExpr.h:35
llvm::RISCVMCExpr::VariantKind
VariantKind
Definition: RISCVMCExpr.h:25
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:199
r4
Common register allocation spilling r4
Definition: README.txt:5
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::PatternMatch::match
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:49
SmallString.h
llvm::RISCVMCExpr::VK_RISCV_LO
@ VK_RISCV_LO
Definition: RISCVMCExpr.h:27
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
MCContext.h
llvm::MCObjectFileInfo::isPositionIndependent
bool isPositionIndependent() const
Definition: MCObjectFileInfo.h:424
t
bitcast float %x to i32 %s=and i32 %t, 2147483647 %d=bitcast i32 %s to float ret float %d } declare float @fabsf(float %n) define float @bar(float %x) nounwind { %d=call float @fabsf(float %x) ret float %d } This IR(from PR6194):target datalayout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple="x86_64-apple-darwin10.0.0" %0=type { double, double } %struct.float3=type { float, float, float } define void @test(%0, %struct.float3 *nocapture %res) nounwind noinline ssp { entry:%tmp18=extractvalue %0 %0, 0 t
Definition: README-SSE.txt:788
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
MCInst.h
group
bb420 i The CBE manages to mtctr r0 r11 stbx r9 addi bdz later b loop This could be much the loop would be a single dispatch group
Definition: README.txt:61
llvm::isUIntN
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:455
MCSubtargetInfo.h
llvm::MCSubtargetInfo::getFeatureBits
const FeatureBitset & getFeatureBits() const
Definition: MCSubtargetInfo.h:111
llvm::MCAsmParser::getContext
virtual MCContext & getContext()=0
in
The object format emitted by the WebAssembly backed is documented in
Definition: README.txt:11
be
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can be
Definition: README.txt:14
RISCVMCTargetDesc.h
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::MCAsmParser::addAliasForDirective
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
llvm::MCTargetStreamer
Target specific streamer interface.
Definition: MCStreamer.h:91
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
input
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 input
Definition: README.txt:10
llvm::SubtargetFeatureKV
Used to provide key value pairs for feature and CPU bit flags.
Definition: MCSubtargetInfo.h:34
Register
Promote Memory to Register
Definition: Mem2Reg.cpp:110
c
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int c
Definition: README.txt:418
only
dot regions only
Definition: RegionPrinter.cpp:205
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
too
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 the input will be treated as an leaving the upper bits uninitialised For i64 store i32 i32 *dst ret void from CodeGen SystemZ asm ll will use LHI rather than LGHI to load This seems to be a general target independent problem The tuning of the choice between LOAD XC and CLC for constant length block operations We could extend them to variable length operations too
Definition: README.txt:40
jump
The object format emitted by the WebAssembly backed is documented see the home and packaging for producing WebAssembly applications that can run in browsers and other environments wasi sdk provides a more minimal C C SDK based on llvm and a libc based on for producing WebAssemmbly applictions that use the WASI ABI Rust provides WebAssembly support integrated into Cargo There are two main which provides a relatively minimal environment that has an emphasis on being native wasm32 unknown which uses Emscripten internally and provides standard C C filesystem GL and SDL bindings For more and br_table instructions can support having a value on the value stack across the jump(sometimes). We should(a) model this
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:78
llvm::MCSubtargetInfo::ToggleFeature
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
Definition: MCSubtargetInfo.cpp:240
llvm::RISCVMCExpr::VK_RISCV_None
@ VK_RISCV_None
Definition: RISCVMCExpr.h:26
bad
We currently generate an sqrtsd and divsd instructions This is bad
Definition: README-SSE.txt:820
RISCVAsmBackend.h
RISCVTargetStreamer.h
MCAsmLexer.h
llvm::isInt< 32 >
constexpr bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:373
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:113
llvm::RISCVMCExpr::VK_RISCV_PCREL_HI
@ VK_RISCV_PCREL_HI
Definition: RISCVMCExpr.h:30
uint64_t
following
This is equivalent to the following
Definition: README.txt:671
s
multiplies can be turned into SHL s
Definition: README.txt:370
RISCVISAInfo.h
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
Domain::Unknown
@ Unknown
MCRegisterInfo.h
llvm::RISCVMCExpr::VK_RISCV_PCREL_LO
@ VK_RISCV_PCREL_LO
Definition: RISCVMCExpr.h:29
llvm::isUInt< 32 >
constexpr bool isUInt< 32 >(uint64_t x)
Definition: MathExtras.h:411
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::RISCVMCExpr::VK_RISCV_GOT_HI
@ VK_RISCV_GOT_HI
Definition: RISCVMCExpr.h:31
llvm::WinEH::EncodingType::CE
@ CE
Windows NT (Windows on ARM)
llvm::RISCVFPRndMode::Invalid
@ Invalid
Definition: RISCVBaseInfo.h:222
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:347
llvm::MCTargetOptions
Definition: MCTargetOptions.h:36
isReg
static bool isReg(const MCInst &MI, unsigned OpNo)
Definition: MipsInstPrinter.cpp:31
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
instruction
Since we know that Vector is byte aligned and we know the element offset of we should change the load into a lve *x instruction
Definition: README_ALTIVEC.txt:37
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
v2
llvm lib Support Unix the directory structure underneath this directory could look like only those directories actually needing to be created should be created further subdirectories could be created to reflect versions of the various standards For under SUS there could be v2
Definition: README.txt:15
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::lltok::comma
@ comma
Definition: LLToken.h:26
not
Should compile r2 movcc movcs str strb mov lr r1 movcs movcc mov lr not
Definition: README.txt:465
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::OperandMatchResultTy
OperandMatchResultTy
Definition: MCTargetAsmParser.h:121
mode
*Add support for compiling functions in both ARM and Thumb mode
Definition: README-Thumb.txt:5
name
static const char * name
Definition: SVEIntrinsicOpts.cpp:74
j
return j(j<< 16)
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::RISCVVType::printVType
void printVType(unsigned VType, raw_ostream &OS)
Definition: RISCVBaseInfo.cpp:159
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
bit
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional ldr LCPI1_0 ldr ldr tst movne lsr ldr LCPI1_1 and r0 bx lr it saves an instruction and a register It might be profitable to cse MOVi16 if there are lots of bit immediates with the same bottom half Robert Muth started working on an alternate jump table implementation that does not put the tables in line in the text This is more like the llvm default jump table implementation This might be useful sometime Several revisions of patches are on the mailing beginning while CMP sets them like a subtract Therefore to be able to use CMN for comparisons other than the Z bit
Definition: README.txt:584
or
compiles or
Definition: README.txt:606
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:325
Casting.h
llvm::isShiftedInt
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition: MathExtras.h:379
llvm::MCTargetAsmParser
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Definition: MCTargetAsmParser.h:309
parseImmediate
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Definition: WebAssemblyDisassembler.cpp:109
MCValue.h
RISCVBaseInfo.h
llvm::AMDGPU::Hwreg::Width
Width
Definition: SIDefines.h:416
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
Invalid
@ Invalid
Definition: AArch64ISelLowering.cpp:8520
llvm::RISCVMCExpr::VK_RISCV_CALL
@ VK_RISCV_CALL
Definition: RISCVMCExpr.h:37
SmallVector.h
llvm::MCStreamer::getTargetStreamer
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:287
SmallBitVector.h
N
#define N
MCStreamer.h
llvm::isMem
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:123
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
RegName
#define RegName(no)
RISCVTargetInfo.h
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
llvm::RISCVTargetStreamer
Definition: RISCVTargetStreamer.h:19
f2
cond_true lis lo16() lo16() lo16() f1 fsel f2
Definition: README.txt:105
llvm::MCSymbolRefExpr::VK_None
@ VK_None
Definition: MCExpr.h:195
llvm::RISCVInstPrinter::getRegisterName
static const char * getRegisterName(unsigned RegNo)
Definition: RISCVInstPrinter.cpp:197
llvm::RISCVMCExpr::VK_RISCV_CALL_PLT
@ VK_RISCV_CALL_PLT
Definition: RISCVMCExpr.h:38
llvm::RISCVFeatureKV
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
Definition: RISCVBaseInfo.cpp:23
TargetRegistry.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
letters
Should combine to x<=9" (the sub has nsw). Currently notoptimized with "clang -emit-llvm-bc|opt -O3".int g(int x) { return (x + 10) < 0; }Should combine to "x< -10" (the add has nsw). Currently notoptimized with "clang -emit-llvm-bc|opt -O3".int f(int i, int j) { return i < j + 1; }int g(int i, int j) { return j > i - 1; }Should combine to "i<=j" (the add/sub has nsw). Currently notoptimized with "clang -emit-llvm-bc|opt -O3".unsigned f(unsigned x) { return ((x & 7) + 1) & 15; }The & 15 part should be optimized away, it doesn't change the result. Currentlynot optimized with "clang -emit-llvm-bc|opt -O3".This was noticed in the entryblock for grokdeclarator in 403.gcc: %tmp = icmp eq i32 %decl_context, 4 %decl_context_addr.0 = select i1 %tmp, i32 3, i32 %decl_context %tmp1 = icmp eq i32 %decl_context_addr.0, 1 %decl_context_addr.1 = select i1 %tmp1, i32 0, i32 %decl_context_addr.0tmp1 should be simplified to something like: (!tmp || decl_context == 1)This allows recursive simplifications, tmp1 is used all over the place inthe function, e.g. by: %tmp23 = icmp eq i32 %decl_context_addr.1, 0 ; <i1> [#uses=1] %tmp24 = xor i1 %tmp1, true ; <i1> [#uses=1] %or.cond8 = and i1 %tmp23, %tmp24 ; <i1> [#uses=1]later.[STORE SINKING]Store sinking: This code:void f (int n, int *cond, int *res) { int i; *res = 0; for (i = 0; i < n; i++) if (*cond) *res ^= 234; }On this function GVN hoists the fully redundant value of *res, but nothingmoves the store out. This gives us this code:bb: ; preds = %bb2, %entry %.rle = phi i32 [ 0, %entry ], [ %.rle6, %bb2 ] %i.05 = phi i32 [ 0, %entry ], [ %indvar.next, %bb2 ] %1 = load i32* %cond, align 4 %2 = icmp eq i32 %1, 0 br i1 %2, label %bb2, label %bb1bb1: ; preds = %bb %3 = xor i32 %.rle, 234 store i32 %3, i32* %res, align 4 br label %bb2bb2: ; preds = %bb, %bb1 %.rle6 = phi i32 [ %3, %bb1 ], [ %.rle, %bb ] %indvar.next = add i32 %i.05, 1 %exitcond = icmp eq i32 %indvar.next, %n br i1 %exitcond, label %return, label %bbDSE should sink partially dead stores to get the store out of the loop.Here's another partial dead case:http:Scalar PRE hoists the mul in the common block up to the else:int test (int a, int b, int c, int g) { int d, e; if (a) d = b * c; else d = b - c; e = b * c + g; return d + e;}It would be better to do the mul once to reduce codesize above the if.This is GCC PR38204.This simple function from 179.art:int winner, numf2s;struct { double y; int reset; } *Y;void find_match() { int i; winner = 0; for (i=0;i<numf2s;i++) if (Y[i].y > Y[winner].y) winner =i;}Compiles into (with clang TBAA):for.body: ; preds = %for.inc, %bb.nph %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.inc ] %i.01718 = phi i32 [ 0, %bb.nph ], [ %i.01719, %for.inc ] %tmp4 = getelementptr inbounds %struct.anon* %tmp3, i64 %indvar, i32 0 %tmp5 = load double* %tmp4, align 8, !tbaa !4 %idxprom7 = sext i32 %i.01718 to i64 %tmp10 = getelementptr inbounds %struct.anon* %tmp3, i64 %idxprom7, i32 0 %tmp11 = load double* %tmp10, align 8, !tbaa !4 %cmp12 = fcmp ogt double %tmp5, %tmp11 br i1 %cmp12, label %if.then, label %for.incif.then: ; preds = %for.body %i.017 = trunc i64 %indvar to i32 br label %for.incfor.inc: ; preds = %for.body, %if.then %i.01719 = phi i32 [ %i.01718, %for.body ], [ %i.017, %if.then ] %indvar.next = add i64 %indvar, 1 %exitcond = icmp eq i64 %indvar.next, %tmp22 br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.bodyIt is good that we hoisted the reloads of numf2's, and Y out of the loop andsunk the store to winner out.However, this is awful on several levels: the conditional truncate in the loop(-indvars at fault? why can't we completely promote the IV to i64?).Beyond that, we have a partially redundant load in the loop: if "winner" (aka %i.01718) isn't updated, we reload Y[winner].y the next time through the loop.Similarly, the addressing that feeds it (including the sext) is redundant. Inthe end we get this generated assembly:LBB0_2: ## %for.body ## =>This Inner Loop Header: Depth=1 movsd (%rdi), %xmm0 movslq %edx, %r8 shlq $4, %r8 ucomisd (%rcx,%r8), %xmm0 jbe LBB0_4 movl %esi, %edxLBB0_4: ## %for.inc addq $16, %rdi incq %rsi cmpq %rsi, %rax jne LBB0_2All things considered this isn't too bad, but we shouldn't need the movslq orthe shlq instruction, or the load folded into ucomisd every time through theloop.On an x86-specific topic, if the loop can't be restructure, the movl should be acmov.[STORE SINKING]GCC PR37810 is an interesting case where we should sink load/store reloadinto the if block and outside the loop, so we don't reload/store it on thenon-call path.for () { *P += 1; if () call(); else ...->tmp = *Pfor () { tmp += 1; if () { *P = tmp; call(); tmp = *P; } else ...}*P = tmp;We now hoist the reload after the call (Transforms/GVN/lpre-call-wrap.ll), butwe don't sink the store. We need partially dead store sinking.[LOAD PRE CRIT EDGE SPLITTING]GCC PR37166: Sinking of loads prevents SROA'ing the "g" struct on the stackleading to excess stack traffic. This could be handled by GVN with some crazysymbolic phi translation. The code we get looks like (g is on the stack):bb2: ; preds = %bb1.. %9 = getelementptr %struct.f* %g, i32 0, i32 0 store i32 %8, i32* %9, align bel %bb3bb3: ; preds = %bb1, %bb2, %bb %c_addr.0 = phi %struct.f* [ %g, %bb2 ], [ %c, %bb ], [ %c, %bb1 ] %b_addr.0 = phi %struct.f* [ %b, %bb2 ], [ %g, %bb ], [ %b, %bb1 ] %10 = getelementptr %struct.f* %c_addr.0, i32 0, i32 0 %11 = load i32* %10, align 4%11 is partially redundant, an in BB2 it should have the value %8.GCC PR33344 and PR35287 are similar cases.[LOAD PRE]There are many load PRE testcases in testsuite/gcc.dg/tree-ssa/loadpre* in theGCC testsuite, ones we don't get yet are (checked through loadpre25):[CRIT EDGE BREAKING]predcom-4.c[PRE OF READONLY CALL]loadpre5.c[TURN SELECT INTO BRANCH]loadpre14.c loadpre15.c actually a conditional increment: loadpre18.c loadpre19.c[LOAD PRE / STORE SINKING / SPEC HACK]This is a chunk of code from 456.hmmer:int f(int M, int *mc, int *mpp, int *tpmm, int *ip, int *tpim, int *dpp, int *tpdm, int xmb, int *bp, int *ms) { int k, sc; for (k = 1; k <= M; k++) { mc[k] = mpp[k-1] + tpmm[k-1]; if ((sc = ip[k-1] + tpim[k-1]) > mc[k]) mc[k] = sc; if ((sc = dpp[k-1] + tpdm[k-1]) > mc[k]) mc[k] = sc; if ((sc = xmb + bp[k]) > mc[k]) mc[k] = sc; mc[k] += ms[k]; }}It is very profitable for this benchmark to turn the conditional stores to mc[k]into a conditional move (select instr in IR) and allow the final store to do thestore. See GCC PR27313 for more details. Note that this is valid to xform evenwith the new C++ memory model, since mc[k] is previously loaded and laterstored.[SCALAR PRE]There are many PRE testcases in testsuite/gcc.dg/tree-ssa/ssa-pre-*.c in theGCC testsuite.There are some interesting cases in testsuite/gcc.dg/tree-ssa/pred-comm* in theGCC testsuite. For example, we get the first example in predcom-1.c, but miss the second one:unsigned fib[1000];unsigned avg[1000];__attribute__ ((noinline))void count_averages(int n) { int i; for (i = 1; i < n; i++) avg[i] = (((unsigned long) fib[i - 1] + fib[i] + fib[i + 1]) / 3) & 0xffff;}which compiles into two loads instead of one in the loop.predcom-2.c is the same as predcom-1.cpredcom-3.c is very similar but needs loads feeding each other instead ofstore->load.[ALIAS ANALYSIS]Type based alias analysis:http:We should do better analysis of posix_memalign. At the least it shouldno-capture its pointer argument, at best, we should know that the out-valueresult doesn't point to anything (like malloc). One example of this is inSingleSource/Benchmarks/Misc/dt.cInteresting missed case because of control flow flattening (should be 2 loads):http:With: llvm-gcc t2.c -S -o - -O0 -emit-llvm | llvm-as | opt -mem2reg -gvn -instcombine | llvm-diswe miss it because we need 1) CRIT EDGE 2) MULTIPLE DIFFERENTVALS PRODUCED BY ONE BLOCK OVER DIFFERENT PATHShttp:We could eliminate the branch condition here, loading from null is undefined:struct S { int w, x, y, z; };struct T { int r; struct S s; };void bar (struct S, int);void foo (int a, struct T b){ struct S *c = 0; if (a) c = &b.s; bar (*c, a);}simplifylibcalls should do several optimizations for strspn/strcspn:strcspn(x, "a") -> inlined loop for up to letters(similarly for strspn)
Definition: README.txt:1233
llvm::MCObjectFileInfo
Definition: MCObjectFileInfo.h:26
of
Add support for conditional and other related patterns Instead of
Definition: README.txt:134
getReg
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:572
llvm::MCRegister
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:24