Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3009,67 +3009,84 @@ 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)) { - reportParseError("unexpected token, expected dollar sign '$'"); + } + + 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; - } - 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; - } - - if (AtRegNo < 0 || AtRegNo > 31) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected dollar sign '$'"); return false; } + } + Parser.Lex(); // Eat "$". - if (!AssemblerOptions.back()->setATReg(AtRegNo)) { - reportParseError("invalid register"); - return false; - } - getParser().Lex(); // Eat the register. + // 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, expected identifier or integer"); + return false; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - Parser.Lex(); // Consume the EndOfStatement. + // Check if $reg is a valid register. If it is, set $at to $reg. + if (!AssemblerOptions.back()->setATReg(AtRegNo)) { + reportParseError("invalid register"); return false; - } else { - reportParseError("unexpected token in statement"); + } + 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() { Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -43,6 +43,9 @@ 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 @@ 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(); Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -34,6 +34,7 @@ virtual void emitDirectiveSetMsa(); virtual void emitDirectiveSetNoMsa(); virtual void emitDirectiveSetAt(); + virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); virtual void emitDirectiveEnd(StringRef Name); @@ -138,6 +139,7 @@ void emitDirectiveSetMsa() override; void emitDirectiveSetNoMsa() override; void emitDirectiveSetAt() override; + void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; void emitDirectiveEnd(StringRef Name) override; Index: test/MC/Mips/mips-noat.s =================================================================== --- test/MC/Mips/mips-noat.s +++ test/MC/Mips/mips-noat.s @@ -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 @@ # 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) Index: test/MC/Mips/set-at-directive-explicit-at.s =================================================================== --- test/MC/Mips/set-at-directive-explicit-at.s +++ test/MC/Mips/set-at-directive-explicit-at.s @@ -15,6 +15,16 @@ # 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] Index: test/MC/Mips/set-at-directive.s =================================================================== --- test/MC/Mips/set-at-directive.s +++ test/MC/Mips/set-at-directive.s @@ -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) Index: test/MC/Mips/set-at-noat-bad-syntax.s =================================================================== --- /dev/null +++ test/MC/Mips/set-at-noat-bad-syntax.s @@ -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