File: | lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp |
Warning: | line 504, column 28 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MSP430AsmParser.cpp - Parse MSP430 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 | //===----------------------------------------------------------------------===// | |||
8 | ||||
9 | #include "MSP430.h" | |||
10 | #include "MSP430RegisterInfo.h" | |||
11 | #include "MCTargetDesc/MSP430MCTargetDesc.h" | |||
12 | #include "TargetInfo/MSP430TargetInfo.h" | |||
13 | ||||
14 | #include "llvm/ADT/APInt.h" | |||
15 | #include "llvm/ADT/StringSwitch.h" | |||
16 | #include "llvm/MC/MCContext.h" | |||
17 | #include "llvm/MC/MCExpr.h" | |||
18 | #include "llvm/MC/MCInst.h" | |||
19 | #include "llvm/MC/MCInstBuilder.h" | |||
20 | #include "llvm/MC/MCParser/MCAsmLexer.h" | |||
21 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" | |||
22 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" | |||
23 | #include "llvm/MC/MCStreamer.h" | |||
24 | #include "llvm/MC/MCSubtargetInfo.h" | |||
25 | #include "llvm/MC/MCSymbol.h" | |||
26 | #include "llvm/MC/MCValue.h" | |||
27 | #include "llvm/Support/Debug.h" | |||
28 | #include "llvm/Support/MathExtras.h" | |||
29 | #include "llvm/Support/TargetRegistry.h" | |||
30 | ||||
31 | #define DEBUG_TYPE"msp430-asm-parser" "msp430-asm-parser" | |||
32 | ||||
33 | using namespace llvm; | |||
34 | ||||
35 | namespace { | |||
36 | ||||
37 | /// Parses MSP430 assembly from a stream. | |||
38 | class MSP430AsmParser : public MCTargetAsmParser { | |||
39 | const MCSubtargetInfo &STI; | |||
40 | MCAsmParser &Parser; | |||
41 | const MCRegisterInfo *MRI; | |||
42 | ||||
43 | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | |||
44 | OperandVector &Operands, MCStreamer &Out, | |||
45 | uint64_t &ErrorInfo, | |||
46 | bool MatchingInlineAsm) override; | |||
47 | ||||
48 | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; | |||
49 | ||||
50 | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | |||
51 | SMLoc NameLoc, OperandVector &Operands) override; | |||
52 | ||||
53 | bool ParseDirective(AsmToken DirectiveID) override; | |||
54 | bool ParseDirectiveRefSym(AsmToken DirectiveID); | |||
55 | ||||
56 | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, | |||
57 | unsigned Kind) override; | |||
58 | ||||
59 | bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name, | |||
60 | SMLoc NameLoc, OperandVector &Operands); | |||
61 | ||||
62 | bool ParseOperand(OperandVector &Operands); | |||
63 | ||||
64 | bool ParseLiteralValues(unsigned Size, SMLoc L); | |||
65 | ||||
66 | MCAsmParser &getParser() const { return Parser; } | |||
67 | MCAsmLexer &getLexer() const { return Parser.getLexer(); } | |||
68 | ||||
69 | /// @name Auto-generated Matcher Functions | |||
70 | /// { | |||
71 | ||||
72 | #define GET_ASSEMBLER_HEADER | |||
73 | #include "MSP430GenAsmMatcher.inc" | |||
74 | ||||
75 | /// } | |||
76 | ||||
77 | public: | |||
78 | MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, | |||
79 | const MCInstrInfo &MII, const MCTargetOptions &Options) | |||
80 | : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) { | |||
81 | MCAsmParserExtension::Initialize(Parser); | |||
82 | MRI = getContext().getRegisterInfo(); | |||
83 | ||||
84 | setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); | |||
85 | } | |||
86 | }; | |||
87 | ||||
88 | /// A parsed MSP430 assembly operand. | |||
89 | class MSP430Operand : public MCParsedAsmOperand { | |||
90 | typedef MCParsedAsmOperand Base; | |||
91 | ||||
92 | enum KindTy { | |||
93 | k_Imm, | |||
94 | k_Reg, | |||
95 | k_Tok, | |||
96 | k_Mem, | |||
97 | k_IndReg, | |||
98 | k_PostIndReg | |||
99 | } Kind; | |||
100 | ||||
101 | struct Memory { | |||
102 | unsigned Reg; | |||
103 | const MCExpr *Offset; | |||
104 | }; | |||
105 | union { | |||
106 | const MCExpr *Imm; | |||
107 | unsigned Reg; | |||
108 | StringRef Tok; | |||
109 | Memory Mem; | |||
110 | }; | |||
111 | ||||
112 | SMLoc Start, End; | |||
113 | ||||
114 | public: | |||
115 | MSP430Operand(StringRef Tok, SMLoc const &S) | |||
116 | : Base(), Kind(k_Tok), Tok(Tok), Start(S), End(S) {} | |||
117 | MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E) | |||
118 | : Base(), Kind(Kind), Reg(Reg), Start(S), End(E) {} | |||
119 | MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E) | |||
120 | : Base(), Kind(k_Imm), Imm(Imm), Start(S), End(E) {} | |||
121 | MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S, SMLoc const &E) | |||
122 | : Base(), Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {} | |||
123 | ||||
124 | void addRegOperands(MCInst &Inst, unsigned N) const { | |||
125 | assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&(((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && "Unexpected operand kind") ? static_cast<void> (0) : __assert_fail ("(Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && \"Unexpected operand kind\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 126, __PRETTY_FUNCTION__)) | |||
126 | "Unexpected operand kind")(((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && "Unexpected operand kind") ? static_cast<void> (0) : __assert_fail ("(Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && \"Unexpected operand kind\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 126, __PRETTY_FUNCTION__)); | |||
127 | assert(N == 1 && "Invalid number of operands!")((N == 1 && "Invalid number of operands!") ? static_cast <void> (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 127, __PRETTY_FUNCTION__)); | |||
128 | ||||
129 | Inst.addOperand(MCOperand::createReg(Reg)); | |||
130 | } | |||
131 | ||||
132 | void addExprOperand(MCInst &Inst, const MCExpr *Expr) const { | |||
133 | // Add as immediate when possible | |||
134 | if (!Expr) | |||
135 | Inst.addOperand(MCOperand::createImm(0)); | |||
136 | else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) | |||
137 | Inst.addOperand(MCOperand::createImm(CE->getValue())); | |||
138 | else | |||
139 | Inst.addOperand(MCOperand::createExpr(Expr)); | |||
140 | } | |||
141 | ||||
142 | void addImmOperands(MCInst &Inst, unsigned N) const { | |||
143 | assert(Kind == k_Imm && "Unexpected operand kind")((Kind == k_Imm && "Unexpected operand kind") ? static_cast <void> (0) : __assert_fail ("Kind == k_Imm && \"Unexpected operand kind\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 143, __PRETTY_FUNCTION__)); | |||
144 | assert(N == 1 && "Invalid number of operands!")((N == 1 && "Invalid number of operands!") ? static_cast <void> (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 144, __PRETTY_FUNCTION__)); | |||
145 | ||||
146 | addExprOperand(Inst, Imm); | |||
147 | } | |||
148 | ||||
149 | void addMemOperands(MCInst &Inst, unsigned N) const { | |||
150 | assert(Kind == k_Mem && "Unexpected operand kind")((Kind == k_Mem && "Unexpected operand kind") ? static_cast <void> (0) : __assert_fail ("Kind == k_Mem && \"Unexpected operand kind\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 150, __PRETTY_FUNCTION__)); | |||
151 | assert(N == 2 && "Invalid number of operands")((N == 2 && "Invalid number of operands") ? static_cast <void> (0) : __assert_fail ("N == 2 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 151, __PRETTY_FUNCTION__)); | |||
152 | ||||
153 | Inst.addOperand(MCOperand::createReg(Mem.Reg)); | |||
154 | addExprOperand(Inst, Mem.Offset); | |||
155 | } | |||
156 | ||||
157 | bool isReg() const { return Kind == k_Reg; } | |||
158 | bool isImm() const { return Kind == k_Imm; } | |||
159 | bool isToken() const { return Kind == k_Tok; } | |||
160 | bool isMem() const { return Kind == k_Mem; } | |||
161 | bool isIndReg() const { return Kind == k_IndReg; } | |||
162 | bool isPostIndReg() const { return Kind == k_PostIndReg; } | |||
163 | ||||
164 | bool isCGImm() const { | |||
165 | if (Kind != k_Imm) | |||
166 | return false; | |||
167 | ||||
168 | int64_t Val; | |||
169 | if (!Imm->evaluateAsAbsolute(Val)) | |||
170 | return false; | |||
171 | ||||
172 | if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1) | |||
173 | return true; | |||
174 | ||||
175 | return false; | |||
176 | } | |||
177 | ||||
178 | StringRef getToken() const { | |||
179 | assert(Kind == k_Tok && "Invalid access!")((Kind == k_Tok && "Invalid access!") ? static_cast< void> (0) : __assert_fail ("Kind == k_Tok && \"Invalid access!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 179, __PRETTY_FUNCTION__)); | |||
180 | return Tok; | |||
181 | } | |||
182 | ||||
183 | unsigned getReg() const { | |||
184 | assert(Kind == k_Reg && "Invalid access!")((Kind == k_Reg && "Invalid access!") ? static_cast< void> (0) : __assert_fail ("Kind == k_Reg && \"Invalid access!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 184, __PRETTY_FUNCTION__)); | |||
185 | return Reg; | |||
186 | } | |||
187 | ||||
188 | void setReg(unsigned RegNo) { | |||
189 | assert(Kind == k_Reg && "Invalid access!")((Kind == k_Reg && "Invalid access!") ? static_cast< void> (0) : __assert_fail ("Kind == k_Reg && \"Invalid access!\"" , "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 189, __PRETTY_FUNCTION__)); | |||
190 | Reg = RegNo; | |||
191 | } | |||
192 | ||||
193 | static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) { | |||
194 | return make_unique<MSP430Operand>(Str, S); | |||
195 | } | |||
196 | ||||
197 | static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S, | |||
198 | SMLoc E) { | |||
199 | return make_unique<MSP430Operand>(k_Reg, RegNum, S, E); | |||
200 | } | |||
201 | ||||
202 | static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S, | |||
203 | SMLoc E) { | |||
204 | return make_unique<MSP430Operand>(Val, S, E); | |||
205 | } | |||
206 | ||||
207 | static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum, | |||
208 | const MCExpr *Val, | |||
209 | SMLoc S, SMLoc E) { | |||
210 | return make_unique<MSP430Operand>(RegNum, Val, S, E); | |||
211 | } | |||
212 | ||||
213 | static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S, | |||
214 | SMLoc E) { | |||
215 | return make_unique<MSP430Operand>(k_IndReg, RegNum, S, E); | |||
216 | } | |||
217 | ||||
218 | static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S, | |||
219 | SMLoc E) { | |||
220 | return make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E); | |||
221 | } | |||
222 | ||||
223 | SMLoc getStartLoc() const { return Start; } | |||
224 | SMLoc getEndLoc() const { return End; } | |||
225 | ||||
226 | virtual void print(raw_ostream &O) const { | |||
227 | switch (Kind) { | |||
228 | case k_Tok: | |||
229 | O << "Token " << Tok; | |||
230 | break; | |||
231 | case k_Reg: | |||
232 | O << "Register " << Reg; | |||
233 | break; | |||
234 | case k_Imm: | |||
235 | O << "Immediate " << *Imm; | |||
236 | break; | |||
237 | case k_Mem: | |||
238 | O << "Memory "; | |||
239 | O << *Mem.Offset << "(" << Reg << ")"; | |||
240 | break; | |||
241 | case k_IndReg: | |||
242 | O << "RegInd " << Reg; | |||
243 | break; | |||
244 | case k_PostIndReg: | |||
245 | O << "PostInc " << Reg; | |||
246 | break; | |||
247 | } | |||
248 | } | |||
249 | }; | |||
250 | } // end anonymous namespace | |||
251 | ||||
252 | bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, | |||
253 | OperandVector &Operands, | |||
254 | MCStreamer &Out, | |||
255 | uint64_t &ErrorInfo, | |||
256 | bool MatchingInlineAsm) { | |||
257 | MCInst Inst; | |||
258 | unsigned MatchResult = | |||
259 | MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); | |||
260 | ||||
261 | switch (MatchResult) { | |||
262 | case Match_Success: | |||
263 | Inst.setLoc(Loc); | |||
264 | Out.EmitInstruction(Inst, STI); | |||
265 | return false; | |||
266 | case Match_MnemonicFail: | |||
267 | return Error(Loc, "invalid instruction mnemonic"); | |||
268 | case Match_InvalidOperand: { | |||
269 | SMLoc ErrorLoc = Loc; | |||
270 | if (ErrorInfo != ~0U) { | |||
271 | if (ErrorInfo >= Operands.size()) | |||
272 | return Error(ErrorLoc, "too few operands for instruction"); | |||
273 | ||||
274 | ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc(); | |||
275 | if (ErrorLoc == SMLoc()) | |||
276 | ErrorLoc = Loc; | |||
277 | } | |||
278 | return Error(ErrorLoc, "invalid operand for instruction"); | |||
279 | } | |||
280 | default: | |||
281 | return true; | |||
282 | } | |||
283 | } | |||
284 | ||||
285 | // Auto-generated by TableGen | |||
286 | static unsigned MatchRegisterName(StringRef Name); | |||
287 | static unsigned MatchRegisterAltName(StringRef Name); | |||
288 | ||||
289 | bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, | |||
290 | SMLoc &EndLoc) { | |||
291 | if (getLexer().getKind() == AsmToken::Identifier) { | |||
292 | auto Name = getLexer().getTok().getIdentifier().lower(); | |||
293 | RegNo = MatchRegisterName(Name); | |||
294 | if (RegNo == MSP430::NoRegister) { | |||
295 | RegNo = MatchRegisterAltName(Name); | |||
296 | if (RegNo == MSP430::NoRegister) | |||
297 | return true; | |||
298 | } | |||
299 | ||||
300 | AsmToken const &T = getParser().getTok(); | |||
301 | StartLoc = T.getLoc(); | |||
302 | EndLoc = T.getEndLoc(); | |||
303 | getLexer().Lex(); // eat register token | |||
304 | ||||
305 | return false; | |||
306 | } | |||
307 | ||||
308 | return Error(StartLoc, "invalid register name"); | |||
309 | } | |||
310 | ||||
311 | bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info, | |||
312 | StringRef Name, SMLoc NameLoc, | |||
313 | OperandVector &Operands) { | |||
314 | if (!Name.startswith_lower("j")) | |||
315 | return true; | |||
316 | ||||
317 | auto CC = Name.drop_front().lower(); | |||
318 | unsigned CondCode; | |||
319 | if (CC == "ne" || CC == "nz") | |||
320 | CondCode = MSP430CC::COND_NE; | |||
321 | else if (CC == "eq" || CC == "z") | |||
322 | CondCode = MSP430CC::COND_E; | |||
323 | else if (CC == "lo" || CC == "nc") | |||
324 | CondCode = MSP430CC::COND_LO; | |||
325 | else if (CC == "hs" || CC == "c") | |||
326 | CondCode = MSP430CC::COND_HS; | |||
327 | else if (CC == "n") | |||
328 | CondCode = MSP430CC::COND_N; | |||
329 | else if (CC == "ge") | |||
330 | CondCode = MSP430CC::COND_GE; | |||
331 | else if (CC == "l") | |||
332 | CondCode = MSP430CC::COND_L; | |||
333 | else if (CC == "mp") | |||
334 | CondCode = MSP430CC::COND_NONE; | |||
335 | else | |||
336 | return Error(NameLoc, "unknown instruction"); | |||
337 | ||||
338 | if (CondCode == (unsigned)MSP430CC::COND_NONE) | |||
339 | Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc)); | |||
340 | else { | |||
341 | Operands.push_back(MSP430Operand::CreateToken("j", NameLoc)); | |||
342 | const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext()); | |||
343 | Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc())); | |||
344 | } | |||
345 | ||||
346 | // Skip optional '$' sign. | |||
347 | if (getLexer().getKind() == AsmToken::Dollar) | |||
348 | getLexer().Lex(); // Eat '$' | |||
349 | ||||
350 | const MCExpr *Val; | |||
351 | SMLoc ExprLoc = getLexer().getLoc(); | |||
352 | if (getParser().parseExpression(Val)) | |||
353 | return Error(ExprLoc, "expected expression operand"); | |||
354 | ||||
355 | int64_t Res; | |||
356 | if (Val->evaluateAsAbsolute(Res)) | |||
357 | if (Res < -512 || Res > 511) | |||
358 | return Error(ExprLoc, "invalid jump offset"); | |||
359 | ||||
360 | Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc, | |||
361 | getLexer().getLoc())); | |||
362 | ||||
363 | if (getLexer().isNot(AsmToken::EndOfStatement)) { | |||
364 | SMLoc Loc = getLexer().getLoc(); | |||
365 | getParser().eatToEndOfStatement(); | |||
366 | return Error(Loc, "unexpected token"); | |||
367 | } | |||
368 | ||||
369 | getParser().Lex(); // Consume the EndOfStatement. | |||
370 | return false; | |||
371 | } | |||
372 | ||||
373 | bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info, | |||
374 | StringRef Name, SMLoc NameLoc, | |||
375 | OperandVector &Operands) { | |||
376 | // Drop .w suffix | |||
377 | if (Name.endswith_lower(".w")) | |||
| ||||
378 | Name = Name.drop_back(2); | |||
379 | ||||
380 | if (!parseJccInstruction(Info, Name, NameLoc, Operands)) | |||
381 | return false; | |||
382 | ||||
383 | // First operand is instruction mnemonic | |||
384 | Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc)); | |||
385 | ||||
386 | // If there are no more operands, then finish | |||
387 | if (getLexer().is(AsmToken::EndOfStatement)) | |||
388 | return false; | |||
389 | ||||
390 | // Parse first operand | |||
391 | if (ParseOperand(Operands)) | |||
392 | return true; | |||
393 | ||||
394 | // Parse second operand if any | |||
395 | if (getLexer().is(AsmToken::Comma)) { | |||
396 | getLexer().Lex(); // Eat ',' | |||
397 | if (ParseOperand(Operands)) | |||
398 | return true; | |||
399 | } | |||
400 | ||||
401 | if (getLexer().isNot(AsmToken::EndOfStatement)) { | |||
402 | SMLoc Loc = getLexer().getLoc(); | |||
403 | getParser().eatToEndOfStatement(); | |||
404 | return Error(Loc, "unexpected token"); | |||
405 | } | |||
406 | ||||
407 | getParser().Lex(); // Consume the EndOfStatement. | |||
408 | return false; | |||
409 | } | |||
410 | ||||
411 | bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) { | |||
412 | StringRef Name; | |||
413 | if (getParser().parseIdentifier(Name)) | |||
414 | return TokError("expected identifier in directive"); | |||
415 | ||||
416 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); | |||
417 | getStreamer().EmitSymbolAttribute(Sym, MCSA_Global); | |||
418 | return false; | |||
419 | } | |||
420 | ||||
421 | bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) { | |||
422 | StringRef IDVal = DirectiveID.getIdentifier(); | |||
423 | if (IDVal.lower() == ".long") { | |||
424 | ParseLiteralValues(4, DirectiveID.getLoc()); | |||
425 | } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { | |||
426 | ParseLiteralValues(2, DirectiveID.getLoc()); | |||
427 | } else if (IDVal.lower() == ".byte") { | |||
428 | ParseLiteralValues(1, DirectiveID.getLoc()); | |||
429 | } else if (IDVal.lower() == ".refsym") { | |||
430 | return ParseDirectiveRefSym(DirectiveID); | |||
431 | } | |||
432 | return true; | |||
433 | } | |||
434 | ||||
435 | bool MSP430AsmParser::ParseOperand(OperandVector &Operands) { | |||
436 | switch (getLexer().getKind()) { | |||
437 | default: return true; | |||
438 | case AsmToken::Identifier: { | |||
439 | // try rN | |||
440 | unsigned RegNo; | |||
441 | SMLoc StartLoc, EndLoc; | |||
442 | if (!ParseRegister(RegNo, StartLoc, EndLoc)) { | |||
443 | Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc)); | |||
444 | return false; | |||
445 | } | |||
446 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
447 | } | |||
448 | case AsmToken::Integer: | |||
449 | case AsmToken::Plus: | |||
450 | case AsmToken::Minus: { | |||
451 | SMLoc StartLoc = getParser().getTok().getLoc(); | |||
452 | const MCExpr *Val; | |||
453 | // Try constexpr[(rN)] | |||
454 | if (!getParser().parseExpression(Val)) { | |||
455 | unsigned RegNo = MSP430::PC; | |||
456 | SMLoc EndLoc = getParser().getTok().getLoc(); | |||
457 | // Try (rN) | |||
458 | if (getLexer().getKind() == AsmToken::LParen) { | |||
459 | getLexer().Lex(); // Eat '(' | |||
460 | SMLoc RegStartLoc; | |||
461 | if (ParseRegister(RegNo, RegStartLoc, EndLoc)) | |||
462 | return true; | |||
463 | if (getLexer().getKind() != AsmToken::RParen) | |||
464 | return true; | |||
465 | EndLoc = getParser().getTok().getEndLoc(); | |||
466 | getLexer().Lex(); // Eat ')' | |||
467 | } | |||
468 | Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc, | |||
469 | EndLoc)); | |||
470 | return false; | |||
471 | } | |||
472 | return true; | |||
473 | } | |||
474 | case AsmToken::Amp: { | |||
475 | // Try &constexpr | |||
476 | SMLoc StartLoc = getParser().getTok().getLoc(); | |||
477 | getLexer().Lex(); // Eat '&' | |||
478 | const MCExpr *Val; | |||
479 | if (!getParser().parseExpression(Val)) { | |||
480 | SMLoc EndLoc = getParser().getTok().getLoc(); | |||
481 | Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc, | |||
482 | EndLoc)); | |||
483 | return false; | |||
484 | } | |||
485 | return true; | |||
486 | } | |||
487 | case AsmToken::At: { | |||
488 | // Try @rN[+] | |||
489 | SMLoc StartLoc = getParser().getTok().getLoc(); | |||
490 | getLexer().Lex(); // Eat '@' | |||
491 | unsigned RegNo; | |||
492 | SMLoc RegStartLoc, EndLoc; | |||
493 | if (ParseRegister(RegNo, RegStartLoc, EndLoc)) | |||
494 | return true; | |||
495 | if (getLexer().getKind() == AsmToken::Plus) { | |||
496 | Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc)); | |||
497 | getLexer().Lex(); // Eat '+' | |||
498 | return false; | |||
499 | } | |||
500 | if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd) | |||
501 | Operands.push_back(MSP430Operand::CreateMem(RegNo, | |||
502 | MCConstantExpr::create(0, getContext()), StartLoc, EndLoc)); | |||
503 | else | |||
504 | Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc)); | |||
| ||||
505 | return false; | |||
506 | } | |||
507 | case AsmToken::Hash: | |||
508 | // Try #constexpr | |||
509 | SMLoc StartLoc = getParser().getTok().getLoc(); | |||
510 | getLexer().Lex(); // Eat '#' | |||
511 | const MCExpr *Val; | |||
512 | if (!getParser().parseExpression(Val)) { | |||
513 | SMLoc EndLoc = getParser().getTok().getLoc(); | |||
514 | Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc)); | |||
515 | return false; | |||
516 | } | |||
517 | return true; | |||
518 | } | |||
519 | } | |||
520 | ||||
521 | bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) { | |||
522 | auto parseOne = [&]() -> bool { | |||
523 | const MCExpr *Value; | |||
524 | if (getParser().parseExpression(Value)) | |||
525 | return true; | |||
526 | getParser().getStreamer().EmitValue(Value, Size, L); | |||
527 | return false; | |||
528 | }; | |||
529 | return (parseMany(parseOne)); | |||
530 | } | |||
531 | ||||
532 | extern "C" void LLVMInitializeMSP430AsmParser() { | |||
533 | RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target()); | |||
534 | } | |||
535 | ||||
536 | #define GET_REGISTER_MATCHER | |||
537 | #define GET_MATCHER_IMPLEMENTATION | |||
538 | #include "MSP430GenAsmMatcher.inc" | |||
539 | ||||
540 | static unsigned convertGR16ToGR8(unsigned Reg) { | |||
541 | switch (Reg) { | |||
542 | default: | |||
543 | llvm_unreachable("Unknown GR16 register")::llvm::llvm_unreachable_internal("Unknown GR16 register", "/build/llvm-toolchain-snapshot-9~svn362543/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp" , 543); | |||
544 | case MSP430::PC: return MSP430::PCB; | |||
545 | case MSP430::SP: return MSP430::SPB; | |||
546 | case MSP430::SR: return MSP430::SRB; | |||
547 | case MSP430::CG: return MSP430::CGB; | |||
548 | case MSP430::FP: return MSP430::FPB; | |||
549 | case MSP430::R5: return MSP430::R5B; | |||
550 | case MSP430::R6: return MSP430::R6B; | |||
551 | case MSP430::R7: return MSP430::R7B; | |||
552 | case MSP430::R8: return MSP430::R8B; | |||
553 | case MSP430::R9: return MSP430::R9B; | |||
554 | case MSP430::R10: return MSP430::R10B; | |||
555 | case MSP430::R11: return MSP430::R11B; | |||
556 | case MSP430::R12: return MSP430::R12B; | |||
557 | case MSP430::R13: return MSP430::R13B; | |||
558 | case MSP430::R14: return MSP430::R14B; | |||
559 | case MSP430::R15: return MSP430::R15B; | |||
560 | } | |||
561 | } | |||
562 | ||||
563 | unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, | |||
564 | unsigned Kind) { | |||
565 | MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp); | |||
566 | ||||
567 | if (!Op.isReg()) | |||
568 | return Match_InvalidOperand; | |||
569 | ||||
570 | unsigned Reg = Op.getReg(); | |||
571 | bool isGR16 = | |||
572 | MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg); | |||
573 | ||||
574 | if (isGR16 && (Kind == MCK_GR8)) { | |||
575 | Op.setReg(convertGR16ToGR8(Reg)); | |||
576 | return Match_Success; | |||
577 | } | |||
578 | ||||
579 | return Match_InvalidOperand; | |||
580 | } |