llvm.org GIT mirror llvm / 9c41fa8
Updates to the ARM target assembler for llvm-mc per review comments from Daniel Dunbar. - Reordered the fields in the ARMOperand Mem struct to make the struct smaller. Making bool's into 1 bit fields and put the MCExpr* fields adjacent to each other. - Fixed a number of places in ARMAsmParser.cpp so they have doxygen comments. - Change the name of ARMAsmParser::ParseRegister() to MaybeParseRegister and added the bool ParseWriteBack parameter. - Changed ARMAsmParser::ParseMemory() to call MaybeParseRegister(). - Added ARMAsmParser::ParseMemoryOffsetReg to factor out parsing the offset of a memory operand. And use it for both parsing both preindexed and post indexing addressing forms in ARMAsmParser::ParseMemory. - Changed the first argument to ParseShift() to a reference. - Changed ParseShift() to check for Rrx first and return to reduce nesting. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85632 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 11 years ago
1 changed file(s) with 139 addition(s) and 140 deletion(s). Raw diff Collapse all Expand all
4343
4444 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
4545
46 bool ParseRegister(ARMOperand &Op);
46 bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack);
4747
4848 bool ParseRegisterList(ARMOperand &Op);
4949
5050 bool ParseMemory(ARMOperand &Op);
5151
52 bool ParseShift(enum ShiftType *St, const MCExpr *&ShiftAmount);
52 bool ParseMemoryOffsetReg(bool &Negative,
53 bool &OffsetRegShifted,
54 enum ShiftType &ShiftType,
55 const MCExpr *&ShiftAmount,
56 const MCExpr *&Offset,
57 bool &OffsetIsReg,
58 int OffsetRegNum);
59
60 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount);
5361
5462 bool ParseOperand(ARMOperand &Op);
5563
122130 // This is for all forms of ARM address expressions
123131 struct {
124132 unsigned BaseRegNum;
125 bool OffsetIsReg;
133 unsigned OffsetRegNum; // used when OffsetIsReg is true
126134 const MCExpr *Offset; // used when OffsetIsReg is false
127 unsigned OffsetRegNum; // used when OffsetIsReg is true
128 bool OffsetRegShifted; // only used when OffsetIsReg is true
135 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
129136 enum ShiftType ShiftType; // used when OffsetRegShifted is true
130 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
131 bool Preindexed;
132 bool Postindexed;
133 bool Negative; // only used when OffsetIsReg is true
134 bool Writeback;
137 unsigned
138 OffsetRegShifted : 1, // only used when OffsetIsReg is true
139 Preindexed : 1,
140 Postindexed : 1,
141 OffsetIsReg : 1,
142 Negative : 1, // only used when OffsetIsReg is true
143 Writeback : 1;
135144 } Mem;
136145
137146 };
207216
208217 } // end anonymous namespace.
209218
210 // Try to parse a register name. The token must be an Identifier when called,
211 // and if it is a register name a Reg operand is created, the token is eaten
212 // and false is returned. Else true is returned and no token is eaten.
213 // TODO this is likely to change to allow different register types and or to
214 // parse for a specific register type.
215 bool ARMAsmParser::ParseRegister(ARMOperand &Op) {
219 /// Try to parse a register name. The token must be an Identifier when called,
220 /// and if it is a register name a Reg operand is created, the token is eaten
221 /// and false is returned. Else true is returned and no token is eaten.
222 /// TODO this is likely to change to allow different register types and or to
223 /// parse for a specific register type.
224 bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
216225 const AsmToken &Tok = getLexer().getTok();
217226 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
218227
226235 getLexer().Lex(); // Eat identifier token.
227236
228237 bool Writeback = false;
229 const AsmToken &ExclaimTok = getLexer().getTok();
230 if (ExclaimTok.is(AsmToken::Exclaim)) {
231 Writeback = true;
232 getLexer().Lex(); // Eat exclaim token
238 if (ParseWriteBack) {
239 const AsmToken &ExclaimTok = getLexer().getTok();
240 if (ExclaimTok.is(AsmToken::Exclaim)) {
241 Writeback = true;
242 getLexer().Lex(); // Eat exclaim token
243 }
233244 }
234245
235246 Op = ARMOperand::CreateReg(RegNum, Writeback);
237248 return false;
238249 }
239250
240 // Parse a register list, return false if successful else return true or an
241 // error. The first token must be a '{' when called.
251 /// Parse a register list, return false if successful else return true or an
252 /// error. The first token must be a '{' when called.
242253 bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
243254 assert(getLexer().getTok().is(AsmToken::LCurly) &&
244255 "Token is not an Left Curly Brace");
284295 return false;
285296 }
286297
287 // Parse an arm memory expression, return false if successful else return true
288 // or an error. The first token must be a '[' when called.
289 // TODO Only preindexing and postindexing addressing are started, unindexed
290 // with option, etc are still to do.
298 /// Parse an arm memory expression, return false if successful else return true
299 /// or an error. The first token must be a '[' when called.
300 /// TODO Only preindexing and postindexing addressing are started, unindexed
301 /// with option, etc are still to do.
291302 bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
292303 assert(getLexer().getTok().is(AsmToken::LBrac) &&
293304 "Token is not an Left Bracket");
296307 const AsmToken &BaseRegTok = getLexer().getTok();
297308 if (BaseRegTok.isNot(AsmToken::Identifier))
298309 return Error(BaseRegTok.getLoc(), "register expected");
299 int BaseRegNum = MatchRegisterName(BaseRegTok.getString());
300 if (BaseRegNum == -1)
310 if (MaybeParseRegister(Op, false))
301311 return Error(BaseRegTok.getLoc(), "register expected");
302 getLexer().Lex(); // Eat identifier token.
312 int BaseRegNum = Op.getReg();
303313
304314 bool Preindexed = false;
305315 bool Postindexed = false;
307317 bool Negative = false;
308318 bool Writeback = false;
309319
310 // First look for preindexed address forms:
311 // [Rn, +/-Rm]
312 // [Rn, #offset]
313 // [Rn, +/-Rm, shift]
314 // that is after the "[Rn" we now have see if the next token is a comma.
320 // First look for preindexed address forms, that is after the "[Rn" we now
321 // have to see if the next token is a comma.
315322 const AsmToken &Tok = getLexer().getTok();
316323 if (Tok.is(AsmToken::Comma)) {
317324 Preindexed = true;
318325 getLexer().Lex(); // Eat comma token.
319
320 const AsmToken &NextTok = getLexer().getTok();
321 if (NextTok.is(AsmToken::Plus))
322 getLexer().Lex(); // Eat plus token.
323 else if (NextTok.is(AsmToken::Minus)) {
324 Negative = true;
325 getLexer().Lex(); // Eat minus token
326 }
327
328 // See if there is a register following the "[Rn," we have so far.
329 const AsmToken &OffsetRegTok = getLexer().getTok();
330 int OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
331 bool OffsetRegShifted = false;
326 int OffsetRegNum;
327 bool OffsetRegShifted;
332328 enum ShiftType ShiftType;
333329 const MCExpr *ShiftAmount;
334330 const MCExpr *Offset;
335 if (OffsetRegNum != -1) {
336 OffsetIsReg = true;
337 getLexer().Lex(); // Eat identifier token for the offset register.
338 // Look for a comma then a shift
339 const AsmToken &Tok = getLexer().getTok();
340 if (Tok.is(AsmToken::Comma)) {
341 getLexer().Lex(); // Eat comma token.
342
343 const AsmToken &Tok = getLexer().getTok();
344 if (ParseShift(&ShiftType, ShiftAmount))
345 return Error(Tok.getLoc(), "shift expected");
346 OffsetRegShifted = true;
347 }
348 }
349 else { // "[Rn," we have so far was not followed by "Rm"
350 // Look for #offset following the "[Rn,"
351 const AsmToken &HashTok = getLexer().getTok();
352 if (HashTok.isNot(AsmToken::Hash))
353 return Error(HashTok.getLoc(), "'#' expected");
354 getLexer().Lex(); // Eat hash token.
355
356 if (getParser().ParseExpression(Offset))
357 return true;
358 }
331 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
332 Offset, OffsetIsReg, OffsetRegNum))
333 return true;
359334 const AsmToken &RBracTok = getLexer().getTok();
360335 if (RBracTok.isNot(AsmToken::RBrac))
361336 return Error(RBracTok.getLoc(), "']' expected");
373348 }
374349 // The "[Rn" we have so far was not followed by a comma.
375350 else if (Tok.is(AsmToken::RBrac)) {
376 // This is a post indexing addressing forms:
377 // [Rn], #offset
378 // [Rn], +/-Rm
379 // [Rn], +/-Rm, shift
380 // that is a ']' follows after the "[Rn".
351 // This is a post indexing addressing forms, that is a ']' follows after
352 // the "[Rn".
381353 Postindexed = true;
382354 Writeback = true;
383355 getLexer().Lex(); // Eat right bracket token.
393365 if (NextTok.isNot(AsmToken::Comma))
394366 return Error(NextTok.getLoc(), "',' expected");
395367 getLexer().Lex(); // Eat comma token.
396
397 const AsmToken &PlusMinusTok = getLexer().getTok();
398 if (PlusMinusTok.is(AsmToken::Plus))
399 getLexer().Lex(); // Eat plus token.
400 else if (PlusMinusTok.is(AsmToken::Minus)) {
401 Negative = true;
402 getLexer().Lex(); // Eat minus token
403 }
404
405 // See if there is a register following the "[Rn]," we have so far.
406 const AsmToken &OffsetRegTok = getLexer().getTok();
407 OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
408 if (OffsetRegNum != -1) {
409 OffsetIsReg = true;
410 getLexer().Lex(); // Eat identifier token for the offset register.
411 // Look for a comma then a shift
412 const AsmToken &Tok = getLexer().getTok();
413 if (Tok.is(AsmToken::Comma)) {
414 getLexer().Lex(); // Eat comma token.
415
416 const AsmToken &Tok = getLexer().getTok();
417 if (ParseShift(&ShiftType, ShiftAmount))
418 return Error(Tok.getLoc(), "shift expected");
419 OffsetRegShifted = true;
420 }
421 }
422 else { // "[Rn]," we have so far was not followed by "Rm"
423 // Look for #offset following the "[Rn],"
424 const AsmToken &HashTok = getLexer().getTok();
425 if (HashTok.isNot(AsmToken::Hash))
426 return Error(HashTok.getLoc(), "'#' expected");
427 getLexer().Lex(); // Eat hash token.
428
429 if (getParser().ParseExpression(Offset))
430 return true;
431 }
368 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
369 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum))
370 return true;
432371 }
433372
434373 Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
440379 return true;
441380 }
442381
382 /// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
383 /// we will parse the following (were +/- means that a plus or minus is
384 /// optional):
385 /// +/-Rm
386 /// +/-Rm, shift
387 /// #offset
388 /// we return false on success or an error otherwise.
389 bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
390 bool &OffsetRegShifted,
391 enum ShiftType &ShiftType,
392 const MCExpr *&ShiftAmount,
393 const MCExpr *&Offset,
394 bool &OffsetIsReg,
395 int OffsetRegNum) {
396 ARMOperand Op;
397 Negative = false;
398 OffsetRegShifted = false;
399 OffsetIsReg = false;
400 OffsetRegNum = -1;
401 const AsmToken &NextTok = getLexer().getTok();
402 if (NextTok.is(AsmToken::Plus))
403 getLexer().Lex(); // Eat plus token.
404 else if (NextTok.is(AsmToken::Minus)) {
405 Negative = true;
406 getLexer().Lex(); // Eat minus token
407 }
408 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
409 const AsmToken &OffsetRegTok = getLexer().getTok();
410 if (OffsetRegTok.is(AsmToken::Identifier)) {
411 OffsetIsReg = !MaybeParseRegister(Op, false);
412 if (OffsetIsReg)
413 OffsetRegNum = Op.getReg();
414 }
415 // If we parsed a register as the offset then their can be a shift after that
416 if (OffsetRegNum != -1) {
417 // Look for a comma then a shift
418 const AsmToken &Tok = getLexer().getTok();
419 if (Tok.is(AsmToken::Comma)) {
420 getLexer().Lex(); // Eat comma token.
421
422 const AsmToken &Tok = getLexer().getTok();
423 if (ParseShift(ShiftType, ShiftAmount))
424 return Error(Tok.getLoc(), "shift expected");
425 OffsetRegShifted = true;
426 }
427 }
428 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
429 // Look for #offset following the "[Rn," or "[Rn],"
430 const AsmToken &HashTok = getLexer().getTok();
431 if (HashTok.isNot(AsmToken::Hash))
432 return Error(HashTok.getLoc(), "'#' expected");
433 getLexer().Lex(); // Eat hash token.
434
435 if (getParser().ParseExpression(Offset))
436 return true;
437 }
438 return false;
439 }
440
443441 /// ParseShift as one of these two:
444442 /// ( lsl | lsr | asr | ror ) , # shift_amount
445443 /// rrx
446444 /// and returns true if it parses a shift otherwise it returns false.
447 bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) {
445 bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
448446 const AsmToken &Tok = getLexer().getTok();
449447 if (Tok.isNot(AsmToken::Identifier))
450448 return true;
451449 const StringRef &ShiftName = Tok.getString();
452450 if (ShiftName == "lsl" || ShiftName == "LSL")
453 *St = Lsl;
451 St = Lsl;
454452 else if (ShiftName == "lsr" || ShiftName == "LSR")
455 *St = Lsr;
453 St = Lsr;
456454 else if (ShiftName == "asr" || ShiftName == "ASR")
457 *St = Asr;
455 St = Asr;
458456 else if (ShiftName == "ror" || ShiftName == "ROR")
459 *St = Ror;
457 St = Ror;
460458 else if (ShiftName == "rrx" || ShiftName == "RRX")
461 *St = Rrx;
459 St = Rrx;
462460 else
463461 return true;
464462 getLexer().Lex(); // Eat shift type token.
465463
466 // For all but a Rotate right there must be a '#' and a shift amount
467 if (*St != Rrx) {
468 // Look for # following the shift type
469 const AsmToken &HashTok = getLexer().getTok();
470 if (HashTok.isNot(AsmToken::Hash))
471 return Error(HashTok.getLoc(), "'#' expected");
472 getLexer().Lex(); // Eat hash token.
473
474 if (getParser().ParseExpression(ShiftAmount))
475 return true;
476 }
477
478 return false;
479 }
480
481 // A hack to allow some testing, to be replaced by a real table gen version.
464 // Rrx stands alone.
465 if (St == Rrx)
466 return false;
467
468 // Otherwise, there must be a '#' and a shift amount.
469 const AsmToken &HashTok = getLexer().getTok();
470 if (HashTok.isNot(AsmToken::Hash))
471 return Error(HashTok.getLoc(), "'#' expected");
472 getLexer().Lex(); // Eat hash token.
473
474 if (getParser().ParseExpression(ShiftAmount))
475 return true;
476
477 return false;
478 }
479
480 /// A hack to allow some testing, to be replaced by a real table gen version.
482481 int ARMAsmParser::MatchRegisterName(const StringRef &Name) {
483482 if (Name == "r0" || Name == "R0")
484483 return 0;
517516 return -1;
518517 }
519518
520 // A hack to allow some testing, to be replaced by a real table gen version.
519 /// A hack to allow some testing, to be replaced by a real table gen version.
521520 bool ARMAsmParser::MatchInstruction(SmallVectorImpl &Operands,
522521 MCInst &Inst) {
523522 struct ARMOperand Op0 = Operands[0];
548547 return true;
549548 }
550549
551 // Parse a arm instruction operand. For now this parses the operand regardless
552 // of the mnemonic.
550 /// Parse a arm instruction operand. For now this parses the operand regardless
551 /// of the mnemonic.
553552 bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
554553 switch (getLexer().getKind()) {
555554 case AsmToken::Identifier:
556 if (!ParseRegister(Op))
555 if (!MaybeParseRegister(Op, true))
557556 return false;
558557 // This was not a register so parse other operands that start with an
559558 // identifier (like labels) as expressions and create them as immediates.
580579 }
581580 }
582581
583 // Parse an arm instruction mnemonic followed by its operands.
582 /// Parse an arm instruction mnemonic followed by its operands.
584583 bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
585584 SmallVector Operands;
586585
738737 return false;
739738 }
740739
741 // Force static initialization.
740 /// Force static initialization.
742741 extern "C" void LLVMInitializeARMAsmParser() {
743742 RegisterAsmParser X(TheARMTarget);
744743 RegisterAsmParser Y(TheThumbTarget);