[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / Target / BPF / AsmParser / BPFAsmParser.cpp
blobce1d2ecd9d266dd1a3f64b646a8aa79e5f66712c
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 //===----------------------------------------------------------------------===//
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"
25 using namespace llvm;
27 namespace {
28 struct BPFOperand;
30 class BPFAsmParser : public MCTargetAsmParser {
32 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
34 bool PreMatchCheck(OperandVector &Operands);
36 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
37 OperandVector &Operands, MCStreamer &Out,
38 uint64_t &ErrorInfo,
39 bool MatchingInlineAsm) override;
41 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
43 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
44 SMLoc NameLoc, OperandVector &Operands) override;
46 bool ParseDirective(AsmToken DirectiveID) override;
48 // "=" is used as assignment operator for assembly statment, so can't be used
49 // for symbol assignment.
50 bool equalIsAsmAssignment() override { return false; }
51 // "*" is used for dereferencing memory that it will be the start of
52 // statement.
53 bool starIsStartOfStatement() override { return true; }
55 #define GET_ASSEMBLER_HEADER
56 #include "BPFGenAsmMatcher.inc"
58 OperandMatchResultTy parseImmediate(OperandVector &Operands);
59 OperandMatchResultTy parseRegister(OperandVector &Operands);
60 OperandMatchResultTy parseOperandAsOperator(OperandVector &Operands);
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
70 BPFAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
71 const MCInstrInfo &MII, const MCTargetOptions &Options)
72 : MCTargetAsmParser(Options, STI, MII) {
73 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
77 /// BPFOperand - Instances of this class represent a parsed machine
78 /// instruction
79 struct BPFOperand : public MCParsedAsmOperand {
81 enum KindTy {
82 Token,
83 Register,
84 Immediate,
85 } Kind;
87 struct RegOp {
88 unsigned RegNum;
91 struct ImmOp {
92 const MCExpr *Val;
95 SMLoc StartLoc, EndLoc;
96 union {
97 StringRef Tok;
98 RegOp Reg;
99 ImmOp Imm;
102 BPFOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
104 public:
105 BPFOperand(const BPFOperand &o) : MCParsedAsmOperand() {
106 Kind = o.Kind;
107 StartLoc = o.StartLoc;
108 EndLoc = o.EndLoc;
110 switch (Kind) {
111 case Register:
112 Reg = o.Reg;
113 break;
114 case Immediate:
115 Imm = o.Imm;
116 break;
117 case Token:
118 Tok = o.Tok;
119 break;
123 bool isToken() const override { return Kind == Token; }
124 bool isReg() const override { return Kind == Register; }
125 bool isImm() const override { return Kind == Immediate; }
126 bool isMem() const override { return false; }
128 bool isConstantImm() const {
129 return isImm() && isa<MCConstantExpr>(getImm());
132 int64_t getConstantImm() const {
133 const MCExpr *Val = getImm();
134 return static_cast<const MCConstantExpr *>(Val)->getValue();
137 bool isSImm12() const {
138 return (isConstantImm() && isInt<12>(getConstantImm()));
141 /// getStartLoc - Gets location of the first token of this operand
142 SMLoc getStartLoc() const override { return StartLoc; }
143 /// getEndLoc - Gets location of the last token of this operand
144 SMLoc getEndLoc() const override { return EndLoc; }
146 unsigned getReg() const override {
147 assert(Kind == Register && "Invalid type access!");
148 return Reg.RegNum;
151 const MCExpr *getImm() const {
152 assert(Kind == Immediate && "Invalid type access!");
153 return Imm.Val;
156 StringRef getToken() const {
157 assert(Kind == Token && "Invalid type access!");
158 return Tok;
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;
176 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
177 assert(Expr && "Expr shouldn't be null!");
179 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
180 Inst.addOperand(MCOperand::createImm(CE->getValue()));
181 else
182 Inst.addOperand(MCOperand::createExpr(Expr));
185 // Used by the TableGen Code
186 void addRegOperands(MCInst &Inst, unsigned N) const {
187 assert(N == 1 && "Invalid number of operands!");
188 Inst.addOperand(MCOperand::createReg(getReg()));
191 void addImmOperands(MCInst &Inst, unsigned N) const {
192 assert(N == 1 && "Invalid number of operands!");
193 addExpr(Inst, getImm());
196 static std::unique_ptr<BPFOperand> createToken(StringRef Str, SMLoc S) {
197 auto Op = std::make_unique<BPFOperand>(Token);
198 Op->Tok = Str;
199 Op->StartLoc = S;
200 Op->EndLoc = S;
201 return Op;
204 static std::unique_ptr<BPFOperand> createReg(unsigned RegNo, SMLoc S,
205 SMLoc E) {
206 auto Op = std::make_unique<BPFOperand>(Register);
207 Op->Reg.RegNum = RegNo;
208 Op->StartLoc = S;
209 Op->EndLoc = E;
210 return Op;
213 static std::unique_ptr<BPFOperand> createImm(const MCExpr *Val, SMLoc S,
214 SMLoc E) {
215 auto Op = std::make_unique<BPFOperand>(Immediate);
216 Op->Imm.Val = Val;
217 Op->StartLoc = S;
218 Op->EndLoc = E;
219 return Op;
222 // Identifiers that can be used at the start of a statment.
223 static bool isValidIdAtStart(StringRef Name) {
224 return StringSwitch<bool>(Name.lower())
225 .Case("if", true)
226 .Case("call", true)
227 .Case("goto", true)
228 .Case("*", true)
229 .Case("exit", true)
230 .Case("lock", true)
231 .Case("ld_pseudo", true)
232 .Default(false);
235 // Identifiers that can be used in the middle of a statment.
236 static bool isValidIdInMiddle(StringRef Name) {
237 return StringSwitch<bool>(Name.lower())
238 .Case("u64", true)
239 .Case("u32", true)
240 .Case("u16", true)
241 .Case("u8", true)
242 .Case("be64", true)
243 .Case("be32", true)
244 .Case("be16", true)
245 .Case("le64", true)
246 .Case("le32", true)
247 .Case("le16", true)
248 .Case("goto", true)
249 .Case("ll", true)
250 .Case("skb", true)
251 .Case("s", true)
252 .Default(false);
255 } // end anonymous namespace.
257 #define GET_REGISTER_MATCHER
258 #define GET_MATCHER_IMPLEMENTATION
259 #include "BPFGenAsmMatcher.inc"
261 bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
263 if (Operands.size() == 4) {
264 // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
265 // reg1 must be the same as reg2
266 BPFOperand &Op0 = (BPFOperand &)*Operands[0];
267 BPFOperand &Op1 = (BPFOperand &)*Operands[1];
268 BPFOperand &Op2 = (BPFOperand &)*Operands[2];
269 BPFOperand &Op3 = (BPFOperand &)*Operands[3];
270 if (Op0.isReg() && Op1.isToken() && Op2.isToken() && Op3.isReg()
271 && Op1.getToken() == "="
272 && (Op2.getToken() == "-" || Op2.getToken() == "be16"
273 || Op2.getToken() == "be32" || Op2.getToken() == "be64"
274 || Op2.getToken() == "le16" || Op2.getToken() == "le32"
275 || Op2.getToken() == "le64")
276 && Op0.getReg() != Op3.getReg())
277 return true;
280 return false;
283 bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
284 OperandVector &Operands,
285 MCStreamer &Out, uint64_t &ErrorInfo,
286 bool MatchingInlineAsm) {
287 MCInst Inst;
288 SMLoc ErrorLoc;
290 if (PreMatchCheck(Operands))
291 return Error(IDLoc, "additional inst constraint not met");
293 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
294 default:
295 break;
296 case Match_Success:
297 Inst.setLoc(IDLoc);
298 Out.EmitInstruction(Inst, getSTI());
299 return false;
300 case Match_MissingFeature:
301 return Error(IDLoc, "instruction use requires an option to be enabled");
302 case Match_MnemonicFail:
303 return Error(IDLoc, "unrecognized instruction mnemonic");
304 case Match_InvalidOperand:
305 ErrorLoc = IDLoc;
307 if (ErrorInfo != ~0U) {
308 if (ErrorInfo >= Operands.size())
309 return Error(ErrorLoc, "too few operands for instruction");
311 ErrorLoc = ((BPFOperand &)*Operands[ErrorInfo]).getStartLoc();
313 if (ErrorLoc == SMLoc())
314 ErrorLoc = IDLoc;
317 return Error(ErrorLoc, "invalid operand for instruction");
320 llvm_unreachable("Unknown match type detected!");
323 bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
324 SMLoc &EndLoc) {
325 const AsmToken &Tok = getParser().getTok();
326 StartLoc = Tok.getLoc();
327 EndLoc = Tok.getEndLoc();
328 RegNo = 0;
329 StringRef Name = getLexer().getTok().getIdentifier();
331 if (!MatchRegisterName(Name)) {
332 getParser().Lex(); // Eat identifier token.
333 return false;
336 return Error(StartLoc, "invalid register name");
339 OperandMatchResultTy
340 BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
341 SMLoc S = getLoc();
343 if (getLexer().getKind() == AsmToken::Identifier) {
344 StringRef Name = getLexer().getTok().getIdentifier();
346 if (BPFOperand::isValidIdInMiddle(Name)) {
347 getLexer().Lex();
348 Operands.push_back(BPFOperand::createToken(Name, S));
349 return MatchOperand_Success;
352 return MatchOperand_NoMatch;
355 switch (getLexer().getKind()) {
356 case AsmToken::Minus:
357 case AsmToken::Plus: {
358 if (getLexer().peekTok().is(AsmToken::Integer))
359 return MatchOperand_NoMatch;
360 LLVM_FALLTHROUGH;
363 case AsmToken::Equal:
364 case AsmToken::Greater:
365 case AsmToken::Less:
366 case AsmToken::Pipe:
367 case AsmToken::Star:
368 case AsmToken::LParen:
369 case AsmToken::RParen:
370 case AsmToken::LBrac:
371 case AsmToken::RBrac:
372 case AsmToken::Slash:
373 case AsmToken::Amp:
374 case AsmToken::Percent:
375 case AsmToken::Caret: {
376 StringRef Name = getLexer().getTok().getString();
377 getLexer().Lex();
378 Operands.push_back(BPFOperand::createToken(Name, S));
380 return MatchOperand_Success;
383 case AsmToken::EqualEqual:
384 case AsmToken::ExclaimEqual:
385 case AsmToken::GreaterEqual:
386 case AsmToken::GreaterGreater:
387 case AsmToken::LessEqual:
388 case AsmToken::LessLess: {
389 Operands.push_back(BPFOperand::createToken(
390 getLexer().getTok().getString().substr(0, 1), S));
391 Operands.push_back(BPFOperand::createToken(
392 getLexer().getTok().getString().substr(1, 1), S));
393 getLexer().Lex();
395 return MatchOperand_Success;
398 default:
399 break;
402 return MatchOperand_NoMatch;
405 OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) {
406 SMLoc S = getLoc();
407 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
409 switch (getLexer().getKind()) {
410 default:
411 return MatchOperand_NoMatch;
412 case AsmToken::Identifier:
413 StringRef Name = getLexer().getTok().getIdentifier();
414 unsigned RegNo = MatchRegisterName(Name);
416 if (RegNo == 0)
417 return MatchOperand_NoMatch;
419 getLexer().Lex();
420 Operands.push_back(BPFOperand::createReg(RegNo, S, E));
422 return MatchOperand_Success;
425 OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) {
426 switch (getLexer().getKind()) {
427 default:
428 return MatchOperand_NoMatch;
429 case AsmToken::LParen:
430 case AsmToken::Minus:
431 case AsmToken::Plus:
432 case AsmToken::Integer:
433 case AsmToken::String:
434 case AsmToken::Identifier:
435 break;
438 const MCExpr *IdVal;
439 SMLoc S = getLoc();
441 if (getParser().parseExpression(IdVal))
442 return MatchOperand_ParseFail;
444 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
445 Operands.push_back(BPFOperand::createImm(IdVal, S, E));
447 return MatchOperand_Success;
450 /// ParseInstruction - Parse an BPF instruction which is in BPF verifier
451 /// format.
452 bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
453 SMLoc NameLoc, OperandVector &Operands) {
454 // The first operand could be either register or actually an operator.
455 unsigned RegNo = MatchRegisterName(Name);
457 if (RegNo != 0) {
458 SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1);
459 Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E));
460 } else if (BPFOperand::isValidIdAtStart (Name))
461 Operands.push_back(BPFOperand::createToken(Name, NameLoc));
462 else
463 return Error(NameLoc, "invalid register/token name");
465 while (!getLexer().is(AsmToken::EndOfStatement)) {
466 // Attempt to parse token as operator
467 if (parseOperandAsOperator(Operands) == MatchOperand_Success)
468 continue;
470 // Attempt to parse token as register
471 if (parseRegister(Operands) == MatchOperand_Success)
472 continue;
474 // Attempt to parse token as an immediate
475 if (parseImmediate(Operands) != MatchOperand_Success) {
476 SMLoc Loc = getLexer().getLoc();
477 return Error(Loc, "unexpected token");
481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
482 SMLoc Loc = getLexer().getLoc();
484 getParser().eatToEndOfStatement();
486 return Error(Loc, "unexpected token");
489 // Consume the EndOfStatement.
490 getParser().Lex();
491 return false;
494 bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
496 extern "C" void LLVMInitializeBPFAsmParser() {
497 RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
498 RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
499 RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());