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