Index: lib/CodeGen/MIRParser/MIParser.h =================================================================== --- lib/CodeGen/MIRParser/MIParser.h +++ lib/CodeGen/MIRParser/MIParser.h @@ -46,9 +46,11 @@ }; struct PerFunctionMIParsingState { + typedef StringMap Name2RegClassMap; MachineFunction &MF; SourceMgr *SM; const SlotMapping &IRSlots; + const Name2RegClassMap &Names2RegClasses; DenseMap MBBSlots; std::vector VRegInfos; @@ -58,7 +60,8 @@ DenseMap JumpTableSlots; PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, - const SlotMapping &IRSlots); + const SlotMapping &IRSlots, + const Name2RegClassMap &Names2RegClasses); VRegInfo &getVRegInfo(unsigned VReg); }; Index: lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIParser.cpp +++ lib/CodeGen/MIRParser/MIParser.cpp @@ -37,8 +37,9 @@ using namespace llvm; PerFunctionMIParsingState::PerFunctionMIParsingState(MachineFunction &MF, - SourceMgr &SM, const SlotMapping &IRSlots) - : MF(MF), SM(&SM), IRSlots(IRSlots) { + SourceMgr &SM, const SlotMapping &IRSlots, + const Name2RegClassMap &Names2RegClasses) + : MF(MF), SM(&SM), IRSlots(IRSlots), Names2RegClasses(Names2RegClasses) { } VRegInfo &PerFunctionMIParsingState::getVRegInfo(unsigned VReg) { @@ -134,6 +135,7 @@ bool parseRegister(unsigned &Reg); bool parseRegisterFlag(unsigned &Flags); + bool parseRegisterClass(const TargetRegisterClass *&RC); bool parseSubRegisterIndex(unsigned &SubReg); bool parseRegisterTiedDefIndex(unsigned &TiedDefIdx); bool parseSize(unsigned &Size); @@ -840,6 +842,18 @@ return false; } +bool MIParser::parseRegisterClass(const TargetRegisterClass *&RC) { + if (Token.isNot(MIToken::Identifier)) + return error("expected a register class name"); + StringRef RCName = Token.stringValue(); + auto RCNameI = PFS.Names2RegClasses.find(RCName); + if (RCNameI == PFS.Names2RegClasses.end()) + return error("expected a register class name"); + RC = RCNameI->getValue(); + lex(); + return false; +} + bool MIParser::parseRegisterFlag(unsigned &Flags) { const unsigned OldFlags = Flags; switch (Token.kind()) { @@ -976,6 +990,33 @@ if (!TargetRegisterInfo::isVirtualRegister(Reg)) return error("subregister index expects a virtual register"); } + if (Token.is(MIToken::colon)) { + StringRef::iterator Loc = Token.location(); + lex(); + const TargetRegisterClass *RC; + if (parseRegisterClass(RC)) + return true; + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return error(Loc, + "register class specification expects a virtual register"); + VRegInfo &Info = PFS.getVRegInfo(Reg); + switch (Info.Kind) { + case VRegInfo::UNKNOWN: + Info.Kind = VRegInfo::NORMAL; + break; + case VRegInfo::GENERIC: + case VRegInfo::REGBANK: + return error(Loc, + "register class specification expects a virtual register"); + case VRegInfo::NORMAL: + break; + } + + if (Info.Explicit && Info.D.RC != RC) + return error(Loc, "conflicting register class"); + Info.D.RC = RC; + Info.Explicit = true; + } if ((Flags & RegState::Define) == 0) { if (consumeIfPresent(MIToken::lparen)) { unsigned Idx; Index: lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIRParser.cpp +++ lib/CodeGen/MIRParser/MIRParser.cpp @@ -285,6 +285,7 @@ return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. + initNames2RegClasses(MF); const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); @@ -292,7 +293,7 @@ MF.setHasInlineAsm(YamlMF.HasInlineAsm); if (YamlMF.AllVRegsAllocated) MF.getProperties().set(MachineFunctionProperties::Property::AllVRegsAllocated); - PerFunctionMIParsingState PFS(MF, SM, IRSlots); + PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses); if (parseRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { @@ -776,7 +777,6 @@ const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF, StringRef Name) { - initNames2RegClasses(MF); auto RegClassInfo = Names2RegClasses.find(Name); if (RegClassInfo == Names2RegClasses.end()) return nullptr; Index: test/CodeGen/MIR/X86/register-operand-class-invalid0.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/register-operand-class-invalid0.mir @@ -0,0 +1,13 @@ +# RUN: not llc -march=x86-64 -run-pass machine-sink -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that an error is reported for specifying the register class +# of a physical register. +--- | + define void @t() { ret void } +... +--- +name: t +body: | + bb.0: + ; CHECK: [[@LINE+1]]:10: register class specification expects a virtual register + %eax : gr32 = COPY %rdx +... Index: test/CodeGen/MIR/X86/register-operand-class-invalid1.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/register-operand-class-invalid1.mir @@ -0,0 +1,14 @@ +# RUN: not llc -march=x86-64 -run-pass machine-sink -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that an error is reported for specifying the register class +# of a physical register. +--- | + define void @t() { ret void } +... +--- +name: t +body: | + bb.0: + %0 : gr32 = COPY %rdx + ; CHECK: [[@LINE+1]]:22: conflicting register class + NOOP implicit %0 : gr32_abcd +... Index: test/CodeGen/MIR/X86/register-operand-class.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/X86/register-operand-class.mir @@ -0,0 +1,25 @@ +# RUN: llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o - %s | FileCheck %s +# Test various aspects of register class specification on machine operands. +--- | + define void @f() { ret void } +... +--- +# CHECK-LABEL: name: f +# CHECK: registers: +# CHECK: - { id: 0, class: gr32 } +# CHECK: - { id: 1, class: gr64 } +# CHECK: - { id: 2, class: gr32 } +# CHECK: - { id: 3, class: gr16 } +name: f +isSSA: true +body: | + bb.0: + %0 : gr32 = COPY %rax + %1.sub_32bit : gr64 = COPY %eax + %rdx = COPY %1 + %2 = COPY %ecx + %ecx = COPY %2 : gr32 + + %3 : gr16 = COPY %bx + %bx = COPY %3 : gr16 +...