Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- BPFAsmParser.cpp - Parse BPF 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 "MCTargetDesc/BPFMCTargetDesc.h"
10
#include "TargetInfo/BPFTargetInfo.h"
11
#include "llvm/ADT/STLExtras.h"
12
#include "llvm/ADT/StringSwitch.h"
13
#include "llvm/MC/MCContext.h"
14
#include "llvm/MC/MCExpr.h"
15
#include "llvm/MC/MCInst.h"
16
#include "llvm/MC/MCParser/MCAsmLexer.h"
17
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
19
#include "llvm/MC/MCRegisterInfo.h"
20
#include "llvm/MC/MCStreamer.h"
21
#include "llvm/MC/MCSubtargetInfo.h"
22
#include "llvm/Support/Casting.h"
23
#include "llvm/Support/TargetRegistry.h"
24
25
using namespace llvm;
26
27
namespace {
28
struct BPFOperand;
29
30
class BPFAsmParser : public MCTargetAsmParser {
31
32
954
  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
33
34
  bool PreMatchCheck(OperandVector &Operands);
35
36
  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
37
                               OperandVector &Operands, MCStreamer &Out,
38
                               uint64_t &ErrorInfo,
39
                               bool MatchingInlineAsm) override;
40
41
  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
42
43
  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
44
                        SMLoc NameLoc, OperandVector &Operands) override;
45
46
  bool ParseDirective(AsmToken DirectiveID) override;
47
48
  // "=" is used as assignment operator for assembly statment, so can't be used
49
  // for symbol assignment.
50
28
  bool equalIsAsmAssignment() override { return false; }
51
  // "*" is used for dereferencing memory that it will be the start of
52
  // statement.
53
7
  bool starIsStartOfStatement() override { return true; }
54
55
#define GET_ASSEMBLER_HEADER
56
#include "BPFGenAsmMatcher.inc"
57
58
  OperandMatchResultTy parseImmediate(OperandVector &Operands);
59
  OperandMatchResultTy parseRegister(OperandVector &Operands);
60
  OperandMatchResultTy parseOperandAsOperator(OperandVector &Operands);
61
62
public:
63
  enum BPFMatchResultTy {
64
    Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
65
#define GET_OPERAND_DIAGNOSTIC_TYPES
66
#include "BPFGenAsmMatcher.inc"
67
#undef GET_OPERAND_DIAGNOSTIC_TYPES
68
  };
69
70
  BPFAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
71
               const MCInstrInfo &MII, const MCTargetOptions &Options)
72
3
      : MCTargetAsmParser(Options, STI, MII) {
73
3
    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
74
3
  }
75
};
76
77
/// BPFOperand - Instances of this class represent a parsed machine
78
/// instruction
79
struct BPFOperand : public MCParsedAsmOperand {
80
81
  enum KindTy {
82
    Token,
83
    Register,
84
    Immediate,
85
  } Kind;
86
87
  struct RegOp {
88
    unsigned RegNum;
89
  };
90
91
  struct ImmOp {
92
    const MCExpr *Val;
93
  };
94
95
  SMLoc StartLoc, EndLoc;
96
  union {
97
    StringRef Tok;
98
    RegOp Reg;
99
    ImmOp Imm;
100
  };
101
102
774
  BPFOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
103
104
public:
105
0
  BPFOperand(const BPFOperand &o) : MCParsedAsmOperand() {
106
0
    Kind = o.Kind;
107
0
    StartLoc = o.StartLoc;
108
0
    EndLoc = o.EndLoc;
109
0
110
0
    switch (Kind) {
111
0
    case Register:
112
0
      Reg = o.Reg;
113
0
      break;
114
0
    case Immediate:
115
0
      Imm = o.Imm;
116
0
      break;
117
0
    case Token:
118
0
      Tok = o.Tok;
119
0
      break;
120
0
    }
121
0
  }
122
123
6.28k
  bool isToken() const override { return Kind == Token; }
124
3.70k
  bool isReg() const override { return Kind == Register; }
125
162
  bool isImm() const override { return Kind == Immediate; }
126
0
  bool isMem() const override { return false; }
127
128
0
  bool isConstantImm() const {
129
0
    return isImm() && isa<MCConstantExpr>(getImm());
130
0
  }
131
132
0
  int64_t getConstantImm() const {
133
0
    const MCExpr *Val = getImm();
134
0
    return static_cast<const MCConstantExpr *>(Val)->getValue();
135
0
  }
136
137
0
  bool isSImm12() const {
138
0
    return (isConstantImm() && isInt<12>(getConstantImm()));
139
0
  }
140
141
  /// getStartLoc - Gets location of the first token of this operand
142
0
  SMLoc getStartLoc() const override { return StartLoc; }
143
  /// getEndLoc - Gets location of the last token of this operand
144
0
  SMLoc getEndLoc() const override { return EndLoc; }
145
146
3.66k
  unsigned getReg() const override {
147
3.66k
    assert(Kind == Register && "Invalid type access!");
148
3.66k
    return Reg.RegNum;
149
3.66k
  }
150
151
110
  const MCExpr *getImm() const {
152
110
    assert(Kind == Immediate && "Invalid type access!");
153
110
    return Imm.Val;
154
110
  }
155
156
2.42k
  StringRef getToken() const {
157
2.42k
    assert(Kind == Token && "Invalid type access!");
158
2.42k
    return Tok;
159
2.42k
  }
160
161
  void print(raw_ostream &OS) const override {
162
    switch (Kind) {
163
    case Immediate:
164
      OS << *getImm();
165
      break;
166
    case Register:
167
      OS << "<register x";
168
      OS << getReg() << ">";
169
      break;
170
    case Token:
171
      OS << "'" << getToken() << "'";
172
      break;
173
    }
174
  }
175
176
110
  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
177
110
    assert(Expr && "Expr shouldn't be null!");
178
110
179
110
    if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
180
68
      Inst.addOperand(MCOperand::createImm(CE->getValue()));
181
42
    else
182
42
      Inst.addOperand(MCOperand::createExpr(Expr));
183
110
  }
184
185
  // Used by the TableGen Code
186
174
  void addRegOperands(MCInst &Inst, unsigned N) const {
187
174
    assert(N == 1 && "Invalid number of operands!");
188
174
    Inst.addOperand(MCOperand::createReg(getReg()));
189
174
  }
190
191
110
  void addImmOperands(MCInst &Inst, unsigned N) const {
192
110
    assert(N == 1 && "Invalid number of operands!");
193
110
    addExpr(Inst, getImm());
194
110
  }
195
196
479
  static std::unique_ptr<BPFOperand> createToken(StringRef Str, SMLoc S) {
197
479
    auto Op = make_unique<BPFOperand>(Token);
198
479
    Op->Tok = Str;
199
479
    Op->StartLoc = S;
200
479
    Op->EndLoc = S;
201
479
    return Op;
202
479
  }
203
204
  static std::unique_ptr<BPFOperand> createReg(unsigned RegNo, SMLoc S,
205
185
                                               SMLoc E) {
206
185
    auto Op = make_unique<BPFOperand>(Register);
207
185
    Op->Reg.RegNum = RegNo;
208
185
    Op->StartLoc = S;
209
185
    Op->EndLoc = E;
210
185
    return Op;
211
185
  }
212
213
  static std::unique_ptr<BPFOperand> createImm(const MCExpr *Val, SMLoc S,
214
110
                                               SMLoc E) {
215
110
    auto Op = make_unique<BPFOperand>(Immediate);
216
110
    Op->Imm.Val = Val;
217
110
    Op->StartLoc = S;
218
110
    Op->EndLoc = E;
219
110
    return Op;
220
110
  }
221
222
  // Identifiers that can be used at the start of a statment.
223
53
  static bool isValidIdAtStart(StringRef Name) {
224
53
    return StringSwitch<bool>(Name.lower())
225
53
        .Case("if", true)
226
53
        .Case("call", true)
227
53
        .Case("goto", true)
228
53
        .Case("*", true)
229
53
        .Case("exit", true)
230
53
        .Case("lock", true)
231
53
        .Case("ld_pseudo", true)
232
53
        .Default(false);
233
53
  }
234
235
  // Identifiers that can be used in the middle of a statment.
236
255
  static bool isValidIdInMiddle(StringRef Name) {
237
255
    return StringSwitch<bool>(Name.lower())
238
255
        .Case("u64", true)
239
255
        .Case("u32", true)
240
255
        .Case("u16", true)
241
255
        .Case("u8", true)
242
255
        .Case("be64", true)
243
255
        .Case("be32", true)
244
255
        .Case("be16", true)
245
255
        .Case("le64", true)
246
255
        .Case("le32", true)
247
255
        .Case("le16", true)
248
255
        .Case("goto", true)
249
255
        .Case("ll", true)
250
255
        .Case("skb", true)
251
255
        .Case("s", true)
252
255
        .Default(false);
253
255
  }
254
};
255
} // end anonymous namespace.
256
257
#define GET_REGISTER_MATCHER
258
#define GET_MATCHER_IMPLEMENTATION
259
#include "BPFGenAsmMatcher.inc"
260
261
121
bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
262
121
263
121
  if (Operands.size() == 4) {
264
37
    // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
265
37
    // reg1 must be the same as reg2
266
37
    BPFOperand &Op0 = (BPFOperand &)*Operands[0];
267
37
    BPFOperand &Op1 = (BPFOperand &)*Operands[1];
268
37
    BPFOperand &Op2 = (BPFOperand &)*Operands[2];
269
37
    BPFOperand &Op3 = (BPFOperand &)*Operands[3];
270
37
    if (Op0.isReg() && Op1.isToken() && Op2.isToken() && 
Op3.isReg()33
271
37
        && 
Op1.getToken() == "="19
272
37
        && 
(5
Op2.getToken() == "-"5
||
Op2.getToken() == "be16"3
273
5
            || 
Op2.getToken() == "be32"2
||
Op2.getToken() == "be64"1
274
5
            || 
Op2.getToken() == "le16"0
||
Op2.getToken() == "le32"0
275
5
            || 
Op2.getToken() == "le64"0
)
276
37
        && 
Op0.getReg() != Op3.getReg()5
)
277
0
      return true;
278
121
  }
279
121
280
121
  return false;
281
121
}
282
283
bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
284
                                           OperandVector &Operands,
285
                                           MCStreamer &Out, uint64_t &ErrorInfo,
286
121
                                           bool MatchingInlineAsm) {
287
121
  MCInst Inst;
288
121
  SMLoc ErrorLoc;
289
121
290
121
  if (PreMatchCheck(Operands))
291
0
    return Error(IDLoc, "additional inst constraint not met");
292
121
293
121
  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
294
121
  default:
295
0
    break;
296
121
  case Match_Success:
297
121
    Inst.setLoc(IDLoc);
298
121
    Out.EmitInstruction(Inst, getSTI());
299
121
    return false;
300
121
  case Match_MissingFeature:
301
0
    return Error(IDLoc, "instruction use requires an option to be enabled");
302
121
  case Match_MnemonicFail:
303
0
    return Error(IDLoc, "unrecognized instruction mnemonic");
304
121
  case Match_InvalidOperand:
305
0
    ErrorLoc = IDLoc;
306
0
307
0
    if (ErrorInfo != ~0U) {
308
0
      if (ErrorInfo >= Operands.size())
309
0
        return Error(ErrorLoc, "too few operands for instruction");
310
0
311
0
      ErrorLoc = ((BPFOperand &)*Operands[ErrorInfo]).getStartLoc();
312
0
313
0
      if (ErrorLoc == SMLoc())
314
0
        ErrorLoc = IDLoc;
315
0
    }
316
0
317
0
    return Error(ErrorLoc, "invalid operand for instruction");
318
0
  }
319
0
320
0
  llvm_unreachable("Unknown match type detected!");
321
0
}
322
323
bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
324
0
                                 SMLoc &EndLoc) {
325
0
  const AsmToken &Tok = getParser().getTok();
326
0
  StartLoc = Tok.getLoc();
327
0
  EndLoc = Tok.getEndLoc();
328
0
  RegNo = 0;
329
0
  StringRef Name = getLexer().getTok().getIdentifier();
330
0
331
0
  if (!MatchRegisterName(Name)) {
332
0
    getParser().Lex(); // Eat identifier token.
333
0
    return false;
334
0
  }
335
0
336
0
  return Error(StartLoc, "invalid register name");
337
0
}
338
339
OperandMatchResultTy
340
617
BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
341
617
  SMLoc S = getLoc();
342
617
343
617
  if (getLexer().getKind() == AsmToken::Identifier) {
344
255
    StringRef Name = getLexer().getTok().getIdentifier();
345
255
346
255
    if (BPFOperand::isValidIdInMiddle(Name)) {
347
96
      getLexer().Lex();
348
96
      Operands.push_back(BPFOperand::createToken(Name, S));
349
96
      return MatchOperand_Success;
350
96
    }
351
159
352
159
    return MatchOperand_NoMatch;
353
159
  }
354
362
355
362
  switch (getLexer().getKind()) {
356
362
  case AsmToken::Minus:
357
36
  case AsmToken::Plus: {
358
36
    if (getLexer().peekTok().is(AsmToken::Integer))
359
23
      return MatchOperand_NoMatch;
360
13
    LLVM_FALLTHROUGH;
361
13
  }
362
13
363
258
  case AsmToken::Equal:
364
258
  case AsmToken::Greater:
365
258
  case AsmToken::Less:
366
258
  case AsmToken::Pipe:
367
258
  case AsmToken::Star:
368
258
  case AsmToken::LParen:
369
258
  case AsmToken::RParen:
370
258
  case AsmToken::LBrac:
371
258
  case AsmToken::RBrac:
372
258
  case AsmToken::Slash:
373
258
  case AsmToken::Amp:
374
258
  case AsmToken::Percent:
375
258
  case AsmToken::Caret: {
376
258
    StringRef Name = getLexer().getTok().getString();
377
258
    getLexer().Lex();
378
258
    Operands.push_back(BPFOperand::createToken(Name, S));
379
258
380
258
    return MatchOperand_Success;
381
258
  }
382
258
383
258
  case AsmToken::EqualEqual:
384
36
  case AsmToken::ExclaimEqual:
385
36
  case AsmToken::GreaterEqual:
386
36
  case AsmToken::GreaterGreater:
387
36
  case AsmToken::LessEqual:
388
36
  case AsmToken::LessLess: {
389
36
    Operands.push_back(BPFOperand::createToken(
390
36
        getLexer().getTok().getString().substr(0, 1), S));
391
36
    Operands.push_back(BPFOperand::createToken(
392
36
        getLexer().getTok().getString().substr(1, 1), S));
393
36
    getLexer().Lex();
394
36
395
36
    return MatchOperand_Success;
396
36
  }
397
36
398
45
  default:
399
45
    break;
400
45
  }
401
45
402
45
  return MatchOperand_NoMatch;
403
45
}
404
405
227
OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) {
406
227
  SMLoc S = getLoc();
407
227
  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
408
227
409
227
  switch (getLexer().getKind()) {
410
227
  default:
411
68
    return MatchOperand_NoMatch;
412
227
  case AsmToken::Identifier:
413
159
    StringRef Name = getLexer().getTok().getIdentifier();
414
159
    unsigned RegNo = MatchRegisterName(Name);
415
159
416
159
    if (RegNo == 0)
417
42
      return MatchOperand_NoMatch;
418
117
419
117
    getLexer().Lex();
420
117
    Operands.push_back(BPFOperand::createReg(RegNo, S, E));
421
227
  }
422
227
  
return MatchOperand_Success117
;
423
227
}
424
425
110
OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) {
426
110
  switch (getLexer().getKind()) {
427
110
  default:
428
0
    return MatchOperand_NoMatch;
429
110
  case AsmToken::LParen:
430
110
  case AsmToken::Minus:
431
110
  case AsmToken::Plus:
432
110
  case AsmToken::Integer:
433
110
  case AsmToken::String:
434
110
  case AsmToken::Identifier:
435
110
    break;
436
110
  }
437
110
438
110
  const MCExpr *IdVal;
439
110
  SMLoc S = getLoc();
440
110
441
110
  if (getParser().parseExpression(IdVal))
442
0
    return MatchOperand_ParseFail;
443
110
444
110
  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
445
110
  Operands.push_back(BPFOperand::createImm(IdVal, S, E));
446
110
447
110
  return MatchOperand_Success;
448
110
}
449
450
/// ParseInstruction - Parse an BPF instruction which is in BPF verifier
451
/// format.
452
bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
453
121
                                    SMLoc NameLoc, OperandVector &Operands) {
454
121
  // The first operand could be either register or actually an operator.
455
121
  unsigned RegNo = MatchRegisterName(Name);
456
121
457
121
  if (RegNo != 0) {
458
68
    SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1);
459
68
    Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E));
460
68
  } else 
if (53
BPFOperand::isValidIdAtStart (Name)53
)
461
53
    Operands.push_back(BPFOperand::createToken(Name, NameLoc));
462
0
  else
463
0
    return Error(NameLoc, "invalid register/token name");
464
121
465
738
  
while (121
!getLexer().is(AsmToken::EndOfStatement)) {
466
617
    // Attempt to parse token as operator
467
617
    if (parseOperandAsOperator(Operands) == MatchOperand_Success)
468
390
      continue;
469
227
470
227
    // Attempt to parse token as register
471
227
    if (parseRegister(Operands) == MatchOperand_Success)
472
117
      continue;
473
110
474
110
    // Attempt to parse token as an immediate
475
110
    if (parseImmediate(Operands) != MatchOperand_Success) {
476
0
      SMLoc Loc = getLexer().getLoc();
477
0
      return Error(Loc, "unexpected token");
478
0
    }
479
110
  }
480
121
481
121
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
482
0
    SMLoc Loc = getLexer().getLoc();
483
0
484
0
    getParser().eatToEndOfStatement();
485
0
486
0
    return Error(Loc, "unexpected token");
487
0
  }
488
121
489
121
  // Consume the EndOfStatement.
490
121
  getParser().Lex();
491
121
  return false;
492
121
}
493
494
0
bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
495
496
91.7k
extern "C" void LLVMInitializeBPFAsmParser() {
497
91.7k
  RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
498
91.7k
  RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
499
91.7k
  RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());
500
91.7k
}