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