MIR Serialization: Serialize references from the stack objects to named allocas.

This commit serializes the references to the named LLVM alloca instructions from
the stack objects in the machine frame info. This commit adds a field 'Name' to
the struct 'yaml::MachineStackObject'. This new field is used to store the name
of the alloca instruction when the alloca is present and when it has a name.

llvm-svn: 242339
This commit is contained in:
Alex Lorenz 2015-07-15 22:14:49 +00:00
parent b9de106d04
commit 37643a04a4
6 changed files with 61 additions and 13 deletions

View File

@ -132,8 +132,9 @@ template <> struct MappingTraits<MachineBasicBlock> {
/// objects (Serialize local objects). /// objects (Serialize local objects).
struct MachineStackObject { struct MachineStackObject {
enum ObjectType { DefaultType, SpillSlot, VariableSized }; enum ObjectType { DefaultType, SpillSlot, VariableSized };
// TODO: Serialize LLVM alloca reference.
unsigned ID; unsigned ID;
StringValue Name;
// TODO: Serialize unnamed LLVM alloca reference.
ObjectType Type = DefaultType; ObjectType Type = DefaultType;
int64_t Offset = 0; int64_t Offset = 0;
uint64_t Size = 0; uint64_t Size = 0;
@ -151,6 +152,8 @@ template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
template <> struct MappingTraits<MachineStackObject> { template <> struct MappingTraits<MachineStackObject> {
static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
YamlIO.mapRequired("id", Object.ID); YamlIO.mapRequired("id", Object.ID);
YamlIO.mapOptional("name", Object.Name,
StringValue()); // Don't print out an empty name.
YamlIO.mapOptional( YamlIO.mapOptional(
"type", Object.Type, "type", Object.Type,
MachineStackObject::DefaultType); // Don't print the default type. MachineStackObject::DefaultType); // Don't print the default type.

View File

@ -108,7 +108,7 @@ public:
const yaml::MachineFunction &YamlMF, const yaml::MachineFunction &YamlMF,
DenseMap<unsigned, unsigned> &VirtualRegisterSlots); DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
bool initializeFrameInfo(MachineFrameInfo &MFI, bool initializeFrameInfo(const Function &F, MachineFrameInfo &MFI,
const yaml::MachineFunction &YamlMF); const yaml::MachineFunction &YamlMF);
private: private:
@ -264,7 +264,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF, if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
PFS.VirtualRegisterSlots)) PFS.VirtualRegisterSlots))
return true; return true;
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF)) if (initializeFrameInfo(*MF.getFunction(), *MF.getFrameInfo(), YamlMF))
return true; return true;
const auto &F = *MF.getFunction(); const auto &F = *MF.getFunction();
@ -366,7 +366,8 @@ bool MIRParserImpl::initializeRegisterInfo(
return false; return false;
} }
bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI, bool MIRParserImpl::initializeFrameInfo(const Function &F,
MachineFrameInfo &MFI,
const yaml::MachineFunction &YamlMF) { const yaml::MachineFunction &YamlMF) {
const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo; const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken); MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
@ -400,13 +401,23 @@ bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI,
// Initialize the ordinary frame objects. // Initialize the ordinary frame objects.
for (const auto &Object : YamlMF.StackObjects) { for (const auto &Object : YamlMF.StackObjects) {
int ObjectIdx; int ObjectIdx;
const AllocaInst *Alloca = nullptr;
const yaml::StringValue &Name = Object.Name;
if (!Name.Value.empty()) {
Alloca = dyn_cast_or_null<AllocaInst>(
F.getValueSymbolTable().lookup(Name.Value));
if (!Alloca)
return error(Name.SourceRange.Start,
"alloca instruction named '" + Name.Value +
"' isn't defined in the function '" + F.getName() +
"'");
}
if (Object.Type == yaml::MachineStackObject::VariableSized) if (Object.Type == yaml::MachineStackObject::VariableSized)
ObjectIdx = ObjectIdx = MFI.CreateVariableSizedObject(Object.Alignment, Alloca);
MFI.CreateVariableSizedObject(Object.Alignment, /*Alloca=*/nullptr);
else else
ObjectIdx = MFI.CreateStackObject( ObjectIdx = MFI.CreateStackObject(
Object.Size, Object.Alignment, Object.Size, Object.Alignment,
Object.Type == yaml::MachineStackObject::SpillSlot); Object.Type == yaml::MachineStackObject::SpillSlot, Alloca);
MFI.setObjectOffset(ObjectIdx, Object.Offset); MFI.setObjectOffset(ObjectIdx, Object.Offset);
// TODO: Store the mapping between object IDs and object indices to parse // TODO: Store the mapping between object IDs and object indices to parse
// stack object references correctly. // stack object references correctly.

View File

@ -19,6 +19,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h" #include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
@ -199,6 +200,9 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
yaml::MachineStackObject YamlObject; yaml::MachineStackObject YamlObject;
YamlObject.ID = ID++; YamlObject.ID = ID++;
if (const auto *Alloca = MFI.getObjectAllocation(I))
YamlObject.Name.Value =
Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>";
YamlObject.Type = MFI.isSpillSlotObjectIndex(I) YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
? yaml::MachineStackObject::SpillSlot ? yaml::MachineStackObject::SpillSlot
: MFI.isVariableSizedObjectIndex(I) : MFI.isVariableSizedObjectIndex(I)

View File

@ -0,0 +1,30 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
# This test ensures that the MIR parser reports an error when it encounters a
# stack object with a name that can't be associated with an alloca instruction.
--- |
define i32 @test(i32 %a) {
entry:
%b = alloca i32
store i32 %a, i32* %b
%c = load i32, i32* %b
ret i32 %c
}
...
---
name: test
frameInfo:
maxAlignment: 4
stack:
# CHECK: [[@LINE+1]]:20: alloca instruction named 'x' isn't defined in the function 'test'
- { id: 0, name: x, offset: -12, size: 4, alignment: 4 }
body:
- id: 0
name: entry
instructions:
- 'MOV32mr %rsp, 1, _, -4, _, %edi'
- '%eax = MOV32rm %rsp, 1, _, -4, _'
- 'RETQ %eax'
...

View File

@ -21,12 +21,12 @@ name: test
frameInfo: frameInfo:
maxAlignment: 8 maxAlignment: 8
# CHECK: stack: # CHECK: stack:
# CHECK-NEXT: - { id: 0, offset: -12, size: 4, alignment: 4 } # CHECK-NEXT: - { id: 0, name: b, offset: -12, size: 4, alignment: 4 }
# CHECK-NEXT: - { id: 1, offset: -24, size: 8, alignment: 8 } # CHECK-NEXT: - { id: 1, name: x, offset: -24, size: 8, alignment: 8 }
# CHECK-NEXT: - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 } # CHECK-NEXT: - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
stack: stack:
- { id: 0, offset: -12, size: 4, alignment: 4 } - { id: 0, name: b, offset: -12, size: 4, alignment: 4 }
- { id: 1, offset: -24, size: 8, alignment: 8 } - { id: 1, name: x, offset: -24, size: 8, alignment: 8 }
- { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 } - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
body: body:
- id: 0 - id: 0

View File

@ -26,11 +26,11 @@ frameInfo:
# CHECK: stack: # CHECK: stack:
# CHECK-NEXT: - { id: 0, offset: -20, size: 4, alignment: 4 } # CHECK-NEXT: - { id: 0, offset: -20, size: 4, alignment: 4 }
# CHECK-NEXT: - { id: 1, offset: -32, size: 8, alignment: 8 } # CHECK-NEXT: - { id: 1, offset: -32, size: 8, alignment: 8 }
# CHECK-NEXT: - { id: 2, type: variable-sized, offset: -32, alignment: 1 } # CHECK-NEXT: - { id: 2, name: y, type: variable-sized, offset: -32, alignment: 1 }
stack: stack:
- { id: 0, offset: -20, size: 4, alignment: 4 } - { id: 0, offset: -20, size: 4, alignment: 4 }
- { id: 1, offset: -32, size: 8, alignment: 8 } - { id: 1, offset: -32, size: 8, alignment: 8 }
- { id: 2, type: variable-sized, offset: -32, alignment: 1 } - { id: 2, name: y, type: variable-sized, offset: -32, alignment: 1 }
body: body:
- id: 0 - id: 0
name: entry name: entry