File: | tools/clang/lib/AST/Interp/Program.cpp |
Warning: | line 126, column 21 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- Program.cpp - Bytecode for the constexpr VM ------------*- C++ -*-===// | |||
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-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | ||||
9 | #include "Program.h" | |||
10 | #include "ByteCodeStmtGen.h" | |||
11 | #include "Context.h" | |||
12 | #include "Function.h" | |||
13 | #include "Opcode.h" | |||
14 | #include "PrimType.h" | |||
15 | #include "clang/AST/Decl.h" | |||
16 | #include "clang/AST/DeclCXX.h" | |||
17 | ||||
18 | using namespace clang; | |||
19 | using namespace clang::interp; | |||
20 | ||||
21 | unsigned Program::createGlobalString(const StringLiteral *S) { | |||
22 | const size_t CharWidth = S->getCharByteWidth(); | |||
23 | const size_t BitWidth = CharWidth * Ctx.getCharBit(); | |||
24 | ||||
25 | PrimType CharType; | |||
26 | switch (CharWidth) { | |||
27 | case 1: | |||
28 | CharType = PT_Sint8; | |||
29 | break; | |||
30 | case 2: | |||
31 | CharType = PT_Uint16; | |||
32 | break; | |||
33 | case 4: | |||
34 | CharType = PT_Uint32; | |||
35 | break; | |||
36 | default: | |||
37 | llvm_unreachable("unsupported character width")::llvm::llvm_unreachable_internal("unsupported character width" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/Interp/Program.cpp" , 37); | |||
38 | } | |||
39 | ||||
40 | // Create a descriptor for the string. | |||
41 | Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1, | |||
42 | /*isConst=*/true, | |||
43 | /*isTemporary=*/false, | |||
44 | /*isMutable=*/false); | |||
45 | ||||
46 | // Allocate storage for the string. | |||
47 | // The byte length does not include the null terminator. | |||
48 | unsigned I = Globals.size(); | |||
49 | unsigned Sz = Desc->getAllocSize(); | |||
50 | auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true, | |||
51 | /*isExtern=*/false); | |||
52 | Globals.push_back(G); | |||
53 | ||||
54 | // Construct the string in storage. | |||
55 | const Pointer Ptr(G->block()); | |||
56 | for (unsigned I = 0, N = S->getLength(); I <= N; ++I) { | |||
57 | Pointer Field = Ptr.atIndex(I).narrow(); | |||
58 | const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I); | |||
59 | switch (CharType) { | |||
60 | case PT_Sint8: { | |||
61 | using T = PrimConv<PT_Sint8>::T; | |||
62 | Field.deref<T>() = T::from(CodePoint, BitWidth); | |||
63 | break; | |||
64 | } | |||
65 | case PT_Uint16: { | |||
66 | using T = PrimConv<PT_Uint16>::T; | |||
67 | Field.deref<T>() = T::from(CodePoint, BitWidth); | |||
68 | break; | |||
69 | } | |||
70 | case PT_Uint32: { | |||
71 | using T = PrimConv<PT_Uint32>::T; | |||
72 | Field.deref<T>() = T::from(CodePoint, BitWidth); | |||
73 | break; | |||
74 | } | |||
75 | default: | |||
76 | llvm_unreachable("unsupported character type")::llvm::llvm_unreachable_internal("unsupported character type" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/Interp/Program.cpp" , 76); | |||
77 | } | |||
78 | } | |||
79 | return I; | |||
80 | } | |||
81 | ||||
82 | Pointer Program::getPtrGlobal(unsigned Idx) { | |||
83 | assert(Idx < Globals.size())((Idx < Globals.size()) ? static_cast<void> (0) : __assert_fail ("Idx < Globals.size()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/Interp/Program.cpp" , 83, __PRETTY_FUNCTION__)); | |||
84 | return Pointer(Globals[Idx]->block()); | |||
85 | } | |||
86 | ||||
87 | llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) { | |||
88 | auto It = GlobalIndices.find(VD); | |||
89 | if (It != GlobalIndices.end()) | |||
90 | return It->second; | |||
91 | ||||
92 | // Find any previous declarations which were aleady evaluated. | |||
93 | llvm::Optional<unsigned> Index; | |||
94 | for (const Decl *P = VD; P; P = P->getPreviousDecl()) { | |||
95 | auto It = GlobalIndices.find(P); | |||
96 | if (It != GlobalIndices.end()) { | |||
97 | Index = It->second; | |||
98 | break; | |||
99 | } | |||
100 | } | |||
101 | ||||
102 | // Map the decl to the existing index. | |||
103 | if (Index) { | |||
104 | GlobalIndices[VD] = *Index; | |||
105 | return {}; | |||
106 | } | |||
107 | ||||
108 | return Index; | |||
109 | } | |||
110 | ||||
111 | llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) { | |||
112 | if (auto Idx = getGlobal(VD)) | |||
113 | return Idx; | |||
114 | ||||
115 | if (auto Idx = createGlobal(VD)) { | |||
116 | GlobalIndices[VD] = *Idx; | |||
117 | return Idx; | |||
118 | } | |||
119 | return {}; | |||
120 | } | |||
121 | ||||
122 | llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) { | |||
123 | auto &ASTCtx = Ctx.getASTContext(); | |||
124 | ||||
125 | // Create a pointer to an incomplete array of the specified elements. | |||
126 | QualType ElemTy = PD->getType()->getAs<PointerType>()->getPointeeType(); | |||
| ||||
| ||||
127 | QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0); | |||
128 | ||||
129 | // Dedup blocks since they are immutable and pointers cannot be compared. | |||
130 | auto It = DummyParams.find(PD); | |||
131 | if (It != DummyParams.end()) | |||
132 | return It->second; | |||
133 | ||||
134 | if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) { | |||
135 | DummyParams[PD] = *Idx; | |||
136 | return Idx; | |||
137 | } | |||
138 | return {}; | |||
139 | } | |||
140 | ||||
141 | llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) { | |||
142 | bool IsStatic, IsExtern; | |||
143 | if (auto *Var = dyn_cast<VarDecl>(VD)) { | |||
144 | IsStatic = !Var->hasLocalStorage(); | |||
145 | IsExtern = !Var->getAnyInitializer(); | |||
146 | } else { | |||
147 | IsStatic = false; | |||
148 | IsExtern = true; | |||
149 | } | |||
150 | if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern)) { | |||
151 | for (const Decl *P = VD; P; P = P->getPreviousDecl()) | |||
152 | GlobalIndices[P] = *Idx; | |||
153 | return *Idx; | |||
154 | } | |||
155 | return {}; | |||
156 | } | |||
157 | ||||
158 | llvm::Optional<unsigned> Program::createGlobal(const Expr *E) { | |||
159 | return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false); | |||
160 | } | |||
161 | ||||
162 | llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty, | |||
163 | bool IsStatic, bool IsExtern) { | |||
164 | // Create a descriptor for the global. | |||
165 | Descriptor *Desc; | |||
166 | const bool IsConst = Ty.isConstQualified(); | |||
167 | const bool IsTemporary = D.dyn_cast<const Expr *>(); | |||
168 | if (auto T = Ctx.classify(Ty)) { | |||
169 | Desc = createDescriptor(D, *T, IsConst, IsTemporary); | |||
170 | } else { | |||
171 | Desc = createDescriptor(D, Ty.getTypePtr(), IsConst, IsTemporary); | |||
172 | } | |||
173 | if (!Desc) | |||
174 | return {}; | |||
175 | ||||
176 | // Allocate a block for storage. | |||
177 | unsigned I = Globals.size(); | |||
178 | ||||
179 | auto *G = new (Allocator, Desc->getAllocSize()) | |||
180 | Global(getCurrentDecl(), Desc, IsStatic, IsExtern); | |||
181 | G->block()->invokeCtor(); | |||
182 | ||||
183 | Globals.push_back(G); | |||
184 | ||||
185 | return I; | |||
186 | } | |||
187 | ||||
188 | Function *Program::getFunction(const FunctionDecl *F) { | |||
189 | F = F->getDefinition(); | |||
190 | auto It = Funcs.find(F); | |||
191 | return It == Funcs.end() ? nullptr : It->second.get(); | |||
192 | } | |||
193 | ||||
194 | llvm::Expected<Function *> Program::getOrCreateFunction(const FunctionDecl *F) { | |||
195 | if (Function *Func = getFunction(F)) { | |||
196 | return Func; | |||
197 | } | |||
198 | ||||
199 | // Try to compile the function if it wasn't compiled yet. | |||
200 | if (const FunctionDecl *FD = F->getDefinition()) | |||
201 | return ByteCodeStmtGen<ByteCodeEmitter>(Ctx, *this).compileFunc(FD); | |||
202 | ||||
203 | // A relocation which traps if not resolved. | |||
204 | return nullptr; | |||
205 | } | |||
206 | ||||
207 | Record *Program::getOrCreateRecord(const RecordDecl *RD) { | |||
208 | // Use the actual definition as a key. | |||
209 | RD = RD->getDefinition(); | |||
210 | if (!RD) | |||
211 | return nullptr; | |||
212 | ||||
213 | // Deduplicate records. | |||
214 | auto It = Records.find(RD); | |||
215 | if (It != Records.end()) { | |||
216 | return It->second; | |||
217 | } | |||
218 | ||||
219 | // Number of bytes required by fields and base classes. | |||
220 | unsigned Size = 0; | |||
221 | // Number of bytes required by virtual base. | |||
222 | unsigned VirtSize = 0; | |||
223 | ||||
224 | // Helper to get a base descriptor. | |||
225 | auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * { | |||
226 | if (!BR) | |||
227 | return nullptr; | |||
228 | return allocateDescriptor(BD, BR, /*isConst=*/false, | |||
229 | /*isTemporary=*/false, | |||
230 | /*isMutable=*/false); | |||
231 | }; | |||
232 | ||||
233 | // Reserve space for base classes. | |||
234 | Record::BaseList Bases; | |||
235 | Record::VirtualBaseList VirtBases; | |||
236 | if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) { | |||
237 | for (const CXXBaseSpecifier &Spec : CD->bases()) { | |||
238 | if (Spec.isVirtual()) | |||
239 | continue; | |||
240 | ||||
241 | const RecordDecl *BD = Spec.getType()->getAs<RecordType>()->getDecl(); | |||
242 | Record *BR = getOrCreateRecord(BD); | |||
243 | if (Descriptor *Desc = GetBaseDesc(BD, BR)) { | |||
244 | Size += align(sizeof(InlineDescriptor)); | |||
245 | Bases.push_back({BD, Size, Desc, BR}); | |||
246 | Size += align(BR->getSize()); | |||
247 | continue; | |||
248 | } | |||
249 | return nullptr; | |||
250 | } | |||
251 | ||||
252 | for (const CXXBaseSpecifier &Spec : CD->vbases()) { | |||
253 | const RecordDecl *BD = Spec.getType()->getAs<RecordType>()->getDecl(); | |||
254 | Record *BR = getOrCreateRecord(BD); | |||
255 | ||||
256 | if (Descriptor *Desc = GetBaseDesc(BD, BR)) { | |||
257 | VirtSize += align(sizeof(InlineDescriptor)); | |||
258 | VirtBases.push_back({BD, VirtSize, Desc, BR}); | |||
259 | VirtSize += align(BR->getSize()); | |||
260 | continue; | |||
261 | } | |||
262 | return nullptr; | |||
263 | } | |||
264 | } | |||
265 | ||||
266 | // Reserve space for fields. | |||
267 | Record::FieldList Fields; | |||
268 | for (const FieldDecl *FD : RD->fields()) { | |||
269 | // Reserve space for the field's descriptor and the offset. | |||
270 | Size += align(sizeof(InlineDescriptor)); | |||
271 | ||||
272 | // Classify the field and add its metadata. | |||
273 | QualType FT = FD->getType(); | |||
274 | const bool IsConst = FT.isConstQualified(); | |||
275 | const bool IsMutable = FD->isMutable(); | |||
276 | Descriptor *Desc; | |||
277 | if (llvm::Optional<PrimType> T = Ctx.classify(FT)) { | |||
278 | Desc = createDescriptor(FD, *T, IsConst, /*isTemporary=*/false, | |||
279 | IsMutable); | |||
280 | } else { | |||
281 | Desc = createDescriptor(FD, FT.getTypePtr(), IsConst, | |||
282 | /*isTemporary=*/false, IsMutable); | |||
283 | } | |||
284 | if (!Desc) | |||
285 | return nullptr; | |||
286 | Fields.push_back({FD, Size, Desc}); | |||
287 | Size += align(Desc->getAllocSize()); | |||
288 | } | |||
289 | ||||
290 | Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields), | |||
291 | std::move(VirtBases), VirtSize, Size); | |||
292 | Records.insert({RD, R}); | |||
293 | return R; | |||
294 | } | |||
295 | ||||
296 | Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, | |||
297 | bool IsConst, bool IsTemporary, | |||
298 | bool IsMutable) { | |||
299 | // Classes and structures. | |||
300 | if (auto *RT = Ty->getAs<RecordType>()) { | |||
301 | if (auto *Record = getOrCreateRecord(RT->getDecl())) | |||
302 | return allocateDescriptor(D, Record, IsConst, IsTemporary, IsMutable); | |||
303 | } | |||
304 | ||||
305 | // Arrays. | |||
306 | if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) { | |||
307 | QualType ElemTy = ArrayType->getElementType(); | |||
308 | // Array of well-known bounds. | |||
309 | if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) { | |||
310 | size_t NumElems = CAT->getSize().getZExtValue(); | |||
311 | if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) { | |||
312 | // Arrays of primitives. | |||
313 | unsigned ElemSize = primSize(*T); | |||
314 | if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) { | |||
315 | return {}; | |||
316 | } | |||
317 | return allocateDescriptor(D, *T, NumElems, IsConst, IsTemporary, | |||
318 | IsMutable); | |||
319 | } else { | |||
320 | // Arrays of composites. In this case, the array is a list of pointers, | |||
321 | // followed by the actual elements. | |||
322 | Descriptor *Desc = | |||
323 | createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary); | |||
324 | if (!Desc) | |||
325 | return nullptr; | |||
326 | InterpSize ElemSize = Desc->getAllocSize() + sizeof(InlineDescriptor); | |||
327 | if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) | |||
328 | return {}; | |||
329 | return allocateDescriptor(D, Desc, NumElems, IsConst, IsTemporary, | |||
330 | IsMutable); | |||
331 | } | |||
332 | } | |||
333 | ||||
334 | // Array of unknown bounds - cannot be accessed and pointer arithmetic | |||
335 | // is forbidden on pointers to such objects. | |||
336 | if (isa<IncompleteArrayType>(ArrayType)) { | |||
337 | if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) { | |||
338 | return allocateDescriptor(D, *T, IsTemporary, | |||
339 | Descriptor::UnknownSize{}); | |||
340 | } else { | |||
341 | Descriptor *Desc = | |||
342 | createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary); | |||
343 | if (!Desc) | |||
344 | return nullptr; | |||
345 | return allocateDescriptor(D, Desc, IsTemporary, | |||
346 | Descriptor::UnknownSize{}); | |||
347 | } | |||
348 | } | |||
349 | } | |||
350 | ||||
351 | // Atomic types. | |||
352 | if (auto *AT = Ty->getAs<AtomicType>()) { | |||
353 | const Type *InnerTy = AT->getValueType().getTypePtr(); | |||
354 | return createDescriptor(D, InnerTy, IsConst, IsTemporary, IsMutable); | |||
355 | } | |||
356 | ||||
357 | // Complex types - represented as arrays of elements. | |||
358 | if (auto *CT = Ty->getAs<ComplexType>()) { | |||
359 | PrimType ElemTy = *Ctx.classify(CT->getElementType()); | |||
360 | return allocateDescriptor(D, ElemTy, 2, IsConst, IsTemporary, IsMutable); | |||
361 | } | |||
362 | ||||
363 | return nullptr; | |||
364 | } |