1 //===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This files defines TypeLocBuilder, a class for building TypeLocs
12 //===----------------------------------------------------------------------===//
14 #include "TypeLocBuilder.h"
16 using namespace clang
;
18 void TypeLocBuilder::pushFullCopy(TypeLoc L
) {
19 size_t Size
= L
.getFullDataSize();
22 SmallVector
<TypeLoc
, 4> TypeLocs
;
25 TypeLocs
.push_back(CurTL
);
26 CurTL
= CurTL
.getNextTypeLoc();
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()); \
39 #include "clang/AST/TypeLocNodes.def"
44 void TypeLocBuilder::pushTrivial(ASTContext
&Context
, QualType T
,
46 auto L
= TypeLoc(T
, nullptr);
47 reserve(L
.getFullDataSize());
49 SmallVector
<TypeLoc
, 4> TypeLocs
;
50 for (auto CurTL
= L
; CurTL
; CurTL
= CurTL
.getNextTypeLoc())
51 TypeLocs
.push_back(CurTL
);
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); \
62 #include "clang/AST/TypeLocNodes.def"
67 void TypeLocBuilder::grow(size_t NewCapacity
) {
68 assert(NewCapacity
> Capacity
);
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
],
77 if (Buffer
!= InlineBuffer
)
81 Capacity
= NewCapacity
;
85 TypeLoc
TypeLocBuilder::pushImpl(QualType T
, size_t LocalSize
, unsigned LocalAlignment
) {
87 QualType TLast
= TypeLoc(T
, nullptr).getNextTypeLoc().getType();
88 assert(TLast
== LastTy
&&
89 "mismatch between last type and new type's inner type");
93 assert(LocalAlignment
<= BufferMaxAlignment
&& "Unexpected alignment");
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
)
104 // Because we're adding elements to the TypeLoc backwards, we have to
105 // do some extra work to keep everything aligned appropriately.
106 // FIXME: This algorithm is a absolute mess because every TypeLoc returned
107 // 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 to
110 if (LocalAlignment
== 4) {
112 NumBytesAtAlign4
+= LocalSize
;
114 unsigned Padding
= NumBytesAtAlign4
% 8;
116 if (LocalSize
% 8 == 0) {
117 // Everything is set: there's no padding and we don't need to add
120 assert(LocalSize
% 8 == 4);
121 // No existing padding; add in 4 bytes padding
122 memmove(&Buffer
[Index
- 4], &Buffer
[Index
], NumBytesAtAlign4
);
126 assert(Padding
== 4);
127 if (LocalSize
% 8 == 0) {
128 // Everything is set: there's 4 bytes padding and we don't need
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
);
137 NumBytesAtAlign4
+= LocalSize
;
139 } else if (LocalAlignment
== 8) {
141 // We have not seen any 8-byte aligned element yet. We insert a padding
142 // only if the new Index is not 8-byte-aligned.
143 if ((Index
- LocalSize
) % 8 != 0) {
144 memmove(&Buffer
[Index
- 4], &Buffer
[Index
], NumBytesAtAlign4
);
148 unsigned Padding
= NumBytesAtAlign4
% 8;
150 if (LocalSize
% 8 == 0) {
151 // Everything is set: there's no padding and we don't need to add
154 assert(LocalSize
% 8 == 4);
155 // No existing padding; add in 4 bytes padding
156 memmove(&Buffer
[Index
- 4], &Buffer
[Index
], NumBytesAtAlign4
);
160 assert(Padding
== 4);
161 if (LocalSize
% 8 == 0) {
162 // Everything is set: there's 4 bytes padding and we don't need
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
);
173 // Forget about any padding.
174 NumBytesAtAlign4
= 0;
177 assert(LocalSize
== 0);
182 assert(Capacity
- Index
== TypeLoc::getFullDataSizeForType(T
) &&
183 "incorrect data size provided to CreateTypeSourceInfo!");
185 return getTemporaryTypeLoc(T
);