Index: include/llvm/MC/MCParser/MCAsmLexer.h =================================================================== --- include/llvm/MC/MCParser/MCAsmLexer.h +++ include/llvm/MC/MCParser/MCAsmLexer.h @@ -74,6 +74,7 @@ SMLoc getLoc() const; SMLoc getEndLoc() const; + SMRange getLocRange() const; /// getStringContents - Get the contents of a string token (without quotes). StringRef getStringContents() const { Index: lib/MC/MCParser/MCAsmLexer.cpp =================================================================== --- lib/MC/MCParser/MCAsmLexer.cpp +++ lib/MC/MCParser/MCAsmLexer.cpp @@ -30,3 +30,7 @@ SMLoc AsmToken::getEndLoc() const { return SMLoc::getFromPointer(Str.data() + Str.size()); } + +SMRange AsmToken::getLocRange() const { + return SMRange(getLoc(), getEndLoc()); +} Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/SourceMgr.h" #include using namespace llvm; @@ -101,6 +102,10 @@ // selected. This usually happens after an '.end func' // directive. + // Print a warning along with its fix-it message at the given range. + void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, + SMRange Range, bool ShowColors = true); + #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -1602,6 +1607,14 @@ } } +void +MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, + SMRange Range, bool ShowColors) { + getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg, + { Range }, { SMFixIt(Range, FixMsg) }, + ShowColors); +} + int MipsAsmParser::matchCPURegisterName(StringRef Name) { int CC; @@ -1644,6 +1657,23 @@ if (!(isABI_N32() || isABI_N64())) return CC; + if (12 <= CC && CC <= 15) { + // Name is one of t4-t7 + AsmToken RegTok = getLexer().peekTok(); + SMRange RegRange = RegTok.getLocRange(); + + StringRef FixedName = StringSwitch(Name) + .Case("t4", "t0") + .Case("t5", "t1") + .Case("t6", "t2") + .Case("t7", "t3") + .Default(""); + assert(FixedName != "" && "Register name is not one of t4-t7."); + + printWarningWithFixIt("register names $t4-$t7 are only available in O32.", + "Did you mean $" + FixedName + "?", RegRange); + } + // Although SGI documentation just cuts out t0-t3 for n32/n64, // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. Index: test/MC/Mips/mips64-register-names-n32-n64.s =================================================================== --- test/MC/Mips/mips64-register-names-n32-n64.s +++ test/MC/Mips/mips64-register-names-n32-n64.s @@ -1,7 +1,11 @@ -# RUN: llvm-mc %s -triple=mips64-unknown-freebsd -show-encoding | FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-freebsd -show-encoding 2>%t0 \ +# RUN: | FileCheck %s +# RUN: FileCheck -check-prefix=WARNING %s < %t0 +# # RUN: llvm-mc %s -triple=mips64-unknown-freebsd -show-encoding \ -# RUN: -mattr=-n64,+n32 | FileCheck %s - +# RUN: -mattr=-n64,+n32 2>%t1 | FileCheck %s +# RUN: FileCheck -check-prefix=WARNING %s < %t1 +# # Check that the register names are mapped to their correct numbers for n32/n64 # Second byte of addiu with $zero at rt contains the number of the source # register. @@ -23,9 +27,25 @@ daddiu $t1, $zero, 0 # [*] # CHECK: encoding: [0x64,0x0d,0x00,0x00] daddiu $t2, $zero, 0 # [*] # CHECK: encoding: [0x64,0x0e,0x00,0x00] daddiu $t3, $zero, 0 # [*] # CHECK: encoding: [0x64,0x0f,0x00,0x00] +# WARNING: mips64-register-names-n32-n64.s:[[@LINE+4]]:9: warning: register names $t4-$t7 are only available in O32. +# WARNING-NEXT: daddiu $t4, $zero, 0 # {{CHECK}}: encoding: [0x64,0x0c,0x00,0x00] +# WARNING-NEXT: ^~ +# WARNING-NEXT: Did you mean $t0? daddiu $t4, $zero, 0 # CHECK: encoding: [0x64,0x0c,0x00,0x00] +# WARNING: mips64-register-names-n32-n64.s:[[@LINE+4]]:9: warning: register names $t4-$t7 are only available in O32. +# WARNING-NEXT: daddiu $t5, $zero, 0 # {{CHECK}}: encoding: [0x64,0x0d,0x00,0x00] +# WARNING-NEXT: ^~ +# WARNING-NEXT: Did you mean $t1? daddiu $t5, $zero, 0 # CHECK: encoding: [0x64,0x0d,0x00,0x00] +# WARNING: mips64-register-names-n32-n64.s:[[@LINE+4]]:9: warning: register names $t4-$t7 are only available in O32. +# WARNING-NEXT: daddiu $t6, $zero, 0 # {{CHECK}}: encoding: [0x64,0x0e,0x00,0x00] +# WARNING-NEXT: ^~ +# WARNING-NEXT: Did you mean $t2? daddiu $t6, $zero, 0 # CHECK: encoding: [0x64,0x0e,0x00,0x00] +# WARNING: mips64-register-names-n32-n64.s:[[@LINE+4]]:9: warning: register names $t4-$t7 are only available in O32. +# WARNING-NEXT: daddiu $t7, $zero, 0 # {{CHECK}}: encoding: [0x64,0x0f,0x00,0x00] +# WARNING-NEXT: ^~ +# WARNING-NEXT: Did you mean $t3? daddiu $t7, $zero, 0 # CHECK: encoding: [0x64,0x0f,0x00,0x00] daddiu $s0, $zero, 0 # CHECK: encoding: [0x64,0x10,0x00,0x00] daddiu $s1, $zero, 0 # CHECK: encoding: [0x64,0x11,0x00,0x00]