[Sparc] Add support for parsing memory operands in sparc AsmParser.

llvm-svn: 198658
This commit is contained in:
Venkatraman Govindaraju 2014-01-07 01:49:11 +00:00
parent 3e69e13092
commit 0458b599f8
4 changed files with 202 additions and 49 deletions

View File

@ -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<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy
parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int ImmOffsetOrReg);
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &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 @@ public:
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,43 +438,99 @@ ParseDirective(AsmToken DirectiveID)
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int ImmOffsetOrReg)
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
{
// FIXME: Implement memory operand parsing here.
return MatchOperand_NoMatch;
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
{
return parseMEMOperand(Operands, 2);
}
SMLoc S, E;
unsigned BaseReg = 0;
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &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::
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &Operands,
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,

View File

@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
// Address operands
def SparcMEMrrAsmOperand : AsmOperandClass {
let Name = "MEMrr";
let ParserMethod = "parseMEMrrOperand";
let ParserMethod = "parseMEMOperand";
}
def SparcMEMriAsmOperand : AsmOperandClass {
let Name = "MEMri";
let ParserMethod = "parseMEMriOperand";
let ParserMethod = "parseMEMOperand";
}
def MEMrr : Operand<iPTR> {

View File

@ -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

View File

@ -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]