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