1Pull in r198658 from upstream llvm trunk: 2 3 [Sparc] Add support for parsing memory operands in sparc AsmParser. 4 5Introduced here: http://svnweb.freebsd.org/changeset/base/262261 6 7Index: test/MC/Sparc/sparc-ctrl-instructions.s 8=================================================================== 9--- test/MC/Sparc/sparc-ctrl-instructions.s 10+++ test/MC/Sparc/sparc-ctrl-instructions.s 11@@ -0,0 +1,23 @@ 12+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s 13+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s 14+ 15+ ! CHECK: call foo 16+ call foo 17+ 18+ ! CHECK: call %g1+%i2 19+ call %g1 + %i2 20+ 21+ ! CHECK: call %o1+8 22+ call %o1 + 8 23+ 24+ ! CHECK: call %g1 25+ call %g1 26+ 27+ ! CHECK: jmp %g1+%i2 28+ jmp %g1 + %i2 29+ 30+ ! CHECK: jmp %o1+8 31+ jmp %o1 + 8 32+ 33+ ! CHECK: jmp %g1 34+ jmp %g1 35Index: test/MC/Sparc/sparc-mem-instructions.s 36=================================================================== 37--- test/MC/Sparc/sparc-mem-instructions.s 38+++ test/MC/Sparc/sparc-mem-instructions.s 39@@ -0,0 +1,58 @@ 40+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s 41+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s 42+ 43+ ! CHECK: ldsb [%i0+%l6], %o2 ! encoding: [0xd4,0x4e,0x00,0x16] 44+ ldsb [%i0 + %l6], %o2 45+ ! CHECK: ldsb [%i0+32], %o2 ! encoding: [0xd4,0x4e,0x20,0x20] 46+ ldsb [%i0 + 32], %o2 47+ ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x60,0x00] 48+ ldsb [%g1], %o4 49+ 50+ ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16] 51+ ldsh [%i0 + %l6], %o2 52+ ! CHECK: ldsh [%i0+32], %o2 ! encoding: [0xd4,0x56,0x20,0x20] 53+ ldsh [%i0 + 32], %o2 54+ ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x60,0x00] 55+ ldsh [%g1], %o4 56+ 57+ ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16] 58+ ldub [%i0 + %l6], %o2 59+ ! CHECK: ldub [%i0+32], %o2 ! encoding: [0xd4,0x0e,0x20,0x20] 60+ ldub [%i0 + 32], %o2 61+ ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x60,0x00] 62+ ldub [%g1], %o2 63+ 64+ ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16] 65+ lduh [%i0 + %l6], %o2 66+ ! CHECK: lduh [%i0+32], %o2 ! encoding: [0xd4,0x16,0x20,0x20] 67+ lduh [%i0 + 32], %o2 68+ ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x60,0x00] 69+ lduh [%g1], %o2 70+ 71+ ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16] 72+ ld [%i0 + %l6], %o2 73+ ! CHECK: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20] 74+ ld [%i0 + 32], %o2 75+ ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x60,0x00] 76+ ld [%g1], %o2 77+ 78+ ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16] 79+ stb %o2, [%i0 + %l6] 80+ ! CHECK: stb %o2, [%i0+32] ! encoding: [0xd4,0x2e,0x20,0x20] 81+ stb %o2, [%i0 + 32] 82+ ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x60,0x00] 83+ stb %o2, [%g1] 84+ 85+ ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16] 86+ sth %o2, [%i0 + %l6] 87+ ! CHECK: sth %o2, [%i0+32] ! encoding: [0xd4,0x36,0x20,0x20] 88+ sth %o2, [%i0 + 32] 89+ ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x60,0x00] 90+ sth %o2, [%g1] 91+ 92+ ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16] 93+ st %o2, [%i0 + %l6] 94+ ! CHECK: st %o2, [%i0+32] ! encoding: [0xd4,0x26,0x20,0x20] 95+ st %o2, [%i0 + 32] 96+ ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x60,0x00] 97+ st %o2, [%g1] 98Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 99=================================================================== 100--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 101+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp 102@@ -28,6 +28,7 @@ namespace llvm { 103 } 104 105 namespace { 106+class SparcOperand; 107 class SparcAsmParser : public MCTargetAsmParser { 108 109 MCSubtargetInfo &STI; 110@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser { 111 112 // Custom parse functions for Sparc specific operands. 113 OperandMatchResultTy 114- parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 115- OperandMatchResultTy 116- parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 117+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 118 119 OperandMatchResultTy 120- parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 121- int ImmOffsetOrReg); 122- 123- OperandMatchResultTy 124 parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 125 StringRef Name); 126 127+ OperandMatchResultTy 128+ parseSparcAsmOperand(SparcOperand *&Operand); 129+ 130 // returns true if Tok is matched to a register and returns register in RegNo. 131 bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, 132 bool isQFP); 133@@ -298,7 +296,35 @@ class SparcOperand : public MCParsedAsmOperand { 134 return Op; 135 } 136 137+ static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) { 138+ unsigned offsetReg = Op->getReg(); 139+ Op->Kind = k_MemoryReg; 140+ Op->Mem.Base = Base; 141+ Op->Mem.OffsetReg = offsetReg; 142+ Op->Mem.Off = 0; 143+ return Op; 144+ } 145 146+ static SparcOperand *CreateMEMri(unsigned Base, 147+ const MCExpr *Off, 148+ SMLoc S, SMLoc E) { 149+ SparcOperand *Op = new SparcOperand(k_MemoryImm); 150+ Op->Mem.Base = Base; 151+ Op->Mem.OffsetReg = 0; 152+ Op->Mem.Off = Off; 153+ Op->StartLoc = S; 154+ Op->EndLoc = E; 155+ return Op; 156+ } 157+ 158+ static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) { 159+ const MCExpr *Imm = Op->getImm(); 160+ Op->Kind = k_MemoryImm; 161+ Op->Mem.Base = Base; 162+ Op->Mem.OffsetReg = 0; 163+ Op->Mem.Off = Imm; 164+ return Op; 165+ } 166 }; 167 168 } // end namespace 169@@ -412,23 +438,42 @@ ParseDirective(AsmToken DirectiveID) 170 } 171 172 SparcAsmParser::OperandMatchResultTy SparcAsmParser:: 173-parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 174- int ImmOffsetOrReg) 175+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) 176 { 177- // FIXME: Implement memory operand parsing here. 178- return MatchOperand_NoMatch; 179-} 180 181-SparcAsmParser::OperandMatchResultTy SparcAsmParser:: 182-parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) 183-{ 184- return parseMEMOperand(Operands, 2); 185-} 186+ SMLoc S, E; 187+ unsigned BaseReg = 0; 188 189-SparcAsmParser::OperandMatchResultTy SparcAsmParser:: 190-parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) 191-{ 192- return parseMEMOperand(Operands, 1); 193+ if (ParseRegister(BaseReg, S, E)) { 194+ return MatchOperand_NoMatch; 195+ } 196+ 197+ switch (getLexer().getKind()) { 198+ default: return MatchOperand_NoMatch; 199+ 200+ case AsmToken::RBrac: 201+ case AsmToken::EndOfStatement: 202+ Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); 203+ return MatchOperand_Success; 204+ 205+ case AsmToken:: Plus: 206+ Parser.Lex(); // Eat the '+' 207+ break; 208+ case AsmToken::Minus: 209+ break; 210+ } 211+ 212+ SparcOperand *Offset = 0; 213+ OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset); 214+ if (ResTy != MatchOperand_Success || !Offset) 215+ return MatchOperand_NoMatch; 216+ 217+ Offset = (Offset->isImm() 218+ ? SparcOperand::MorphToMEMri(BaseReg, Offset) 219+ : SparcOperand::MorphToMEMrr(BaseReg, Offset)); 220+ 221+ Operands.push_back(Offset); 222+ return MatchOperand_Success; 223 } 224 225 SparcAsmParser::OperandMatchResultTy SparcAsmParser:: 226@@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse 227 parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 228 StringRef Mnemonic) 229 { 230+ 231 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 232- if (ResTy == MatchOperand_Success) 233- return ResTy; 234+ 235 // If there wasn't a custom match, try the generic matcher below. Otherwise, 236 // there was a match, but an error occurred, in which case, just return that 237 // the operand parsing failed. 238- if (ResTy == MatchOperand_ParseFail) 239+ if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail) 240 return ResTy; 241 242+ if (getLexer().is(AsmToken::LBrac)) { 243+ // Memory operand 244+ Operands.push_back(SparcOperand::CreateToken("[", 245+ Parser.getTok().getLoc())); 246+ Parser.Lex(); // Eat the [ 247+ 248+ ResTy = parseMEMOperand(Operands); 249+ if (ResTy != MatchOperand_Success) 250+ return ResTy; 251+ 252+ if (!getLexer().is(AsmToken::RBrac)) 253+ return MatchOperand_ParseFail; 254+ 255+ Operands.push_back(SparcOperand::CreateToken("]", 256+ Parser.getTok().getLoc())); 257+ Parser.Lex(); // Eat the ] 258+ return MatchOperand_Success; 259+ } 260+ 261+ SparcOperand *Op = 0; 262+ ResTy = parseSparcAsmOperand(Op); 263+ if (ResTy != MatchOperand_Success || !Op) 264+ return MatchOperand_ParseFail; 265+ 266+ // Push the parsed operand into the list of operands 267+ Operands.push_back(Op); 268+ 269+ return MatchOperand_Success; 270+} 271+ 272+SparcAsmParser::OperandMatchResultTy 273+SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) 274+{ 275+ 276 SMLoc S = Parser.getTok().getLoc(); 277 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 278 const MCExpr *EVal; 279- SparcOperand *Op; 280+ 281+ Op = 0; 282 switch (getLexer().getKind()) { 283+ default: break; 284+ 285 case AsmToken::Percent: 286 Parser.Lex(); // Eat the '%'. 287 unsigned RegNo; 288@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> 289 break; 290 } 291 // FIXME: Handle modifiers like %hi, %lo etc., 292- return MatchOperand_ParseFail; 293+ break; 294 295 case AsmToken::Minus: 296 case AsmToken::Integer: 297- if (getParser().parseExpression(EVal)) 298- return MatchOperand_ParseFail; 299- 300- Op = SparcOperand::CreateImm(EVal, S, E); 301+ if (!getParser().parseExpression(EVal)) 302+ Op = SparcOperand::CreateImm(EVal, S, E); 303 break; 304 305 case AsmToken::Identifier: { 306 StringRef Identifier; 307- if (getParser().parseIdentifier(Identifier)) 308- return MatchOperand_ParseFail; 309- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 310- MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); 311+ if (!getParser().parseIdentifier(Identifier)) { 312+ SMLoc E = SMLoc::getFromPointer(Parser.getTok(). 313+ getLoc().getPointer() - 1); 314+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); 315 316- // Otherwise create a symbol reference. 317- const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, 318- getContext()); 319+ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, 320+ getContext()); 321 322- Op = SparcOperand::CreateImm(Res, S, E); 323+ Op = SparcOperand::CreateImm(Res, S, E); 324+ } 325 break; 326 } 327- 328- case AsmToken::LBrac: // handle [ 329- return parseMEMOperand(Operands, 0); 330- 331- default: 332- return MatchOperand_ParseFail; 333 } 334- // Push the parsed operand into the list of operands 335- Operands.push_back(Op); 336- return MatchOperand_Success; 337+ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; 338 } 339 340 bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, 341Index: lib/Target/Sparc/SparcInstrInfo.td 342=================================================================== 343--- lib/Target/Sparc/SparcInstrInfo.td 344+++ lib/Target/Sparc/SparcInstrInfo.td 345@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri 346 // Address operands 347 def SparcMEMrrAsmOperand : AsmOperandClass { 348 let Name = "MEMrr"; 349- let ParserMethod = "parseMEMrrOperand"; 350+ let ParserMethod = "parseMEMOperand"; 351 } 352 353 def SparcMEMriAsmOperand : AsmOperandClass { 354 let Name = "MEMri"; 355- let ParserMethod = "parseMEMriOperand"; 356+ let ParserMethod = "parseMEMOperand"; 357 } 358 359 def MEMrr : Operand<iPTR> { 360