MIR Serialization: Serialize the virtual register operands.

Reviewers: Duncan P. N. Exon Smith

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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241959 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alex Lorenz 2015-07-10 22:51:20 +00:00
parent c3b47b30ab
commit 1cca87a981
8 changed files with 149 additions and 17 deletions

View File

@ -115,9 +115,22 @@ static Cursor maybeLexMachineBasicBlock(
return C;
}
static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
auto Range = C;
C.advance(); // Skip '%'
auto NumberRange = C;
while (isdigit(C.peek()))
C.advance();
Token = MIToken(MIToken::VirtualRegister, Range.upto(C),
APSInt(NumberRange.upto(C)));
return C;
}
static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
if (C.peek() != '%')
return None;
if (isdigit(C.peek(1)))
return lexVirtualRegister(C, Token);
auto Range = C;
C.advance(); // Skip '%'
while (isIdentifierChar(C.peek()))

View File

@ -51,7 +51,8 @@ struct MIToken {
GlobalValue,
// Other tokens
IntegerLiteral
IntegerLiteral,
VirtualRegister
};
private:
@ -73,7 +74,8 @@ public:
bool isError() const { return Kind == Error; }
bool isRegister() const {
return Kind == NamedRegister || Kind == underscore;
return Kind == NamedRegister || Kind == underscore ||
Kind == VirtualRegister;
}
bool isRegisterFlag() const {
@ -93,7 +95,7 @@ public:
bool hasIntegerValue() const {
return Kind == IntegerLiteral || Kind == MachineBasicBlock ||
Kind == GlobalValue;
Kind == GlobalValue || Kind == VirtualRegister;
}
};

View File

@ -288,6 +288,17 @@ bool MIParser::parseRegister(unsigned &Reg) {
return error(Twine("unknown register name '") + Name + "'");
break;
}
case MIToken::VirtualRegister: {
unsigned ID;
if (getUnsigned(ID))
return true;
const auto RegInfo = PFS.VirtualRegisterSlots.find(ID);
if (RegInfo == PFS.VirtualRegisterSlots.end())
return error(Twine("use of undefined virtual register '%") + Twine(ID) +
"'");
Reg = RegInfo->second;
break;
}
// TODO: Parse other register kinds.
default:
llvm_unreachable("The current token should be a register");
@ -425,6 +436,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
case MIToken::kw_undef:
case MIToken::underscore:
case MIToken::NamedRegister:
case MIToken::VirtualRegister:
return parseRegisterOperand(Dest);
case MIToken::IntegerLiteral:
return parseImmediateOperand(Dest);

View File

@ -28,6 +28,7 @@ class SourceMgr;
struct PerFunctionMIParsingState {
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
DenseMap<unsigned, unsigned> VirtualRegisterSlots;
};
bool parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF,

View File

@ -102,9 +102,11 @@ public:
const yaml::MachineBasicBlock &YamlMBB,
const PerFunctionMIParsingState &PFS);
bool initializeRegisterInfo(const MachineFunction &MF,
MachineRegisterInfo &RegInfo,
const yaml::MachineFunction &YamlMF);
bool
initializeRegisterInfo(const MachineFunction &MF,
MachineRegisterInfo &RegInfo,
const yaml::MachineFunction &YamlMF,
DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
bool initializeFrameInfo(MachineFrameInfo &MFI,
const yaml::MachineFunction &YamlMF);
@ -258,12 +260,13 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
PerFunctionMIParsingState PFS;
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
PFS.VirtualRegisterSlots))
return true;
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
return true;
PerFunctionMIParsingState PFS;
const auto &F = *MF.getFunction();
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
const BasicBlock *BB = nullptr;
@ -330,7 +333,8 @@ bool MIRParserImpl::initializeMachineBasicBlock(
bool MIRParserImpl::initializeRegisterInfo(
const MachineFunction &MF, MachineRegisterInfo &RegInfo,
const yaml::MachineFunction &YamlMF) {
const yaml::MachineFunction &YamlMF,
DenseMap<unsigned, unsigned> &VirtualRegisterSlots) {
assert(RegInfo.isSSA());
if (!YamlMF.IsSSA)
RegInfo.leaveSSA();
@ -346,9 +350,10 @@ bool MIRParserImpl::initializeRegisterInfo(
return error(VReg.Class.SourceRange.Start,
Twine("use of undefined register class '") +
VReg.Class.Value + "'");
// TODO: create the mapping from IDs to registers so that the virtual
// register references can be parsed correctly.
RegInfo.createVirtualRegister(RC);
unsigned Reg = RegInfo.createVirtualRegister(RC);
// TODO: Report an error when the same virtual register with the same ID is
// redefined.
VirtualRegisterSlots.insert(std::make_pair(VReg.ID, Reg));
}
return false;
}

View File

@ -250,9 +250,10 @@ void MIPrinter::print(const MachineInstr &MI) {
static void printReg(unsigned Reg, raw_ostream &OS,
const TargetRegisterInfo *TRI) {
// TODO: Print Stack Slots.
// TODO: Print virtual registers.
if (!Reg)
OS << '_';
else if (TargetRegisterInfo::isVirtualRegister(Reg))
OS << '%' << TargetRegisterInfo::virtReg2Index(Reg);
else if (Reg < TRI->getNumRegs())
OS << '%' << StringRef(TRI->getName(Reg)).lower();
else

View File

@ -0,0 +1,28 @@
# RUN: not llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser reports an error when parsing a
# reference to an undefined virtual register.
--- |
define i32 @test(i32 %a) {
entry:
ret i32 %a
}
...
---
name: test
isSSA: true
tracksRegLiveness: true
registers:
- { id: 0, class: gr32 }
body:
- id: 0
name: entry
instructions:
- '%0 = COPY %edi'
# CHECK: [[@LINE+1]]:22: use of undefined virtual register '%10'
- '%eax = COPY %10'
- 'RETQ %eax'
...

View File

@ -1,6 +1,6 @@
# RUN: llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s | FileCheck %s
# This test ensures that the MIR parser parses virtual register definitions
# correctly.
# This test ensures that the MIR parser parses virtual register definitions and
# references correctly.
--- |
@ -16,6 +16,18 @@
ret i32 %a
}
define i32 @foo(i32 %a) {
entry:
%0 = icmp sle i32 %a, 10
br i1 %0, label %less, label %exit
less:
ret i32 0
exit:
ret i32 %a
}
...
---
name: bar
@ -30,6 +42,64 @@ registers:
- { id: 1, class: gr32 }
- { id: 2, class: gr32 }
body:
- id: 0
- id: 0
name: entry
# CHECK: %0 = COPY %edi
# CHECK-NEXT: %1 = SUB32ri8 %0, 10
instructions:
- '%0 = COPY %edi'
- '%1 = SUB32ri8 %0, 10, implicit-def %eflags'
- 'JG_1 %bb.2.exit, implicit %eflags'
- 'JMP_1 %bb.1.less'
- id: 1
name: less
# CHECK: %2 = MOV32r0
# CHECK-NEXT: %eax = COPY %2
instructions:
- '%2 = MOV32r0 implicit-def %eflags'
- '%eax = COPY %2'
- 'RETQ %eax'
- id: 2
name: exit
instructions:
- '%eax = COPY %0'
- 'RETQ %eax'
...
---
name: foo
isSSA: true
tracksRegLiveness: true
# CHECK: name: foo
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gr32 }
# CHECK-NEXT: - { id: 1, class: gr32 }
# CHECK-NEXT: - { id: 2, class: gr32 }
registers:
- { id: 2, class: gr32 }
- { id: 0, class: gr32 }
- { id: 10, class: gr32 }
body:
- id: 0
name: entry
# CHECK: %0 = COPY %edi
# CHECK-NEXT: %1 = SUB32ri8 %0, 10
instructions:
- '%2 = COPY %edi'
- '%0 = SUB32ri8 %2, 10, implicit-def %eflags'
- 'JG_1 %bb.2.exit, implicit %eflags'
- 'JMP_1 %bb.1.less'
- id: 1
name: less
# CHECK: %2 = MOV32r0
# CHECK-NEXT: %eax = COPY %2
instructions:
- '%10 = MOV32r0 implicit-def %eflags'
- '%eax = COPY %10'
- 'RETQ %eax'
- id: 2
name: exit
# CHECK: %eax = COPY %0
instructions:
- '%eax = COPY %2'
- 'RETQ %eax'
...