1 //===-- ARMAsmLexer.cpp - Tokenize ARM assembly to AsmTokens --------------===// 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 "MCTargetDesc/ARMBaseInfo.h" 11 12 #include "llvm/MC/MCAsmInfo.h" 13 #include "llvm/MC/MCParser/MCAsmLexer.h" 14 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 15 #include "llvm/MC/MCRegisterInfo.h" 16 #include "llvm/MC/MCTargetAsmLexer.h" 17 18 #include "llvm/Support/TargetRegistry.h" 19 20 #include "llvm/ADT/OwningPtr.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/ADT/StringExtras.h" 23 #include "llvm/ADT/StringSwitch.h" 24 25 #include <string> 26 #include <map> 27 28 using namespace llvm; 29 30 namespace { 31 32 class ARMBaseAsmLexer : public MCTargetAsmLexer { 33 const MCAsmInfo &AsmInfo; 34 35 const AsmToken &lexDefinite() { 36 return getLexer()->Lex(); 37 } 38 39 AsmToken LexTokenUAL(); 40 protected: 41 typedef std::map <std::string, unsigned> rmap_ty; 42 43 rmap_ty RegisterMap; 44 45 void InitRegisterMap(const MCRegisterInfo *info) { 46 unsigned numRegs = info->getNumRegs(); 47 48 for (unsigned i = 0; i < numRegs; ++i) { 49 const char *regName = info->getName(i); 50 if (regName) 51 RegisterMap[regName] = i; 52 } 53 } 54 55 unsigned MatchRegisterName(StringRef Name) { 56 rmap_ty::iterator iter = RegisterMap.find(Name.str()); 57 if (iter != RegisterMap.end()) 58 return iter->second; 59 else 60 return 0; 61 } 62 63 AsmToken LexToken() { 64 if (!Lexer) { 65 SetError(SMLoc(), "No MCAsmLexer installed"); 66 return AsmToken(AsmToken::Error, "", 0); 67 } 68 69 switch (AsmInfo.getAssemblerDialect()) { 70 default: 71 SetError(SMLoc(), "Unhandled dialect"); 72 return AsmToken(AsmToken::Error, "", 0); 73 case 0: 74 return LexTokenUAL(); 75 } 76 } 77 public: 78 ARMBaseAsmLexer(const Target &T, const MCAsmInfo &MAI) 79 : MCTargetAsmLexer(T), AsmInfo(MAI) { 80 } 81 }; 82 83 class ARMAsmLexer : public ARMBaseAsmLexer { 84 public: 85 ARMAsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI) 86 : ARMBaseAsmLexer(T, MAI) { 87 InitRegisterMap(&MRI); 88 } 89 }; 90 91 class ThumbAsmLexer : public ARMBaseAsmLexer { 92 public: 93 ThumbAsmLexer(const Target &T, const MCRegisterInfo &MRI,const MCAsmInfo &MAI) 94 : ARMBaseAsmLexer(T, MAI) { 95 InitRegisterMap(&MRI); 96 } 97 }; 98 99 } // end anonymous namespace 100 101 AsmToken ARMBaseAsmLexer::LexTokenUAL() { 102 const AsmToken &lexedToken = lexDefinite(); 103 104 switch (lexedToken.getKind()) { 105 default: break; 106 case AsmToken::Error: 107 SetError(Lexer->getErrLoc(), Lexer->getErr()); 108 break; 109 case AsmToken::Identifier: { 110 std::string upperCase = lexedToken.getString().str(); 111 std::string lowerCase = LowercaseString(upperCase); 112 StringRef lowerRef(lowerCase); 113 114 unsigned regID = MatchRegisterName(lowerRef); 115 // Check for register aliases. 116 // r13 -> sp 117 // r14 -> lr 118 // r15 -> pc 119 // ip -> r12 120 // FIXME: Some assemblers support lots of others. Do we want them all? 121 if (!regID) { 122 regID = StringSwitch<unsigned>(lowerCase) 123 .Case("r13", ARM::SP) 124 .Case("r14", ARM::LR) 125 .Case("r15", ARM::PC) 126 .Case("ip", ARM::R12) 127 .Default(0); 128 } 129 130 if (regID) 131 return AsmToken(AsmToken::Register, 132 lexedToken.getString(), 133 static_cast<int64_t>(regID)); 134 } 135 } 136 137 return AsmToken(lexedToken); 138 } 139 140 extern "C" void LLVMInitializeARMAsmLexer() { 141 RegisterMCAsmLexer<ARMAsmLexer> X(TheARMTarget); 142 RegisterMCAsmLexer<ThumbAsmLexer> Y(TheThumbTarget); 143 } 144