]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- X86AsmParser.cpp - Parse X86 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 "MCTargetDesc/X86BaseInfo.h" | |
1a4d82fc JJ |
11 | #include "X86AsmInstrumentation.h" |
12 | #include "X86AsmParserCommon.h" | |
13 | #include "X86Operand.h" | |
970d7e83 | 14 | #include "llvm/ADT/APFloat.h" |
1a4d82fc | 15 | #include "llvm/ADT/STLExtras.h" |
970d7e83 LB |
16 | #include "llvm/ADT/SmallString.h" |
17 | #include "llvm/ADT/SmallVector.h" | |
18 | #include "llvm/ADT/StringSwitch.h" | |
19 | #include "llvm/ADT/Twine.h" | |
1a4d82fc | 20 | #include "llvm/MC/MCContext.h" |
223e47cc LB |
21 | #include "llvm/MC/MCExpr.h" |
22 | #include "llvm/MC/MCInst.h" | |
1a4d82fc | 23 | #include "llvm/MC/MCInstrInfo.h" |
223e47cc LB |
24 | #include "llvm/MC/MCParser/MCAsmLexer.h" |
25 | #include "llvm/MC/MCParser/MCAsmParser.h" | |
26 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" | |
970d7e83 LB |
27 | #include "llvm/MC/MCRegisterInfo.h" |
28 | #include "llvm/MC/MCStreamer.h" | |
29 | #include "llvm/MC/MCSubtargetInfo.h" | |
30 | #include "llvm/MC/MCSymbol.h" | |
31 | #include "llvm/MC/MCTargetAsmParser.h" | |
223e47cc LB |
32 | #include "llvm/Support/SourceMgr.h" |
33 | #include "llvm/Support/TargetRegistry.h" | |
34 | #include "llvm/Support/raw_ostream.h" | |
1a4d82fc JJ |
35 | #include <algorithm> |
36 | #include <memory> | |
223e47cc LB |
37 | |
38 | using namespace llvm; | |
39 | ||
40 | namespace { | |
1a4d82fc JJ |
41 | |
42 | static const char OpPrecedence[] = { | |
43 | 0, // IC_OR | |
44 | 1, // IC_AND | |
45 | 2, // IC_LSHIFT | |
46 | 2, // IC_RSHIFT | |
47 | 3, // IC_PLUS | |
48 | 3, // IC_MINUS | |
49 | 4, // IC_MULTIPLY | |
50 | 4, // IC_DIVIDE | |
51 | 5, // IC_RPAREN | |
52 | 6, // IC_LPAREN | |
53 | 0, // IC_IMM | |
54 | 0 // IC_REGISTER | |
55 | }; | |
223e47cc LB |
56 | |
57 | class X86AsmParser : public MCTargetAsmParser { | |
58 | MCSubtargetInfo &STI; | |
1a4d82fc | 59 | const MCInstrInfo &MII; |
970d7e83 | 60 | ParseInstructionInfo *InstInfo; |
1a4d82fc | 61 | std::unique_ptr<X86AsmInstrumentation> Instrumentation; |
223e47cc | 62 | private: |
1a4d82fc | 63 | SMLoc consumeToken() { |
85aaf69f | 64 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
65 | SMLoc Result = Parser.getTok().getLoc(); |
66 | Parser.Lex(); | |
67 | return Result; | |
68 | } | |
69 | ||
70 | enum InfixCalculatorTok { | |
71 | IC_OR = 0, | |
72 | IC_AND, | |
73 | IC_LSHIFT, | |
74 | IC_RSHIFT, | |
75 | IC_PLUS, | |
76 | IC_MINUS, | |
77 | IC_MULTIPLY, | |
78 | IC_DIVIDE, | |
79 | IC_RPAREN, | |
80 | IC_LPAREN, | |
81 | IC_IMM, | |
82 | IC_REGISTER | |
83 | }; | |
84 | ||
85 | class InfixCalculator { | |
86 | typedef std::pair< InfixCalculatorTok, int64_t > ICToken; | |
87 | SmallVector<InfixCalculatorTok, 4> InfixOperatorStack; | |
88 | SmallVector<ICToken, 4> PostfixStack; | |
85aaf69f | 89 | |
1a4d82fc JJ |
90 | public: |
91 | int64_t popOperand() { | |
92 | assert (!PostfixStack.empty() && "Poped an empty stack!"); | |
93 | ICToken Op = PostfixStack.pop_back_val(); | |
94 | assert ((Op.first == IC_IMM || Op.first == IC_REGISTER) | |
95 | && "Expected and immediate or register!"); | |
96 | return Op.second; | |
97 | } | |
98 | void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) { | |
99 | assert ((Op == IC_IMM || Op == IC_REGISTER) && | |
100 | "Unexpected operand!"); | |
101 | PostfixStack.push_back(std::make_pair(Op, Val)); | |
102 | } | |
85aaf69f | 103 | |
1a4d82fc JJ |
104 | void popOperator() { InfixOperatorStack.pop_back(); } |
105 | void pushOperator(InfixCalculatorTok Op) { | |
106 | // Push the new operator if the stack is empty. | |
107 | if (InfixOperatorStack.empty()) { | |
108 | InfixOperatorStack.push_back(Op); | |
109 | return; | |
110 | } | |
85aaf69f | 111 | |
1a4d82fc JJ |
112 | // Push the new operator if it has a higher precedence than the operator |
113 | // on the top of the stack or the operator on the top of the stack is a | |
114 | // left parentheses. | |
115 | unsigned Idx = InfixOperatorStack.size() - 1; | |
116 | InfixCalculatorTok StackOp = InfixOperatorStack[Idx]; | |
117 | if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) { | |
118 | InfixOperatorStack.push_back(Op); | |
119 | return; | |
120 | } | |
85aaf69f | 121 | |
1a4d82fc JJ |
122 | // The operator on the top of the stack has higher precedence than the |
123 | // new operator. | |
124 | unsigned ParenCount = 0; | |
125 | while (1) { | |
126 | // Nothing to process. | |
127 | if (InfixOperatorStack.empty()) | |
128 | break; | |
85aaf69f | 129 | |
1a4d82fc JJ |
130 | Idx = InfixOperatorStack.size() - 1; |
131 | StackOp = InfixOperatorStack[Idx]; | |
132 | if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount)) | |
133 | break; | |
85aaf69f | 134 | |
1a4d82fc JJ |
135 | // If we have an even parentheses count and we see a left parentheses, |
136 | // then stop processing. | |
137 | if (!ParenCount && StackOp == IC_LPAREN) | |
138 | break; | |
85aaf69f | 139 | |
1a4d82fc JJ |
140 | if (StackOp == IC_RPAREN) { |
141 | ++ParenCount; | |
142 | InfixOperatorStack.pop_back(); | |
143 | } else if (StackOp == IC_LPAREN) { | |
144 | --ParenCount; | |
145 | InfixOperatorStack.pop_back(); | |
146 | } else { | |
147 | InfixOperatorStack.pop_back(); | |
148 | PostfixStack.push_back(std::make_pair(StackOp, 0)); | |
149 | } | |
150 | } | |
151 | // Push the new operator. | |
152 | InfixOperatorStack.push_back(Op); | |
153 | } | |
154 | int64_t execute() { | |
155 | // Push any remaining operators onto the postfix stack. | |
156 | while (!InfixOperatorStack.empty()) { | |
157 | InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val(); | |
158 | if (StackOp != IC_LPAREN && StackOp != IC_RPAREN) | |
159 | PostfixStack.push_back(std::make_pair(StackOp, 0)); | |
160 | } | |
85aaf69f | 161 | |
1a4d82fc JJ |
162 | if (PostfixStack.empty()) |
163 | return 0; | |
85aaf69f | 164 | |
1a4d82fc JJ |
165 | SmallVector<ICToken, 16> OperandStack; |
166 | for (unsigned i = 0, e = PostfixStack.size(); i != e; ++i) { | |
167 | ICToken Op = PostfixStack[i]; | |
168 | if (Op.first == IC_IMM || Op.first == IC_REGISTER) { | |
169 | OperandStack.push_back(Op); | |
170 | } else { | |
171 | assert (OperandStack.size() > 1 && "Too few operands."); | |
172 | int64_t Val; | |
173 | ICToken Op2 = OperandStack.pop_back_val(); | |
174 | ICToken Op1 = OperandStack.pop_back_val(); | |
175 | switch (Op.first) { | |
176 | default: | |
177 | report_fatal_error("Unexpected operator!"); | |
178 | break; | |
179 | case IC_PLUS: | |
180 | Val = Op1.second + Op2.second; | |
181 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
182 | break; | |
183 | case IC_MINUS: | |
184 | Val = Op1.second - Op2.second; | |
185 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
186 | break; | |
187 | case IC_MULTIPLY: | |
188 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
189 | "Multiply operation with an immediate and a register!"); | |
190 | Val = Op1.second * Op2.second; | |
191 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
192 | break; | |
193 | case IC_DIVIDE: | |
194 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
195 | "Divide operation with an immediate and a register!"); | |
196 | assert (Op2.second != 0 && "Division by zero!"); | |
197 | Val = Op1.second / Op2.second; | |
198 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
199 | break; | |
200 | case IC_OR: | |
201 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
202 | "Or operation with an immediate and a register!"); | |
203 | Val = Op1.second | Op2.second; | |
204 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
205 | break; | |
206 | case IC_AND: | |
207 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
208 | "And operation with an immediate and a register!"); | |
209 | Val = Op1.second & Op2.second; | |
210 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
211 | break; | |
212 | case IC_LSHIFT: | |
213 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
214 | "Left shift operation with an immediate and a register!"); | |
215 | Val = Op1.second << Op2.second; | |
216 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
217 | break; | |
218 | case IC_RSHIFT: | |
219 | assert (Op1.first == IC_IMM && Op2.first == IC_IMM && | |
220 | "Right shift operation with an immediate and a register!"); | |
221 | Val = Op1.second >> Op2.second; | |
222 | OperandStack.push_back(std::make_pair(IC_IMM, Val)); | |
223 | break; | |
224 | } | |
225 | } | |
226 | } | |
227 | assert (OperandStack.size() == 1 && "Expected a single result."); | |
228 | return OperandStack.pop_back_val().second; | |
229 | } | |
230 | }; | |
231 | ||
232 | enum IntelExprState { | |
233 | IES_OR, | |
234 | IES_AND, | |
235 | IES_LSHIFT, | |
236 | IES_RSHIFT, | |
237 | IES_PLUS, | |
238 | IES_MINUS, | |
239 | IES_NOT, | |
240 | IES_MULTIPLY, | |
241 | IES_DIVIDE, | |
242 | IES_LBRAC, | |
243 | IES_RBRAC, | |
244 | IES_LPAREN, | |
245 | IES_RPAREN, | |
246 | IES_REGISTER, | |
247 | IES_INTEGER, | |
248 | IES_IDENTIFIER, | |
249 | IES_ERROR | |
250 | }; | |
251 | ||
252 | class IntelExprStateMachine { | |
253 | IntelExprState State, PrevState; | |
254 | unsigned BaseReg, IndexReg, TmpReg, Scale; | |
255 | int64_t Imm; | |
256 | const MCExpr *Sym; | |
257 | StringRef SymName; | |
258 | bool StopOnLBrac, AddImmPrefix; | |
259 | InfixCalculator IC; | |
260 | InlineAsmIdentifierInfo Info; | |
261 | public: | |
262 | IntelExprStateMachine(int64_t imm, bool stoponlbrac, bool addimmprefix) : | |
263 | State(IES_PLUS), PrevState(IES_ERROR), BaseReg(0), IndexReg(0), TmpReg(0), | |
264 | Scale(1), Imm(imm), Sym(nullptr), StopOnLBrac(stoponlbrac), | |
265 | AddImmPrefix(addimmprefix) { Info.clear(); } | |
85aaf69f | 266 | |
1a4d82fc JJ |
267 | unsigned getBaseReg() { return BaseReg; } |
268 | unsigned getIndexReg() { return IndexReg; } | |
269 | unsigned getScale() { return Scale; } | |
270 | const MCExpr *getSym() { return Sym; } | |
271 | StringRef getSymName() { return SymName; } | |
272 | int64_t getImm() { return Imm + IC.execute(); } | |
273 | bool isValidEndState() { | |
274 | return State == IES_RBRAC || State == IES_INTEGER; | |
275 | } | |
276 | bool getStopOnLBrac() { return StopOnLBrac; } | |
277 | bool getAddImmPrefix() { return AddImmPrefix; } | |
278 | bool hadError() { return State == IES_ERROR; } | |
279 | ||
280 | InlineAsmIdentifierInfo &getIdentifierInfo() { | |
281 | return Info; | |
282 | } | |
283 | ||
284 | void onOr() { | |
285 | IntelExprState CurrState = State; | |
286 | switch (State) { | |
287 | default: | |
288 | State = IES_ERROR; | |
289 | break; | |
290 | case IES_INTEGER: | |
291 | case IES_RPAREN: | |
292 | case IES_REGISTER: | |
293 | State = IES_OR; | |
294 | IC.pushOperator(IC_OR); | |
295 | break; | |
296 | } | |
297 | PrevState = CurrState; | |
298 | } | |
299 | void onAnd() { | |
300 | IntelExprState CurrState = State; | |
301 | switch (State) { | |
302 | default: | |
303 | State = IES_ERROR; | |
304 | break; | |
305 | case IES_INTEGER: | |
306 | case IES_RPAREN: | |
307 | case IES_REGISTER: | |
308 | State = IES_AND; | |
309 | IC.pushOperator(IC_AND); | |
310 | break; | |
311 | } | |
312 | PrevState = CurrState; | |
313 | } | |
314 | void onLShift() { | |
315 | IntelExprState CurrState = State; | |
316 | switch (State) { | |
317 | default: | |
318 | State = IES_ERROR; | |
319 | break; | |
320 | case IES_INTEGER: | |
321 | case IES_RPAREN: | |
322 | case IES_REGISTER: | |
323 | State = IES_LSHIFT; | |
324 | IC.pushOperator(IC_LSHIFT); | |
325 | break; | |
326 | } | |
327 | PrevState = CurrState; | |
328 | } | |
329 | void onRShift() { | |
330 | IntelExprState CurrState = State; | |
331 | switch (State) { | |
332 | default: | |
333 | State = IES_ERROR; | |
334 | break; | |
335 | case IES_INTEGER: | |
336 | case IES_RPAREN: | |
337 | case IES_REGISTER: | |
338 | State = IES_RSHIFT; | |
339 | IC.pushOperator(IC_RSHIFT); | |
340 | break; | |
341 | } | |
342 | PrevState = CurrState; | |
343 | } | |
344 | void onPlus() { | |
345 | IntelExprState CurrState = State; | |
346 | switch (State) { | |
347 | default: | |
348 | State = IES_ERROR; | |
349 | break; | |
350 | case IES_INTEGER: | |
351 | case IES_RPAREN: | |
352 | case IES_REGISTER: | |
353 | State = IES_PLUS; | |
354 | IC.pushOperator(IC_PLUS); | |
355 | if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) { | |
356 | // If we already have a BaseReg, then assume this is the IndexReg with | |
357 | // a scale of 1. | |
358 | if (!BaseReg) { | |
359 | BaseReg = TmpReg; | |
360 | } else { | |
361 | assert (!IndexReg && "BaseReg/IndexReg already set!"); | |
362 | IndexReg = TmpReg; | |
363 | Scale = 1; | |
364 | } | |
365 | } | |
366 | break; | |
367 | } | |
368 | PrevState = CurrState; | |
369 | } | |
370 | void onMinus() { | |
371 | IntelExprState CurrState = State; | |
372 | switch (State) { | |
373 | default: | |
374 | State = IES_ERROR; | |
375 | break; | |
376 | case IES_PLUS: | |
377 | case IES_NOT: | |
378 | case IES_MULTIPLY: | |
379 | case IES_DIVIDE: | |
380 | case IES_LPAREN: | |
381 | case IES_RPAREN: | |
382 | case IES_LBRAC: | |
383 | case IES_RBRAC: | |
384 | case IES_INTEGER: | |
385 | case IES_REGISTER: | |
386 | State = IES_MINUS; | |
387 | // Only push the minus operator if it is not a unary operator. | |
388 | if (!(CurrState == IES_PLUS || CurrState == IES_MINUS || | |
389 | CurrState == IES_MULTIPLY || CurrState == IES_DIVIDE || | |
390 | CurrState == IES_LPAREN || CurrState == IES_LBRAC)) | |
391 | IC.pushOperator(IC_MINUS); | |
392 | if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) { | |
393 | // If we already have a BaseReg, then assume this is the IndexReg with | |
394 | // a scale of 1. | |
395 | if (!BaseReg) { | |
396 | BaseReg = TmpReg; | |
397 | } else { | |
398 | assert (!IndexReg && "BaseReg/IndexReg already set!"); | |
399 | IndexReg = TmpReg; | |
400 | Scale = 1; | |
401 | } | |
402 | } | |
403 | break; | |
404 | } | |
405 | PrevState = CurrState; | |
406 | } | |
407 | void onNot() { | |
408 | IntelExprState CurrState = State; | |
409 | switch (State) { | |
410 | default: | |
411 | State = IES_ERROR; | |
412 | break; | |
413 | case IES_PLUS: | |
414 | case IES_NOT: | |
415 | State = IES_NOT; | |
416 | break; | |
417 | } | |
418 | PrevState = CurrState; | |
419 | } | |
420 | void onRegister(unsigned Reg) { | |
421 | IntelExprState CurrState = State; | |
422 | switch (State) { | |
423 | default: | |
424 | State = IES_ERROR; | |
425 | break; | |
426 | case IES_PLUS: | |
427 | case IES_LPAREN: | |
428 | State = IES_REGISTER; | |
429 | TmpReg = Reg; | |
430 | IC.pushOperand(IC_REGISTER); | |
431 | break; | |
432 | case IES_MULTIPLY: | |
433 | // Index Register - Scale * Register | |
434 | if (PrevState == IES_INTEGER) { | |
435 | assert (!IndexReg && "IndexReg already set!"); | |
436 | State = IES_REGISTER; | |
437 | IndexReg = Reg; | |
438 | // Get the scale and replace the 'Scale * Register' with '0'. | |
439 | Scale = IC.popOperand(); | |
440 | IC.pushOperand(IC_IMM); | |
441 | IC.popOperator(); | |
442 | } else { | |
443 | State = IES_ERROR; | |
444 | } | |
445 | break; | |
446 | } | |
447 | PrevState = CurrState; | |
448 | } | |
449 | void onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName) { | |
450 | PrevState = State; | |
451 | switch (State) { | |
452 | default: | |
453 | State = IES_ERROR; | |
454 | break; | |
455 | case IES_PLUS: | |
456 | case IES_MINUS: | |
457 | case IES_NOT: | |
458 | State = IES_INTEGER; | |
459 | Sym = SymRef; | |
460 | SymName = SymRefName; | |
461 | IC.pushOperand(IC_IMM); | |
462 | break; | |
463 | } | |
464 | } | |
465 | bool onInteger(int64_t TmpInt, StringRef &ErrMsg) { | |
466 | IntelExprState CurrState = State; | |
467 | switch (State) { | |
468 | default: | |
469 | State = IES_ERROR; | |
470 | break; | |
471 | case IES_PLUS: | |
472 | case IES_MINUS: | |
473 | case IES_NOT: | |
474 | case IES_OR: | |
475 | case IES_AND: | |
476 | case IES_LSHIFT: | |
477 | case IES_RSHIFT: | |
478 | case IES_DIVIDE: | |
479 | case IES_MULTIPLY: | |
480 | case IES_LPAREN: | |
481 | State = IES_INTEGER; | |
482 | if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) { | |
483 | // Index Register - Register * Scale | |
484 | assert (!IndexReg && "IndexReg already set!"); | |
485 | IndexReg = TmpReg; | |
486 | Scale = TmpInt; | |
487 | if(Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) { | |
488 | ErrMsg = "scale factor in address must be 1, 2, 4 or 8"; | |
489 | return true; | |
490 | } | |
491 | // Get the scale and replace the 'Register * Scale' with '0'. | |
492 | IC.popOperator(); | |
493 | } else if ((PrevState == IES_PLUS || PrevState == IES_MINUS || | |
494 | PrevState == IES_OR || PrevState == IES_AND || | |
495 | PrevState == IES_LSHIFT || PrevState == IES_RSHIFT || | |
496 | PrevState == IES_MULTIPLY || PrevState == IES_DIVIDE || | |
497 | PrevState == IES_LPAREN || PrevState == IES_LBRAC || | |
498 | PrevState == IES_NOT) && | |
499 | CurrState == IES_MINUS) { | |
500 | // Unary minus. No need to pop the minus operand because it was never | |
501 | // pushed. | |
502 | IC.pushOperand(IC_IMM, -TmpInt); // Push -Imm. | |
503 | } else if ((PrevState == IES_PLUS || PrevState == IES_MINUS || | |
504 | PrevState == IES_OR || PrevState == IES_AND || | |
505 | PrevState == IES_LSHIFT || PrevState == IES_RSHIFT || | |
506 | PrevState == IES_MULTIPLY || PrevState == IES_DIVIDE || | |
507 | PrevState == IES_LPAREN || PrevState == IES_LBRAC || | |
508 | PrevState == IES_NOT) && | |
509 | CurrState == IES_NOT) { | |
510 | // Unary not. No need to pop the not operand because it was never | |
511 | // pushed. | |
512 | IC.pushOperand(IC_IMM, ~TmpInt); // Push ~Imm. | |
513 | } else { | |
514 | IC.pushOperand(IC_IMM, TmpInt); | |
515 | } | |
516 | break; | |
517 | } | |
518 | PrevState = CurrState; | |
519 | return false; | |
520 | } | |
521 | void onStar() { | |
522 | PrevState = State; | |
523 | switch (State) { | |
524 | default: | |
525 | State = IES_ERROR; | |
526 | break; | |
527 | case IES_INTEGER: | |
528 | case IES_REGISTER: | |
529 | case IES_RPAREN: | |
530 | State = IES_MULTIPLY; | |
531 | IC.pushOperator(IC_MULTIPLY); | |
532 | break; | |
533 | } | |
534 | } | |
535 | void onDivide() { | |
536 | PrevState = State; | |
537 | switch (State) { | |
538 | default: | |
539 | State = IES_ERROR; | |
540 | break; | |
541 | case IES_INTEGER: | |
542 | case IES_RPAREN: | |
543 | State = IES_DIVIDE; | |
544 | IC.pushOperator(IC_DIVIDE); | |
545 | break; | |
546 | } | |
547 | } | |
548 | void onLBrac() { | |
549 | PrevState = State; | |
550 | switch (State) { | |
551 | default: | |
552 | State = IES_ERROR; | |
553 | break; | |
554 | case IES_RBRAC: | |
555 | State = IES_PLUS; | |
556 | IC.pushOperator(IC_PLUS); | |
557 | break; | |
558 | } | |
559 | } | |
560 | void onRBrac() { | |
561 | IntelExprState CurrState = State; | |
562 | switch (State) { | |
563 | default: | |
564 | State = IES_ERROR; | |
565 | break; | |
566 | case IES_INTEGER: | |
567 | case IES_REGISTER: | |
568 | case IES_RPAREN: | |
569 | State = IES_RBRAC; | |
570 | if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) { | |
571 | // If we already have a BaseReg, then assume this is the IndexReg with | |
572 | // a scale of 1. | |
573 | if (!BaseReg) { | |
574 | BaseReg = TmpReg; | |
575 | } else { | |
576 | assert (!IndexReg && "BaseReg/IndexReg already set!"); | |
577 | IndexReg = TmpReg; | |
578 | Scale = 1; | |
579 | } | |
580 | } | |
581 | break; | |
582 | } | |
583 | PrevState = CurrState; | |
584 | } | |
585 | void onLParen() { | |
586 | IntelExprState CurrState = State; | |
587 | switch (State) { | |
588 | default: | |
589 | State = IES_ERROR; | |
590 | break; | |
591 | case IES_PLUS: | |
592 | case IES_MINUS: | |
593 | case IES_NOT: | |
594 | case IES_OR: | |
595 | case IES_AND: | |
596 | case IES_LSHIFT: | |
597 | case IES_RSHIFT: | |
598 | case IES_MULTIPLY: | |
599 | case IES_DIVIDE: | |
600 | case IES_LPAREN: | |
601 | // FIXME: We don't handle this type of unary minus or not, yet. | |
602 | if ((PrevState == IES_PLUS || PrevState == IES_MINUS || | |
603 | PrevState == IES_OR || PrevState == IES_AND || | |
604 | PrevState == IES_LSHIFT || PrevState == IES_RSHIFT || | |
605 | PrevState == IES_MULTIPLY || PrevState == IES_DIVIDE || | |
606 | PrevState == IES_LPAREN || PrevState == IES_LBRAC || | |
607 | PrevState == IES_NOT) && | |
608 | (CurrState == IES_MINUS || CurrState == IES_NOT)) { | |
609 | State = IES_ERROR; | |
610 | break; | |
611 | } | |
612 | State = IES_LPAREN; | |
613 | IC.pushOperator(IC_LPAREN); | |
614 | break; | |
615 | } | |
616 | PrevState = CurrState; | |
617 | } | |
618 | void onRParen() { | |
619 | PrevState = State; | |
620 | switch (State) { | |
621 | default: | |
622 | State = IES_ERROR; | |
623 | break; | |
624 | case IES_INTEGER: | |
625 | case IES_REGISTER: | |
626 | case IES_RPAREN: | |
627 | State = IES_RPAREN; | |
628 | IC.pushOperator(IC_RPAREN); | |
629 | break; | |
630 | } | |
631 | } | |
632 | }; | |
633 | ||
223e47cc | 634 | bool Error(SMLoc L, const Twine &Msg, |
1a4d82fc | 635 | ArrayRef<SMRange> Ranges = None, |
970d7e83 | 636 | bool MatchingInlineAsm = false) { |
85aaf69f | 637 | MCAsmParser &Parser = getParser(); |
970d7e83 | 638 | if (MatchingInlineAsm) return true; |
223e47cc LB |
639 | return Parser.Error(L, Msg, Ranges); |
640 | } | |
641 | ||
1a4d82fc JJ |
642 | bool ErrorAndEatStatement(SMLoc L, const Twine &Msg, |
643 | ArrayRef<SMRange> Ranges = None, | |
644 | bool MatchingInlineAsm = false) { | |
85aaf69f SL |
645 | MCAsmParser &Parser = getParser(); |
646 | Parser.eatToEndOfStatement(); | |
647 | return Error(L, Msg, Ranges, MatchingInlineAsm); | |
223e47cc LB |
648 | } |
649 | ||
1a4d82fc JJ |
650 | std::nullptr_t ErrorOperand(SMLoc Loc, StringRef Msg) { |
651 | Error(Loc, Msg); | |
652 | return nullptr; | |
653 | } | |
654 | ||
655 | std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc); | |
656 | std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc); | |
657 | std::unique_ptr<X86Operand> ParseOperand(); | |
658 | std::unique_ptr<X86Operand> ParseATTOperand(); | |
659 | std::unique_ptr<X86Operand> ParseIntelOperand(); | |
660 | std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator(); | |
661 | bool ParseIntelDotOperator(const MCExpr *Disp, const MCExpr *&NewDisp); | |
662 | std::unique_ptr<X86Operand> ParseIntelOperator(unsigned OpKind); | |
663 | std::unique_ptr<X86Operand> | |
664 | ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size); | |
665 | std::unique_ptr<X86Operand> | |
666 | ParseIntelMemOperand(int64_t ImmDisp, SMLoc StartLoc, unsigned Size); | |
667 | bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); | |
668 | std::unique_ptr<X86Operand> ParseIntelBracExpression(unsigned SegReg, | |
669 | SMLoc Start, | |
670 | int64_t ImmDisp, | |
671 | unsigned Size); | |
672 | bool ParseIntelIdentifier(const MCExpr *&Val, StringRef &Identifier, | |
673 | InlineAsmIdentifierInfo &Info, | |
674 | bool IsUnevaluatedOperand, SMLoc &End); | |
675 | ||
676 | std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc StartLoc); | |
677 | ||
678 | std::unique_ptr<X86Operand> | |
679 | CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, | |
680 | unsigned IndexReg, unsigned Scale, SMLoc Start, | |
681 | SMLoc End, unsigned Size, StringRef Identifier, | |
682 | InlineAsmIdentifierInfo &Info); | |
970d7e83 | 683 | |
223e47cc LB |
684 | bool ParseDirectiveWord(unsigned Size, SMLoc L); |
685 | bool ParseDirectiveCode(StringRef IDVal, SMLoc L); | |
686 | ||
85aaf69f | 687 | bool validateInstruction(MCInst &Inst, const OperandVector &Ops); |
1a4d82fc JJ |
688 | bool processInstruction(MCInst &Inst, const OperandVector &Ops); |
689 | ||
690 | /// Wrapper around MCStreamer::EmitInstruction(). Possibly adds | |
691 | /// instrumentation around Inst. | |
692 | void EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out); | |
223e47cc | 693 | |
970d7e83 | 694 | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
1a4d82fc JJ |
695 | OperandVector &Operands, MCStreamer &Out, |
696 | uint64_t &ErrorInfo, | |
697 | bool MatchingInlineAsm) override; | |
698 | ||
699 | void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands, | |
700 | MCStreamer &Out, bool MatchingInlineAsm); | |
223e47cc | 701 | |
1a4d82fc JJ |
702 | bool ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, |
703 | bool MatchingInlineAsm); | |
223e47cc | 704 | |
1a4d82fc JJ |
705 | bool MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, |
706 | OperandVector &Operands, MCStreamer &Out, | |
707 | uint64_t &ErrorInfo, | |
708 | bool MatchingInlineAsm); | |
709 | ||
710 | bool MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, | |
711 | OperandVector &Operands, MCStreamer &Out, | |
712 | uint64_t &ErrorInfo, | |
713 | bool MatchingInlineAsm); | |
714 | ||
1a4d82fc JJ |
715 | bool OmitRegisterFromClobberLists(unsigned RegNo) override; |
716 | ||
717 | /// doSrcDstMatch - Returns true if operands are matching in their | |
718 | /// word size (%si and %di, %esi and %edi, etc.). Order depends on | |
719 | /// the parsing mode (Intel vs. AT&T). | |
720 | bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2); | |
721 | ||
722 | /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z}) | |
723 | /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required. | |
724 | /// \return \c true if no parsing errors occurred, \c false otherwise. | |
725 | bool HandleAVX512Operand(OperandVector &Operands, | |
726 | const MCParsedAsmOperand &Op); | |
223e47cc LB |
727 | |
728 | bool is64BitMode() const { | |
729 | // FIXME: Can tablegen auto-generate this? | |
730 | return (STI.getFeatureBits() & X86::Mode64Bit) != 0; | |
731 | } | |
1a4d82fc JJ |
732 | bool is32BitMode() const { |
733 | // FIXME: Can tablegen auto-generate this? | |
734 | return (STI.getFeatureBits() & X86::Mode32Bit) != 0; | |
735 | } | |
736 | bool is16BitMode() const { | |
737 | // FIXME: Can tablegen auto-generate this? | |
738 | return (STI.getFeatureBits() & X86::Mode16Bit) != 0; | |
739 | } | |
740 | void SwitchMode(uint64_t mode) { | |
741 | uint64_t oldMode = STI.getFeatureBits() & | |
742 | (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit); | |
743 | unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(oldMode | mode)); | |
223e47cc | 744 | setAvailableFeatures(FB); |
1a4d82fc JJ |
745 | assert(mode == (STI.getFeatureBits() & |
746 | (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit))); | |
747 | } | |
748 | ||
749 | unsigned getPointerWidth() { | |
750 | if (is16BitMode()) return 16; | |
751 | if (is32BitMode()) return 32; | |
752 | if (is64BitMode()) return 64; | |
753 | llvm_unreachable("invalid mode"); | |
754 | } | |
755 | ||
756 | bool isParsingIntelSyntax() { | |
757 | return getParser().getAssemblerDialect(); | |
223e47cc LB |
758 | } |
759 | ||
760 | /// @name Auto-generated Matcher Functions | |
761 | /// { | |
762 | ||
763 | #define GET_ASSEMBLER_HEADER | |
764 | #include "X86GenAsmMatcher.inc" | |
765 | ||
766 | /// } | |
767 | ||
768 | public: | |
85aaf69f SL |
769 | X86AsmParser(MCSubtargetInfo &sti, MCAsmParser &Parser, |
770 | const MCInstrInfo &mii, const MCTargetOptions &Options) | |
771 | : MCTargetAsmParser(), STI(sti), MII(mii), InstInfo(nullptr) { | |
223e47cc LB |
772 | |
773 | // Initialize the set of available features. | |
774 | setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); | |
1a4d82fc JJ |
775 | Instrumentation.reset( |
776 | CreateX86AsmInstrumentation(Options, Parser.getContext(), STI)); | |
223e47cc | 777 | } |
223e47cc | 778 | |
1a4d82fc | 779 | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; |
223e47cc | 780 | |
1a4d82fc | 781 | void SetFrameRegister(unsigned RegNo) override; |
223e47cc | 782 | |
1a4d82fc JJ |
783 | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
784 | SMLoc NameLoc, OperandVector &Operands) override; | |
785 | ||
786 | bool ParseDirective(AsmToken DirectiveID) override; | |
223e47cc LB |
787 | }; |
788 | } // end anonymous namespace | |
789 | ||
790 | /// @name Auto-generated Match Functions | |
791 | /// { | |
792 | ||
793 | static unsigned MatchRegisterName(StringRef Name); | |
794 | ||
795 | /// } | |
796 | ||
1a4d82fc JJ |
797 | static bool CheckBaseRegAndIndexReg(unsigned BaseReg, unsigned IndexReg, |
798 | StringRef &ErrMsg) { | |
799 | // If we have both a base register and an index register make sure they are | |
800 | // both 64-bit or 32-bit registers. | |
801 | // To support VSIB, IndexReg can be 128-bit or 256-bit registers. | |
802 | if (BaseReg != 0 && IndexReg != 0) { | |
803 | if (X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) && | |
804 | (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) || | |
805 | X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg)) && | |
806 | IndexReg != X86::RIZ) { | |
807 | ErrMsg = "base register is 64-bit, but index register is not"; | |
223e47cc | 808 | return true; |
1a4d82fc JJ |
809 | } |
810 | if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) && | |
811 | (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) || | |
812 | X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) && | |
813 | IndexReg != X86::EIZ){ | |
814 | ErrMsg = "base register is 32-bit, but index register is not"; | |
223e47cc | 815 | return true; |
1a4d82fc JJ |
816 | } |
817 | if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) { | |
818 | if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) || | |
819 | X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) { | |
820 | ErrMsg = "base register is 16-bit, but index register is not"; | |
821 | return true; | |
822 | } | |
823 | if (((BaseReg == X86::BX || BaseReg == X86::BP) && | |
824 | IndexReg != X86::SI && IndexReg != X86::DI) || | |
825 | ((BaseReg == X86::SI || BaseReg == X86::DI) && | |
826 | IndexReg != X86::BX && IndexReg != X86::BP)) { | |
827 | ErrMsg = "invalid 16-bit base/index register combination"; | |
828 | return true; | |
829 | } | |
830 | } | |
223e47cc | 831 | } |
1a4d82fc | 832 | return false; |
223e47cc LB |
833 | } |
834 | ||
1a4d82fc JJ |
835 | bool X86AsmParser::doSrcDstMatch(X86Operand &Op1, X86Operand &Op2) |
836 | { | |
837 | // Return true and let a normal complaint about bogus operands happen. | |
838 | if (!Op1.isMem() || !Op2.isMem()) | |
839 | return true; | |
223e47cc | 840 | |
1a4d82fc JJ |
841 | // Actually these might be the other way round if Intel syntax is |
842 | // being used. It doesn't matter. | |
843 | unsigned diReg = Op1.Mem.BaseReg; | |
844 | unsigned siReg = Op2.Mem.BaseReg; | |
845 | ||
846 | if (X86MCRegisterClasses[X86::GR16RegClassID].contains(siReg)) | |
847 | return X86MCRegisterClasses[X86::GR16RegClassID].contains(diReg); | |
848 | if (X86MCRegisterClasses[X86::GR32RegClassID].contains(siReg)) | |
849 | return X86MCRegisterClasses[X86::GR32RegClassID].contains(diReg); | |
850 | if (X86MCRegisterClasses[X86::GR64RegClassID].contains(siReg)) | |
851 | return X86MCRegisterClasses[X86::GR64RegClassID].contains(diReg); | |
852 | // Again, return true and let another error happen. | |
853 | return true; | |
223e47cc LB |
854 | } |
855 | ||
856 | bool X86AsmParser::ParseRegister(unsigned &RegNo, | |
857 | SMLoc &StartLoc, SMLoc &EndLoc) { | |
85aaf69f | 858 | MCAsmParser &Parser = getParser(); |
223e47cc LB |
859 | RegNo = 0; |
860 | const AsmToken &PercentTok = Parser.getTok(); | |
861 | StartLoc = PercentTok.getLoc(); | |
862 | ||
863 | // If we encounter a %, ignore it. This code handles registers with and | |
864 | // without the prefix, unprefixed registers can occur in cfi directives. | |
865 | if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) | |
866 | Parser.Lex(); // Eat percent token. | |
867 | ||
868 | const AsmToken &Tok = Parser.getTok(); | |
970d7e83 LB |
869 | EndLoc = Tok.getEndLoc(); |
870 | ||
223e47cc LB |
871 | if (Tok.isNot(AsmToken::Identifier)) { |
872 | if (isParsingIntelSyntax()) return true; | |
873 | return Error(StartLoc, "invalid register name", | |
970d7e83 | 874 | SMRange(StartLoc, EndLoc)); |
223e47cc LB |
875 | } |
876 | ||
877 | RegNo = MatchRegisterName(Tok.getString()); | |
878 | ||
879 | // If the match failed, try the register name as lowercase. | |
880 | if (RegNo == 0) | |
881 | RegNo = MatchRegisterName(Tok.getString().lower()); | |
882 | ||
883 | if (!is64BitMode()) { | |
1a4d82fc | 884 | // FIXME: This should be done using Requires<Not64BitMode> and |
223e47cc LB |
885 | // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also |
886 | // checked. | |
887 | // FIXME: Check AH, CH, DH, BH cannot be used in an instruction requiring a | |
888 | // REX prefix. | |
889 | if (RegNo == X86::RIZ || | |
890 | X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) || | |
891 | X86II::isX86_64NonExtLowByteReg(RegNo) || | |
892 | X86II::isX86_64ExtendedReg(RegNo)) | |
893 | return Error(StartLoc, "register %" | |
894 | + Tok.getString() + " is only available in 64-bit mode", | |
970d7e83 | 895 | SMRange(StartLoc, EndLoc)); |
223e47cc LB |
896 | } |
897 | ||
898 | // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. | |
899 | if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) { | |
900 | RegNo = X86::ST0; | |
223e47cc LB |
901 | Parser.Lex(); // Eat 'st' |
902 | ||
903 | // Check to see if we have '(4)' after %st. | |
904 | if (getLexer().isNot(AsmToken::LParen)) | |
905 | return false; | |
906 | // Lex the paren. | |
907 | getParser().Lex(); | |
908 | ||
909 | const AsmToken &IntTok = Parser.getTok(); | |
910 | if (IntTok.isNot(AsmToken::Integer)) | |
911 | return Error(IntTok.getLoc(), "expected stack index"); | |
912 | switch (IntTok.getIntVal()) { | |
913 | case 0: RegNo = X86::ST0; break; | |
914 | case 1: RegNo = X86::ST1; break; | |
915 | case 2: RegNo = X86::ST2; break; | |
916 | case 3: RegNo = X86::ST3; break; | |
917 | case 4: RegNo = X86::ST4; break; | |
918 | case 5: RegNo = X86::ST5; break; | |
919 | case 6: RegNo = X86::ST6; break; | |
920 | case 7: RegNo = X86::ST7; break; | |
921 | default: return Error(IntTok.getLoc(), "invalid stack index"); | |
922 | } | |
923 | ||
924 | if (getParser().Lex().isNot(AsmToken::RParen)) | |
925 | return Error(Parser.getTok().getLoc(), "expected ')'"); | |
926 | ||
970d7e83 | 927 | EndLoc = Parser.getTok().getEndLoc(); |
223e47cc LB |
928 | Parser.Lex(); // Eat ')' |
929 | return false; | |
930 | } | |
931 | ||
970d7e83 LB |
932 | EndLoc = Parser.getTok().getEndLoc(); |
933 | ||
223e47cc LB |
934 | // If this is "db[0-7]", match it as an alias |
935 | // for dr[0-7]. | |
936 | if (RegNo == 0 && Tok.getString().size() == 3 && | |
937 | Tok.getString().startswith("db")) { | |
938 | switch (Tok.getString()[2]) { | |
939 | case '0': RegNo = X86::DR0; break; | |
940 | case '1': RegNo = X86::DR1; break; | |
941 | case '2': RegNo = X86::DR2; break; | |
942 | case '3': RegNo = X86::DR3; break; | |
943 | case '4': RegNo = X86::DR4; break; | |
944 | case '5': RegNo = X86::DR5; break; | |
945 | case '6': RegNo = X86::DR6; break; | |
946 | case '7': RegNo = X86::DR7; break; | |
947 | } | |
948 | ||
949 | if (RegNo != 0) { | |
970d7e83 | 950 | EndLoc = Parser.getTok().getEndLoc(); |
223e47cc LB |
951 | Parser.Lex(); // Eat it. |
952 | return false; | |
953 | } | |
954 | } | |
955 | ||
956 | if (RegNo == 0) { | |
957 | if (isParsingIntelSyntax()) return true; | |
958 | return Error(StartLoc, "invalid register name", | |
970d7e83 | 959 | SMRange(StartLoc, EndLoc)); |
223e47cc LB |
960 | } |
961 | ||
223e47cc LB |
962 | Parser.Lex(); // Eat identifier token. |
963 | return false; | |
964 | } | |
965 | ||
1a4d82fc | 966 | void X86AsmParser::SetFrameRegister(unsigned RegNo) { |
85aaf69f | 967 | Instrumentation->SetInitialFrameRegister(RegNo); |
1a4d82fc JJ |
968 | } |
969 | ||
970 | std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { | |
971 | unsigned basereg = | |
972 | is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI); | |
973 | const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); | |
85aaf69f SL |
974 | return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, |
975 | /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, | |
976 | Loc, Loc, 0); | |
1a4d82fc JJ |
977 | } |
978 | ||
979 | std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) { | |
980 | unsigned basereg = | |
981 | is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI); | |
982 | const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); | |
85aaf69f SL |
983 | return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, |
984 | /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, | |
985 | Loc, Loc, 0); | |
1a4d82fc JJ |
986 | } |
987 | ||
988 | std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() { | |
223e47cc LB |
989 | if (isParsingIntelSyntax()) |
990 | return ParseIntelOperand(); | |
991 | return ParseATTOperand(); | |
992 | } | |
993 | ||
994 | /// getIntelMemOperandSize - Return intel memory operand size. | |
995 | static unsigned getIntelMemOperandSize(StringRef OpStr) { | |
996 | unsigned Size = StringSwitch<unsigned>(OpStr) | |
997 | .Cases("BYTE", "byte", 8) | |
998 | .Cases("WORD", "word", 16) | |
999 | .Cases("DWORD", "dword", 32) | |
1000 | .Cases("QWORD", "qword", 64) | |
1001 | .Cases("XWORD", "xword", 80) | |
1002 | .Cases("XMMWORD", "xmmword", 128) | |
1003 | .Cases("YMMWORD", "ymmword", 256) | |
1a4d82fc JJ |
1004 | .Cases("ZMMWORD", "zmmword", 512) |
1005 | .Cases("OPAQUE", "opaque", -1U) // needs to be non-zero, but doesn't matter | |
223e47cc LB |
1006 | .Default(0); |
1007 | return Size; | |
1008 | } | |
1009 | ||
1a4d82fc JJ |
1010 | std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm( |
1011 | unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, | |
1012 | unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier, | |
1013 | InlineAsmIdentifierInfo &Info) { | |
1014 | // If we found a decl other than a VarDecl, then assume it is a FuncDecl or | |
1015 | // some other label reference. | |
1016 | if (isa<MCSymbolRefExpr>(Disp) && Info.OpDecl && !Info.IsVarDecl) { | |
1017 | // Insert an explicit size if the user didn't have one. | |
1018 | if (!Size) { | |
1019 | Size = getPointerWidth(); | |
1020 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_SizeDirective, Start, | |
1021 | /*Len=*/0, Size)); | |
1022 | } | |
970d7e83 | 1023 | |
1a4d82fc JJ |
1024 | // Create an absolute memory reference in order to match against |
1025 | // instructions taking a PC relative operand. | |
85aaf69f SL |
1026 | return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size, |
1027 | Identifier, Info.OpDecl); | |
1a4d82fc JJ |
1028 | } |
1029 | ||
1030 | // We either have a direct symbol reference, or an offset from a symbol. The | |
1031 | // parser always puts the symbol on the LHS, so look there for size | |
1032 | // calculation purposes. | |
1033 | const MCBinaryExpr *BinOp = dyn_cast<MCBinaryExpr>(Disp); | |
1034 | bool IsSymRef = | |
1035 | isa<MCSymbolRefExpr>(BinOp ? BinOp->getLHS() : Disp); | |
1036 | if (IsSymRef) { | |
1037 | if (!Size) { | |
1038 | Size = Info.Type * 8; // Size is in terms of bits in this context. | |
1039 | if (Size) | |
1040 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_SizeDirective, Start, | |
1041 | /*Len=*/0, Size)); | |
970d7e83 | 1042 | } |
970d7e83 | 1043 | } |
1a4d82fc JJ |
1044 | |
1045 | // When parsing inline assembly we set the base register to a non-zero value | |
1046 | // if we don't know the actual value at this time. This is necessary to | |
1047 | // get the matching correct in some cases. | |
1048 | BaseReg = BaseReg ? BaseReg : 1; | |
85aaf69f SL |
1049 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, |
1050 | IndexReg, Scale, Start, End, Size, Identifier, | |
1051 | Info.OpDecl); | |
1a4d82fc JJ |
1052 | } |
1053 | ||
1054 | static void | |
1055 | RewriteIntelBracExpression(SmallVectorImpl<AsmRewrite> *AsmRewrites, | |
1056 | StringRef SymName, int64_t ImmDisp, | |
1057 | int64_t FinalImmDisp, SMLoc &BracLoc, | |
1058 | SMLoc &StartInBrac, SMLoc &End) { | |
1059 | // Remove the '[' and ']' from the IR string. | |
1060 | AsmRewrites->push_back(AsmRewrite(AOK_Skip, BracLoc, 1)); | |
1061 | AsmRewrites->push_back(AsmRewrite(AOK_Skip, End, 1)); | |
1062 | ||
1063 | // If ImmDisp is non-zero, then we parsed a displacement before the | |
1064 | // bracketed expression (i.e., ImmDisp [ BaseReg + Scale*IndexReg + Disp]) | |
1065 | // If ImmDisp doesn't match the displacement computed by the state machine | |
1066 | // then we have an additional displacement in the bracketed expression. | |
1067 | if (ImmDisp != FinalImmDisp) { | |
1068 | if (ImmDisp) { | |
1069 | // We have an immediate displacement before the bracketed expression. | |
1070 | // Adjust this to match the final immediate displacement. | |
1071 | bool Found = false; | |
1072 | for (SmallVectorImpl<AsmRewrite>::iterator I = AsmRewrites->begin(), | |
1073 | E = AsmRewrites->end(); I != E; ++I) { | |
1074 | if ((*I).Loc.getPointer() > BracLoc.getPointer()) | |
1075 | continue; | |
1076 | if ((*I).Kind == AOK_ImmPrefix || (*I).Kind == AOK_Imm) { | |
1077 | assert (!Found && "ImmDisp already rewritten."); | |
1078 | (*I).Kind = AOK_Imm; | |
1079 | (*I).Len = BracLoc.getPointer() - (*I).Loc.getPointer(); | |
1080 | (*I).Val = FinalImmDisp; | |
1081 | Found = true; | |
1082 | break; | |
1083 | } | |
970d7e83 | 1084 | } |
1a4d82fc JJ |
1085 | assert (Found && "Unable to rewrite ImmDisp."); |
1086 | (void)Found; | |
1087 | } else { | |
1088 | // We have a symbolic and an immediate displacement, but no displacement | |
1089 | // before the bracketed expression. Put the immediate displacement | |
1090 | // before the bracketed expression. | |
1091 | AsmRewrites->push_back(AsmRewrite(AOK_Imm, BracLoc, 0, FinalImmDisp)); | |
970d7e83 LB |
1092 | } |
1093 | } | |
1a4d82fc JJ |
1094 | // Remove all the ImmPrefix rewrites within the brackets. |
1095 | for (SmallVectorImpl<AsmRewrite>::iterator I = AsmRewrites->begin(), | |
1096 | E = AsmRewrites->end(); I != E; ++I) { | |
1097 | if ((*I).Loc.getPointer() < StartInBrac.getPointer()) | |
1098 | continue; | |
1099 | if ((*I).Kind == AOK_ImmPrefix) | |
1100 | (*I).Kind = AOK_Delete; | |
1101 | } | |
1102 | const char *SymLocPtr = SymName.data(); | |
85aaf69f | 1103 | // Skip everything before the symbol. |
1a4d82fc JJ |
1104 | if (unsigned Len = SymLocPtr - StartInBrac.getPointer()) { |
1105 | assert(Len > 0 && "Expected a non-negative length."); | |
1106 | AsmRewrites->push_back(AsmRewrite(AOK_Skip, StartInBrac, Len)); | |
1107 | } | |
1108 | // Skip everything after the symbol. | |
1109 | if (unsigned Len = End.getPointer() - (SymLocPtr + SymName.size())) { | |
1110 | SMLoc Loc = SMLoc::getFromPointer(SymLocPtr + SymName.size()); | |
1111 | assert(Len > 0 && "Expected a non-negative length."); | |
1112 | AsmRewrites->push_back(AsmRewrite(AOK_Skip, Loc, Len)); | |
970d7e83 | 1113 | } |
1a4d82fc | 1114 | } |
970d7e83 | 1115 | |
1a4d82fc | 1116 | bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { |
85aaf69f | 1117 | MCAsmParser &Parser = getParser(); |
970d7e83 | 1118 | const AsmToken &Tok = Parser.getTok(); |
223e47cc | 1119 | |
970d7e83 | 1120 | bool Done = false; |
970d7e83 LB |
1121 | while (!Done) { |
1122 | bool UpdateLocLex = true; | |
1123 | ||
1124 | // The period in the dot operator (e.g., [ebx].foo.bar) is parsed as an | |
1125 | // identifier. Don't try an parse it as a register. | |
1126 | if (Tok.getString().startswith(".")) | |
1127 | break; | |
85aaf69f | 1128 | |
1a4d82fc JJ |
1129 | // If we're parsing an immediate expression, we don't expect a '['. |
1130 | if (SM.getStopOnLBrac() && getLexer().getKind() == AsmToken::LBrac) | |
1131 | break; | |
970d7e83 | 1132 | |
1a4d82fc JJ |
1133 | AsmToken::TokenKind TK = getLexer().getKind(); |
1134 | switch (TK) { | |
970d7e83 LB |
1135 | default: { |
1136 | if (SM.isValidEndState()) { | |
1137 | Done = true; | |
1138 | break; | |
1139 | } | |
1a4d82fc JJ |
1140 | return Error(Tok.getLoc(), "unknown token in expression"); |
1141 | } | |
1142 | case AsmToken::EndOfStatement: { | |
1143 | Done = true; | |
1144 | break; | |
970d7e83 | 1145 | } |
1a4d82fc | 1146 | case AsmToken::String: |
970d7e83 | 1147 | case AsmToken::Identifier: { |
1a4d82fc JJ |
1148 | // This could be a register or a symbolic displacement. |
1149 | unsigned TmpReg; | |
1150 | const MCExpr *Val; | |
1151 | SMLoc IdentLoc = Tok.getLoc(); | |
1152 | StringRef Identifier = Tok.getString(); | |
1153 | if (TK != AsmToken::String && !ParseRegister(TmpReg, IdentLoc, End)) { | |
970d7e83 LB |
1154 | SM.onRegister(TmpReg); |
1155 | UpdateLocLex = false; | |
1156 | break; | |
1a4d82fc JJ |
1157 | } else { |
1158 | if (!isParsingInlineAsm()) { | |
1159 | if (getParser().parsePrimaryExpr(Val, End)) | |
1160 | return Error(Tok.getLoc(), "Unexpected identifier!"); | |
1161 | } else { | |
1162 | // This is a dot operator, not an adjacent identifier. | |
1163 | if (Identifier.find('.') != StringRef::npos) { | |
1164 | return false; | |
1165 | } else { | |
1166 | InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo(); | |
1167 | if (ParseIntelIdentifier(Val, Identifier, Info, | |
1168 | /*Unevaluated=*/false, End)) | |
1169 | return true; | |
1170 | } | |
1171 | } | |
1172 | SM.onIdentifierExpr(Val, Identifier); | |
970d7e83 LB |
1173 | UpdateLocLex = false; |
1174 | break; | |
1175 | } | |
1a4d82fc | 1176 | return Error(Tok.getLoc(), "Unexpected identifier!"); |
970d7e83 LB |
1177 | } |
1178 | case AsmToken::Integer: { | |
1a4d82fc JJ |
1179 | StringRef ErrMsg; |
1180 | if (isParsingInlineAsm() && SM.getAddImmPrefix()) | |
1181 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, | |
1182 | Tok.getLoc())); | |
1183 | // Look for 'b' or 'f' following an Integer as a directional label | |
1184 | SMLoc Loc = getTok().getLoc(); | |
1185 | int64_t IntVal = getTok().getIntVal(); | |
1186 | End = consumeToken(); | |
1187 | UpdateLocLex = false; | |
1188 | if (getLexer().getKind() == AsmToken::Identifier) { | |
1189 | StringRef IDVal = getTok().getString(); | |
1190 | if (IDVal == "f" || IDVal == "b") { | |
1191 | MCSymbol *Sym = | |
1192 | getContext().GetDirectionalLocalSymbol(IntVal, IDVal == "b"); | |
1193 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; | |
85aaf69f | 1194 | const MCExpr *Val = |
1a4d82fc JJ |
1195 | MCSymbolRefExpr::Create(Sym, Variant, getContext()); |
1196 | if (IDVal == "b" && Sym->isUndefined()) | |
1197 | return Error(Loc, "invalid reference to undefined symbol"); | |
1198 | StringRef Identifier = Sym->getName(); | |
1199 | SM.onIdentifierExpr(Val, Identifier); | |
1200 | End = consumeToken(); | |
1201 | } else { | |
1202 | if (SM.onInteger(IntVal, ErrMsg)) | |
1203 | return Error(Loc, ErrMsg); | |
1204 | } | |
1205 | } else { | |
1206 | if (SM.onInteger(IntVal, ErrMsg)) | |
1207 | return Error(Loc, ErrMsg); | |
1208 | } | |
970d7e83 LB |
1209 | break; |
1210 | } | |
1211 | case AsmToken::Plus: SM.onPlus(); break; | |
1212 | case AsmToken::Minus: SM.onMinus(); break; | |
1a4d82fc | 1213 | case AsmToken::Tilde: SM.onNot(); break; |
970d7e83 | 1214 | case AsmToken::Star: SM.onStar(); break; |
1a4d82fc JJ |
1215 | case AsmToken::Slash: SM.onDivide(); break; |
1216 | case AsmToken::Pipe: SM.onOr(); break; | |
1217 | case AsmToken::Amp: SM.onAnd(); break; | |
1218 | case AsmToken::LessLess: | |
1219 | SM.onLShift(); break; | |
1220 | case AsmToken::GreaterGreater: | |
1221 | SM.onRShift(); break; | |
970d7e83 LB |
1222 | case AsmToken::LBrac: SM.onLBrac(); break; |
1223 | case AsmToken::RBrac: SM.onRBrac(); break; | |
1a4d82fc JJ |
1224 | case AsmToken::LParen: SM.onLParen(); break; |
1225 | case AsmToken::RParen: SM.onRParen(); break; | |
970d7e83 | 1226 | } |
1a4d82fc JJ |
1227 | if (SM.hadError()) |
1228 | return Error(Tok.getLoc(), "unknown token in expression"); | |
1229 | ||
1230 | if (!Done && UpdateLocLex) | |
1231 | End = consumeToken(); | |
223e47cc | 1232 | } |
1a4d82fc JJ |
1233 | return false; |
1234 | } | |
223e47cc | 1235 | |
1a4d82fc JJ |
1236 | std::unique_ptr<X86Operand> |
1237 | X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, | |
1238 | int64_t ImmDisp, unsigned Size) { | |
85aaf69f | 1239 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1240 | const AsmToken &Tok = Parser.getTok(); |
1241 | SMLoc BracLoc = Tok.getLoc(), End = Tok.getEndLoc(); | |
1242 | if (getLexer().isNot(AsmToken::LBrac)) | |
1243 | return ErrorOperand(BracLoc, "Expected '[' token!"); | |
1244 | Parser.Lex(); // Eat '[' | |
1245 | ||
1246 | SMLoc StartInBrac = Tok.getLoc(); | |
1247 | // Parse [ Symbol + ImmDisp ] and [ BaseReg + Scale*IndexReg + ImmDisp ]. We | |
1248 | // may have already parsed an immediate displacement before the bracketed | |
1249 | // expression. | |
1250 | IntelExprStateMachine SM(ImmDisp, /*StopOnLBrac=*/false, /*AddImmPrefix=*/true); | |
1251 | if (ParseIntelExpression(SM, End)) | |
1252 | return nullptr; | |
1253 | ||
1254 | const MCExpr *Disp = nullptr; | |
1255 | if (const MCExpr *Sym = SM.getSym()) { | |
1256 | // A symbolic displacement. | |
1257 | Disp = Sym; | |
1258 | if (isParsingInlineAsm()) | |
1259 | RewriteIntelBracExpression(InstInfo->AsmRewrites, SM.getSymName(), | |
1260 | ImmDisp, SM.getImm(), BracLoc, StartInBrac, | |
1261 | End); | |
1262 | } | |
1263 | ||
1264 | if (SM.getImm() || !Disp) { | |
1265 | const MCExpr *Imm = MCConstantExpr::Create(SM.getImm(), getContext()); | |
1266 | if (Disp) | |
1267 | Disp = MCBinaryExpr::CreateAdd(Disp, Imm, getContext()); | |
1268 | else | |
1269 | Disp = Imm; // An immediate displacement only. | |
1270 | } | |
223e47cc | 1271 | |
1a4d82fc JJ |
1272 | // Parse struct field access. Intel requires a dot, but MSVC doesn't. MSVC |
1273 | // will in fact do global lookup the field name inside all global typedefs, | |
1274 | // but we don't emulate that. | |
1275 | if (Tok.getString().find('.') != StringRef::npos) { | |
970d7e83 | 1276 | const MCExpr *NewDisp; |
1a4d82fc JJ |
1277 | if (ParseIntelDotOperator(Disp, NewDisp)) |
1278 | return nullptr; | |
85aaf69f | 1279 | |
1a4d82fc | 1280 | End = Tok.getEndLoc(); |
970d7e83 LB |
1281 | Parser.Lex(); // Eat the field. |
1282 | Disp = NewDisp; | |
1283 | } | |
1284 | ||
1285 | int BaseReg = SM.getBaseReg(); | |
1286 | int IndexReg = SM.getIndexReg(); | |
1a4d82fc JJ |
1287 | int Scale = SM.getScale(); |
1288 | if (!isParsingInlineAsm()) { | |
1289 | // handle [-42] | |
1290 | if (!BaseReg && !IndexReg) { | |
1291 | if (!SegReg) | |
85aaf69f SL |
1292 | return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size); |
1293 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, | |
1294 | Start, End, Size); | |
1a4d82fc JJ |
1295 | } |
1296 | StringRef ErrMsg; | |
1297 | if (CheckBaseRegAndIndexReg(BaseReg, IndexReg, ErrMsg)) { | |
1298 | Error(StartInBrac, ErrMsg); | |
1299 | return nullptr; | |
1300 | } | |
85aaf69f SL |
1301 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, |
1302 | IndexReg, Scale, Start, End, Size); | |
970d7e83 | 1303 | } |
223e47cc | 1304 | |
1a4d82fc JJ |
1305 | InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo(); |
1306 | return CreateMemForInlineAsm(SegReg, Disp, BaseReg, IndexReg, Scale, Start, | |
1307 | End, Size, SM.getSymName(), Info); | |
223e47cc LB |
1308 | } |
1309 | ||
1a4d82fc JJ |
1310 | // Inline assembly may use variable names with namespace alias qualifiers. |
1311 | bool X86AsmParser::ParseIntelIdentifier(const MCExpr *&Val, | |
1312 | StringRef &Identifier, | |
1313 | InlineAsmIdentifierInfo &Info, | |
1314 | bool IsUnevaluatedOperand, SMLoc &End) { | |
85aaf69f | 1315 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1316 | assert (isParsingInlineAsm() && "Expected to be parsing inline assembly."); |
1317 | Val = nullptr; | |
1318 | ||
1319 | StringRef LineBuf(Identifier.data()); | |
1320 | void *Result = | |
1321 | SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand); | |
1322 | ||
223e47cc | 1323 | const AsmToken &Tok = Parser.getTok(); |
1a4d82fc JJ |
1324 | SMLoc Loc = Tok.getLoc(); |
1325 | ||
1326 | // Advance the token stream until the end of the current token is | |
1327 | // after the end of what the frontend claimed. | |
1328 | const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size(); | |
1329 | while (true) { | |
1330 | End = Tok.getEndLoc(); | |
1331 | getLexer().Lex(); | |
1332 | ||
1333 | assert(End.getPointer() <= EndPtr && "frontend claimed part of a token?"); | |
1334 | if (End.getPointer() == EndPtr) break; | |
1335 | } | |
1336 | Identifier = LineBuf; | |
1337 | ||
1338 | // If the identifier lookup was unsuccessful, assume that we are dealing with | |
1339 | // a label. | |
1340 | if (!Result) { | |
1341 | StringRef InternalName = | |
1342 | SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(), | |
1343 | Loc, false); | |
1344 | assert(InternalName.size() && "We should have an internal name here."); | |
1345 | // Push a rewrite for replacing the identifier name with the internal name. | |
1346 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Label, Loc, | |
1347 | Identifier.size(), | |
1348 | InternalName)); | |
1349 | } | |
1350 | ||
1351 | // Create the symbol reference. | |
1352 | MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); | |
1353 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; | |
1354 | Val = MCSymbolRefExpr::Create(Sym, Variant, getParser().getContext()); | |
1355 | return false; | |
1356 | } | |
1357 | ||
1358 | /// \brief Parse intel style segment override. | |
1359 | std::unique_ptr<X86Operand> | |
1360 | X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, | |
1361 | unsigned Size) { | |
85aaf69f | 1362 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1363 | assert(SegReg != 0 && "Tried to parse a segment override without a segment!"); |
1364 | const AsmToken &Tok = Parser.getTok(); // Eat colon. | |
1365 | if (Tok.isNot(AsmToken::Colon)) | |
1366 | return ErrorOperand(Tok.getLoc(), "Expected ':' token!"); | |
1367 | Parser.Lex(); // Eat ':' | |
1368 | ||
1369 | int64_t ImmDisp = 0; | |
1370 | if (getLexer().is(AsmToken::Integer)) { | |
1371 | ImmDisp = Tok.getIntVal(); | |
1372 | AsmToken ImmDispToken = Parser.Lex(); // Eat the integer. | |
1373 | ||
1374 | if (isParsingInlineAsm()) | |
1375 | InstInfo->AsmRewrites->push_back( | |
1376 | AsmRewrite(AOK_ImmPrefix, ImmDispToken.getLoc())); | |
1377 | ||
1378 | if (getLexer().isNot(AsmToken::LBrac)) { | |
1379 | // An immediate following a 'segment register', 'colon' token sequence can | |
1380 | // be followed by a bracketed expression. If it isn't we know we have our | |
1381 | // final segment override. | |
1382 | const MCExpr *Disp = MCConstantExpr::Create(ImmDisp, getContext()); | |
85aaf69f SL |
1383 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, |
1384 | /*BaseReg=*/0, /*IndexReg=*/0, /*Scale=*/1, | |
1385 | Start, ImmDispToken.getEndLoc(), Size); | |
1a4d82fc JJ |
1386 | } |
1387 | } | |
1388 | ||
1389 | if (getLexer().is(AsmToken::LBrac)) | |
1390 | return ParseIntelBracExpression(SegReg, Start, ImmDisp, Size); | |
1391 | ||
1392 | const MCExpr *Val; | |
970d7e83 | 1393 | SMLoc End; |
1a4d82fc JJ |
1394 | if (!isParsingInlineAsm()) { |
1395 | if (getParser().parsePrimaryExpr(Val, End)) | |
1396 | return ErrorOperand(Tok.getLoc(), "unknown token in expression"); | |
223e47cc | 1397 | |
85aaf69f | 1398 | return X86Operand::CreateMem(getPointerWidth(), Val, Start, End, Size); |
223e47cc LB |
1399 | } |
1400 | ||
1a4d82fc JJ |
1401 | InlineAsmIdentifierInfo Info; |
1402 | StringRef Identifier = Tok.getString(); | |
1403 | if (ParseIntelIdentifier(Val, Identifier, Info, | |
1404 | /*Unevaluated=*/false, End)) | |
1405 | return nullptr; | |
1406 | return CreateMemForInlineAsm(/*SegReg=*/0, Val, /*BaseReg=*/0,/*IndexReg=*/0, | |
1407 | /*Scale=*/1, Start, End, Size, Identifier, Info); | |
1408 | } | |
1409 | ||
1410 | /// ParseIntelMemOperand - Parse intel style memory operand. | |
1411 | std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, | |
1412 | SMLoc Start, | |
1413 | unsigned Size) { | |
85aaf69f | 1414 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1415 | const AsmToken &Tok = Parser.getTok(); |
1416 | SMLoc End; | |
1417 | ||
1418 | // Parse ImmDisp [ BaseReg + Scale*IndexReg + Disp ]. | |
223e47cc | 1419 | if (getLexer().is(AsmToken::LBrac)) |
1a4d82fc JJ |
1420 | return ParseIntelBracExpression(/*SegReg=*/0, Start, ImmDisp, Size); |
1421 | assert(ImmDisp == 0); | |
223e47cc | 1422 | |
1a4d82fc JJ |
1423 | const MCExpr *Val; |
1424 | if (!isParsingInlineAsm()) { | |
1425 | if (getParser().parsePrimaryExpr(Val, End)) | |
1426 | return ErrorOperand(Tok.getLoc(), "unknown token in expression"); | |
1427 | ||
85aaf69f | 1428 | return X86Operand::CreateMem(getPointerWidth(), Val, Start, End, Size); |
223e47cc LB |
1429 | } |
1430 | ||
1a4d82fc JJ |
1431 | InlineAsmIdentifierInfo Info; |
1432 | StringRef Identifier = Tok.getString(); | |
1433 | if (ParseIntelIdentifier(Val, Identifier, Info, | |
1434 | /*Unevaluated=*/false, End)) | |
1435 | return nullptr; | |
970d7e83 | 1436 | |
1a4d82fc JJ |
1437 | if (!getLexer().is(AsmToken::LBrac)) |
1438 | return CreateMemForInlineAsm(/*SegReg=*/0, Val, /*BaseReg=*/0, /*IndexReg=*/0, | |
1439 | /*Scale=*/1, Start, End, Size, Identifier, Info); | |
1440 | ||
1441 | Parser.Lex(); // Eat '[' | |
1442 | ||
1443 | // Parse Identifier [ ImmDisp ] | |
1444 | IntelExprStateMachine SM(/*ImmDisp=*/0, /*StopOnLBrac=*/true, | |
1445 | /*AddImmPrefix=*/false); | |
1446 | if (ParseIntelExpression(SM, End)) | |
1447 | return nullptr; | |
1448 | ||
1449 | if (SM.getSym()) { | |
1450 | Error(Start, "cannot use more than one symbol in memory operand"); | |
1451 | return nullptr; | |
1452 | } | |
1453 | if (SM.getBaseReg()) { | |
1454 | Error(Start, "cannot use base register with variable reference"); | |
1455 | return nullptr; | |
970d7e83 | 1456 | } |
1a4d82fc JJ |
1457 | if (SM.getIndexReg()) { |
1458 | Error(Start, "cannot use index register with variable reference"); | |
1459 | return nullptr; | |
1460 | } | |
1461 | ||
1462 | const MCExpr *Disp = MCConstantExpr::Create(SM.getImm(), getContext()); | |
1463 | // BaseReg is non-zero to avoid assertions. In the context of inline asm, | |
1464 | // we're pointing to a local variable in memory, so the base register is | |
1465 | // really the frame or stack pointer. | |
85aaf69f SL |
1466 | return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, |
1467 | /*BaseReg=*/1, /*IndexReg=*/0, /*Scale=*/1, | |
1468 | Start, End, Size, Identifier, Info.OpDecl); | |
970d7e83 LB |
1469 | } |
1470 | ||
1471 | /// Parse the '.' operator. | |
1472 | bool X86AsmParser::ParseIntelDotOperator(const MCExpr *Disp, | |
1a4d82fc | 1473 | const MCExpr *&NewDisp) { |
85aaf69f | 1474 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1475 | const AsmToken &Tok = Parser.getTok(); |
1476 | int64_t OrigDispVal, DotDispVal; | |
970d7e83 LB |
1477 | |
1478 | // FIXME: Handle non-constant expressions. | |
1a4d82fc | 1479 | if (const MCConstantExpr *OrigDisp = dyn_cast<MCConstantExpr>(Disp)) |
970d7e83 | 1480 | OrigDispVal = OrigDisp->getValue(); |
1a4d82fc JJ |
1481 | else |
1482 | return Error(Tok.getLoc(), "Non-constant offsets are not supported!"); | |
970d7e83 | 1483 | |
1a4d82fc JJ |
1484 | // Drop the optional '.'. |
1485 | StringRef DotDispStr = Tok.getString(); | |
1486 | if (DotDispStr.startswith(".")) | |
1487 | DotDispStr = DotDispStr.drop_front(1); | |
970d7e83 LB |
1488 | |
1489 | // .Imm gets lexed as a real. | |
1490 | if (Tok.is(AsmToken::Real)) { | |
1491 | APInt DotDisp; | |
1492 | DotDispStr.getAsInteger(10, DotDisp); | |
1493 | DotDispVal = DotDisp.getZExtValue(); | |
1a4d82fc | 1494 | } else if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) { |
970d7e83 LB |
1495 | unsigned DotDisp; |
1496 | std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.'); | |
1497 | if (SemaCallback->LookupInlineAsmField(BaseMember.first, BaseMember.second, | |
1a4d82fc JJ |
1498 | DotDisp)) |
1499 | return Error(Tok.getLoc(), "Unable to lookup field reference!"); | |
970d7e83 | 1500 | DotDispVal = DotDisp; |
1a4d82fc JJ |
1501 | } else |
1502 | return Error(Tok.getLoc(), "Unexpected token type!"); | |
970d7e83 LB |
1503 | |
1504 | if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) { | |
1505 | SMLoc Loc = SMLoc::getFromPointer(DotDispStr.data()); | |
1506 | unsigned Len = DotDispStr.size(); | |
1507 | unsigned Val = OrigDispVal + DotDispVal; | |
1508 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_DotOperator, Loc, Len, | |
1509 | Val)); | |
1510 | } | |
1511 | ||
1a4d82fc | 1512 | NewDisp = MCConstantExpr::Create(OrigDispVal + DotDispVal, getContext()); |
970d7e83 LB |
1513 | return false; |
1514 | } | |
1515 | ||
1516 | /// Parse the 'offset' operator. This operator is used to specify the | |
1517 | /// location rather then the content of a variable. | |
1a4d82fc | 1518 | std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() { |
85aaf69f | 1519 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1520 | const AsmToken &Tok = Parser.getTok(); |
1521 | SMLoc OffsetOfLoc = Tok.getLoc(); | |
970d7e83 | 1522 | Parser.Lex(); // Eat offset. |
970d7e83 | 1523 | |
970d7e83 | 1524 | const MCExpr *Val; |
1a4d82fc JJ |
1525 | InlineAsmIdentifierInfo Info; |
1526 | SMLoc Start = Tok.getLoc(), End; | |
1527 | StringRef Identifier = Tok.getString(); | |
1528 | if (ParseIntelIdentifier(Val, Identifier, Info, | |
1529 | /*Unevaluated=*/false, End)) | |
1530 | return nullptr; | |
970d7e83 LB |
1531 | |
1532 | // Don't emit the offset operator. | |
1533 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, OffsetOfLoc, 7)); | |
1534 | ||
1535 | // The offset operator will have an 'r' constraint, thus we need to create | |
1536 | // register operand to ensure proper matching. Just pick a GPR based on | |
1537 | // the size of a pointer. | |
1a4d82fc JJ |
1538 | unsigned RegNo = |
1539 | is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX); | |
970d7e83 | 1540 | return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true, |
1a4d82fc | 1541 | OffsetOfLoc, Identifier, Info.OpDecl); |
970d7e83 LB |
1542 | } |
1543 | ||
1544 | enum IntelOperatorKind { | |
1545 | IOK_LENGTH, | |
1546 | IOK_SIZE, | |
1547 | IOK_TYPE | |
1548 | }; | |
1549 | ||
1550 | /// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator | |
1551 | /// returns the number of elements in an array. It returns the value 1 for | |
1552 | /// non-array variables. The SIZE operator returns the size of a C or C++ | |
1553 | /// variable. A variable's size is the product of its LENGTH and TYPE. The | |
1554 | /// TYPE operator returns the size of a C or C++ type or variable. If the | |
1555 | /// variable is an array, TYPE returns the size of a single element. | |
1a4d82fc | 1556 | std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) { |
85aaf69f | 1557 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1558 | const AsmToken &Tok = Parser.getTok(); |
1559 | SMLoc TypeLoc = Tok.getLoc(); | |
1560 | Parser.Lex(); // Eat operator. | |
970d7e83 | 1561 | |
1a4d82fc JJ |
1562 | const MCExpr *Val = nullptr; |
1563 | InlineAsmIdentifierInfo Info; | |
1564 | SMLoc Start = Tok.getLoc(), End; | |
1565 | StringRef Identifier = Tok.getString(); | |
1566 | if (ParseIntelIdentifier(Val, Identifier, Info, | |
1567 | /*Unevaluated=*/true, End)) | |
1568 | return nullptr; | |
1569 | ||
1570 | if (!Info.OpDecl) | |
1571 | return ErrorOperand(Start, "unable to lookup expression"); | |
1572 | ||
1573 | unsigned CVal = 0; | |
970d7e83 LB |
1574 | switch(OpKind) { |
1575 | default: llvm_unreachable("Unexpected operand kind!"); | |
1a4d82fc JJ |
1576 | case IOK_LENGTH: CVal = Info.Length; break; |
1577 | case IOK_SIZE: CVal = Info.Size; break; | |
1578 | case IOK_TYPE: CVal = Info.Type; break; | |
970d7e83 LB |
1579 | } |
1580 | ||
1581 | // Rewrite the type operator and the C or C++ type or variable in terms of an | |
1582 | // immediate. E.g. TYPE foo -> $$4 | |
1583 | unsigned Len = End.getPointer() - TypeLoc.getPointer(); | |
1584 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, CVal)); | |
1585 | ||
1586 | const MCExpr *Imm = MCConstantExpr::Create(CVal, getContext()); | |
1a4d82fc | 1587 | return X86Operand::CreateImm(Imm, Start, End); |
223e47cc LB |
1588 | } |
1589 | ||
1a4d82fc | 1590 | std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() { |
85aaf69f | 1591 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1592 | const AsmToken &Tok = Parser.getTok(); |
1593 | SMLoc Start, End; | |
970d7e83 LB |
1594 | |
1595 | // Offset, length, type and size operators. | |
1596 | if (isParsingInlineAsm()) { | |
1a4d82fc | 1597 | StringRef AsmTokStr = Tok.getString(); |
970d7e83 | 1598 | if (AsmTokStr == "offset" || AsmTokStr == "OFFSET") |
1a4d82fc | 1599 | return ParseIntelOffsetOfOperator(); |
970d7e83 | 1600 | if (AsmTokStr == "length" || AsmTokStr == "LENGTH") |
1a4d82fc | 1601 | return ParseIntelOperator(IOK_LENGTH); |
970d7e83 | 1602 | if (AsmTokStr == "size" || AsmTokStr == "SIZE") |
1a4d82fc | 1603 | return ParseIntelOperator(IOK_SIZE); |
970d7e83 | 1604 | if (AsmTokStr == "type" || AsmTokStr == "TYPE") |
1a4d82fc JJ |
1605 | return ParseIntelOperator(IOK_TYPE); |
1606 | } | |
1607 | ||
1608 | unsigned Size = getIntelMemOperandSize(Tok.getString()); | |
1609 | if (Size) { | |
1610 | Parser.Lex(); // Eat operand size (e.g., byte, word). | |
1611 | if (Tok.getString() != "PTR" && Tok.getString() != "ptr") | |
1612 | return ErrorOperand(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!"); | |
1613 | Parser.Lex(); // Eat ptr. | |
970d7e83 | 1614 | } |
1a4d82fc | 1615 | Start = Tok.getLoc(); |
223e47cc | 1616 | |
970d7e83 | 1617 | // Immediate. |
1a4d82fc JJ |
1618 | if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Minus) || |
1619 | getLexer().is(AsmToken::Tilde) || getLexer().is(AsmToken::LParen)) { | |
1620 | AsmToken StartTok = Tok; | |
1621 | IntelExprStateMachine SM(/*Imm=*/0, /*StopOnLBrac=*/true, | |
1622 | /*AddImmPrefix=*/false); | |
1623 | if (ParseIntelExpression(SM, End)) | |
1624 | return nullptr; | |
1625 | ||
1626 | int64_t Imm = SM.getImm(); | |
1627 | if (isParsingInlineAsm()) { | |
1628 | unsigned Len = Tok.getLoc().getPointer() - Start.getPointer(); | |
1629 | if (StartTok.getString().size() == Len) | |
1630 | // Just add a prefix if this wasn't a complex immediate expression. | |
1631 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, Start)); | |
1632 | else | |
1633 | // Otherwise, rewrite the complex expression as a single immediate. | |
1634 | InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, Start, Len, Imm)); | |
1635 | } | |
1636 | ||
1637 | if (getLexer().isNot(AsmToken::LBrac)) { | |
1638 | // If a directional label (ie. 1f or 2b) was parsed above from | |
1639 | // ParseIntelExpression() then SM.getSym() was set to a pointer to | |
1640 | // to the MCExpr with the directional local symbol and this is a | |
1641 | // memory operand not an immediate operand. | |
1642 | if (SM.getSym()) | |
85aaf69f SL |
1643 | return X86Operand::CreateMem(getPointerWidth(), SM.getSym(), Start, End, |
1644 | Size); | |
1a4d82fc JJ |
1645 | |
1646 | const MCExpr *ImmExpr = MCConstantExpr::Create(Imm, getContext()); | |
1647 | return X86Operand::CreateImm(ImmExpr, Start, End); | |
223e47cc | 1648 | } |
1a4d82fc JJ |
1649 | |
1650 | // Only positive immediates are valid. | |
1651 | if (Imm < 0) | |
1652 | return ErrorOperand(Start, "expected a positive immediate displacement " | |
1653 | "before bracketed expr."); | |
1654 | ||
1655 | // Parse ImmDisp [ BaseReg + Scale*IndexReg + Disp ]. | |
1656 | return ParseIntelMemOperand(Imm, Start, Size); | |
223e47cc LB |
1657 | } |
1658 | ||
970d7e83 | 1659 | // Register. |
223e47cc LB |
1660 | unsigned RegNo = 0; |
1661 | if (!ParseRegister(RegNo, Start, End)) { | |
970d7e83 | 1662 | // If this is a segment register followed by a ':', then this is the start |
1a4d82fc | 1663 | // of a segment override, otherwise this is a normal register reference. |
970d7e83 LB |
1664 | if (getLexer().isNot(AsmToken::Colon)) |
1665 | return X86Operand::CreateReg(RegNo, Start, End); | |
1666 | ||
1a4d82fc | 1667 | return ParseIntelSegmentOverride(/*SegReg=*/RegNo, Start, Size); |
223e47cc LB |
1668 | } |
1669 | ||
970d7e83 | 1670 | // Memory operand. |
1a4d82fc | 1671 | return ParseIntelMemOperand(/*Disp=*/0, Start, Size); |
223e47cc LB |
1672 | } |
1673 | ||
1a4d82fc | 1674 | std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() { |
85aaf69f | 1675 | MCAsmParser &Parser = getParser(); |
223e47cc LB |
1676 | switch (getLexer().getKind()) { |
1677 | default: | |
1678 | // Parse a memory operand with no segment register. | |
1679 | return ParseMemOperand(0, Parser.getTok().getLoc()); | |
1680 | case AsmToken::Percent: { | |
1681 | // Read the register. | |
1682 | unsigned RegNo; | |
1683 | SMLoc Start, End; | |
1a4d82fc | 1684 | if (ParseRegister(RegNo, Start, End)) return nullptr; |
223e47cc LB |
1685 | if (RegNo == X86::EIZ || RegNo == X86::RIZ) { |
1686 | Error(Start, "%eiz and %riz can only be used as index registers", | |
1687 | SMRange(Start, End)); | |
1a4d82fc | 1688 | return nullptr; |
223e47cc LB |
1689 | } |
1690 | ||
1691 | // If this is a segment register followed by a ':', then this is the start | |
1692 | // of a memory reference, otherwise this is a normal register reference. | |
1693 | if (getLexer().isNot(AsmToken::Colon)) | |
1694 | return X86Operand::CreateReg(RegNo, Start, End); | |
1695 | ||
1a4d82fc JJ |
1696 | if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo)) |
1697 | return ErrorOperand(Start, "invalid segment register"); | |
223e47cc LB |
1698 | |
1699 | getParser().Lex(); // Eat the colon. | |
1700 | return ParseMemOperand(RegNo, Start); | |
1701 | } | |
1702 | case AsmToken::Dollar: { | |
1703 | // $42 -> immediate. | |
1704 | SMLoc Start = Parser.getTok().getLoc(), End; | |
1705 | Parser.Lex(); | |
1706 | const MCExpr *Val; | |
970d7e83 | 1707 | if (getParser().parseExpression(Val, End)) |
1a4d82fc | 1708 | return nullptr; |
223e47cc LB |
1709 | return X86Operand::CreateImm(Val, Start, End); |
1710 | } | |
1711 | } | |
1712 | } | |
1713 | ||
1a4d82fc JJ |
1714 | bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands, |
1715 | const MCParsedAsmOperand &Op) { | |
85aaf69f | 1716 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
1717 | if(STI.getFeatureBits() & X86::FeatureAVX512) { |
1718 | if (getLexer().is(AsmToken::LCurly)) { | |
1719 | // Eat "{" and mark the current place. | |
1720 | const SMLoc consumedToken = consumeToken(); | |
1721 | // Distinguish {1to<NUM>} from {%k<NUM>}. | |
1722 | if(getLexer().is(AsmToken::Integer)) { | |
1723 | // Parse memory broadcasting ({1to<NUM>}). | |
1724 | if (getLexer().getTok().getIntVal() != 1) | |
1725 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1726 | "Expected 1to<NUM> at this point"); | |
1727 | Parser.Lex(); // Eat "1" of 1to8 | |
1728 | if (!getLexer().is(AsmToken::Identifier) || | |
1729 | !getLexer().getTok().getIdentifier().startswith("to")) | |
1730 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1731 | "Expected 1to<NUM> at this point"); | |
1732 | // Recognize only reasonable suffixes. | |
1733 | const char *BroadcastPrimitive = | |
1734 | StringSwitch<const char*>(getLexer().getTok().getIdentifier()) | |
1735 | .Case("to2", "{1to2}") | |
1736 | .Case("to4", "{1to4}") | |
1737 | .Case("to8", "{1to8}") | |
1738 | .Case("to16", "{1to16}") | |
1739 | .Default(nullptr); | |
1740 | if (!BroadcastPrimitive) | |
1741 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1742 | "Invalid memory broadcast primitive."); | |
1743 | Parser.Lex(); // Eat "toN" of 1toN | |
1744 | if (!getLexer().is(AsmToken::RCurly)) | |
1745 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1746 | "Expected } at this point"); | |
1747 | Parser.Lex(); // Eat "}" | |
1748 | Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive, | |
1749 | consumedToken)); | |
1750 | // No AVX512 specific primitives can pass | |
1751 | // after memory broadcasting, so return. | |
1752 | return true; | |
1753 | } else { | |
1754 | // Parse mask register {%k1} | |
1755 | Operands.push_back(X86Operand::CreateToken("{", consumedToken)); | |
1756 | if (std::unique_ptr<X86Operand> Op = ParseOperand()) { | |
1757 | Operands.push_back(std::move(Op)); | |
1758 | if (!getLexer().is(AsmToken::RCurly)) | |
1759 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1760 | "Expected } at this point"); | |
1761 | Operands.push_back(X86Operand::CreateToken("}", consumeToken())); | |
1762 | ||
1763 | // Parse "zeroing non-masked" semantic {z} | |
1764 | if (getLexer().is(AsmToken::LCurly)) { | |
1765 | Operands.push_back(X86Operand::CreateToken("{z}", consumeToken())); | |
1766 | if (!getLexer().is(AsmToken::Identifier) || | |
1767 | getLexer().getTok().getIdentifier() != "z") | |
1768 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1769 | "Expected z at this point"); | |
1770 | Parser.Lex(); // Eat the z | |
1771 | if (!getLexer().is(AsmToken::RCurly)) | |
1772 | return !ErrorAndEatStatement(getLexer().getLoc(), | |
1773 | "Expected } at this point"); | |
1774 | Parser.Lex(); // Eat the } | |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | } | |
1779 | } | |
1780 | return true; | |
1781 | } | |
1782 | ||
223e47cc LB |
1783 | /// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix |
1784 | /// has already been parsed if present. | |
1a4d82fc JJ |
1785 | std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg, |
1786 | SMLoc MemStart) { | |
223e47cc | 1787 | |
85aaf69f | 1788 | MCAsmParser &Parser = getParser(); |
223e47cc LB |
1789 | // We have to disambiguate a parenthesized expression "(4+5)" from the start |
1790 | // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The | |
1791 | // only way to do this without lookahead is to eat the '(' and see what is | |
1792 | // after it. | |
1793 | const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); | |
1794 | if (getLexer().isNot(AsmToken::LParen)) { | |
1795 | SMLoc ExprEnd; | |
1a4d82fc | 1796 | if (getParser().parseExpression(Disp, ExprEnd)) return nullptr; |
223e47cc LB |
1797 | |
1798 | // After parsing the base expression we could either have a parenthesized | |
1799 | // memory address or not. If not, return now. If so, eat the (. | |
1800 | if (getLexer().isNot(AsmToken::LParen)) { | |
1801 | // Unless we have a segment register, treat this as an immediate. | |
1802 | if (SegReg == 0) | |
85aaf69f SL |
1803 | return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, ExprEnd); |
1804 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, | |
1805 | MemStart, ExprEnd); | |
223e47cc LB |
1806 | } |
1807 | ||
1808 | // Eat the '('. | |
1809 | Parser.Lex(); | |
1810 | } else { | |
1811 | // Okay, we have a '('. We don't know if this is an expression or not, but | |
1812 | // so we have to eat the ( to see beyond it. | |
1813 | SMLoc LParenLoc = Parser.getTok().getLoc(); | |
1814 | Parser.Lex(); // Eat the '('. | |
1815 | ||
1816 | if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) { | |
1817 | // Nothing to do here, fall into the code below with the '(' part of the | |
1818 | // memory operand consumed. | |
1819 | } else { | |
1820 | SMLoc ExprEnd; | |
1821 | ||
1822 | // It must be an parenthesized expression, parse it now. | |
970d7e83 | 1823 | if (getParser().parseParenExpression(Disp, ExprEnd)) |
1a4d82fc | 1824 | return nullptr; |
223e47cc LB |
1825 | |
1826 | // After parsing the base expression we could either have a parenthesized | |
1827 | // memory address or not. If not, return now. If so, eat the (. | |
1828 | if (getLexer().isNot(AsmToken::LParen)) { | |
1829 | // Unless we have a segment register, treat this as an immediate. | |
1830 | if (SegReg == 0) | |
85aaf69f SL |
1831 | return X86Operand::CreateMem(getPointerWidth(), Disp, LParenLoc, |
1832 | ExprEnd); | |
1833 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1, | |
1834 | MemStart, ExprEnd); | |
223e47cc LB |
1835 | } |
1836 | ||
1837 | // Eat the '('. | |
1838 | Parser.Lex(); | |
1839 | } | |
1840 | } | |
1841 | ||
1842 | // If we reached here, then we just ate the ( of the memory operand. Process | |
1843 | // the rest of the memory operand. | |
1844 | unsigned BaseReg = 0, IndexReg = 0, Scale = 1; | |
1a4d82fc | 1845 | SMLoc IndexLoc, BaseLoc; |
223e47cc LB |
1846 | |
1847 | if (getLexer().is(AsmToken::Percent)) { | |
1848 | SMLoc StartLoc, EndLoc; | |
1a4d82fc JJ |
1849 | BaseLoc = Parser.getTok().getLoc(); |
1850 | if (ParseRegister(BaseReg, StartLoc, EndLoc)) return nullptr; | |
223e47cc LB |
1851 | if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) { |
1852 | Error(StartLoc, "eiz and riz can only be used as index registers", | |
1853 | SMRange(StartLoc, EndLoc)); | |
1a4d82fc | 1854 | return nullptr; |
223e47cc LB |
1855 | } |
1856 | } | |
1857 | ||
1858 | if (getLexer().is(AsmToken::Comma)) { | |
1859 | Parser.Lex(); // Eat the comma. | |
1860 | IndexLoc = Parser.getTok().getLoc(); | |
1861 | ||
1862 | // Following the comma we should have either an index register, or a scale | |
1863 | // value. We don't support the later form, but we want to parse it | |
1864 | // correctly. | |
1865 | // | |
1866 | // Not that even though it would be completely consistent to support syntax | |
1867 | // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this. | |
1868 | if (getLexer().is(AsmToken::Percent)) { | |
1869 | SMLoc L; | |
1a4d82fc | 1870 | if (ParseRegister(IndexReg, L, L)) return nullptr; |
223e47cc LB |
1871 | |
1872 | if (getLexer().isNot(AsmToken::RParen)) { | |
1873 | // Parse the scale amount: | |
1874 | // ::= ',' [scale-expression] | |
1875 | if (getLexer().isNot(AsmToken::Comma)) { | |
1876 | Error(Parser.getTok().getLoc(), | |
1877 | "expected comma in scale expression"); | |
1a4d82fc | 1878 | return nullptr; |
223e47cc LB |
1879 | } |
1880 | Parser.Lex(); // Eat the comma. | |
1881 | ||
1882 | if (getLexer().isNot(AsmToken::RParen)) { | |
1883 | SMLoc Loc = Parser.getTok().getLoc(); | |
1884 | ||
1885 | int64_t ScaleVal; | |
970d7e83 | 1886 | if (getParser().parseAbsoluteExpression(ScaleVal)){ |
223e47cc | 1887 | Error(Loc, "expected scale expression"); |
1a4d82fc | 1888 | return nullptr; |
223e47cc LB |
1889 | } |
1890 | ||
1891 | // Validate the scale amount. | |
1a4d82fc JJ |
1892 | if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) && |
1893 | ScaleVal != 1) { | |
1894 | Error(Loc, "scale factor in 16-bit address must be 1"); | |
1895 | return nullptr; | |
1896 | } | |
223e47cc LB |
1897 | if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){ |
1898 | Error(Loc, "scale factor in address must be 1, 2, 4 or 8"); | |
1a4d82fc | 1899 | return nullptr; |
223e47cc LB |
1900 | } |
1901 | Scale = (unsigned)ScaleVal; | |
1902 | } | |
1903 | } | |
1904 | } else if (getLexer().isNot(AsmToken::RParen)) { | |
1905 | // A scale amount without an index is ignored. | |
1906 | // index. | |
1907 | SMLoc Loc = Parser.getTok().getLoc(); | |
1908 | ||
1909 | int64_t Value; | |
970d7e83 | 1910 | if (getParser().parseAbsoluteExpression(Value)) |
1a4d82fc | 1911 | return nullptr; |
223e47cc LB |
1912 | |
1913 | if (Value != 1) | |
1914 | Warning(Loc, "scale factor without index register is ignored"); | |
1915 | Scale = 1; | |
1916 | } | |
1917 | } | |
1918 | ||
1919 | // Ok, we've eaten the memory operand, verify we have a ')' and eat it too. | |
1920 | if (getLexer().isNot(AsmToken::RParen)) { | |
1921 | Error(Parser.getTok().getLoc(), "unexpected token in memory operand"); | |
1a4d82fc | 1922 | return nullptr; |
223e47cc | 1923 | } |
970d7e83 | 1924 | SMLoc MemEnd = Parser.getTok().getEndLoc(); |
223e47cc LB |
1925 | Parser.Lex(); // Eat the ')'. |
1926 | ||
1a4d82fc JJ |
1927 | // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed, |
1928 | // and then only in non-64-bit modes. Except for DX, which is a special case | |
1929 | // because an unofficial form of in/out instructions uses it. | |
1930 | if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) && | |
1931 | (is64BitMode() || (BaseReg != X86::BX && BaseReg != X86::BP && | |
1932 | BaseReg != X86::SI && BaseReg != X86::DI)) && | |
1933 | BaseReg != X86::DX) { | |
1934 | Error(BaseLoc, "invalid 16-bit base register"); | |
1935 | return nullptr; | |
1936 | } | |
1937 | if (BaseReg == 0 && | |
1938 | X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) { | |
1939 | Error(IndexLoc, "16-bit memory operand may not include only index register"); | |
1940 | return nullptr; | |
1941 | } | |
1942 | ||
1943 | StringRef ErrMsg; | |
1944 | if (CheckBaseRegAndIndexReg(BaseReg, IndexReg, ErrMsg)) { | |
1945 | Error(BaseLoc, ErrMsg); | |
1946 | return nullptr; | |
223e47cc LB |
1947 | } |
1948 | ||
1a4d82fc | 1949 | if (SegReg || BaseReg || IndexReg) |
85aaf69f SL |
1950 | return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, |
1951 | IndexReg, Scale, MemStart, MemEnd); | |
1952 | return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, MemEnd); | |
223e47cc LB |
1953 | } |
1954 | ||
1a4d82fc JJ |
1955 | bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
1956 | SMLoc NameLoc, OperandVector &Operands) { | |
85aaf69f | 1957 | MCAsmParser &Parser = getParser(); |
970d7e83 | 1958 | InstInfo = &Info; |
223e47cc LB |
1959 | StringRef PatchedName = Name; |
1960 | ||
1961 | // FIXME: Hack to recognize setneb as setne. | |
1962 | if (PatchedName.startswith("set") && PatchedName.endswith("b") && | |
1963 | PatchedName != "setb" && PatchedName != "setnb") | |
1964 | PatchedName = PatchedName.substr(0, Name.size()-1); | |
1965 | ||
1966 | // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}. | |
1a4d82fc | 1967 | const MCExpr *ExtraImmOp = nullptr; |
223e47cc LB |
1968 | if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) && |
1969 | (PatchedName.endswith("ss") || PatchedName.endswith("sd") || | |
1970 | PatchedName.endswith("ps") || PatchedName.endswith("pd"))) { | |
1971 | bool IsVCMP = PatchedName[0] == 'v'; | |
1972 | unsigned SSECCIdx = IsVCMP ? 4 : 3; | |
1973 | unsigned SSEComparisonCode = StringSwitch<unsigned>( | |
1974 | PatchedName.slice(SSECCIdx, PatchedName.size() - 2)) | |
1975 | .Case("eq", 0x00) | |
1976 | .Case("lt", 0x01) | |
1977 | .Case("le", 0x02) | |
1978 | .Case("unord", 0x03) | |
1979 | .Case("neq", 0x04) | |
1980 | .Case("nlt", 0x05) | |
1981 | .Case("nle", 0x06) | |
1982 | .Case("ord", 0x07) | |
1983 | /* AVX only from here */ | |
1984 | .Case("eq_uq", 0x08) | |
1985 | .Case("nge", 0x09) | |
1986 | .Case("ngt", 0x0A) | |
1987 | .Case("false", 0x0B) | |
1988 | .Case("neq_oq", 0x0C) | |
1989 | .Case("ge", 0x0D) | |
1990 | .Case("gt", 0x0E) | |
1991 | .Case("true", 0x0F) | |
1992 | .Case("eq_os", 0x10) | |
1993 | .Case("lt_oq", 0x11) | |
1994 | .Case("le_oq", 0x12) | |
1995 | .Case("unord_s", 0x13) | |
1996 | .Case("neq_us", 0x14) | |
1997 | .Case("nlt_uq", 0x15) | |
1998 | .Case("nle_uq", 0x16) | |
1999 | .Case("ord_s", 0x17) | |
2000 | .Case("eq_us", 0x18) | |
2001 | .Case("nge_uq", 0x19) | |
2002 | .Case("ngt_uq", 0x1A) | |
2003 | .Case("false_os", 0x1B) | |
2004 | .Case("neq_os", 0x1C) | |
2005 | .Case("ge_oq", 0x1D) | |
2006 | .Case("gt_oq", 0x1E) | |
2007 | .Case("true_us", 0x1F) | |
2008 | .Default(~0U); | |
2009 | if (SSEComparisonCode != ~0U && (IsVCMP || SSEComparisonCode < 8)) { | |
2010 | ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode, | |
2011 | getParser().getContext()); | |
2012 | if (PatchedName.endswith("ss")) { | |
2013 | PatchedName = IsVCMP ? "vcmpss" : "cmpss"; | |
2014 | } else if (PatchedName.endswith("sd")) { | |
2015 | PatchedName = IsVCMP ? "vcmpsd" : "cmpsd"; | |
2016 | } else if (PatchedName.endswith("ps")) { | |
2017 | PatchedName = IsVCMP ? "vcmpps" : "cmpps"; | |
2018 | } else { | |
2019 | assert(PatchedName.endswith("pd") && "Unexpected mnemonic!"); | |
2020 | PatchedName = IsVCMP ? "vcmppd" : "cmppd"; | |
2021 | } | |
2022 | } | |
2023 | } | |
2024 | ||
2025 | Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); | |
2026 | ||
2027 | if (ExtraImmOp && !isParsingIntelSyntax()) | |
2028 | Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); | |
2029 | ||
2030 | // Determine whether this is an instruction prefix. | |
2031 | bool isPrefix = | |
2032 | Name == "lock" || Name == "rep" || | |
2033 | Name == "repe" || Name == "repz" || | |
2034 | Name == "repne" || Name == "repnz" || | |
2035 | Name == "rex64" || Name == "data16"; | |
2036 | ||
2037 | ||
2038 | // This does the actual operand parsing. Don't parse any more if we have a | |
2039 | // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we | |
2040 | // just want to parse the "lock" as the first instruction and the "incl" as | |
2041 | // the next one. | |
2042 | if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) { | |
2043 | ||
2044 | // Parse '*' modifier. | |
1a4d82fc JJ |
2045 | if (getLexer().is(AsmToken::Star)) |
2046 | Operands.push_back(X86Operand::CreateToken("*", consumeToken())); | |
2047 | ||
2048 | // Read the operands. | |
2049 | while(1) { | |
2050 | if (std::unique_ptr<X86Operand> Op = ParseOperand()) { | |
2051 | Operands.push_back(std::move(Op)); | |
2052 | if (!HandleAVX512Operand(Operands, *Operands.back())) | |
2053 | return true; | |
2054 | } else { | |
2055 | Parser.eatToEndOfStatement(); | |
2056 | return true; | |
223e47cc | 2057 | } |
1a4d82fc JJ |
2058 | // check for comma and eat it |
2059 | if (getLexer().is(AsmToken::Comma)) | |
2060 | Parser.Lex(); | |
2061 | else | |
2062 | break; | |
2063 | } | |
223e47cc | 2064 | |
1a4d82fc JJ |
2065 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
2066 | return ErrorAndEatStatement(getLexer().getLoc(), | |
2067 | "unexpected token in argument list"); | |
2068 | } | |
223e47cc | 2069 | |
1a4d82fc JJ |
2070 | // Consume the EndOfStatement or the prefix separator Slash |
2071 | if (getLexer().is(AsmToken::EndOfStatement) || | |
2072 | (isPrefix && getLexer().is(AsmToken::Slash))) | |
2073 | Parser.Lex(); | |
223e47cc LB |
2074 | |
2075 | if (ExtraImmOp && isParsingIntelSyntax()) | |
2076 | Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); | |
2077 | ||
2078 | // This is a terrible hack to handle "out[bwl]? %al, (%dx)" -> | |
2079 | // "outb %al, %dx". Out doesn't take a memory form, but this is a widely | |
2080 | // documented form in various unofficial manuals, so a lot of code uses it. | |
2081 | if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") && | |
2082 | Operands.size() == 3) { | |
1a4d82fc | 2083 | X86Operand &Op = (X86Operand &)*Operands.back(); |
223e47cc LB |
2084 | if (Op.isMem() && Op.Mem.SegReg == 0 && |
2085 | isa<MCConstantExpr>(Op.Mem.Disp) && | |
2086 | cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 && | |
2087 | Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) { | |
2088 | SMLoc Loc = Op.getEndLoc(); | |
2089 | Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc); | |
223e47cc LB |
2090 | } |
2091 | } | |
2092 | // Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al". | |
2093 | if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") && | |
2094 | Operands.size() == 3) { | |
1a4d82fc | 2095 | X86Operand &Op = (X86Operand &)*Operands[1]; |
223e47cc LB |
2096 | if (Op.isMem() && Op.Mem.SegReg == 0 && |
2097 | isa<MCConstantExpr>(Op.Mem.Disp) && | |
2098 | cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 && | |
2099 | Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) { | |
2100 | SMLoc Loc = Op.getEndLoc(); | |
1a4d82fc JJ |
2101 | Operands[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc); |
2102 | } | |
2103 | } | |
2104 | ||
2105 | // Append default arguments to "ins[bwld]" | |
2106 | if (Name.startswith("ins") && Operands.size() == 1 && | |
2107 | (Name == "insb" || Name == "insw" || Name == "insl" || | |
2108 | Name == "insd" )) { | |
2109 | if (isParsingIntelSyntax()) { | |
2110 | Operands.push_back(X86Operand::CreateReg(X86::DX, NameLoc, NameLoc)); | |
2111 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2112 | } else { | |
2113 | Operands.push_back(X86Operand::CreateReg(X86::DX, NameLoc, NameLoc)); | |
2114 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2115 | } | |
2116 | } | |
2117 | ||
2118 | // Append default arguments to "outs[bwld]" | |
2119 | if (Name.startswith("outs") && Operands.size() == 1 && | |
2120 | (Name == "outsb" || Name == "outsw" || Name == "outsl" || | |
2121 | Name == "outsd" )) { | |
2122 | if (isParsingIntelSyntax()) { | |
2123 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2124 | Operands.push_back(X86Operand::CreateReg(X86::DX, NameLoc, NameLoc)); | |
2125 | } else { | |
2126 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2127 | Operands.push_back(X86Operand::CreateReg(X86::DX, NameLoc, NameLoc)); | |
2128 | } | |
2129 | } | |
2130 | ||
2131 | // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate | |
2132 | // values of $SIREG according to the mode. It would be nice if this | |
2133 | // could be achieved with InstAlias in the tables. | |
2134 | if (Name.startswith("lods") && Operands.size() == 1 && | |
223e47cc | 2135 | (Name == "lods" || Name == "lodsb" || Name == "lodsw" || |
1a4d82fc JJ |
2136 | Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) |
2137 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2138 | ||
2139 | // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate | |
2140 | // values of $DIREG according to the mode. It would be nice if this | |
2141 | // could be achieved with InstAlias in the tables. | |
2142 | if (Name.startswith("stos") && Operands.size() == 1 && | |
2143 | (Name == "stos" || Name == "stosb" || Name == "stosw" || | |
2144 | Name == "stosl" || Name == "stosd" || Name == "stosq")) | |
2145 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2146 | ||
2147 | // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate | |
2148 | // values of $DIREG according to the mode. It would be nice if this | |
2149 | // could be achieved with InstAlias in the tables. | |
2150 | if (Name.startswith("scas") && Operands.size() == 1 && | |
2151 | (Name == "scas" || Name == "scasb" || Name == "scasw" || | |
2152 | Name == "scasl" || Name == "scasd" || Name == "scasq")) | |
2153 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2154 | ||
2155 | // Add default SI and DI operands to "cmps[bwlq]". | |
2156 | if (Name.startswith("cmps") && | |
2157 | (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" || | |
2158 | Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) { | |
2159 | if (Operands.size() == 1) { | |
2160 | if (isParsingIntelSyntax()) { | |
2161 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2162 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2163 | } else { | |
2164 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2165 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
223e47cc | 2166 | } |
1a4d82fc JJ |
2167 | } else if (Operands.size() == 3) { |
2168 | X86Operand &Op = (X86Operand &)*Operands[1]; | |
2169 | X86Operand &Op2 = (X86Operand &)*Operands[2]; | |
2170 | if (!doSrcDstMatch(Op, Op2)) | |
2171 | return Error(Op.getStartLoc(), | |
2172 | "mismatching source and destination index registers"); | |
223e47cc LB |
2173 | } |
2174 | } | |
1a4d82fc JJ |
2175 | |
2176 | // Add default SI and DI operands to "movs[bwlq]". | |
2177 | if ((Name.startswith("movs") && | |
2178 | (Name == "movs" || Name == "movsb" || Name == "movsw" || | |
2179 | Name == "movsl" || Name == "movsd" || Name == "movsq")) || | |
2180 | (Name.startswith("smov") && | |
2181 | (Name == "smov" || Name == "smovb" || Name == "smovw" || | |
2182 | Name == "smovl" || Name == "smovd" || Name == "smovq"))) { | |
2183 | if (Operands.size() == 1) { | |
2184 | if (Name == "movsd") | |
2185 | Operands.back() = X86Operand::CreateToken("movsl", NameLoc); | |
2186 | if (isParsingIntelSyntax()) { | |
2187 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
2188 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2189 | } else { | |
2190 | Operands.push_back(DefaultMemSIOperand(NameLoc)); | |
2191 | Operands.push_back(DefaultMemDIOperand(NameLoc)); | |
223e47cc | 2192 | } |
1a4d82fc JJ |
2193 | } else if (Operands.size() == 3) { |
2194 | X86Operand &Op = (X86Operand &)*Operands[1]; | |
2195 | X86Operand &Op2 = (X86Operand &)*Operands[2]; | |
2196 | if (!doSrcDstMatch(Op, Op2)) | |
2197 | return Error(Op.getStartLoc(), | |
2198 | "mismatching source and destination index registers"); | |
223e47cc LB |
2199 | } |
2200 | } | |
2201 | ||
2202 | // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to | |
2203 | // "shift <op>". | |
2204 | if ((Name.startswith("shr") || Name.startswith("sar") || | |
2205 | Name.startswith("shl") || Name.startswith("sal") || | |
2206 | Name.startswith("rcl") || Name.startswith("rcr") || | |
2207 | Name.startswith("rol") || Name.startswith("ror")) && | |
2208 | Operands.size() == 3) { | |
2209 | if (isParsingIntelSyntax()) { | |
2210 | // Intel syntax | |
1a4d82fc JJ |
2211 | X86Operand &Op1 = static_cast<X86Operand &>(*Operands[2]); |
2212 | if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) && | |
2213 | cast<MCConstantExpr>(Op1.getImm())->getValue() == 1) | |
223e47cc | 2214 | Operands.pop_back(); |
223e47cc | 2215 | } else { |
1a4d82fc JJ |
2216 | X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]); |
2217 | if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) && | |
2218 | cast<MCConstantExpr>(Op1.getImm())->getValue() == 1) | |
223e47cc | 2219 | Operands.erase(Operands.begin() + 1); |
223e47cc LB |
2220 | } |
2221 | } | |
2222 | ||
2223 | // Transforms "int $3" into "int3" as a size optimization. We can't write an | |
2224 | // instalias with an immediate operand yet. | |
2225 | if (Name == "int" && Operands.size() == 2) { | |
1a4d82fc JJ |
2226 | X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]); |
2227 | if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) && | |
2228 | cast<MCConstantExpr>(Op1.getImm())->getValue() == 3) { | |
223e47cc | 2229 | Operands.erase(Operands.begin() + 1); |
1a4d82fc | 2230 | static_cast<X86Operand &>(*Operands[0]).setTokenValue("int3"); |
223e47cc LB |
2231 | } |
2232 | } | |
2233 | ||
2234 | return false; | |
2235 | } | |
2236 | ||
970d7e83 LB |
2237 | static bool convertToSExti8(MCInst &Inst, unsigned Opcode, unsigned Reg, |
2238 | bool isCmp) { | |
2239 | MCInst TmpInst; | |
2240 | TmpInst.setOpcode(Opcode); | |
2241 | if (!isCmp) | |
2242 | TmpInst.addOperand(MCOperand::CreateReg(Reg)); | |
2243 | TmpInst.addOperand(MCOperand::CreateReg(Reg)); | |
2244 | TmpInst.addOperand(Inst.getOperand(0)); | |
2245 | Inst = TmpInst; | |
2246 | return true; | |
2247 | } | |
223e47cc | 2248 | |
970d7e83 LB |
2249 | static bool convert16i16to16ri8(MCInst &Inst, unsigned Opcode, |
2250 | bool isCmp = false) { | |
2251 | if (!Inst.getOperand(0).isImm() || | |
2252 | !isImmSExti16i8Value(Inst.getOperand(0).getImm())) | |
2253 | return false; | |
223e47cc | 2254 | |
970d7e83 LB |
2255 | return convertToSExti8(Inst, Opcode, X86::AX, isCmp); |
2256 | } | |
223e47cc | 2257 | |
970d7e83 LB |
2258 | static bool convert32i32to32ri8(MCInst &Inst, unsigned Opcode, |
2259 | bool isCmp = false) { | |
2260 | if (!Inst.getOperand(0).isImm() || | |
2261 | !isImmSExti32i8Value(Inst.getOperand(0).getImm())) | |
2262 | return false; | |
223e47cc | 2263 | |
970d7e83 LB |
2264 | return convertToSExti8(Inst, Opcode, X86::EAX, isCmp); |
2265 | } | |
223e47cc | 2266 | |
970d7e83 LB |
2267 | static bool convert64i32to64ri8(MCInst &Inst, unsigned Opcode, |
2268 | bool isCmp = false) { | |
2269 | if (!Inst.getOperand(0).isImm() || | |
2270 | !isImmSExti64i8Value(Inst.getOperand(0).getImm())) | |
2271 | return false; | |
223e47cc | 2272 | |
970d7e83 | 2273 | return convertToSExti8(Inst, Opcode, X86::RAX, isCmp); |
223e47cc LB |
2274 | } |
2275 | ||
85aaf69f SL |
2276 | bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) { |
2277 | switch (Inst.getOpcode()) { | |
2278 | default: return true; | |
2279 | case X86::INT: | |
2280 | X86Operand &Op = static_cast<X86Operand &>(*Ops[1]); | |
2281 | assert(Op.isImm() && "expected immediate"); | |
2282 | int64_t Res; | |
2283 | if (!Op.getImm()->EvaluateAsAbsolute(Res) || Res > 255) { | |
2284 | Error(Op.getStartLoc(), "interrupt vector must be in range [0-255]"); | |
2285 | return false; | |
2286 | } | |
2287 | return true; | |
2288 | } | |
2289 | llvm_unreachable("handle the instruction appropriately"); | |
2290 | } | |
2291 | ||
1a4d82fc | 2292 | bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) { |
970d7e83 LB |
2293 | switch (Inst.getOpcode()) { |
2294 | default: return false; | |
2295 | case X86::AND16i16: return convert16i16to16ri8(Inst, X86::AND16ri8); | |
2296 | case X86::AND32i32: return convert32i32to32ri8(Inst, X86::AND32ri8); | |
2297 | case X86::AND64i32: return convert64i32to64ri8(Inst, X86::AND64ri8); | |
2298 | case X86::XOR16i16: return convert16i16to16ri8(Inst, X86::XOR16ri8); | |
2299 | case X86::XOR32i32: return convert32i32to32ri8(Inst, X86::XOR32ri8); | |
2300 | case X86::XOR64i32: return convert64i32to64ri8(Inst, X86::XOR64ri8); | |
2301 | case X86::OR16i16: return convert16i16to16ri8(Inst, X86::OR16ri8); | |
2302 | case X86::OR32i32: return convert32i32to32ri8(Inst, X86::OR32ri8); | |
2303 | case X86::OR64i32: return convert64i32to64ri8(Inst, X86::OR64ri8); | |
2304 | case X86::CMP16i16: return convert16i16to16ri8(Inst, X86::CMP16ri8, true); | |
2305 | case X86::CMP32i32: return convert32i32to32ri8(Inst, X86::CMP32ri8, true); | |
2306 | case X86::CMP64i32: return convert64i32to64ri8(Inst, X86::CMP64ri8, true); | |
2307 | case X86::ADD16i16: return convert16i16to16ri8(Inst, X86::ADD16ri8); | |
2308 | case X86::ADD32i32: return convert32i32to32ri8(Inst, X86::ADD32ri8); | |
2309 | case X86::ADD64i32: return convert64i32to64ri8(Inst, X86::ADD64ri8); | |
2310 | case X86::SUB16i16: return convert16i16to16ri8(Inst, X86::SUB16ri8); | |
2311 | case X86::SUB32i32: return convert32i32to32ri8(Inst, X86::SUB32ri8); | |
2312 | case X86::SUB64i32: return convert64i32to64ri8(Inst, X86::SUB64ri8); | |
2313 | case X86::ADC16i16: return convert16i16to16ri8(Inst, X86::ADC16ri8); | |
2314 | case X86::ADC32i32: return convert32i32to32ri8(Inst, X86::ADC32ri8); | |
2315 | case X86::ADC64i32: return convert64i32to64ri8(Inst, X86::ADC64ri8); | |
2316 | case X86::SBB16i16: return convert16i16to16ri8(Inst, X86::SBB16ri8); | |
2317 | case X86::SBB32i32: return convert32i32to32ri8(Inst, X86::SBB32ri8); | |
2318 | case X86::SBB64i32: return convert64i32to64ri8(Inst, X86::SBB64ri8); | |
1a4d82fc JJ |
2319 | case X86::VMOVAPDrr: |
2320 | case X86::VMOVAPDYrr: | |
2321 | case X86::VMOVAPSrr: | |
2322 | case X86::VMOVAPSYrr: | |
2323 | case X86::VMOVDQArr: | |
2324 | case X86::VMOVDQAYrr: | |
2325 | case X86::VMOVDQUrr: | |
2326 | case X86::VMOVDQUYrr: | |
2327 | case X86::VMOVUPDrr: | |
2328 | case X86::VMOVUPDYrr: | |
2329 | case X86::VMOVUPSrr: | |
2330 | case X86::VMOVUPSYrr: { | |
2331 | if (X86II::isX86_64ExtendedReg(Inst.getOperand(0).getReg()) || | |
2332 | !X86II::isX86_64ExtendedReg(Inst.getOperand(1).getReg())) | |
2333 | return false; | |
2334 | ||
2335 | unsigned NewOpc; | |
2336 | switch (Inst.getOpcode()) { | |
2337 | default: llvm_unreachable("Invalid opcode"); | |
2338 | case X86::VMOVAPDrr: NewOpc = X86::VMOVAPDrr_REV; break; | |
2339 | case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break; | |
2340 | case X86::VMOVAPSrr: NewOpc = X86::VMOVAPSrr_REV; break; | |
2341 | case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break; | |
2342 | case X86::VMOVDQArr: NewOpc = X86::VMOVDQArr_REV; break; | |
2343 | case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break; | |
2344 | case X86::VMOVDQUrr: NewOpc = X86::VMOVDQUrr_REV; break; | |
2345 | case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break; | |
2346 | case X86::VMOVUPDrr: NewOpc = X86::VMOVUPDrr_REV; break; | |
2347 | case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break; | |
2348 | case X86::VMOVUPSrr: NewOpc = X86::VMOVUPSrr_REV; break; | |
2349 | case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break; | |
2350 | } | |
2351 | Inst.setOpcode(NewOpc); | |
2352 | return true; | |
2353 | } | |
2354 | case X86::VMOVSDrr: | |
2355 | case X86::VMOVSSrr: { | |
2356 | if (X86II::isX86_64ExtendedReg(Inst.getOperand(0).getReg()) || | |
2357 | !X86II::isX86_64ExtendedReg(Inst.getOperand(2).getReg())) | |
2358 | return false; | |
2359 | unsigned NewOpc; | |
2360 | switch (Inst.getOpcode()) { | |
2361 | default: llvm_unreachable("Invalid opcode"); | |
2362 | case X86::VMOVSDrr: NewOpc = X86::VMOVSDrr_REV; break; | |
2363 | case X86::VMOVSSrr: NewOpc = X86::VMOVSSrr_REV; break; | |
2364 | } | |
2365 | Inst.setOpcode(NewOpc); | |
2366 | return true; | |
2367 | } | |
970d7e83 | 2368 | } |
223e47cc LB |
2369 | } |
2370 | ||
1a4d82fc | 2371 | static const char *getSubtargetFeatureName(uint64_t Val); |
223e47cc | 2372 | |
1a4d82fc JJ |
2373 | void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands, |
2374 | MCStreamer &Out) { | |
2375 | Instrumentation->InstrumentAndEmitInstruction(Inst, Operands, getContext(), | |
2376 | MII, Out); | |
2377 | } | |
2378 | ||
2379 | bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | |
2380 | OperandVector &Operands, | |
2381 | MCStreamer &Out, uint64_t &ErrorInfo, | |
2382 | bool MatchingInlineAsm) { | |
2383 | if (isParsingIntelSyntax()) | |
2384 | return MatchAndEmitIntelInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo, | |
2385 | MatchingInlineAsm); | |
2386 | return MatchAndEmitATTInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo, | |
2387 | MatchingInlineAsm); | |
2388 | } | |
2389 | ||
2390 | void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, | |
2391 | OperandVector &Operands, MCStreamer &Out, | |
2392 | bool MatchingInlineAsm) { | |
223e47cc LB |
2393 | // FIXME: This should be replaced with a real .td file alias mechanism. |
2394 | // Also, MatchInstructionImpl should actually *do* the EmitInstruction | |
2395 | // call. | |
1a4d82fc JJ |
2396 | const char *Repl = StringSwitch<const char *>(Op.getToken()) |
2397 | .Case("finit", "fninit") | |
2398 | .Case("fsave", "fnsave") | |
2399 | .Case("fstcw", "fnstcw") | |
2400 | .Case("fstcww", "fnstcw") | |
2401 | .Case("fstenv", "fnstenv") | |
2402 | .Case("fstsw", "fnstsw") | |
2403 | .Case("fstsww", "fnstsw") | |
2404 | .Case("fclex", "fnclex") | |
2405 | .Default(nullptr); | |
2406 | if (Repl) { | |
223e47cc LB |
2407 | MCInst Inst; |
2408 | Inst.setOpcode(X86::WAIT); | |
2409 | Inst.setLoc(IDLoc); | |
970d7e83 | 2410 | if (!MatchingInlineAsm) |
1a4d82fc | 2411 | EmitInstruction(Inst, Operands, Out); |
223e47cc LB |
2412 | Operands[0] = X86Operand::CreateToken(Repl, IDLoc); |
2413 | } | |
1a4d82fc JJ |
2414 | } |
2415 | ||
2416 | bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, | |
2417 | bool MatchingInlineAsm) { | |
2418 | assert(ErrorInfo && "Unknown missing feature!"); | |
2419 | ArrayRef<SMRange> EmptyRanges = None; | |
2420 | SmallString<126> Msg; | |
2421 | raw_svector_ostream OS(Msg); | |
2422 | OS << "instruction requires:"; | |
2423 | uint64_t Mask = 1; | |
2424 | for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { | |
2425 | if (ErrorInfo & Mask) | |
2426 | OS << ' ' << getSubtargetFeatureName(ErrorInfo & Mask); | |
2427 | Mask <<= 1; | |
2428 | } | |
2429 | return Error(IDLoc, OS.str(), EmptyRanges, MatchingInlineAsm); | |
2430 | } | |
2431 | ||
2432 | bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, | |
2433 | OperandVector &Operands, | |
2434 | MCStreamer &Out, | |
2435 | uint64_t &ErrorInfo, | |
2436 | bool MatchingInlineAsm) { | |
2437 | assert(!Operands.empty() && "Unexpect empty operand list!"); | |
2438 | X86Operand &Op = static_cast<X86Operand &>(*Operands[0]); | |
2439 | assert(Op.isToken() && "Leading operand should always be a mnemonic!"); | |
2440 | ArrayRef<SMRange> EmptyRanges = None; | |
2441 | ||
2442 | // First, handle aliases that expand to multiple instructions. | |
2443 | MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm); | |
223e47cc LB |
2444 | |
2445 | bool WasOriginallyInvalidOperand = false; | |
2446 | MCInst Inst; | |
2447 | ||
2448 | // First, try a direct match. | |
970d7e83 LB |
2449 | switch (MatchInstructionImpl(Operands, Inst, |
2450 | ErrorInfo, MatchingInlineAsm, | |
223e47cc | 2451 | isParsingIntelSyntax())) { |
85aaf69f | 2452 | default: llvm_unreachable("Unexpected match result!"); |
223e47cc | 2453 | case Match_Success: |
85aaf69f SL |
2454 | if (!validateInstruction(Inst, Operands)) |
2455 | return true; | |
2456 | ||
223e47cc LB |
2457 | // Some instructions need post-processing to, for example, tweak which |
2458 | // encoding is selected. Loop on it while changes happen so the | |
2459 | // individual transformations can chain off each other. | |
970d7e83 LB |
2460 | if (!MatchingInlineAsm) |
2461 | while (processInstruction(Inst, Operands)) | |
2462 | ; | |
223e47cc LB |
2463 | |
2464 | Inst.setLoc(IDLoc); | |
970d7e83 | 2465 | if (!MatchingInlineAsm) |
1a4d82fc | 2466 | EmitInstruction(Inst, Operands, Out); |
970d7e83 | 2467 | Opcode = Inst.getOpcode(); |
223e47cc | 2468 | return false; |
1a4d82fc JJ |
2469 | case Match_MissingFeature: |
2470 | return ErrorMissingFeature(IDLoc, ErrorInfo, MatchingInlineAsm); | |
223e47cc LB |
2471 | case Match_InvalidOperand: |
2472 | WasOriginallyInvalidOperand = true; | |
2473 | break; | |
2474 | case Match_MnemonicFail: | |
2475 | break; | |
2476 | } | |
2477 | ||
2478 | // FIXME: Ideally, we would only attempt suffix matches for things which are | |
2479 | // valid prefixes, and we could just infer the right unambiguous | |
2480 | // type. However, that requires substantially more matcher support than the | |
2481 | // following hack. | |
2482 | ||
2483 | // Change the operand to point to a temporary token. | |
1a4d82fc | 2484 | StringRef Base = Op.getToken(); |
223e47cc LB |
2485 | SmallString<16> Tmp; |
2486 | Tmp += Base; | |
2487 | Tmp += ' '; | |
1a4d82fc | 2488 | Op.setTokenValue(Tmp.str()); |
223e47cc LB |
2489 | |
2490 | // If this instruction starts with an 'f', then it is a floating point stack | |
2491 | // instruction. These come in up to three forms for 32-bit, 64-bit, and | |
2492 | // 80-bit floating point, which use the suffixes s,l,t respectively. | |
2493 | // | |
2494 | // Otherwise, we assume that this may be an integer instruction, which comes | |
2495 | // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively. | |
2496 | const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0"; | |
2497 | ||
2498 | // Check for the various suffix matches. | |
1a4d82fc JJ |
2499 | uint64_t ErrorInfoIgnore; |
2500 | uint64_t ErrorInfoMissingFeature = 0; // Init suppresses compiler warnings. | |
2501 | unsigned Match[4]; | |
2502 | ||
2503 | for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) { | |
2504 | Tmp.back() = Suffixes[I]; | |
2505 | Match[I] = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, | |
2506 | MatchingInlineAsm, isParsingIntelSyntax()); | |
2507 | // If this returned as a missing feature failure, remember that. | |
2508 | if (Match[I] == Match_MissingFeature) | |
2509 | ErrorInfoMissingFeature = ErrorInfoIgnore; | |
2510 | } | |
223e47cc LB |
2511 | |
2512 | // Restore the old token. | |
1a4d82fc | 2513 | Op.setTokenValue(Base); |
223e47cc LB |
2514 | |
2515 | // If exactly one matched, then we treat that as a successful match (and the | |
2516 | // instruction will already have been filled in correctly, since the failing | |
2517 | // matches won't have modified it). | |
2518 | unsigned NumSuccessfulMatches = | |
1a4d82fc | 2519 | std::count(std::begin(Match), std::end(Match), Match_Success); |
223e47cc LB |
2520 | if (NumSuccessfulMatches == 1) { |
2521 | Inst.setLoc(IDLoc); | |
970d7e83 | 2522 | if (!MatchingInlineAsm) |
1a4d82fc | 2523 | EmitInstruction(Inst, Operands, Out); |
970d7e83 | 2524 | Opcode = Inst.getOpcode(); |
223e47cc LB |
2525 | return false; |
2526 | } | |
2527 | ||
2528 | // Otherwise, the match failed, try to produce a decent error message. | |
2529 | ||
2530 | // If we had multiple suffix matches, then identify this as an ambiguous | |
2531 | // match. | |
2532 | if (NumSuccessfulMatches > 1) { | |
2533 | char MatchChars[4]; | |
2534 | unsigned NumMatches = 0; | |
1a4d82fc JJ |
2535 | for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) |
2536 | if (Match[I] == Match_Success) | |
2537 | MatchChars[NumMatches++] = Suffixes[I]; | |
223e47cc LB |
2538 | |
2539 | SmallString<126> Msg; | |
2540 | raw_svector_ostream OS(Msg); | |
2541 | OS << "ambiguous instructions require an explicit suffix (could be "; | |
2542 | for (unsigned i = 0; i != NumMatches; ++i) { | |
2543 | if (i != 0) | |
2544 | OS << ", "; | |
2545 | if (i + 1 == NumMatches) | |
2546 | OS << "or "; | |
2547 | OS << "'" << Base << MatchChars[i] << "'"; | |
2548 | } | |
2549 | OS << ")"; | |
970d7e83 | 2550 | Error(IDLoc, OS.str(), EmptyRanges, MatchingInlineAsm); |
223e47cc LB |
2551 | return true; |
2552 | } | |
2553 | ||
2554 | // Okay, we know that none of the variants matched successfully. | |
2555 | ||
2556 | // If all of the instructions reported an invalid mnemonic, then the original | |
2557 | // mnemonic was invalid. | |
1a4d82fc | 2558 | if (std::count(std::begin(Match), std::end(Match), Match_MnemonicFail) == 4) { |
223e47cc | 2559 | if (!WasOriginallyInvalidOperand) { |
1a4d82fc JJ |
2560 | ArrayRef<SMRange> Ranges = |
2561 | MatchingInlineAsm ? EmptyRanges : Op.getLocRange(); | |
223e47cc | 2562 | return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'", |
970d7e83 | 2563 | Ranges, MatchingInlineAsm); |
223e47cc LB |
2564 | } |
2565 | ||
2566 | // Recover location info for the operand if we know which was the problem. | |
1a4d82fc | 2567 | if (ErrorInfo != ~0ULL) { |
970d7e83 | 2568 | if (ErrorInfo >= Operands.size()) |
223e47cc | 2569 | return Error(IDLoc, "too few operands for instruction", |
970d7e83 | 2570 | EmptyRanges, MatchingInlineAsm); |
223e47cc | 2571 | |
1a4d82fc JJ |
2572 | X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo]; |
2573 | if (Operand.getStartLoc().isValid()) { | |
2574 | SMRange OperandRange = Operand.getLocRange(); | |
2575 | return Error(Operand.getStartLoc(), "invalid operand for instruction", | |
970d7e83 | 2576 | OperandRange, MatchingInlineAsm); |
223e47cc LB |
2577 | } |
2578 | } | |
2579 | ||
2580 | return Error(IDLoc, "invalid operand for instruction", EmptyRanges, | |
970d7e83 | 2581 | MatchingInlineAsm); |
223e47cc LB |
2582 | } |
2583 | ||
2584 | // If one instruction matched with a missing feature, report this as a | |
2585 | // missing feature. | |
1a4d82fc JJ |
2586 | if (std::count(std::begin(Match), std::end(Match), |
2587 | Match_MissingFeature) == 1) { | |
2588 | ErrorInfo = ErrorInfoMissingFeature; | |
2589 | return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, | |
2590 | MatchingInlineAsm); | |
223e47cc LB |
2591 | } |
2592 | ||
2593 | // If one instruction matched with an invalid operand, report this as an | |
2594 | // operand failure. | |
1a4d82fc JJ |
2595 | if (std::count(std::begin(Match), std::end(Match), |
2596 | Match_InvalidOperand) == 1) { | |
2597 | return Error(IDLoc, "invalid operand for instruction", EmptyRanges, | |
2598 | MatchingInlineAsm); | |
223e47cc LB |
2599 | } |
2600 | ||
2601 | // If all of these were an outright failure, report it in a useless way. | |
2602 | Error(IDLoc, "unknown use of instruction mnemonic without a size suffix", | |
970d7e83 | 2603 | EmptyRanges, MatchingInlineAsm); |
223e47cc LB |
2604 | return true; |
2605 | } | |
2606 | ||
1a4d82fc JJ |
2607 | bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, |
2608 | OperandVector &Operands, | |
2609 | MCStreamer &Out, | |
2610 | uint64_t &ErrorInfo, | |
2611 | bool MatchingInlineAsm) { | |
2612 | assert(!Operands.empty() && "Unexpect empty operand list!"); | |
2613 | X86Operand &Op = static_cast<X86Operand &>(*Operands[0]); | |
2614 | assert(Op.isToken() && "Leading operand should always be a mnemonic!"); | |
2615 | StringRef Mnemonic = Op.getToken(); | |
2616 | ArrayRef<SMRange> EmptyRanges = None; | |
2617 | ||
2618 | // First, handle aliases that expand to multiple instructions. | |
2619 | MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm); | |
2620 | ||
2621 | MCInst Inst; | |
2622 | ||
2623 | // Find one unsized memory operand, if present. | |
2624 | X86Operand *UnsizedMemOp = nullptr; | |
2625 | for (const auto &Op : Operands) { | |
2626 | X86Operand *X86Op = static_cast<X86Operand *>(Op.get()); | |
2627 | if (X86Op->isMemUnsized()) | |
2628 | UnsizedMemOp = X86Op; | |
2629 | } | |
2630 | ||
2631 | // Allow some instructions to have implicitly pointer-sized operands. This is | |
2632 | // compatible with gas. | |
2633 | if (UnsizedMemOp) { | |
2634 | static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"}; | |
2635 | for (const char *Instr : PtrSizedInstrs) { | |
2636 | if (Mnemonic == Instr) { | |
85aaf69f | 2637 | UnsizedMemOp->Mem.Size = getPointerWidth(); |
1a4d82fc JJ |
2638 | break; |
2639 | } | |
2640 | } | |
2641 | } | |
2642 | ||
2643 | // If an unsized memory operand is present, try to match with each memory | |
2644 | // operand size. In Intel assembly, the size is not part of the instruction | |
2645 | // mnemonic. | |
2646 | SmallVector<unsigned, 8> Match; | |
2647 | uint64_t ErrorInfoMissingFeature = 0; | |
2648 | if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { | |
85aaf69f | 2649 | static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; |
1a4d82fc JJ |
2650 | for (unsigned Size : MopSizes) { |
2651 | UnsizedMemOp->Mem.Size = Size; | |
2652 | uint64_t ErrorInfoIgnore; | |
2653 | unsigned LastOpcode = Inst.getOpcode(); | |
2654 | unsigned M = | |
2655 | MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, | |
2656 | MatchingInlineAsm, isParsingIntelSyntax()); | |
2657 | if (Match.empty() || LastOpcode != Inst.getOpcode()) | |
2658 | Match.push_back(M); | |
2659 | ||
2660 | // If this returned as a missing feature failure, remember that. | |
2661 | if (Match.back() == Match_MissingFeature) | |
2662 | ErrorInfoMissingFeature = ErrorInfoIgnore; | |
2663 | } | |
2664 | ||
2665 | // Restore the size of the unsized memory operand if we modified it. | |
2666 | if (UnsizedMemOp) | |
2667 | UnsizedMemOp->Mem.Size = 0; | |
2668 | } | |
2669 | ||
2670 | // If we haven't matched anything yet, this is not a basic integer or FPU | |
2671 | // operation. There shouldn't be any ambiguity in our mneumonic table, so try | |
2672 | // matching with the unsized operand. | |
2673 | if (Match.empty()) { | |
2674 | Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo, | |
2675 | MatchingInlineAsm, | |
2676 | isParsingIntelSyntax())); | |
2677 | // If this returned as a missing feature failure, remember that. | |
2678 | if (Match.back() == Match_MissingFeature) | |
2679 | ErrorInfoMissingFeature = ErrorInfo; | |
2680 | } | |
2681 | ||
2682 | // Restore the size of the unsized memory operand if we modified it. | |
2683 | if (UnsizedMemOp) | |
2684 | UnsizedMemOp->Mem.Size = 0; | |
2685 | ||
2686 | // If it's a bad mnemonic, all results will be the same. | |
2687 | if (Match.back() == Match_MnemonicFail) { | |
2688 | ArrayRef<SMRange> Ranges = | |
2689 | MatchingInlineAsm ? EmptyRanges : Op.getLocRange(); | |
2690 | return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'", | |
2691 | Ranges, MatchingInlineAsm); | |
2692 | } | |
2693 | ||
2694 | // If exactly one matched, then we treat that as a successful match (and the | |
2695 | // instruction will already have been filled in correctly, since the failing | |
2696 | // matches won't have modified it). | |
2697 | unsigned NumSuccessfulMatches = | |
2698 | std::count(std::begin(Match), std::end(Match), Match_Success); | |
2699 | if (NumSuccessfulMatches == 1) { | |
85aaf69f SL |
2700 | if (!validateInstruction(Inst, Operands)) |
2701 | return true; | |
2702 | ||
1a4d82fc JJ |
2703 | // Some instructions need post-processing to, for example, tweak which |
2704 | // encoding is selected. Loop on it while changes happen so the individual | |
2705 | // transformations can chain off each other. | |
2706 | if (!MatchingInlineAsm) | |
2707 | while (processInstruction(Inst, Operands)) | |
2708 | ; | |
2709 | Inst.setLoc(IDLoc); | |
2710 | if (!MatchingInlineAsm) | |
2711 | EmitInstruction(Inst, Operands, Out); | |
2712 | Opcode = Inst.getOpcode(); | |
2713 | return false; | |
2714 | } else if (NumSuccessfulMatches > 1) { | |
2715 | assert(UnsizedMemOp && | |
2716 | "multiple matches only possible with unsized memory operands"); | |
2717 | ArrayRef<SMRange> Ranges = | |
2718 | MatchingInlineAsm ? EmptyRanges : UnsizedMemOp->getLocRange(); | |
2719 | return Error(UnsizedMemOp->getStartLoc(), | |
2720 | "ambiguous operand size for instruction '" + Mnemonic + "\'", | |
2721 | Ranges, MatchingInlineAsm); | |
2722 | } | |
2723 | ||
2724 | // If one instruction matched with a missing feature, report this as a | |
2725 | // missing feature. | |
2726 | if (std::count(std::begin(Match), std::end(Match), | |
2727 | Match_MissingFeature) == 1) { | |
2728 | ErrorInfo = ErrorInfoMissingFeature; | |
2729 | return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, | |
2730 | MatchingInlineAsm); | |
2731 | } | |
2732 | ||
2733 | // If one instruction matched with an invalid operand, report this as an | |
2734 | // operand failure. | |
2735 | if (std::count(std::begin(Match), std::end(Match), | |
2736 | Match_InvalidOperand) == 1) { | |
2737 | return Error(IDLoc, "invalid operand for instruction", EmptyRanges, | |
2738 | MatchingInlineAsm); | |
2739 | } | |
2740 | ||
2741 | // If all of these were an outright failure, report it in a useless way. | |
2742 | return Error(IDLoc, "unknown instruction mnemonic", EmptyRanges, | |
2743 | MatchingInlineAsm); | |
2744 | } | |
2745 | ||
2746 | bool X86AsmParser::OmitRegisterFromClobberLists(unsigned RegNo) { | |
2747 | return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo); | |
2748 | } | |
223e47cc LB |
2749 | |
2750 | bool X86AsmParser::ParseDirective(AsmToken DirectiveID) { | |
85aaf69f | 2751 | MCAsmParser &Parser = getParser(); |
223e47cc LB |
2752 | StringRef IDVal = DirectiveID.getIdentifier(); |
2753 | if (IDVal == ".word") | |
2754 | return ParseDirectiveWord(2, DirectiveID.getLoc()); | |
2755 | else if (IDVal.startswith(".code")) | |
2756 | return ParseDirectiveCode(IDVal, DirectiveID.getLoc()); | |
2757 | else if (IDVal.startswith(".att_syntax")) { | |
1a4d82fc JJ |
2758 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
2759 | if (Parser.getTok().getString() == "prefix") | |
2760 | Parser.Lex(); | |
2761 | else if (Parser.getTok().getString() == "noprefix") | |
2762 | return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not " | |
2763 | "supported: registers must have a " | |
2764 | "'%' prefix in .att_syntax"); | |
2765 | } | |
223e47cc LB |
2766 | getParser().setAssemblerDialect(0); |
2767 | return false; | |
2768 | } else if (IDVal.startswith(".intel_syntax")) { | |
2769 | getParser().setAssemblerDialect(1); | |
2770 | if (getLexer().isNot(AsmToken::EndOfStatement)) { | |
1a4d82fc | 2771 | if (Parser.getTok().getString() == "noprefix") |
223e47cc | 2772 | Parser.Lex(); |
1a4d82fc JJ |
2773 | else if (Parser.getTok().getString() == "prefix") |
2774 | return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not " | |
2775 | "supported: registers must not have " | |
2776 | "a '%' prefix in .intel_syntax"); | |
223e47cc LB |
2777 | } |
2778 | return false; | |
2779 | } | |
2780 | return true; | |
2781 | } | |
2782 | ||
2783 | /// ParseDirectiveWord | |
2784 | /// ::= .word [ expression (, expression)* ] | |
2785 | bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { | |
85aaf69f | 2786 | MCAsmParser &Parser = getParser(); |
223e47cc LB |
2787 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
2788 | for (;;) { | |
2789 | const MCExpr *Value; | |
970d7e83 | 2790 | if (getParser().parseExpression(Value)) |
1a4d82fc | 2791 | return false; |
223e47cc | 2792 | |
970d7e83 | 2793 | getParser().getStreamer().EmitValue(Value, Size); |
223e47cc LB |
2794 | |
2795 | if (getLexer().is(AsmToken::EndOfStatement)) | |
2796 | break; | |
2797 | ||
2798 | // FIXME: Improve diagnostic. | |
1a4d82fc JJ |
2799 | if (getLexer().isNot(AsmToken::Comma)) { |
2800 | Error(L, "unexpected token in directive"); | |
2801 | return false; | |
2802 | } | |
223e47cc LB |
2803 | Parser.Lex(); |
2804 | } | |
2805 | } | |
2806 | ||
2807 | Parser.Lex(); | |
2808 | return false; | |
2809 | } | |
2810 | ||
2811 | /// ParseDirectiveCode | |
1a4d82fc | 2812 | /// ::= .code16 | .code32 | .code64 |
223e47cc | 2813 | bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) { |
85aaf69f | 2814 | MCAsmParser &Parser = getParser(); |
1a4d82fc JJ |
2815 | if (IDVal == ".code16") { |
2816 | Parser.Lex(); | |
2817 | if (!is16BitMode()) { | |
2818 | SwitchMode(X86::Mode16Bit); | |
2819 | getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); | |
2820 | } | |
2821 | } else if (IDVal == ".code32") { | |
223e47cc | 2822 | Parser.Lex(); |
1a4d82fc JJ |
2823 | if (!is32BitMode()) { |
2824 | SwitchMode(X86::Mode32Bit); | |
223e47cc LB |
2825 | getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); |
2826 | } | |
2827 | } else if (IDVal == ".code64") { | |
2828 | Parser.Lex(); | |
2829 | if (!is64BitMode()) { | |
1a4d82fc | 2830 | SwitchMode(X86::Mode64Bit); |
223e47cc LB |
2831 | getParser().getStreamer().EmitAssemblerFlag(MCAF_Code64); |
2832 | } | |
2833 | } else { | |
1a4d82fc JJ |
2834 | Error(L, "unknown directive " + IDVal); |
2835 | return false; | |
223e47cc LB |
2836 | } |
2837 | ||
2838 | return false; | |
2839 | } | |
2840 | ||
223e47cc LB |
2841 | // Force static initialization. |
2842 | extern "C" void LLVMInitializeX86AsmParser() { | |
2843 | RegisterMCAsmParser<X86AsmParser> X(TheX86_32Target); | |
2844 | RegisterMCAsmParser<X86AsmParser> Y(TheX86_64Target); | |
223e47cc LB |
2845 | } |
2846 | ||
2847 | #define GET_REGISTER_MATCHER | |
2848 | #define GET_MATCHER_IMPLEMENTATION | |
970d7e83 | 2849 | #define GET_SUBTARGET_FEATURE_NAME |
223e47cc | 2850 | #include "X86GenAsmMatcher.inc" |