OSDN Git Service

MIR Serialization: Serialize references from the stack objects to named allocas.
authorAlex Lorenz <arphaman@gmail.com>
Wed, 15 Jul 2015 22:14:49 +0000 (22:14 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Wed, 15 Jul 2015 22:14:49 +0000 (22:14 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242339 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 9798e5c..49cf138 100644 (file)
@@ -132,8 +132,9 @@ template <> struct MappingTraits<MachineBasicBlock> {
 /// objects (Serialize local objects).
 struct MachineStackObject {
   enum ObjectType { DefaultType, SpillSlot, VariableSized };
-  // TODO: Serialize LLVM alloca reference.
   unsigned ID;
+  StringValue Name;
+  // TODO: Serialize unnamed LLVM alloca reference.
   ObjectType Type = DefaultType;
   int64_t Offset = 0;
   uint64_t Size = 0;
@@ -151,6 +152,8 @@ template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
 template <> struct MappingTraits<MachineStackObject> {
   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
     YamlIO.mapRequired("id", Object.ID);
+    YamlIO.mapOptional("name", Object.Name,
+                       StringValue()); // Don't print out an empty name.
     YamlIO.mapOptional(
         "type", Object.Type,
         MachineStackObject::DefaultType); // Don't print the default type.
index 16b0e16..8dd7699 100644 (file)
@@ -108,7 +108,7 @@ public:
                          const yaml::MachineFunction &YamlMF,
                          DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
 
-  bool initializeFrameInfo(MachineFrameInfo &MFI,
+  bool initializeFrameInfo(const Function &F, MachineFrameInfo &MFI,
                            const yaml::MachineFunction &YamlMF);
 
 private:
@@ -264,7 +264,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
   if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
                              PFS.VirtualRegisterSlots))
     return true;
-  if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
+  if (initializeFrameInfo(*MF.getFunction(), *MF.getFrameInfo(), YamlMF))
     return true;
 
   const auto &F = *MF.getFunction();
@@ -366,7 +366,8 @@ bool MIRParserImpl::initializeRegisterInfo(
   return false;
 }
 
-bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI,
+bool MIRParserImpl::initializeFrameInfo(const Function &F,
+                                        MachineFrameInfo &MFI,
                                         const yaml::MachineFunction &YamlMF) {
   const yaml::MachineFrameInfo &YamlMFI = YamlMF.FrameInfo;
   MFI.setFrameAddressIsTaken(YamlMFI.IsFrameAddressTaken);
@@ -400,13 +401,23 @@ bool MIRParserImpl::initializeFrameInfo(MachineFrameInfo &MFI,
   // Initialize the ordinary frame objects.
   for (const auto &Object : YamlMF.StackObjects) {
     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)
-      ObjectIdx =
-          MFI.CreateVariableSizedObject(Object.Alignment, /*Alloca=*/nullptr);
+      ObjectIdx = MFI.CreateVariableSizedObject(Object.Alignment, Alloca);
     else
       ObjectIdx = MFI.CreateStackObject(
           Object.Size, Object.Alignment,
-          Object.Type == yaml::MachineStackObject::SpillSlot);
+          Object.Type == yaml::MachineStackObject::SpillSlot, Alloca);
     MFI.setObjectOffset(ObjectIdx, Object.Offset);
     // TODO: Store the mapping between object IDs and object indices to parse
     // stack object references correctly.
index d5cf924..1adfdef 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ModuleSlotTracker.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -199,6 +200,9 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
 
     yaml::MachineStackObject YamlObject;
     YamlObject.ID = ID++;
+    if (const auto *Alloca = MFI.getObjectAllocation(I))
+      YamlObject.Name.Value =
+          Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>";
     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
                           ? yaml::MachineStackObject::SpillSlot
                           : MFI.isVariableSizedObjectIndex(I)
diff --git a/test/CodeGen/MIR/X86/stack-object-invalid-name.mir b/test/CodeGen/MIR/X86/stack-object-invalid-name.mir
new file mode 100644 (file)
index 0000000..2d4f57b
--- /dev/null
@@ -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'
+...
index 14ed4b7..3766630 100644 (file)
@@ -21,12 +21,12 @@ 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: 0, name: b, offset: -12, size: 4, alignment: 4 }
+# 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 }
 stack:
-  - { id: 0, offset: -12, size: 4, alignment: 4 }
-  - { id: 1, offset: -24, size: 8, alignment: 8 }
+  - { id: 0, name: b, offset: -12, size: 4, alignment: 4 }
+  - { id: 1, name: x, offset: -24, size: 8, alignment: 8 }
   - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
 body:
   - id:          0
index 4c45742..5e6467e 100644 (file)
@@ -26,11 +26,11 @@ frameInfo:
 # 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 }
+# CHECK-NEXT: - { id: 2, name: y, 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 }
+  - { id: 2, name: y, type: variable-sized, offset: -32, alignment: 1 }
 body:
   - id:          0
     name:        entry