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