Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LanaiAsmParser.cpp - Parse Lanai 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
9
#include "LanaiAluCode.h"
10
#include "LanaiCondCode.h"
11
#include "LanaiInstrInfo.h"
12
#include "MCTargetDesc/LanaiMCExpr.h"
13
#include "TargetInfo/LanaiTargetInfo.h"
14
#include "llvm/ADT/STLExtras.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/ADT/StringSwitch.h"
17
#include "llvm/MC/MCContext.h"
18
#include "llvm/MC/MCExpr.h"
19
#include "llvm/MC/MCInst.h"
20
#include "llvm/MC/MCParser/MCAsmLexer.h"
21
#include "llvm/MC/MCParser/MCAsmParser.h"
22
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
24
#include "llvm/MC/MCStreamer.h"
25
#include "llvm/MC/MCSubtargetInfo.h"
26
#include "llvm/MC/MCSymbol.h"
27
#include "llvm/MC/TargetRegistry.h"
28
#include "llvm/Support/Casting.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/MathExtras.h"
31
#include "llvm/Support/SMLoc.h"
32
#include "llvm/Support/raw_ostream.h"
33
#include <algorithm>
34
#include <cassert>
35
#include <cstddef>
36
#include <cstdint>
37
#include <memory>
38
#include <optional>
39
40
using namespace llvm;
41
42
// Auto-generated by TableGen
43
static unsigned MatchRegisterName(StringRef Name);
44
45
namespace {
46
47
struct LanaiOperand;
48
49
class LanaiAsmParser : public MCTargetAsmParser {
50
  // Parse operands
51
  std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);
52
53
  std::unique_ptr<LanaiOperand> parseImmediate();
54
55
  std::unique_ptr<LanaiOperand> parseIdentifier();
56
57
  unsigned parseAluOperator(bool PreOp, bool PostOp);
58
59
  // Split the mnemonic stripping conditional code and quantifiers
60
  StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
61
                          OperandVector *Operands);
62
63
  bool parsePrePost(StringRef Type, int *OffsetValue);
64
65
  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66
                        SMLoc NameLoc, OperandVector &Operands) override;
67
68
  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
69
  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
70
                               SMLoc &EndLoc) override;
71
72
  bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
73
                               OperandVector &Operands, MCStreamer &Out,
74
                               uint64_t &ErrorInfo,
75
                               bool MatchingInlineAsm) override;
76
77
// Auto-generated instruction matching functions
78
#define GET_ASSEMBLER_HEADER
79
#include "LanaiGenAsmMatcher.inc"
80
81
  ParseStatus parseOperand(OperandVector *Operands, StringRef Mnemonic);
82
83
  ParseStatus parseMemoryOperand(OperandVector &Operands);
84
85
public:
86
  LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
87
                 const MCInstrInfo &MII, const MCTargetOptions &Options)
88
      : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
89
0
        Lexer(Parser.getLexer()), SubtargetInfo(STI) {
90
0
    setAvailableFeatures(
91
0
        ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92
0
  }
93
94
private:
95
  MCAsmParser &Parser;
96
  MCAsmLexer &Lexer;
97
98
  const MCSubtargetInfo &SubtargetInfo;
99
};
100
101
// LanaiOperand - Instances of this class represented a parsed machine
102
// instruction
103
struct LanaiOperand : public MCParsedAsmOperand {
104
  enum KindTy {
105
    TOKEN,
106
    REGISTER,
107
    IMMEDIATE,
108
    MEMORY_IMM,
109
    MEMORY_REG_IMM,
110
    MEMORY_REG_REG,
111
  } Kind;
112
113
  SMLoc StartLoc, EndLoc;
114
115
  struct Token {
116
    const char *Data;
117
    unsigned Length;
118
  };
119
120
  struct RegOp {
121
    unsigned RegNum;
122
  };
123
124
  struct ImmOp {
125
    const MCExpr *Value;
126
  };
127
128
  struct MemOp {
129
    unsigned BaseReg;
130
    unsigned OffsetReg;
131
    unsigned AluOp;
132
    const MCExpr *Offset;
133
  };
134
135
  union {
136
    struct Token Tok;
137
    struct RegOp Reg;
138
    struct ImmOp Imm;
139
    struct MemOp Mem;
140
  };
141
142
0
  explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}
143
144
public:
145
  // The functions below are used by the autogenerated ASM matcher and hence to
146
  // be of the form expected.
147
148
  // getStartLoc - Gets location of the first token of this operand
149
0
  SMLoc getStartLoc() const override { return StartLoc; }
150
151
  // getEndLoc - Gets location of the last token of this operand
152
0
  SMLoc getEndLoc() const override { return EndLoc; }
153
154
0
  unsigned getReg() const override {
155
0
    assert(isReg() && "Invalid type access!");
156
0
    return Reg.RegNum;
157
0
  }
158
159
0
  const MCExpr *getImm() const {
160
0
    assert(isImm() && "Invalid type access!");
161
0
    return Imm.Value;
162
0
  }
163
164
0
  StringRef getToken() const {
165
0
    assert(isToken() && "Invalid type access!");
166
0
    return StringRef(Tok.Data, Tok.Length);
167
0
  }
168
169
0
  unsigned getMemBaseReg() const {
170
0
    assert(isMem() && "Invalid type access!");
171
0
    return Mem.BaseReg;
172
0
  }
173
174
0
  unsigned getMemOffsetReg() const {
175
0
    assert(isMem() && "Invalid type access!");
176
0
    return Mem.OffsetReg;
177
0
  }
178
179
0
  const MCExpr *getMemOffset() const {
180
0
    assert(isMem() && "Invalid type access!");
181
0
    return Mem.Offset;
182
0
  }
183
184
0
  unsigned getMemOp() const {
185
0
    assert(isMem() && "Invalid type access!");
186
0
    return Mem.AluOp;
187
0
  }
188
189
  // Functions for testing operand type
190
0
  bool isReg() const override { return Kind == REGISTER; }
191
192
0
  bool isImm() const override { return Kind == IMMEDIATE; }
193
194
0
  bool isMem() const override {
195
0
    return isMemImm() || isMemRegImm() || isMemRegReg();
196
0
  }
197
198
0
  bool isMemImm() const { return Kind == MEMORY_IMM; }
199
200
0
  bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
201
202
0
  bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
203
204
0
  bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
205
206
0
  bool isToken() const override { return Kind == TOKEN; }
207
208
0
  bool isBrImm() {
209
0
    if (!isImm())
210
0
      return false;
211
212
    // Constant case
213
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
214
0
    if (!MCE)
215
0
      return true;
216
0
    int64_t Value = MCE->getValue();
217
    // Check if value fits in 25 bits with 2 least significant bits 0.
218
0
    return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
219
0
  }
220
221
0
  bool isBrTarget() { return isBrImm() || isToken(); }
222
223
0
  bool isCallTarget() { return isImm() || isToken(); }
224
225
0
  bool isHiImm16() {
226
0
    if (!isImm())
227
0
      return false;
228
229
    // Constant case
230
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
231
0
      int64_t Value = ConstExpr->getValue();
232
0
      return Value != 0 && isShiftedUInt<16, 16>(Value);
233
0
    }
234
235
    // Symbolic reference expression
236
0
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237
0
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238
239
    // Binary expression
240
0
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
241
0
      if (const LanaiMCExpr *SymbolRefExpr =
242
0
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
243
0
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
244
245
0
    return false;
246
0
  }
247
248
0
  bool isHiImm16And() {
249
0
    if (!isImm())
250
0
      return false;
251
252
0
    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
253
0
    if (ConstExpr) {
254
0
      int64_t Value = ConstExpr->getValue();
255
      // Check if in the form 0xXYZWffff
256
0
      return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
257
0
    }
258
0
    return false;
259
0
  }
260
261
0
  bool isLoImm16() {
262
0
    if (!isImm())
263
0
      return false;
264
265
    // Constant case
266
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
267
0
      int64_t Value = ConstExpr->getValue();
268
      // Check if value fits in 16 bits
269
0
      return isUInt<16>(static_cast<int32_t>(Value));
270
0
    }
271
272
    // Symbolic reference expression
273
0
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274
0
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275
276
    // Binary expression
277
0
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
278
0
      if (const LanaiMCExpr *SymbolRefExpr =
279
0
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
280
0
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
281
282
0
    return false;
283
0
  }
284
285
0
  bool isLoImm16Signed() {
286
0
    if (!isImm())
287
0
      return false;
288
289
    // Constant case
290
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
291
0
      int64_t Value = ConstExpr->getValue();
292
      // Check if value fits in 16 bits or value of the form 0xffffxyzw
293
0
      return isInt<16>(static_cast<int32_t>(Value));
294
0
    }
295
296
    // Symbolic reference expression
297
0
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298
0
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299
300
    // Binary expression
301
0
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
302
0
      if (const LanaiMCExpr *SymbolRefExpr =
303
0
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
304
0
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
305
306
0
    return false;
307
0
  }
308
309
0
  bool isLoImm16And() {
310
0
    if (!isImm())
311
0
      return false;
312
313
0
    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
314
0
    if (ConstExpr) {
315
0
      int64_t Value = ConstExpr->getValue();
316
      // Check if in the form 0xffffXYZW
317
0
      return ((Value & ~0xffff) == 0xffff0000);
318
0
    }
319
0
    return false;
320
0
  }
321
322
0
  bool isImmShift() {
323
0
    if (!isImm())
324
0
      return false;
325
326
0
    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
327
0
    if (!ConstExpr)
328
0
      return false;
329
0
    int64_t Value = ConstExpr->getValue();
330
0
    return (Value >= -31) && (Value <= 31);
331
0
  }
332
333
0
  bool isLoImm21() {
334
0
    if (!isImm())
335
0
      return false;
336
337
    // Constant case
338
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
339
0
      int64_t Value = ConstExpr->getValue();
340
0
      return isUInt<21>(Value);
341
0
    }
342
343
    // Symbolic reference expression
344
0
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
345
0
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
346
0
    if (const MCSymbolRefExpr *SymbolRefExpr =
347
0
            dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
348
0
      return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349
0
    }
350
351
    // Binary expression
352
0
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
353
0
      if (const LanaiMCExpr *SymbolRefExpr =
354
0
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
355
0
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
356
0
      if (const MCSymbolRefExpr *SymbolRefExpr =
357
0
              dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
358
0
        return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
359
0
    }
360
361
0
    return false;
362
0
  }
363
364
0
  bool isImm10() {
365
0
    if (!isImm())
366
0
      return false;
367
368
0
    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
369
0
    if (!ConstExpr)
370
0
      return false;
371
0
    int64_t Value = ConstExpr->getValue();
372
0
    return isInt<10>(Value);
373
0
  }
374
375
0
  bool isCondCode() {
376
0
    if (!isImm())
377
0
      return false;
378
379
0
    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
380
0
    if (!ConstExpr)
381
0
      return false;
382
0
    uint64_t Value = ConstExpr->getValue();
383
    // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
384
    // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
385
    // value corresponds to a valid condition code.
386
0
    return Value < LPCC::UNKNOWN;
387
0
  }
388
389
0
  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
390
    // Add as immediates where possible. Null MCExpr = 0
391
0
    if (Expr == nullptr)
392
0
      Inst.addOperand(MCOperand::createImm(0));
393
0
    else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
394
0
      Inst.addOperand(
395
0
          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
396
0
    else
397
0
      Inst.addOperand(MCOperand::createExpr(Expr));
398
0
  }
399
400
0
  void addRegOperands(MCInst &Inst, unsigned N) const {
401
0
    assert(N == 1 && "Invalid number of operands!");
402
0
    Inst.addOperand(MCOperand::createReg(getReg()));
403
0
  }
404
405
0
  void addImmOperands(MCInst &Inst, unsigned N) const {
406
0
    assert(N == 1 && "Invalid number of operands!");
407
0
    addExpr(Inst, getImm());
408
0
  }
409
410
0
  void addBrTargetOperands(MCInst &Inst, unsigned N) const {
411
0
    assert(N == 1 && "Invalid number of operands!");
412
0
    addExpr(Inst, getImm());
413
0
  }
414
415
0
  void addCallTargetOperands(MCInst &Inst, unsigned N) const {
416
0
    assert(N == 1 && "Invalid number of operands!");
417
0
    addExpr(Inst, getImm());
418
0
  }
419
420
0
  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
421
0
    assert(N == 1 && "Invalid number of operands!");
422
0
    addExpr(Inst, getImm());
423
0
  }
424
425
0
  void addMemImmOperands(MCInst &Inst, unsigned N) const {
426
0
    assert(N == 1 && "Invalid number of operands!");
427
0
    const MCExpr *Expr = getMemOffset();
428
0
    addExpr(Inst, Expr);
429
0
  }
430
431
0
  void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
432
0
    assert(N == 3 && "Invalid number of operands!");
433
0
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
434
0
    const MCExpr *Expr = getMemOffset();
435
0
    addExpr(Inst, Expr);
436
0
    Inst.addOperand(MCOperand::createImm(getMemOp()));
437
0
  }
438
439
0
  void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
440
0
    assert(N == 3 && "Invalid number of operands!");
441
0
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
442
0
    assert(getMemOffsetReg() != 0 && "Invalid offset");
443
0
    Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
444
0
    Inst.addOperand(MCOperand::createImm(getMemOp()));
445
0
  }
446
447
0
  void addMemSplsOperands(MCInst &Inst, unsigned N) const {
448
0
    if (isMemRegImm())
449
0
      addMemRegImmOperands(Inst, N);
450
0
    if (isMemRegReg())
451
0
      addMemRegRegOperands(Inst, N);
452
0
  }
453
454
0
  void addImmShiftOperands(MCInst &Inst, unsigned N) const {
455
0
    assert(N == 1 && "Invalid number of operands!");
456
0
    addExpr(Inst, getImm());
457
0
  }
458
459
0
  void addImm10Operands(MCInst &Inst, unsigned N) const {
460
0
    assert(N == 1 && "Invalid number of operands!");
461
0
    addExpr(Inst, getImm());
462
0
  }
463
464
0
  void addLoImm16Operands(MCInst &Inst, unsigned N) const {
465
0
    assert(N == 1 && "Invalid number of operands!");
466
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
467
0
      Inst.addOperand(
468
0
          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
469
0
    else if (isa<LanaiMCExpr>(getImm())) {
470
0
#ifndef NDEBUG
471
0
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
472
0
      assert(SymbolRefExpr &&
473
0
             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
474
0
#endif
475
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
476
0
    } else if (isa<MCBinaryExpr>(getImm())) {
477
0
#ifndef NDEBUG
478
0
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
479
0
      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
480
0
             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
481
0
                 LanaiMCExpr::VK_Lanai_ABS_LO);
482
0
#endif
483
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
484
0
    } else
485
0
      assert(false && "Operand type not supported.");
486
0
  }
487
488
0
  void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
489
0
    assert(N == 1 && "Invalid number of operands!");
490
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
491
0
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
492
0
    else
493
0
      assert(false && "Operand type not supported.");
494
0
  }
495
496
0
  void addHiImm16Operands(MCInst &Inst, unsigned N) const {
497
0
    assert(N == 1 && "Invalid number of operands!");
498
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
499
0
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
500
0
    else if (isa<LanaiMCExpr>(getImm())) {
501
0
#ifndef NDEBUG
502
0
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
503
0
      assert(SymbolRefExpr &&
504
0
             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
505
0
#endif
506
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
507
0
    } else if (isa<MCBinaryExpr>(getImm())) {
508
0
#ifndef NDEBUG
509
0
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
510
0
      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
511
0
             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
512
0
                 LanaiMCExpr::VK_Lanai_ABS_HI);
513
0
#endif
514
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
515
0
    } else
516
0
      assert(false && "Operand type not supported.");
517
0
  }
518
519
0
  void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
520
0
    assert(N == 1 && "Invalid number of operands!");
521
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
522
0
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
523
0
    else
524
0
      assert(false && "Operand type not supported.");
525
0
  }
526
527
0
  void addLoImm21Operands(MCInst &Inst, unsigned N) const {
528
0
    assert(N == 1 && "Invalid number of operands!");
529
0
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
530
0
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
531
0
    else if (isa<LanaiMCExpr>(getImm())) {
532
0
#ifndef NDEBUG
533
0
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
534
0
      assert(SymbolRefExpr &&
535
0
             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536
0
#endif
537
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
538
0
    } else if (isa<MCSymbolRefExpr>(getImm())) {
539
0
#ifndef NDEBUG
540
0
      const MCSymbolRefExpr *SymbolRefExpr =
541
0
          dyn_cast<MCSymbolRefExpr>(getImm());
542
0
      assert(SymbolRefExpr &&
543
0
             SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
544
0
#endif
545
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
546
0
    } else if (isa<MCBinaryExpr>(getImm())) {
547
0
#ifndef NDEBUG
548
0
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
549
0
      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
550
0
             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
551
0
                 LanaiMCExpr::VK_Lanai_None);
552
0
#endif
553
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
554
0
    } else
555
0
      assert(false && "Operand type not supported.");
556
0
  }
557
558
0
  void print(raw_ostream &OS) const override {
559
0
    switch (Kind) {
560
0
    case IMMEDIATE:
561
0
      OS << "Imm: " << getImm() << "\n";
562
0
      break;
563
0
    case TOKEN:
564
0
      OS << "Token: " << getToken() << "\n";
565
0
      break;
566
0
    case REGISTER:
567
0
      OS << "Reg: %r" << getReg() << "\n";
568
0
      break;
569
0
    case MEMORY_IMM:
570
0
      OS << "MemImm: " << *getMemOffset() << "\n";
571
0
      break;
572
0
    case MEMORY_REG_IMM:
573
0
      OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
574
0
      break;
575
0
    case MEMORY_REG_REG:
576
0
      assert(getMemOffset() == nullptr);
577
0
      OS << "MemRegReg: " << getMemBaseReg() << "+"
578
0
         << "%r" << getMemOffsetReg() << "\n";
579
0
      break;
580
0
    }
581
0
  }
582
583
0
  static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
584
0
    auto Op = std::make_unique<LanaiOperand>(TOKEN);
585
0
    Op->Tok.Data = Str.data();
586
0
    Op->Tok.Length = Str.size();
587
0
    Op->StartLoc = Start;
588
0
    Op->EndLoc = Start;
589
0
    return Op;
590
0
  }
591
592
  static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
593
0
                                                 SMLoc End) {
594
0
    auto Op = std::make_unique<LanaiOperand>(REGISTER);
595
0
    Op->Reg.RegNum = RegNum;
596
0
    Op->StartLoc = Start;
597
0
    Op->EndLoc = End;
598
0
    return Op;
599
0
  }
600
601
  static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
602
0
                                                 SMLoc Start, SMLoc End) {
603
0
    auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
604
0
    Op->Imm.Value = Value;
605
0
    Op->StartLoc = Start;
606
0
    Op->EndLoc = End;
607
0
    return Op;
608
0
  }
609
610
  static std::unique_ptr<LanaiOperand>
611
0
  MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
612
0
    const MCExpr *Imm = Op->getImm();
613
0
    Op->Kind = MEMORY_IMM;
614
0
    Op->Mem.BaseReg = 0;
615
0
    Op->Mem.AluOp = LPAC::ADD;
616
0
    Op->Mem.OffsetReg = 0;
617
0
    Op->Mem.Offset = Imm;
618
0
    return Op;
619
0
  }
620
621
  static std::unique_ptr<LanaiOperand>
622
  MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
623
0
                   unsigned AluOp) {
624
0
    unsigned OffsetReg = Op->getReg();
625
0
    Op->Kind = MEMORY_REG_REG;
626
0
    Op->Mem.BaseReg = BaseReg;
627
0
    Op->Mem.AluOp = AluOp;
628
0
    Op->Mem.OffsetReg = OffsetReg;
629
0
    Op->Mem.Offset = nullptr;
630
0
    return Op;
631
0
  }
632
633
  static std::unique_ptr<LanaiOperand>
634
  MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
635
0
                   unsigned AluOp) {
636
0
    const MCExpr *Imm = Op->getImm();
637
0
    Op->Kind = MEMORY_REG_IMM;
638
0
    Op->Mem.BaseReg = BaseReg;
639
0
    Op->Mem.AluOp = AluOp;
640
0
    Op->Mem.OffsetReg = 0;
641
0
    Op->Mem.Offset = Imm;
642
0
    return Op;
643
0
  }
644
};
645
646
} // end anonymous namespace
647
648
bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
649
                                             OperandVector &Operands,
650
                                             MCStreamer &Out,
651
                                             uint64_t &ErrorInfo,
652
0
                                             bool MatchingInlineAsm) {
653
0
  MCInst Inst;
654
0
  SMLoc ErrorLoc;
655
656
0
  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
657
0
  case Match_Success:
658
0
    Out.emitInstruction(Inst, SubtargetInfo);
659
0
    Opcode = Inst.getOpcode();
660
0
    return false;
661
0
  case Match_MissingFeature:
662
0
    return Error(IdLoc, "Instruction use requires option to be enabled");
663
0
  case Match_MnemonicFail:
664
0
    return Error(IdLoc, "Unrecognized instruction mnemonic");
665
0
  case Match_InvalidOperand: {
666
0
    ErrorLoc = IdLoc;
667
0
    if (ErrorInfo != ~0U) {
668
0
      if (ErrorInfo >= Operands.size())
669
0
        return Error(IdLoc, "Too few operands for instruction");
670
671
0
      ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
672
0
      if (ErrorLoc == SMLoc())
673
0
        ErrorLoc = IdLoc;
674
0
    }
675
0
    return Error(ErrorLoc, "Invalid operand for instruction");
676
0
  }
677
0
  default:
678
0
    break;
679
0
  }
680
681
0
  llvm_unreachable("Unknown match type detected!");
682
0
}
683
684
// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
685
// backwards compatible with GCC and the different ways inline assembly is
686
// handled.
687
// TODO: see if there isn't a better way to do this.
688
std::unique_ptr<LanaiOperand>
689
0
LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
690
0
  SMLoc Start = Parser.getTok().getLoc();
691
0
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
692
0
  std::optional<AsmToken> PercentTok;
693
694
0
  unsigned RegNum;
695
  // Eat the '%'.
696
0
  if (Lexer.getKind() == AsmToken::Percent) {
697
0
    PercentTok = Parser.getTok();
698
0
    Parser.Lex();
699
0
  }
700
0
  if (Lexer.getKind() == AsmToken::Identifier) {
701
0
    RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
702
0
    if (RegNum == 0) {
703
0
      if (PercentTok && RestoreOnFailure)
704
0
        Lexer.UnLex(*PercentTok);
705
0
      return nullptr;
706
0
    }
707
0
    Parser.Lex(); // Eat identifier token
708
0
    return LanaiOperand::createReg(RegNum, Start, End);
709
0
  }
710
0
  if (PercentTok && RestoreOnFailure)
711
0
    Lexer.UnLex(*PercentTok);
712
0
  return nullptr;
713
0
}
714
715
bool LanaiAsmParser::parseRegister(MCRegister &RegNum, SMLoc &StartLoc,
716
0
                                   SMLoc &EndLoc) {
717
0
  const AsmToken &Tok = getParser().getTok();
718
0
  StartLoc = Tok.getLoc();
719
0
  EndLoc = Tok.getEndLoc();
720
0
  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);
721
0
  if (Op != nullptr)
722
0
    RegNum = Op->getReg();
723
0
  return (Op == nullptr);
724
0
}
725
726
ParseStatus LanaiAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
727
0
                                             SMLoc &EndLoc) {
728
0
  const AsmToken &Tok = getParser().getTok();
729
0
  StartLoc = Tok.getLoc();
730
0
  EndLoc = Tok.getEndLoc();
731
0
  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
732
0
  if (Op == nullptr)
733
0
    return ParseStatus::NoMatch;
734
0
  Reg = Op->getReg();
735
0
  return ParseStatus::Success;
736
0
}
737
738
0
std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
739
0
  SMLoc Start = Parser.getTok().getLoc();
740
0
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
741
0
  const MCExpr *Res, *RHS = nullptr;
742
0
  LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
743
744
0
  if (Lexer.getKind() != AsmToken::Identifier)
745
0
    return nullptr;
746
747
0
  StringRef Identifier;
748
0
  if (Parser.parseIdentifier(Identifier))
749
0
    return nullptr;
750
751
  // Check if identifier has a modifier
752
0
  if (Identifier.equals_insensitive("hi"))
753
0
    Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
754
0
  else if (Identifier.equals_insensitive("lo"))
755
0
    Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
756
757
  // If the identifier corresponds to a variant then extract the real
758
  // identifier.
759
0
  if (Kind != LanaiMCExpr::VK_Lanai_None) {
760
0
    if (Lexer.getKind() != AsmToken::LParen) {
761
0
      Error(Lexer.getLoc(), "Expected '('");
762
0
      return nullptr;
763
0
    }
764
0
    Lexer.Lex(); // lex '('
765
766
    // Parse identifier
767
0
    if (Parser.parseIdentifier(Identifier))
768
0
      return nullptr;
769
0
  }
770
771
  // If addition parse the RHS.
772
0
  if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
773
0
    return nullptr;
774
775
  // For variants parse the final ')'
776
0
  if (Kind != LanaiMCExpr::VK_Lanai_None) {
777
0
    if (Lexer.getKind() != AsmToken::RParen) {
778
0
      Error(Lexer.getLoc(), "Expected ')'");
779
0
      return nullptr;
780
0
    }
781
0
    Lexer.Lex(); // lex ')'
782
0
  }
783
784
0
  End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
785
0
  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
786
0
  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
787
0
  Res = LanaiMCExpr::create(Kind, Expr, getContext());
788
789
  // Nest if this was an addition
790
0
  if (RHS)
791
0
    Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
792
793
0
  return LanaiOperand::createImm(Res, Start, End);
794
0
}
795
796
0
std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
797
0
  SMLoc Start = Parser.getTok().getLoc();
798
0
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
799
800
0
  const MCExpr *ExprVal;
801
0
  switch (Lexer.getKind()) {
802
0
  case AsmToken::Identifier:
803
0
    return parseIdentifier();
804
0
  case AsmToken::Plus:
805
0
  case AsmToken::Minus:
806
0
  case AsmToken::Integer:
807
0
  case AsmToken::Dot:
808
0
    if (!Parser.parseExpression(ExprVal))
809
0
      return LanaiOperand::createImm(ExprVal, Start, End);
810
0
    [[fallthrough]];
811
0
  default:
812
0
    return nullptr;
813
0
  }
814
0
}
815
816
0
static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
817
0
  if (PreOp)
818
0
    return LPAC::makePreOp(AluCode);
819
0
  if (PostOp)
820
0
    return LPAC::makePostOp(AluCode);
821
0
  return AluCode;
822
0
}
823
824
0
unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
825
0
  StringRef IdString;
826
0
  Parser.parseIdentifier(IdString);
827
0
  unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
828
0
  if (AluCode == LPAC::UNKNOWN) {
829
0
    Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
830
0
    return 0;
831
0
  }
832
0
  return AluCode;
833
0
}
834
835
0
static int SizeForSuffix(StringRef T) {
836
0
  return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
837
0
}
838
839
0
bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
840
0
  bool PreOrPost = false;
841
0
  if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
842
0
    PreOrPost = true;
843
0
    if (Lexer.is(AsmToken::Minus))
844
0
      *OffsetValue = -SizeForSuffix(Type);
845
0
    else if (Lexer.is(AsmToken::Plus))
846
0
      *OffsetValue = SizeForSuffix(Type);
847
0
    else
848
0
      return false;
849
850
    // Eat the '-' '-' or '+' '+'
851
0
    Parser.Lex();
852
0
    Parser.Lex();
853
0
  } else if (Lexer.is(AsmToken::Star)) {
854
0
    Parser.Lex(); // Eat the '*'
855
0
    PreOrPost = true;
856
0
  }
857
858
0
  return PreOrPost;
859
0
}
860
861
0
bool shouldBeSls(const LanaiOperand &Op) {
862
  // The instruction should be encoded as an SLS if the constant is word
863
  // aligned and will fit in 21 bits
864
0
  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
865
0
    int64_t Value = ConstExpr->getValue();
866
0
    return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
867
0
  }
868
  // The instruction should be encoded as an SLS if the operand is a symbolic
869
  // reference with no variant.
870
0
  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
871
0
    return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
872
  // The instruction should be encoded as an SLS if the operand is a binary
873
  // expression with the left-hand side being a symbolic reference with no
874
  // variant.
875
0
  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
876
0
    const LanaiMCExpr *LHSSymbolRefExpr =
877
0
        dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
878
0
    return (LHSSymbolRefExpr &&
879
0
            LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
880
0
  }
881
0
  return false;
882
0
}
883
884
// Matches memory operand. Returns true if error encountered.
885
0
ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
886
  // Try to match a memory operand.
887
  // The memory operands are of the form:
888
  //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or
889
  //                            ^
890
  //  (2)  '[' '*'? Register '*'? AluOperator Register ']'
891
  //      ^
892
  //  (3)  '[' '--'|'++' Register '--'|'++' ']'
893
  //
894
  //  (4) '[' Immediate ']' (for SLS)
895
896
  // Store the type for use in parsing pre/post increment/decrement operators
897
0
  StringRef Type;
898
0
  if (Operands[0]->isToken())
899
0
    Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
900
901
  // Use 0 if no offset given
902
0
  int OffsetValue = 0;
903
0
  unsigned BaseReg = 0;
904
0
  unsigned AluOp = LPAC::ADD;
905
0
  bool PostOp = false, PreOp = false;
906
907
  // Try to parse the offset
908
0
  std::unique_ptr<LanaiOperand> Op = parseRegister();
909
0
  if (!Op)
910
0
    Op = parseImmediate();
911
912
  // Only continue if next token is '['
913
0
  if (Lexer.isNot(AsmToken::LBrac)) {
914
0
    if (!Op)
915
0
      return ParseStatus::NoMatch;
916
917
    // The start of this custom parsing overlaps with register/immediate so
918
    // consider this as a successful match of an operand of that type as the
919
    // token stream can't be rewound to allow them to match separately.
920
0
    Operands.push_back(std::move(Op));
921
0
    return ParseStatus::Success;
922
0
  }
923
924
0
  Parser.Lex(); // Eat the '['.
925
0
  std::unique_ptr<LanaiOperand> Offset = nullptr;
926
0
  if (Op)
927
0
    Offset.swap(Op);
928
929
  // Determine if a pre operation
930
0
  PreOp = parsePrePost(Type, &OffsetValue);
931
932
0
  Op = parseRegister();
933
0
  if (!Op) {
934
0
    if (!Offset) {
935
0
      if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
936
0
        Parser.Lex(); // Eat the ']'
937
938
        // Memory address operations aligned to word boundary are encoded as
939
        // SLS, the rest as RM.
940
0
        if (shouldBeSls(*Op)) {
941
0
          Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
942
0
        } else {
943
0
          if (!Op->isLoImm16Signed())
944
0
            return Error(Parser.getTok().getLoc(),
945
0
                         "Memory address is not word aligned and larger than "
946
0
                         "class RM can handle");
947
0
          Operands.push_back(LanaiOperand::MorphToMemRegImm(
948
0
              Lanai::R0, std::move(Op), LPAC::ADD));
949
0
        }
950
0
        return ParseStatus::Success;
951
0
      }
952
0
    }
953
954
0
    return Error(Parser.getTok().getLoc(),
955
0
                 "Unknown operand, expected register or immediate");
956
0
  }
957
0
  BaseReg = Op->getReg();
958
959
  // Determine if a post operation
960
0
  if (!PreOp)
961
0
    PostOp = parsePrePost(Type, &OffsetValue);
962
963
  // If ] match form (1) else match form (2)
964
0
  if (Lexer.is(AsmToken::RBrac)) {
965
0
    Parser.Lex(); // Eat the ']'.
966
0
    if (!Offset) {
967
0
      SMLoc Start = Parser.getTok().getLoc();
968
0
      SMLoc End =
969
0
          SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
970
0
      const MCConstantExpr *OffsetConstExpr =
971
0
          MCConstantExpr::create(OffsetValue, getContext());
972
0
      Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
973
0
    }
974
0
  } else {
975
0
    if (Offset || OffsetValue != 0)
976
0
      return Error(Parser.getTok().getLoc(), "Expected ']'");
977
978
    // Parse operator
979
0
    AluOp = parseAluOperator(PreOp, PostOp);
980
981
    // Second form requires offset register
982
0
    Offset = parseRegister();
983
0
    if (!BaseReg || Lexer.isNot(AsmToken::RBrac))
984
0
      return Error(Parser.getTok().getLoc(), "Expected ']'");
985
0
    Parser.Lex(); // Eat the ']'.
986
0
  }
987
988
  // First form has addition as operator. Add pre- or post-op indicator as
989
  // needed.
990
0
  AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
991
992
  // Ensure immediate offset is not too large
993
0
  if (Offset->isImm() && !Offset->isLoImm16Signed())
994
0
    return Error(Parser.getTok().getLoc(),
995
0
                 "Memory address is not word aligned and larger than class RM "
996
0
                 "can handle");
997
998
0
  Operands.push_back(
999
0
      Offset->isImm()
1000
0
          ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
1001
0
          : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1002
1003
0
  return ParseStatus::Success;
1004
0
}
1005
1006
// Looks at a token type and creates the relevant operand from this
1007
// information, adding to operands.
1008
// If operand was parsed, returns false, else true.
1009
ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,
1010
0
                                         StringRef Mnemonic) {
1011
  // Check if the current operand has a custom associated parser, if so, try to
1012
  // custom parse the operand, or fallback to the general approach.
1013
0
  ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);
1014
1015
0
  if (Result.isSuccess())
1016
0
    return Result;
1017
0
  if (Result.isFailure()) {
1018
0
    Parser.eatToEndOfStatement();
1019
0
    return Result;
1020
0
  }
1021
1022
  // Attempt to parse token as register
1023
0
  std::unique_ptr<LanaiOperand> Op = parseRegister();
1024
1025
  // Attempt to parse token as immediate
1026
0
  if (!Op)
1027
0
    Op = parseImmediate();
1028
1029
  // If the token could not be parsed then fail
1030
0
  if (!Op) {
1031
0
    Error(Parser.getTok().getLoc(), "Unknown operand");
1032
0
    Parser.eatToEndOfStatement();
1033
0
    return ParseStatus::Failure;
1034
0
  }
1035
1036
  // Push back parsed operand into list of operands
1037
0
  Operands->push_back(std::move(Op));
1038
1039
0
  return ParseStatus::Success;
1040
0
}
1041
1042
// Split the mnemonic into ASM operand, conditional code and instruction
1043
// qualifier (half-word, byte).
1044
StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1045
0
                                        OperandVector *Operands) {
1046
0
  size_t Next = Name.find('.');
1047
1048
0
  StringRef Mnemonic = Name;
1049
1050
0
  bool IsBRR = false;
1051
0
  if (Name.ends_with(".r")) {
1052
0
    Mnemonic = Name.substr(0, Name.size() - 2);
1053
0
    IsBRR = true;
1054
0
  }
1055
1056
  // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1057
0
  if (Mnemonic[0] == 'b' ||
1058
0
      (Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&
1059
0
       !Mnemonic.starts_with("st"))) {
1060
    // Parse instructions with a conditional code. For example, 'bne' is
1061
    // converted into two operands 'b' and 'ne'.
1062
0
    LPCC::CondCode CondCode =
1063
0
        LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1064
0
    if (CondCode != LPCC::UNKNOWN) {
1065
0
      Mnemonic = Mnemonic.slice(0, 1);
1066
0
      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1067
0
      Operands->push_back(LanaiOperand::createImm(
1068
0
          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1069
0
      if (IsBRR) {
1070
0
        Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1071
0
      }
1072
0
      return Mnemonic;
1073
0
    }
1074
0
  }
1075
1076
  // Parse other instructions with condition codes (RR instructions).
1077
  // We ignore .f here and assume they are flag-setting operations, not
1078
  // conditional codes (except for select instructions where flag-setting
1079
  // variants are not yet implemented).
1080
0
  if (Mnemonic.starts_with("sel") ||
1081
0
      (!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {
1082
0
    LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1083
0
    if (CondCode != LPCC::UNKNOWN) {
1084
0
      size_t Next = Mnemonic.rfind('.', Name.size());
1085
      // 'sel' doesn't use a predicate operand whose printer adds the period,
1086
      // but instead has the period as part of the identifier (i.e., 'sel.' is
1087
      // expected by the generated matcher). If the mnemonic starts with 'sel'
1088
      // then include the period as part of the mnemonic, else don't include it
1089
      // as part of the mnemonic.
1090
0
      if (Mnemonic.starts_with("sel")) {
1091
0
        Mnemonic = Mnemonic.substr(0, Next + 1);
1092
0
      } else {
1093
0
        Mnemonic = Mnemonic.substr(0, Next);
1094
0
      }
1095
0
      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1096
0
      Operands->push_back(LanaiOperand::createImm(
1097
0
          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1098
0
      return Mnemonic;
1099
0
    }
1100
0
  }
1101
1102
0
  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1103
0
  if (IsBRR) {
1104
0
    Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1105
0
  }
1106
1107
0
  return Mnemonic;
1108
0
}
1109
1110
0
static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1111
  // Detects if a memory operation has an erroneous base register modification.
1112
  // Memory operations are detected by matching the types of operands.
1113
  //
1114
  // TODO: This test is focussed on one specific instance (ld/st).
1115
  // Extend it to handle more cases or be more robust.
1116
0
  bool Modifies = false;
1117
1118
0
  int Offset = 0;
1119
1120
0
  if (Operands.size() < 5)
1121
0
    return false;
1122
0
  else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1123
0
           Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1124
0
    Offset = 0;
1125
0
  else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1126
0
           Operands[2]->isReg() && Operands[3]->isImm() &&
1127
0
           Operands[4]->isImm() && Operands[5]->isReg())
1128
0
    Offset = 1;
1129
0
  else
1130
0
    return false;
1131
1132
0
  int PossibleAluOpIdx = Offset + 3;
1133
0
  int PossibleBaseIdx = Offset + 1;
1134
0
  int PossibleDestIdx = Offset + 4;
1135
0
  if (LanaiOperand *PossibleAluOp =
1136
0
          static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1137
0
    if (PossibleAluOp->isImm())
1138
0
      if (const MCConstantExpr *ConstExpr =
1139
0
              dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1140
0
        Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1141
0
  return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1142
0
         Operands[PossibleDestIdx]->isReg() &&
1143
0
         Operands[PossibleBaseIdx]->getReg() ==
1144
0
             Operands[PossibleDestIdx]->getReg();
1145
0
}
1146
1147
0
static bool IsRegister(const MCParsedAsmOperand &op) {
1148
0
  return static_cast<const LanaiOperand &>(op).isReg();
1149
0
}
1150
1151
0
static bool MaybePredicatedInst(const OperandVector &Operands) {
1152
0
  if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1153
0
      !IsRegister(*Operands[2]))
1154
0
    return false;
1155
0
  return StringSwitch<bool>(
1156
0
             static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1157
0
      .StartsWith("addc", true)
1158
0
      .StartsWith("add", true)
1159
0
      .StartsWith("and", true)
1160
0
      .StartsWith("sh", true)
1161
0
      .StartsWith("subb", true)
1162
0
      .StartsWith("sub", true)
1163
0
      .StartsWith("or", true)
1164
0
      .StartsWith("xor", true)
1165
0
      .Default(false);
1166
0
}
1167
1168
bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1169
                                      StringRef Name, SMLoc NameLoc,
1170
0
                                      OperandVector &Operands) {
1171
  // First operand is token for instruction
1172
0
  StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1173
1174
  // If there are no more operands, then finish
1175
0
  if (Lexer.is(AsmToken::EndOfStatement))
1176
0
    return false;
1177
1178
  // Parse first operand
1179
0
  if (!parseOperand(&Operands, Mnemonic).isSuccess())
1180
0
    return true;
1181
1182
  // If it is a st instruction with one 1 operand then it is a "store true".
1183
  // Transform <"st"> to <"s">, <LPCC:ICC_T>
1184
0
  if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1185
0
      Operands.size() == 2) {
1186
0
    Operands.erase(Operands.begin(), Operands.begin() + 1);
1187
0
    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1188
0
    Operands.insert(Operands.begin() + 1,
1189
0
                    LanaiOperand::createImm(
1190
0
                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
1191
0
                        NameLoc, NameLoc));
1192
0
  }
1193
1194
  // If the instruction is a bt instruction with 1 operand (in assembly) then it
1195
  // is an unconditional branch instruction and the first two elements of
1196
  // operands need to be merged.
1197
0
  if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&
1198
0
      Operands.size() == 3) {
1199
0
    Operands.erase(Operands.begin(), Operands.begin() + 2);
1200
0
    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1201
0
  }
1202
1203
  // Parse until end of statement, consuming commas between operands
1204
0
  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1205
    // Consume comma token
1206
0
    Lex();
1207
1208
    // Parse next operand
1209
0
    if (!parseOperand(&Operands, Mnemonic).isSuccess())
1210
0
      return true;
1211
0
  }
1212
1213
0
  if (IsMemoryAssignmentError(Operands)) {
1214
0
    Error(Parser.getTok().getLoc(),
1215
0
          "the destination register can't equal the base register in an "
1216
0
          "instruction that modifies the base register.");
1217
0
    return true;
1218
0
  }
1219
1220
  // Insert always true operand for instruction that may be predicated but
1221
  // are not. Currently the autogenerated parser always expects a predicate.
1222
0
  if (MaybePredicatedInst(Operands)) {
1223
0
    Operands.insert(Operands.begin() + 1,
1224
0
                    LanaiOperand::createImm(
1225
0
                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
1226
0
                        NameLoc, NameLoc));
1227
0
  }
1228
1229
0
  return false;
1230
0
}
1231
1232
#define GET_REGISTER_MATCHER
1233
#define GET_MATCHER_IMPLEMENTATION
1234
#include "LanaiGenAsmMatcher.inc"
1235
1236
24
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() {
1237
24
  RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());
1238
24
}