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