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