This patch is a partial implementation of mips .set assembler directive. Directive is defined as follows:

.set option
The patch implements following options

    at - lets the assembler use the $at register for macros,
         but generates warnings if the source program uses $at

    noat - let source programs use $at without issuingwarnings.

    noreorder - prevents the assembler from reordering machine 
                language instructions.
    nomacro - causes the assembler to print a warning whenever 
              an assembler operation generates more than one 
              machine language instruction.
    macro - lets the assembler generate multiple machine instructions 
            from a single assembler instruction
    reorder - lets the assembler reorder machine language 
               instructions to improve performance

The above variants are parsed and their boolean values set or unset.
The code to actually use them will come later.

Following options are not implemented yet:

nomips16
nomicromips
move
nomove

Contributer: Vladimir Medic


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165194 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jack Carter 2012-10-04 02:29:46 +00:00
parent 047d3617cb
commit 30116cd2e2
2 changed files with 245 additions and 44 deletions

View File

@ -24,7 +24,31 @@
using namespace llvm;
namespace {
class MipsAssemblerOptions {
public:
MipsAssemblerOptions():
aTReg(1), reorder(true), macro(true) {
}
unsigned getATRegNum() {return aTReg;}
bool setATReg(unsigned Reg);
bool isReorder() {return reorder;}
void setReorder() {reorder = true;}
void setNoreorder() {reorder = false;}
bool isMacro() {return macro;}
void setMacro() {macro = true;}
void setNomacro() {macro = false;}
private:
unsigned aTReg;
bool reorder;
bool macro;
};
}
namespace {
class MipsAsmParser : public MCTargetAsmParser {
enum FpFormatTy {
@ -37,6 +61,8 @@ class MipsAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
MCAsmParser &Parser;
MipsAssemblerOptions *Options;
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
@ -66,8 +92,20 @@ class MipsAsmParser : public MCTargetAsmParser {
bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic);
bool reportParseError(StringRef ErrorMsg);
bool parseMemOffset(const MCExpr *&Res);
bool parseRelocOperand(const MCExpr *&Res);
bool parseDirectiveSet();
bool parseSetAtDirective();
bool parseSetNoAtDirective();
bool parseSetMacroDirective();
bool parseSetNoMacroDirective();
bool parseSetReorderDirective();
bool parseSetNoReorderDirective();
MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
bool isMips64() const {
@ -96,11 +134,13 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned getReg(int RC,int RegNo);
unsigned getATReg();
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
: MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Options = new MipsAssemblerOptions();
}
MCAsmParser &getParser() const { return Parser; }
@ -395,11 +435,27 @@ void MipsAsmParser::setFpFormat(StringRef Format) {
.Default(FP_FORMAT_NONE);
}
unsigned MipsAsmParser::getReg(int RC,int RegNo){
bool MipsAssemblerOptions::setATReg(unsigned Reg) {
if (Reg > 31)
return false;
aTReg = Reg;
return true;
}
unsigned MipsAsmParser::getATReg() {
unsigned Reg = Options->getATRegNum();
if (isMips64())
return getReg(Mips::CPU64RegsRegClassID,Reg);
else
return getReg(Mips::CPURegsRegClassID,Reg);
}
unsigned MipsAsmParser::getReg(int RC,int RegNo) {
return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
}
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
if (Mnemonic.lower() == "rdhwr") {
//at the moment only hwreg29 is supported
@ -411,7 +467,7 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
if (RegNum > 31)
return -1;
return getReg(Mips::CPURegsRegClassID,RegNum);
return getReg(Mips::CPURegsRegClassID, RegNum);
}
int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
@ -544,14 +600,14 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
return false;
}//case AsmToken::Percent
}//switch(getLexer().getKind())
} // case AsmToken::Percent
} // switch(getLexer().getKind())
return true;
}
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Parser.Lex(); //eat % token
Parser.Lex(); // eat % token
const AsmToken &Tok = Parser.getTok(); //get next token, operation
if (Tok.isNot(AsmToken::Identifier))
return true;
@ -559,21 +615,21 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
std::string Str = Tok.getIdentifier().str();
Parser.Lex(); //eat identifier
//now make expression from the rest of the operand
// 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
Parser.Lex(); // eat '(' token
if (getLexer().getKind() == AsmToken::Percent) {
Parser.Lex(); //eat % token
Parser.Lex(); // eat % token
const AsmToken &nextTok = Parser.getTok();
if (nextTok.isNot(AsmToken::Identifier))
return true;
Str += "(%";
Str += nextTok.getIdentifier();
Parser.Lex(); //eat identifier
Parser.Lex(); // eat identifier
if (getLexer().getKind() != AsmToken::LParen)
return true;
} else
@ -583,12 +639,12 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
return true;
while (getLexer().getKind() == AsmToken::RParen)
Parser.Lex(); //eat ')' token
Parser.Lex(); // eat ')' token
} else
return true; //parenthesis must follow reloc operand
return true; // parenthesis must follow reloc operand
//Check the type of the expression
// Check the type of the expression
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
//it's a constant, evaluate lo or hi value
int Val = MCE->getValue();
@ -602,7 +658,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
}
if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
//it's a symbol, create symbolic expression from symbol
// it's a symbol, create symbolic expression from symbol
StringRef Symbol = MSRE->getSymbol().getName();
MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
@ -634,7 +690,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
case AsmToken::Percent:
return parseRelocOperand(Res);
case AsmToken::LParen:
return false; //it's probably assuming 0
return false; // it's probably assuming 0
}
return true;
}
@ -644,13 +700,13 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
const MCExpr *IdVal = 0;
SMLoc S;
//first operand is the offset
// first operand is the offset
S = Parser.getTok().getLoc();
if (parseMemOffset(IdVal))
return MatchOperand_ParseFail;
const AsmToken &Tok = Parser.getTok(); //get next token
const AsmToken &Tok = Parser.getTok(); // get next token
if (Tok.isNot(AsmToken::LParen)) {
Error(Parser.getTok().getLoc(), "'(' expected");
return MatchOperand_ParseFail;
@ -667,11 +723,11 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
}
} else {
Error(Parser.getTok().getLoc(),"unexpected token in operand");
Error(Parser.getTok().getLoc(), "unexpected token in operand");
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;
@ -684,12 +740,12 @@ 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
Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
delete op;
return MatchOperand_Success;
@ -746,17 +802,17 @@ static int ConvertCcString(StringRef CondString) {
bool MipsAsmParser::
parseMathOperation(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
//split the format
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// 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.
@ -800,7 +856,7 @@ parseMathOperation(StringRef Name, SMLoc NameLoc,
bool MipsAsmParser::
ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
//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));
@ -814,8 +870,8 @@ ParseInstruction(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
// StringRef Rest = Name.slice(Next, StringRef::npos);
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
@ -833,11 +889,11 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
Operands.push_back(MipsOperand::CreateImm(
MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
} else {
//trunc, ceil, floor ...
// trunc, ceil, floor ...
return parseMathOperation(Name, NameLoc, Operands);
}
//the rest is a format
// the rest is a format
Format = Name.slice(Dot, StringRef::npos);
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
}
@ -877,47 +933,186 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
return false;
}
bool MipsAsmParser::
ParseDirective(AsmToken DirectiveID) {
bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
SMLoc Loc = getLexer().getLoc();
Parser.EatToEndOfStatement();
return Error(Loc, ErrorMsg);
}
bool MipsAsmParser::parseSetNoAtDirective() {
// line should look like:
// .set noat
// set at reg to 0
Options->setATReg(0);
// eat noat
Parser.Lex();
// if this is not the end of the statement, report error
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Parser.Lex(); // Consume the EndOfStatement
return false;
}
bool MipsAsmParser::parseSetAtDirective() {
// line can be
// .set at - defaults to $1
// or .set at=$reg
getParser().Lex();
if (getLexer().is(AsmToken::EndOfStatement)) {
Options->setATReg(1);
Parser.Lex(); // Consume the EndOfStatement
return false;
} else if (getLexer().is(AsmToken::Equal)) {
getParser().Lex(); //eat '='
if (getLexer().isNot(AsmToken::Dollar)) {
reportParseError("unexpected token in statement");
return false;
}
Parser.Lex(); // eat '$'
if (getLexer().isNot(AsmToken::Integer)) {
reportParseError("unexpected token in statement");
return false;
}
const AsmToken &Reg = Parser.getTok();
if (!Options->setATReg(Reg.getIntVal())) {
reportParseError("unexpected token in statement");
return false;
}
getParser().Lex(); //eat reg
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Parser.Lex(); // Consume the EndOfStatement
return false;
} else {
reportParseError("unexpected token in statement");
return false;
}
}
bool MipsAsmParser::parseSetReorderDirective() {
Parser.Lex();
// if this is not the end of the statement, report error
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Options->setReorder();
Parser.Lex(); // Consume the EndOfStatement
return false;
}
bool MipsAsmParser::parseSetNoReorderDirective() {
Parser.Lex();
// if this is not the end of the statement, report error
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Options->setNoreorder();
Parser.Lex(); // Consume the EndOfStatement
return false;
}
bool MipsAsmParser::parseSetMacroDirective() {
Parser.Lex();
// if this is not the end of the statement, report error
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Options->setMacro();
Parser.Lex(); // Consume the EndOfStatement
return false;
}
bool MipsAsmParser::parseSetNoMacroDirective() {
Parser.Lex();
// if this is not the end of the statement, report error
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("`noreorder' must be set before `nomacro'");
return false;
}
if (Options->isReorder()) {
reportParseError("`noreorder' must be set before `nomacro'");
return false;
}
Options->setNomacro();
Parser.Lex(); // Consume the EndOfStatement
return false;
}
bool MipsAsmParser::parseDirectiveSet() {
// get next token
const AsmToken &Tok = Parser.getTok();
if (Tok.getString() == "noat") {
return parseSetNoAtDirective();
} else if (Tok.getString() == "at") {
return parseSetAtDirective();
} else if (Tok.getString() == "reorder") {
return parseSetReorderDirective();
} else if (Tok.getString() == "noreorder") {
return parseSetNoReorderDirective();
} else if (Tok.getString() == "macro") {
return parseSetMacroDirective();
} else if (Tok.getString() == "nomacro") {
return parseSetNoMacroDirective();
} else if (Tok.getString() == "nomips16") {
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
} else if (Tok.getString() == "nomicromips") {
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
}
return true;
}
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
if (DirectiveID.getString() == ".ent") {
//ignore this directive for now
// ignore this directive for now
Parser.Lex();
return false;
}
if (DirectiveID.getString() == ".end") {
//ignore this directive for now
// ignore this directive for now
Parser.Lex();
return false;
}
if (DirectiveID.getString() == ".frame") {
//ignore this directive for now
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
}
if (DirectiveID.getString() == ".set") {
//ignore this directive for now
Parser.EatToEndOfStatement();
return false;
// ignore this directive for now
//Parser.EatToEndOfStatement();
return parseDirectiveSet();
}
if (DirectiveID.getString() == ".fmask") {
//ignore this directive for now
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
}
if (DirectiveID.getString() == ".mask") {
//ignore this directive for now
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
}
if (DirectiveID.getString() == ".gpword") {
//ignore this directive for now
// ignore this directive for now
Parser.EatToEndOfStatement();
return false;
}

View File

@ -1,10 +1,16 @@
# RUN: llvm-mc -triple mips-unknown-unknown %s
#this test produces no output so there isS no FileCheck call
$BB0_2:
.ent directives_test
.frame $sp,0,$ra
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
.set noat
$JTI0_0:
.gpword ($BB0_2)
.set at=$12
.set macro
.set reorder
.end directives_test