[llvm] 7c44ee8 - [ms] [llvm-ml] Fix struct padding logic

Eric Astor via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 14 11:12:38 PDT 2020


Author: Eric Astor
Date: 2020-09-14T14:12:20-04:00
New Revision: 7c44ee8e1937c7402a106f3fa6a356caa73a14e8

URL: https://github.com/llvm/llvm-project/commit/7c44ee8e1937c7402a106f3fa6a356caa73a14e8
DIFF: https://github.com/llvm/llvm-project/commit/7c44ee8e1937c7402a106f3fa6a356caa73a14e8.diff

LOG: [ms] [llvm-ml] Fix struct padding logic

MASM structs are end-padded to have size a multiple of the smaller of the requested alignment and the size of their largest field (taken recursively, if they have a field of STRUCT type).

This matches the behavior of ml.exe and ml64.exe. Our original implementation followed the MASM 6.0 documentation, which instead specified that MASM structs were padded to a multiple of their requested alignment.

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D87248

Added: 
    llvm/test/tools/llvm-ml/struct_alignment.test

Modified: 
    llvm/lib/MC/MCParser/MasmParser.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index ea18cf8936de..c1917d729c85 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -124,10 +124,12 @@ struct StructInfo {
   bool IsUnion = false;
   size_t Alignment = 0;
   size_t Size = 0;
+  size_t AlignmentSize = 0;
   std::vector<FieldInfo> Fields;
   StringMap<size_t> FieldsByName;
 
-  FieldInfo &addField(StringRef FieldName, FieldType FT, size_t FieldSize);
+  FieldInfo &addField(StringRef FieldName, FieldType FT,
+                      size_t FieldAlignmentSize);
 
   StructInfo() = default;
 
@@ -331,7 +333,7 @@ struct FieldInfo {
 };
 
 FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
-                                size_t FieldSize) {
+                                size_t FieldAlignmentSize) {
   if (!FieldName.empty())
     FieldsByName[FieldName] = Fields.size();
   Fields.emplace_back(FT);
@@ -339,9 +341,10 @@ FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
   if (IsUnion) {
     Field.Offset = 0;
   } else {
-    Size = llvm::alignTo(Size, std::min(Alignment, FieldSize));
+    Size = llvm::alignTo(Size, std::min(Alignment, FieldAlignmentSize));
     Field.Offset = Size;
   }
+  AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
   return Field;
 }
 
@@ -3973,7 +3976,8 @@ bool MasmParser::emitStructValues(const StructInfo &Structure) {
 // Declare a field in the current struct.
 bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
   StructInfo &OwningStruct = StructInProgress.back();
-  FieldInfo &Field = OwningStruct.addField(Name, FT_STRUCT, Structure.Size);
+  FieldInfo &Field =
+      OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
   StructFieldInfo &StructInfo = Field.Contents.StructInfo;
 
   StructInfo.Structure = Structure;
@@ -4101,8 +4105,10 @@ bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
     return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
                               StructInProgress.back().Name + "'");
   StructInfo Structure = StructInProgress.pop_back_val();
-  // Pad to make the structure's size divisible by its alignment.
-  Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
+  // Pad to make the structure's size divisible by the smaller of its alignment
+  // and the size of its largest field.
+  Structure.Size = llvm::alignTo(
+      Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
   Structs[Name.lower()] = Structure;
 
   if (parseToken(AsmToken::EndOfStatement))
@@ -4147,8 +4153,8 @@ bool MasmParser::parseDirectiveNestedEnds() {
     else
       ParentStruct.Size += Structure.Size;
   } else {
-    FieldInfo &Field =
-        ParentStruct.addField(Structure.Name, FT_STRUCT, Structure.Size);
+    FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
+                                             Structure.AlignmentSize);
     StructFieldInfo &StructInfo = Field.Contents.StructInfo;
     Field.Type = Structure.Size;
     Field.LengthOf = 1;

diff  --git a/llvm/test/tools/llvm-ml/struct_alignment.test b/llvm/test/tools/llvm-ml/struct_alignment.test
new file mode 100644
index 000000000000..cfe803872c3b
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/struct_alignment.test
@@ -0,0 +1,44 @@
+; RUN: llvm-ml -filetype=asm %s | FileCheck %s
+
+.data
+
+FOO STRUCT 8
+  f FWORD -1
+FOO ENDS
+
+t1 FOO <>
+; CHECK-LABEL: t1:
+; CHECK-NEXT: .long 4294967295
+; CHECK-NEXT: .short 65535
+; CHECK-NOT: .zero
+
+BAZ STRUCT
+  b BYTE 3 DUP (-1)
+  f FWORD -1
+BAZ ENDS
+
+FOOBAR STRUCT 8
+  f1 BAZ <>
+  f2 BAZ <>
+  h BYTE -1
+FOOBAR ENDS
+
+t2 FOOBAR <>
+; CHECK-LABEL: t2:
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .long 4294967295
+; CHECK-NEXT: .short 65535
+; CHECK-NEXT: .zero 3
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .long 4294967295
+; CHECK-NEXT: .short 65535
+; CHECK-NEXT: .byte -1
+; CHECK-NEXT: .zero 2
+
+.code
+
+END


        


More information about the llvm-commits mailing list