TypeLocBuilder.cpp revision 263508
1//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This files defines TypeLocBuilder, a class for building TypeLocs
11//  bottom-up.
12//
13//===----------------------------------------------------------------------===//
14
15#include "TypeLocBuilder.h"
16
17using namespace clang;
18
19void TypeLocBuilder::pushFullCopy(TypeLoc L) {
20  size_t Size = L.getFullDataSize();
21  reserve(Size);
22
23  SmallVector<TypeLoc, 4> TypeLocs;
24  TypeLoc CurTL = L;
25  while (CurTL) {
26    TypeLocs.push_back(CurTL);
27    CurTL = CurTL.getNextTypeLoc();
28  }
29
30  for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
31    TypeLoc CurTL = TypeLocs[e-i-1];
32    switch (CurTL.getTypeLocClass()) {
33#define ABSTRACT_TYPELOC(CLASS, PARENT)
34#define TYPELOC(CLASS, PARENT) \
35    case TypeLoc::CLASS: { \
36      CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
37      memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
38      break; \
39    }
40#include "clang/AST/TypeLocNodes.def"
41    }
42  }
43}
44
45void TypeLocBuilder::grow(size_t NewCapacity) {
46  assert(NewCapacity > Capacity);
47
48  // Allocate the new buffer and copy the old data into it.
49  char *NewBuffer = new char[NewCapacity];
50  unsigned NewIndex = Index + NewCapacity - Capacity;
51  memcpy(&NewBuffer[NewIndex],
52         &Buffer[Index],
53         Capacity - Index);
54
55  if (Buffer != InlineBuffer.buffer)
56    delete[] Buffer;
57
58  Buffer = NewBuffer;
59  Capacity = NewCapacity;
60  Index = NewIndex;
61}
62
63TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
64#ifndef NDEBUG
65  QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
66  assert(TLast == LastTy &&
67         "mismatch between last type and new type's inner type");
68  LastTy = T;
69#endif
70
71  assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
72
73  // If we need to grow, grow by a factor of 2.
74  if (LocalSize > Index) {
75    size_t RequiredCapacity = Capacity + (LocalSize - Index);
76    size_t NewCapacity = Capacity * 2;
77    while (RequiredCapacity > NewCapacity)
78      NewCapacity *= 2;
79    grow(NewCapacity);
80  }
81
82  // Because we're adding elements to the TypeLoc backwards, we have to
83  // do some extra work to keep everything aligned appropriately.
84  // FIXME: This algorithm is a absolute mess because every TypeLoc returned
85  // needs to be valid.  Partial TypeLocs are a terrible idea.
86  // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
87  // hardcode them.
88  if (LocalAlignment == 4) {
89    if (NumBytesAtAlign8 == 0) {
90      NumBytesAtAlign4 += LocalSize;
91    } else {
92      unsigned Padding = NumBytesAtAlign4 % 8;
93      if (Padding == 0) {
94        if (LocalSize % 8 == 0) {
95          // Everything is set: there's no padding and we don't need to add
96          // any.
97        } else {
98          assert(LocalSize % 8 == 4);
99          // No existing padding; add in 4 bytes padding
100          memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
101          Index -= 4;
102        }
103      } else {
104        assert(Padding == 4);
105        if (LocalSize % 8 == 0) {
106          // Everything is set: there's 4 bytes padding and we don't need
107          // to add any.
108        } else {
109          assert(LocalSize % 8 == 4);
110          // There are 4 bytes padding, but we don't need any; remove it.
111          memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
112          Index += 4;
113        }
114      }
115      NumBytesAtAlign4 += LocalSize;
116    }
117  } else if (LocalAlignment == 8) {
118    if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {
119      // No existing padding and misaligned members; add in 4 bytes padding
120      memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
121      Index -= 4;
122    }
123    // Forget about any padding.
124    NumBytesAtAlign4 = 0;
125    NumBytesAtAlign8 += LocalSize;
126  } else {
127    assert(LocalSize == 0);
128  }
129
130  Index -= LocalSize;
131
132  assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
133         "incorrect data size provided to CreateTypeSourceInfo!");
134
135  return getTemporaryTypeLoc(T);
136}
137