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