brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · fcd090f Raw
187 lines · cpp
1//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This files defines TypeLocBuilder, a class for building TypeLocs10//  bottom-up.11//12//===----------------------------------------------------------------------===//13 14#include "TypeLocBuilder.h"15 16using namespace clang;17 18void TypeLocBuilder::pushFullCopy(TypeLoc L) {19  size_t Size = L.getFullDataSize();20  reserve(Size);21 22  SmallVector<TypeLoc, 4> TypeLocs;23  TypeLoc CurTL = L;24  while (CurTL) {25    TypeLocs.push_back(CurTL);26    CurTL = CurTL.getNextTypeLoc();27  }28 29  for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {30    TypeLoc CurTL = TypeLocs[e-i-1];31    switch (CurTL.getTypeLocClass()) {32#define ABSTRACT_TYPELOC(CLASS, PARENT)33#define TYPELOC(CLASS, PARENT) \34    case TypeLoc::CLASS: { \35      CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \36      memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \37      break; \38    }39#include "clang/AST/TypeLocNodes.def"40    }41  }42}43 44void TypeLocBuilder::pushTrivial(ASTContext &Context, QualType T,45                                 SourceLocation Loc) {46  auto L = TypeLoc(T, nullptr);47  reserve(L.getFullDataSize());48 49  SmallVector<TypeLoc, 4> TypeLocs;50  for (auto CurTL = L; CurTL; CurTL = CurTL.getNextTypeLoc())51    TypeLocs.push_back(CurTL);52 53  for (const auto &CurTL : llvm::reverse(TypeLocs)) {54    switch (CurTL.getTypeLocClass()) {55#define ABSTRACT_TYPELOC(CLASS, PARENT)56#define TYPELOC(CLASS, PARENT)                                                 \57  case TypeLoc::CLASS: {                                                       \58    auto NewTL = push<class CLASS##TypeLoc>(CurTL.getType());                  \59    NewTL.initializeLocal(Context, Loc);                                       \60    break;                                                                     \61  }62#include "clang/AST/TypeLocNodes.def"63    }64  }65}66 67void TypeLocBuilder::grow(size_t NewCapacity) {68  assert(NewCapacity > Capacity);69 70  // Allocate the new buffer and copy the old data into it.71  char *NewBuffer = new char[NewCapacity];72  unsigned NewIndex = Index + NewCapacity - Capacity;73  memcpy(&NewBuffer[NewIndex],74         &Buffer[Index],75         Capacity - Index);76 77  if (Buffer != InlineBuffer)78    delete[] Buffer;79 80  Buffer = NewBuffer;81  Capacity = NewCapacity;82  Index = NewIndex;83}84 85TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {86#ifndef NDEBUG87  QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();88  assert(TLast == LastTy &&89         "mismatch between last type and new type's inner type");90  LastTy = T;91#endif92 93  assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");94 95  // If we need to grow, grow by a factor of 2.96  if (LocalSize > Index) {97    size_t RequiredCapacity = Capacity + (LocalSize - Index);98    size_t NewCapacity = Capacity * 2;99    while (RequiredCapacity > NewCapacity)100      NewCapacity *= 2;101    grow(NewCapacity);102  }103 104  // Because we're adding elements to the TypeLoc backwards, we have to105  // do some extra work to keep everything aligned appropriately.106  // FIXME: This algorithm is a absolute mess because every TypeLoc returned107  // needs to be valid.  Partial TypeLocs are a terrible idea.108  // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to109  // hardcode them.110  if (LocalAlignment == 4) {111    if (!AtAlign8) {112      NumBytesAtAlign4 += LocalSize;113    } else {114      unsigned Padding = NumBytesAtAlign4 % 8;115      if (Padding == 0) {116        if (LocalSize % 8 == 0) {117          // Everything is set: there's no padding and we don't need to add118          // any.119        } else {120          assert(LocalSize % 8 == 4);121          // No existing padding; add in 4 bytes padding122          memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);123          Index -= 4;124        }125      } else {126        assert(Padding == 4);127        if (LocalSize % 8 == 0) {128          // Everything is set: there's 4 bytes padding and we don't need129          // to add any.130        } else {131          assert(LocalSize % 8 == 4);132          // There are 4 bytes padding, but we don't need any; remove it.133          memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);134          Index += 4;135        }136      }137      NumBytesAtAlign4 += LocalSize;138    }139  } else if (LocalAlignment == 8) {140    if (!AtAlign8) {141      // We have not seen any 8-byte aligned element yet. We insert a padding142      // only if the new Index is not 8-byte-aligned.143      if ((Index - LocalSize) % 8 != 0) {144        memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);145        Index -= 4;146      }147    } else {148      unsigned Padding = NumBytesAtAlign4 % 8;149      if (Padding == 0) {150        if (LocalSize % 8 == 0) {151          // Everything is set: there's no padding and we don't need to add152          // any.153        } else {154          assert(LocalSize % 8 == 4);155          // No existing padding; add in 4 bytes padding156          memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);157          Index -= 4;158        }159      } else {160        assert(Padding == 4);161        if (LocalSize % 8 == 0) {162          // Everything is set: there's 4 bytes padding and we don't need163          // to add any.164        } else {165          assert(LocalSize % 8 == 4);166          // There are 4 bytes padding, but we don't need any; remove it.167          memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);168          Index += 4;169        }170      }171    }172 173    // Forget about any padding.174    NumBytesAtAlign4 = 0;175    AtAlign8 = true;176  } else {177    assert(LocalSize == 0);178  }179 180  Index -= LocalSize;181 182  assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&183         "incorrect data size provided to CreateTypeSourceInfo!");184 185  return getTemporaryTypeLoc(T);186}187