diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h index 4a6018d08c94c..2ecd445f0deb7 100644 --- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -129,9 +129,8 @@ template <> struct MappingTraits { /// /// 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 { 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 { "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); } diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index db2dfdc395aa2..cbc4e66ccc462 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -541,6 +541,14 @@ class MachineFrameInfo { 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, diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index ab4a037aba203..bfec6c59164ff 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -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. diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index d9cd136f985e1..0af2fbd94dd32 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -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/llvm/test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir b/llvm/test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir new file mode 100644 index 0000000000000..8e50c52f5e181 --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir @@ -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/llvm/test/CodeGen/MIR/X86/variable-sized-stack-objects.mir b/llvm/test/CodeGen/MIR/X86/variable-sized-stack-objects.mir new file mode 100644 index 0000000000000..4c45742b25a4c --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/variable-sized-stack-objects.mir @@ -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' +...