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