1 //===-- BPFAsmParser.cpp - Parse BPF assembly to MCInst instructions --===//
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
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/MCInstrInfo.h"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/TargetRegistry.h"
24 #include "llvm/Support/Casting.h"
31 class BPFAsmParser
: public MCTargetAsmParser
{
33 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
35 bool PreMatchCheck(OperandVector
&Operands
);
37 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
38 OperandVector
&Operands
, MCStreamer
&Out
,
40 bool MatchingInlineAsm
) override
;
42 bool parseRegister(MCRegister
&Reo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
43 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
44 SMLoc
&EndLoc
) override
;
46 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
47 SMLoc NameLoc
, OperandVector
&Operands
) override
;
49 // "=" is used as assignment operator for assembly statment, so can't be used
50 // for symbol assignment.
51 bool equalIsAsmAssignment() override
{ return false; }
52 // "*" is used for dereferencing memory that it will be the start of
54 bool starIsStartOfStatement() override
{ return true; }
56 #define GET_ASSEMBLER_HEADER
57 #include "BPFGenAsmMatcher.inc"
59 ParseStatus
parseImmediate(OperandVector
&Operands
);
60 ParseStatus
parseRegister(OperandVector
&Operands
);
61 ParseStatus
parseOperandAsOperator(OperandVector
&Operands
);
64 enum BPFMatchResultTy
{
65 Match_Dummy
= FIRST_TARGET_MATCH_RESULT_TY
,
66 #define GET_OPERAND_DIAGNOSTIC_TYPES
67 #include "BPFGenAsmMatcher.inc"
68 #undef GET_OPERAND_DIAGNOSTIC_TYPES
71 BPFAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
72 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
73 : MCTargetAsmParser(Options
, STI
, MII
) {
74 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
78 /// BPFOperand - Instances of this class represent a parsed machine
80 struct BPFOperand
: public MCParsedAsmOperand
{
96 SMLoc StartLoc
, EndLoc
;
103 BPFOperand(KindTy K
) : Kind(K
) {}
106 BPFOperand(const BPFOperand
&o
) : MCParsedAsmOperand() {
108 StartLoc
= o
.StartLoc
;
124 bool isToken() const override
{ return Kind
== Token
; }
125 bool isReg() const override
{ return Kind
== Register
; }
126 bool isImm() const override
{ return Kind
== Immediate
; }
127 bool isMem() const override
{ return false; }
129 bool isConstantImm() const {
130 return isImm() && isa
<MCConstantExpr
>(getImm());
133 int64_t getConstantImm() const {
134 const MCExpr
*Val
= getImm();
135 return static_cast<const MCConstantExpr
*>(Val
)->getValue();
138 bool isSImm16() const {
139 return (isConstantImm() && isInt
<16>(getConstantImm()));
142 bool isSymbolRef() const { return isImm() && isa
<MCSymbolRefExpr
>(getImm()); }
144 bool isBrTarget() const { return isSymbolRef() || isSImm16(); }
146 /// getStartLoc - Gets location of the first token of this operand
147 SMLoc
getStartLoc() const override
{ return StartLoc
; }
148 /// getEndLoc - Gets location of the last token of this operand
149 SMLoc
getEndLoc() const override
{ return EndLoc
; }
151 unsigned getReg() const override
{
152 assert(Kind
== Register
&& "Invalid type access!");
156 const MCExpr
*getImm() const {
157 assert(Kind
== Immediate
&& "Invalid type access!");
161 StringRef
getToken() const {
162 assert(Kind
== Token
&& "Invalid type access!");
166 void print(raw_ostream
&OS
) const override
{
173 OS
<< getReg() << ">";
176 OS
<< "'" << getToken() << "'";
181 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
182 assert(Expr
&& "Expr shouldn't be null!");
184 if (auto *CE
= dyn_cast
<MCConstantExpr
>(Expr
))
185 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
187 Inst
.addOperand(MCOperand::createExpr(Expr
));
190 // Used by the TableGen Code
191 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
192 assert(N
== 1 && "Invalid number of operands!");
193 Inst
.addOperand(MCOperand::createReg(getReg()));
196 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
197 assert(N
== 1 && "Invalid number of operands!");
198 addExpr(Inst
, getImm());
201 static std::unique_ptr
<BPFOperand
> createToken(StringRef Str
, SMLoc S
) {
202 auto Op
= std::make_unique
<BPFOperand
>(Token
);
209 static std::unique_ptr
<BPFOperand
> createReg(unsigned RegNo
, SMLoc S
,
211 auto Op
= std::make_unique
<BPFOperand
>(Register
);
212 Op
->Reg
.RegNum
= RegNo
;
218 static std::unique_ptr
<BPFOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
220 auto Op
= std::make_unique
<BPFOperand
>(Immediate
);
227 // Identifiers that can be used at the start of a statment.
228 static bool isValidIdAtStart(StringRef Name
) {
229 return StringSwitch
<bool>(Name
.lower())
237 .Case("ld_pseudo", true)
241 // Identifiers that can be used in the middle of a statment.
242 static bool isValidIdInMiddle(StringRef Name
) {
243 return StringSwitch
<bool>(Name
.lower())
257 .Case("bswap16", true)
258 .Case("bswap32", true)
259 .Case("bswap64", true)
265 .Case("atomic_fetch_add", true)
266 .Case("atomic_fetch_and", true)
267 .Case("atomic_fetch_or", true)
268 .Case("atomic_fetch_xor", true)
269 .Case("xchg_64", true)
270 .Case("xchg32_32", true)
271 .Case("cmpxchg_64", true)
272 .Case("cmpxchg32_32", true)
276 } // end anonymous namespace.
278 #define GET_REGISTER_MATCHER
279 #define GET_MATCHER_IMPLEMENTATION
280 #include "BPFGenAsmMatcher.inc"
282 bool BPFAsmParser::PreMatchCheck(OperandVector
&Operands
) {
284 if (Operands
.size() == 4) {
285 // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
286 // reg1 must be the same as reg2
287 BPFOperand
&Op0
= (BPFOperand
&)*Operands
[0];
288 BPFOperand
&Op1
= (BPFOperand
&)*Operands
[1];
289 BPFOperand
&Op2
= (BPFOperand
&)*Operands
[2];
290 BPFOperand
&Op3
= (BPFOperand
&)*Operands
[3];
291 if (Op0
.isReg() && Op1
.isToken() && Op2
.isToken() && Op3
.isReg()
292 && Op1
.getToken() == "="
293 && (Op2
.getToken() == "-" || Op2
.getToken() == "be16"
294 || Op2
.getToken() == "be32" || Op2
.getToken() == "be64"
295 || Op2
.getToken() == "le16" || Op2
.getToken() == "le32"
296 || Op2
.getToken() == "le64")
297 && Op0
.getReg() != Op3
.getReg())
304 bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
305 OperandVector
&Operands
,
306 MCStreamer
&Out
, uint64_t &ErrorInfo
,
307 bool MatchingInlineAsm
) {
311 if (PreMatchCheck(Operands
))
312 return Error(IDLoc
, "additional inst constraint not met");
314 switch (MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
)) {
319 Out
.emitInstruction(Inst
, getSTI());
321 case Match_MissingFeature
:
322 return Error(IDLoc
, "instruction use requires an option to be enabled");
323 case Match_MnemonicFail
:
324 return Error(IDLoc
, "unrecognized instruction mnemonic");
325 case Match_InvalidOperand
:
328 if (ErrorInfo
!= ~0U) {
329 if (ErrorInfo
>= Operands
.size())
330 return Error(ErrorLoc
, "too few operands for instruction");
332 ErrorLoc
= ((BPFOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
334 if (ErrorLoc
== SMLoc())
338 return Error(ErrorLoc
, "invalid operand for instruction");
339 case Match_InvalidBrTarget
:
340 return Error(Operands
[ErrorInfo
]->getStartLoc(),
341 "operand is not an identifier or 16-bit signed integer");
342 case Match_InvalidSImm16
:
343 return Error(Operands
[ErrorInfo
]->getStartLoc(),
344 "operand is not a 16-bit signed integer");
347 llvm_unreachable("Unknown match type detected!");
350 bool BPFAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
352 if (!tryParseRegister(Reg
, StartLoc
, EndLoc
).isSuccess())
353 return Error(StartLoc
, "invalid register name");
357 ParseStatus
BPFAsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
359 const AsmToken
&Tok
= getParser().getTok();
360 StartLoc
= Tok
.getLoc();
361 EndLoc
= Tok
.getEndLoc();
362 Reg
= BPF::NoRegister
;
363 StringRef Name
= getLexer().getTok().getIdentifier();
365 if (!MatchRegisterName(Name
)) {
366 getParser().Lex(); // Eat identifier token.
367 return ParseStatus::Success
;
370 return ParseStatus::NoMatch
;
373 ParseStatus
BPFAsmParser::parseOperandAsOperator(OperandVector
&Operands
) {
376 if (getLexer().getKind() == AsmToken::Identifier
) {
377 StringRef Name
= getLexer().getTok().getIdentifier();
379 if (BPFOperand::isValidIdInMiddle(Name
)) {
381 Operands
.push_back(BPFOperand::createToken(Name
, S
));
382 return ParseStatus::Success
;
385 return ParseStatus::NoMatch
;
388 switch (getLexer().getKind()) {
389 case AsmToken::Minus
:
390 case AsmToken::Plus
: {
391 if (getLexer().peekTok().is(AsmToken::Integer
))
392 return ParseStatus::NoMatch
;
396 case AsmToken::Equal
:
397 case AsmToken::Greater
:
401 case AsmToken::LParen
:
402 case AsmToken::RParen
:
403 case AsmToken::LBrac
:
404 case AsmToken::RBrac
:
405 case AsmToken::Slash
:
407 case AsmToken::Percent
:
408 case AsmToken::Caret
: {
409 StringRef Name
= getLexer().getTok().getString();
411 Operands
.push_back(BPFOperand::createToken(Name
, S
));
413 return ParseStatus::Success
;
416 case AsmToken::EqualEqual
:
417 case AsmToken::ExclaimEqual
:
418 case AsmToken::GreaterEqual
:
419 case AsmToken::GreaterGreater
:
420 case AsmToken::LessEqual
:
421 case AsmToken::LessLess
: {
422 Operands
.push_back(BPFOperand::createToken(
423 getLexer().getTok().getString().substr(0, 1), S
));
424 Operands
.push_back(BPFOperand::createToken(
425 getLexer().getTok().getString().substr(1, 1), S
));
428 return ParseStatus::Success
;
435 return ParseStatus::NoMatch
;
438 ParseStatus
BPFAsmParser::parseRegister(OperandVector
&Operands
) {
440 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() - 1);
442 switch (getLexer().getKind()) {
444 return ParseStatus::NoMatch
;
445 case AsmToken::Identifier
:
446 StringRef Name
= getLexer().getTok().getIdentifier();
447 unsigned RegNo
= MatchRegisterName(Name
);
450 return ParseStatus::NoMatch
;
453 Operands
.push_back(BPFOperand::createReg(RegNo
, S
, E
));
455 return ParseStatus::Success
;
458 ParseStatus
BPFAsmParser::parseImmediate(OperandVector
&Operands
) {
459 switch (getLexer().getKind()) {
461 return ParseStatus::NoMatch
;
462 case AsmToken::LParen
:
463 case AsmToken::Minus
:
465 case AsmToken::Integer
:
466 case AsmToken::String
:
467 case AsmToken::Identifier
:
474 if (getParser().parseExpression(IdVal
))
475 return ParseStatus::Failure
;
477 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() - 1);
478 Operands
.push_back(BPFOperand::createImm(IdVal
, S
, E
));
480 return ParseStatus::Success
;
483 /// ParseInstruction - Parse an BPF instruction which is in BPF verifier
485 bool BPFAsmParser::ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
486 SMLoc NameLoc
, OperandVector
&Operands
) {
487 // The first operand could be either register or actually an operator.
488 unsigned RegNo
= MatchRegisterName(Name
);
491 SMLoc E
= SMLoc::getFromPointer(NameLoc
.getPointer() - 1);
492 Operands
.push_back(BPFOperand::createReg(RegNo
, NameLoc
, E
));
493 } else if (BPFOperand::isValidIdAtStart (Name
))
494 Operands
.push_back(BPFOperand::createToken(Name
, NameLoc
));
496 return Error(NameLoc
, "invalid register/token name");
498 while (!getLexer().is(AsmToken::EndOfStatement
)) {
499 // Attempt to parse token as operator
500 if (parseOperandAsOperator(Operands
).isSuccess())
503 // Attempt to parse token as register
504 if (parseRegister(Operands
).isSuccess())
507 if (getLexer().is(AsmToken::Comma
)) {
512 // Attempt to parse token as an immediate
513 if (!parseImmediate(Operands
).isSuccess()) {
514 SMLoc Loc
= getLexer().getLoc();
515 return Error(Loc
, "unexpected token");
519 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
520 SMLoc Loc
= getLexer().getLoc();
522 getParser().eatToEndOfStatement();
524 return Error(Loc
, "unexpected token");
527 // Consume the EndOfStatement.
532 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeBPFAsmParser() {
533 RegisterMCAsmParser
<BPFAsmParser
> X(getTheBPFTarget());
534 RegisterMCAsmParser
<BPFAsmParser
> Y(getTheBPFleTarget());
535 RegisterMCAsmParser
<BPFAsmParser
> Z(getTheBPFbeTarget());