Pull in r198658 from upstream llvm trunk: [Sparc] Add support for parsing memory operands in sparc AsmParser. Introduced here: http://svnweb.freebsd.org/changeset/base/262261 Index: test/MC/Sparc/sparc-ctrl-instructions.s =================================================================== --- test/MC/Sparc/sparc-ctrl-instructions.s +++ test/MC/Sparc/sparc-ctrl-instructions.s @@ -0,0 +1,23 @@ +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + + ! CHECK: call foo + call foo + + ! CHECK: call %g1+%i2 + call %g1 + %i2 + + ! CHECK: call %o1+8 + call %o1 + 8 + + ! CHECK: call %g1 + call %g1 + + ! CHECK: jmp %g1+%i2 + jmp %g1 + %i2 + + ! CHECK: jmp %o1+8 + jmp %o1 + 8 + + ! CHECK: jmp %g1 + jmp %g1 Index: test/MC/Sparc/sparc-mem-instructions.s =================================================================== --- test/MC/Sparc/sparc-mem-instructions.s +++ test/MC/Sparc/sparc-mem-instructions.s @@ -0,0 +1,58 @@ +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + + ! CHECK: ldsb [%i0+%l6], %o2 ! encoding: [0xd4,0x4e,0x00,0x16] + ldsb [%i0 + %l6], %o2 + ! CHECK: ldsb [%i0+32], %o2 ! encoding: [0xd4,0x4e,0x20,0x20] + ldsb [%i0 + 32], %o2 + ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x60,0x00] + ldsb [%g1], %o4 + + ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16] + ldsh [%i0 + %l6], %o2 + ! CHECK: ldsh [%i0+32], %o2 ! encoding: [0xd4,0x56,0x20,0x20] + ldsh [%i0 + 32], %o2 + ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x60,0x00] + ldsh [%g1], %o4 + + ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16] + ldub [%i0 + %l6], %o2 + ! CHECK: ldub [%i0+32], %o2 ! encoding: [0xd4,0x0e,0x20,0x20] + ldub [%i0 + 32], %o2 + ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x60,0x00] + ldub [%g1], %o2 + + ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16] + lduh [%i0 + %l6], %o2 + ! CHECK: lduh [%i0+32], %o2 ! encoding: [0xd4,0x16,0x20,0x20] + lduh [%i0 + 32], %o2 + ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x60,0x00] + lduh [%g1], %o2 + + ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16] + ld [%i0 + %l6], %o2 + ! CHECK: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20] + ld [%i0 + 32], %o2 + ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x60,0x00] + ld [%g1], %o2 + + ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16] + stb %o2, [%i0 + %l6] + ! CHECK: stb %o2, [%i0+32] ! encoding: [0xd4,0x2e,0x20,0x20] + stb %o2, [%i0 + 32] + ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x60,0x00] + stb %o2, [%g1] + + ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16] + sth %o2, [%i0 + %l6] + ! CHECK: sth %o2, [%i0+32] ! encoding: [0xd4,0x36,0x20,0x20] + sth %o2, [%i0 + 32] + ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x60,0x00] + sth %o2, [%g1] + + ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16] + st %o2, [%i0 + %l6] + ! CHECK: st %o2, [%i0+32] ! encoding: [0xd4,0x26,0x20,0x20] + st %o2, [%i0 + 32] + ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x60,0x00] + st %o2, [%g1] Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -28,6 +28,7 @@ namespace llvm { } namespace { +class SparcOperand; class SparcAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; @@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser { // Custom parse functions for Sparc specific operands. OperandMatchResultTy - parseMEMrrOperand(SmallVectorImpl &Operands); - OperandMatchResultTy - parseMEMriOperand(SmallVectorImpl &Operands); + parseMEMOperand(SmallVectorImpl &Operands); OperandMatchResultTy - parseMEMOperand(SmallVectorImpl &Operands, - int ImmOffsetOrReg); - - OperandMatchResultTy parseOperand(SmallVectorImpl &Operands, StringRef Name); + OperandMatchResultTy + parseSparcAsmOperand(SparcOperand *&Operand); + // returns true if Tok is matched to a register and returns register in RegNo. bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, bool isQFP); @@ -298,7 +296,35 @@ class SparcOperand : public MCParsedAsmOperand { return Op; } + static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) { + unsigned offsetReg = Op->getReg(); + Op->Kind = k_MemoryReg; + Op->Mem.Base = Base; + Op->Mem.OffsetReg = offsetReg; + Op->Mem.Off = 0; + return Op; + } + static SparcOperand *CreateMEMri(unsigned Base, + const MCExpr *Off, + SMLoc S, SMLoc E) { + SparcOperand *Op = new SparcOperand(k_MemoryImm); + Op->Mem.Base = Base; + Op->Mem.OffsetReg = 0; + Op->Mem.Off = Off; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) { + const MCExpr *Imm = Op->getImm(); + Op->Kind = k_MemoryImm; + Op->Mem.Base = Base; + Op->Mem.OffsetReg = 0; + Op->Mem.Off = Imm; + return Op; + } }; } // end namespace @@ -412,23 +438,42 @@ ParseDirective(AsmToken DirectiveID) } SparcAsmParser::OperandMatchResultTy SparcAsmParser:: -parseMEMOperand(SmallVectorImpl &Operands, - int ImmOffsetOrReg) +parseMEMOperand(SmallVectorImpl &Operands) { - // FIXME: Implement memory operand parsing here. - return MatchOperand_NoMatch; -} -SparcAsmParser::OperandMatchResultTy SparcAsmParser:: -parseMEMrrOperand(SmallVectorImpl &Operands) -{ - return parseMEMOperand(Operands, 2); -} + SMLoc S, E; + unsigned BaseReg = 0; -SparcAsmParser::OperandMatchResultTy SparcAsmParser:: -parseMEMriOperand(SmallVectorImpl &Operands) -{ - return parseMEMOperand(Operands, 1); + if (ParseRegister(BaseReg, S, E)) { + return MatchOperand_NoMatch; + } + + switch (getLexer().getKind()) { + default: return MatchOperand_NoMatch; + + case AsmToken::RBrac: + case AsmToken::EndOfStatement: + Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); + return MatchOperand_Success; + + case AsmToken:: Plus: + Parser.Lex(); // Eat the '+' + break; + case AsmToken::Minus: + break; + } + + SparcOperand *Offset = 0; + OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset); + if (ResTy != MatchOperand_Success || !Offset) + return MatchOperand_NoMatch; + + Offset = (Offset->isImm() + ? SparcOperand::MorphToMEMri(BaseReg, Offset) + : SparcOperand::MorphToMEMrr(BaseReg, Offset)); + + Operands.push_back(Offset); + return MatchOperand_Success; } SparcAsmParser::OperandMatchResultTy SparcAsmParser:: @@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse parseOperand(SmallVectorImpl &Operands, StringRef Mnemonic) { + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); - if (ResTy == MatchOperand_Success) - return ResTy; + // If there wasn't a custom match, try the generic matcher below. Otherwise, // there was a match, but an error occurred, in which case, just return that // the operand parsing failed. - if (ResTy == MatchOperand_ParseFail) + if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail) return ResTy; + if (getLexer().is(AsmToken::LBrac)) { + // Memory operand + Operands.push_back(SparcOperand::CreateToken("[", + Parser.getTok().getLoc())); + Parser.Lex(); // Eat the [ + + ResTy = parseMEMOperand(Operands); + if (ResTy != MatchOperand_Success) + return ResTy; + + if (!getLexer().is(AsmToken::RBrac)) + return MatchOperand_ParseFail; + + Operands.push_back(SparcOperand::CreateToken("]", + Parser.getTok().getLoc())); + Parser.Lex(); // Eat the ] + return MatchOperand_Success; + } + + SparcOperand *Op = 0; + ResTy = parseSparcAsmOperand(Op); + if (ResTy != MatchOperand_Success || !Op) + return MatchOperand_ParseFail; + + // Push the parsed operand into the list of operands + Operands.push_back(Op); + + return MatchOperand_Success; +} + +SparcAsmParser::OperandMatchResultTy +SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) +{ + SMLoc S = Parser.getTok().getLoc(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); const MCExpr *EVal; - SparcOperand *Op; + + Op = 0; switch (getLexer().getKind()) { + default: break; + case AsmToken::Percent: Parser.Lex(); // Eat the '%'. unsigned RegNo; @@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl break; } // FIXME: Handle modifiers like %hi, %lo etc., - return MatchOperand_ParseFail; + break; case AsmToken::Minus: case AsmToken::Integer: - if (getParser().parseExpression(EVal)) - return MatchOperand_ParseFail; - - Op = SparcOperand::CreateImm(EVal, S, E); + if (!getParser().parseExpression(EVal)) + Op = SparcOperand::CreateImm(EVal, S, E); break; case AsmToken::Identifier: { StringRef Identifier; - if (getParser().parseIdentifier(Identifier)) - return MatchOperand_ParseFail; - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); + if (!getParser().parseIdentifier(Identifier)) { + SMLoc E = SMLoc::getFromPointer(Parser.getTok(). + getLoc().getPointer() - 1); + MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); - // Otherwise create a symbol reference. - const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, - getContext()); + const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + getContext()); - Op = SparcOperand::CreateImm(Res, S, E); + Op = SparcOperand::CreateImm(Res, S, E); + } break; } - - case AsmToken::LBrac: // handle [ - return parseMEMOperand(Operands, 0); - - default: - return MatchOperand_ParseFail; } - // Push the parsed operand into the list of operands - Operands.push_back(Op); - return MatchOperand_Success; + return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; } bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -78,12 +78,12 @@ def ADDRri : ComplexPattern {