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