mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-04 22:07:27 +00:00
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:
parent
c3b47b30ab
commit
1cca87a981
@ -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()))
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -28,6 +28,7 @@ class SourceMgr;
|
||||
|
||||
struct PerFunctionMIParsingState {
|
||||
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
|
||||
DenseMap<unsigned, unsigned> VirtualRegisterSlots;
|
||||
};
|
||||
|
||||
bool parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
28
test/CodeGen/MIR/X86/undefined-virtual-register.mir
Normal file
28
test/CodeGen/MIR/X86/undefined-virtual-register.mir
Normal 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'
|
||||
...
|
||||
|
@ -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'
|
||||
...
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user