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