[mips] Improve support for the .set at/noat assembler directives.

Summary:
Made the following changes:
  Added calls to emitDirectiveSetNoAt() and emitDirectiveSetAt().
  Added special emit function for .set at=$reg, emitDirectiveSetAtWithArg(unsigned RegNo).
  Improved parsing error checks for .set at.
  Refactored parser code for .set at.
  Improved testing of both directives.
  Improved code readability and comments.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D7176

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229097 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Toma Tabacu 2015-02-13 10:30:57 +00:00
parent 7ea33e53c7
commit 94b64060af
7 changed files with 139 additions and 38 deletions

View File

@ -3276,67 +3276,84 @@ bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
bool MipsAsmParser::parseSetNoAtDirective() {
MCAsmParser &Parser = getParser();
// Line should look like: ".set noat".
// set at reg to 0.
// Set the $at register to $0.
AssemblerOptions.back()->setATReg(0);
// eat noat
Parser.Lex();
Parser.Lex(); // Eat "noat".
// If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token, expected end of statement");
return false;
}
getTargetStreamer().emitDirectiveSetNoAt();
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
bool MipsAsmParser::parseSetAtDirective() {
// Line can be: ".set at", which sets $at to $1
// or ".set at=$reg", which sets $at to $reg.
MCAsmParser &Parser = getParser();
// Line can be .set at - defaults to $1
// or .set at=$reg
int AtRegNo;
getParser().Lex();
Parser.Lex(); // Eat "at".
if (getLexer().is(AsmToken::EndOfStatement)) {
// No register was specified, so we set $at to $1.
AssemblerOptions.back()->setATReg(1);
getTargetStreamer().emitDirectiveSetAt();
Parser.Lex(); // Consume the EndOfStatement.
return false;
} else if (getLexer().is(AsmToken::Equal)) {
getParser().Lex(); // Eat the '='.
if (getLexer().isNot(AsmToken::Dollar)) {
}
if (getLexer().isNot(AsmToken::Equal)) {
reportParseError("unexpected token, expected equals sign");
return false;
}
Parser.Lex(); // Eat "=".
if (getLexer().isNot(AsmToken::Dollar)) {
if (getLexer().is(AsmToken::EndOfStatement)) {
reportParseError("no register specified");
return false;
} else {
reportParseError("unexpected token, expected dollar sign '$'");
return false;
}
Parser.Lex(); // Eat the '$'.
const AsmToken &Reg = Parser.getTok();
if (Reg.is(AsmToken::Identifier)) {
AtRegNo = matchCPURegisterName(Reg.getIdentifier());
} else if (Reg.is(AsmToken::Integer)) {
AtRegNo = Reg.getIntVal();
} else {
reportParseError("unexpected token, expected identifier or integer");
return false;
}
}
Parser.Lex(); // Eat "$".
if (AtRegNo < 0 || AtRegNo > 31) {
reportParseError("unexpected token in statement");
return false;
}
if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
reportParseError("invalid register");
return false;
}
getParser().Lex(); // Eat the register.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token, expected end of statement");
return false;
}
Parser.Lex(); // Consume the EndOfStatement.
return false;
// Find out what "reg" is.
unsigned AtRegNo;
const AsmToken &Reg = Parser.getTok();
if (Reg.is(AsmToken::Identifier)) {
AtRegNo = matchCPURegisterName(Reg.getIdentifier());
} else if (Reg.is(AsmToken::Integer)) {
AtRegNo = Reg.getIntVal();
} else {
reportParseError("unexpected token in statement");
reportParseError("unexpected token, expected identifier or integer");
return false;
}
// Check if $reg is a valid register. If it is, set $at to $reg.
if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
reportParseError("invalid register");
return false;
}
Parser.Lex(); // Eat "reg".
// If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token, expected end of statement");
return false;
}
getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
bool MipsAsmParser::parseSetReorderDirective() {

View File

@ -43,6 +43,9 @@ void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
forbidModuleDirective();
}
void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {}
void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {}
@ -144,6 +147,11 @@ void MipsTargetAsmStreamer::emitDirectiveSetAt() {
MipsTargetStreamer::emitDirectiveSetAt();
}
void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
OS << "\t.set\tat=$" << Twine(RegNo) << "\n";
MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo);
}
void MipsTargetAsmStreamer::emitDirectiveSetNoAt() {
OS << "\t.set\tnoat\n";
MipsTargetStreamer::emitDirectiveSetNoAt();

View File

@ -35,6 +35,7 @@ public:
virtual void emitDirectiveSetMsa();
virtual void emitDirectiveSetNoMsa();
virtual void emitDirectiveSetAt();
virtual void emitDirectiveSetAtWithArg(unsigned RegNo);
virtual void emitDirectiveSetNoAt();
virtual void emitDirectiveEnd(StringRef Name);
@ -145,6 +146,7 @@ public:
void emitDirectiveSetMsa() override;
void emitDirectiveSetNoMsa() override;
void emitDirectiveSetAt() override;
void emitDirectiveSetAtWithArg(unsigned RegNo) override;
void emitDirectiveSetNoAt() override;
void emitDirectiveEnd(StringRef Name) override;

View File

@ -7,6 +7,8 @@
# CHECK: lui $1, 1
# CHECK: addu $1, $1, $2
# CHECK: lw $2, 0($1)
# CHECK-LABEL: test2:
# CHECK: .set noat
test1:
lw $2, 65536($2)
@ -20,6 +22,8 @@ test2:
# CHECK: lui $1, 1
# CHECK: addu $1, $1, $2
# CHECK: lw $2, 0($1)
# CHECK-LABEL: test4:
# CHECK: .set at=$0
test3:
.set at
lw $2, 65536($2)

View File

@ -15,6 +15,16 @@ foo:
# WARNINGS: :[[@LINE+2]]:11: warning: used $at without ".set noat"
.set at=$1
jr $1
# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00]
# WARNINGS: :[[@LINE+2]]:11: warning: used $at without ".set noat"
.set at=$at
jr $at
# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00]
# WARNINGS: :[[@LINE+2]]:11: warning: used $at without ".set noat"
.set at=$at
jr $1
# WARNINGS-NOT: warning: used $at without ".set noat"
# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00]

View File

@ -4,156 +4,187 @@
# for ".set at" and set the correct value.
.text
foo:
# CHECK: .set at=$1
# CHECK: lui $1, 1
# CHECK: addu $1, $1, $2
# CHECK: lw $2, 0($1)
.set at=$1
lw $2, 65536($2)
# CHECK: .set at=$2
# CHECK: lui $2, 1
# CHECK: addu $2, $2, $1
# CHECK: lw $1, 0($2)
.set at=$2
lw $1, 65536($1)
# CHECK: .set at=$3
# CHECK: lui $3, 1
# CHECK: addu $3, $3, $1
# CHECK: lw $1, 0($3)
.set at=$3
lw $1, 65536($1)
# CHECK: .set at=$4
# CHECK: lui $4, 1
# CHECK: addu $4, $4, $1
# CHECK: lw $1, 0($4)
.set at=$a0
lw $1, 65536($1)
# CHECK: .set at=$5
# CHECK: lui $5, 1
# CHECK: addu $5, $5, $1
# CHECK: lw $1, 0($5)
.set at=$a1
lw $1, 65536($1)
# CHECK: .set at=$6
# CHECK: lui $6, 1
# CHECK: addu $6, $6, $1
# CHECK: lw $1, 0($6)
.set at=$a2
lw $1, 65536($1)
# CHECK: .set at=$7
# CHECK: lui $7, 1
# CHECK: addu $7, $7, $1
# CHECK: lw $1, 0($7)
.set at=$a3
lw $1, 65536($1)
# CHECK: .set at=$8
# CHECK: lui $8, 1
# CHECK: addu $8, $8, $1
# CHECK: lw $1, 0($8)
.set at=$8
lw $1, 65536($1)
# CHECK: .set at=$9
# CHECK: lui $9, 1
# CHECK: addu $9, $9, $1
# CHECK: lw $1, 0($9)
.set at=$9
lw $1, 65536($1)
# CHECK: .set at=$10
# CHECK: lui $10, 1
# CHECK: addu $10, $10, $1
# CHECK: lw $1, 0($10)
.set at=$10
lw $1, 65536($1)
# CHECK: .set at=$11
# CHECK: lui $11, 1
# CHECK: addu $11, $11, $1
# CHECK: lw $1, 0($11)
.set at=$11
lw $1, 65536($1)
# CHECK: .set at=$12
# CHECK: lui $12, 1
# CHECK: addu $12, $12, $1
# CHECK: lw $1, 0($12)
.set at=$12
lw $1, 65536($1)
# CHECK: .set at=$13
# CHECK: lui $13, 1
# CHECK: addu $13, $13, $1
# CHECK: lw $1, 0($13)
.set at=$13
lw $1, 65536($1)
# CHECK: .set at=$14
# CHECK: lui $14, 1
# CHECK: addu $14, $14, $1
# CHECK: lw $1, 0($14)
.set at=$14
lw $1, 65536($1)
# CHECK: .set at=$15
# CHECK: lui $15, 1
# CHECK: addu $15, $15, $1
# CHECK: lw $1, 0($15)
.set at=$15
lw $1, 65536($1)
# CHECK: .set at=$16
# CHECK: lui $16, 1
# CHECK: addu $16, $16, $1
# CHECK: lw $1, 0($16)
.set at=$s0
lw $1, 65536($1)
# CHECK: .set at=$17
# CHECK: lui $17, 1
# CHECK: addu $17, $17, $1
# CHECK: lw $1, 0($17)
.set at=$s1
lw $1, 65536($1)
# CHECK: .set at=$18
# CHECK: lui $18, 1
# CHECK: addu $18, $18, $1
# CHECK: lw $1, 0($18)
.set at=$s2
lw $1, 65536($1)
# CHECK: .set at=$19
# CHECK: lui $19, 1
# CHECK: addu $19, $19, $1
# CHECK: lw $1, 0($19)
.set at=$s3
lw $1, 65536($1)
# CHECK: .set at=$20
# CHECK: lui $20, 1
# CHECK: addu $20, $20, $1
# CHECK: lw $1, 0($20)
.set at=$s4
lw $1, 65536($1)
# CHECK: .set at=$21
# CHECK: lui $21, 1
# CHECK: addu $21, $21, $1
# CHECK: lw $1, 0($21)
.set at=$s5
lw $1, 65536($1)
# CHECK: .set at=$22
# CHECK: lui $22, 1
# CHECK: addu $22, $22, $1
# CHECK: lw $1, 0($22)
.set at=$s6
lw $1, 65536($1)
# CHECK: .set at=$23
# CHECK: lui $23, 1
# CHECK: addu $23, $23, $1
# CHECK: lw $1, 0($23)
.set at=$s7
lw $1, 65536($1)
# CHECK: .set at=$24
# CHECK: lui $24, 1
# CHECK: addu $24, $24, $1
# CHECK: lw $1, 0($24)
.set at=$24
lw $1, 65536($1)
# CHECK: .set at=$25
# CHECK: lui $25, 1
# CHECK: addu $25, $25, $1
# CHECK: lw $1, 0($25)
.set at=$25
lw $1, 65536($1)
# CHECK: .set at=$26
# CHECK: lui $26, 1
# CHECK: addu $26, $26, $1
# CHECK: lw $1, 0($26)
.set at=$26
lw $1, 65536($1)
# CHECK: .set at=$27
# CHECK: lui $27, 1
# CHECK: addu $27, $27, $1
# CHECK: lw $1, 0($27)
.set at=$27
lw $1, 65536($1)
# CHECK: .set at=$28
# CHECK: lui $gp, 1
# CHECK: addu $gp, $gp, $1
# CHECK: lw $1, 0($gp)
.set at=$gp
lw $1, 65536($1)
# CHECK: .set at=$30
# CHECK: lui $fp, 1
# CHECK: addu $fp, $fp, $1
# CHECK: lw $1, 0($fp)
.set at=$fp
lw $1, 65536($1)
# CHECK: .set at=$29
# CHECK: lui $sp, 1
# CHECK: addu $sp, $sp, $1
# CHECK: lw $1, 0($sp)
.set at=$sp
lw $1, 65536($1)
# CHECK: .set at=$31
# CHECK: lui $ra, 1
# CHECK: addu $ra, $ra, $1
# CHECK: lw $1, 0($ra)

View File

@ -0,0 +1,29 @@
# RUN: not llvm-mc %s -triple=mips-unknown-unknown -mcpu=mips32 2>%t1
# RUN: FileCheck %s < %t1
.set at~
# CHECK: error: unexpected token, expected equals sign
.set at=
# CHECK: error: no register specified
.set at=~
# CHECK: error: unexpected token, expected dollar sign '$'
.set at=$
# CHECK: error: unexpected token, expected identifier or integer
.set at=$-4
# CHECK: error: unexpected token, expected identifier or integer
.set at=$1000
# CHECK: error: invalid register
.set at=$foo
# CHECK: error: invalid register
.set at=$2bar
# CHECK: error: unexpected token, expected end of statement
.set noat bar
# CHECK: error: unexpected token, expected end of statement