ARMAsmParser.cpp revision d8d716fad3eefce98fac5a76a70250d89fcf9a20
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 delete Op; 470 } else { 471 Error(BaseRegTok.getLoc(), "register expected"); 472 return 0; 473 } 474 475 bool Preindexed = false; 476 bool Postindexed = false; 477 bool OffsetIsReg = false; 478 bool Negative = false; 479 bool Writeback = false; 480 481 // First look for preindexed address forms, that is after the "[Rn" we now 482 // have to see if the next token is a comma. 483 const AsmToken &Tok = Parser.getTok(); 484 if (Tok.is(AsmToken::Comma)) { 485 Preindexed = true; 486 Parser.Lex(); // Eat comma token. 487 int OffsetRegNum; 488 bool OffsetRegShifted; 489 enum ShiftType ShiftType; 490 const MCExpr *ShiftAmount; 491 const MCExpr *Offset; 492 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, 493 Offset, OffsetIsReg, OffsetRegNum, E)) 494 return 0; 495 const AsmToken &RBracTok = Parser.getTok(); 496 if (RBracTok.isNot(AsmToken::RBrac)) { 497 Error(RBracTok.getLoc(), "']' expected"); 498 return 0; 499 } 500 E = RBracTok.getLoc(); 501 Parser.Lex(); // Eat right bracket token. 502 503 const AsmToken &ExclaimTok = Parser.getTok(); 504 if (ExclaimTok.is(AsmToken::Exclaim)) { 505 E = ExclaimTok.getLoc(); 506 Writeback = true; 507 Parser.Lex(); // Eat exclaim token 508 } 509 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, 510 OffsetRegShifted, ShiftType, ShiftAmount, 511 Preindexed, Postindexed, Negative, Writeback, 512 S, E); 513 } 514 // The "[Rn" we have so far was not followed by a comma. 515 else if (Tok.is(AsmToken::RBrac)) { 516 // This is a post indexing addressing forms, that is a ']' follows after 517 // the "[Rn". 518 Postindexed = true; 519 Writeback = true; 520 E = Tok.getLoc(); 521 Parser.Lex(); // Eat right bracket token. 522 523 int OffsetRegNum = 0; 524 bool OffsetRegShifted = false; 525 enum ShiftType ShiftType; 526 const MCExpr *ShiftAmount; 527 const MCExpr *Offset = 0; 528 529 const AsmToken &NextTok = Parser.getTok(); 530 if (NextTok.isNot(AsmToken::EndOfStatement)) { 531 if (NextTok.isNot(AsmToken::Comma)) { 532 Error(NextTok.getLoc(), "',' expected"); 533 return 0; 534 } 535 Parser.Lex(); // Eat comma token. 536 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, 537 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, 538 E)) 539 return 0; 540 } 541 542 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, 543 OffsetRegShifted, ShiftType, ShiftAmount, 544 Preindexed, Postindexed, Negative, Writeback, 545 S, E); 546 } 547 548 return 0; 549} 550 551/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," 552/// we will parse the following (were +/- means that a plus or minus is 553/// optional): 554/// +/-Rm 555/// +/-Rm, shift 556/// #offset 557/// we return false on success or an error otherwise. 558bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, 559 bool &OffsetRegShifted, 560 enum ShiftType &ShiftType, 561 const MCExpr *&ShiftAmount, 562 const MCExpr *&Offset, 563 bool &OffsetIsReg, 564 int &OffsetRegNum, 565 SMLoc &E) { 566 Negative = false; 567 OffsetRegShifted = false; 568 OffsetIsReg = false; 569 OffsetRegNum = -1; 570 const AsmToken &NextTok = Parser.getTok(); 571 E = NextTok.getLoc(); 572 if (NextTok.is(AsmToken::Plus)) 573 Parser.Lex(); // Eat plus token. 574 else if (NextTok.is(AsmToken::Minus)) { 575 Negative = true; 576 Parser.Lex(); // Eat minus token 577 } 578 // See if there is a register following the "[Rn," or "[Rn]," we have so far. 579 const AsmToken &OffsetRegTok = Parser.getTok(); 580 if (OffsetRegTok.is(AsmToken::Identifier)) { 581 if (ARMOperand *Op = MaybeParseRegister(false)) { 582 OffsetIsReg = true; 583 E = Op->getEndLoc(); 584 OffsetRegNum = Op->getReg(); 585 delete Op; 586 } 587 } 588 // If we parsed a register as the offset then their can be a shift after that 589 if (OffsetRegNum != -1) { 590 // Look for a comma then a shift 591 const AsmToken &Tok = Parser.getTok(); 592 if (Tok.is(AsmToken::Comma)) { 593 Parser.Lex(); // Eat comma token. 594 595 const AsmToken &Tok = Parser.getTok(); 596 if (ParseShift(ShiftType, ShiftAmount, E)) 597 return Error(Tok.getLoc(), "shift expected"); 598 OffsetRegShifted = true; 599 } 600 } 601 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" 602 // Look for #offset following the "[Rn," or "[Rn]," 603 const AsmToken &HashTok = Parser.getTok(); 604 if (HashTok.isNot(AsmToken::Hash)) 605 return Error(HashTok.getLoc(), "'#' expected"); 606 607 Parser.Lex(); // Eat hash token. 608 609 if (getParser().ParseExpression(Offset)) 610 return true; 611 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 612 } 613 return false; 614} 615 616/// ParseShift as one of these two: 617/// ( lsl | lsr | asr | ror ) , # shift_amount 618/// rrx 619/// and returns true if it parses a shift otherwise it returns false. 620bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount, 621 SMLoc &E) { 622 const AsmToken &Tok = Parser.getTok(); 623 if (Tok.isNot(AsmToken::Identifier)) 624 return true; 625 StringRef ShiftName = Tok.getString(); 626 if (ShiftName == "lsl" || ShiftName == "LSL") 627 St = Lsl; 628 else if (ShiftName == "lsr" || ShiftName == "LSR") 629 St = Lsr; 630 else if (ShiftName == "asr" || ShiftName == "ASR") 631 St = Asr; 632 else if (ShiftName == "ror" || ShiftName == "ROR") 633 St = Ror; 634 else if (ShiftName == "rrx" || ShiftName == "RRX") 635 St = Rrx; 636 else 637 return true; 638 Parser.Lex(); // Eat shift type token. 639 640 // Rrx stands alone. 641 if (St == Rrx) 642 return false; 643 644 // Otherwise, there must be a '#' and a shift amount. 645 const AsmToken &HashTok = Parser.getTok(); 646 if (HashTok.isNot(AsmToken::Hash)) 647 return Error(HashTok.getLoc(), "'#' expected"); 648 Parser.Lex(); // Eat hash token. 649 650 if (getParser().ParseExpression(ShiftAmount)) 651 return true; 652 653 return false; 654} 655 656/// Parse a arm instruction operand. For now this parses the operand regardless 657/// of the mnemonic. 658ARMOperand *ARMAsmParser::ParseOperand() { 659 SMLoc S, E; 660 661 switch (getLexer().getKind()) { 662 case AsmToken::Identifier: 663 if (ARMOperand *Op = MaybeParseRegister(true)) 664 return Op; 665 666 // This was not a register so parse other operands that start with an 667 // identifier (like labels) as expressions and create them as immediates. 668 const MCExpr *IdVal; 669 S = Parser.getTok().getLoc(); 670 if (getParser().ParseExpression(IdVal)) 671 return 0; 672 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 673 return ARMOperand::CreateImm(IdVal, S, E); 674 case AsmToken::LBrac: 675 return ParseMemory(); 676 case AsmToken::LCurly: 677 return ParseRegisterList(); 678 case AsmToken::Hash: 679 // #42 -> immediate. 680 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate 681 S = Parser.getTok().getLoc(); 682 Parser.Lex(); 683 const MCExpr *ImmVal; 684 if (getParser().ParseExpression(ImmVal)) 685 return 0; 686 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 687 return ARMOperand::CreateImm(ImmVal, S, E); 688 default: 689 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 690 return 0; 691 } 692} 693 694/// Parse an arm instruction mnemonic followed by its operands. 695bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, 696 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 697 // Create the leading tokens for the mnemonic, split by '.' characters. 698 size_t Start = 0, Next = Name.find('.'); 699 StringRef Head = Name.slice(Start, Next); 700 701 // Determine the predicate, if any. 702 // 703 // FIXME: We need a way to check whether a prefix supports predication, 704 // otherwise we will end up with an ambiguity for instructions that happen to 705 // end with a predicate name. 706 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2)) 707 .Case("eq", ARMCC::EQ) 708 .Case("ne", ARMCC::NE) 709 .Case("hs", ARMCC::HS) 710 .Case("lo", ARMCC::LO) 711 .Case("mi", ARMCC::MI) 712 .Case("pl", ARMCC::PL) 713 .Case("vs", ARMCC::VS) 714 .Case("vc", ARMCC::VC) 715 .Case("hi", ARMCC::HI) 716 .Case("ls", ARMCC::LS) 717 .Case("ge", ARMCC::GE) 718 .Case("lt", ARMCC::LT) 719 .Case("gt", ARMCC::GT) 720 .Case("le", ARMCC::LE) 721 .Case("al", ARMCC::AL) 722 .Default(~0U); 723 724 if (CC != ~0U) 725 Head = Head.slice(0, Head.size() - 2); 726 else 727 CC = ARMCC::AL; 728 729 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 730 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc)); 731 732 // Add the remaining tokens in the mnemonic. 733 while (Next != StringRef::npos) { 734 Start = Next; 735 Next = Name.find('.', Start + 1); 736 Head = Name.slice(Start, Next); 737 738 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 739 } 740 741 // Read the remaining operands. 742 if (getLexer().isNot(AsmToken::EndOfStatement)) { 743 // Read the first operand. 744 if (ARMOperand *Op = ParseOperand()) 745 Operands.push_back(Op); 746 else { 747 Parser.EatToEndOfStatement(); 748 return true; 749 } 750 751 while (getLexer().is(AsmToken::Comma)) { 752 Parser.Lex(); // Eat the comma. 753 754 // Parse and remember the operand. 755 if (ARMOperand *Op = ParseOperand()) 756 Operands.push_back(Op); 757 else { 758 Parser.EatToEndOfStatement(); 759 return true; 760 } 761 } 762 } 763 764 if (getLexer().isNot(AsmToken::EndOfStatement)) { 765 Parser.EatToEndOfStatement(); 766 return TokError("unexpected token in argument list"); 767 } 768 Parser.Lex(); // Consume the EndOfStatement 769 return false; 770} 771 772bool ARMAsmParser:: 773MatchAndEmitInstruction(SMLoc IDLoc, 774 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 775 MCStreamer &Out) { 776 MCInst Inst; 777 unsigned ErrorInfo; 778 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) { 779 case Match_Success: 780 Out.EmitInstruction(Inst); 781 return false; 782 783 case Match_MissingFeature: 784 Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 785 return true; 786 case Match_InvalidOperand: { 787 SMLoc ErrorLoc = IDLoc; 788 if (ErrorInfo != ~0U) { 789 if (ErrorInfo >= Operands.size()) 790 return Error(IDLoc, "too few operands for instruction"); 791 792 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 793 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 794 } 795 796 return Error(ErrorLoc, "invalid operand for instruction"); 797 } 798 case Match_MnemonicFail: 799 return Error(IDLoc, "unrecognized instruction mnemonic"); 800 } 801 802 llvm_unreachable("Implement any new match types added!"); 803} 804 805 806 807/// ParseDirective parses the arm specific directives 808bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 809 StringRef IDVal = DirectiveID.getIdentifier(); 810 if (IDVal == ".word") 811 return ParseDirectiveWord(4, DirectiveID.getLoc()); 812 else if (IDVal == ".thumb") 813 return ParseDirectiveThumb(DirectiveID.getLoc()); 814 else if (IDVal == ".thumb_func") 815 return ParseDirectiveThumbFunc(DirectiveID.getLoc()); 816 else if (IDVal == ".code") 817 return ParseDirectiveCode(DirectiveID.getLoc()); 818 else if (IDVal == ".syntax") 819 return ParseDirectiveSyntax(DirectiveID.getLoc()); 820 return true; 821} 822 823/// ParseDirectiveWord 824/// ::= .word [ expression (, expression)* ] 825bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 826 if (getLexer().isNot(AsmToken::EndOfStatement)) { 827 for (;;) { 828 const MCExpr *Value; 829 if (getParser().ParseExpression(Value)) 830 return true; 831 832 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); 833 834 if (getLexer().is(AsmToken::EndOfStatement)) 835 break; 836 837 // FIXME: Improve diagnostic. 838 if (getLexer().isNot(AsmToken::Comma)) 839 return Error(L, "unexpected token in directive"); 840 Parser.Lex(); 841 } 842 } 843 844 Parser.Lex(); 845 return false; 846} 847 848/// ParseDirectiveThumb 849/// ::= .thumb 850bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { 851 if (getLexer().isNot(AsmToken::EndOfStatement)) 852 return Error(L, "unexpected token in directive"); 853 Parser.Lex(); 854 855 // TODO: set thumb mode 856 // TODO: tell the MC streamer the mode 857 // getParser().getStreamer().Emit???(); 858 return false; 859} 860 861/// ParseDirectiveThumbFunc 862/// ::= .thumbfunc symbol_name 863bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { 864 const AsmToken &Tok = Parser.getTok(); 865 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 866 return Error(L, "unexpected token in .syntax directive"); 867 Parser.Lex(); // Consume the identifier token. 868 869 if (getLexer().isNot(AsmToken::EndOfStatement)) 870 return Error(L, "unexpected token in directive"); 871 Parser.Lex(); 872 873 // TODO: mark symbol as a thumb symbol 874 // getParser().getStreamer().Emit???(); 875 return false; 876} 877 878/// ParseDirectiveSyntax 879/// ::= .syntax unified | divided 880bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { 881 const AsmToken &Tok = Parser.getTok(); 882 if (Tok.isNot(AsmToken::Identifier)) 883 return Error(L, "unexpected token in .syntax directive"); 884 StringRef Mode = Tok.getString(); 885 if (Mode == "unified" || Mode == "UNIFIED") 886 Parser.Lex(); 887 else if (Mode == "divided" || Mode == "DIVIDED") 888 Parser.Lex(); 889 else 890 return Error(L, "unrecognized syntax mode in .syntax directive"); 891 892 if (getLexer().isNot(AsmToken::EndOfStatement)) 893 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 894 Parser.Lex(); 895 896 // TODO tell the MC streamer the mode 897 // getParser().getStreamer().Emit???(); 898 return false; 899} 900 901/// ParseDirectiveCode 902/// ::= .code 16 | 32 903bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { 904 const AsmToken &Tok = Parser.getTok(); 905 if (Tok.isNot(AsmToken::Integer)) 906 return Error(L, "unexpected token in .code directive"); 907 int64_t Val = Parser.getTok().getIntVal(); 908 if (Val == 16) 909 Parser.Lex(); 910 else if (Val == 32) 911 Parser.Lex(); 912 else 913 return Error(L, "invalid operand to .code directive"); 914 915 if (getLexer().isNot(AsmToken::EndOfStatement)) 916 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 917 Parser.Lex(); 918 919 // TODO tell the MC streamer the mode 920 // getParser().getStreamer().Emit???(); 921 return false; 922} 923 924extern "C" void LLVMInitializeARMAsmLexer(); 925 926/// Force static initialization. 927extern "C" void LLVMInitializeARMAsmParser() { 928 RegisterAsmParser<ARMAsmParser> X(TheARMTarget); 929 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget); 930 LLVMInitializeARMAsmLexer(); 931} 932 933#define GET_REGISTER_MATCHER 934#define GET_MATCHER_IMPLEMENTATION 935#include "ARMGenAsmMatcher.inc" 936