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