/// 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;
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.
const yaml::MachineFunction &YamlMF,
DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
- bool initializeFrameInfo(MachineFrameInfo &MFI,
+ bool initializeFrameInfo(const Function &F, MachineFrameInfo &MFI,
const yaml::MachineFunction &YamlMF);
private:
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();
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);
// 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.
#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"
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)
--- /dev/null
+# 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'
+...
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
# 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