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