Mips assembler: Enable handling of nested expressions

This patch allows the Mips assembler to parse and emit nested 
expressions as instruction operands. It also extends the 
expansion of memory instructions when an offset is given as 
an expression. 

Contributer: Vladimir Medic
llvm-svn: 179657
This commit is contained in:
Jack Carter 2013-04-17 00:18:04 +00:00
parent eb294538c3
commit b5cf5909ac
3 changed files with 273 additions and 143 deletions

View File

@ -127,9 +127,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool isLoad,bool isImmOpnd);
bool reportParseError(StringRef ErrorMsg);
bool parseMemOffset(const MCExpr *&Res);
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
bool parseRelocOperand(const MCExpr *&Res);
const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
bool isEvaluated(const MCExpr *Expr);
bool parseDirectiveSet();
bool parseSetAtDirective();
@ -409,7 +412,7 @@ static const MCInstrDesc &getInstDesc(unsigned Opcode) {
}
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Inst.setLoc(IDLoc);
if (MCID.mayLoad() || MCID.mayStore()) {
@ -431,17 +434,20 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
const MCExpr *Expr = Op.getExpr();
if (Expr->getKind() == MCExpr::SymbolRef){
const MCSymbolRefExpr *SR =
static_cast<const MCSymbolRefExpr*>(Expr);
static_cast<const MCSymbolRefExpr*>(Expr);
if (SR->getKind() == MCSymbolRefExpr::VK_None) {
// Expand symbol
expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),false);
return false;
}
} else if (!isEvaluated(Expr)) {
expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),false);
return false;
}
}
}
}
}
}// For
}// If load/store
if (needsExpansion(Inst))
expandInstruction(Inst, IDLoc, Instructions);
@ -644,20 +650,23 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
MCSymbolRefExpr::VK_Mips_ABS_HI,
getContext());
TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
} else {
const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset,"hi");
TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
}
}
// Add the instruction to the list
Instructions.push_back(TempInst);
// and prepare TempInst for next instruction
// And prepare TempInst for next instruction
TempInst.clear();
// which is add temp register to base
// Which is add temp register to base
TempInst.setOpcode(Mips::ADDu);
TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
Instructions.push_back(TempInst);
TempInst.clear();
// and finaly, create original instruction with low part
// And finaly, create original instruction with low part
// of offset and new base
TempInst.setOpcode(Inst.getOpcode());
TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
@ -671,6 +680,9 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
MCSymbolRefExpr::VK_Mips_ABS_LO,
getContext());
TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
} else {
const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset,"lo");
TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
}
}
Instructions.push_back(TempInst);
@ -960,13 +972,13 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
// we need to assigne the propper RegisterKind
if (searchSymbolAlias(Operands,MipsOperand::Kind_None))
return false;
//else drop to expression parsing
// Else drop to expression parsing
case AsmToken::LParen:
case AsmToken::Minus:
case AsmToken::Plus:
case AsmToken::Integer:
case AsmToken::String: {
// quoted label names
// Quoted label names
const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc();
if (getParser().parseExpression(IdVal))
@ -976,9 +988,9 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
return false;
}
case AsmToken::Percent: {
// it is a symbol reference or constant expression
// It is a symbol reference or constant expression
const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc(); // start location of the operand
SMLoc S = Parser.getTok().getLoc(); // Start location of the operand
if (parseRelocOperand(IdVal))
return true;
@ -991,52 +1003,17 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
return true;
}
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Parser.Lex(); // eat % token
const AsmToken &Tok = Parser.getTok(); // get next token, operation
if (Tok.isNot(AsmToken::Identifier))
return true;
std::string Str = Tok.getIdentifier().str();
Parser.Lex(); // eat identifier
// now make expression from the rest of the operand
const MCExpr *IdVal;
SMLoc EndLoc;
if (getLexer().getKind() == AsmToken::LParen) {
while (1) {
Parser.Lex(); // eat '(' token
if (getLexer().getKind() == AsmToken::Percent) {
Parser.Lex(); // eat % token
const AsmToken &nextTok = Parser.getTok();
if (nextTok.isNot(AsmToken::Identifier))
return true;
Str += "(%";
Str += nextTok.getIdentifier();
Parser.Lex(); // eat identifier
if (getLexer().getKind() != AsmToken::LParen)
return true;
} else
break;
}
if (getParser().parseParenExpression(IdVal,EndLoc))
return true;
while (getLexer().getKind() == AsmToken::RParen)
Parser.Lex(); // eat ')' token
} else
return true; // parenthesis must follow reloc operand
const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
StringRef RelocStr) {
const MCExpr *Res;
// Check the type of the expression
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
// It's a constant, evaluate lo or hi value
if (Str == "lo") {
if (RelocStr == "lo") {
short Val = MCE->getValue();
Res = MCConstantExpr::Create(Val, getContext());
} else if (Str == "hi") {
} else if (RelocStr == "hi") {
int Val = MCE->getValue();
int LoSign = Val & 0x8000;
Val = (Val & 0xffff0000) >> 16;
@ -1046,17 +1023,96 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Val++;
Res = MCConstantExpr::Create(Val, getContext());
}
return false;
return Res;
}
if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
// It's a symbol, create symbolic expression from symbol
StringRef Symbol = MSRE->getSymbol().getName();
MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
return Res;
}
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(),RelocStr);
const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(),RelocStr);
Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
return Res;
}
if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(),RelocStr);
Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
return Res;
}
// Just return the original expr
return Expr;
}
bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
switch (Expr->getKind()) {
case MCExpr::Constant:
return true;
case MCExpr::SymbolRef:
return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
case MCExpr::Binary:
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
if (!isEvaluated(BE->getLHS()))
return false;
return isEvaluated(BE->getRHS());
}
case MCExpr::Unary:
return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
default:
return false;
}
return true;
return false;
}
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Parser.Lex(); // Eat % token
const AsmToken &Tok = Parser.getTok(); // Get next token, operation
if (Tok.isNot(AsmToken::Identifier))
return true;
std::string Str = Tok.getIdentifier().str();
Parser.Lex(); // Eat identifier
// Now make expression from the rest of the operand
const MCExpr *IdVal;
SMLoc EndLoc;
if (getLexer().getKind() == AsmToken::LParen) {
while (1) {
Parser.Lex(); // Eat '(' token
if (getLexer().getKind() == AsmToken::Percent) {
Parser.Lex(); // Eat % token
const AsmToken &nextTok = Parser.getTok();
if (nextTok.isNot(AsmToken::Identifier))
return true;
Str += "(%";
Str += nextTok.getIdentifier();
Parser.Lex(); // Eat identifier
if (getLexer().getKind() != AsmToken::LParen)
return true;
} else
break;
}
if (getParser().parseParenExpression(IdVal,EndLoc))
return true;
while (getLexer().getKind() == AsmToken::RParen)
Parser.Lex(); // Eat ')' token
} else
return true; // Parenthesis must follow reloc operand
Res = evaluateRelocExpr(IdVal,Str);
return false;
}
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
@ -1068,24 +1124,33 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
return (RegNo == (unsigned)-1);
}
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
SMLoc S;
bool Result = true;
while (getLexer().getKind() == AsmToken::LParen)
Parser.Lex();
switch(getLexer().getKind()) {
default:
return true;
case AsmToken::Identifier:
case AsmToken::LParen:
case AsmToken::Integer:
case AsmToken::Minus:
case AsmToken::Plus:
return (getParser().parseExpression(Res));
if (isParenExpr)
Result = getParser().parseParenExpression(Res,S);
else
Result = (getParser().parseExpression(Res));
while (getLexer().getKind() == AsmToken::RParen)
Parser.Lex();
break;
case AsmToken::Percent:
return parseRelocOperand(Res);
case AsmToken::LParen:
return false; // it's probably assuming 0
Result = parseRelocOperand(Res);
}
return true;
return Result;
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
@ -1093,27 +1158,46 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
const MCExpr *IdVal = 0;
SMLoc S;
// first operand is the offset
bool isParenExpr = false;
// First operand is the offset
S = Parser.getTok().getLoc();
if (parseMemOffset(IdVal))
return MatchOperand_ParseFail;
const AsmToken &Tok = Parser.getTok(); // get next token
if (Tok.isNot(AsmToken::LParen)) {
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
if (Mnemonic->getToken() == "la") {
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
return MatchOperand_Success;
}
Error(Parser.getTok().getLoc(), "'(' expected");
return MatchOperand_ParseFail;
if (getLexer().getKind() == AsmToken::LParen) {
Parser.Lex();
isParenExpr = true;
}
Parser.Lex(); // Eat '(' token.
if (getLexer().getKind() != AsmToken::Dollar) {
if (parseMemOffset(IdVal,isParenExpr))
return MatchOperand_ParseFail;
const AsmToken &Tok1 = Parser.getTok(); // get next token
const AsmToken &Tok = Parser.getTok(); // Get next token
if (Tok.isNot(AsmToken::LParen)) {
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
if (Mnemonic->getToken() == "la") {
SMLoc E = SMLoc::getFromPointer(
Parser.getTok().getLoc().getPointer() -1);
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
return MatchOperand_Success;
}
if (Tok.is(AsmToken::EndOfStatement)) {
SMLoc E = SMLoc::getFromPointer(
Parser.getTok().getLoc().getPointer() -1);
// Zero register assumed, add memory operand with ZERO as base
Operands.push_back(MipsOperand::CreateMem(isMips64()?
Mips::ZERO_64:Mips::ZERO,
IdVal, S, E));
return MatchOperand_Success;
}
Error(Parser.getTok().getLoc(), "'(' expected");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat '(' token.
}
const AsmToken &Tok1 = Parser.getTok(); // Get next token
if (Tok1.is(AsmToken::Dollar)) {
Parser.Lex(); // Eat '$' token.
if (tryParseRegisterOperand(Operands, isMips64())) {
@ -1126,7 +1210,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
return MatchOperand_ParseFail;
}
const AsmToken &Tok2 = Parser.getTok(); // get next token
const AsmToken &Tok2 = Parser.getTok(); // Get next token
if (Tok2.isNot(AsmToken::RParen)) {
Error(Parser.getTok().getLoc(), "')' expected");
return MatchOperand_ParseFail;
@ -1139,12 +1223,21 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
if (IdVal == 0)
IdVal = MCConstantExpr::Create(0, getContext());
// now replace register operand with the mem operand
// Now replace register operand with the mem operand
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
int RegNo = op->getReg();
// remove register from operands
// Remove register from operands
Operands.pop_back();
// and add memory operand
// And add memory operand
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
int64_t Imm;
if (IdVal->EvaluateAsAbsolute(Imm))
IdVal = MCConstantExpr::Create(Imm, getContext());
else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
getContext());
}
Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
delete op;
return MatchOperand_Success;
@ -1160,13 +1253,13 @@ MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
return MatchOperand_NoMatch;
}
// if the first token is not '$' we have an error
// If the first token is not '$' we have an error
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
Parser.Lex(); // Eat $
if(!tryParseRegisterOperand(Operands, true)) {
// set the proper register kind
// Set the proper register kind
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
op->setRegKind(MipsOperand::Kind_CPU64Regs);
return MatchOperand_Success;
@ -1220,13 +1313,13 @@ MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
return MatchOperand_NoMatch;
}
// if the first token is not '$' we have an error
// If the first token is not '$' we have an error
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
Parser.Lex(); // Eat $
if(!tryParseRegisterOperand(Operands, false)) {
// set the propper register kind
// Set the propper register kind
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
op->setRegKind(MipsOperand::Kind_CPURegs);
return MatchOperand_Success;
@ -1240,18 +1333,18 @@ MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (isMips64())
return MatchOperand_NoMatch;
// if the first token is not '$' we have error
// If the first token is not '$' we have error
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat $
const AsmToken &Tok = Parser.getTok(); // get next token
const AsmToken &Tok = Parser.getTok(); // Get next token
if (Tok.isNot(AsmToken::Integer))
return MatchOperand_NoMatch;
unsigned RegNum = Tok.getIntVal();
// at the moment only hwreg29 is supported
// At the moment only hwreg29 is supported
if (RegNum != 29)
return MatchOperand_ParseFail;
@ -1269,18 +1362,18 @@ MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (!isMips64())
return MatchOperand_NoMatch;
//if the first token is not '$' we have error
// If the first token is not '$' we have error
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat $
const AsmToken &Tok = Parser.getTok(); // get next token
const AsmToken &Tok = Parser.getTok(); // Get next token
if (Tok.isNot(AsmToken::Integer))
return MatchOperand_NoMatch;
unsigned RegNum = Tok.getIntVal();
// at the moment only hwreg29 is supported
// At the moment only hwreg29 is supported
if (RegNum != 29)
return MatchOperand_ParseFail;
@ -1296,20 +1389,20 @@ MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
unsigned RegNum;
//if the first token is not '$' we have error
// If the first token is not '$' we have error
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat $
const AsmToken &Tok = Parser.getTok(); // get next token
const AsmToken &Tok = Parser.getTok(); // Get next token
if (Tok.is(AsmToken::Integer)) {
RegNum = Tok.getIntVal();
// at the moment only fcc0 is supported
// At the moment only fcc0 is supported
if (RegNum != 0)
return MatchOperand_ParseFail;
} else if (Tok.is(AsmToken::Identifier)) {
// at the moment only fcc0 is supported
// At the moment only fcc0 is supported
if (Tok.getIdentifier() != "fcc0")
return MatchOperand_ParseFail;
} else
@ -1376,16 +1469,16 @@ static int ConvertCcString(StringRef CondString) {
bool MipsAsmParser::
parseMathOperation(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// split the format
// Split the format
size_t Start = Name.find('.'), Next = Name.rfind('.');
StringRef Format1 = Name.slice(Start, Next);
// and add the first format to the operands
// And add the first format to the operands
Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
// now for the second format
// Now for the second format
StringRef Format2 = Name.slice(Next, StringRef::npos);
Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
// set the format for the first register
// Set the format for the first register
setFpFormat(Format1);
// Read the remaining operands.
@ -1405,7 +1498,7 @@ parseMathOperation(StringRef Name, SMLoc NameLoc,
}
Parser.Lex(); // Eat the comma.
//set the format for the first register
// Set the format for the first register
setFpFormat(Format2);
// Parse and remember the operand.
@ -1430,7 +1523,7 @@ bool MipsAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
StringRef Mnemonic;
// floating point instructions: should register be treated as double?
// Floating point instructions: should register be treated as double?
if (requestsDoubleOperand(Name)) {
setFpFormat(FP_FORMAT_D);
Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
@ -1445,15 +1538,14 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
if (Next != StringRef::npos) {
// there is a format token in mnemonic
// StringRef Rest = Name.slice(Next, StringRef::npos);
// There is a format token in mnemonic
size_t Dot = Name.find('.', Next+1);
StringRef Format = Name.slice(Next, Dot);
if (Dot == StringRef::npos) //only one '.' in a string, it's a format
if (Dot == StringRef::npos) // Only one '.' in a string, it's a format
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
else {
if (Name.startswith("c.")){
// floating point compare, add '.' and immediate represent for cc
// Floating point compare, add '.' and immediate represent for cc
Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
int Cc = ConvertCcString(Format);
if (Cc == -1) {
@ -1640,12 +1732,12 @@ bool MipsAsmParser::parseSetAssignment() {
if (getLexer().isNot(AsmToken::Comma))
return reportParseError("unexpected token in .set directive");
Lex(); //eat comma
Lex(); // Eat comma
if (Parser.parseExpression(Value))
reportParseError("expected valid expression after comma");
// check if the Name already exists as a symbol
// Check if the Name already exists as a symbol
MCSymbol *Sym = getContext().LookupSymbol(Name);
if (Sym) {
return reportParseError("symbol already defined");
@ -1657,7 +1749,7 @@ bool MipsAsmParser::parseSetAssignment() {
}
bool MipsAsmParser::parseDirectiveSet() {
// get next token
// Get next token
const AsmToken &Tok = Parser.getTok();
if (Tok.getString() == "noat") {
@ -1673,11 +1765,11 @@ bool MipsAsmParser::parseDirectiveSet() {
} else if (Tok.getString() == "nomacro") {
return parseSetNoMacroDirective();
} else if (Tok.getString() == "nomips16") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
} else if (Tok.getString() == "nomicromips") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
} else {
@ -1719,19 +1811,19 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getString();
if ( IDVal == ".ent") {
// ignore this directive for now
// Ignore this directive for now
Parser.Lex();
return false;
}
if (IDVal == ".end") {
// ignore this directive for now
// Ignore this directive for now
Parser.Lex();
return false;
}
if (IDVal == ".frame") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
}
@ -1741,19 +1833,19 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
}
if (IDVal == ".fmask") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
}
if (IDVal == ".mask") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
}
if (IDVal == ".gpword") {
// ignore this directive for now
// Ignore this directive for now
Parser.eatToEndOfStatement();
return false;
}

View File

@ -88,6 +88,9 @@ public:
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;
unsigned
getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const;
}; // class MipsMCCodeEmitter
} // namespace
@ -192,35 +195,24 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
return 0;
}
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const {
if (MO.isReg()) {
unsigned Reg = MO.getReg();
unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg);
return RegNo;
} else if (MO.isImm()) {
return static_cast<unsigned>(MO.getImm());
} else if (MO.isFPImm()) {
return static_cast<unsigned>(APFloat(MO.getFPImm())
.bitcastToAPInt().getHiBits(32).getLimitedValue());
}
getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const {
int64_t Res;
// MO must be an Expr.
assert(MO.isExpr());
if (Expr->EvaluateAsAbsolute(Res))
return Res;
const MCExpr *Expr = MO.getExpr();
MCExpr::ExprKind Kind = Expr->getKind();
if (Kind == MCExpr::Constant) {
return cast<MCConstantExpr>(Expr)->getValue();
}
if (Kind == MCExpr::Binary) {
Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
Kind = Expr->getKind();
unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups);
Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups);
return Res;
}
assert (Kind == MCExpr::SymbolRef);
if (Kind == MCExpr::SymbolRef) {
Mips::Fixups FixupKind = Mips::Fixups(0);
switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
@ -300,12 +292,32 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
break;
} // switch
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
// All of the information is in the fixup.
Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
return 0;
}
return 0;
}
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const {
if (MO.isReg()) {
unsigned Reg = MO.getReg();
unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg);
return RegNo;
} else if (MO.isImm()) {
return static_cast<unsigned>(MO.getImm());
} else if (MO.isFPImm()) {
return static_cast<unsigned>(APFloat(MO.getFPImm())
.bitcastToAPInt().getHiBits(32).getLimitedValue());
}
// MO must be an Expr.
assert(MO.isExpr());
return getExprOpValue(MO.getExpr(),Fixups);
}
/// getMemEncoding - Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
unsigned

26
llvm/test/MC/Mips/expr1.s Normal file
View File

@ -0,0 +1,26 @@
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s
# Check that the assembler can handle the expressions as operands.
# CHECK: .text
# CHECK: .globl foo
# CHECK: foo:
# CHECK: lw $4, %lo(foo)($4) # encoding: [A,A,0x84,0x8c]
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
# CHECK: lw $4, 56($4) # encoding: [0x38,0x00,0x84,0x8c]
# CHECK: lw $4, %lo(foo+8)($4) # encoding: [0x08'A',A,0x84,0x8c]
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
# CHECK: lw $4, %lo(foo+8)($4) # encoding: [0x08'A',A,0x84,0x8c]
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
# CHECK: lw $4, %lo(foo+8)($4) # encoding: [0x08'A',A,0x84,0x8c]
# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
# CHECK: .space 64
.globl foo
.ent foo
foo:
lw $4,%lo(foo)($4)
lw $4,((10 + 4) * 4)($4)
lw $4,%lo (2 * 4) + foo($4)
lw $4,%lo((2 * 4) + foo)($4)
lw $4,(((%lo ((2 * 4) + foo))))($4)
.space 64
.end foo