///
/// TODO: Determine isPreallocated flag by mapping between objects and local
/// objects (Serialize local objects).
-/// TODO: Serialize variable sized and fixed stack objects.
+/// TODO: Serialize variable sized objects.
struct MachineStackObject {
enum ObjectType { DefaultType, SpillSlot };
// TODO: Serialize LLVM alloca reference.
static const bool flow = true;
};
+/// Serializable representation of the fixed stack object from the
+/// MachineFrameInfo class.
+struct FixedMachineStackObject {
+ enum ObjectType { DefaultType, SpillSlot };
+ unsigned ID;
+ ObjectType Type = DefaultType;
+ int64_t Offset = 0;
+ uint64_t Size = 0;
+ unsigned Alignment = 0;
+ bool IsImmutable = false;
+ bool IsAliased = false;
+};
+
+template <>
+struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
+ static void enumeration(yaml::IO &IO,
+ FixedMachineStackObject::ObjectType &Type) {
+ IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
+ IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
+ }
+};
+
+template <> struct MappingTraits<FixedMachineStackObject> {
+ static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
+ YamlIO.mapRequired("id", Object.ID);
+ YamlIO.mapOptional(
+ "type", Object.Type,
+ FixedMachineStackObject::DefaultType); // Don't print the default type.
+ YamlIO.mapOptional("offset", Object.Offset);
+ YamlIO.mapOptional("size", Object.Size);
+ YamlIO.mapOptional("alignment", Object.Alignment);
+ if (Object.Type != FixedMachineStackObject::SpillSlot) {
+ YamlIO.mapOptional("isImmutable", Object.IsImmutable);
+ YamlIO.mapOptional("isAliased", Object.IsAliased);
+ }
+ }
+
+ static const bool flow = true;
+};
+
} // end namespace yaml
} // end namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
namespace llvm {
namespace yaml {
// TODO: Serialize live in registers.
// Frame information
MachineFrameInfo FrameInfo;
+ std::vector<FixedMachineStackObject> FixedStackObjects;
std::vector<MachineStackObject> StackObjects;
std::vector<MachineBasicBlock> BasicBlocks;
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
YamlIO.mapOptional("registers", MF.VirtualRegisters);
YamlIO.mapOptional("frameInfo", MF.FrameInfo);
+ YamlIO.mapOptional("fixedStack", MF.FixedStackObjects);
YamlIO.mapOptional("stack", MF.StackObjects);
YamlIO.mapOptional("body", MF.BasicBlocks);
}
MFI.setHasVAStart(YamlMFI.HasVAStart);
MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
- // Initialize the frame objects.
+ // Initialize the fixed frame objects.
+ for (const auto &Object : YamlMF.FixedStackObjects) {
+ int ObjectIdx;
+ if (Object.Type != yaml::FixedMachineStackObject::SpillSlot)
+ ObjectIdx = MFI.CreateFixedObject(Object.Size, Object.Offset,
+ Object.IsImmutable, Object.IsAliased);
+ else
+ ObjectIdx = MFI.CreateFixedSpillStackObject(Object.Size, Object.Offset);
+ MFI.setObjectAlignment(ObjectIdx, Object.Alignment);
+ // TODO: Store the mapping between fixed object IDs and object indices to
+ // parse fixed stack object references correctly.
+ }
+
+ // Initialize the ordinary frame objects.
for (const auto &Object : YamlMF.StackObjects) {
int ObjectIdx = MFI.CreateStackObject(
Object.Size, Object.Alignment,
void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
const MachineFrameInfo &MFI) {
+ // Process fixed stack objects.
unsigned ID = 0;
+ for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
+ if (MFI.isDeadObjectIndex(I))
+ continue;
+
+ yaml::FixedMachineStackObject YamlObject;
+ YamlObject.ID = ID++;
+ YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
+ ? yaml::FixedMachineStackObject::SpillSlot
+ : yaml::FixedMachineStackObject::DefaultType;
+ YamlObject.Offset = MFI.getObjectOffset(I);
+ YamlObject.Size = MFI.getObjectSize(I);
+ YamlObject.Alignment = MFI.getObjectAlignment(I);
+ YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
+ YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
+ MF.FixedStackObjects.push_back(YamlObject);
+ // TODO: Store the mapping between fixed object IDs and object indices to
+ // print the fixed stack object references correctly.
+ }
+
+ // Process ordinary stack objects.
+ ID = 0;
for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I) {
if (MFI.isDeadObjectIndex(I))
continue;
--- /dev/null
+# RUN: llc -march=x86 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser parses fixed stack objects correctly.
+
+--- |
+
+ define i32 @test(i32 %a) #0 {
+ entry:
+ %b = alloca i32
+ store i32 %a, i32* %b
+ %c = load i32, i32* %b
+ ret i32 %c
+ }
+
+ attributes #0 = { "no-frame-pointer-elim"="false" }
+
+...
+---
+name: test
+frameInfo:
+ stackSize: 4
+ maxAlignment: 4
+# CHECK: fixedStack:
+# CHECK-NEXT: - { id: 0, offset: 0, size: 4, alignment: 4, isImmutable: true, isAliased: false }
+fixedStack:
+ - { id: 0, offset: 0, size: 4, alignment: 4, isImmutable: true, isAliased: false }
+stack:
+ - { id: 0, offset: -8, size: 4, alignment: 4 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%eax = MOV32rm %esp, 1, _, 8, _'
+ - 'MOV32mr %esp, 1, _, 0, _, %eax'
+ - 'RETL %eax'
+...
--- /dev/null
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+ define i32 @test(i32 %a) #0 {
+ entry:
+ %b = alloca i32
+ store i32 %a, i32* %b
+ %c = load i32, i32* %b
+ ret i32 %c
+ }
+
+ attributes #0 = { "no-frame-pointer-elim"="false" }
+
+...
+---
+name: test
+frameInfo:
+ maxAlignment: 4
+fixedStack:
+ # CHECK: [[@LINE+1]]:63: unknown key 'isAliased'
+ - { id: 0, type: spill-slot, offset: 0, size: 4, isAliased: true }
+stack:
+ - { id: 0, offset: -12, size: 4, alignment: 4 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+ - '%eax = COPY %edi'
+ - 'RETQ %eax'
+...
--- /dev/null
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+ define i32 @test(i32 %a) #0 {
+ entry:
+ %b = alloca i32
+ store i32 %a, i32* %b
+ %c = load i32, i32* %b
+ ret i32 %c
+ }
+
+ attributes #0 = { "no-frame-pointer-elim"="false" }
+
+...
+---
+name: test
+frameInfo:
+ maxAlignment: 4
+fixedStack:
+ # CHECK: [[@LINE+1]]:65: unknown key 'isImmutable'
+ - { id: 0, type: spill-slot, offset: 0, size: 4, isImmutable: true }
+stack:
+ - { id: 0, offset: -12, size: 4, alignment: 4 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+ - '%eax = COPY %edi'
+ - 'RETQ %eax'
+...
--- /dev/null
+# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser parses fixed stack objects correctly.
+
+--- |
+
+ define i32 @test(i32 %a) #0 {
+ entry:
+ %b = alloca i32
+ store i32 %a, i32* %b
+ %c = load i32, i32* %b
+ ret i32 %c
+ }
+
+ attributes #0 = { "no-frame-pointer-elim"="false" }
+
+...
+---
+name: test
+frameInfo:
+ maxAlignment: 4
+# CHECK: fixedStack:
+# CHECK-NEXT: - { id: 0, type: spill-slot, offset: 0, size: 4, alignment: 4 }
+fixedStack:
+ - { id: 0, type: spill-slot, offset: 0, size: 4, alignment: 4 }
+stack:
+ - { id: 0, offset: -12, size: 4, alignment: 4 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+ - '%eax = COPY %edi'
+ - 'RETQ %eax'
+...