ahatanak updated this revision to Diff 47413.
ahatanak added a comment.

Rename and add variables. Add comments to make it clearer what the code is 
doing.


http://reviews.llvm.org/D16843

Files:
  lib/Sema/TypeLocBuilder.cpp
  lib/Sema/TypeLocBuilder.h
  test/SemaObjCXX/typeloc-data-alignment.mm

Index: test/SemaObjCXX/typeloc-data-alignment.mm
===================================================================
--- /dev/null
+++ test/SemaObjCXX/typeloc-data-alignment.mm
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+// Make sure this doesn't crash.
+
+@protocol P
+@end
+template <class T>
+id<P> foo(T) {
+  int i;
+  foo(i);
+}
Index: lib/Sema/TypeLocBuilder.h
===================================================================
--- lib/Sema/TypeLocBuilder.h
+++ lib/Sema/TypeLocBuilder.h
@@ -41,12 +41,18 @@
   /// The inline buffer.
   enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
   llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
-  unsigned NumBytesAtAlign4, NumBytesAtAlign8;
+
+  // Total size of the 4-byte aligned elements that were pushed since the last
+  // 8-byte element was pushed.
+  unsigned NumBytesAtAlign4;
+
+  // Indicates whether we've pushed an 8-byte aligned element.
+  bool SeenAlign8;
 
  public:
   TypeLocBuilder()
     : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
-      Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
+      Index(InlineCapacity), NumBytesAtAlign4(0), SeenAlign8(false)
   {
   }
 
@@ -80,7 +86,8 @@
     LastTy = QualType();
 #endif
     Index = Capacity;
-    NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
+    NumBytesAtAlign4 = 0;
+    SeenAlign8 = false;
   }  
 
   /// \brief Tell the TypeLocBuilder that the type it is storing has been
Index: lib/Sema/TypeLocBuilder.cpp
===================================================================
--- lib/Sema/TypeLocBuilder.cpp
+++ lib/Sema/TypeLocBuilder.cpp
@@ -43,6 +43,9 @@
 }
 
 void TypeLocBuilder::grow(size_t NewCapacity) {
+  // Make sure NewCapacity is a multiple of 8.
+  NewCapacity = llvm::alignTo(NewCapacity, 8);
+
   assert(NewCapacity > Capacity);
 
   // Allocate the new buffer and copy the old data into it.
@@ -68,66 +71,58 @@
   LastTy = T;
 #endif
 
-  assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
+  assert(Capacity % 8 == 0 && "Capacity must be a multiple of 8");
+  assert(LocalSize % 4 == 0 && "LocalSize must be a multiple of 4");
+  assert(LocalAlignment <= BufferMaxAlignment &&
+         (LocalAlignment == 8 || LocalAlignment == 4 || LocalSize == 0) &&
+         "Unexpected alignment");
+  assert(Index % 4 == 0 && "Index must be a multiple of 4");
+
+  // Check whether there is a 4-byte padding at the tail of the 4-byte elements.
+  bool CurrentlyHasPadding = SeenAlign8 && NumBytesAtAlign4 % 8;
+  bool RemoveOrInsertPadding = false;
+  unsigned RequiredCapacity = Capacity - Index + LocalSize;
+
+  // Check if the new Index has to be aligned on an 8-byte boundary.
+  bool RequiresAlign8 = SeenAlign8 || LocalAlignment == 8 && LocalSize != 0;
+
+  // Adjust the new Index if 8-byte alignment is required. Since Capacity is
+  // always a multiple of 8 and Index = Capacity - RequiredCapacity, this means
+  // RequiredCapacity has to be a multiple of 8 too.
+  if (RequiresAlign8 && RequiredCapacity % 8) {
+    // Adjust RequiredCapacity.
+    RequiredCapacity += (CurrentlyHasPadding ? -4 : 4);
+
+    // Determine if we have to insert or remove padding and move the 4-byte
+    // aligned elements that were pushed since the last 8-byte aligned
+    // element was pushed.
+    RemoveOrInsertPadding = NumBytesAtAlign4 != 0;
+  }
+
+  unsigned NewCapacity = Capacity;
 
   // If we need to grow, grow by a factor of 2.
-  if (LocalSize > Index) {
-    size_t RequiredCapacity = Capacity + (LocalSize - Index);
-    size_t NewCapacity = Capacity * 2;
-    while (RequiredCapacity > NewCapacity)
-      NewCapacity *= 2;
+  while (RequiredCapacity > NewCapacity)
+    NewCapacity *= 2;
+
+  if (NewCapacity != Capacity)
     grow(NewCapacity);
-  }
 
-  // Because we're adding elements to the TypeLoc backwards, we have to
-  // do some extra work to keep everything aligned appropriately.
-  // FIXME: This algorithm is a absolute mess because every TypeLoc returned
-  // needs to be valid.  Partial TypeLocs are a terrible idea.
-  // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
-  // hardcode them.
-  if (LocalAlignment == 4) {
-    if (NumBytesAtAlign8 == 0) {
-      NumBytesAtAlign4 += LocalSize;
-    } else {
-      unsigned Padding = NumBytesAtAlign4 % 8;
-      if (Padding == 0) {
-        if (LocalSize % 8 == 0) {
-          // Everything is set: there's no padding and we don't need to add
-          // any.
-        } else {
-          assert(LocalSize % 8 == 4);
-          // No existing padding; add in 4 bytes padding
-          memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
-          Index -= 4;
-        }
-      } else {
-        assert(Padding == 4);
-        if (LocalSize % 8 == 0) {
-          // Everything is set: there's 4 bytes padding and we don't need
-          // to add any.
-        } else {
-          assert(LocalSize % 8 == 4);
-          // There are 4 bytes padding, but we don't need any; remove it.
-          memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
-          Index += 4;
-        }
-      }
-      NumBytesAtAlign4 += LocalSize;
-    }
-  } else if (LocalAlignment == 8) {
-    if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {
-      // No existing padding and misaligned members; add in 4 bytes padding
+  if (RemoveOrInsertPadding) {
+    if (CurrentlyHasPadding) // Remove padding.
+      memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
+    else // Insert padding.
       memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
-      Index -= 4;
-    }
-    // Forget about any padding.
+  }
+
+  if (LocalAlignment == 8) {
+    SeenAlign8 = SeenAlign8 || LocalSize != 0;
     NumBytesAtAlign4 = 0;
-    NumBytesAtAlign8 += LocalSize;
-  } else {
-    assert(LocalSize == 0);
+  } else if (LocalAlignment == 4) {
+    NumBytesAtAlign4 += LocalSize;
   }
 
-  Index -= LocalSize;
+  Index = Capacity - RequiredCapacity;
 
   assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
          "incorrect data size provided to CreateTypeSourceInfo!");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to