1bdd1243dSDimitry Andric //===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // The LLVM Compiler Infrastructure
4bdd1243dSDimitry Andric //
5bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
7bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
10bdd1243dSDimitry Andric
11bdd1243dSDimitry Andric #include "MCTargetDesc/XtensaMCTargetDesc.h"
12bdd1243dSDimitry Andric #include "TargetInfo/XtensaTargetInfo.h"
13bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h"
14bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h"
15bdd1243dSDimitry Andric #include "llvm/MC/MCContext.h"
16bdd1243dSDimitry Andric #include "llvm/MC/MCExpr.h"
17bdd1243dSDimitry Andric #include "llvm/MC/MCInst.h"
18bdd1243dSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
19bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
20bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22bdd1243dSDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
23bdd1243dSDimitry Andric #include "llvm/MC/MCStreamer.h"
24bdd1243dSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
25bdd1243dSDimitry Andric #include "llvm/MC/TargetRegistry.h"
26bdd1243dSDimitry Andric #include "llvm/Support/Casting.h"
27bdd1243dSDimitry Andric
28bdd1243dSDimitry Andric using namespace llvm;
29bdd1243dSDimitry Andric
30bdd1243dSDimitry Andric #define DEBUG_TYPE "xtensa-asm-parser"
31bdd1243dSDimitry Andric
32bdd1243dSDimitry Andric struct XtensaOperand;
33bdd1243dSDimitry Andric
34bdd1243dSDimitry Andric class XtensaAsmParser : public MCTargetAsmParser {
35bdd1243dSDimitry Andric
getLoc() const36bdd1243dSDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); }
37bdd1243dSDimitry Andric
38*5f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
39bdd1243dSDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
40bdd1243dSDimitry Andric SMLoc NameLoc, OperandVector &Operands) override;
41bdd1243dSDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
42bdd1243dSDimitry Andric OperandVector &Operands, MCStreamer &Out,
43bdd1243dSDimitry Andric uint64_t &ErrorInfo,
44bdd1243dSDimitry Andric bool MatchingInlineAsm) override;
45bdd1243dSDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
46bdd1243dSDimitry Andric unsigned Kind) override;
47bdd1243dSDimitry Andric
48bdd1243dSDimitry Andric // Auto-generated instruction matching functions
49bdd1243dSDimitry Andric #define GET_ASSEMBLER_HEADER
50bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc"
51bdd1243dSDimitry Andric
52*5f757f3fSDimitry Andric ParseStatus parseImmediate(OperandVector &Operands);
53*5f757f3fSDimitry Andric ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false,
54*5f757f3fSDimitry Andric bool SR = false);
55*5f757f3fSDimitry Andric ParseStatus parseOperandWithModifier(OperandVector &Operands);
56bdd1243dSDimitry Andric bool parseOperand(OperandVector &Operands, StringRef Mnemonic,
57bdd1243dSDimitry Andric bool SR = false);
58bdd1243dSDimitry Andric bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
59bdd1243dSDimitry Andric SMLoc NameLoc, OperandVector &Operands);
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)60*5f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
61bdd1243dSDimitry Andric SMLoc &EndLoc) override {
62*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
63bdd1243dSDimitry Andric }
64*5f757f3fSDimitry Andric ParseStatus parsePCRelTarget(OperandVector &Operands);
65bdd1243dSDimitry Andric
66bdd1243dSDimitry Andric public:
67bdd1243dSDimitry Andric enum XtensaMatchResultTy {
68bdd1243dSDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
69bdd1243dSDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
70bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc"
71bdd1243dSDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
72bdd1243dSDimitry Andric };
73bdd1243dSDimitry Andric
XtensaAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)74bdd1243dSDimitry Andric XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
75bdd1243dSDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options)
76bdd1243dSDimitry Andric : MCTargetAsmParser(Options, STI, MII) {
77bdd1243dSDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
78bdd1243dSDimitry Andric }
79bdd1243dSDimitry Andric };
80bdd1243dSDimitry Andric
81bdd1243dSDimitry Andric // Return true if Expr is in the range [MinValue, MaxValue].
inRange(const MCExpr * Expr,int64_t MinValue,int64_t MaxValue)82bdd1243dSDimitry Andric static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
83bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
84bdd1243dSDimitry Andric int64_t Value = CE->getValue();
85bdd1243dSDimitry Andric return Value >= MinValue && Value <= MaxValue;
86bdd1243dSDimitry Andric }
87bdd1243dSDimitry Andric return false;
88bdd1243dSDimitry Andric }
89bdd1243dSDimitry Andric
90bdd1243dSDimitry Andric struct XtensaOperand : public MCParsedAsmOperand {
91bdd1243dSDimitry Andric
92bdd1243dSDimitry Andric enum KindTy {
93bdd1243dSDimitry Andric Token,
94bdd1243dSDimitry Andric Register,
95bdd1243dSDimitry Andric Immediate,
96bdd1243dSDimitry Andric } Kind;
97bdd1243dSDimitry Andric
98bdd1243dSDimitry Andric struct RegOp {
99bdd1243dSDimitry Andric unsigned RegNum;
100bdd1243dSDimitry Andric };
101bdd1243dSDimitry Andric
102bdd1243dSDimitry Andric struct ImmOp {
103bdd1243dSDimitry Andric const MCExpr *Val;
104bdd1243dSDimitry Andric };
105bdd1243dSDimitry Andric
106bdd1243dSDimitry Andric SMLoc StartLoc, EndLoc;
107bdd1243dSDimitry Andric union {
108bdd1243dSDimitry Andric StringRef Tok;
109bdd1243dSDimitry Andric RegOp Reg;
110bdd1243dSDimitry Andric ImmOp Imm;
111bdd1243dSDimitry Andric };
112bdd1243dSDimitry Andric
XtensaOperandXtensaOperand113bdd1243dSDimitry Andric XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
114bdd1243dSDimitry Andric
115bdd1243dSDimitry Andric public:
XtensaOperandXtensaOperand116bdd1243dSDimitry Andric XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() {
117bdd1243dSDimitry Andric Kind = o.Kind;
118bdd1243dSDimitry Andric StartLoc = o.StartLoc;
119bdd1243dSDimitry Andric EndLoc = o.EndLoc;
120bdd1243dSDimitry Andric switch (Kind) {
121bdd1243dSDimitry Andric case Register:
122bdd1243dSDimitry Andric Reg = o.Reg;
123bdd1243dSDimitry Andric break;
124bdd1243dSDimitry Andric case Immediate:
125bdd1243dSDimitry Andric Imm = o.Imm;
126bdd1243dSDimitry Andric break;
127bdd1243dSDimitry Andric case Token:
128bdd1243dSDimitry Andric Tok = o.Tok;
129bdd1243dSDimitry Andric break;
130bdd1243dSDimitry Andric }
131bdd1243dSDimitry Andric }
132bdd1243dSDimitry Andric
isTokenXtensaOperand133bdd1243dSDimitry Andric bool isToken() const override { return Kind == Token; }
isRegXtensaOperand134bdd1243dSDimitry Andric bool isReg() const override { return Kind == Register; }
isImmXtensaOperand135bdd1243dSDimitry Andric bool isImm() const override { return Kind == Immediate; }
isMemXtensaOperand136bdd1243dSDimitry Andric bool isMem() const override { return false; }
137bdd1243dSDimitry Andric
isImmXtensaOperand138bdd1243dSDimitry Andric bool isImm(int64_t MinValue, int64_t MaxValue) const {
139bdd1243dSDimitry Andric return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
140bdd1243dSDimitry Andric }
141bdd1243dSDimitry Andric
isImm8XtensaOperand142bdd1243dSDimitry Andric bool isImm8() const { return isImm(-128, 127); }
143bdd1243dSDimitry Andric
isImm8_sh8XtensaOperand144bdd1243dSDimitry Andric bool isImm8_sh8() const {
145bdd1243dSDimitry Andric return isImm(-32768, 32512) &&
146bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
147bdd1243dSDimitry Andric }
148bdd1243dSDimitry Andric
isImm12XtensaOperand149bdd1243dSDimitry Andric bool isImm12() const { return isImm(-2048, 2047); }
150bdd1243dSDimitry Andric
isImm12mXtensaOperand151bdd1243dSDimitry Andric bool isImm12m() const { return isImm(-2048, 2047); }
152bdd1243dSDimitry Andric
isOffset4m32XtensaOperand153bdd1243dSDimitry Andric bool isOffset4m32() const {
154bdd1243dSDimitry Andric return isImm(0, 60) &&
155bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
156bdd1243dSDimitry Andric }
157bdd1243dSDimitry Andric
isOffset8m8XtensaOperand158bdd1243dSDimitry Andric bool isOffset8m8() const { return isImm(0, 255); }
159bdd1243dSDimitry Andric
isOffset8m16XtensaOperand160bdd1243dSDimitry Andric bool isOffset8m16() const {
161bdd1243dSDimitry Andric return isImm(0, 510) &&
162bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
163bdd1243dSDimitry Andric }
164bdd1243dSDimitry Andric
isOffset8m32XtensaOperand165bdd1243dSDimitry Andric bool isOffset8m32() const {
166bdd1243dSDimitry Andric return isImm(0, 1020) &&
167bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
168bdd1243dSDimitry Andric }
169bdd1243dSDimitry Andric
isUimm4XtensaOperand170bdd1243dSDimitry Andric bool isUimm4() const { return isImm(0, 15); }
171bdd1243dSDimitry Andric
isUimm5XtensaOperand172bdd1243dSDimitry Andric bool isUimm5() const { return isImm(0, 31); }
173bdd1243dSDimitry Andric
isImm8n_7XtensaOperand174bdd1243dSDimitry Andric bool isImm8n_7() const { return isImm(-8, 7); }
175bdd1243dSDimitry Andric
isShimm1_31XtensaOperand176bdd1243dSDimitry Andric bool isShimm1_31() const { return isImm(1, 31); }
177bdd1243dSDimitry Andric
isImm16_31XtensaOperand178bdd1243dSDimitry Andric bool isImm16_31() const { return isImm(16, 31); }
179bdd1243dSDimitry Andric
isImm1_16XtensaOperand180bdd1243dSDimitry Andric bool isImm1_16() const { return isImm(1, 16); }
181bdd1243dSDimitry Andric
isB4constXtensaOperand182bdd1243dSDimitry Andric bool isB4const() const {
183bdd1243dSDimitry Andric if (Kind != Immediate)
184bdd1243dSDimitry Andric return false;
185bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
186bdd1243dSDimitry Andric int64_t Value = CE->getValue();
187bdd1243dSDimitry Andric switch (Value) {
188bdd1243dSDimitry Andric case -1:
189bdd1243dSDimitry Andric case 1:
190bdd1243dSDimitry Andric case 2:
191bdd1243dSDimitry Andric case 3:
192bdd1243dSDimitry Andric case 4:
193bdd1243dSDimitry Andric case 5:
194bdd1243dSDimitry Andric case 6:
195bdd1243dSDimitry Andric case 7:
196bdd1243dSDimitry Andric case 8:
197bdd1243dSDimitry Andric case 10:
198bdd1243dSDimitry Andric case 12:
199bdd1243dSDimitry Andric case 16:
200bdd1243dSDimitry Andric case 32:
201bdd1243dSDimitry Andric case 64:
202bdd1243dSDimitry Andric case 128:
203bdd1243dSDimitry Andric case 256:
204bdd1243dSDimitry Andric return true;
205bdd1243dSDimitry Andric default:
206bdd1243dSDimitry Andric return false;
207bdd1243dSDimitry Andric }
208bdd1243dSDimitry Andric }
209bdd1243dSDimitry Andric return false;
210bdd1243dSDimitry Andric }
211bdd1243dSDimitry Andric
isB4constuXtensaOperand212bdd1243dSDimitry Andric bool isB4constu() const {
213bdd1243dSDimitry Andric if (Kind != Immediate)
214bdd1243dSDimitry Andric return false;
215bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
216bdd1243dSDimitry Andric int64_t Value = CE->getValue();
217bdd1243dSDimitry Andric switch (Value) {
218bdd1243dSDimitry Andric case 32768:
219bdd1243dSDimitry Andric case 65536:
220bdd1243dSDimitry Andric case 2:
221bdd1243dSDimitry Andric case 3:
222bdd1243dSDimitry Andric case 4:
223bdd1243dSDimitry Andric case 5:
224bdd1243dSDimitry Andric case 6:
225bdd1243dSDimitry Andric case 7:
226bdd1243dSDimitry Andric case 8:
227bdd1243dSDimitry Andric case 10:
228bdd1243dSDimitry Andric case 12:
229bdd1243dSDimitry Andric case 16:
230bdd1243dSDimitry Andric case 32:
231bdd1243dSDimitry Andric case 64:
232bdd1243dSDimitry Andric case 128:
233bdd1243dSDimitry Andric case 256:
234bdd1243dSDimitry Andric return true;
235bdd1243dSDimitry Andric default:
236bdd1243dSDimitry Andric return false;
237bdd1243dSDimitry Andric }
238bdd1243dSDimitry Andric }
239bdd1243dSDimitry Andric return false;
240bdd1243dSDimitry Andric }
241bdd1243dSDimitry Andric
242bdd1243dSDimitry Andric /// getStartLoc - Gets location of the first token of this operand
getStartLocXtensaOperand243bdd1243dSDimitry Andric SMLoc getStartLoc() const override { return StartLoc; }
244bdd1243dSDimitry Andric /// getEndLoc - Gets location of the last token of this operand
getEndLocXtensaOperand245bdd1243dSDimitry Andric SMLoc getEndLoc() const override { return EndLoc; }
246bdd1243dSDimitry Andric
getRegXtensaOperand247bdd1243dSDimitry Andric unsigned getReg() const override {
248bdd1243dSDimitry Andric assert(Kind == Register && "Invalid type access!");
249bdd1243dSDimitry Andric return Reg.RegNum;
250bdd1243dSDimitry Andric }
251bdd1243dSDimitry Andric
getImmXtensaOperand252bdd1243dSDimitry Andric const MCExpr *getImm() const {
253bdd1243dSDimitry Andric assert(Kind == Immediate && "Invalid type access!");
254bdd1243dSDimitry Andric return Imm.Val;
255bdd1243dSDimitry Andric }
256bdd1243dSDimitry Andric
getTokenXtensaOperand257bdd1243dSDimitry Andric StringRef getToken() const {
258bdd1243dSDimitry Andric assert(Kind == Token && "Invalid type access!");
259bdd1243dSDimitry Andric return Tok;
260bdd1243dSDimitry Andric }
261bdd1243dSDimitry Andric
printXtensaOperand262bdd1243dSDimitry Andric void print(raw_ostream &OS) const override {
263bdd1243dSDimitry Andric switch (Kind) {
264bdd1243dSDimitry Andric case Immediate:
265bdd1243dSDimitry Andric OS << *getImm();
266bdd1243dSDimitry Andric break;
267bdd1243dSDimitry Andric case Register:
268bdd1243dSDimitry Andric OS << "<register x";
269bdd1243dSDimitry Andric OS << getReg() << ">";
270bdd1243dSDimitry Andric break;
271bdd1243dSDimitry Andric case Token:
272bdd1243dSDimitry Andric OS << "'" << getToken() << "'";
273bdd1243dSDimitry Andric break;
274bdd1243dSDimitry Andric }
275bdd1243dSDimitry Andric }
276bdd1243dSDimitry Andric
createTokenXtensaOperand277bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {
278bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Token);
279bdd1243dSDimitry Andric Op->Tok = Str;
280bdd1243dSDimitry Andric Op->StartLoc = S;
281bdd1243dSDimitry Andric Op->EndLoc = S;
282bdd1243dSDimitry Andric return Op;
283bdd1243dSDimitry Andric }
284bdd1243dSDimitry Andric
createRegXtensaOperand285bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,
286bdd1243dSDimitry Andric SMLoc E) {
287bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Register);
288bdd1243dSDimitry Andric Op->Reg.RegNum = RegNo;
289bdd1243dSDimitry Andric Op->StartLoc = S;
290bdd1243dSDimitry Andric Op->EndLoc = E;
291bdd1243dSDimitry Andric return Op;
292bdd1243dSDimitry Andric }
293bdd1243dSDimitry Andric
createImmXtensaOperand294bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,
295bdd1243dSDimitry Andric SMLoc E) {
296bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Immediate);
297bdd1243dSDimitry Andric Op->Imm.Val = Val;
298bdd1243dSDimitry Andric Op->StartLoc = S;
299bdd1243dSDimitry Andric Op->EndLoc = E;
300bdd1243dSDimitry Andric return Op;
301bdd1243dSDimitry Andric }
302bdd1243dSDimitry Andric
addExprXtensaOperand303bdd1243dSDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const {
304bdd1243dSDimitry Andric assert(Expr && "Expr shouldn't be null!");
305bdd1243dSDimitry Andric int64_t Imm = 0;
306bdd1243dSDimitry Andric bool IsConstant = false;
307bdd1243dSDimitry Andric
308bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
309bdd1243dSDimitry Andric IsConstant = true;
310bdd1243dSDimitry Andric Imm = CE->getValue();
311bdd1243dSDimitry Andric }
312bdd1243dSDimitry Andric
313bdd1243dSDimitry Andric if (IsConstant)
314bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createImm(Imm));
315bdd1243dSDimitry Andric else
316bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr));
317bdd1243dSDimitry Andric }
318bdd1243dSDimitry Andric
319bdd1243dSDimitry Andric // Used by the TableGen Code
addRegOperandsXtensaOperand320bdd1243dSDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const {
321bdd1243dSDimitry Andric assert(N == 1 && "Invalid number of operands!");
322bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createReg(getReg()));
323bdd1243dSDimitry Andric }
324bdd1243dSDimitry Andric
addImmOperandsXtensaOperand325bdd1243dSDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const {
326bdd1243dSDimitry Andric assert(N == 1 && "Invalid number of operands!");
327bdd1243dSDimitry Andric addExpr(Inst, getImm());
328bdd1243dSDimitry Andric }
329bdd1243dSDimitry Andric };
330bdd1243dSDimitry Andric
331bdd1243dSDimitry Andric #define GET_REGISTER_MATCHER
332bdd1243dSDimitry Andric #define GET_MATCHER_IMPLEMENTATION
333bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc"
334bdd1243dSDimitry Andric
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)335bdd1243dSDimitry Andric unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
336bdd1243dSDimitry Andric unsigned Kind) {
337bdd1243dSDimitry Andric return Match_InvalidOperand;
338bdd1243dSDimitry Andric }
339bdd1243dSDimitry Andric
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)340bdd1243dSDimitry Andric static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
341bdd1243dSDimitry Andric uint64_t ErrorInfo) {
342bdd1243dSDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
343bdd1243dSDimitry Andric SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
344bdd1243dSDimitry Andric if (ErrorLoc == SMLoc())
345bdd1243dSDimitry Andric return Loc;
346bdd1243dSDimitry Andric return ErrorLoc;
347bdd1243dSDimitry Andric }
348bdd1243dSDimitry Andric return Loc;
349bdd1243dSDimitry Andric }
350bdd1243dSDimitry Andric
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)351bdd1243dSDimitry Andric bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
352bdd1243dSDimitry Andric OperandVector &Operands,
353bdd1243dSDimitry Andric MCStreamer &Out,
354bdd1243dSDimitry Andric uint64_t &ErrorInfo,
355bdd1243dSDimitry Andric bool MatchingInlineAsm) {
356bdd1243dSDimitry Andric MCInst Inst;
357bdd1243dSDimitry Andric auto Result =
358bdd1243dSDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
359bdd1243dSDimitry Andric
360bdd1243dSDimitry Andric switch (Result) {
361bdd1243dSDimitry Andric default:
362bdd1243dSDimitry Andric break;
363bdd1243dSDimitry Andric case Match_Success:
364bdd1243dSDimitry Andric Inst.setLoc(IDLoc);
365bdd1243dSDimitry Andric Out.emitInstruction(Inst, getSTI());
366bdd1243dSDimitry Andric return false;
367bdd1243dSDimitry Andric case Match_MissingFeature:
368bdd1243dSDimitry Andric return Error(IDLoc, "instruction use requires an option to be enabled");
369bdd1243dSDimitry Andric case Match_MnemonicFail:
370bdd1243dSDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic");
371bdd1243dSDimitry Andric case Match_InvalidOperand: {
372bdd1243dSDimitry Andric SMLoc ErrorLoc = IDLoc;
373bdd1243dSDimitry Andric if (ErrorInfo != ~0U) {
374bdd1243dSDimitry Andric if (ErrorInfo >= Operands.size())
375bdd1243dSDimitry Andric return Error(ErrorLoc, "too few operands for instruction");
376bdd1243dSDimitry Andric
377bdd1243dSDimitry Andric ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();
378bdd1243dSDimitry Andric if (ErrorLoc == SMLoc())
379bdd1243dSDimitry Andric ErrorLoc = IDLoc;
380bdd1243dSDimitry Andric }
381bdd1243dSDimitry Andric return Error(ErrorLoc, "invalid operand for instruction");
382bdd1243dSDimitry Andric }
383bdd1243dSDimitry Andric case Match_InvalidImm8:
384bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
385bdd1243dSDimitry Andric "expected immediate in range [-128, 127]");
386bdd1243dSDimitry Andric case Match_InvalidImm8_sh8:
387bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
388bdd1243dSDimitry Andric "expected immediate in range [-32768, 32512], first 8 bits "
389bdd1243dSDimitry Andric "should be zero");
390bdd1243dSDimitry Andric case Match_InvalidB4const:
391bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
392bdd1243dSDimitry Andric "expected b4const immediate");
393bdd1243dSDimitry Andric case Match_InvalidB4constu:
394bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
395bdd1243dSDimitry Andric "expected b4constu immediate");
396bdd1243dSDimitry Andric case Match_InvalidImm12:
397bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
398bdd1243dSDimitry Andric "expected immediate in range [-2048, 2047]");
399bdd1243dSDimitry Andric case Match_InvalidImm12m:
400bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
401bdd1243dSDimitry Andric "expected immediate in range [-2048, 2047]");
402bdd1243dSDimitry Andric case Match_InvalidImm1_16:
403bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
404bdd1243dSDimitry Andric "expected immediate in range [1, 16]");
405bdd1243dSDimitry Andric case Match_InvalidShimm1_31:
406bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
407bdd1243dSDimitry Andric "expected immediate in range [1, 31]");
408bdd1243dSDimitry Andric case Match_InvalidUimm4:
409bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
410bdd1243dSDimitry Andric "expected immediate in range [0, 15]");
411bdd1243dSDimitry Andric case Match_InvalidUimm5:
412bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
413bdd1243dSDimitry Andric "expected immediate in range [0, 31]");
414bdd1243dSDimitry Andric case Match_InvalidOffset8m8:
415bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
416bdd1243dSDimitry Andric "expected immediate in range [0, 255]");
417bdd1243dSDimitry Andric case Match_InvalidOffset8m16:
418bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
419bdd1243dSDimitry Andric "expected immediate in range [0, 510], first bit "
420bdd1243dSDimitry Andric "should be zero");
421bdd1243dSDimitry Andric case Match_InvalidOffset8m32:
422bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
423bdd1243dSDimitry Andric "expected immediate in range [0, 1020], first 2 bits "
424bdd1243dSDimitry Andric "should be zero");
425bdd1243dSDimitry Andric case Match_InvalidOffset4m32:
426bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
427bdd1243dSDimitry Andric "expected immediate in range [0, 60], first 2 bits "
428bdd1243dSDimitry Andric "should be zero");
429bdd1243dSDimitry Andric }
430bdd1243dSDimitry Andric
431bdd1243dSDimitry Andric report_fatal_error("Unknown match type detected!");
432bdd1243dSDimitry Andric }
433bdd1243dSDimitry Andric
parsePCRelTarget(OperandVector & Operands)434*5f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
435bdd1243dSDimitry Andric MCAsmParser &Parser = getParser();
436bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
437bdd1243dSDimitry Andric
438bdd1243dSDimitry Andric SMLoc S = getLexer().getLoc();
439bdd1243dSDimitry Andric
440bdd1243dSDimitry Andric // Expressions are acceptable
441bdd1243dSDimitry Andric const MCExpr *Expr = nullptr;
442bdd1243dSDimitry Andric if (Parser.parseExpression(Expr)) {
443bdd1243dSDimitry Andric // We have no way of knowing if a symbol was consumed so we must ParseFail
444*5f757f3fSDimitry Andric return ParseStatus::Failure;
445bdd1243dSDimitry Andric }
446bdd1243dSDimitry Andric
447bdd1243dSDimitry Andric // Currently not support constants
448*5f757f3fSDimitry Andric if (Expr->getKind() == MCExpr::ExprKind::Constant)
449*5f757f3fSDimitry Andric return Error(getLoc(), "unknown operand");
450bdd1243dSDimitry Andric
451bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
452*5f757f3fSDimitry Andric return ParseStatus::Success;
453bdd1243dSDimitry Andric }
454bdd1243dSDimitry Andric
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)455*5f757f3fSDimitry Andric bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
456bdd1243dSDimitry Andric SMLoc &EndLoc) {
457bdd1243dSDimitry Andric const AsmToken &Tok = getParser().getTok();
458bdd1243dSDimitry Andric StartLoc = Tok.getLoc();
459bdd1243dSDimitry Andric EndLoc = Tok.getEndLoc();
460*5f757f3fSDimitry Andric Reg = Xtensa::NoRegister;
461bdd1243dSDimitry Andric StringRef Name = getLexer().getTok().getIdentifier();
462bdd1243dSDimitry Andric
463bdd1243dSDimitry Andric if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {
464bdd1243dSDimitry Andric getParser().Lex(); // Eat identifier token.
465bdd1243dSDimitry Andric return false;
466bdd1243dSDimitry Andric }
467bdd1243dSDimitry Andric
468bdd1243dSDimitry Andric return Error(StartLoc, "invalid register name");
469bdd1243dSDimitry Andric }
470bdd1243dSDimitry Andric
parseRegister(OperandVector & Operands,bool AllowParens,bool SR)471*5f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
472bdd1243dSDimitry Andric bool AllowParens, bool SR) {
473bdd1243dSDimitry Andric SMLoc FirstS = getLoc();
474bdd1243dSDimitry Andric bool HadParens = false;
475bdd1243dSDimitry Andric AsmToken Buf[2];
476bdd1243dSDimitry Andric StringRef RegName;
477bdd1243dSDimitry Andric
478bdd1243dSDimitry Andric // If this a parenthesised register name is allowed, parse it atomically
479bdd1243dSDimitry Andric if (AllowParens && getLexer().is(AsmToken::LParen)) {
480bdd1243dSDimitry Andric size_t ReadCount = getLexer().peekTokens(Buf);
481bdd1243dSDimitry Andric if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
482bdd1243dSDimitry Andric if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))
483*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
484bdd1243dSDimitry Andric HadParens = true;
485bdd1243dSDimitry Andric getParser().Lex(); // Eat '('
486bdd1243dSDimitry Andric }
487bdd1243dSDimitry Andric }
488bdd1243dSDimitry Andric
489bdd1243dSDimitry Andric unsigned RegNo = 0;
490bdd1243dSDimitry Andric
491bdd1243dSDimitry Andric switch (getLexer().getKind()) {
492bdd1243dSDimitry Andric default:
493*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
494bdd1243dSDimitry Andric case AsmToken::Integer:
495bdd1243dSDimitry Andric if (!SR)
496*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
497bdd1243dSDimitry Andric RegName = StringRef(std::to_string(getLexer().getTok().getIntVal()));
498bdd1243dSDimitry Andric RegNo = MatchRegisterName(RegName);
499bdd1243dSDimitry Andric if (RegNo == 0)
500bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName);
501bdd1243dSDimitry Andric break;
502bdd1243dSDimitry Andric case AsmToken::Identifier:
503bdd1243dSDimitry Andric RegName = getLexer().getTok().getIdentifier();
504bdd1243dSDimitry Andric RegNo = MatchRegisterName(RegName);
505bdd1243dSDimitry Andric if (RegNo == 0)
506bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName);
507bdd1243dSDimitry Andric break;
508bdd1243dSDimitry Andric }
509bdd1243dSDimitry Andric
510bdd1243dSDimitry Andric if (RegNo == 0) {
511bdd1243dSDimitry Andric if (HadParens)
512bdd1243dSDimitry Andric getLexer().UnLex(Buf[0]);
513*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
514bdd1243dSDimitry Andric }
515bdd1243dSDimitry Andric if (HadParens)
516bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken("(", FirstS));
517bdd1243dSDimitry Andric SMLoc S = getLoc();
518bdd1243dSDimitry Andric SMLoc E = getParser().getTok().getEndLoc();
519bdd1243dSDimitry Andric getLexer().Lex();
520bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
521bdd1243dSDimitry Andric
522bdd1243dSDimitry Andric if (HadParens) {
523bdd1243dSDimitry Andric getParser().Lex(); // Eat ')'
524bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(")", getLoc()));
525bdd1243dSDimitry Andric }
526bdd1243dSDimitry Andric
527*5f757f3fSDimitry Andric return ParseStatus::Success;
528bdd1243dSDimitry Andric }
529bdd1243dSDimitry Andric
parseImmediate(OperandVector & Operands)530*5f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
531bdd1243dSDimitry Andric SMLoc S = getLoc();
532bdd1243dSDimitry Andric SMLoc E;
533bdd1243dSDimitry Andric const MCExpr *Res;
534bdd1243dSDimitry Andric
535bdd1243dSDimitry Andric switch (getLexer().getKind()) {
536bdd1243dSDimitry Andric default:
537*5f757f3fSDimitry Andric return ParseStatus::NoMatch;
538bdd1243dSDimitry Andric case AsmToken::LParen:
539bdd1243dSDimitry Andric case AsmToken::Minus:
540bdd1243dSDimitry Andric case AsmToken::Plus:
541bdd1243dSDimitry Andric case AsmToken::Tilde:
542bdd1243dSDimitry Andric case AsmToken::Integer:
543bdd1243dSDimitry Andric case AsmToken::String:
544bdd1243dSDimitry Andric if (getParser().parseExpression(Res))
545*5f757f3fSDimitry Andric return ParseStatus::Failure;
546bdd1243dSDimitry Andric break;
547bdd1243dSDimitry Andric case AsmToken::Identifier: {
548bdd1243dSDimitry Andric StringRef Identifier;
549bdd1243dSDimitry Andric if (getParser().parseIdentifier(Identifier))
550*5f757f3fSDimitry Andric return ParseStatus::Failure;
551bdd1243dSDimitry Andric
552bdd1243dSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
553bdd1243dSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
554bdd1243dSDimitry Andric break;
555bdd1243dSDimitry Andric }
556bdd1243dSDimitry Andric case AsmToken::Percent:
557bdd1243dSDimitry Andric return parseOperandWithModifier(Operands);
558bdd1243dSDimitry Andric }
559bdd1243dSDimitry Andric
560bdd1243dSDimitry Andric E = SMLoc::getFromPointer(S.getPointer() - 1);
561bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createImm(Res, S, E));
562*5f757f3fSDimitry Andric return ParseStatus::Success;
563bdd1243dSDimitry Andric }
564bdd1243dSDimitry Andric
parseOperandWithModifier(OperandVector & Operands)565*5f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
566*5f757f3fSDimitry Andric return ParseStatus::Failure;
567bdd1243dSDimitry Andric }
568bdd1243dSDimitry Andric
569bdd1243dSDimitry Andric /// Looks at a token type and creates the relevant operand
570bdd1243dSDimitry Andric /// from this information, adding to Operands.
571bdd1243dSDimitry Andric /// If operand was parsed, returns false, else true.
parseOperand(OperandVector & Operands,StringRef Mnemonic,bool SR)572bdd1243dSDimitry Andric bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
573bdd1243dSDimitry Andric bool SR) {
574bdd1243dSDimitry Andric // Check if the current operand has a custom associated parser, if so, try to
575bdd1243dSDimitry Andric // custom parse the operand, or fallback to the general approach.
576*5f757f3fSDimitry Andric ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
577*5f757f3fSDimitry Andric if (Res.isSuccess())
578bdd1243dSDimitry Andric return false;
579bdd1243dSDimitry Andric
580bdd1243dSDimitry Andric // If there wasn't a custom match, try the generic matcher below. Otherwise,
581bdd1243dSDimitry Andric // there was a match, but an error occurred, in which case, just return that
582bdd1243dSDimitry Andric // the operand parsing failed.
583*5f757f3fSDimitry Andric if (Res.isFailure())
584bdd1243dSDimitry Andric return true;
585bdd1243dSDimitry Andric
586bdd1243dSDimitry Andric // Attempt to parse token as register
587*5f757f3fSDimitry Andric if (parseRegister(Operands, true, SR).isSuccess())
588bdd1243dSDimitry Andric return false;
589bdd1243dSDimitry Andric
590bdd1243dSDimitry Andric // Attempt to parse token as an immediate
591*5f757f3fSDimitry Andric if (parseImmediate(Operands).isSuccess())
592bdd1243dSDimitry Andric return false;
593bdd1243dSDimitry Andric
594bdd1243dSDimitry Andric // Finally we have exhausted all options and must declare defeat.
595*5f757f3fSDimitry Andric return Error(getLoc(), "unknown operand");
596bdd1243dSDimitry Andric }
597bdd1243dSDimitry Andric
ParseInstructionWithSR(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)598bdd1243dSDimitry Andric bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
599bdd1243dSDimitry Andric StringRef Name, SMLoc NameLoc,
600bdd1243dSDimitry Andric OperandVector &Operands) {
601*5f757f3fSDimitry Andric if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||
602*5f757f3fSDimitry Andric Name.starts_with("xsr.")) &&
603bdd1243dSDimitry Andric (Name.size() > 4)) {
604bdd1243dSDimitry Andric // Parse case when instruction name is concatenated with SR register
605bdd1243dSDimitry Andric // name, like "wsr.sar a1"
606bdd1243dSDimitry Andric
607bdd1243dSDimitry Andric // First operand is token for instruction
608bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
609bdd1243dSDimitry Andric
610bdd1243dSDimitry Andric StringRef RegName = Name.drop_front(4);
611bdd1243dSDimitry Andric unsigned RegNo = MatchRegisterName(RegName);
612bdd1243dSDimitry Andric
613bdd1243dSDimitry Andric if (RegNo == 0)
614bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName);
615bdd1243dSDimitry Andric
616*5f757f3fSDimitry Andric if (RegNo == 0)
617*5f757f3fSDimitry Andric return Error(NameLoc, "invalid register name");
618bdd1243dSDimitry Andric
619bdd1243dSDimitry Andric // Parse operand
620bdd1243dSDimitry Andric if (parseOperand(Operands, Name))
621bdd1243dSDimitry Andric return true;
622bdd1243dSDimitry Andric
623bdd1243dSDimitry Andric SMLoc S = getLoc();
624bdd1243dSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
625bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
626bdd1243dSDimitry Andric } else {
627bdd1243dSDimitry Andric // First operand is token for instruction
628bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
629bdd1243dSDimitry Andric
630bdd1243dSDimitry Andric // Parse first operand
631bdd1243dSDimitry Andric if (parseOperand(Operands, Name))
632bdd1243dSDimitry Andric return true;
633bdd1243dSDimitry Andric
63406c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) {
635bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc();
636bdd1243dSDimitry Andric getParser().eatToEndOfStatement();
637bdd1243dSDimitry Andric return Error(Loc, "unexpected token");
638bdd1243dSDimitry Andric }
639bdd1243dSDimitry Andric
640bdd1243dSDimitry Andric // Parse second operand
641bdd1243dSDimitry Andric if (parseOperand(Operands, Name, true))
642bdd1243dSDimitry Andric return true;
643bdd1243dSDimitry Andric }
644bdd1243dSDimitry Andric
645bdd1243dSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
646bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc();
647bdd1243dSDimitry Andric getParser().eatToEndOfStatement();
648bdd1243dSDimitry Andric return Error(Loc, "unexpected token");
649bdd1243dSDimitry Andric }
650bdd1243dSDimitry Andric
651bdd1243dSDimitry Andric getParser().Lex(); // Consume the EndOfStatement.
652bdd1243dSDimitry Andric return false;
653bdd1243dSDimitry Andric }
654bdd1243dSDimitry Andric
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)655bdd1243dSDimitry Andric bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
656bdd1243dSDimitry Andric StringRef Name, SMLoc NameLoc,
657bdd1243dSDimitry Andric OperandVector &Operands) {
658*5f757f3fSDimitry Andric if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
659*5f757f3fSDimitry Andric Name.starts_with("xsr")) {
660bdd1243dSDimitry Andric return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
661bdd1243dSDimitry Andric }
662bdd1243dSDimitry Andric
663bdd1243dSDimitry Andric // First operand is token for instruction
664bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
665bdd1243dSDimitry Andric
666bdd1243dSDimitry Andric // If there are no more operands, then finish
667bdd1243dSDimitry Andric if (getLexer().is(AsmToken::EndOfStatement))
668bdd1243dSDimitry Andric return false;
669bdd1243dSDimitry Andric
670bdd1243dSDimitry Andric // Parse first operand
671bdd1243dSDimitry Andric if (parseOperand(Operands, Name))
672bdd1243dSDimitry Andric return true;
673bdd1243dSDimitry Andric
674bdd1243dSDimitry Andric // Parse until end of statement, consuming commas between operands
67506c3fb27SDimitry Andric while (parseOptionalToken(AsmToken::Comma))
676bdd1243dSDimitry Andric if (parseOperand(Operands, Name))
677bdd1243dSDimitry Andric return true;
678bdd1243dSDimitry Andric
679bdd1243dSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
680bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc();
681bdd1243dSDimitry Andric getParser().eatToEndOfStatement();
682bdd1243dSDimitry Andric return Error(Loc, "unexpected token");
683bdd1243dSDimitry Andric }
684bdd1243dSDimitry Andric
685bdd1243dSDimitry Andric getParser().Lex(); // Consume the EndOfStatement.
686bdd1243dSDimitry Andric return false;
687bdd1243dSDimitry Andric }
688bdd1243dSDimitry Andric
689bdd1243dSDimitry Andric // Force static initialization.
LLVMInitializeXtensaAsmParser()690bdd1243dSDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
691bdd1243dSDimitry Andric RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
692bdd1243dSDimitry Andric }
693