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/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"
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
,
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
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
);
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
79 struct BPFOperand
: public MCParsedAsmOperand
{
95 SMLoc StartLoc
, EndLoc
;
102 BPFOperand(KindTy K
) : MCParsedAsmOperand(), Kind(K
) {}
105 BPFOperand(const BPFOperand
&o
) : MCParsedAsmOperand() {
107 StartLoc
= o
.StartLoc
;
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!");
151 const MCExpr
*getImm() const {
152 assert(Kind
== Immediate
&& "Invalid type access!");
156 StringRef
getToken() const {
157 assert(Kind
== Token
&& "Invalid type access!");
161 void print(raw_ostream
&OS
) const override
{
168 OS
<< getReg() << ">";
171 OS
<< "'" << getToken() << "'";
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()));
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
);
204 static std::unique_ptr
<BPFOperand
> createReg(unsigned RegNo
, SMLoc S
,
206 auto Op
= std::make_unique
<BPFOperand
>(Register
);
207 Op
->Reg
.RegNum
= RegNo
;
213 static std::unique_ptr
<BPFOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
215 auto Op
= std::make_unique
<BPFOperand
>(Immediate
);
222 // Identifiers that can be used at the start of a statment.
223 static bool isValidIdAtStart(StringRef Name
) {
224 return StringSwitch
<bool>(Name
.lower())
231 .Case("ld_pseudo", true)
235 // Identifiers that can be used in the middle of a statment.
236 static bool isValidIdInMiddle(StringRef Name
) {
237 return StringSwitch
<bool>(Name
.lower())
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())
283 bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
284 OperandVector
&Operands
,
285 MCStreamer
&Out
, uint64_t &ErrorInfo
,
286 bool MatchingInlineAsm
) {
290 if (PreMatchCheck(Operands
))
291 return Error(IDLoc
, "additional inst constraint not met");
293 switch (MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
)) {
298 Out
.EmitInstruction(Inst
, getSTI());
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
:
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())
317 return Error(ErrorLoc
, "invalid operand for instruction");
320 llvm_unreachable("Unknown match type detected!");
323 bool BPFAsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
325 const AsmToken
&Tok
= getParser().getTok();
326 StartLoc
= Tok
.getLoc();
327 EndLoc
= Tok
.getEndLoc();
329 StringRef Name
= getLexer().getTok().getIdentifier();
331 if (!MatchRegisterName(Name
)) {
332 getParser().Lex(); // Eat identifier token.
336 return Error(StartLoc
, "invalid register name");
340 BPFAsmParser::parseOperandAsOperator(OperandVector
&Operands
) {
343 if (getLexer().getKind() == AsmToken::Identifier
) {
344 StringRef Name
= getLexer().getTok().getIdentifier();
346 if (BPFOperand::isValidIdInMiddle(Name
)) {
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
;
363 case AsmToken::Equal
:
364 case AsmToken::Greater
:
368 case AsmToken::LParen
:
369 case AsmToken::RParen
:
370 case AsmToken::LBrac
:
371 case AsmToken::RBrac
:
372 case AsmToken::Slash
:
374 case AsmToken::Percent
:
375 case AsmToken::Caret
: {
376 StringRef Name
= getLexer().getTok().getString();
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
));
395 return MatchOperand_Success
;
402 return MatchOperand_NoMatch
;
405 OperandMatchResultTy
BPFAsmParser::parseRegister(OperandVector
&Operands
) {
407 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() - 1);
409 switch (getLexer().getKind()) {
411 return MatchOperand_NoMatch
;
412 case AsmToken::Identifier
:
413 StringRef Name
= getLexer().getTok().getIdentifier();
414 unsigned RegNo
= MatchRegisterName(Name
);
417 return MatchOperand_NoMatch
;
420 Operands
.push_back(BPFOperand::createReg(RegNo
, S
, E
));
422 return MatchOperand_Success
;
425 OperandMatchResultTy
BPFAsmParser::parseImmediate(OperandVector
&Operands
) {
426 switch (getLexer().getKind()) {
428 return MatchOperand_NoMatch
;
429 case AsmToken::LParen
:
430 case AsmToken::Minus
:
432 case AsmToken::Integer
:
433 case AsmToken::String
:
434 case AsmToken::Identifier
:
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
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
);
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
));
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
)
470 // Attempt to parse token as register
471 if (parseRegister(Operands
) == MatchOperand_Success
)
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.
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());