ARMAsmParser.cpp revision 14b93851cc7611ae6c2000f1c162592ead954420
1//===-- ARMAsmParser.cpp - Parse ARM 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 "ARM.h" 11#include "ARMSubtarget.h" 12#include "llvm/MC/MCParser/MCAsmLexer.h" 13#include "llvm/MC/MCParser/MCAsmParser.h" 14#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 15#include "llvm/MC/MCStreamer.h" 16#include "llvm/MC/MCExpr.h" 17#include "llvm/MC/MCInst.h" 18#include "llvm/Target/TargetRegistry.h" 19#include "llvm/Target/TargetAsmParser.h" 20#include "llvm/Support/SourceMgr.h" 21#include "llvm/Support/raw_ostream.h" 22#include "llvm/ADT/SmallVector.h" 23#include "llvm/ADT/StringSwitch.h" 24#include "llvm/ADT/Twine.h" 25using namespace llvm; 26 27// The shift types for register controlled shifts in arm memory addressing 28enum ShiftType { 29 Lsl, 30 Lsr, 31 Asr, 32 Ror, 33 Rrx 34}; 35 36namespace { 37 struct ARMOperand; 38 39class ARMAsmParser : public TargetAsmParser { 40 MCAsmParser &Parser; 41 TargetMachine &TM; 42 43private: 44 MCAsmParser &getParser() const { return Parser; } 45 46 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 47 48 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } 49 50 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } 51 52 ARMOperand *MaybeParseRegister(bool ParseWriteBack); 53 ARMOperand *ParseRegisterList(); 54 ARMOperand *ParseMemory(); 55 56 bool ParseMemoryOffsetReg(bool &Negative, 57 bool &OffsetRegShifted, 58 enum ShiftType &ShiftType, 59 const MCExpr *&ShiftAmount, 60 const MCExpr *&Offset, 61 bool &OffsetIsReg, 62 int &OffsetRegNum, 63 SMLoc &E); 64 65 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E); 66 67 ARMOperand *ParseOperand(); 68 69 bool ParseDirectiveWord(unsigned Size, SMLoc L); 70 71 bool ParseDirectiveThumb(SMLoc L); 72 73 bool ParseDirectiveThumbFunc(SMLoc L); 74 75 bool ParseDirectiveCode(SMLoc L); 76 77 bool ParseDirectiveSyntax(SMLoc L); 78 79 bool MatchAndEmitInstruction(SMLoc IDLoc, 80 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 81 MCStreamer &Out); 82 83 /// @name Auto-generated Match Functions 84 /// { 85 86#define GET_ASSEMBLER_HEADER 87#include "ARMGenAsmMatcher.inc" 88 89 /// } 90 91 92public: 93 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) 94 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {} 95 96 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, 97 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 98 99 virtual bool ParseDirective(AsmToken DirectiveID); 100}; 101} // end anonymous namespace 102 103namespace { 104 105/// ARMOperand - Instances of this class represent a parsed ARM machine 106/// instruction. 107struct ARMOperand : public MCParsedAsmOperand { 108public: 109 enum KindTy { 110 CondCode, 111 Immediate, 112 Memory, 113 Register, 114 Token 115 } Kind; 116 117 SMLoc StartLoc, EndLoc; 118 119 union { 120 struct { 121 ARMCC::CondCodes Val; 122 } CC; 123 124 struct { 125 const char *Data; 126 unsigned Length; 127 } Tok; 128 129 struct { 130 unsigned RegNum; 131 bool Writeback; 132 } Reg; 133 134 struct { 135 const MCExpr *Val; 136 } Imm; 137 138 // This is for all forms of ARM address expressions 139 struct { 140 unsigned BaseRegNum; 141 unsigned OffsetRegNum; // used when OffsetIsReg is true 142 const MCExpr *Offset; // used when OffsetIsReg is false 143 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true 144 enum ShiftType ShiftType; // used when OffsetRegShifted is true 145 unsigned 146 OffsetRegShifted : 1, // only used when OffsetIsReg is true 147 Preindexed : 1, 148 Postindexed : 1, 149 OffsetIsReg : 1, 150 Negative : 1, // only used when OffsetIsReg is true 151 Writeback : 1; 152 } Mem; 153 154 }; 155 156 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { 157 Kind = o.Kind; 158 StartLoc = o.StartLoc; 159 EndLoc = o.EndLoc; 160 switch (Kind) { 161 case CondCode: 162 CC = o.CC; 163 break; 164 case Token: 165 Tok = o.Tok; 166 break; 167 case Register: 168 Reg = o.Reg; 169 break; 170 case Immediate: 171 Imm = o.Imm; 172 break; 173 case Memory: 174 Mem = o.Mem; 175 break; 176 } 177 } 178 179 /// getStartLoc - Get the location of the first token of this operand. 180 SMLoc getStartLoc() const { return StartLoc; } 181 /// getEndLoc - Get the location of the last token of this operand. 182 SMLoc getEndLoc() const { return EndLoc; } 183 184 ARMCC::CondCodes getCondCode() const { 185 assert(Kind == CondCode && "Invalid access!"); 186 return CC.Val; 187 } 188 189 StringRef getToken() const { 190 assert(Kind == Token && "Invalid access!"); 191 return StringRef(Tok.Data, Tok.Length); 192 } 193 194 unsigned getReg() const { 195 assert(Kind == Register && "Invalid access!"); 196 return Reg.RegNum; 197 } 198 199 const MCExpr *getImm() const { 200 assert(Kind == Immediate && "Invalid access!"); 201 return Imm.Val; 202 } 203 204 bool isCondCode() const { return Kind == CondCode; } 205 bool isImm() const { return Kind == Immediate; } 206 bool isReg() const { return Kind == Register; } 207 bool isToken() const { return Kind == Token; } 208 bool isMemory() const { return Kind == Memory; } 209 210 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 211 // Add as immediates when possible. Null MCExpr = 0. 212 if (Expr == 0) 213 Inst.addOperand(MCOperand::CreateImm(0)); 214 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 215 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 216 else 217 Inst.addOperand(MCOperand::CreateExpr(Expr)); 218 } 219 220 void addCondCodeOperands(MCInst &Inst, unsigned N) const { 221 assert(N == 2 && "Invalid number of operands!"); 222 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 223 // FIXME: What belongs here? 224 Inst.addOperand(MCOperand::CreateReg(0)); 225 } 226 227 void addRegOperands(MCInst &Inst, unsigned N) const { 228 assert(N == 1 && "Invalid number of operands!"); 229 Inst.addOperand(MCOperand::CreateReg(getReg())); 230 } 231 232 void addImmOperands(MCInst &Inst, unsigned N) const { 233 assert(N == 1 && "Invalid number of operands!"); 234 addExpr(Inst, getImm()); 235 } 236 237 238 bool isMemMode5() const { 239 // FIXME: Is this right? What about postindexed and Writeback? 240 if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted || 241 Mem.Preindexed || Mem.Negative) 242 return false; 243 244 return true; 245 } 246 247 void addMemMode5Operands(MCInst &Inst, unsigned N) const { 248 assert(N == 2 && isMemMode5() && "Invalid number of operands!"); 249 250 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); 251 assert(!Mem.OffsetIsReg && "invalid mode 5 operand"); 252 addExpr(Inst, Mem.Offset); 253 } 254 255 virtual void dump(raw_ostream &OS) const; 256 257 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { 258 ARMOperand *Op = new ARMOperand(CondCode); 259 Op->CC.Val = CC; 260 Op->StartLoc = S; 261 Op->EndLoc = S; 262 return Op; 263 } 264 265 static ARMOperand *CreateToken(StringRef Str, SMLoc S) { 266 ARMOperand *Op = new ARMOperand(Token); 267 Op->Tok.Data = Str.data(); 268 Op->Tok.Length = Str.size(); 269 Op->StartLoc = S; 270 Op->EndLoc = S; 271 return Op; 272 } 273 274 static ARMOperand *CreateReg(unsigned RegNum, bool Writeback, SMLoc S, 275 SMLoc E) { 276 ARMOperand *Op = new ARMOperand(Register); 277 Op->Reg.RegNum = RegNum; 278 Op->Reg.Writeback = Writeback; 279 Op->StartLoc = S; 280 Op->EndLoc = E; 281 return Op; 282 } 283 284 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 285 ARMOperand *Op = new ARMOperand(Immediate); 286 Op->Imm.Val = Val; 287 Op->StartLoc = S; 288 Op->EndLoc = E; 289 return Op; 290 } 291 292 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg, 293 const MCExpr *Offset, unsigned OffsetRegNum, 294 bool OffsetRegShifted, enum ShiftType ShiftType, 295 const MCExpr *ShiftAmount, bool Preindexed, 296 bool Postindexed, bool Negative, bool Writeback, 297 SMLoc S, SMLoc E) { 298 ARMOperand *Op = new ARMOperand(Memory); 299 Op->Mem.BaseRegNum = BaseRegNum; 300 Op->Mem.OffsetIsReg = OffsetIsReg; 301 Op->Mem.Offset = Offset; 302 Op->Mem.OffsetRegNum = OffsetRegNum; 303 Op->Mem.OffsetRegShifted = OffsetRegShifted; 304 Op->Mem.ShiftType = ShiftType; 305 Op->Mem.ShiftAmount = ShiftAmount; 306 Op->Mem.Preindexed = Preindexed; 307 Op->Mem.Postindexed = Postindexed; 308 Op->Mem.Negative = Negative; 309 Op->Mem.Writeback = Writeback; 310 311 Op->StartLoc = S; 312 Op->EndLoc = E; 313 return Op; 314 } 315 316private: 317 ARMOperand(KindTy K) : Kind(K) {} 318}; 319 320} // end anonymous namespace. 321 322void ARMOperand::dump(raw_ostream &OS) const { 323 switch (Kind) { 324 case CondCode: 325 OS << ARMCondCodeToString(getCondCode()); 326 break; 327 case Immediate: 328 getImm()->print(OS); 329 break; 330 case Memory: 331 OS << "<memory>"; 332 break; 333 case Register: 334 OS << "<register " << getReg() << ">"; 335 break; 336 case Token: 337 OS << "'" << getToken() << "'"; 338 break; 339 } 340} 341 342/// @name Auto-generated Match Functions 343/// { 344 345static unsigned MatchRegisterName(StringRef Name); 346 347/// } 348 349/// Try to parse a register name. The token must be an Identifier when called, 350/// and if it is a register name the token is eaten and a Reg operand is created 351/// and returned. Otherwise return null. 352/// 353/// TODO this is likely to change to allow different register types and or to 354/// parse for a specific register type. 355ARMOperand *ARMAsmParser::MaybeParseRegister(bool ParseWriteBack) { 356 SMLoc S, E; 357 const AsmToken &Tok = Parser.getTok(); 358 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 359 360 // FIXME: Validate register for the current architecture; we have to do 361 // validation later, so maybe there is no need for this here. 362 int RegNum; 363 364 RegNum = MatchRegisterName(Tok.getString()); 365 if (RegNum == -1) 366 return 0; 367 368 S = Tok.getLoc(); 369 370 Parser.Lex(); // Eat identifier token. 371 372 E = Parser.getTok().getLoc(); 373 374 bool Writeback = false; 375 if (ParseWriteBack) { 376 const AsmToken &ExclaimTok = Parser.getTok(); 377 if (ExclaimTok.is(AsmToken::Exclaim)) { 378 E = ExclaimTok.getLoc(); 379 Writeback = true; 380 Parser.Lex(); // Eat exclaim token 381 } 382 } 383 384 return ARMOperand::CreateReg(RegNum, Writeback, S, E); 385} 386 387/// Parse a register list, return it if successful else return null. The first 388/// token must be a '{' when called. 389ARMOperand *ARMAsmParser::ParseRegisterList() { 390 SMLoc S, E; 391 assert(Parser.getTok().is(AsmToken::LCurly) && 392 "Token is not an Left Curly Brace"); 393 S = Parser.getTok().getLoc(); 394 Parser.Lex(); // Eat left curly brace token. 395 396 const AsmToken &RegTok = Parser.getTok(); 397 SMLoc RegLoc = RegTok.getLoc(); 398 if (RegTok.isNot(AsmToken::Identifier)) { 399 Error(RegLoc, "register expected"); 400 return 0; 401 } 402 int RegNum = MatchRegisterName(RegTok.getString()); 403 if (RegNum == -1) { 404 Error(RegLoc, "register expected"); 405 return 0; 406 } 407 408 Parser.Lex(); // Eat identifier token. 409 unsigned RegList = 1 << RegNum; 410 411 int HighRegNum = RegNum; 412 // TODO ranges like "{Rn-Rm}" 413 while (Parser.getTok().is(AsmToken::Comma)) { 414 Parser.Lex(); // Eat comma token. 415 416 const AsmToken &RegTok = Parser.getTok(); 417 SMLoc RegLoc = RegTok.getLoc(); 418 if (RegTok.isNot(AsmToken::Identifier)) { 419 Error(RegLoc, "register expected"); 420 return 0; 421 } 422 int RegNum = MatchRegisterName(RegTok.getString()); 423 if (RegNum == -1) { 424 Error(RegLoc, "register expected"); 425 return 0; 426 } 427 428 if (RegList & (1 << RegNum)) 429 Warning(RegLoc, "register duplicated in register list"); 430 else if (RegNum <= HighRegNum) 431 Warning(RegLoc, "register not in ascending order in register list"); 432 RegList |= 1 << RegNum; 433 HighRegNum = RegNum; 434 435 Parser.Lex(); // Eat identifier token. 436 } 437 const AsmToken &RCurlyTok = Parser.getTok(); 438 if (RCurlyTok.isNot(AsmToken::RCurly)) { 439 Error(RCurlyTok.getLoc(), "'}' expected"); 440 return 0; 441 } 442 E = RCurlyTok.getLoc(); 443 Parser.Lex(); // Eat left curly brace token. 444 445 // FIXME: Need to return an operand! 446 Error(E, "FIXME: register list parsing not implemented"); 447 return 0; 448} 449 450/// Parse an arm memory expression, return false if successful else return true 451/// or an error. The first token must be a '[' when called. 452/// TODO Only preindexing and postindexing addressing are started, unindexed 453/// with option, etc are still to do. 454ARMOperand *ARMAsmParser::ParseMemory() { 455 SMLoc S, E; 456 assert(Parser.getTok().is(AsmToken::LBrac) && 457 "Token is not an Left Bracket"); 458 S = Parser.getTok().getLoc(); 459 Parser.Lex(); // Eat left bracket token. 460 461 const AsmToken &BaseRegTok = Parser.getTok(); 462 if (BaseRegTok.isNot(AsmToken::Identifier)) { 463 Error(BaseRegTok.getLoc(), "register expected"); 464 return 0; 465 } 466 int BaseRegNum = 0; 467 if (ARMOperand *Op = MaybeParseRegister(false)) 468 BaseRegNum = Op->getReg(); 469 else { 470 Error(BaseRegTok.getLoc(), "register expected"); 471 return 0; 472 } 473 474 bool Preindexed = false; 475 bool Postindexed = false; 476 bool OffsetIsReg = false; 477 bool Negative = false; 478 bool Writeback = false; 479 480 // First look for preindexed address forms, that is after the "[Rn" we now 481 // have to see if the next token is a comma. 482 const AsmToken &Tok = Parser.getTok(); 483 if (Tok.is(AsmToken::Comma)) { 484 Preindexed = true; 485 Parser.Lex(); // Eat comma token. 486 int OffsetRegNum; 487 bool OffsetRegShifted; 488 enum ShiftType ShiftType; 489 const MCExpr *ShiftAmount; 490 const MCExpr *Offset; 491 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, 492 Offset, OffsetIsReg, OffsetRegNum, E)) 493 return 0; 494 const AsmToken &RBracTok = Parser.getTok(); 495 if (RBracTok.isNot(AsmToken::RBrac)) { 496 Error(RBracTok.getLoc(), "']' expected"); 497 return 0; 498 } 499 E = RBracTok.getLoc(); 500 Parser.Lex(); // Eat right bracket token. 501 502 const AsmToken &ExclaimTok = Parser.getTok(); 503 if (ExclaimTok.is(AsmToken::Exclaim)) { 504 E = ExclaimTok.getLoc(); 505 Writeback = true; 506 Parser.Lex(); // Eat exclaim token 507 } 508 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, 509 OffsetRegShifted, ShiftType, ShiftAmount, 510 Preindexed, Postindexed, Negative, Writeback, 511 S, E); 512 } 513 // The "[Rn" we have so far was not followed by a comma. 514 else if (Tok.is(AsmToken::RBrac)) { 515 // This is a post indexing addressing forms, that is a ']' follows after 516 // the "[Rn". 517 Postindexed = true; 518 Writeback = true; 519 E = Tok.getLoc(); 520 Parser.Lex(); // Eat right bracket token. 521 522 int OffsetRegNum = 0; 523 bool OffsetRegShifted = false; 524 enum ShiftType ShiftType; 525 const MCExpr *ShiftAmount; 526 const MCExpr *Offset = 0; 527 528 const AsmToken &NextTok = Parser.getTok(); 529 if (NextTok.isNot(AsmToken::EndOfStatement)) { 530 if (NextTok.isNot(AsmToken::Comma)) { 531 Error(NextTok.getLoc(), "',' expected"); 532 return 0; 533 } 534 Parser.Lex(); // Eat comma token. 535 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, 536 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, 537 E)) 538 return 0; 539 } 540 541 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, 542 OffsetRegShifted, ShiftType, ShiftAmount, 543 Preindexed, Postindexed, Negative, Writeback, 544 S, E); 545 } 546 547 return 0; 548} 549 550/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," 551/// we will parse the following (were +/- means that a plus or minus is 552/// optional): 553/// +/-Rm 554/// +/-Rm, shift 555/// #offset 556/// we return false on success or an error otherwise. 557bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, 558 bool &OffsetRegShifted, 559 enum ShiftType &ShiftType, 560 const MCExpr *&ShiftAmount, 561 const MCExpr *&Offset, 562 bool &OffsetIsReg, 563 int &OffsetRegNum, 564 SMLoc &E) { 565 Negative = false; 566 OffsetRegShifted = false; 567 OffsetIsReg = false; 568 OffsetRegNum = -1; 569 const AsmToken &NextTok = Parser.getTok(); 570 E = NextTok.getLoc(); 571 if (NextTok.is(AsmToken::Plus)) 572 Parser.Lex(); // Eat plus token. 573 else if (NextTok.is(AsmToken::Minus)) { 574 Negative = true; 575 Parser.Lex(); // Eat minus token 576 } 577 // See if there is a register following the "[Rn," or "[Rn]," we have so far. 578 const AsmToken &OffsetRegTok = Parser.getTok(); 579 if (OffsetRegTok.is(AsmToken::Identifier)) { 580 if (ARMOperand *Op = MaybeParseRegister(false)) { 581 OffsetIsReg = true; 582 E = Op->getEndLoc(); 583 OffsetRegNum = Op->getReg(); 584 delete Op; 585 } 586 } 587 // If we parsed a register as the offset then their can be a shift after that 588 if (OffsetRegNum != -1) { 589 // Look for a comma then a shift 590 const AsmToken &Tok = Parser.getTok(); 591 if (Tok.is(AsmToken::Comma)) { 592 Parser.Lex(); // Eat comma token. 593 594 const AsmToken &Tok = Parser.getTok(); 595 if (ParseShift(ShiftType, ShiftAmount, E)) 596 return Error(Tok.getLoc(), "shift expected"); 597 OffsetRegShifted = true; 598 } 599 } 600 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" 601 // Look for #offset following the "[Rn," or "[Rn]," 602 const AsmToken &HashTok = Parser.getTok(); 603 if (HashTok.isNot(AsmToken::Hash)) 604 return Error(HashTok.getLoc(), "'#' expected"); 605 606 Parser.Lex(); // Eat hash token. 607 608 if (getParser().ParseExpression(Offset)) 609 return true; 610 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 611 } 612 return false; 613} 614 615/// ParseShift as one of these two: 616/// ( lsl | lsr | asr | ror ) , # shift_amount 617/// rrx 618/// and returns true if it parses a shift otherwise it returns false. 619bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount, 620 SMLoc &E) { 621 const AsmToken &Tok = Parser.getTok(); 622 if (Tok.isNot(AsmToken::Identifier)) 623 return true; 624 StringRef ShiftName = Tok.getString(); 625 if (ShiftName == "lsl" || ShiftName == "LSL") 626 St = Lsl; 627 else if (ShiftName == "lsr" || ShiftName == "LSR") 628 St = Lsr; 629 else if (ShiftName == "asr" || ShiftName == "ASR") 630 St = Asr; 631 else if (ShiftName == "ror" || ShiftName == "ROR") 632 St = Ror; 633 else if (ShiftName == "rrx" || ShiftName == "RRX") 634 St = Rrx; 635 else 636 return true; 637 Parser.Lex(); // Eat shift type token. 638 639 // Rrx stands alone. 640 if (St == Rrx) 641 return false; 642 643 // Otherwise, there must be a '#' and a shift amount. 644 const AsmToken &HashTok = Parser.getTok(); 645 if (HashTok.isNot(AsmToken::Hash)) 646 return Error(HashTok.getLoc(), "'#' expected"); 647 Parser.Lex(); // Eat hash token. 648 649 if (getParser().ParseExpression(ShiftAmount)) 650 return true; 651 652 return false; 653} 654 655/// Parse a arm instruction operand. For now this parses the operand regardless 656/// of the mnemonic. 657ARMOperand *ARMAsmParser::ParseOperand() { 658 SMLoc S, E; 659 660 switch (getLexer().getKind()) { 661 case AsmToken::Identifier: 662 if (ARMOperand *Op = MaybeParseRegister(true)) 663 return Op; 664 665 // This was not a register so parse other operands that start with an 666 // identifier (like labels) as expressions and create them as immediates. 667 const MCExpr *IdVal; 668 S = Parser.getTok().getLoc(); 669 if (getParser().ParseExpression(IdVal)) 670 return 0; 671 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 672 return ARMOperand::CreateImm(IdVal, S, E); 673 case AsmToken::LBrac: 674 return ParseMemory(); 675 case AsmToken::LCurly: 676 return ParseRegisterList(); 677 case AsmToken::Hash: 678 // #42 -> immediate. 679 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate 680 S = Parser.getTok().getLoc(); 681 Parser.Lex(); 682 const MCExpr *ImmVal; 683 if (getParser().ParseExpression(ImmVal)) 684 return 0; 685 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 686 return ARMOperand::CreateImm(ImmVal, S, E); 687 default: 688 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 689 return 0; 690 } 691} 692 693/// Parse an arm instruction mnemonic followed by its operands. 694bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, 695 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 696 // Create the leading tokens for the mnemonic, split by '.' characters. 697 size_t Start = 0, Next = Name.find('.'); 698 StringRef Head = Name.slice(Start, Next); 699 700 // Determine the predicate, if any. 701 // 702 // FIXME: We need a way to check whether a prefix supports predication, 703 // otherwise we will end up with an ambiguity for instructions that happen to 704 // end with a predicate name. 705 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2)) 706 .Case("eq", ARMCC::EQ) 707 .Case("ne", ARMCC::NE) 708 .Case("hs", ARMCC::HS) 709 .Case("lo", ARMCC::LO) 710 .Case("mi", ARMCC::MI) 711 .Case("pl", ARMCC::PL) 712 .Case("vs", ARMCC::VS) 713 .Case("vc", ARMCC::VC) 714 .Case("hi", ARMCC::HI) 715 .Case("ls", ARMCC::LS) 716 .Case("ge", ARMCC::GE) 717 .Case("lt", ARMCC::LT) 718 .Case("gt", ARMCC::GT) 719 .Case("le", ARMCC::LE) 720 .Case("al", ARMCC::AL) 721 .Default(~0U); 722 723 if (CC != ~0U) 724 Head = Head.slice(0, Head.size() - 2); 725 else 726 CC = ARMCC::AL; 727 728 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 729 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc)); 730 731 // Add the remaining tokens in the mnemonic. 732 while (Next != StringRef::npos) { 733 Start = Next; 734 Next = Name.find('.', Start + 1); 735 Head = Name.slice(Start, Next); 736 737 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 738 } 739 740 // Read the remaining operands. 741 if (getLexer().isNot(AsmToken::EndOfStatement)) { 742 // Read the first operand. 743 if (ARMOperand *Op = ParseOperand()) 744 Operands.push_back(Op); 745 else { 746 Parser.EatToEndOfStatement(); 747 return true; 748 } 749 750 while (getLexer().is(AsmToken::Comma)) { 751 Parser.Lex(); // Eat the comma. 752 753 // Parse and remember the operand. 754 if (ARMOperand *Op = ParseOperand()) 755 Operands.push_back(Op); 756 else { 757 Parser.EatToEndOfStatement(); 758 return true; 759 } 760 } 761 } 762 763 if (getLexer().isNot(AsmToken::EndOfStatement)) { 764 Parser.EatToEndOfStatement(); 765 return TokError("unexpected token in argument list"); 766 } 767 Parser.Lex(); // Consume the EndOfStatement 768 return false; 769} 770 771bool ARMAsmParser:: 772MatchAndEmitInstruction(SMLoc IDLoc, 773 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 774 MCStreamer &Out) { 775 MCInst Inst; 776 unsigned ErrorInfo; 777 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) { 778 case Match_Success: 779 Out.EmitInstruction(Inst); 780 return false; 781 782 case Match_MissingFeature: 783 Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 784 return true; 785 case Match_InvalidOperand: { 786 SMLoc ErrorLoc = IDLoc; 787 if (ErrorInfo != ~0U) { 788 if (ErrorInfo >= Operands.size()) 789 return Error(IDLoc, "too few operands for instruction"); 790 791 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 792 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 793 } 794 795 return Error(ErrorLoc, "invalid operand for instruction"); 796 } 797 case Match_MnemonicFail: 798 return Error(IDLoc, "unrecognized instruction mnemonic"); 799 } 800} 801 802 803 804/// ParseDirective parses the arm specific directives 805bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 806 StringRef IDVal = DirectiveID.getIdentifier(); 807 if (IDVal == ".word") 808 return ParseDirectiveWord(4, DirectiveID.getLoc()); 809 else if (IDVal == ".thumb") 810 return ParseDirectiveThumb(DirectiveID.getLoc()); 811 else if (IDVal == ".thumb_func") 812 return ParseDirectiveThumbFunc(DirectiveID.getLoc()); 813 else if (IDVal == ".code") 814 return ParseDirectiveCode(DirectiveID.getLoc()); 815 else if (IDVal == ".syntax") 816 return ParseDirectiveSyntax(DirectiveID.getLoc()); 817 return true; 818} 819 820/// ParseDirectiveWord 821/// ::= .word [ expression (, expression)* ] 822bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 823 if (getLexer().isNot(AsmToken::EndOfStatement)) { 824 for (;;) { 825 const MCExpr *Value; 826 if (getParser().ParseExpression(Value)) 827 return true; 828 829 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); 830 831 if (getLexer().is(AsmToken::EndOfStatement)) 832 break; 833 834 // FIXME: Improve diagnostic. 835 if (getLexer().isNot(AsmToken::Comma)) 836 return Error(L, "unexpected token in directive"); 837 Parser.Lex(); 838 } 839 } 840 841 Parser.Lex(); 842 return false; 843} 844 845/// ParseDirectiveThumb 846/// ::= .thumb 847bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { 848 if (getLexer().isNot(AsmToken::EndOfStatement)) 849 return Error(L, "unexpected token in directive"); 850 Parser.Lex(); 851 852 // TODO: set thumb mode 853 // TODO: tell the MC streamer the mode 854 // getParser().getStreamer().Emit???(); 855 return false; 856} 857 858/// ParseDirectiveThumbFunc 859/// ::= .thumbfunc symbol_name 860bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { 861 const AsmToken &Tok = Parser.getTok(); 862 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 863 return Error(L, "unexpected token in .syntax directive"); 864 Parser.Lex(); // Consume the identifier token. 865 866 if (getLexer().isNot(AsmToken::EndOfStatement)) 867 return Error(L, "unexpected token in directive"); 868 Parser.Lex(); 869 870 // TODO: mark symbol as a thumb symbol 871 // getParser().getStreamer().Emit???(); 872 return false; 873} 874 875/// ParseDirectiveSyntax 876/// ::= .syntax unified | divided 877bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { 878 const AsmToken &Tok = Parser.getTok(); 879 if (Tok.isNot(AsmToken::Identifier)) 880 return Error(L, "unexpected token in .syntax directive"); 881 StringRef Mode = Tok.getString(); 882 if (Mode == "unified" || Mode == "UNIFIED") 883 Parser.Lex(); 884 else if (Mode == "divided" || Mode == "DIVIDED") 885 Parser.Lex(); 886 else 887 return Error(L, "unrecognized syntax mode in .syntax directive"); 888 889 if (getLexer().isNot(AsmToken::EndOfStatement)) 890 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 891 Parser.Lex(); 892 893 // TODO tell the MC streamer the mode 894 // getParser().getStreamer().Emit???(); 895 return false; 896} 897 898/// ParseDirectiveCode 899/// ::= .code 16 | 32 900bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { 901 const AsmToken &Tok = Parser.getTok(); 902 if (Tok.isNot(AsmToken::Integer)) 903 return Error(L, "unexpected token in .code directive"); 904 int64_t Val = Parser.getTok().getIntVal(); 905 if (Val == 16) 906 Parser.Lex(); 907 else if (Val == 32) 908 Parser.Lex(); 909 else 910 return Error(L, "invalid operand to .code directive"); 911 912 if (getLexer().isNot(AsmToken::EndOfStatement)) 913 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 914 Parser.Lex(); 915 916 // TODO tell the MC streamer the mode 917 // getParser().getStreamer().Emit???(); 918 return false; 919} 920 921extern "C" void LLVMInitializeARMAsmLexer(); 922 923/// Force static initialization. 924extern "C" void LLVMInitializeARMAsmParser() { 925 RegisterAsmParser<ARMAsmParser> X(TheARMTarget); 926 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget); 927 LLVMInitializeARMAsmLexer(); 928} 929 930#define GET_REGISTER_MATCHER 931#define GET_MATCHER_IMPLEMENTATION 932#include "ARMGenAsmMatcher.inc" 933