mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-29 10:25:12 +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:
@@ -115,9 +115,22 @@ static Cursor maybeLexMachineBasicBlock(
|
|||||||
return C;
|
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) {
|
static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
|
||||||
if (C.peek() != '%')
|
if (C.peek() != '%')
|
||||||
return None;
|
return None;
|
||||||
|
if (isdigit(C.peek(1)))
|
||||||
|
return lexVirtualRegister(C, Token);
|
||||||
auto Range = C;
|
auto Range = C;
|
||||||
C.advance(); // Skip '%'
|
C.advance(); // Skip '%'
|
||||||
while (isIdentifierChar(C.peek()))
|
while (isIdentifierChar(C.peek()))
|
||||||
|
@@ -51,7 +51,8 @@ struct MIToken {
|
|||||||
GlobalValue,
|
GlobalValue,
|
||||||
|
|
||||||
// Other tokens
|
// Other tokens
|
||||||
IntegerLiteral
|
IntegerLiteral,
|
||||||
|
VirtualRegister
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -73,7 +74,8 @@ public:
|
|||||||
bool isError() const { return Kind == Error; }
|
bool isError() const { return Kind == Error; }
|
||||||
|
|
||||||
bool isRegister() const {
|
bool isRegister() const {
|
||||||
return Kind == NamedRegister || Kind == underscore;
|
return Kind == NamedRegister || Kind == underscore ||
|
||||||
|
Kind == VirtualRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRegisterFlag() const {
|
bool isRegisterFlag() const {
|
||||||
@@ -93,7 +95,7 @@ public:
|
|||||||
|
|
||||||
bool hasIntegerValue() const {
|
bool hasIntegerValue() const {
|
||||||
return Kind == IntegerLiteral || Kind == MachineBasicBlock ||
|
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 + "'");
|
return error(Twine("unknown register name '") + Name + "'");
|
||||||
break;
|
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.
|
// TODO: Parse other register kinds.
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("The current token should be a register");
|
llvm_unreachable("The current token should be a register");
|
||||||
@@ -425,6 +436,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
|
|||||||
case MIToken::kw_undef:
|
case MIToken::kw_undef:
|
||||||
case MIToken::underscore:
|
case MIToken::underscore:
|
||||||
case MIToken::NamedRegister:
|
case MIToken::NamedRegister:
|
||||||
|
case MIToken::VirtualRegister:
|
||||||
return parseRegisterOperand(Dest);
|
return parseRegisterOperand(Dest);
|
||||||
case MIToken::IntegerLiteral:
|
case MIToken::IntegerLiteral:
|
||||||
return parseImmediateOperand(Dest);
|
return parseImmediateOperand(Dest);
|
||||||
|
@@ -28,6 +28,7 @@ class SourceMgr;
|
|||||||
|
|
||||||
struct PerFunctionMIParsingState {
|
struct PerFunctionMIParsingState {
|
||||||
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
|
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
|
||||||
|
DenseMap<unsigned, unsigned> VirtualRegisterSlots;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF,
|
bool parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF,
|
||||||
|
@@ -102,9 +102,11 @@ public:
|
|||||||
const yaml::MachineBasicBlock &YamlMBB,
|
const yaml::MachineBasicBlock &YamlMBB,
|
||||||
const PerFunctionMIParsingState &PFS);
|
const PerFunctionMIParsingState &PFS);
|
||||||
|
|
||||||
bool initializeRegisterInfo(const MachineFunction &MF,
|
bool
|
||||||
|
initializeRegisterInfo(const MachineFunction &MF,
|
||||||
MachineRegisterInfo &RegInfo,
|
MachineRegisterInfo &RegInfo,
|
||||||
const yaml::MachineFunction &YamlMF);
|
const yaml::MachineFunction &YamlMF,
|
||||||
|
DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
|
||||||
|
|
||||||
bool initializeFrameInfo(MachineFrameInfo &MFI,
|
bool initializeFrameInfo(MachineFrameInfo &MFI,
|
||||||
const yaml::MachineFunction &YamlMF);
|
const yaml::MachineFunction &YamlMF);
|
||||||
@@ -258,12 +260,13 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
|
|||||||
MF.setAlignment(YamlMF.Alignment);
|
MF.setAlignment(YamlMF.Alignment);
|
||||||
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
|
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
|
||||||
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
|
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
|
||||||
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
|
PerFunctionMIParsingState PFS;
|
||||||
|
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
|
||||||
|
PFS.VirtualRegisterSlots))
|
||||||
return true;
|
return true;
|
||||||
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
|
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
PerFunctionMIParsingState PFS;
|
|
||||||
const auto &F = *MF.getFunction();
|
const auto &F = *MF.getFunction();
|
||||||
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
|
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
|
||||||
const BasicBlock *BB = nullptr;
|
const BasicBlock *BB = nullptr;
|
||||||
@@ -330,7 +333,8 @@ bool MIRParserImpl::initializeMachineBasicBlock(
|
|||||||
|
|
||||||
bool MIRParserImpl::initializeRegisterInfo(
|
bool MIRParserImpl::initializeRegisterInfo(
|
||||||
const MachineFunction &MF, MachineRegisterInfo &RegInfo,
|
const MachineFunction &MF, MachineRegisterInfo &RegInfo,
|
||||||
const yaml::MachineFunction &YamlMF) {
|
const yaml::MachineFunction &YamlMF,
|
||||||
|
DenseMap<unsigned, unsigned> &VirtualRegisterSlots) {
|
||||||
assert(RegInfo.isSSA());
|
assert(RegInfo.isSSA());
|
||||||
if (!YamlMF.IsSSA)
|
if (!YamlMF.IsSSA)
|
||||||
RegInfo.leaveSSA();
|
RegInfo.leaveSSA();
|
||||||
@@ -346,9 +350,10 @@ bool MIRParserImpl::initializeRegisterInfo(
|
|||||||
return error(VReg.Class.SourceRange.Start,
|
return error(VReg.Class.SourceRange.Start,
|
||||||
Twine("use of undefined register class '") +
|
Twine("use of undefined register class '") +
|
||||||
VReg.Class.Value + "'");
|
VReg.Class.Value + "'");
|
||||||
// TODO: create the mapping from IDs to registers so that the virtual
|
unsigned Reg = RegInfo.createVirtualRegister(RC);
|
||||||
// register references can be parsed correctly.
|
// TODO: Report an error when the same virtual register with the same ID is
|
||||||
RegInfo.createVirtualRegister(RC);
|
// redefined.
|
||||||
|
VirtualRegisterSlots.insert(std::make_pair(VReg.ID, Reg));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -250,9 +250,10 @@ void MIPrinter::print(const MachineInstr &MI) {
|
|||||||
static void printReg(unsigned Reg, raw_ostream &OS,
|
static void printReg(unsigned Reg, raw_ostream &OS,
|
||||||
const TargetRegisterInfo *TRI) {
|
const TargetRegisterInfo *TRI) {
|
||||||
// TODO: Print Stack Slots.
|
// TODO: Print Stack Slots.
|
||||||
// TODO: Print virtual registers.
|
|
||||||
if (!Reg)
|
if (!Reg)
|
||||||
OS << '_';
|
OS << '_';
|
||||||
|
else if (TargetRegisterInfo::isVirtualRegister(Reg))
|
||||||
|
OS << '%' << TargetRegisterInfo::virtReg2Index(Reg);
|
||||||
else if (Reg < TRI->getNumRegs())
|
else if (Reg < TRI->getNumRegs())
|
||||||
OS << '%' << StringRef(TRI->getName(Reg)).lower();
|
OS << '%' << StringRef(TRI->getName(Reg)).lower();
|
||||||
else
|
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
|
# 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
|
# This test ensures that the MIR parser parses virtual register definitions and
|
||||||
# correctly.
|
# references correctly.
|
||||||
|
|
||||||
--- |
|
--- |
|
||||||
|
|
||||||
@@ -16,6 +16,18 @@
|
|||||||
ret i32 %a
|
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
|
name: bar
|
||||||
@@ -31,5 +43,63 @@ registers:
|
|||||||
- { id: 2, class: gr32 }
|
- { id: 2, class: gr32 }
|
||||||
body:
|
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'
|
||||||
...
|
...
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user