X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FAsmParser%2FSparcAsmParser.cpp;h=65d9228ad94e712645d471965f9e9455f71d12c0;hb=243491693bda5368a8c447f35983fc946a696b56;hp=a4ea265a65d7b8ff8f487437f8c62eb33c447610;hpb=8c6a26194bccf825496b4f4231aa93712afe0b11;p=oota-llvm.git diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index a4ea265a65d..65d9228ad94 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -12,9 +12,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/TargetRegistry.h" @@ -66,14 +68,19 @@ class SparcAsmParser : public MCTargetAsmParser { StringRef Name); OperandMatchResultTy - parseSparcAsmOperand(SparcOperand *&Operand); + parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false); + + OperandMatchResultTy + parseBranchModifiers(SmallVectorImpl &Operands); // returns true if Tok is matched to a register and returns register in RegNo. bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, unsigned &RegKind); bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); + bool parseDirectiveWord(unsigned Size, SMLoc L); + bool is64Bit() const { return STI.getTargetTriple().startswith("sparcv9"); } public: SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII) @@ -393,7 +400,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_Success: { Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst); + Out.EmitInstruction(Inst, STI); return false; } @@ -415,7 +422,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(ErrorLoc, "invalid operand for instruction"); } case Match_MnemonicFail: - return Error(IDLoc, "invalid instruction"); + return Error(IDLoc, "invalid instruction mnemonic"); } return true; } @@ -444,16 +451,19 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl &Operands) { - // Check if we have valid mnemonic. - if (!mnemonicIsValid(Name, 0)) { - Parser.eatToEndOfStatement(); - return Error(NameLoc, "Unknown instruction"); - } + // First operand in MCInst is instruction mnemonic. Operands.push_back(SparcOperand::CreateToken(Name, NameLoc)); if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. + if (getLexer().is(AsmToken::Comma)) { + if (parseBranchModifiers(Operands) != MatchOperand_Success) { + SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); + return Error(Loc, "unexpected token"); + } + } if (parseOperand(Operands, Name) != MatchOperand_Success) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); @@ -482,8 +492,52 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, bool SparcAsmParser:: ParseDirective(AsmToken DirectiveID) { - // Ignore all directives for now. - Parser.eatToEndOfStatement(); + StringRef IDVal = DirectiveID.getString(); + + if (IDVal == ".byte") + return parseDirectiveWord(1, DirectiveID.getLoc()); + + if (IDVal == ".half") + return parseDirectiveWord(2, DirectiveID.getLoc()); + + if (IDVal == ".word") + return parseDirectiveWord(4, DirectiveID.getLoc()); + + if (IDVal == ".nword") + return parseDirectiveWord(is64Bit() ? 8 : 4, DirectiveID.getLoc()); + + if (is64Bit() && IDVal == ".xword") + return parseDirectiveWord(8, DirectiveID.getLoc()); + + if (IDVal == ".register") { + // For now, ignore .register directive. + Parser.eatToEndOfStatement(); + return false; + } + + // Let the MC layer to handle other directives. + return true; +} + +bool SparcAsmParser:: parseDirectiveWord(unsigned Size, SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + if (getParser().parseExpression(Value)) + return true; + + getParser().getStreamer().EmitValue(Value, Size); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return Error(L, "unexpected token in directive"); + Parser.Lex(); + } + } + Parser.Lex(); return false; } @@ -546,7 +600,24 @@ parseOperand(SmallVectorImpl &Operands, Parser.getTok().getLoc())); Parser.Lex(); // Eat the [ - ResTy = parseMEMOperand(Operands); + if (Mnemonic == "cas" || Mnemonic == "casx") { + SMLoc S = Parser.getTok().getLoc(); + if (getLexer().getKind() != AsmToken::Percent) + return MatchOperand_NoMatch; + Parser.Lex(); // eat % + + unsigned RegNo, RegKind; + if (!matchRegisterName(Parser.getTok(), RegNo, RegKind)) + return MatchOperand_NoMatch; + + Parser.Lex(); // Eat the identifier token. + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1); + Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E)); + ResTy = MatchOperand_Success; + } else { + ResTy = parseMEMOperand(Operands); + } + if (ResTy != MatchOperand_Success) return ResTy; @@ -560,7 +631,7 @@ parseOperand(SmallVectorImpl &Operands, } SparcOperand *Op = 0; - ResTy = parseSparcAsmOperand(Op); + ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call")); if (ResTy != MatchOperand_Success || !Op) return MatchOperand_ParseFail; @@ -571,7 +642,7 @@ parseOperand(SmallVectorImpl &Operands, } SparcAsmParser::OperandMatchResultTy -SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) +SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall) { SMLoc S = Parser.getTok().getLoc(); @@ -605,7 +676,7 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) Op = SparcOperand::CreateToken("%icc", S); break; - case Sparc::FCC: + case Sparc::FCC0: assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet"); Op = SparcOperand::CreateToken("%fcc0", S); break; @@ -632,6 +703,10 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + if (isCall && + getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) + Res = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_WPLT30, Res, + getContext()); Op = SparcOperand::CreateImm(Res, S, E); } break; @@ -640,6 +715,27 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; } +SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +parseBranchModifiers(SmallVectorImpl &Operands) { + + // parse (,a|,pn|,pt)+ + + while (getLexer().is(AsmToken::Comma)) { + + Parser.Lex(); // Eat the comma + + if (!getLexer().is(AsmToken::Identifier)) + return MatchOperand_ParseFail; + StringRef modName = Parser.getTok().getString(); + if (modName == "a" || modName == "pn" || modName == "pt") { + Operands.push_back(SparcOperand::CreateToken(modName, + Parser.getTok().getLoc())); + Parser.Lex(); // eat the identifier. + } + } + return MatchOperand_Success; +} + bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, unsigned &RegKind) @@ -687,7 +783,7 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, && !name.substr(3).getAsInteger(10, intVal) && intVal < 4) { // FIXME: check 64bit and handle %fcc1 - %fcc3 - RegNo = Sparc::FCC; + RegNo = Sparc::FCC0; RegKind = SparcOperand::rk_CCReg; return true; } @@ -750,6 +846,31 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, return false; } +static bool hasGOTReference(const MCExpr *Expr) { + switch (Expr->getKind()) { + case MCExpr::Target: + if (const SparcMCExpr *SE = dyn_cast(Expr)) + return hasGOTReference(SE->getSubExpr()); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Expr); + return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS()); + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SymRef = *cast(Expr); + return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_"); + } + + case MCExpr::Unary: + return hasGOTReference(cast(Expr)->getSubExpr()); + } + return false; +} bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc) @@ -773,6 +894,23 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, const MCExpr *subExpr; if (Parser.parseParenExpression(subExpr, EndLoc)) return false; + + bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; + + switch(VK) { + default: break; + case SparcMCExpr::VK_Sparc_LO: + VK = (hasGOTReference(subExpr) + ? SparcMCExpr::VK_Sparc_PC10 + : (isPIC ? SparcMCExpr::VK_Sparc_GOT10 : VK)); + break; + case SparcMCExpr::VK_Sparc_HI: + VK = (hasGOTReference(subExpr) + ? SparcMCExpr::VK_Sparc_PC22 + : (isPIC ? SparcMCExpr::VK_Sparc_GOT22 : VK)); + break; + } + EVal = SparcMCExpr::Create(VK, subExpr, getContext()); return true; }