MIR Serialization: Serialize the variable sized stack objects.
authorAlex Lorenz <arphaman@gmail.com>
Tue, 14 Jul 2015 00:26:26 +0000 (00:26 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 14 Jul 2015 00:26:26 +0000 (00:26 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242095 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MIRYamlMapping.h
include/llvm/CodeGen/MachineFrameInfo.h
lib/CodeGen/MIRParser/MIRParser.cpp
lib/CodeGen/MIRPrinter.cpp
test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir [new file with mode: 0644]
test/CodeGen/MIR/X86/variable-sized-stack-objects.mir [new file with mode: 0644]

index 4a6018d08c94ce48c291a3144b262d120b7a0352..2ecd445f0deb7fd1f88da067dd2ec75816a961e2 100644 (file)
@@ -129,9 +129,8 @@ template <> struct MappingTraits<MachineBasicBlock> {
 ///
 /// TODO: Determine isPreallocated flag by mapping between objects and local
 /// objects (Serialize local objects).
-/// TODO: Serialize variable sized objects.
 struct MachineStackObject {
-  enum ObjectType { DefaultType, SpillSlot };
+  enum ObjectType { DefaultType, SpillSlot, VariableSized };
   // TODO: Serialize LLVM alloca reference.
   unsigned ID;
   ObjectType Type = DefaultType;
@@ -144,6 +143,7 @@ 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);
+    IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
   }
 };
 
@@ -154,7 +154,8 @@ template <> struct MappingTraits<MachineStackObject> {
         "type", Object.Type,
         MachineStackObject::DefaultType); // Don't print the default type.
     YamlIO.mapOptional("offset", Object.Offset);
-    YamlIO.mapRequired("size", Object.Size);
+    if (Object.Type != MachineStackObject::VariableSized)
+      YamlIO.mapRequired("size", Object.Size);
     YamlIO.mapOptional("alignment", Object.Alignment);
   }
 
index db2dfdc395aa27c5ed25f182c6a37073de0982a0..cbc4e66ccc462e51fe1c14986aaa13e2ebcfdde2 100644 (file)
@@ -541,6 +541,14 @@ public:
     return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL;
   }
 
+  /// Returns true if the specified index corresponds to a variable sized
+  /// object.
+  bool isVariableSizedObjectIndex(int ObjectIdx) const {
+    assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() &&
+           "Invalid Object Idx!");
+    return Objects[ObjectIdx + NumFixedObjects].Size == 0;
+  }
+
   /// Create a new statically sized stack object, returning
   /// a nonnegative identifier to represent it.
   int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS,
index ab4a037aba203a31e5924fc1967545f0531afebf..bfec6c59164ffa6a8dcc0d705dfcba2493f0ece1 100644 (file)
@@ -391,9 +391,14 @@ bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI,
 
   // Initialize the ordinary frame objects.
   for (const auto &Object : YamlMF.StackObjects) {
-    int ObjectIdx = MFI.CreateStackObject(
-        Object.Size, Object.Alignment,
-        Object.Type == yaml::MachineStackObject::SpillSlot);
+    int ObjectIdx;
+    if (Object.Type == yaml::MachineStackObject::VariableSized)
+      ObjectIdx =
+          MFI.CreateVariableSizedObject(Object.Alignment, /*Alloca=*/nullptr);
+    else
+      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.
index d9cd136f985e1b469dbc4170987d00ed46438e27..0af2fbd94dd3282315123a0613934a9b58c2a6af 100644 (file)
@@ -188,7 +188,9 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
     YamlObject.ID = ID++;
     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
                           ? yaml::MachineStackObject::SpillSlot
-                          : yaml::MachineStackObject::DefaultType;
+                          : MFI.isVariableSizedObjectIndex(I)
+                                ? yaml::MachineStackObject::VariableSized
+                                : yaml::MachineStackObject::DefaultType;
     YamlObject.Offset = MFI.getObjectOffset(I);
     YamlObject.Size = MFI.getObjectSize(I);
     YamlObject.Alignment = MFI.getObjectAlignment(I);
diff --git a/test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir b/test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir
new file mode 100644 (file)
index 0000000..8e50c52
--- /dev/null
@@ -0,0 +1,36 @@
+# 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) {
+  entry:
+    %b = alloca i32
+    %x = alloca i64
+    %y = alloca i32, i32 %a
+    store i32 %a, i32* %b
+    store i64 2, i64* %x
+    %c = load i32, i32* %b
+    ret i32 %c
+  }
+
+...
+---
+name:            test
+frameInfo:
+  stackSize:       24
+  offsetAdjustment: -16
+  maxAlignment:    8
+  adjustsStack:    true
+stack:
+  - { id: 0, offset: -20, size: 4, alignment: 4 }
+  - { id: 1, offset: -32, size: 8, alignment: 8 }
+  # CHECK: [[@LINE+1]]:55: unknown key 'size'
+  - { id: 2, type: variable-sized, offset: -32, size: 42, alignment: 1 }
+body:
+  - id:          0
+    name:        entry
+    instructions:
+      - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+      - 'MOV64mi32 %rsp, 1, _, -16, _, 2'
+      - '%eax = MOV32rm %rsp, 1, _, -4, _'
+      - 'RETQ %eax'
+...
diff --git a/test/CodeGen/MIR/X86/variable-sized-stack-objects.mir b/test/CodeGen/MIR/X86/variable-sized-stack-objects.mir
new file mode 100644 (file)
index 0000000..4c45742
--- /dev/null
@@ -0,0 +1,42 @@
+# 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 variable sized stack objects
+# correctly.
+
+--- |
+
+  define i32 @test(i32 %a) {
+  entry:
+    %b = alloca i32
+    %x = alloca i64
+    %y = alloca i32, i32 %a
+    store i32 %a, i32* %b
+    store i64 2, i64* %x
+    %c = load i32, i32* %b
+    ret i32 %c
+  }
+
+...
+---
+name:            test
+frameInfo:
+  stackSize:       24
+  offsetAdjustment: -16
+  maxAlignment:    8
+  adjustsStack:    true
+# CHECK: stack:
+# CHECK-NEXT: - { id: 0, offset: -20, size: 4, alignment: 4 }
+# CHECK-NEXT: - { id: 1, offset: -32, size: 8, alignment: 8 }
+# CHECK-NEXT: - { id: 2, type: variable-sized, offset: -32, alignment: 1 }
+stack:
+  - { id: 0, offset: -20, size: 4, alignment: 4 }
+  - { id: 1, offset: -32, size: 8, alignment: 8 }
+  - { id: 2, type: variable-sized, offset: -32, alignment: 1 }
+body:
+  - id:          0
+    name:        entry
+    instructions:
+      - 'MOV32mr %rsp, 1, _, -4, _, %edi'
+      - 'MOV64mi32 %rsp, 1, _, -16, _, 2'
+      - '%eax = MOV32rm %rsp, 1, _, -4, _'
+      - 'RETQ %eax'
+...