mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-02 16:56:50 +00:00
MIR Serialization: Serialize the virtual register definitions.
The virtual registers are serialized using a YAML sequence of YAML inline mappings. Each mapping has the id of the virtual register and the register class. Reviewers: Duncan P. N. Exon Smith Differential Revision: http://reviews.llvm.org/D10981 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241868 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
81e7e2dfab
commit
ad6702ec23
@ -81,6 +81,21 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
|
||||
struct VirtualRegisterDefinition {
|
||||
unsigned ID;
|
||||
StringValue Class;
|
||||
// TODO: Serialize the virtual register hints.
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<VirtualRegisterDefinition> {
|
||||
static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
|
||||
YamlIO.mapRequired("id", Reg.ID);
|
||||
YamlIO.mapRequired("class", Reg.Class);
|
||||
}
|
||||
|
||||
static const bool flow = true;
|
||||
};
|
||||
|
||||
struct MachineBasicBlock {
|
||||
unsigned ID;
|
||||
StringValue Name;
|
||||
@ -109,6 +124,7 @@ template <> struct MappingTraits<MachineBasicBlock> {
|
||||
} // end namespace yaml
|
||||
} // end namespace llvm
|
||||
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock)
|
||||
|
||||
namespace llvm {
|
||||
@ -169,7 +185,7 @@ struct MachineFunction {
|
||||
bool IsSSA = false;
|
||||
bool TracksRegLiveness = false;
|
||||
bool TracksSubRegLiveness = false;
|
||||
// TODO: Serialize virtual register definitions.
|
||||
std::vector<VirtualRegisterDefinition> VirtualRegisters;
|
||||
// TODO: Serialize the various register masks.
|
||||
// TODO: Serialize live in registers.
|
||||
// Frame information
|
||||
@ -187,6 +203,7 @@ template <> struct MappingTraits<MachineFunction> {
|
||||
YamlIO.mapOptional("isSSA", MF.IsSSA);
|
||||
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
|
||||
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
|
||||
YamlIO.mapOptional("registers", MF.VirtualRegisters);
|
||||
YamlIO.mapOptional("frameInfo", MF.FrameInfo);
|
||||
YamlIO.mapOptional("body", MF.BasicBlocks);
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ class MIRParserImpl {
|
||||
LLVMContext &Context;
|
||||
StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
|
||||
SlotMapping IRSlots;
|
||||
/// Maps from register class names to register classes.
|
||||
StringMap<const TargetRegisterClass *> Names2RegClasses;
|
||||
|
||||
public:
|
||||
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
|
||||
@ -100,7 +102,8 @@ public:
|
||||
const yaml::MachineBasicBlock &YamlMBB,
|
||||
const PerFunctionMIParsingState &PFS);
|
||||
|
||||
bool initializeRegisterInfo(MachineRegisterInfo &RegInfo,
|
||||
bool initializeRegisterInfo(const MachineFunction &MF,
|
||||
MachineRegisterInfo &RegInfo,
|
||||
const yaml::MachineFunction &YamlMF);
|
||||
|
||||
bool initializeFrameInfo(MachineFrameInfo &MFI,
|
||||
@ -117,6 +120,14 @@ private:
|
||||
|
||||
/// Create an empty function with the given name.
|
||||
void createDummyFunction(StringRef Name, Module &M);
|
||||
|
||||
void initNames2RegClasses(const MachineFunction &MF);
|
||||
|
||||
/// Check if the given identifier is a name of a register class.
|
||||
///
|
||||
/// Return null if the name isn't a register class.
|
||||
const TargetRegisterClass *getRegClass(const MachineFunction &MF,
|
||||
StringRef Name);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
@ -247,7 +258,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
|
||||
MF.setAlignment(YamlMF.Alignment);
|
||||
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
|
||||
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
|
||||
if (initializeRegisterInfo(MF.getRegInfo(), YamlMF))
|
||||
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
|
||||
return true;
|
||||
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF.FrameInfo))
|
||||
return true;
|
||||
@ -318,7 +329,8 @@ bool MIRParserImpl::initializeMachineBasicBlock(
|
||||
}
|
||||
|
||||
bool MIRParserImpl::initializeRegisterInfo(
|
||||
MachineRegisterInfo &RegInfo, const yaml::MachineFunction &YamlMF) {
|
||||
const MachineFunction &MF, MachineRegisterInfo &RegInfo,
|
||||
const yaml::MachineFunction &YamlMF) {
|
||||
assert(RegInfo.isSSA());
|
||||
if (!YamlMF.IsSSA)
|
||||
RegInfo.leaveSSA();
|
||||
@ -326,6 +338,18 @@ bool MIRParserImpl::initializeRegisterInfo(
|
||||
if (!YamlMF.TracksRegLiveness)
|
||||
RegInfo.invalidateLiveness();
|
||||
RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness);
|
||||
|
||||
// Parse the virtual register information.
|
||||
for (const auto &VReg : YamlMF.VirtualRegisters) {
|
||||
const auto *RC = getRegClass(MF, VReg.Class.Value);
|
||||
if (!RC)
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -395,6 +419,26 @@ SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
|
||||
Error.getFixIts());
|
||||
}
|
||||
|
||||
void MIRParserImpl::initNames2RegClasses(const MachineFunction &MF) {
|
||||
if (!Names2RegClasses.empty())
|
||||
return;
|
||||
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
|
||||
for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; ++I) {
|
||||
const auto *RC = TRI->getRegClass(I);
|
||||
Names2RegClasses.insert(
|
||||
std::make_pair(StringRef(TRI->getRegClassName(RC)).lower(), RC));
|
||||
}
|
||||
}
|
||||
|
||||
const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,
|
||||
StringRef Name) {
|
||||
initNames2RegClasses(MF);
|
||||
auto RegClassInfo = Names2RegClasses.find(Name);
|
||||
if (RegClassInfo == Names2RegClasses.end())
|
||||
return nullptr;
|
||||
return RegClassInfo->getValue();
|
||||
}
|
||||
|
||||
MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
|
||||
: Impl(std::move(Impl)) {}
|
||||
|
||||
|
@ -42,7 +42,8 @@ public:
|
||||
|
||||
void print(const MachineFunction &MF);
|
||||
|
||||
void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
|
||||
void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI);
|
||||
void convert(yaml::MachineFrameInfo &YamlMFI, const MachineFrameInfo &MFI);
|
||||
void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB,
|
||||
const MachineBasicBlock &MBB);
|
||||
@ -95,7 +96,7 @@ void MIRPrinter::print(const MachineFunction &MF) {
|
||||
YamlMF.Alignment = MF.getAlignment();
|
||||
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
|
||||
YamlMF.HasInlineAsm = MF.hasInlineAsm();
|
||||
convert(YamlMF, MF.getRegInfo());
|
||||
convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
|
||||
convert(YamlMF.FrameInfo, *MF.getFrameInfo());
|
||||
|
||||
int I = 0;
|
||||
@ -117,10 +118,21 @@ void MIRPrinter::print(const MachineFunction &MF) {
|
||||
}
|
||||
|
||||
void MIRPrinter::convert(yaml::MachineFunction &MF,
|
||||
const MachineRegisterInfo &RegInfo) {
|
||||
const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
MF.IsSSA = RegInfo.isSSA();
|
||||
MF.TracksRegLiveness = RegInfo.tracksLiveness();
|
||||
MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
|
||||
|
||||
// Print the virtual register definitions.
|
||||
for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
|
||||
unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
|
||||
yaml::VirtualRegisterDefinition VReg;
|
||||
VReg.ID = I;
|
||||
VReg.Class =
|
||||
StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
|
||||
MF.VirtualRegisters.push_back(VReg);
|
||||
}
|
||||
}
|
||||
|
||||
void MIRPrinter::convert(yaml::MachineFrameInfo &YamlMFI,
|
||||
|
26
test/CodeGen/MIR/X86/undefined-register-class.mir
Normal file
26
test/CodeGen/MIR/X86/undefined-register-class.mir
Normal file
@ -0,0 +1,26 @@
|
||||
# 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 it encounters an
|
||||
# unknown register class.
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32 %a) {
|
||||
entry:
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
isSSA: true
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
# CHECK: [[@LINE+1]]:20: use of undefined register class 'gr3200'
|
||||
- {id: 0, class: 'gr3200'}
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
instructions:
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
35
test/CodeGen/MIR/X86/virtual-registers.mir
Normal file
35
test/CodeGen/MIR/X86/virtual-registers.mir
Normal file
@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @bar(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
|
||||
isSSA: true
|
||||
tracksRegLiveness: true
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 1, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 2, class: gr32 }
|
||||
registers:
|
||||
- { id: 0, class: gr32 }
|
||||
- { id: 1, class: gr32 }
|
||||
- { id: 2, class: gr32 }
|
||||
body:
|
||||
- id: 0
|
||||
...
|
||||
|
Loading…
Reference in New Issue
Block a user