/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "Lanai.h" |
11 | | #include "LanaiAluCode.h" |
12 | | #include "LanaiCondCode.h" |
13 | | #include "MCTargetDesc/LanaiMCExpr.h" |
14 | | #include "llvm/ADT/STLExtras.h" |
15 | | #include "llvm/ADT/StringRef.h" |
16 | | #include "llvm/ADT/StringSwitch.h" |
17 | | #include "llvm/MC/MCContext.h" |
18 | | #include "llvm/MC/MCExpr.h" |
19 | | #include "llvm/MC/MCInst.h" |
20 | | #include "llvm/MC/MCParser/MCAsmLexer.h" |
21 | | #include "llvm/MC/MCParser/MCAsmParser.h" |
22 | | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
23 | | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
24 | | #include "llvm/MC/MCStreamer.h" |
25 | | #include "llvm/MC/MCSubtargetInfo.h" |
26 | | #include "llvm/MC/MCSymbol.h" |
27 | | #include "llvm/Support/Casting.h" |
28 | | #include "llvm/Support/ErrorHandling.h" |
29 | | #include "llvm/Support/MathExtras.h" |
30 | | #include "llvm/Support/SMLoc.h" |
31 | | #include "llvm/Support/TargetRegistry.h" |
32 | | #include "llvm/Support/raw_ostream.h" |
33 | | #include <algorithm> |
34 | | #include <cassert> |
35 | | #include <cstddef> |
36 | | #include <cstdint> |
37 | | #include <memory> |
38 | | |
39 | | namespace llvm { |
40 | | |
41 | | // Auto-generated by TableGen |
42 | | static unsigned MatchRegisterName(StringRef Name); |
43 | | |
44 | | namespace { |
45 | | |
46 | | struct LanaiOperand; |
47 | | |
48 | | class LanaiAsmParser : public MCTargetAsmParser { |
49 | | // Parse operands |
50 | | std::unique_ptr<LanaiOperand> parseRegister(); |
51 | | |
52 | | std::unique_ptr<LanaiOperand> parseImmediate(); |
53 | | |
54 | | std::unique_ptr<LanaiOperand> parseIdentifier(); |
55 | | |
56 | | unsigned parseAluOperator(bool PreOp, bool PostOp); |
57 | | |
58 | | // Split the mnemonic stripping conditional code and quantifiers |
59 | | StringRef splitMnemonic(StringRef Name, SMLoc NameLoc, |
60 | | OperandVector *Operands); |
61 | | |
62 | | bool parsePrePost(StringRef Type, int *OffsetValue); |
63 | | |
64 | | bool ParseDirective(AsmToken DirectiveID) override; |
65 | | |
66 | | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
67 | | SMLoc NameLoc, OperandVector &Operands) override; |
68 | | |
69 | | bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override; |
70 | | |
71 | | bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode, |
72 | | OperandVector &Operands, MCStreamer &Out, |
73 | | uint64_t &ErrorInfo, |
74 | | bool MatchingInlineAsm) override; |
75 | | |
76 | | // Auto-generated instruction matching functions |
77 | | #define GET_ASSEMBLER_HEADER |
78 | | #include "LanaiGenAsmMatcher.inc" |
79 | | |
80 | | OperandMatchResultTy parseOperand(OperandVector *Operands, |
81 | | StringRef Mnemonic); |
82 | | |
83 | | OperandMatchResultTy parseMemoryOperand(OperandVector &Operands); |
84 | | |
85 | | public: |
86 | | LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, |
87 | | const MCInstrInfo &MII, const MCTargetOptions &Options) |
88 | | : MCTargetAsmParser(Options, STI), Parser(Parser), |
89 | 4 | Lexer(Parser.getLexer()), SubtargetInfo(STI) { |
90 | 4 | setAvailableFeatures( |
91 | 4 | ComputeAvailableFeatures(SubtargetInfo.getFeatureBits())); |
92 | 4 | } |
93 | | |
94 | | private: |
95 | | MCAsmParser &Parser; |
96 | | MCAsmLexer &Lexer; |
97 | | |
98 | | const MCSubtargetInfo &SubtargetInfo; |
99 | | }; |
100 | | |
101 | | // LanaiOperand - Instances of this class represented a parsed machine |
102 | | // instruction |
103 | | struct LanaiOperand : public MCParsedAsmOperand { |
104 | | enum KindTy { |
105 | | TOKEN, |
106 | | REGISTER, |
107 | | IMMEDIATE, |
108 | | MEMORY_IMM, |
109 | | MEMORY_REG_IMM, |
110 | | MEMORY_REG_REG, |
111 | | } Kind; |
112 | | |
113 | | SMLoc StartLoc, EndLoc; |
114 | | |
115 | | struct Token { |
116 | | const char *Data; |
117 | | unsigned Length; |
118 | | }; |
119 | | |
120 | | struct RegOp { |
121 | | unsigned RegNum; |
122 | | }; |
123 | | |
124 | | struct ImmOp { |
125 | | const MCExpr *Value; |
126 | | }; |
127 | | |
128 | | struct MemOp { |
129 | | unsigned BaseReg; |
130 | | unsigned OffsetReg; |
131 | | unsigned AluOp; |
132 | | const MCExpr *Offset; |
133 | | }; |
134 | | |
135 | | union { |
136 | | struct Token Tok; |
137 | | struct RegOp Reg; |
138 | | struct ImmOp Imm; |
139 | | struct MemOp Mem; |
140 | | }; |
141 | | |
142 | 1.89k | explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {} |
143 | | |
144 | | public: |
145 | | // The functions below are used by the autogenerated ASM matcher and hence to |
146 | | // be of the form expected. |
147 | | |
148 | | // getStartLoc - Gets location of the first token of this operand |
149 | 0 | SMLoc getStartLoc() const override { return StartLoc; } |
150 | | |
151 | | // getEndLoc - Gets location of the last token of this operand |
152 | 0 | SMLoc getEndLoc() const override { return EndLoc; } |
153 | | |
154 | 1.70k | unsigned getReg() const override { |
155 | 1.70k | assert(isReg() && "Invalid type access!"); |
156 | 1.70k | return Reg.RegNum; |
157 | 1.70k | } |
158 | | |
159 | 399 | const MCExpr *getImm() const { |
160 | 399 | assert(isImm() && "Invalid type access!"); |
161 | 399 | return Imm.Value; |
162 | 399 | } |
163 | | |
164 | 859 | StringRef getToken() const { |
165 | 859 | assert(isToken() && "Invalid type access!"); |
166 | 859 | return StringRef(Tok.Data, Tok.Length); |
167 | 859 | } |
168 | | |
169 | 294 | unsigned getMemBaseReg() const { |
170 | 294 | assert(isMem() && "Invalid type access!"); |
171 | 294 | return Mem.BaseReg; |
172 | 294 | } |
173 | | |
174 | 127 | unsigned getMemOffsetReg() const { |
175 | 127 | assert(isMem() && "Invalid type access!"); |
176 | 127 | return Mem.OffsetReg; |
177 | 127 | } |
178 | | |
179 | 172 | const MCExpr *getMemOffset() const { |
180 | 172 | assert(isMem() && "Invalid type access!"); |
181 | 172 | return Mem.Offset; |
182 | 172 | } |
183 | | |
184 | 294 | unsigned getMemOp() const { |
185 | 294 | assert(isMem() && "Invalid type access!"); |
186 | 294 | return Mem.AluOp; |
187 | 294 | } |
188 | | |
189 | | // Functions for testing operand type |
190 | 1.33k | bool isReg() const override { return Kind == REGISTER; } |
191 | | |
192 | 1.06k | bool isImm() const override { return Kind == IMMEDIATE; } |
193 | | |
194 | 0 | bool isMem() const override { |
195 | 0 | return isMemImm() || isMemRegImm()0 || isMemRegReg()0 ; |
196 | 0 | } |
197 | | |
198 | 119 | bool isMemImm() const { return Kind == MEMORY_IMM; } |
199 | | |
200 | 336 | bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; } |
201 | | |
202 | 331 | bool isMemRegReg() const { return Kind == MEMORY_REG_REG; } |
203 | | |
204 | 102 | bool isMemSpls() const { return isMemRegImm() || 102 isMemRegReg()0 ; } |
205 | | |
206 | 2.11k | bool isToken() const override { return Kind == TOKEN; } |
207 | | |
208 | 27 | bool isBrImm() { |
209 | 27 | if (!isImm()) |
210 | 0 | return false; |
211 | 27 | |
212 | 27 | // Constant case |
213 | 27 | const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value); |
214 | 27 | if (!MCE) |
215 | 5 | return true; |
216 | 22 | int64_t Value = MCE->getValue(); |
217 | 22 | // Check if value fits in 25 bits with 2 least significant bits 0. |
218 | 22 | return isShiftedUInt<23, 2>(static_cast<int32_t>(Value)); |
219 | 22 | } |
220 | | |
221 | 27 | bool isBrTarget() { return isBrImm() || 27 isToken()0 ; } |
222 | | |
223 | 0 | bool isCallTarget() { return isImm() || 0 isToken()0 ; } |
224 | | |
225 | 44 | bool isHiImm16() { |
226 | 44 | if (!isImm()) |
227 | 0 | return false; |
228 | 44 | |
229 | 44 | // Constant case |
230 | 44 | if (const MCConstantExpr *44 ConstExpr44 = dyn_cast<MCConstantExpr>(Imm.Value)) { |
231 | 42 | int64_t Value = ConstExpr->getValue(); |
232 | 29 | return Value != 0 && isShiftedUInt<16, 16>(Value); |
233 | 42 | } |
234 | 2 | |
235 | 2 | // Symbolic reference expression |
236 | 2 | if (const LanaiMCExpr *2 SymbolRefExpr2 = dyn_cast<LanaiMCExpr>(Imm.Value)) |
237 | 1 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI; |
238 | 1 | |
239 | 1 | // Binary expression |
240 | 1 | if (const MCBinaryExpr *1 BinaryExpr1 = dyn_cast<MCBinaryExpr>(Imm.Value)) |
241 | 1 | if (const LanaiMCExpr *1 SymbolRefExpr1 = |
242 | 1 | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) |
243 | 1 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI; |
244 | 0 |
|
245 | 0 | return false; |
246 | 0 | } |
247 | | |
248 | 13 | bool isHiImm16And() { |
249 | 13 | if (!isImm()) |
250 | 0 | return false; |
251 | 13 | |
252 | 13 | const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); |
253 | 13 | if (ConstExpr13 ) { |
254 | 11 | int64_t Value = ConstExpr->getValue(); |
255 | 11 | // Check if in the form 0xXYZWffff |
256 | 10 | return (Value != 0) && ((Value & ~0xffff0000) == 0xffff); |
257 | 11 | } |
258 | 2 | return false; |
259 | 2 | } |
260 | | |
261 | 27 | bool isLoImm16() { |
262 | 27 | if (!isImm()) |
263 | 0 | return false; |
264 | 27 | |
265 | 27 | // Constant case |
266 | 27 | if (const MCConstantExpr *27 ConstExpr27 = dyn_cast<MCConstantExpr>(Imm.Value)) { |
267 | 27 | int64_t Value = ConstExpr->getValue(); |
268 | 27 | // Check if value fits in 16 bits |
269 | 27 | return isUInt<16>(static_cast<int32_t>(Value)); |
270 | 27 | } |
271 | 0 |
|
272 | 0 | // Symbolic reference expression |
273 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = dyn_cast<LanaiMCExpr>(Imm.Value)) |
274 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; |
275 | 0 |
|
276 | 0 | // Binary expression |
277 | 0 | if (const MCBinaryExpr *0 BinaryExpr0 = dyn_cast<MCBinaryExpr>(Imm.Value)) |
278 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = |
279 | 0 | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) |
280 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; |
281 | 0 |
|
282 | 0 | return false; |
283 | 0 | } |
284 | | |
285 | 167 | bool isLoImm16Signed() { |
286 | 167 | if (!isImm()) |
287 | 0 | return false; |
288 | 167 | |
289 | 167 | // Constant case |
290 | 167 | if (const MCConstantExpr *167 ConstExpr167 = dyn_cast<MCConstantExpr>(Imm.Value)) { |
291 | 167 | int64_t Value = ConstExpr->getValue(); |
292 | 167 | // Check if value fits in 16 bits or value of the form 0xffffxyzw |
293 | 167 | return isInt<16>(static_cast<int32_t>(Value)); |
294 | 167 | } |
295 | 0 |
|
296 | 0 | // Symbolic reference expression |
297 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = dyn_cast<LanaiMCExpr>(Imm.Value)) |
298 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; |
299 | 0 |
|
300 | 0 | // Binary expression |
301 | 0 | if (const MCBinaryExpr *0 BinaryExpr0 = dyn_cast<MCBinaryExpr>(Imm.Value)) |
302 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = |
303 | 0 | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) |
304 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; |
305 | 0 |
|
306 | 0 | return false; |
307 | 0 | } |
308 | | |
309 | 6 | bool isLoImm16And() { |
310 | 6 | if (!isImm()) |
311 | 0 | return false; |
312 | 6 | |
313 | 6 | const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); |
314 | 6 | if (ConstExpr6 ) { |
315 | 6 | int64_t Value = ConstExpr->getValue(); |
316 | 6 | // Check if in the form 0xffffXYZW |
317 | 6 | return ((Value & ~0xffff) == 0xffff0000); |
318 | 6 | } |
319 | 0 | return false; |
320 | 0 | } |
321 | | |
322 | 16 | bool isImmShift() { |
323 | 16 | if (!isImm()) |
324 | 0 | return false; |
325 | 16 | |
326 | 16 | const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); |
327 | 16 | if (!ConstExpr) |
328 | 0 | return false; |
329 | 16 | int64_t Value = ConstExpr->getValue(); |
330 | 16 | return (Value >= -31) && (Value <= 31); |
331 | 16 | } |
332 | | |
333 | 1 | bool isLoImm21() { |
334 | 1 | if (!isImm()) |
335 | 0 | return false; |
336 | 1 | |
337 | 1 | // Constant case |
338 | 1 | if (const MCConstantExpr *1 ConstExpr1 = dyn_cast<MCConstantExpr>(Imm.Value)) { |
339 | 1 | int64_t Value = ConstExpr->getValue(); |
340 | 1 | return isUInt<21>(Value); |
341 | 1 | } |
342 | 0 |
|
343 | 0 | // Symbolic reference expression |
344 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = dyn_cast<LanaiMCExpr>(Imm.Value)) |
345 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; |
346 | 0 | if (const MCSymbolRefExpr *0 SymbolRefExpr0 = |
347 | 0 | dyn_cast<MCSymbolRefExpr>(Imm.Value)) { |
348 | 0 | return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None; |
349 | 0 | } |
350 | 0 |
|
351 | 0 | // Binary expression |
352 | 0 | if (const MCBinaryExpr *0 BinaryExpr0 = dyn_cast<MCBinaryExpr>(Imm.Value)) { |
353 | 0 | if (const LanaiMCExpr *SymbolRefExpr = |
354 | 0 | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) |
355 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; |
356 | 0 | if (const MCSymbolRefExpr *0 SymbolRefExpr0 = |
357 | 0 | dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS())) |
358 | 0 | return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None; |
359 | 0 | } |
360 | 0 |
|
361 | 0 | return false; |
362 | 0 | } |
363 | | |
364 | 0 | bool isImm10() { |
365 | 0 | if (!isImm()) |
366 | 0 | return false; |
367 | 0 |
|
368 | 0 | const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); |
369 | 0 | if (!ConstExpr) |
370 | 0 | return false; |
371 | 0 | int64_t Value = ConstExpr->getValue(); |
372 | 0 | return isInt<10>(Value); |
373 | 0 | } |
374 | | |
375 | 23 | bool isCondCode() { |
376 | 23 | if (!isImm()) |
377 | 0 | return false; |
378 | 23 | |
379 | 23 | const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); |
380 | 23 | if (!ConstExpr) |
381 | 0 | return false; |
382 | 23 | uint64_t Value = ConstExpr->getValue(); |
383 | 23 | // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the |
384 | 23 | // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then |
385 | 23 | // value corresponds to a valid condition code. |
386 | 23 | return Value < LPCC::UNKNOWN; |
387 | 23 | } |
388 | | |
389 | 337 | void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
390 | 337 | // Add as immediates where possible. Null MCExpr = 0 |
391 | 337 | if (Expr == nullptr) |
392 | 0 | Inst.addOperand(MCOperand::createImm(0)); |
393 | 337 | else if (const MCConstantExpr *337 ConstExpr337 = dyn_cast<MCConstantExpr>(Expr)) |
394 | 332 | Inst.addOperand( |
395 | 332 | MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue()))); |
396 | 337 | else |
397 | 5 | Inst.addOperand(MCOperand::createExpr(Expr)); |
398 | 337 | } |
399 | | |
400 | 573 | void addRegOperands(MCInst &Inst, unsigned N) const { |
401 | 573 | assert(N == 1 && "Invalid number of operands!"); |
402 | 573 | Inst.addOperand(MCOperand::createReg(getReg())); |
403 | 573 | } |
404 | | |
405 | 99 | void addImmOperands(MCInst &Inst, unsigned N) const { |
406 | 99 | assert(N == 1 && "Invalid number of operands!"); |
407 | 99 | addExpr(Inst, getImm()); |
408 | 99 | } |
409 | | |
410 | 27 | void addBrTargetOperands(MCInst &Inst, unsigned N) const { |
411 | 27 | assert(N == 1 && "Invalid number of operands!"); |
412 | 27 | addExpr(Inst, getImm()); |
413 | 27 | } |
414 | | |
415 | 0 | void addCallTargetOperands(MCInst &Inst, unsigned N) const { |
416 | 0 | assert(N == 1 && "Invalid number of operands!"); |
417 | 0 | addExpr(Inst, getImm()); |
418 | 0 | } |
419 | | |
420 | 23 | void addCondCodeOperands(MCInst &Inst, unsigned N) const { |
421 | 23 | assert(N == 1 && "Invalid number of operands!"); |
422 | 23 | addExpr(Inst, getImm()); |
423 | 23 | } |
424 | | |
425 | 5 | void addMemImmOperands(MCInst &Inst, unsigned N) const { |
426 | 5 | assert(N == 1 && "Invalid number of operands!"); |
427 | 5 | const MCExpr *Expr = getMemOffset(); |
428 | 5 | addExpr(Inst, Expr); |
429 | 5 | } |
430 | | |
431 | 167 | void addMemRegImmOperands(MCInst &Inst, unsigned N) const { |
432 | 167 | assert(N == 3 && "Invalid number of operands!"); |
433 | 167 | Inst.addOperand(MCOperand::createReg(getMemBaseReg())); |
434 | 167 | const MCExpr *Expr = getMemOffset(); |
435 | 167 | addExpr(Inst, Expr); |
436 | 167 | Inst.addOperand(MCOperand::createImm(getMemOp())); |
437 | 167 | } |
438 | | |
439 | 127 | void addMemRegRegOperands(MCInst &Inst, unsigned N) const { |
440 | 127 | assert(N == 3 && "Invalid number of operands!"); |
441 | 127 | Inst.addOperand(MCOperand::createReg(getMemBaseReg())); |
442 | 127 | assert(getMemOffsetReg() != 0 && "Invalid offset"); |
443 | 127 | Inst.addOperand(MCOperand::createReg(getMemOffsetReg())); |
444 | 127 | Inst.addOperand(MCOperand::createImm(getMemOp())); |
445 | 127 | } |
446 | | |
447 | 102 | void addMemSplsOperands(MCInst &Inst, unsigned N) const { |
448 | 102 | if (isMemRegImm()) |
449 | 102 | addMemRegImmOperands(Inst, N); |
450 | 102 | if (isMemRegReg()) |
451 | 0 | addMemRegRegOperands(Inst, N); |
452 | 102 | } |
453 | | |
454 | 16 | void addImmShiftOperands(MCInst &Inst, unsigned N) const { |
455 | 16 | assert(N == 1 && "Invalid number of operands!"); |
456 | 16 | addExpr(Inst, getImm()); |
457 | 16 | } |
458 | | |
459 | 0 | void addImm10Operands(MCInst &Inst, unsigned N) const { |
460 | 0 | assert(N == 1 && "Invalid number of operands!"); |
461 | 0 | addExpr(Inst, getImm()); |
462 | 0 | } |
463 | | |
464 | 26 | void addLoImm16Operands(MCInst &Inst, unsigned N) const { |
465 | 26 | assert(N == 1 && "Invalid number of operands!"); |
466 | 26 | if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) |
467 | 26 | Inst.addOperand( |
468 | 26 | MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue()))); |
469 | 0 | else if (0 isa<LanaiMCExpr>(getImm())0 ) { |
470 | | #ifndef NDEBUG |
471 | | const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); |
472 | | assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO); |
473 | | #endif |
474 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
475 | 0 | } else if (0 isa<MCBinaryExpr>(getImm())0 ) { |
476 | | #ifndef NDEBUG |
477 | | const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); |
478 | | assert(dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()) && |
479 | | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() == |
480 | | LanaiMCExpr::VK_Lanai_ABS_LO); |
481 | | #endif |
482 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
483 | 0 | } else |
484 | 0 | assert(false && "Operand type not supported."); |
485 | 26 | } |
486 | | |
487 | 3 | void addLoImm16AndOperands(MCInst &Inst, unsigned N) const { |
488 | 3 | assert(N == 1 && "Invalid number of operands!"); |
489 | 3 | if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) |
490 | 3 | Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff)); |
491 | 3 | else |
492 | 3 | assert(false && "Operand type not supported."); |
493 | 3 | } |
494 | | |
495 | 16 | void addHiImm16Operands(MCInst &Inst, unsigned N) const { |
496 | 16 | assert(N == 1 && "Invalid number of operands!"); |
497 | 16 | if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) |
498 | 14 | Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16)); |
499 | 2 | else if (2 isa<LanaiMCExpr>(getImm())2 ) { |
500 | | #ifndef NDEBUG |
501 | | const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); |
502 | | assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI); |
503 | | #endif |
504 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
505 | 2 | } else if (1 isa<MCBinaryExpr>(getImm())1 ) { |
506 | | #ifndef NDEBUG |
507 | | const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); |
508 | | assert(dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()) && |
509 | | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() == |
510 | | LanaiMCExpr::VK_Lanai_ABS_HI); |
511 | | #endif |
512 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
513 | 1 | } else |
514 | 2 | assert(false && "Operand type not supported."); |
515 | 16 | } |
516 | | |
517 | 3 | void addHiImm16AndOperands(MCInst &Inst, unsigned N) const { |
518 | 3 | assert(N == 1 && "Invalid number of operands!"); |
519 | 3 | if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) |
520 | 3 | Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16)); |
521 | 3 | else |
522 | 3 | assert(false && "Operand type not supported."); |
523 | 3 | } |
524 | | |
525 | 1 | void addLoImm21Operands(MCInst &Inst, unsigned N) const { |
526 | 1 | assert(N == 1 && "Invalid number of operands!"); |
527 | 1 | if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) |
528 | 1 | Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff)); |
529 | 0 | else if (0 isa<LanaiMCExpr>(getImm())0 ) { |
530 | | #ifndef NDEBUG |
531 | | const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); |
532 | | assert(SymbolRefExpr && |
533 | | SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None); |
534 | | #endif |
535 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
536 | 0 | } else if (0 isa<MCSymbolRefExpr>(getImm())0 ) { |
537 | | #ifndef NDEBUG |
538 | | const MCSymbolRefExpr *SymbolRefExpr = |
539 | | dyn_cast<MCSymbolRefExpr>(getImm()); |
540 | | assert(SymbolRefExpr && |
541 | | SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None); |
542 | | #endif |
543 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
544 | 0 | } else if (0 isa<MCBinaryExpr>(getImm())0 ) { |
545 | | #ifndef NDEBUG |
546 | | const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); |
547 | | const LanaiMCExpr *SymbolRefExpr = |
548 | | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()); |
549 | | assert(SymbolRefExpr && |
550 | | SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None); |
551 | | #endif |
552 | | Inst.addOperand(MCOperand::createExpr(getImm())); |
553 | 0 | } else |
554 | 0 | assert(false && "Operand type not supported."); |
555 | 1 | } |
556 | | |
557 | 0 | void print(raw_ostream &OS) const override { |
558 | 0 | switch (Kind) { |
559 | 0 | case IMMEDIATE: |
560 | 0 | OS << "Imm: " << getImm() << "\n"; |
561 | 0 | break; |
562 | 0 | case TOKEN: |
563 | 0 | OS << "Token: " << getToken() << "\n"; |
564 | 0 | break; |
565 | 0 | case REGISTER: |
566 | 0 | OS << "Reg: %r" << getReg() << "\n"; |
567 | 0 | break; |
568 | 0 | case MEMORY_IMM: |
569 | 0 | OS << "MemImm: " << *getMemOffset() << "\n"; |
570 | 0 | break; |
571 | 0 | case MEMORY_REG_IMM: |
572 | 0 | OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n"; |
573 | 0 | break; |
574 | 0 | case MEMORY_REG_REG: |
575 | 0 | assert(getMemOffset() == nullptr); |
576 | 0 | OS << "MemRegReg: " << getMemBaseReg() << "+" |
577 | 0 | << "%r" << getMemOffsetReg() << "\n"; |
578 | 0 | break; |
579 | 0 | } |
580 | 0 | } |
581 | | |
582 | 510 | static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) { |
583 | 510 | auto Op = make_unique<LanaiOperand>(TOKEN); |
584 | 510 | Op->Tok.Data = Str.data(); |
585 | 510 | Op->Tok.Length = Str.size(); |
586 | 510 | Op->StartLoc = Start; |
587 | 510 | Op->EndLoc = Start; |
588 | 510 | return Op; |
589 | 510 | } |
590 | | |
591 | | static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start, |
592 | 991 | SMLoc End) { |
593 | 991 | auto Op = make_unique<LanaiOperand>(REGISTER); |
594 | 991 | Op->Reg.RegNum = RegNum; |
595 | 991 | Op->StartLoc = Start; |
596 | 991 | Op->EndLoc = End; |
597 | 991 | return Op; |
598 | 991 | } |
599 | | |
600 | | static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value, |
601 | 394 | SMLoc Start, SMLoc End) { |
602 | 394 | auto Op = make_unique<LanaiOperand>(IMMEDIATE); |
603 | 394 | Op->Imm.Value = Value; |
604 | 394 | Op->StartLoc = Start; |
605 | 394 | Op->EndLoc = End; |
606 | 394 | return Op; |
607 | 394 | } |
608 | | |
609 | | static std::unique_ptr<LanaiOperand> |
610 | 5 | MorphToMemImm(std::unique_ptr<LanaiOperand> Op) { |
611 | 5 | const MCExpr *Imm = Op->getImm(); |
612 | 5 | Op->Kind = MEMORY_IMM; |
613 | 5 | Op->Mem.BaseReg = 0; |
614 | 5 | Op->Mem.AluOp = LPAC::ADD; |
615 | 5 | Op->Mem.OffsetReg = 0; |
616 | 5 | Op->Mem.Offset = Imm; |
617 | 5 | return Op; |
618 | 5 | } |
619 | | |
620 | | static std::unique_ptr<LanaiOperand> |
621 | | MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op, |
622 | 127 | unsigned AluOp) { |
623 | 127 | unsigned OffsetReg = Op->getReg(); |
624 | 127 | Op->Kind = MEMORY_REG_REG; |
625 | 127 | Op->Mem.BaseReg = BaseReg; |
626 | 127 | Op->Mem.AluOp = AluOp; |
627 | 127 | Op->Mem.OffsetReg = OffsetReg; |
628 | 127 | Op->Mem.Offset = nullptr; |
629 | 127 | return Op; |
630 | 127 | } |
631 | | |
632 | | static std::unique_ptr<LanaiOperand> |
633 | | MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op, |
634 | 167 | unsigned AluOp) { |
635 | 167 | const MCExpr *Imm = Op->getImm(); |
636 | 167 | Op->Kind = MEMORY_REG_IMM; |
637 | 167 | Op->Mem.BaseReg = BaseReg; |
638 | 167 | Op->Mem.AluOp = AluOp; |
639 | 167 | Op->Mem.OffsetReg = 0; |
640 | 167 | Op->Mem.Offset = Imm; |
641 | 167 | return Op; |
642 | 167 | } |
643 | | }; |
644 | | |
645 | | } // end anonymous namespace |
646 | | |
647 | 3 | bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; } |
648 | | |
649 | | bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode, |
650 | | OperandVector &Operands, |
651 | | MCStreamer &Out, |
652 | | uint64_t &ErrorInfo, |
653 | 481 | bool MatchingInlineAsm) { |
654 | 481 | MCInst Inst; |
655 | 481 | SMLoc ErrorLoc; |
656 | 481 | |
657 | 481 | switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { |
658 | 481 | case Match_Success: |
659 | 481 | Out.EmitInstruction(Inst, SubtargetInfo); |
660 | 481 | Opcode = Inst.getOpcode(); |
661 | 481 | return false; |
662 | 0 | case Match_MissingFeature: |
663 | 0 | return Error(IdLoc, "Instruction use requires option to be enabled"); |
664 | 0 | case Match_MnemonicFail: |
665 | 0 | return Error(IdLoc, "Unrecognized instruction mnemonic"); |
666 | 0 | case Match_InvalidOperand: { |
667 | 0 | ErrorLoc = IdLoc; |
668 | 0 | if (ErrorInfo != ~0U0 ) { |
669 | 0 | if (ErrorInfo >= Operands.size()) |
670 | 0 | return Error(IdLoc, "Too few operands for instruction"); |
671 | 0 |
|
672 | 0 | ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc(); |
673 | 0 | if (ErrorLoc == SMLoc()) |
674 | 0 | ErrorLoc = IdLoc; |
675 | 0 | } |
676 | 0 | return Error(ErrorLoc, "Invalid operand for instruction"); |
677 | 0 | } |
678 | 0 | default: |
679 | 0 | break; |
680 | 0 | } |
681 | 0 |
|
682 | 0 | llvm_unreachable0 ("Unknown match type detected!"); |
683 | 0 | } |
684 | | |
685 | | // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain |
686 | | // backwards compatible with GCC and the different ways inline assembly is |
687 | | // handled. |
688 | | // TODO: see if there isn't a better way to do this. |
689 | 1.39k | std::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() { |
690 | 1.39k | SMLoc Start = Parser.getTok().getLoc(); |
691 | 1.39k | SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
692 | 1.39k | |
693 | 1.39k | unsigned RegNum; |
694 | 1.39k | // Eat the '%'. |
695 | 1.39k | if (Lexer.getKind() == AsmToken::Percent) |
696 | 991 | Parser.Lex(); |
697 | 1.39k | if (Lexer.getKind() == AsmToken::Identifier1.39k ) { |
698 | 996 | RegNum = MatchRegisterName(Lexer.getTok().getIdentifier()); |
699 | 996 | if (RegNum == 0) |
700 | 5 | return nullptr; |
701 | 991 | Parser.Lex(); // Eat identifier token |
702 | 991 | return LanaiOperand::createReg(RegNum, Start, End); |
703 | 991 | } |
704 | 395 | return nullptr; |
705 | 395 | } |
706 | | |
707 | | bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc, |
708 | 0 | SMLoc &EndLoc) { |
709 | 0 | const AsmToken &Tok = getParser().getTok(); |
710 | 0 | StartLoc = Tok.getLoc(); |
711 | 0 | EndLoc = Tok.getEndLoc(); |
712 | 0 | std::unique_ptr<LanaiOperand> Op = parseRegister(); |
713 | 0 | if (Op != nullptr) |
714 | 0 | RegNum = Op->getReg(); |
715 | 0 | return (Op == nullptr); |
716 | 0 | } |
717 | | |
718 | 5 | std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() { |
719 | 5 | SMLoc Start = Parser.getTok().getLoc(); |
720 | 5 | SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
721 | 5 | const MCExpr *Res, *RHS = nullptr; |
722 | 5 | LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None; |
723 | 5 | |
724 | 5 | if (Lexer.getKind() != AsmToken::Identifier) |
725 | 0 | return nullptr; |
726 | 5 | |
727 | 5 | StringRef Identifier; |
728 | 5 | if (Parser.parseIdentifier(Identifier)) |
729 | 0 | return nullptr; |
730 | 5 | |
731 | 5 | // Check if identifier has a modifier |
732 | 5 | if (5 Identifier.equals_lower("hi")5 ) |
733 | 2 | Kind = LanaiMCExpr::VK_Lanai_ABS_HI; |
734 | 3 | else if (3 Identifier.equals_lower("lo")3 ) |
735 | 0 | Kind = LanaiMCExpr::VK_Lanai_ABS_LO; |
736 | 5 | |
737 | 5 | // If the identifier corresponds to a variant then extract the real |
738 | 5 | // identifier. |
739 | 5 | if (Kind != LanaiMCExpr::VK_Lanai_None5 ) { |
740 | 2 | if (Lexer.getKind() != AsmToken::LParen2 ) { |
741 | 0 | Error(Lexer.getLoc(), "Expected '('"); |
742 | 0 | return nullptr; |
743 | 0 | } |
744 | 2 | Lexer.Lex(); // lex '(' |
745 | 2 | |
746 | 2 | // Parse identifier |
747 | 2 | if (Parser.parseIdentifier(Identifier)) |
748 | 0 | return nullptr; |
749 | 5 | } |
750 | 5 | |
751 | 5 | // If addition parse the RHS. |
752 | 5 | if (5 Lexer.getKind() == AsmToken::Plus && 5 Parser.parseExpression(RHS)1 ) |
753 | 0 | return nullptr; |
754 | 5 | |
755 | 5 | // For variants parse the final ')' |
756 | 5 | if (5 Kind != LanaiMCExpr::VK_Lanai_None5 ) { |
757 | 2 | if (Lexer.getKind() != AsmToken::RParen2 ) { |
758 | 0 | Error(Lexer.getLoc(), "Expected ')'"); |
759 | 0 | return nullptr; |
760 | 0 | } |
761 | 2 | Lexer.Lex(); // lex ')' |
762 | 2 | } |
763 | 5 | |
764 | 5 | End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
765 | 5 | MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); |
766 | 5 | const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext()); |
767 | 5 | Res = LanaiMCExpr::create(Kind, Expr, getContext()); |
768 | 5 | |
769 | 5 | // Nest if this was an addition |
770 | 5 | if (RHS) |
771 | 1 | Res = MCBinaryExpr::createAdd(Res, RHS, getContext()); |
772 | 5 | |
773 | 5 | return LanaiOperand::createImm(Res, Start, End); |
774 | 5 | } |
775 | | |
776 | 400 | std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() { |
777 | 400 | SMLoc Start = Parser.getTok().getLoc(); |
778 | 400 | SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
779 | 400 | |
780 | 400 | const MCExpr *ExprVal; |
781 | 400 | switch (Lexer.getKind()) { |
782 | 5 | case AsmToken::Identifier: |
783 | 5 | return parseIdentifier(); |
784 | 238 | case AsmToken::Plus: |
785 | 238 | case AsmToken::Minus: |
786 | 238 | case AsmToken::Integer: |
787 | 238 | case AsmToken::Dot: |
788 | 238 | if (!Parser.parseExpression(ExprVal)) |
789 | 238 | return LanaiOperand::createImm(ExprVal, Start, End); |
790 | 0 | LLVM_FALLTHROUGH0 ; |
791 | 157 | default: |
792 | 157 | return nullptr; |
793 | 0 | } |
794 | 0 | } |
795 | | |
796 | 291 | static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) { |
797 | 291 | if (PreOp) |
798 | 99 | return LPAC::makePreOp(AluCode); |
799 | 192 | if (192 PostOp192 ) |
800 | 102 | return LPAC::makePostOp(AluCode); |
801 | 90 | return AluCode; |
802 | 90 | } |
803 | | |
804 | 108 | unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) { |
805 | 108 | StringRef IdString; |
806 | 108 | Parser.parseIdentifier(IdString); |
807 | 108 | unsigned AluCode = LPAC::stringToLanaiAluCode(IdString); |
808 | 108 | if (AluCode == LPAC::UNKNOWN108 ) { |
809 | 0 | Error(Parser.getTok().getLoc(), "Can't parse ALU operator"); |
810 | 0 | return 0; |
811 | 0 | } |
812 | 108 | return AluCode; |
813 | 108 | } |
814 | | |
815 | 37 | static int SizeForSuffix(StringRef T) { |
816 | 37 | return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4); |
817 | 37 | } |
818 | | |
819 | 491 | bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) { |
820 | 491 | bool PreOrPost = false; |
821 | 491 | if (Lexer.getKind() == Lexer.peekTok(true).getKind()491 ) { |
822 | 37 | PreOrPost = true; |
823 | 37 | if (Lexer.is(AsmToken::Minus)) |
824 | 19 | *OffsetValue = -SizeForSuffix(Type); |
825 | 18 | else if (18 Lexer.is(AsmToken::Plus)18 ) |
826 | 18 | *OffsetValue = SizeForSuffix(Type); |
827 | 18 | else |
828 | 0 | return false; |
829 | 37 | |
830 | 37 | // Eat the '-' '-' or '+' '+' |
831 | 37 | Parser.Lex(); |
832 | 37 | Parser.Lex(); |
833 | 491 | } else if (454 Lexer.is(AsmToken::Star)454 ) { |
834 | 164 | Parser.Lex(); // Eat the '*' |
835 | 164 | PreOrPost = true; |
836 | 164 | } |
837 | 491 | |
838 | 491 | return PreOrPost; |
839 | 491 | } |
840 | | |
841 | 8 | bool shouldBeSls(const LanaiOperand &Op) { |
842 | 8 | // The instruction should be encoded as an SLS if the constant is word |
843 | 8 | // aligned and will fit in 21 bits |
844 | 8 | if (const MCConstantExpr *ConstExpr8 = dyn_cast<MCConstantExpr>(Op.getImm())) { |
845 | 8 | int64_t Value = ConstExpr->getValue(); |
846 | 8 | return (Value % 4 == 0) && (Value >= 0)7 && (Value <= 0x1fffff)6 ; |
847 | 8 | } |
848 | 0 | // The instruction should be encoded as an SLS if the operand is a symbolic |
849 | 0 | // reference with no variant. |
850 | 0 | if (const LanaiMCExpr *0 SymbolRefExpr0 = dyn_cast<LanaiMCExpr>(Op.getImm())) |
851 | 0 | return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; |
852 | 0 | // The instruction should be encoded as an SLS if the operand is a binary |
853 | 0 | // expression with the left-hand side being a symbolic reference with no |
854 | 0 | // variant. |
855 | 0 | if (const MCBinaryExpr *0 BinaryExpr0 = dyn_cast<MCBinaryExpr>(Op.getImm())) { |
856 | 0 | const LanaiMCExpr *LHSSymbolRefExpr = |
857 | 0 | dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()); |
858 | 0 | return (LHSSymbolRefExpr && |
859 | 0 | LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None); |
860 | 0 | } |
861 | 0 | return false; |
862 | 0 | } |
863 | | |
864 | | // Matches memory operand. Returns true if error encountered. |
865 | | OperandMatchResultTy |
866 | 299 | LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) { |
867 | 299 | // Try to match a memory operand. |
868 | 299 | // The memory operands are of the form: |
869 | 299 | // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or |
870 | 299 | // ^ |
871 | 299 | // (2) '[' '*'? Register '*'? AluOperator Register ']' |
872 | 299 | // ^ |
873 | 299 | // (3) '[' '--'|'++' Register '--'|'++' ']' |
874 | 299 | // |
875 | 299 | // (4) '[' Immediate ']' (for SLS) |
876 | 299 | |
877 | 299 | // Store the type for use in parsing pre/post increment/decrement operators |
878 | 299 | StringRef Type; |
879 | 299 | if (Operands[0]->isToken()) |
880 | 299 | Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken(); |
881 | 299 | |
882 | 299 | // Use 0 if no offset given |
883 | 299 | int OffsetValue = 0; |
884 | 299 | unsigned BaseReg = 0; |
885 | 299 | unsigned AluOp = LPAC::ADD; |
886 | 299 | bool PostOp = false, PreOp = false; |
887 | 299 | |
888 | 299 | // Try to parse the offset |
889 | 299 | std::unique_ptr<LanaiOperand> Op = parseRegister(); |
890 | 299 | if (!Op) |
891 | 280 | Op = parseImmediate(); |
892 | 299 | |
893 | 299 | // Only continue if next token is '[' |
894 | 299 | if (Lexer.isNot(AsmToken::LBrac)299 ) { |
895 | 0 | if (!Op) |
896 | 0 | return MatchOperand_NoMatch; |
897 | 0 |
|
898 | 0 | // The start of this custom parsing overlaps with register/immediate so |
899 | 0 | // consider this as a successful match of an operand of that type as the |
900 | 0 | // token stream can't be rewound to allow them to match separately. |
901 | 0 | Operands.push_back(std::move(Op)); |
902 | 0 | return MatchOperand_Success; |
903 | 0 | } |
904 | 299 | |
905 | 299 | Parser.Lex(); // Eat the '['. |
906 | 299 | std::unique_ptr<LanaiOperand> Offset = nullptr; |
907 | 299 | if (Op) |
908 | 142 | Offset.swap(Op); |
909 | 299 | |
910 | 299 | // Determine if a pre operation |
911 | 299 | PreOp = parsePrePost(Type, &OffsetValue); |
912 | 299 | |
913 | 299 | Op = parseRegister(); |
914 | 299 | if (!Op299 ) { |
915 | 8 | if (!Offset8 ) { |
916 | 8 | if ((Op = parseImmediate()) && 8 Lexer.is(AsmToken::RBrac)8 ) { |
917 | 8 | Parser.Lex(); // Eat the ']' |
918 | 8 | |
919 | 8 | // Memory address operations aligned to word boundary are encoded as |
920 | 8 | // SLS, the rest as RM. |
921 | 8 | if (shouldBeSls(*Op)8 ) { |
922 | 5 | Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op))); |
923 | 8 | } else { |
924 | 3 | if (!Op->isLoImm16Signed()3 ) { |
925 | 0 | Error(Parser.getTok().getLoc(), |
926 | 0 | "Memory address is not word " |
927 | 0 | "aligned and larger than class RM can handle"); |
928 | 0 | return MatchOperand_ParseFail; |
929 | 0 | } |
930 | 3 | Operands.push_back(LanaiOperand::MorphToMemRegImm( |
931 | 3 | Lanai::R0, std::move(Op), LPAC::ADD)); |
932 | 3 | } |
933 | 8 | return MatchOperand_Success; |
934 | 0 | } |
935 | 8 | } |
936 | 0 |
|
937 | 0 | Error(Parser.getTok().getLoc(), |
938 | 0 | "Unknown operand, expected register or immediate"); |
939 | 0 | return MatchOperand_ParseFail; |
940 | 0 | } |
941 | 291 | BaseReg = Op->getReg(); |
942 | 291 | |
943 | 291 | // Determine if a post operation |
944 | 291 | if (!PreOp) |
945 | 192 | PostOp = parsePrePost(Type, &OffsetValue); |
946 | 291 | |
947 | 291 | // If ] match form (1) else match form (2) |
948 | 291 | if (Lexer.is(AsmToken::RBrac)291 ) { |
949 | 183 | Parser.Lex(); // Eat the ']'. |
950 | 183 | if (!Offset183 ) { |
951 | 41 | SMLoc Start = Parser.getTok().getLoc(); |
952 | 41 | SMLoc End = |
953 | 41 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
954 | 41 | const MCConstantExpr *OffsetConstExpr = |
955 | 41 | MCConstantExpr::create(OffsetValue, getContext()); |
956 | 41 | Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End); |
957 | 41 | } |
958 | 291 | } else { |
959 | 108 | if (Offset || 108 OffsetValue != 0108 ) { |
960 | 0 | Error(Parser.getTok().getLoc(), "Expected ']'"); |
961 | 0 | return MatchOperand_ParseFail; |
962 | 0 | } |
963 | 108 | |
964 | 108 | // Parse operator |
965 | 108 | AluOp = parseAluOperator(PreOp, PostOp); |
966 | 108 | |
967 | 108 | // Second form requires offset register |
968 | 108 | Offset = parseRegister(); |
969 | 108 | if (!BaseReg || 108 Lexer.isNot(AsmToken::RBrac)108 ) { |
970 | 0 | Error(Parser.getTok().getLoc(), "Expected ']'"); |
971 | 0 | return MatchOperand_ParseFail; |
972 | 0 | } |
973 | 108 | Parser.Lex(); // Eat the ']'. |
974 | 108 | } |
975 | 291 | |
976 | 291 | // First form has addition as operator. Add pre- or post-op indicator as |
977 | 291 | // needed. |
978 | 291 | AluOp = AluWithPrePost(AluOp, PreOp, PostOp); |
979 | 291 | |
980 | 291 | // Ensure immediate offset is not too large |
981 | 291 | if (Offset->isImm() && 291 !Offset->isLoImm16Signed()164 ) { |
982 | 0 | Error(Parser.getTok().getLoc(), |
983 | 0 | "Memory address is not word " |
984 | 0 | "aligned and larger than class RM can handle"); |
985 | 0 | return MatchOperand_ParseFail; |
986 | 0 | } |
987 | 291 | |
988 | 291 | Operands.push_back( |
989 | 291 | Offset->isImm() |
990 | 164 | ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp) |
991 | 127 | : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp)); |
992 | 299 | |
993 | 299 | return MatchOperand_Success; |
994 | 299 | } |
995 | | |
996 | | // Looks at a token type and creates the relevant operand from this |
997 | | // information, adding to operands. |
998 | | // If operand was parsed, returns false, else true. |
999 | | OperandMatchResultTy |
1000 | 984 | LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) { |
1001 | 984 | // Check if the current operand has a custom associated parser, if so, try to |
1002 | 984 | // custom parse the operand, or fallback to the general approach. |
1003 | 984 | OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic); |
1004 | 984 | |
1005 | 984 | if (Result == MatchOperand_Success) |
1006 | 299 | return Result; |
1007 | 685 | if (685 Result == MatchOperand_ParseFail685 ) { |
1008 | 0 | Parser.eatToEndOfStatement(); |
1009 | 0 | return Result; |
1010 | 0 | } |
1011 | 685 | |
1012 | 685 | // Attempt to parse token as register |
1013 | 685 | std::unique_ptr<LanaiOperand> Op = parseRegister(); |
1014 | 685 | |
1015 | 685 | // Attempt to parse token as immediate |
1016 | 685 | if (!Op) |
1017 | 112 | Op = parseImmediate(); |
1018 | 685 | |
1019 | 685 | // If the token could not be parsed then fail |
1020 | 685 | if (!Op685 ) { |
1021 | 0 | Error(Parser.getTok().getLoc(), "Unknown operand"); |
1022 | 0 | Parser.eatToEndOfStatement(); |
1023 | 0 | return MatchOperand_ParseFail; |
1024 | 0 | } |
1025 | 685 | |
1026 | 685 | // Push back parsed operand into list of operands |
1027 | 685 | Operands->push_back(std::move(Op)); |
1028 | 685 | |
1029 | 685 | return MatchOperand_Success; |
1030 | 685 | } |
1031 | | |
1032 | | // Split the mnemonic into ASM operand, conditional code and instruction |
1033 | | // qualifier (half-word, byte). |
1034 | | StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc, |
1035 | 481 | OperandVector *Operands) { |
1036 | 481 | size_t Next = Name.find('.'); |
1037 | 481 | |
1038 | 481 | StringRef Mnemonic = Name; |
1039 | 481 | |
1040 | 481 | bool IsBRR = false; |
1041 | 481 | if (Name.endswith(".r")481 ) { |
1042 | 20 | Mnemonic = Name.substr(0, Name.size() - 2); |
1043 | 20 | IsBRR = true; |
1044 | 20 | } |
1045 | 481 | |
1046 | 481 | // Match b?? and s?? (BR, BRR, and SCC instruction classes). |
1047 | 481 | if (Mnemonic[0] == 'b' || |
1048 | 432 | (Mnemonic[0] == 's' && 432 !Mnemonic.startswith("sel")222 && |
1049 | 481 | !Mnemonic.startswith("st")204 )) { |
1050 | 104 | // Parse instructions with a conditional code. For example, 'bne' is |
1051 | 104 | // converted into two operands 'b' and 'ne'. |
1052 | 104 | LPCC::CondCode CondCode = |
1053 | 104 | LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next)); |
1054 | 104 | if (CondCode != LPCC::UNKNOWN104 ) { |
1055 | 68 | Mnemonic = Mnemonic.slice(0, 1); |
1056 | 68 | Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); |
1057 | 68 | Operands->push_back(LanaiOperand::createImm( |
1058 | 68 | MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc)); |
1059 | 68 | if (IsBRR68 ) { |
1060 | 20 | Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc)); |
1061 | 20 | } |
1062 | 68 | return Mnemonic; |
1063 | 68 | } |
1064 | 413 | } |
1065 | 413 | |
1066 | 413 | // Parse other instructions with condition codes (RR instructions). |
1067 | 413 | // We ignore .f here and assume they are flag-setting operations, not |
1068 | 413 | // conditional codes (except for select instructions where flag-setting |
1069 | 413 | // variants are not yet implemented). |
1070 | 413 | if (413 Mnemonic.startswith("sel") || |
1071 | 413 | (!Mnemonic.endswith(".f") && 395 !Mnemonic.startswith("st")357 )) { |
1072 | 226 | LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic); |
1073 | 226 | if (CondCode != LPCC::UNKNOWN226 ) { |
1074 | 22 | size_t Next = Mnemonic.rfind('.', Name.size()); |
1075 | 22 | // 'sel' doesn't use a predicate operand whose printer adds the period, |
1076 | 22 | // but instead has the period as part of the identifier (i.e., 'sel.' is |
1077 | 22 | // expected by the generated matcher). If the mnemonic starts with 'sel' |
1078 | 22 | // then include the period as part of the mnemonic, else don't include it |
1079 | 22 | // as part of the mnemonic. |
1080 | 22 | if (Mnemonic.startswith("sel")22 ) { |
1081 | 18 | Mnemonic = Mnemonic.substr(0, Next + 1); |
1082 | 22 | } else { |
1083 | 4 | Mnemonic = Mnemonic.substr(0, Next); |
1084 | 4 | } |
1085 | 22 | Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); |
1086 | 22 | Operands->push_back(LanaiOperand::createImm( |
1087 | 22 | MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc)); |
1088 | 22 | return Mnemonic; |
1089 | 22 | } |
1090 | 391 | } |
1091 | 391 | |
1092 | 391 | Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); |
1093 | 391 | if (IsBRR391 ) { |
1094 | 0 | Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc)); |
1095 | 0 | } |
1096 | 481 | |
1097 | 481 | return Mnemonic; |
1098 | 481 | } |
1099 | | |
1100 | 478 | static bool IsMemoryAssignmentError(const OperandVector &Operands) { |
1101 | 478 | // Detects if a memory operation has an erroneous base register modification. |
1102 | 478 | // Memory operations are detected by matching the types of operands. |
1103 | 478 | // |
1104 | 478 | // TODO: This test is focussed on one specific instance (ld/st). |
1105 | 478 | // Extend it to handle more cases or be more robust. |
1106 | 478 | bool Modifies = false; |
1107 | 478 | |
1108 | 478 | int Offset = 0; |
1109 | 478 | |
1110 | 478 | if (Operands.size() < 5) |
1111 | 456 | return false; |
1112 | 22 | else if (22 Operands[0]->isToken() && 22 Operands[1]->isReg()22 && |
1113 | 22 | Operands[2]->isImm()0 && Operands[3]->isImm()0 && Operands[4]->isReg()0 ) |
1114 | 0 | Offset = 0; |
1115 | 22 | else if (22 Operands[0]->isToken() && 22 Operands[1]->isToken()22 && |
1116 | 22 | Operands[2]->isReg()0 && Operands[3]->isImm()0 && |
1117 | 22 | Operands[4]->isImm()0 && Operands[5]->isReg()0 ) |
1118 | 0 | Offset = 1; |
1119 | 22 | else |
1120 | 22 | return false; |
1121 | 0 |
|
1122 | 0 | int PossibleAluOpIdx = Offset + 3; |
1123 | 0 | int PossibleBaseIdx = Offset + 1; |
1124 | 0 | int PossibleDestIdx = Offset + 4; |
1125 | 0 | if (LanaiOperand *PossibleAluOp = |
1126 | 0 | static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get())) |
1127 | 0 | if (0 PossibleAluOp->isImm()0 ) |
1128 | 0 | if (const MCConstantExpr *0 ConstExpr0 = |
1129 | 0 | dyn_cast<MCConstantExpr>(PossibleAluOp->getImm())) |
1130 | 0 | Modifies = LPAC::modifiesOp(ConstExpr->getValue()); |
1131 | 0 | return Modifies && Operands[PossibleBaseIdx]->isReg() && |
1132 | 0 | Operands[PossibleDestIdx]->isReg() && |
1133 | 0 | Operands[PossibleBaseIdx]->getReg() == |
1134 | 0 | Operands[PossibleDestIdx]->getReg(); |
1135 | 478 | } |
1136 | | |
1137 | 192 | static bool IsRegister(const MCParsedAsmOperand &op) { |
1138 | 192 | return static_cast<const LanaiOperand &>(op).isReg(); |
1139 | 192 | } |
1140 | | |
1141 | 478 | static bool MaybePredicatedInst(const OperandVector &Operands) { |
1142 | 478 | if (Operands.size() < 4 || 478 !IsRegister(*Operands[1])117 || |
1143 | 75 | !IsRegister(*Operands[2])) |
1144 | 459 | return false; |
1145 | 19 | return StringSwitch<bool>( |
1146 | 19 | static_cast<const LanaiOperand &>(*Operands[0]).getToken()) |
1147 | 19 | .StartsWith("addc", true) |
1148 | 19 | .StartsWith("add", true) |
1149 | 19 | .StartsWith("and", true) |
1150 | 19 | .StartsWith("sh", true) |
1151 | 19 | .StartsWith("subb", true) |
1152 | 19 | .StartsWith("sub", true) |
1153 | 19 | .StartsWith("or", true) |
1154 | 19 | .StartsWith("xor", true) |
1155 | 19 | .Default(false); |
1156 | 19 | } |
1157 | | |
1158 | | bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/, |
1159 | | StringRef Name, SMLoc NameLoc, |
1160 | 481 | OperandVector &Operands) { |
1161 | 481 | // First operand is token for instruction |
1162 | 481 | StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands); |
1163 | 481 | |
1164 | 481 | // If there are no more operands, then finish |
1165 | 481 | if (Lexer.is(AsmToken::EndOfStatement)) |
1166 | 3 | return false; |
1167 | 478 | |
1168 | 478 | // Parse first operand |
1169 | 478 | if (478 parseOperand(&Operands, Mnemonic) != MatchOperand_Success478 ) |
1170 | 0 | return true; |
1171 | 478 | |
1172 | 478 | // If it is a st instruction with one 1 operand then it is a "store true". |
1173 | 478 | // Transform <"st"> to <"s">, <LPCC:ICC_T> |
1174 | 478 | if (478 Lexer.is(AsmToken::EndOfStatement) && 478 Name == "st"69 && |
1175 | 478 | Operands.size() == 21 ) { |
1176 | 1 | Operands.erase(Operands.begin(), Operands.begin() + 1); |
1177 | 1 | Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc)); |
1178 | 1 | Operands.insert(Operands.begin() + 1, |
1179 | 1 | LanaiOperand::createImm( |
1180 | 1 | MCConstantExpr::create(LPCC::ICC_T, getContext()), |
1181 | 1 | NameLoc, NameLoc)); |
1182 | 1 | } |
1183 | 478 | |
1184 | 478 | // If the instruction is a bt instruction with 1 operand (in assembly) then it |
1185 | 478 | // is an unconditional branch instruction and the first two elements of |
1186 | 478 | // operands need to be merged. |
1187 | 478 | if (Lexer.is(AsmToken::EndOfStatement) && 478 Name.startswith("bt")69 && |
1188 | 478 | Operands.size() == 39 ) { |
1189 | 8 | Operands.erase(Operands.begin(), Operands.begin() + 2); |
1190 | 8 | Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc)); |
1191 | 8 | } |
1192 | 478 | |
1193 | 478 | // Parse until end of statement, consuming commas between operands |
1194 | 984 | while (Lexer.isNot(AsmToken::EndOfStatement) && 984 Lexer.is(AsmToken::Comma)506 ) { |
1195 | 506 | // Consume comma token |
1196 | 506 | Lex(); |
1197 | 506 | |
1198 | 506 | // Parse next operand |
1199 | 506 | if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success) |
1200 | 0 | return true; |
1201 | 506 | } |
1202 | 478 | |
1203 | 478 | if (478 IsMemoryAssignmentError(Operands)478 ) { |
1204 | 0 | Error(Parser.getTok().getLoc(), |
1205 | 0 | "the destination register can't equal the base register in an " |
1206 | 0 | "instruction that modifies the base register."); |
1207 | 0 | return true; |
1208 | 0 | } |
1209 | 478 | |
1210 | 478 | // Insert always true operand for instruction that may be predicated but |
1211 | 478 | // are not. Currently the autogenerated parser always expects a predicate. |
1212 | 478 | if (478 MaybePredicatedInst(Operands)478 ) { |
1213 | 19 | Operands.insert(Operands.begin() + 1, |
1214 | 19 | LanaiOperand::createImm( |
1215 | 19 | MCConstantExpr::create(LPCC::ICC_T, getContext()), |
1216 | 19 | NameLoc, NameLoc)); |
1217 | 19 | } |
1218 | 481 | |
1219 | 481 | return false; |
1220 | 481 | } |
1221 | | |
1222 | | #define GET_REGISTER_MATCHER |
1223 | | #define GET_MATCHER_IMPLEMENTATION |
1224 | | #include "LanaiGenAsmMatcher.inc" |
1225 | | |
1226 | 67.9k | extern "C" void LLVMInitializeLanaiAsmParser() { |
1227 | 67.9k | RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget()); |
1228 | 67.9k | } |
1229 | | |
1230 | | } // end namespace llvm |