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/Support/Casting.h"
39 
40 #include <limits>
41 
42 using namespace llvm;
43 
44 #define DEBUG_TYPE "riscv-asm-parser"
45 
46 // Include the auto-generated portion of the compress emitter.
47 #define GEN_COMPRESS_INSTR
48 #include "RISCVGenCompressInstEmitter.inc"
49 
50 STATISTIC(RISCVNumInstrsCompressed,
51  "Number of RISC-V Compressed instructions emitted");
52 
53 namespace {
54 struct RISCVOperand;
55 
56 struct ParserOptionsSet {
57  bool IsPicEnabled;
58 };
59 
60 class RISCVAsmParser : public MCTargetAsmParser {
61  SmallVector<FeatureBitset, 4> FeatureBitStack;
62 
63  SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
64  ParserOptionsSet ParserOptions;
65 
66  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
67  bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
68  bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); }
69 
70  RISCVTargetStreamer &getTargetStreamer() {
71  MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
72  return static_cast<RISCVTargetStreamer &>(TS);
73  }
74 
75  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
76  unsigned Kind) override;
77 
78  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
79  int64_t Lower, int64_t Upper, Twine Msg);
80 
81  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
83  uint64_t &ErrorInfo,
84  bool MatchingInlineAsm) override;
85 
86  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
87  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
88  SMLoc &EndLoc) override;
89 
90  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
91  SMLoc NameLoc, OperandVector &Operands) override;
92 
93  bool ParseDirective(AsmToken DirectiveID) override;
94 
95  // Helper to actually emit an instruction to the MCStreamer. Also, when
96  // possible, compression of the instruction is performed.
97  void emitToStreamer(MCStreamer &S, const MCInst &Inst);
98 
99  // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
100  // synthesize the desired immedate value into the destination register.
101  void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
102 
103  // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
104  // helpers such as emitLoadLocalAddress and emitLoadAddress.
105  void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
107  unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
108 
109  // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
110  void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
111 
112  // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
113  void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
114 
115  // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
116  // addressing.
117  void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
118 
119  // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
120  // addressing.
121  void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
122 
123  // Helper to emit pseudo load/store instruction with a symbol.
124  void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
125  MCStreamer &Out, bool HasTmpReg);
126 
127  // Helper to emit pseudo sign/zero extend instruction.
128  void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
129  SMLoc IDLoc, MCStreamer &Out);
130 
131  // Helper to emit pseudo vmsge{u}.vx instruction.
132  void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
133 
134  // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
135  // Enforcing this using a restricted register class for the second input
136  // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
137  // 'add' is an overloaded mnemonic.
138  bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
139 
140  // Check instruction constraints.
141  bool validateInstruction(MCInst &Inst, OperandVector &Operands);
142 
143  /// Helper for processing MC instructions that have been successfully matched
144  /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
145  /// like the expansion of pseudo instructions (e.g., "li"), can be performed
146  /// in this method.
147  bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
148  MCStreamer &Out);
149 
150 // Auto-generated instruction matching functions
151 #define GET_ASSEMBLER_HEADER
152 #include "RISCVGenAsmMatcher.inc"
153 
154  OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
157  bool AllowParens = false);
158  OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
159  OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands);
160  OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
161  OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
162  OperandMatchResultTy parseCallSymbol(OperandVector &Operands);
163  OperandMatchResultTy parsePseudoJumpSymbol(OperandVector &Operands);
167 
168  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
169 
170  bool parseDirectiveOption();
171  bool parseDirectiveAttribute();
172 
173  void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
174  if (!(getSTI().getFeatureBits()[Feature])) {
175  MCSubtargetInfo &STI = copySTI();
176  setAvailableFeatures(
177  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
178  }
179  }
180 
181  bool getFeatureBits(uint64_t Feature) {
182  return getSTI().getFeatureBits()[Feature];
183  }
184 
185  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
186  if (getSTI().getFeatureBits()[Feature]) {
187  MCSubtargetInfo &STI = copySTI();
188  setAvailableFeatures(
189  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
190  }
191  }
192 
193  void pushFeatureBits() {
194  assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
195  "These two stacks must be kept synchronized");
196  FeatureBitStack.push_back(getSTI().getFeatureBits());
197  ParserOptionsStack.push_back(ParserOptions);
198  }
199 
200  bool popFeatureBits() {
201  assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
202  "These two stacks must be kept synchronized");
203  if (FeatureBitStack.empty())
204  return true;
205 
206  FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
207  copySTI().setFeatureBits(FeatureBits);
208  setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
209 
210  ParserOptions = ParserOptionsStack.pop_back_val();
211 
212  return false;
213  }
214 
215  std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
216 
217 public:
218  enum RISCVMatchResultTy {
219  Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
220 #define GET_OPERAND_DIAGNOSTIC_TYPES
221 #include "RISCVGenAsmMatcher.inc"
222 #undef GET_OPERAND_DIAGNOSTIC_TYPES
223  };
224 
225  static bool classifySymbolRef(const MCExpr *Expr,
227 
228  RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
229  const MCInstrInfo &MII, const MCTargetOptions &Options)
230  : MCTargetAsmParser(Options, STI, MII) {
231  Parser.addAliasForDirective(".half", ".2byte");
232  Parser.addAliasForDirective(".hword", ".2byte");
233  Parser.addAliasForDirective(".word", ".4byte");
234  Parser.addAliasForDirective(".dword", ".8byte");
235  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
236 
237  auto ABIName = StringRef(Options.ABIName);
238  if (ABIName.endswith("f") &&
239  !getSTI().getFeatureBits()[RISCV::FeatureStdExtF]) {
240  errs() << "Hard-float 'f' ABI can't be used for a target that "
241  "doesn't support the F instruction set extension (ignoring "
242  "target-abi)\n";
243  } else if (ABIName.endswith("d") &&
244  !getSTI().getFeatureBits()[RISCV::FeatureStdExtD]) {
245  errs() << "Hard-float 'd' ABI can't be used for a target that "
246  "doesn't support the D instruction set extension (ignoring "
247  "target-abi)\n";
248  }
249 
250  const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
251  ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
252  }
253 };
254 
255 /// RISCVOperand - Instances of this class represent a parsed machine
256 /// instruction
257 struct RISCVOperand : public MCParsedAsmOperand {
258 
259  enum class KindTy {
260  Token,
261  Register,
262  Immediate,
263  SystemRegister,
264  VType,
265  } Kind;
266 
267  bool IsRV64;
268 
269  struct RegOp {
270  MCRegister RegNum;
271  };
272 
273  struct ImmOp {
274  const MCExpr *Val;
275  };
276 
277  struct SysRegOp {
278  const char *Data;
279  unsigned Length;
280  unsigned Encoding;
281  // FIXME: Add the Encoding parsed fields as needed for checks,
282  // e.g.: read/write or user/supervisor/machine privileges.
283  };
284 
285  struct VTypeOp {
286  unsigned Val;
287  };
288 
289  SMLoc StartLoc, EndLoc;
290  union {
291  StringRef Tok;
292  RegOp Reg;
293  ImmOp Imm;
294  struct SysRegOp SysReg;
295  struct VTypeOp VType;
296  };
297 
298  RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
299 
300 public:
301  RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
302  Kind = o.Kind;
303  IsRV64 = o.IsRV64;
304  StartLoc = o.StartLoc;
305  EndLoc = o.EndLoc;
306  switch (Kind) {
307  case KindTy::Register:
308  Reg = o.Reg;
309  break;
310  case KindTy::Immediate:
311  Imm = o.Imm;
312  break;
313  case KindTy::Token:
314  Tok = o.Tok;
315  break;
316  case KindTy::SystemRegister:
317  SysReg = o.SysReg;
318  break;
319  case KindTy::VType:
320  VType = o.VType;
321  break;
322  }
323  }
324 
325  bool isToken() const override { return Kind == KindTy::Token; }
326  bool isReg() const override { return Kind == KindTy::Register; }
327  bool isV0Reg() const {
328  return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
329  }
330  bool isImm() const override { return Kind == KindTy::Immediate; }
331  bool isMem() const override { return false; }
332  bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
333  bool isVType() const { return Kind == KindTy::VType; }
334 
335  bool isGPR() const {
336  return Kind == KindTy::Register &&
337  RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
338  }
339 
340  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
342  if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
343  VK = RE->getKind();
344  return RE->evaluateAsConstant(Imm);
345  }
346 
347  if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
349  Imm = CE->getValue();
350  return true;
351  }
352 
353  return false;
354  }
355 
356  // True if operand is a symbol with no modifiers, or a constant with no
357  // modifiers and isShiftedInt<N-1, 1>(Op).
358  template <int N> bool isBareSimmNLsb0() const {
359  int64_t Imm;
361  if (!isImm())
362  return false;
363  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
364  bool IsValid;
365  if (!IsConstantImm)
366  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
367  else
368  IsValid = isShiftedInt<N - 1, 1>(Imm);
369  return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
370  }
371 
372  // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
373 
374  bool isBareSymbol() const {
375  int64_t Imm;
377  // Must be of 'immediate' type but not a constant.
378  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
379  return false;
380  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
382  }
383 
384  bool isCallSymbol() const {
385  int64_t Imm;
387  // Must be of 'immediate' type but not a constant.
388  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
389  return false;
390  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
393  }
394 
395  bool isPseudoJumpSymbol() const {
396  int64_t Imm;
398  // Must be of 'immediate' type but not a constant.
399  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
400  return false;
401  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
403  }
404 
405  bool isTPRelAddSymbol() const {
406  int64_t Imm;
408  // Must be of 'immediate' type but not a constant.
409  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
410  return false;
411  return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
413  }
414 
415  bool isCSRSystemRegister() const { return isSystemRegister(); }
416 
417  bool isVTypeI() const { return isVType(); }
418 
419  /// Return true if the operand is a valid for the fence instruction e.g.
420  /// ('iorw').
421  bool isFenceArg() const {
422  if (!isImm())
423  return false;
424  const MCExpr *Val = getImm();
425  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
426  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
427  return false;
428 
429  StringRef Str = SVal->getSymbol().getName();
430  // Letters must be unique, taken from 'iorw', and in ascending order. This
431  // holds as long as each individual character is one of 'iorw' and is
432  // greater than the previous character.
433  char Prev = '\0';
434  for (char c : Str) {
435  if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
436  return false;
437  if (c <= Prev)
438  return false;
439  Prev = c;
440  }
441  return true;
442  }
443 
444  /// Return true if the operand is a valid floating point rounding mode.
445  bool isFRMArg() const {
446  if (!isImm())
447  return false;
448  const MCExpr *Val = getImm();
449  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
450  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
451  return false;
452 
453  StringRef Str = SVal->getSymbol().getName();
454 
456  }
457 
458  bool isImmXLenLI() const {
459  int64_t Imm;
461  if (!isImm())
462  return false;
463  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
465  return true;
466  // Given only Imm, ensuring that the actually specified constant is either
467  // a signed or unsigned 64-bit number is unfortunately impossible.
468  return IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None &&
469  (isRV64() || (isInt<32>(Imm) || isUInt<32>(Imm)));
470  }
471 
472  bool isUImmLog2XLen() const {
473  int64_t Imm;
475  if (!isImm())
476  return false;
477  if (!evaluateConstantImm(getImm(), Imm, VK) ||
479  return false;
480  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
481  }
482 
483  bool isUImmLog2XLenNonZero() const {
484  int64_t Imm;
486  if (!isImm())
487  return false;
488  if (!evaluateConstantImm(getImm(), Imm, VK) ||
490  return false;
491  if (Imm == 0)
492  return false;
493  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
494  }
495 
496  bool isUImmLog2XLenHalf() const {
497  int64_t Imm;
499  if (!isImm())
500  return false;
501  if (!evaluateConstantImm(getImm(), Imm, VK) ||
503  return false;
504  return (isRV64() && isUInt<5>(Imm)) || isUInt<4>(Imm);
505  }
506 
507  bool isUImm5() const {
508  int64_t Imm;
510  if (!isImm())
511  return false;
512  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
513  return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
514  }
515 
516  bool isSImm5() const {
517  if (!isImm())
518  return false;
520  int64_t Imm;
521  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
522  return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
523  }
524 
525  bool isSImm6() const {
526  if (!isImm())
527  return false;
529  int64_t Imm;
530  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
531  return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
532  }
533 
534  bool isSImm6NonZero() const {
535  if (!isImm())
536  return false;
538  int64_t Imm;
539  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
540  return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
542  }
543 
544  bool isCLUIImm() const {
545  if (!isImm())
546  return false;
547  int64_t Imm;
549  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
550  return IsConstantImm && (Imm != 0) &&
551  (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
553  }
554 
555  bool isUImm7Lsb00() const {
556  if (!isImm())
557  return false;
558  int64_t Imm;
560  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
561  return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
563  }
564 
565  bool isUImm8Lsb00() const {
566  if (!isImm())
567  return false;
568  int64_t Imm;
570  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
571  return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
573  }
574 
575  bool isUImm8Lsb000() const {
576  if (!isImm())
577  return false;
578  int64_t Imm;
580  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
581  return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
583  }
584 
585  bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
586 
587  bool isUImm9Lsb000() const {
588  if (!isImm())
589  return false;
590  int64_t Imm;
592  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
593  return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
595  }
596 
597  bool isUImm10Lsb00NonZero() const {
598  if (!isImm())
599  return false;
600  int64_t Imm;
602  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
603  return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
605  }
606 
607  bool isSImm12() const {
609  int64_t Imm;
610  bool IsValid;
611  if (!isImm())
612  return false;
613  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
614  if (!IsConstantImm)
615  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
616  else
617  IsValid = isInt<12>(Imm);
618  return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
619  VK == RISCVMCExpr::VK_RISCV_LO ||
622  }
623 
624  bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
625 
626  bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
627 
628  bool isSImm10Lsb0000NonZero() const {
629  if (!isImm())
630  return false;
631  int64_t Imm;
633  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
634  return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
636  }
637 
638  bool isUImm20LUI() const {
640  int64_t Imm;
641  bool IsValid;
642  if (!isImm())
643  return false;
644  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
645  if (!IsConstantImm) {
646  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
647  return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
649  } else {
650  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
651  VK == RISCVMCExpr::VK_RISCV_HI ||
653  }
654  }
655 
656  bool isUImm20AUIPC() const {
658  int64_t Imm;
659  bool IsValid;
660  if (!isImm())
661  return false;
662  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
663  if (!IsConstantImm) {
664  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
665  return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
669  } else {
670  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
675  }
676  }
677 
678  bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
679 
680  bool isImmZero() const {
681  if (!isImm())
682  return false;
683  int64_t Imm;
685  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
686  return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
687  }
688 
689  bool isSImm5Plus1() const {
690  if (!isImm())
691  return false;
693  int64_t Imm;
694  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
695  return IsConstantImm && isInt<5>(Imm - 1) &&
697  }
698 
699  /// getStartLoc - Gets location of the first token of this operand
700  SMLoc getStartLoc() const override { return StartLoc; }
701  /// getEndLoc - Gets location of the last token of this operand
702  SMLoc getEndLoc() const override { return EndLoc; }
703  /// True if this operand is for an RV64 instruction
704  bool isRV64() const { return IsRV64; }
705 
706  unsigned getReg() const override {
707  assert(Kind == KindTy::Register && "Invalid type access!");
708  return Reg.RegNum.id();
709  }
710 
711  StringRef getSysReg() const {
712  assert(Kind == KindTy::SystemRegister && "Invalid type access!");
713  return StringRef(SysReg.Data, SysReg.Length);
714  }
715 
716  const MCExpr *getImm() const {
717  assert(Kind == KindTy::Immediate && "Invalid type access!");
718  return Imm.Val;
719  }
720 
721  StringRef getToken() const {
722  assert(Kind == KindTy::Token && "Invalid type access!");
723  return Tok;
724  }
725 
726  unsigned getVType() const {
727  assert(Kind == KindTy::VType && "Invalid type access!");
728  return VType.Val;
729  }
730 
731  void print(raw_ostream &OS) const override {
732  auto RegName = [](unsigned Reg) {
733  if (Reg)
735  else
736  return "noreg";
737  };
738 
739  switch (Kind) {
740  case KindTy::Immediate:
741  OS << *getImm();
742  break;
743  case KindTy::Register:
744  OS << "<register " << RegName(getReg()) << ">";
745  break;
746  case KindTy::Token:
747  OS << "'" << getToken() << "'";
748  break;
749  case KindTy::SystemRegister:
750  OS << "<sysreg: " << getSysReg() << '>';
751  break;
752  case KindTy::VType:
753  OS << "<vtype: ";
754  RISCVVType::printVType(getVType(), OS);
755  OS << '>';
756  break;
757  }
758  }
759 
760  static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
761  bool IsRV64) {
762  auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
763  Op->Tok = Str;
764  Op->StartLoc = S;
765  Op->EndLoc = S;
766  Op->IsRV64 = IsRV64;
767  return Op;
768  }
769 
770  static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
771  SMLoc E, bool IsRV64) {
772  auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
773  Op->Reg.RegNum = RegNo;
774  Op->StartLoc = S;
775  Op->EndLoc = E;
776  Op->IsRV64 = IsRV64;
777  return Op;
778  }
779 
780  static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
781  SMLoc E, bool IsRV64) {
782  auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
783  Op->Imm.Val = Val;
784  Op->StartLoc = S;
785  Op->EndLoc = E;
786  Op->IsRV64 = IsRV64;
787  return Op;
788  }
789 
790  static std::unique_ptr<RISCVOperand>
791  createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
792  auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
793  Op->SysReg.Data = Str.data();
794  Op->SysReg.Length = Str.size();
795  Op->SysReg.Encoding = Encoding;
796  Op->StartLoc = S;
797  Op->IsRV64 = IsRV64;
798  return Op;
799  }
800 
801  static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S,
802  bool IsRV64) {
803  auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
804  Op->VType.Val = VTypeI;
805  Op->StartLoc = S;
806  Op->IsRV64 = IsRV64;
807  return Op;
808  }
809 
810  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
811  assert(Expr && "Expr shouldn't be null!");
812  int64_t Imm = 0;
813  RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
814  bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
815 
816  if (IsConstant)
817  Inst.addOperand(MCOperand::createImm(Imm));
818  else
819  Inst.addOperand(MCOperand::createExpr(Expr));
820  }
821 
822  // Used by the TableGen Code
823  void addRegOperands(MCInst &Inst, unsigned N) const {
824  assert(N == 1 && "Invalid number of operands!");
825  Inst.addOperand(MCOperand::createReg(getReg()));
826  }
827 
828  void addImmOperands(MCInst &Inst, unsigned N) const {
829  assert(N == 1 && "Invalid number of operands!");
830  addExpr(Inst, getImm());
831  }
832 
833  void addFenceArgOperands(MCInst &Inst, unsigned N) const {
834  assert(N == 1 && "Invalid number of operands!");
835  // isFenceArg has validated the operand, meaning this cast is safe
836  auto SE = cast<MCSymbolRefExpr>(getImm());
837 
838  unsigned Imm = 0;
839  for (char c : SE->getSymbol().getName()) {
840  switch (c) {
841  default:
842  llvm_unreachable("FenceArg must contain only [iorw]");
843  case 'i':
844  Imm |= RISCVFenceField::I;
845  break;
846  case 'o':
847  Imm |= RISCVFenceField::O;
848  break;
849  case 'r':
850  Imm |= RISCVFenceField::R;
851  break;
852  case 'w':
853  Imm |= RISCVFenceField::W;
854  break;
855  }
856  }
857  Inst.addOperand(MCOperand::createImm(Imm));
858  }
859 
860  void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
861  assert(N == 1 && "Invalid number of operands!");
862  Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
863  }
864 
865  void addVTypeIOperands(MCInst &Inst, unsigned N) const {
866  assert(N == 1 && "Invalid number of operands!");
867  Inst.addOperand(MCOperand::createImm(getVType()));
868  }
869 
870  // Returns the rounding mode represented by this RISCVOperand. Should only
871  // be called after checking isFRMArg.
872  RISCVFPRndMode::RoundingMode getRoundingMode() const {
873  // isFRMArg has validated the operand, meaning this cast is safe.
874  auto SE = cast<MCSymbolRefExpr>(getImm());
875  RISCVFPRndMode::RoundingMode FRM =
876  RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
877  assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
878  return FRM;
879  }
880 
881  void addFRMArgOperands(MCInst &Inst, unsigned N) const {
882  assert(N == 1 && "Invalid number of operands!");
883  Inst.addOperand(MCOperand::createImm(getRoundingMode()));
884  }
885 };
886 } // end anonymous namespace.
887 
888 #define GET_REGISTER_MATCHER
889 #define GET_SUBTARGET_FEATURE_NAME
890 #define GET_MATCHER_IMPLEMENTATION
891 #define GET_MNEMONIC_SPELL_CHECKER
892 #include "RISCVGenAsmMatcher.inc"
893 
894 static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
895  assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
896  return Reg - RISCV::F0_D + RISCV::F0_H;
897 }
898 
899 static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
900  assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
901  return Reg - RISCV::F0_D + RISCV::F0_F;
902 }
903 
904 static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
905  unsigned Kind) {
906  unsigned RegClassID;
907  if (Kind == MCK_VRM2)
908  RegClassID = RISCV::VRM2RegClassID;
909  else if (Kind == MCK_VRM4)
910  RegClassID = RISCV::VRM4RegClassID;
911  else if (Kind == MCK_VRM8)
912  RegClassID = RISCV::VRM8RegClassID;
913  else
914  return 0;
915  return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
916  &RISCVMCRegisterClasses[RegClassID]);
917 }
918 
919 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
920  unsigned Kind) {
921  RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
922  if (!Op.isReg())
923  return Match_InvalidOperand;
924 
925  MCRegister Reg = Op.getReg();
926  bool IsRegFPR64 =
927  RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
928  bool IsRegFPR64C =
929  RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
930  bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
931 
932  // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
933  // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
934  if ((IsRegFPR64 && Kind == MCK_FPR32) ||
935  (IsRegFPR64C && Kind == MCK_FPR32C)) {
936  Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
937  return Match_Success;
938  }
939  // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
940  // register from FPR64 to FPR16 if necessary.
941  if (IsRegFPR64 && Kind == MCK_FPR16) {
942  Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
943  return Match_Success;
944  }
945  // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
946  // the register from VR to VRM2/VRM4/VRM8 if necessary.
947  if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
948  Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
949  if (Op.Reg.RegNum == 0)
950  return Match_InvalidOperand;
951  return Match_Success;
952  }
953  return Match_InvalidOperand;
954 }
955 
956 bool RISCVAsmParser::generateImmOutOfRangeError(
957  OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
958  Twine Msg = "immediate must be an integer in the range") {
959  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
960  return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
961 }
962 
963 static std::string RISCVMnemonicSpellCheck(StringRef S,
964  const FeatureBitset &FBS,
965  unsigned VariantID = 0);
966 
967 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
968  OperandVector &Operands,
969  MCStreamer &Out,
970  uint64_t &ErrorInfo,
971  bool MatchingInlineAsm) {
972  MCInst Inst;
973  FeatureBitset MissingFeatures;
974 
975  auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
976  MatchingInlineAsm);
977  switch (Result) {
978  default:
979  break;
980  case Match_Success:
981  if (validateInstruction(Inst, Operands))
982  return true;
983  return processInstruction(Inst, IDLoc, Operands, Out);
984  case Match_MissingFeature: {
985  assert(MissingFeatures.any() && "Unknown missing features!");
986  bool FirstFeature = true;
987  std::string Msg = "instruction requires the following:";
988  for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
989  if (MissingFeatures[i]) {
990  Msg += FirstFeature ? " " : ", ";
991  Msg += getSubtargetFeatureName(i);
992  FirstFeature = false;
993  }
994  }
995  return Error(IDLoc, Msg);
996  }
997  case Match_MnemonicFail: {
998  FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
999  std::string Suggestion =
1000  RISCVMnemonicSpellCheck(((RISCVOperand &)*Operands[0]).getToken(), FBS);
1001  return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1002  }
1003  case Match_InvalidOperand: {
1004  SMLoc ErrorLoc = IDLoc;
1005  if (ErrorInfo != ~0U) {
1006  if (ErrorInfo >= Operands.size())
1007  return Error(ErrorLoc, "too few operands for instruction");
1008 
1009  ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1010  if (ErrorLoc == SMLoc())
1011  ErrorLoc = IDLoc;
1012  }
1013  return Error(ErrorLoc, "invalid operand for instruction");
1014  }
1015  }
1016 
1017  // Handle the case when the error message is of specific type
1018  // other than the generic Match_InvalidOperand, and the
1019  // corresponding operand is missing.
1020  if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1021  SMLoc ErrorLoc = IDLoc;
1022  if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
1023  return Error(ErrorLoc, "too few operands for instruction");
1024  }
1025 
1026  switch (Result) {
1027  default:
1028  break;
1029  case Match_InvalidImmXLenLI:
1030  if (isRV64()) {
1031  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1032  return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1033  }
1034  return generateImmOutOfRangeError(Operands, ErrorInfo,
1035  std::numeric_limits<int32_t>::min(),
1036  std::numeric_limits<uint32_t>::max());
1037  case Match_InvalidImmZero: {
1038  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1039  return Error(ErrorLoc, "immediate must be zero");
1040  }
1041  case Match_InvalidUImmLog2XLen:
1042  if (isRV64())
1043  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1044  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1045  case Match_InvalidUImmLog2XLenNonZero:
1046  if (isRV64())
1047  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1048  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1049  case Match_InvalidUImmLog2XLenHalf:
1050  if (isRV64())
1051  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1052  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1053  case Match_InvalidUImm5:
1054  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1055  case Match_InvalidSImm5:
1056  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1057  (1 << 4) - 1);
1058  case Match_InvalidSImm6:
1059  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1060  (1 << 5) - 1);
1061  case Match_InvalidSImm6NonZero:
1062  return generateImmOutOfRangeError(
1063  Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1064  "immediate must be non-zero in the range");
1065  case Match_InvalidCLUIImm:
1066  return generateImmOutOfRangeError(
1067  Operands, ErrorInfo, 1, (1 << 5) - 1,
1068  "immediate must be in [0xfffe0, 0xfffff] or");
1069  case Match_InvalidUImm7Lsb00:
1070  return generateImmOutOfRangeError(
1071  Operands, ErrorInfo, 0, (1 << 7) - 4,
1072  "immediate must be a multiple of 4 bytes in the range");
1073  case Match_InvalidUImm8Lsb00:
1074  return generateImmOutOfRangeError(
1075  Operands, ErrorInfo, 0, (1 << 8) - 4,
1076  "immediate must be a multiple of 4 bytes in the range");
1077  case Match_InvalidUImm8Lsb000:
1078  return generateImmOutOfRangeError(
1079  Operands, ErrorInfo, 0, (1 << 8) - 8,
1080  "immediate must be a multiple of 8 bytes in the range");
1081  case Match_InvalidSImm9Lsb0:
1082  return generateImmOutOfRangeError(
1083  Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1084  "immediate must be a multiple of 2 bytes in the range");
1085  case Match_InvalidUImm9Lsb000:
1086  return generateImmOutOfRangeError(
1087  Operands, ErrorInfo, 0, (1 << 9) - 8,
1088  "immediate must be a multiple of 8 bytes in the range");
1089  case Match_InvalidUImm10Lsb00NonZero:
1090  return generateImmOutOfRangeError(
1091  Operands, ErrorInfo, 4, (1 << 10) - 4,
1092  "immediate must be a multiple of 4 bytes in the range");
1093  case Match_InvalidSImm10Lsb0000NonZero:
1094  return generateImmOutOfRangeError(
1095  Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1096  "immediate must be a multiple of 16 bytes and non-zero in the range");
1097  case Match_InvalidSImm12:
1098  return generateImmOutOfRangeError(
1099  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1100  "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1101  "integer in the range");
1102  case Match_InvalidSImm12Lsb0:
1103  return generateImmOutOfRangeError(
1104  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1105  "immediate must be a multiple of 2 bytes in the range");
1106  case Match_InvalidSImm13Lsb0:
1107  return generateImmOutOfRangeError(
1108  Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1109  "immediate must be a multiple of 2 bytes in the range");
1110  case Match_InvalidUImm20LUI:
1111  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1112  "operand must be a symbol with "
1113  "%hi/%tprel_hi modifier or an integer in "
1114  "the range");
1115  case Match_InvalidUImm20AUIPC:
1116  return generateImmOutOfRangeError(
1117  Operands, ErrorInfo, 0, (1 << 20) - 1,
1118  "operand must be a symbol with a "
1119  "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1120  "an integer in the range");
1121  case Match_InvalidSImm21Lsb0JAL:
1122  return generateImmOutOfRangeError(
1123  Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1124  "immediate must be a multiple of 2 bytes in the range");
1125  case Match_InvalidCSRSystemRegister: {
1126  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1127  "operand must be a valid system register "
1128  "name or an integer in the range");
1129  }
1130  case Match_InvalidFenceArg: {
1131  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1132  return Error(
1133  ErrorLoc,
1134  "operand must be formed of letters selected in-order from 'iorw'");
1135  }
1136  case Match_InvalidFRMArg: {
1137  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1138  return Error(
1139  ErrorLoc,
1140  "operand must be a valid floating point rounding mode mnemonic");
1141  }
1142  case Match_InvalidBareSymbol: {
1143  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1144  return Error(ErrorLoc, "operand must be a bare symbol name");
1145  }
1146  case Match_InvalidPseudoJumpSymbol: {
1147  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1148  return Error(ErrorLoc, "operand must be a valid jump target");
1149  }
1150  case Match_InvalidCallSymbol: {
1151  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1152  return Error(ErrorLoc, "operand must be a bare symbol name");
1153  }
1154  case Match_InvalidTPRelAddSymbol: {
1155  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1156  return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1157  }
1158  case Match_InvalidVTypeI: {
1159  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1160  return Error(
1161  ErrorLoc,
1162  "operand must be "
1163  "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
1164  }
1165  case Match_InvalidVMaskRegister: {
1166  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1167  return Error(ErrorLoc, "operand must be v0.t");
1168  }
1169  case Match_InvalidSImm5Plus1: {
1170  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1171  (1 << 4),
1172  "immediate must be in the range");
1173  }
1174  }
1175 
1176  llvm_unreachable("Unknown match type detected!");
1177 }
1178 
1179 // Attempts to match Name as a register (either using the default name or
1180 // alternative ABI names), setting RegNo to the matching register. Upon
1181 // failure, returns true and sets RegNo to 0. If IsRV32E then registers
1182 // x16-x31 will be rejected.
1183 static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo,
1184  StringRef Name) {
1185  RegNo = MatchRegisterName(Name);
1186  // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1187  // match always matches the 64-bit variant, and not the 16/32-bit one.
1188  assert(!(RegNo >= RISCV::F0_H && RegNo <= RISCV::F31_H));
1189  assert(!(RegNo >= RISCV::F0_F && RegNo <= RISCV::F31_F));
1190  // The default FPR register class is based on the tablegen enum ordering.
1191  static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1192  static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1193  if (RegNo == RISCV::NoRegister)
1194  RegNo = MatchRegisterAltName(Name);
1195  if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
1196  RegNo = RISCV::NoRegister;
1197  return RegNo == RISCV::NoRegister;
1198 }
1199 
1200 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1201  SMLoc &EndLoc) {
1202  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
1203  return Error(StartLoc, "invalid register name");
1204  return false;
1205 }
1206 
1207 OperandMatchResultTy RISCVAsmParser::tryParseRegister(unsigned &RegNo,
1208  SMLoc &StartLoc,
1209  SMLoc &EndLoc) {
1210  const AsmToken &Tok = getParser().getTok();
1211  StartLoc = Tok.getLoc();
1212  EndLoc = Tok.getEndLoc();
1213  RegNo = 0;
1214  StringRef Name = getLexer().getTok().getIdentifier();
1215 
1216  if (matchRegisterNameHelper(isRV32E(), (MCRegister &)RegNo, Name))
1217  return MatchOperand_NoMatch;
1218 
1219  getParser().Lex(); // Eat identifier token.
1220  return MatchOperand_Success;
1221 }
1222 
1223 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
1224  bool AllowParens) {
1225  SMLoc FirstS = getLoc();
1226  bool HadParens = false;
1227  AsmToken LParen;
1228 
1229  // If this is an LParen and a parenthesised register name is allowed, parse it
1230  // atomically.
1231  if (AllowParens && getLexer().is(AsmToken::LParen)) {
1232  AsmToken Buf[2];
1233  size_t ReadCount = getLexer().peekTokens(Buf);
1234  if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1235  HadParens = true;
1236  LParen = getParser().getTok();
1237  getParser().Lex(); // Eat '('
1238  }
1239  }
1240 
1241  switch (getLexer().getKind()) {
1242  default:
1243  if (HadParens)
1244  getLexer().UnLex(LParen);
1245  return MatchOperand_NoMatch;
1246  case AsmToken::Identifier:
1247  StringRef Name = getLexer().getTok().getIdentifier();
1248  MCRegister RegNo;
1249  matchRegisterNameHelper(isRV32E(), RegNo, Name);
1250 
1251  if (RegNo == RISCV::NoRegister) {
1252  if (HadParens)
1253  getLexer().UnLex(LParen);
1254  return MatchOperand_NoMatch;
1255  }
1256  if (HadParens)
1257  Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
1258  SMLoc S = getLoc();
1259  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1260  getLexer().Lex();
1261  Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
1262  }
1263 
1264  if (HadParens) {
1265  getParser().Lex(); // Eat ')'
1266  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
1267  }
1268 
1269  return MatchOperand_Success;
1270 }
1271 
1272 OperandMatchResultTy
1273 RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1274  SMLoc S = getLoc();
1275  const MCExpr *Res;
1276 
1277  switch (getLexer().getKind()) {
1278  default:
1279  return MatchOperand_NoMatch;
1280  case AsmToken::LParen:
1281  case AsmToken::Minus:
1282  case AsmToken::Plus:
1283  case AsmToken::Exclaim:
1284  case AsmToken::Tilde:
1285  case AsmToken::Integer:
1286  case AsmToken::String: {
1287  if (getParser().parseExpression(Res))
1288  return MatchOperand_ParseFail;
1289 
1290  auto *CE = dyn_cast<MCConstantExpr>(Res);
1291  if (CE) {
1292  int64_t Imm = CE->getValue();
1293  if (isUInt<12>(Imm)) {
1294  auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1295  // Accept an immediate representing a named or un-named Sys Reg
1296  // if the range is valid, regardless of the required features.
1297  Operands.push_back(RISCVOperand::createSysReg(
1298  SysReg ? SysReg->Name : "", S, Imm, isRV64()));
1299  return MatchOperand_Success;
1300  }
1301  }
1302 
1303  Twine Msg = "immediate must be an integer in the range";
1304  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1305  return MatchOperand_ParseFail;
1306  }
1307  case AsmToken::Identifier: {
1308  StringRef Identifier;
1309  if (getParser().parseIdentifier(Identifier))
1310  return MatchOperand_ParseFail;
1311 
1312  auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1313  if (!SysReg)
1314  SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1315  if (!SysReg)
1316  if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1317  Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1318  SysReg->Name + "'");
1319 
1320  // Accept a named Sys Reg if the required features are present.
1321  if (SysReg) {
1322  if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1323  Error(S, "system register use requires an option to be enabled");
1324  return MatchOperand_ParseFail;
1325  }
1326  Operands.push_back(RISCVOperand::createSysReg(
1327  Identifier, S, SysReg->Encoding, isRV64()));
1328  return MatchOperand_Success;
1329  }
1330 
1331  Twine Msg = "operand must be a valid system register name "
1332  "or an integer in the range";
1333  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1334  return MatchOperand_ParseFail;
1335  }
1336  case AsmToken::Percent: {
1337  // Discard operand with modifier.
1338  Twine Msg = "immediate must be an integer in the range";
1339  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1340  return MatchOperand_ParseFail;
1341  }
1342  }
1343 
1344  return MatchOperand_NoMatch;
1345 }
1346 
1347 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1348  SMLoc S = getLoc();
1349  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1350  const MCExpr *Res;
1351 
1352  switch (getLexer().getKind()) {
1353  default:
1354  return MatchOperand_NoMatch;
1355  case AsmToken::LParen:
1356  case AsmToken::Dot:
1357  case AsmToken::Minus:
1358  case AsmToken::Plus:
1359  case AsmToken::Exclaim:
1360  case AsmToken::Tilde:
1361  case AsmToken::Integer:
1362  case AsmToken::String:
1363  case AsmToken::Identifier:
1364  if (getParser().parseExpression(Res))
1365  return MatchOperand_ParseFail;
1366  break;
1367  case AsmToken::Percent:
1368  return parseOperandWithModifier(Operands);
1369  }
1370 
1371  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1372  return MatchOperand_Success;
1373 }
1374 
1375 OperandMatchResultTy
1376 RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1377  SMLoc S = getLoc();
1378  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1379 
1380  if (getLexer().getKind() != AsmToken::Percent) {
1381  Error(getLoc(), "expected '%' for operand modifier");
1382  return MatchOperand_ParseFail;
1383  }
1384 
1385  getParser().Lex(); // Eat '%'
1386 
1387  if (getLexer().getKind() != AsmToken::Identifier) {
1388  Error(getLoc(), "expected valid identifier for operand modifier");
1389  return MatchOperand_ParseFail;
1390  }
1391  StringRef Identifier = getParser().getTok().getIdentifier();
1392  RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1393  if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1394  Error(getLoc(), "unrecognized operand modifier");
1395  return MatchOperand_ParseFail;
1396  }
1397 
1398  getParser().Lex(); // Eat the identifier
1399  if (getLexer().getKind() != AsmToken::LParen) {
1400  Error(getLoc(), "expected '('");
1401  return MatchOperand_ParseFail;
1402  }
1403  getParser().Lex(); // Eat '('
1404 
1405  const MCExpr *SubExpr;
1406  if (getParser().parseParenExpression(SubExpr, E)) {
1407  return MatchOperand_ParseFail;
1408  }
1409 
1410  const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1411  Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1412  return MatchOperand_Success;
1413 }
1414 
1415 OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1416  SMLoc S = getLoc();
1417  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1418  const MCExpr *Res;
1419 
1420  if (getLexer().getKind() != AsmToken::Identifier)
1421  return MatchOperand_NoMatch;
1422 
1423  StringRef Identifier;
1424  AsmToken Tok = getLexer().getTok();
1425 
1426  if (getParser().parseIdentifier(Identifier))
1427  return MatchOperand_ParseFail;
1428 
1429  if (Identifier.consume_back("@plt")) {
1430  Error(getLoc(), "'@plt' operand not valid for instruction");
1431  return MatchOperand_ParseFail;
1432  }
1433 
1434  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1435 
1436  if (Sym->isVariable()) {
1437  const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1438  if (!isa<MCSymbolRefExpr>(V)) {
1439  getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1440  return MatchOperand_NoMatch;
1441  }
1442  Res = V;
1443  } else
1444  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1445 
1446  MCBinaryExpr::Opcode Opcode;
1447  switch (getLexer().getKind()) {
1448  default:
1449  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1450  return MatchOperand_Success;
1451  case AsmToken::Plus:
1452  Opcode = MCBinaryExpr::Add;
1453  break;
1454  case AsmToken::Minus:
1455  Opcode = MCBinaryExpr::Sub;
1456  break;
1457  }
1458 
1459  const MCExpr *Expr;
1460  if (getParser().parseExpression(Expr))
1461  return MatchOperand_ParseFail;
1462  Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1463  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1464  return MatchOperand_Success;
1465 }
1466 
1467 OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
1468  SMLoc S = getLoc();
1469  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1470  const MCExpr *Res;
1471 
1472  if (getLexer().getKind() != AsmToken::Identifier)
1473  return MatchOperand_NoMatch;
1474 
1475  // Avoid parsing the register in `call rd, foo` as a call symbol.
1476  if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
1477  return MatchOperand_NoMatch;
1478 
1479  StringRef Identifier;
1480  if (getParser().parseIdentifier(Identifier))
1481  return MatchOperand_ParseFail;
1482 
1483  RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL;
1484  if (Identifier.consume_back("@plt"))
1485  Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
1486 
1487  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1488  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1489  Res = RISCVMCExpr::create(Res, Kind, getContext());
1490  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1491  return MatchOperand_Success;
1492 }
1493 
1494 OperandMatchResultTy
1495 RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
1496  SMLoc S = getLoc();
1497  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1498  const MCExpr *Res;
1499 
1500  if (getParser().parseExpression(Res))
1501  return MatchOperand_ParseFail;
1502 
1503  if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
1504  cast<MCSymbolRefExpr>(Res)->getKind() ==
1505  MCSymbolRefExpr::VariantKind::VK_PLT) {
1506  Error(S, "operand must be a valid jump target");
1507  return MatchOperand_ParseFail;
1508  }
1509 
1510  Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
1511  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1512  return MatchOperand_Success;
1513 }
1514 
1515 OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1516  // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1517  // both being acceptable forms. When parsing `jal ra, foo` this function
1518  // will be called for the `ra` register operand in an attempt to match the
1519  // single-operand alias. parseJALOffset must fail for this case. It would
1520  // seem logical to try parse the operand using parseImmediate and return
1521  // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1522  // the second form rather than the first). We can't do this as there's no
1523  // way of rewinding the lexer state. Instead, return NoMatch if this operand
1524  // is an identifier and is followed by a comma.
1525  if (getLexer().is(AsmToken::Identifier) &&
1526  getLexer().peekTok().is(AsmToken::Comma))
1527  return MatchOperand_NoMatch;
1528 
1529  return parseImmediate(Operands);
1530 }
1531 
1532 OperandMatchResultTy RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
1533  SMLoc S = getLoc();
1534  if (getLexer().isNot(AsmToken::Identifier))
1535  return MatchOperand_NoMatch;
1536 
1537  SmallVector<AsmToken, 7> VTypeIElements;
1538  // Put all the tokens for vtypei operand into VTypeIElements vector.
1539  while (getLexer().isNot(AsmToken::EndOfStatement)) {
1540  VTypeIElements.push_back(getLexer().getTok());
1541  getLexer().Lex();
1542  if (getLexer().is(AsmToken::EndOfStatement))
1543  break;
1544  if (getLexer().isNot(AsmToken::Comma))
1545  goto MatchFail;
1546  AsmToken Comma = getLexer().getTok();
1547  VTypeIElements.push_back(Comma);
1548  getLexer().Lex();
1549  }
1550 
1551  if (VTypeIElements.size() == 7) {
1552  // The VTypeIElements layout is:
1553  // SEW comma LMUL comma TA comma MA
1554  // 0 1 2 3 4 5 6
1555  StringRef Name = VTypeIElements[0].getIdentifier();
1556  if (!Name.consume_front("e"))
1557  goto MatchFail;
1558  unsigned Sew;
1559  if (Name.getAsInteger(10, Sew))
1560  goto MatchFail;
1561  if (!RISCVVType::isValidSEW(Sew))
1562  goto MatchFail;
1563 
1564  Name = VTypeIElements[2].getIdentifier();
1565  if (!Name.consume_front("m"))
1566  goto MatchFail;
1567  // "m" or "mf"
1568  bool Fractional = Name.consume_front("f");
1569  unsigned Lmul;
1570  if (Name.getAsInteger(10, Lmul))
1571  goto MatchFail;
1572  if (!RISCVVType::isValidLMUL(Lmul, Fractional))
1573  goto MatchFail;
1574 
1575  // ta or tu
1576  Name = VTypeIElements[4].getIdentifier();
1577  bool TailAgnostic;
1578  if (Name == "ta")
1579  TailAgnostic = true;
1580  else if (Name == "tu")
1581  TailAgnostic = false;
1582  else
1583  goto MatchFail;
1584 
1585  // ma or mu
1586  Name = VTypeIElements[6].getIdentifier();
1587  bool MaskAgnostic;
1588  if (Name == "ma")
1589  MaskAgnostic = true;
1590  else if (Name == "mu")
1591  MaskAgnostic = false;
1592  else
1593  goto MatchFail;
1594 
1595  unsigned LmulLog2 = Log2_32(Lmul);
1596  RISCVII::VLMUL VLMUL =
1597  static_cast<RISCVII::VLMUL>(Fractional ? 8 - LmulLog2 : LmulLog2);
1598 
1599  unsigned VTypeI =
1600  RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
1601  Operands.push_back(RISCVOperand::createVType(VTypeI, S, isRV64()));
1602  return MatchOperand_Success;
1603  }
1604 
1605 // If NoMatch, unlex all the tokens that comprise a vtypei operand
1606 MatchFail:
1607  while (!VTypeIElements.empty())
1608  getLexer().UnLex(VTypeIElements.pop_back_val());
1609  return MatchOperand_NoMatch;
1610 }
1611 
1612 OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
1613  switch (getLexer().getKind()) {
1614  default:
1615  return MatchOperand_NoMatch;
1616  case AsmToken::Identifier:
1617  StringRef Name = getLexer().getTok().getIdentifier();
1618  if (!Name.consume_back(".t")) {
1619  Error(getLoc(), "expected '.t' suffix");
1620  return MatchOperand_ParseFail;
1621  }
1622  MCRegister RegNo;
1623  matchRegisterNameHelper(isRV32E(), RegNo, Name);
1624 
1625  if (RegNo == RISCV::NoRegister)
1626  return MatchOperand_NoMatch;
1627  if (RegNo != RISCV::V0)
1628  return MatchOperand_NoMatch;
1629  SMLoc S = getLoc();
1630  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1631  getLexer().Lex();
1632  Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
1633  }
1634 
1635  return MatchOperand_Success;
1636 }
1637 
1638 OperandMatchResultTy
1639 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1640  if (getLexer().isNot(AsmToken::LParen)) {
1641  Error(getLoc(), "expected '('");
1642  return MatchOperand_ParseFail;
1643  }
1644 
1645  getParser().Lex(); // Eat '('
1646  Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
1647 
1648  if (parseRegister(Operands) != MatchOperand_Success) {
1649  Error(getLoc(), "expected register");
1650  return MatchOperand_ParseFail;
1651  }
1652 
1653  if (getLexer().isNot(AsmToken::RParen)) {
1654  Error(getLoc(), "expected ')'");
1655  return MatchOperand_ParseFail;
1656  }
1657 
1658  getParser().Lex(); // Eat ')'
1659  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
1660 
1661  return MatchOperand_Success;
1662 }
1663 
1664 OperandMatchResultTy RISCVAsmParser::parseAtomicMemOp(OperandVector &Operands) {
1665  // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
1666  // as one of their register operands, such as `(a0)`. This just denotes that
1667  // the register (in this case `a0`) contains a memory address.
1668  //
1669  // Normally, we would be able to parse these by putting the parens into the
1670  // instruction string. However, GNU as also accepts a zero-offset memory
1671  // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
1672  // with parseImmediate followed by parseMemOpBaseReg, but these instructions
1673  // do not accept an immediate operand, and we do not want to add a "dummy"
1674  // operand that is silently dropped.
1675  //
1676  // Instead, we use this custom parser. This will: allow (and discard) an
1677  // offset if it is zero; require (and discard) parentheses; and add only the
1678  // parsed register operand to `Operands`.
1679  //
1680  // These operands are printed with RISCVInstPrinter::printAtomicMemOp, which
1681  // will only print the register surrounded by parentheses (which GNU as also
1682  // uses as its canonical representation for these operands).
1683  std::unique_ptr<RISCVOperand> OptionalImmOp;
1684 
1685  if (getLexer().isNot(AsmToken::LParen)) {
1686  // Parse an Integer token. We do not accept arbritrary constant expressions
1687  // in the offset field (because they may include parens, which complicates
1688  // parsing a lot).
1689  int64_t ImmVal;
1690  SMLoc ImmStart = getLoc();
1691  if (getParser().parseIntToken(ImmVal,
1692  "expected '(' or optional integer offset"))
1693  return MatchOperand_ParseFail;
1694 
1695  // Create a RISCVOperand for checking later (so the error messages are
1696  // nicer), but we don't add it to Operands.
1697  SMLoc ImmEnd = getLoc();
1698  OptionalImmOp =
1699  RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
1700  ImmStart, ImmEnd, isRV64());
1701  }
1702 
1703  if (getLexer().isNot(AsmToken::LParen)) {
1704  Error(getLoc(), OptionalImmOp ? "expected '(' after optional integer offset"
1705  : "expected '(' or optional integer offset");
1706  return MatchOperand_ParseFail;
1707  }
1708  getParser().Lex(); // Eat '('
1709 
1710  if (parseRegister(Operands) != MatchOperand_Success) {
1711  Error(getLoc(), "expected register");
1712  return MatchOperand_ParseFail;
1713  }
1714 
1715  if (getLexer().isNot(AsmToken::RParen)) {
1716  Error(getLoc(), "expected ')'");
1717  return MatchOperand_ParseFail;
1718  }
1719  getParser().Lex(); // Eat ')'
1720 
1721  // Deferred Handling of non-zero offsets. This makes the error messages nicer.
1722  if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
1723  Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
1724  SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
1725  return MatchOperand_ParseFail;
1726  }
1727 
1728  return MatchOperand_Success;
1729 }
1730 
1731 /// Looks at a token type and creates the relevant operand from this
1732 /// information, adding to Operands. If operand was parsed, returns false, else
1733 /// true.
1734 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1735  // Check if the current operand has a custom associated parser, if so, try to
1736  // custom parse the operand, or fallback to the general approach.
1737  OperandMatchResultTy Result =
1738  MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1739  if (Result == MatchOperand_Success)
1740  return false;
1741  if (Result == MatchOperand_ParseFail)
1742  return true;
1743 
1744  // Attempt to parse token as a register.
1745  if (parseRegister(Operands, true) == MatchOperand_Success)
1746  return false;
1747 
1748  // Attempt to parse token as an immediate
1749  if (parseImmediate(Operands) == MatchOperand_Success) {
1750  // Parse memory base register if present
1751  if (getLexer().is(AsmToken::LParen))
1752  return parseMemOpBaseReg(Operands) != MatchOperand_Success;
1753  return false;
1754  }
1755 
1756  // Finally we have exhausted all options and must declare defeat.
1757  Error(getLoc(), "unknown operand");
1758  return true;
1759 }
1760 
1761 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1762  StringRef Name, SMLoc NameLoc,
1763  OperandVector &Operands) {
1764  // Ensure that if the instruction occurs when relaxation is enabled,
1765  // relocations are forced for the file. Ideally this would be done when there
1766  // is enough information to reliably determine if the instruction itself may
1767  // cause relaxations. Unfortunately instruction processing stage occurs in the
1768  // same pass as relocation emission, so it's too late to set a 'sticky bit'
1769  // for the entire file.
1770  if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1771  auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1772  if (Assembler != nullptr) {
1773  RISCVAsmBackend &MAB =
1774  static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1775  MAB.setForceRelocs();
1776  }
1777  }
1778 
1779  // First operand is token for instruction
1780  Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
1781 
1782  // If there are no more operands, then finish
1783  if (getLexer().is(AsmToken::EndOfStatement))
1784  return false;
1785 
1786  // Parse first operand
1787  if (parseOperand(Operands, Name))
1788  return true;
1789 
1790  // Parse until end of statement, consuming commas between operands
1791  unsigned OperandIdx = 1;
1792  while (getLexer().is(AsmToken::Comma)) {
1793  // Consume comma token
1794  getLexer().Lex();
1795 
1796  // Parse next operand
1797  if (parseOperand(Operands, Name))
1798  return true;
1799 
1800  ++OperandIdx;
1801  }
1802 
1803  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1804  SMLoc Loc = getLexer().getLoc();
1805  getParser().eatToEndOfStatement();
1806  return Error(Loc, "unexpected token");
1807  }
1808 
1809  getParser().Lex(); // Consume the EndOfStatement.
1810  return false;
1811 }
1812 
1813 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1814  RISCVMCExpr::VariantKind &Kind) {
1815  Kind = RISCVMCExpr::VK_RISCV_None;
1816 
1817  if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1818  Kind = RE->getKind();
1819  Expr = RE->getSubExpr();
1820  }
1821 
1822  MCValue Res;
1823  MCFixup Fixup;
1824  if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
1825  return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
1826  return false;
1827 }
1828 
1829 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1830  // This returns false if this function recognizes the directive
1831  // regardless of whether it is successfully handles or reports an
1832  // error. Otherwise it returns true to give the generic parser a
1833  // chance at recognizing it.
1834  StringRef IDVal = DirectiveID.getString();
1835 
1836  if (IDVal == ".option")
1837  return parseDirectiveOption();
1838  else if (IDVal == ".attribute")
1839  return parseDirectiveAttribute();
1840 
1841  return true;
1842 }
1843 
1844 bool RISCVAsmParser::parseDirectiveOption() {
1845  MCAsmParser &Parser = getParser();
1846  // Get the option token.
1847  AsmToken Tok = Parser.getTok();
1848  // At the moment only identifiers are supported.
1849  if (Tok.isNot(AsmToken::Identifier))
1850  return Error(Parser.getTok().getLoc(),
1851  "unexpected token, expected identifier");
1852 
1853  StringRef Option = Tok.getIdentifier();
1854 
1855  if (Option == "push") {
1856  getTargetStreamer().emitDirectiveOptionPush();
1857 
1858  Parser.Lex();
1859  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1860  return Error(Parser.getTok().getLoc(),
1861  "unexpected token, expected end of statement");
1862 
1863  pushFeatureBits();
1864  return false;
1865  }
1866 
1867  if (Option == "pop") {
1868  SMLoc StartLoc = Parser.getTok().getLoc();
1869  getTargetStreamer().emitDirectiveOptionPop();
1870 
1871  Parser.Lex();
1872  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1873  return Error(Parser.getTok().getLoc(),
1874  "unexpected token, expected end of statement");
1875 
1876  if (popFeatureBits())
1877  return Error(StartLoc, ".option pop with no .option push");
1878 
1879  return false;
1880  }
1881 
1882  if (Option == "rvc") {
1883  getTargetStreamer().emitDirectiveOptionRVC();
1884 
1885  Parser.Lex();
1886  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1887  return Error(Parser.getTok().getLoc(),
1888  "unexpected token, expected end of statement");
1889 
1890  setFeatureBits(RISCV::FeatureStdExtC, "c");
1891  return false;
1892  }
1893 
1894  if (Option == "norvc") {
1895  getTargetStreamer().emitDirectiveOptionNoRVC();
1896 
1897  Parser.Lex();
1898  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1899  return Error(Parser.getTok().getLoc(),
1900  "unexpected token, expected end of statement");
1901 
1902  clearFeatureBits(RISCV::FeatureStdExtC, "c");
1903  return false;
1904  }
1905 
1906  if (Option == "pic") {
1907  getTargetStreamer().emitDirectiveOptionPIC();
1908 
1909  Parser.Lex();
1910  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1911  return Error(Parser.getTok().getLoc(),
1912  "unexpected token, expected end of statement");
1913 
1914  ParserOptions.IsPicEnabled = true;
1915  return false;
1916  }
1917 
1918  if (Option == "nopic") {
1919  getTargetStreamer().emitDirectiveOptionNoPIC();
1920 
1921  Parser.Lex();
1922  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1923  return Error(Parser.getTok().getLoc(),
1924  "unexpected token, expected end of statement");
1925 
1926  ParserOptions.IsPicEnabled = false;
1927  return false;
1928  }
1929 
1930  if (Option == "relax") {
1931  getTargetStreamer().emitDirectiveOptionRelax();
1932 
1933  Parser.Lex();
1934  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1935  return Error(Parser.getTok().getLoc(),
1936  "unexpected token, expected end of statement");
1937 
1938  setFeatureBits(RISCV::FeatureRelax, "relax");
1939  return false;
1940  }
1941 
1942  if (Option == "norelax") {
1943  getTargetStreamer().emitDirectiveOptionNoRelax();
1944 
1945  Parser.Lex();
1946  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1947  return Error(Parser.getTok().getLoc(),
1948  "unexpected token, expected end of statement");
1949 
1950  clearFeatureBits(RISCV::FeatureRelax, "relax");
1951  return false;
1952  }
1953 
1954  // Unknown option.
1955  Warning(Parser.getTok().getLoc(),
1956  "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
1957  "'norelax'");
1958  Parser.eatToEndOfStatement();
1959  return false;
1960 }
1961 
1962 /// parseDirectiveAttribute
1963 /// ::= .attribute expression ',' ( expression | "string" )
1964 /// ::= .attribute identifier ',' ( expression | "string" )
1965 bool RISCVAsmParser::parseDirectiveAttribute() {
1966  MCAsmParser &Parser = getParser();
1967  int64_t Tag;
1968  SMLoc TagLoc;
1969  TagLoc = Parser.getTok().getLoc();
1970  if (Parser.getTok().is(AsmToken::Identifier)) {
1971  StringRef Name = Parser.getTok().getIdentifier();
1972  Optional<unsigned> Ret =
1973  ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
1974  if (!Ret.hasValue()) {
1975  Error(TagLoc, "attribute name not recognised: " + Name);
1976  return false;
1977  }
1978  Tag = Ret.getValue();
1979  Parser.Lex();
1980  } else {
1981  const MCExpr *AttrExpr;
1982 
1983  TagLoc = Parser.getTok().getLoc();
1984  if (Parser.parseExpression(AttrExpr))
1985  return true;
1986 
1987  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
1988  if (check(!CE, TagLoc, "expected numeric constant"))
1989  return true;
1990 
1991  Tag = CE->getValue();
1992  }
1993 
1994  if (Parser.parseToken(AsmToken::Comma, "comma expected"))
1995  return true;
1996 
1997  StringRef StringValue;
1998  int64_t IntegerValue = 0;
1999  bool IsIntegerValue = true;
2000 
2001  // RISC-V attributes have a string value if the tag number is odd
2002  // and an integer value if the tag number is even.
2003  if (Tag % 2)
2004  IsIntegerValue = false;
2005 
2006  SMLoc ValueExprLoc = Parser.getTok().getLoc();
2007  if (IsIntegerValue) {
2008  const MCExpr *ValueExpr;
2009  if (Parser.parseExpression(ValueExpr))
2010  return true;
2011 
2012  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
2013  if (!CE)
2014  return Error(ValueExprLoc, "expected numeric constant");
2015  IntegerValue = CE->getValue();
2016  } else {
2017  if (Parser.getTok().isNot(AsmToken::String))
2018  return Error(Parser.getTok().getLoc(), "expected string constant");
2019 
2020  StringValue = Parser.getTok().getStringContents();
2021  Parser.Lex();
2022  }
2023 
2024  if (Parser.parseToken(AsmToken::EndOfStatement,
2025  "unexpected token in '.attribute' directive"))
2026  return true;
2027 
2028  if (Tag == RISCVAttrs::ARCH) {
2029  StringRef Arch = StringValue;
2030  if (Arch.consume_front("rv32"))
2031  clearFeatureBits(RISCV::Feature64Bit, "64bit");
2032  else if (Arch.consume_front("rv64"))
2033  setFeatureBits(RISCV::Feature64Bit, "64bit");
2034  else
2035  return Error(ValueExprLoc, "bad arch string " + Arch);
2036 
2037  // .attribute arch overrides the current architecture, so unset all
2038  // currently enabled extensions
2039  clearFeatureBits(RISCV::FeatureRV32E, "e");
2040  clearFeatureBits(RISCV::FeatureStdExtM, "m");
2041  clearFeatureBits(RISCV::FeatureStdExtA, "a");
2042  clearFeatureBits(RISCV::FeatureStdExtF, "f");
2043  clearFeatureBits(RISCV::FeatureStdExtD, "d");
2044  clearFeatureBits(RISCV::FeatureStdExtC, "c");
2045  clearFeatureBits(RISCV::FeatureStdExtB, "experimental-b");
2046  clearFeatureBits(RISCV::FeatureStdExtV, "experimental-v");
2047  clearFeatureBits(RISCV::FeatureExtZfh, "experimental-zfh");
2048  clearFeatureBits(RISCV::FeatureExtZba, "experimental-zba");
2049  clearFeatureBits(RISCV::FeatureExtZbb, "experimental-zbb");
2050  clearFeatureBits(RISCV::FeatureExtZbc, "experimental-zbc");
2051  clearFeatureBits(RISCV::FeatureExtZbe, "experimental-zbe");
2052  clearFeatureBits(RISCV::FeatureExtZbf, "experimental-zbf");
2053  clearFeatureBits(RISCV::FeatureExtZbm, "experimental-zbm");
2054  clearFeatureBits(RISCV::FeatureExtZbp, "experimental-zbp");
2055  clearFeatureBits(RISCV::FeatureExtZbproposedc, "experimental-zbproposedc");
2056  clearFeatureBits(RISCV::FeatureExtZbr, "experimental-zbr");
2057  clearFeatureBits(RISCV::FeatureExtZbs, "experimental-zbs");
2058  clearFeatureBits(RISCV::FeatureExtZbt, "experimental-zbt");
2059  clearFeatureBits(RISCV::FeatureExtZvamo, "experimental-zvamo");
2060  clearFeatureBits(RISCV::FeatureStdExtZvlsseg, "experimental-zvlsseg");
2061 
2062  while (!Arch.empty()) {
2063  bool DropFirst = true;
2064  if (Arch[0] == 'i')
2065  clearFeatureBits(RISCV::FeatureRV32E, "e");
2066  else if (Arch[0] == 'e')
2067  setFeatureBits(RISCV::FeatureRV32E, "e");
2068  else if (Arch[0] == 'g') {
2069  clearFeatureBits(RISCV::FeatureRV32E, "e");
2070  setFeatureBits(RISCV::FeatureStdExtM, "m");
2071  setFeatureBits(RISCV::FeatureStdExtA, "a");
2072  setFeatureBits(RISCV::FeatureStdExtF, "f");
2073  setFeatureBits(RISCV::FeatureStdExtD, "d");
2074  } else if (Arch[0] == 'm')
2075  setFeatureBits(RISCV::FeatureStdExtM, "m");
2076  else if (Arch[0] == 'a')
2077  setFeatureBits(RISCV::FeatureStdExtA, "a");
2078  else if (Arch[0] == 'f')
2079  setFeatureBits(RISCV::FeatureStdExtF, "f");
2080  else if (Arch[0] == 'd') {
2081  setFeatureBits(RISCV::FeatureStdExtF, "f");
2082  setFeatureBits(RISCV::FeatureStdExtD, "d");
2083  } else if (Arch[0] == 'c') {
2084  setFeatureBits(RISCV::FeatureStdExtC, "c");
2085  } else if (Arch[0] == 'b') {
2086  setFeatureBits(RISCV::FeatureStdExtB, "experimental-b");
2087  } else if (Arch[0] == 'v') {
2088  setFeatureBits(RISCV::FeatureStdExtV, "experimental-v");
2089  } else if (Arch[0] == 's' || Arch[0] == 'x' || Arch[0] == 'z') {
2090  StringRef Ext =
2091  Arch.take_until([](char c) { return ::isdigit(c) || c == '_'; });
2092  if (Ext == "zba")
2093  setFeatureBits(RISCV::FeatureExtZba, "experimental-zba");
2094  else if (Ext == "zbb")
2095  setFeatureBits(RISCV::FeatureExtZbb, "experimental-zbb");
2096  else if (Ext == "zbc")
2097  setFeatureBits(RISCV::FeatureExtZbc, "experimental-zbc");
2098  else if (Ext == "zbe")
2099  setFeatureBits(RISCV::FeatureExtZbe, "experimental-zbe");
2100  else if (Ext == "zbf")
2101  setFeatureBits(RISCV::FeatureExtZbf, "experimental-zbf");
2102  else if (Ext == "zbm")
2103  setFeatureBits(RISCV::FeatureExtZbm, "experimental-zbm");
2104  else if (Ext == "zbp")
2105  setFeatureBits(RISCV::FeatureExtZbp, "experimental-zbp");
2106  else if (Ext == "zbproposedc")
2107  setFeatureBits(RISCV::FeatureExtZbproposedc,
2108  "experimental-zbproposedc");
2109  else if (Ext == "zbr")
2110  setFeatureBits(RISCV::FeatureExtZbr, "experimental-zbr");
2111  else if (Ext == "zbs")
2112  setFeatureBits(RISCV::FeatureExtZbs, "experimental-zbs");
2113  else if (Ext == "zbt")
2114  setFeatureBits(RISCV::FeatureExtZbt, "experimental-zbt");
2115  else if (Ext == "zfh")
2116  setFeatureBits(RISCV::FeatureExtZfh, "experimental-zfh");
2117  else if (Ext == "zvamo")
2118  setFeatureBits(RISCV::FeatureExtZvamo, "experimental-zvamo");
2119  else if (Ext == "zvlsseg")
2120  setFeatureBits(RISCV::FeatureStdExtZvlsseg, "experimental-zvlsseg");
2121  else
2122  return Error(ValueExprLoc, "bad arch string " + Ext);
2123  Arch = Arch.drop_until([](char c) { return ::isdigit(c) || c == '_'; });
2124  DropFirst = false;
2125  } else
2126  return Error(ValueExprLoc, "bad arch string " + Arch);
2127 
2128  if (DropFirst)
2129  Arch = Arch.drop_front(1);
2130  int major = 0;
2131  int minor = 0;
2132  Arch.consumeInteger(10, major);
2133  Arch.consume_front("p");
2134  Arch.consumeInteger(10, minor);
2135  Arch = Arch.drop_while([](char c) { return c == '_'; });
2136  }
2137  }
2138 
2139  if (IsIntegerValue)
2140  getTargetStreamer().emitAttribute(Tag, IntegerValue);
2141  else {
2142  if (Tag != RISCVAttrs::ARCH) {
2143  getTargetStreamer().emitTextAttribute(Tag, StringValue);
2144  } else {
2145  std::string formalArchStr = "rv32";
2146  if (getFeatureBits(RISCV::Feature64Bit))
2147  formalArchStr = "rv64";
2148  if (getFeatureBits(RISCV::FeatureRV32E))
2149  formalArchStr = (Twine(formalArchStr) + "e1p9").str();
2150  else
2151  formalArchStr = (Twine(formalArchStr) + "i2p0").str();
2152 
2153  if (getFeatureBits(RISCV::FeatureStdExtM))
2154  formalArchStr = (Twine(formalArchStr) + "_m2p0").str();
2155  if (getFeatureBits(RISCV::FeatureStdExtA))
2156  formalArchStr = (Twine(formalArchStr) + "_a2p0").str();
2157  if (getFeatureBits(RISCV::FeatureStdExtF))
2158  formalArchStr = (Twine(formalArchStr) + "_f2p0").str();
2159  if (getFeatureBits(RISCV::FeatureStdExtD))
2160  formalArchStr = (Twine(formalArchStr) + "_d2p0").str();
2161  if (getFeatureBits(RISCV::FeatureStdExtC))
2162  formalArchStr = (Twine(formalArchStr) + "_c2p0").str();
2163  if (getFeatureBits(RISCV::FeatureStdExtB))
2164  formalArchStr = (Twine(formalArchStr) + "_b0p93").str();
2165  if (getFeatureBits(RISCV::FeatureStdExtV))
2166  formalArchStr = (Twine(formalArchStr) + "_v0p10").str();
2167  if (getFeatureBits(RISCV::FeatureExtZfh))
2168  formalArchStr = (Twine(formalArchStr) + "_zfh0p1").str();
2169  if (getFeatureBits(RISCV::FeatureExtZba))
2170  formalArchStr = (Twine(formalArchStr) + "_zba0p93").str();
2171  if (getFeatureBits(RISCV::FeatureExtZbb))
2172  formalArchStr = (Twine(formalArchStr) + "_zbb0p93").str();
2173  if (getFeatureBits(RISCV::FeatureExtZbc))
2174  formalArchStr = (Twine(formalArchStr) + "_zbc0p93").str();
2175  if (getFeatureBits(RISCV::FeatureExtZbe))
2176  formalArchStr = (Twine(formalArchStr) + "_zbe0p93").str();
2177  if (getFeatureBits(RISCV::FeatureExtZbf))
2178  formalArchStr = (Twine(formalArchStr) + "_zbf0p93").str();
2179  if (getFeatureBits(RISCV::FeatureExtZbm))
2180  formalArchStr = (Twine(formalArchStr) + "_zbm0p93").str();
2181  if (getFeatureBits(RISCV::FeatureExtZbp))
2182  formalArchStr = (Twine(formalArchStr) + "_zbp0p93").str();
2183  if (getFeatureBits(RISCV::FeatureExtZbproposedc))
2184  formalArchStr = (Twine(formalArchStr) + "_zbproposedc0p93").str();
2185  if (getFeatureBits(RISCV::FeatureExtZbr))
2186  formalArchStr = (Twine(formalArchStr) + "_zbr0p93").str();
2187  if (getFeatureBits(RISCV::FeatureExtZbs))
2188  formalArchStr = (Twine(formalArchStr) + "_zbs0p93").str();
2189  if (getFeatureBits(RISCV::FeatureExtZbt))
2190  formalArchStr = (Twine(formalArchStr) + "_zbt0p93").str();
2191  if (getFeatureBits(RISCV::FeatureExtZvamo))
2192  formalArchStr = (Twine(formalArchStr) + "_zvamo0p10").str();
2193  if (getFeatureBits(RISCV::FeatureStdExtZvlsseg))
2194  formalArchStr = (Twine(formalArchStr) + "_zvlsseg0p10").str();
2195 
2196  getTargetStreamer().emitTextAttribute(Tag, formalArchStr);
2197  }
2198  }
2199 
2200  return false;
2201 }
2202 
2203 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
2204  MCInst CInst;
2205  bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
2206  if (Res)
2207  ++RISCVNumInstrsCompressed;
2208  S.emitInstruction((Res ? CInst : Inst), getSTI());
2209 }
2210 
2211 void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
2212  MCStreamer &Out) {
2213  RISCVMatInt::InstSeq Seq =
2214  RISCVMatInt::generateInstSeq(Value, getSTI().getFeatureBits());
2215 
2216  MCRegister SrcReg = RISCV::X0;
2217  for (RISCVMatInt::Inst &Inst : Seq) {
2218  if (Inst.Opc == RISCV::LUI) {
2219  emitToStreamer(
2220  Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
2221  } else if (Inst.Opc == RISCV::ADDUW) {
2222  emitToStreamer(Out, MCInstBuilder(RISCV::ADDUW)
2223  .addReg(DestReg)
2224  .addReg(SrcReg)
2225  .addReg(RISCV::X0));
2226  } else {
2227  emitToStreamer(
2228  Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
2229  Inst.Imm));
2230  }
2231 
2232  // Only the first instruction has X0 as its source.
2233  SrcReg = DestReg;
2234  }
2235 }
2236 
2237 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
2238  const MCExpr *Symbol,
2239  RISCVMCExpr::VariantKind VKHi,
2240  unsigned SecondOpcode, SMLoc IDLoc,
2241  MCStreamer &Out) {
2242  // A pair of instructions for PC-relative addressing; expands to
2243  // TmpLabel: AUIPC TmpReg, VKHi(symbol)
2244  // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
2245  MCContext &Ctx = getContext();
2246 
2247  MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
2248  Out.emitLabel(TmpLabel);
2249 
2250  const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
2251  emitToStreamer(
2252  Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
2253 
2254  const MCExpr *RefToLinkTmpLabel =
2255  RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
2256  RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
2257 
2258  emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2259  .addOperand(DestReg)
2260  .addOperand(TmpReg)
2261  .addExpr(RefToLinkTmpLabel));
2262 }
2263 
2264 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
2265  MCStreamer &Out) {
2266  // The load local address pseudo-instruction "lla" is used in PC-relative
2267  // addressing of local symbols:
2268  // lla rdest, symbol
2269  // expands to
2270  // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2271  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2272  MCOperand DestReg = Inst.getOperand(0);
2273  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2274  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2275  RISCV::ADDI, IDLoc, Out);
2276 }
2277 
2278 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
2279  MCStreamer &Out) {
2280  // The load address pseudo-instruction "la" is used in PC-relative and
2281  // GOT-indirect addressing of global symbols:
2282  // la rdest, symbol
2283  // expands to either (for non-PIC)
2284  // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2285  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2286  // or (for PIC)
2287  // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
2288  // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2289  MCOperand DestReg = Inst.getOperand(0);
2290  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2291  unsigned SecondOpcode;
2292  RISCVMCExpr::VariantKind VKHi;
2293  if (ParserOptions.IsPicEnabled) {
2294  SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2295  VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
2296  } else {
2297  SecondOpcode = RISCV::ADDI;
2298  VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
2299  }
2300  emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
2301 }
2302 
2303 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
2304  MCStreamer &Out) {
2305  // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
2306  // initial-exec TLS model addressing of global symbols:
2307  // la.tls.ie rdest, symbol
2308  // expands to
2309  // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
2310  // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2311  MCOperand DestReg = Inst.getOperand(0);
2312  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2313  unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2314  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
2315  SecondOpcode, IDLoc, Out);
2316 }
2317 
2318 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
2319  MCStreamer &Out) {
2320  // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
2321  // global-dynamic TLS model addressing of global symbols:
2322  // la.tls.gd rdest, symbol
2323  // expands to
2324  // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
2325  // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2326  MCOperand DestReg = Inst.getOperand(0);
2327  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2328  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
2329  RISCV::ADDI, IDLoc, Out);
2330 }
2331 
2332 void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
2333  SMLoc IDLoc, MCStreamer &Out,
2334  bool HasTmpReg) {
2335  // The load/store pseudo-instruction does a pc-relative load with
2336  // a symbol.
2337  //
2338  // The expansion looks like this
2339  //
2340  // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
2341  // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
2342  MCOperand DestReg = Inst.getOperand(0);
2343  unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
2344  unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0;
2345  MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx);
2346  const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
2347  emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2348  Opcode, IDLoc, Out);
2349 }
2350 
2351 void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
2352  int64_t Width, SMLoc IDLoc,
2353  MCStreamer &Out) {
2354  // The sign/zero extend pseudo-instruction does two shifts, with the shift
2355  // amounts dependent on the XLEN.
2356  //
2357  // The expansion looks like this
2358  //
2359  // SLLI rd, rs, XLEN - Width
2360  // SR[A|R]I rd, rd, XLEN - Width
2361  MCOperand DestReg = Inst.getOperand(0);
2362  MCOperand SourceReg = Inst.getOperand(1);
2363 
2364  unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
2365  int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
2366 
2367  assert(ShAmt > 0 && "Shift amount must be non-zero.");
2368 
2369  emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
2370  .addOperand(DestReg)
2371  .addOperand(SourceReg)
2372  .addImm(ShAmt));
2373 
2374  emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2375  .addOperand(DestReg)
2376  .addOperand(DestReg)
2377  .addImm(ShAmt));
2378 }
2379 
2380 void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
2381  MCStreamer &Out) {
2382  if (Inst.getNumOperands() == 3) {
2383  // unmasked va >= x
2384  //
2385  // pseudoinstruction: vmsge{u}.vx vd, va, x
2386  // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
2387  emitToStreamer(Out, MCInstBuilder(Opcode)
2388  .addOperand(Inst.getOperand(0))
2389  .addOperand(Inst.getOperand(1))
2390  .addOperand(Inst.getOperand(2))
2391  .addReg(RISCV::NoRegister));
2392  emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
2393  .addOperand(Inst.getOperand(0))
2394  .addOperand(Inst.getOperand(0))
2395  .addOperand(Inst.getOperand(0)));
2396  } else if (Inst.getNumOperands() == 4) {
2397  // masked va >= x, vd != v0
2398  //
2399  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
2400  // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
2401  assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
2402  "The destination register should not be V0.");
2403  emitToStreamer(Out, MCInstBuilder(Opcode)
2404  .addOperand(Inst.getOperand(0))
2405  .addOperand(Inst.getOperand(1))
2406  .addOperand(Inst.getOperand(2))
2407  .addOperand(Inst.getOperand(3)));
2408  emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
2409  .addOperand(Inst.getOperand(0))
2410  .addOperand(Inst.getOperand(0))
2411  .addReg(RISCV::V0));
2412  } else if (Inst.getNumOperands() == 5 &&
2413  Inst.getOperand(0).getReg() == RISCV::V0) {
2414  // masked va >= x, vd == v0
2415  //
2416  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2417  // expansion: vmslt{u}.vx vt, va, x; vmandnot.mm vd, vd, vt
2418  assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
2419  "The destination register should be V0.");
2420  assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2421  "The temporary vector register should not be V0.");
2422  emitToStreamer(Out, MCInstBuilder(Opcode)
2423  .addOperand(Inst.getOperand(1))
2424  .addOperand(Inst.getOperand(2))
2425  .addOperand(Inst.getOperand(3))
2426  .addOperand(Inst.getOperand(4)));
2427  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDNOT_MM)
2428  .addOperand(Inst.getOperand(0))
2429  .addOperand(Inst.getOperand(0))
2430  .addOperand(Inst.getOperand(1)));
2431  } else if (Inst.getNumOperands() == 5) {
2432  // masked va >= x, any vd
2433  //
2434  // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2435  // expansion: vmslt{u}.vx vt, va, x; vmandnot.mm vt, v0, vt; vmandnot.mm vd,
2436  // vd, v0; vmor.mm vd, vt, vd
2437  assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2438  "The temporary vector register should not be V0.");
2439  emitToStreamer(Out, MCInstBuilder(Opcode)
2440  .addOperand(Inst.getOperand(1))
2441  .addOperand(Inst.getOperand(2))
2442  .addOperand(Inst.getOperand(3))
2443  .addReg(RISCV::NoRegister));
2444  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDNOT_MM)
2445  .addOperand(Inst.getOperand(1))
2446  .addReg(RISCV::V0)
2447  .addOperand(Inst.getOperand(1)));
2448  emitToStreamer(Out, MCInstBuilder(RISCV::VMANDNOT_MM)
2449  .addOperand(Inst.getOperand(0))
2450  .addOperand(Inst.getOperand(0))
2451  .addReg(RISCV::V0));
2452  emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
2453  .addOperand(Inst.getOperand(0))
2454  .addOperand(Inst.getOperand(1))
2455  .addOperand(Inst.getOperand(0)));
2456  }
2457 }
2458 
2459 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
2460  OperandVector &Operands) {
2461  assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
2462  assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
2463  if (Inst.getOperand(2).getReg() != RISCV::X4) {
2464  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
2465  return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
2466  "%tprel_add modifier");
2467  }
2468 
2469  return false;
2470 }
2471 
2472 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
2473  return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
2474  llvm::SMLoc(), isRV64());
2475 }
2476 
2477 bool RISCVAsmParser::validateInstruction(MCInst &Inst,
2478  OperandVector &Operands) {
2479  if (Inst.getOpcode() == RISCV::PseudoVMSGEU_VX_M_T ||
2480  Inst.getOpcode() == RISCV::PseudoVMSGE_VX_M_T) {
2481  unsigned DestReg = Inst.getOperand(0).getReg();
2482  unsigned TempReg = Inst.getOperand(1).getReg();
2483  if (DestReg == TempReg) {
2484  SMLoc Loc = Operands.back()->getStartLoc();
2485  return Error(Loc, "The temporary vector register cannot be the same as "
2486  "the destination register.");
2487  }
2488  }
2489 
2490  const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
2491  RISCVII::VConstraintType Constraints =
2492  RISCVII::getConstraint(MCID.TSFlags);
2493  if (Constraints == RISCVII::NoConstraint)
2494  return false;
2495 
2496  unsigned DestReg = Inst.getOperand(0).getReg();
2497  // Operands[1] will be the first operand, DestReg.
2498  SMLoc Loc = Operands[1]->getStartLoc();
2499  if (Constraints & RISCVII::VS2Constraint) {
2500  unsigned CheckReg = Inst.getOperand(1).getReg();
2501  if (DestReg == CheckReg)
2502  return Error(Loc, "The destination vector register group cannot overlap"
2503  " the source vector register group.");
2504  }
2505  if ((Constraints & RISCVII::VS1Constraint) && (Inst.getOperand(2).isReg())) {
2506  unsigned CheckReg = Inst.getOperand(2).getReg();
2507  if (DestReg == CheckReg)
2508  return Error(Loc, "The destination vector register group cannot overlap"
2509  " the source vector register group.");
2510  }
2511  if ((Constraints & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
2512  // vadc, vsbc are special cases. These instructions have no mask register.
2513  // The destination register could not be V0.
2514  unsigned Opcode = Inst.getOpcode();
2515  if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
2516  Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
2517  Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
2518  Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
2519  Opcode == RISCV::VMERGE_VXM)
2520  return Error(Loc, "The destination vector register group cannot be V0.");
2521 
2522  // Regardless masked or unmasked version, the number of operands is the
2523  // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
2524  // actually. We need to check the last operand to ensure whether it is
2525  // masked or not.
2526  unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
2527  assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
2528  "Unexpected register for mask operand");
2529 
2530  if (DestReg == CheckReg)
2531  return Error(Loc, "The destination vector register group cannot overlap"
2532  " the mask register.");
2533  }
2534  return false;
2535 }
2536 
2537 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
2538  OperandVector &Operands,
2539  MCStreamer &Out) {
2540  Inst.setLoc(IDLoc);
2541 
2542  switch (Inst.getOpcode()) {
2543  default:
2544  break;
2545  case RISCV::PseudoLI: {
2546  MCRegister Reg = Inst.getOperand(0).getReg();
2547  const MCOperand &Op1 = Inst.getOperand(1);
2548  if (Op1.isExpr()) {
2549  // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
2550  // Just convert to an addi. This allows compatibility with gas.
2551  emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
2552  .addReg(Reg)
2553  .addReg(RISCV::X0)
2554  .addExpr(Op1.getExpr()));
2555  return false;
2556  }
2557  int64_t Imm = Inst.getOperand(1).getImm();
2558  // On RV32 the immediate here can either be a signed or an unsigned
2559  // 32-bit number. Sign extension has to be performed to ensure that Imm
2560  // represents the expected signed 64-bit number.
2561  if (!isRV64())
2562  Imm = SignExtend64<32>(Imm);
2563  emitLoadImm(Reg, Imm, Out);
2564  return false;
2565  }
2566  case RISCV::PseudoLLA:
2567  emitLoadLocalAddress(Inst, IDLoc, Out);
2568  return false;
2569  case RISCV::PseudoLA:
2570  emitLoadAddress(Inst, IDLoc, Out);
2571  return false;
2572  case RISCV::PseudoLA_TLS_IE:
2573  emitLoadTLSIEAddress(Inst, IDLoc, Out);
2574  return false;
2575  case RISCV::PseudoLA_TLS_GD:
2576  emitLoadTLSGDAddress(Inst, IDLoc, Out);
2577  return false;
2578  case RISCV::PseudoLB:
2579  emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
2580  return false;
2581  case RISCV::PseudoLBU:
2582  emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
2583  return false;
2584  case RISCV::PseudoLH:
2585  emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
2586  return false;
2587  case RISCV::PseudoLHU:
2588  emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
2589  return false;
2590  case RISCV::PseudoLW:
2591  emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
2592  return false;
2593  case RISCV::PseudoLWU:
2594  emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
2595  return false;
2596  case RISCV::PseudoLD:
2597  emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
2598  return false;
2599  case RISCV::PseudoFLH:
2600  emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
2601  return false;
2602  case RISCV::PseudoFLW:
2603  emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
2604  return false;
2605  case RISCV::PseudoFLD:
2606  emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
2607  return false;
2608  case RISCV::PseudoSB:
2609  emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
2610  return false;
2611  case RISCV::PseudoSH:
2612  emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
2613  return false;
2614  case RISCV::PseudoSW:
2615  emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
2616  return false;
2617  case RISCV::PseudoSD:
2618  emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
2619  return false;
2620  case RISCV::PseudoFSH:
2621  emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
2622  return false;
2623  case RISCV::PseudoFSW:
2624  emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
2625  return false;
2626  case RISCV::PseudoFSD:
2627  emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
2628  return false;
2629  case RISCV::PseudoAddTPRel:
2630  if (checkPseudoAddTPRel(Inst, Operands))
2631  return true;
2632  break;
2633  case RISCV::PseudoSEXT_B:
2634  emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
2635  return false;
2636  case RISCV::PseudoSEXT_H:
2637  emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
2638  return false;
2639  case RISCV::PseudoZEXT_H:
2640  emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
2641  return false;
2642  case RISCV::PseudoZEXT_W:
2643  emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
2644  return false;
2645  case RISCV::PseudoVMSGEU_VX:
2646  case RISCV::PseudoVMSGEU_VX_M:
2647  case RISCV::PseudoVMSGEU_VX_M_T:
2648  emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
2649  return false;
2650  case RISCV::PseudoVMSGE_VX:
2651  case RISCV::PseudoVMSGE_VX_M:
2652  case RISCV::PseudoVMSGE_VX_M_T:
2653  emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
2654  return false;
2655  case RISCV::PseudoVMSGE_VI:
2656  case RISCV::PseudoVMSLT_VI: {
2657  // These instructions are signed and so is immediate so we can subtract one
2658  // and change the opcode.
2659  int64_t Imm = Inst.getOperand(2).getImm();
2660  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
2661  : RISCV::VMSLE_VI;
2662  emitToStreamer(Out, MCInstBuilder(Opc)
2663  .addOperand(Inst.getOperand(0))
2664  .addOperand(Inst.getOperand(1))
2665  .addImm(Imm - 1)
2666  .addOperand(Inst.getOperand(3)));
2667  return false;
2668  }
2669  case RISCV::PseudoVMSGEU_VI:
2670  case RISCV::PseudoVMSLTU_VI: {
2671  int64_t Imm = Inst.getOperand(2).getImm();
2672  // Unsigned comparisons are tricky because the immediate is signed. If the
2673  // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
2674  // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
2675  // vmsne v0, v1, v1 which is always false.
2676  if (Imm == 0) {
2677  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2678  ? RISCV::VMSEQ_VV
2679  : RISCV::VMSNE_VV;
2680  emitToStreamer(Out, MCInstBuilder(Opc)
2681  .addOperand(Inst.getOperand(0))
2682  .addOperand(Inst.getOperand(1))
2683  .addOperand(Inst.getOperand(1))
2684  .addOperand(Inst.getOperand(3)));
2685  } else {
2686  // Other immediate values can subtract one like signed.
2687  unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2688  ? RISCV::VMSGTU_VI
2689  : RISCV::VMSLEU_VI;
2690  emitToStreamer(Out, MCInstBuilder(Opc)
2691  .addOperand(Inst.getOperand(0))
2692  .addOperand(Inst.getOperand(1))
2693  .addImm(Imm - 1)
2694  .addOperand(Inst.getOperand(3)));
2695  }
2696 
2697  return false;
2698  }
2699  }
2700 
2701  emitToStreamer(Out, Inst);
2702  return false;
2703 }
2704 
2705 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
2706  RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
2707  RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
2708 }
llvm::MCTargetStreamer::getStreamer
MCStreamer & getStreamer()
Definition: MCStreamer.h:99
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
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
type
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
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:24
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:1168
Statistic.h
MCParsedAsmOperand.h
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:233
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:3817
llvm::FeatureBitset
Container class for subtarget features.
Definition: SubtargetFeature.h:40
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
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:635
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:216
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:56
p
the resulting code requires compare and branches when and if * p
Definition: README.txt:396
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:197
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:420
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
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:53
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
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
following
This is equivalent to the following
Definition: README.txt:671
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:194
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:349
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::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:75
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:140
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
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:314
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:403
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
Invalid
@ Invalid
Definition: AArch64ISelLowering.cpp:8134
llvm::RISCVMCExpr::VK_RISCV_CALL
@ VK_RISCV_CALL
Definition: RISCVMCExpr.h:37
SmallVector.h
llvm::MCStreamer::getTargetStreamer
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:285
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:189
llvm::RISCVMCExpr::VK_RISCV_CALL_PLT
@ VK_RISCV_CALL_PLT
Definition: RISCVMCExpr.h:38
d
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 int d
Definition: README.txt:418
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:75
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:580
llvm::MCRegister
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:23