}
};
+/// Serializable representation of stack object from the MachineFrameInfo class.
+///
+/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
+/// determined by the object's type and frame information flags.
+/// Dead stack objects aren't serialized.
+///
+/// TODO: Determine isPreallocated flag by mapping between objects and local
+/// objects (Serialize local objects).
+/// TODO: Serialize variable sized and fixed stack objects.
+struct MachineStackObject {
+ enum ObjectType { DefaultType, SpillSlot };
+ // TODO: Serialize LLVM alloca reference.
+ unsigned ID;
+ ObjectType Type = DefaultType;
+ int64_t Offset = 0;
+ uint64_t Size = 0;
+ unsigned Alignment = 0;
+};
+
+template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
+ static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
+ IO.enumCase(Type, "default", MachineStackObject::DefaultType);
+ IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
+ }
+};
+
+template <> struct MappingTraits<MachineStackObject> {
+ static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
+ YamlIO.mapRequired("id", Object.ID);
+ YamlIO.mapOptional(
+ "type", Object.Type,
+ MachineStackObject::DefaultType); // Don't print the default type.
+ YamlIO.mapOptional("offset", Object.Offset);
+ YamlIO.mapRequired("size", Object.Size);
+ YamlIO.mapOptional("alignment", Object.Alignment);
+ }
+
+ 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)
namespace llvm {
namespace yaml {
/// It also doesn't serialize attributes like 'NumFixedObject' and
/// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
struct MachineFrameInfo {
- // TODO: Serialize stack objects.
bool IsFrameAddressTaken = false;
bool IsReturnAddressTaken = false;
bool HasStackMap = false;
// TODO: Serialize live in registers.
// Frame information
MachineFrameInfo FrameInfo;
+ 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("stack", MF.StackObjects);
YamlIO.mapOptional("body", MF.BasicBlocks);
}
};
const yaml::MachineFunction &YamlMF);
bool initializeFrameInfo(MachineFrameInfo &MFI,
- const yaml::MachineFrameInfo &YamlMFI);
+ const yaml::MachineFunction &YamlMF);
private:
/// Return a MIR diagnostic converted from an MI string diagnostic.
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
return true;
- if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF.FrameInfo))
+ if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
return true;
PerFunctionMIParsingState PFS;
}
bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI,
- const yaml::MachineFrameInfo &YamlMFI) {
+ const yaml::MachineFunction &YamlMF) {
+ const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken);
MFI.setHasStackMap(YamlMFI.HasStackMap);
MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);
MFI.setHasVAStart(YamlMFI.HasVAStart);
MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc);
+
+ // Initialize the frame objects.
+ for (const auto &Object : YamlMF.StackObjects) {
+ int ObjectIdx = MFI.CreateStackObject(
+ Object.Size, Object.Alignment,
+ Object.Type == yaml::MachineStackObject::SpillSlot);
+ MFI.setObjectOffset(ObjectIdx, Object.Offset);
+ // TODO: Store the mapping between object IDs and object indices to parse
+ // stack object references correctly.
+ }
return false;
}
void convert(yaml::MachineFrameInfo &YamlMFI, const MachineFrameInfo &MFI);
void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB,
const MachineBasicBlock &MBB);
+ void convertStackObjects(yaml::MachineFunction &MF,
+ const MachineFrameInfo &MFI);
private:
void initRegisterMaskIds(const MachineFunction &MF);
YamlMF.HasInlineAsm = MF.hasInlineAsm();
convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
convert(YamlMF.FrameInfo, *MF.getFrameInfo());
+ convertStackObjects(YamlMF, *MF.getFrameInfo());
int I = 0;
ModuleSlotTracker MST(MF.getFunction()->getParent());
YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc();
}
+void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
+ const MachineFrameInfo &MFI) {
+ unsigned ID = 0;
+ for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I) {
+ if (MFI.isDeadObjectIndex(I))
+ continue;
+
+ yaml::MachineStackObject YamlObject;
+ YamlObject.ID = ID++;
+ YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
+ ? yaml::MachineStackObject::SpillSlot
+ : yaml::MachineStackObject::DefaultType;
+ YamlObject.Offset = MFI.getObjectOffset(I);
+ YamlObject.Size = MFI.getObjectSize(I);
+ YamlObject.Alignment = MFI.getObjectAlignment(I);
+
+ MF.StackObjects.push_back(YamlObject);
+ // TODO: Store the mapping between object IDs and object indices to print
+ // the stack object references correctly.
+ }
+}
+
void MIRPrinter::convert(ModuleSlotTracker &MST,
yaml::MachineBasicBlock &YamlMBB,
const MachineBasicBlock &MBB) {
--- /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 stack objects correctly.
+
+--- |
+
+ define i32 @test(i32 %a) #0 {
+ entry:
+ %b = alloca i32
+ %x = alloca i64
+ store i32 %a, i32* %b
+ store i64 2, i64* %x
+ %c = load i32, i32* %b
+ ret i32 %c
+ }
+
+ attributes #0 = { "no-frame-pointer-elim"="false" }
+
+...
+---
+name: test
+frameInfo:
+ maxAlignment: 8
+# CHECK: stack:
+# CHECK-NEXT: - { id: 0, offset: -12, size: 4, alignment: 4 }
+# CHECK-NEXT: - { id: 1, offset: -24, size: 8, alignment: 8 }
+# CHECK-NEXT: - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
+stack:
+ - { id: 0, offset: -12, size: 4, alignment: 4 }
+ - { id: 1, offset: -24, size: 8, alignment: 8 }
+ - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+ - 'MOV64mi32 %rsp, 1, _, -16, _, 2'
+ - '%eax = MOV32rm %rsp, 1, _, -4, _'
+ - 'RETQ %eax'
+...