GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 98.1% 254 / 1 / 260
Functions: 97.8% 45 / 0 / 46
Branches: 59.2% 297 / 6 / 508

src/symboltablebuilder/Type.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "Type.h"
4
5 #include <utility>
6
7 #include <SourceFile.h>
8 #include <ast/Attributes.h>
9 #include <driver/Driver.h>
10 #include <exception/CompilerError.h>
11 #include <exception/SemanticError.h>
12 #include <global/GlobalResourceManager.h>
13 #include <global/TypeRegistry.h>
14 #include <irgenerator/NameMangling.h>
15 #include <model/Struct.h>
16 #include <model/Union.h>
17 #include <symboltablebuilder/Scope.h>
18 #include <symboltablebuilder/SymbolTableEntry.h>
19
20 #include <llvm/IR/Module.h>
21 #include <llvm/IR/Type.h>
22
23 namespace spice::compiler {
24
25
3/10
✓ Branch 5 → 6 taken 9911220 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 9911220 times.
✓ Branch 7 → 9 taken 9911220 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 19 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
29733660 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
26
27
4/12
✓ Branch 4 → 5 taken 12277 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 12277 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 12277 times.
✓ Branch 8 → 10 taken 12277 times.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 24 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
36831 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
28
29 14183 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
30 const QualTypeList &templateTypes)
31
5/14
✓ Branch 4 → 5 taken 14183 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 14183 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 14183 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 14183 times.
✓ Branch 9 → 11 taken 14183 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 29 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
42549 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
32
33 41892516 Type::Type(TypeChain typeChain) : typeChain(std::move(typeChain)) {}
34
35 /**
36 * Get the super type of the current type
37 *
38 * @return Super type
39 */
40 104570199 SuperType Type::getSuperType() const {
41
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 104570199 times.
104570199 assert(!typeChain.empty());
42 104570199 return typeChain.back().superType;
43 }
44
45 /**
46 * Get the sub type of the current type
47 *
48 * @return Sub type
49 */
50 2354324 const std::string &Type::getSubType() const {
51
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2354324 times.
2354324 assert(!typeChain.empty());
52
2/4
✓ Branch 5 → 6 taken 2354324 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2354324 times.
2354324 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION, TY_ENUM, TY_GENERIC}));
53 2354324 return typeChain.back().subType;
54 }
55
56 /**
57 * Get the array size of the current type
58 *
59 * @return Array size
60 */
61 11837 unsigned int Type::getArraySize() const {
62
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11837 times.
11837 assert(isArray());
63 11837 return typeChain.back().data.arraySize;
64 }
65
66 /**
67 * Get the body scope of the current type
68 *
69 * @return Body scope
70 */
71 8720746 Scope *Type::getBodyScope() const {
72
2/4
✓ Branch 2 → 3 taken 8720746 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8720746 times.
8720746 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION}));
73 8720746 return typeChain.back().data.bodyScope;
74 }
75
76 /**
77 * Get the return type of function type
78 *
79 * @return Function return type
80 */
81 156 const QualType &Type::getFunctionReturnType() const {
82
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 156 times.
156 assert(is(TY_FUNCTION));
83
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 156 times.
156 assert(!typeChain.front().paramTypes.empty());
84 156 return typeChain.front().paramTypes.front();
85 }
86
87 /**
88 * Get the param types of a function or procedure type
89 *
90 * @return Function param types
91 */
92 824 QualTypeList Type::getFunctionParamTypes() const {
93
2/4
✓ Branch 2 → 3 taken 824 times.
✗ Branch 2 → 23 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 824 times.
824 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
94
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 824 times.
824 if (typeChain.front().paramTypes.empty())
95 return {};
96
1/2
✓ Branch 18 → 19 taken 824 times.
✗ Branch 18 → 24 not taken.
3296 return {typeChain.front().paramTypes.begin() + 1, typeChain.front().paramTypes.end()};
97 }
98
99 /**
100 * Get the param and return types of a function or procedure base type
101 *
102 * @return Function param and return types (first is return type, rest are param types)
103 */
104 11090 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
105
2/4
✓ Branch 3 → 4 taken 11090 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 11090 times.
11090 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
106 11090 return typeChain.front().paramTypes;
107 }
108
109 /**
110 * Check if a function or procedure type has captures
111 *
112 * @return Has captures
113 */
114 730 bool Type::hasLambdaCaptures() const {
115
2/4
✓ Branch 3 → 4 taken 730 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 730 times.
730 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
116 730 return typeChain.front().data.hasCaptures;
117 }
118
119 /**
120 * Retrieve template types of the current type
121 *
122 * @return Vector of template types
123 */
124 4079099 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
125
126 /**
127 * Get the type chain depth of the current type
128 *
129 * @return Type chain depth
130 */
131 size_t Type::getTypeChainDepth() const { return typeChain.size(); }
132
133 /**
134 * Check if the current type is of a certain super type
135 *
136 * @return Applicable or not
137 */
138 80483270 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
139
140 /**
141 * Check if the current type is one of a list of super types
142 *
143 * @return Applicable or not
144 */
145 21956534 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
146 63049743 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
147 }
148
149 /**
150 * Check if the base type of the current type chain is of a certain super type
151 *
152 * @param superType Super type to check for
153 * @return Applicable or not
154 */
155 41379521 bool Type::isBase(SuperType superType) const {
156
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 41379521 times.
41379521 assert(!typeChain.empty());
157 41379521 return typeChain.front().superType == superType;
158 }
159
160 /**
161 * Check if the current type is a primitive type
162 *
163 * @return Primitive type or not
164 */
165
1/2
✓ Branch 2 → 3 taken 1110126 times.
✗ Branch 2 → 6 not taken.
1110126 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
166
167 /**
168 * Check if the type is an extended primitive type
169 * The definition of extended primitive types contains all primitive types plus the following:
170 * - structs
171 * - interfaces
172 * - functions/procedures
173 *
174 * @return Extended primitive or not
175 */
176 847719 bool Type::isExtendedPrimitive() const {
177
6/8
✓ Branch 2 → 3 taken 847719 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 316464 times.
✓ Branch 3 → 6 taken 531255 times.
✓ Branch 4 → 5 taken 316464 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 240035 times.
✓ Branch 5 → 7 taken 76429 times.
847719 return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION, TY_FUNCTION, TY_PROCEDURE});
178 }
179
180 /**
181 * Check if the current type is a pointer type
182 *
183 * @return Pointer type or not
184 */
185 4015982 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
186
187 /**
188 * Check if the current type is a reference type
189 *
190 * @return Reference type or not
191 */
192 8651347 bool Type::isRef() const { return getSuperType() == TY_REF; }
193
194 /**
195 * Check if the current type is an array type
196 *
197 * @return Array type or not
198 */
199 2321613 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
200
201 /**
202 * Checks if the base type is generic itself or has generic parts in its template types
203 *
204 * @return Contains generic parts or not
205 */
206 3358696 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
207
1/2
✓ Branch 2 → 3 taken 3358696 times.
✗ Branch 2 → 34 not taken.
3358696 const Type *baseType = getBase();
208
209 // Check if the type itself is generic
210
2/2
✓ Branch 4 → 5 taken 544299 times.
✓ Branch 4 → 6 taken 2814397 times.
3358696 if (baseType->is(TY_GENERIC))
211 544299 return true;
212
213 // Check if the type has generic template types
214
1/2
✓ Branch 7 → 8 taken 2814397 times.
✗ Branch 7 → 34 not taken.
2814397 const auto templateTypes = baseType->getTemplateTypes();
215
3/4
✓ Branch 8 → 9 taken 2814397 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 232271 times.
✓ Branch 9 → 11 taken 2582126 times.
3450659 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
216 232271 return true;
217
218 // Check param and return types or functions/procedures
219
3/4
✓ Branch 11 → 12 taken 2582126 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 10265 times.
✓ Branch 12 → 24 taken 2571861 times.
2582126 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
220
2/4
✓ Branch 13 → 14 taken 10265 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 10265 times.
✗ Branch 14 → 31 not taken.
10265 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
221
3/4
✓ Branch 15 → 16 taken 10265 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 446 times.
✓ Branch 16 → 18 taken 9819 times.
28475 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
222 446 return true;
223
2/2
✓ Branch 20 → 21 taken 9819 times.
✓ Branch 20 → 23 taken 446 times.
10265 }
224
225 2581680 return false; // Does not have generic parts
226 2814397 }
227
228 /**
229 * Check if the current type is of the same container type like the other type.
230 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
231 *
232 * @param other Other symbol type
233 * @return Same container type or not
234 */
235 877909 bool Type::isSameContainerTypeAs(const Type *other) const {
236
4/4
✓ Branch 3 → 4 taken 30952 times.
✓ Branch 3 → 7 taken 846957 times.
✓ Branch 5 → 6 taken 28493 times.
✓ Branch 5 → 7 taken 2459 times.
877909 const bool bothPtr = isPtr() && other->isPtr();
237
4/4
✓ Branch 9 → 10 taken 56025 times.
✓ Branch 9 → 13 taken 821884 times.
✓ Branch 11 → 12 taken 41699 times.
✓ Branch 11 → 13 taken 14326 times.
877909 const bool bothRef = isRef() && other->isRef();
238
3/4
✓ Branch 15 → 16 taken 856 times.
✓ Branch 15 → 19 taken 877053 times.
✓ Branch 17 → 18 taken 856 times.
✗ Branch 17 → 19 not taken.
877909 const bool bothArray = isArray() && other->isArray();
239
6/6
✓ Branch 20 → 21 taken 849416 times.
✓ Branch 20 → 23 taken 28493 times.
✓ Branch 21 → 22 taken 807717 times.
✓ Branch 21 → 23 taken 41699 times.
✓ Branch 22 → 23 taken 856 times.
✓ Branch 22 → 24 taken 806861 times.
877909 return bothPtr || bothRef || bothArray;
240 }
241
242 /**
243 * Check for the matching compatibility of two types.
244 * Useful for struct and function matching as well as assignment type validation and function arg matching.
245 *
246 * @param otherType Type to compare against
247 * @param ignoreArraySize Ignore array sizes
248 * @return Matching or not
249 */
250 1013392 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
251 // If the size does not match, it is not equal
252
2/2
✓ Branch 4 → 5 taken 118898 times.
✓ Branch 4 → 6 taken 894494 times.
1013392 if (typeChain.size() != otherType->typeChain.size())
253 118898 return false;
254
255 // Compare the elements
256
2/2
✓ Branch 18 → 7 taken 995658 times.
✓ Branch 18 → 19 taken 601744 times.
1597402 for (size_t i = 0; i < typeChain.size(); i++) {
257 995658 const TypeChainElement &lhsElement = typeChain.at(i);
258 995658 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
259
260 // Ignore differences in array size
261
5/6
✓ Branch 9 → 10 taken 603643 times.
✓ Branch 9 → 13 taken 392015 times.
✓ Branch 10 → 11 taken 10 times.
✓ Branch 10 → 13 taken 603633 times.
✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 13 not taken.
995658 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
262 10 continue;
263
264 // Not both types are arrays -> compare them as usual
265
2/2
✓ Branch 14 → 15 taken 292750 times.
✓ Branch 14 → 16 taken 702898 times.
995648 if (lhsElement != rhsElement)
266 292750 return false;
267 }
268
269 601744 return true;
270 }
271
272 /**
273 * Get the name of the symbol type as a string
274 *
275 * @param name Get name of type
276 * @param withSize Include the array size for sized types
277 * @param ignorePublic Ignore any potential public qualifier
278 * @param withAliases Print aliases as is and not decompose them
279 * @return Symbol type name
280 */
281 5442991 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
282 // Loop through all chain elements
283
2/2
✓ Branch 18 → 4 taken 7142885 times.
✓ Branch 18 → 19 taken 5442991 times.
18028867 for (const TypeChainElement &chainElement : typeChain)
284
2/4
✓ Branch 6 → 7 taken 7142885 times.
✗ Branch 6 → 22 not taken.
✓ Branch 7 → 8 taken 7142885 times.
✗ Branch 7 → 20 not taken.
7142885 name << chainElement.getName(withSize, ignorePublic, withAliases);
285 5442991 }
286
287 /**
288 * Get the name of the symbol type as a string
289 *
290 * @param withSize Include the array size for sized types
291 * @param ignorePublic Ignore any potential public qualifier
292 * @param withAliases Print aliases as is and not decompose them
293 * @return Symbol type name
294 */
295 117579 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
296
1/2
✓ Branch 2 → 3 taken 117579 times.
✗ Branch 2 → 11 not taken.
117579 std::stringstream name;
297
1/2
✓ Branch 3 → 4 taken 117579 times.
✗ Branch 3 → 9 not taken.
117579 getName(name, withSize, ignorePublic, withAliases);
298
1/2
✓ Branch 4 → 5 taken 117579 times.
✗ Branch 4 → 9 not taken.
235158 return name.str();
299 117579 }
300
301 /**
302 * Get the pointer type of the current type as a new type
303 *
304 * @param node AST node for error messages
305 * @return Pointer type of the current type
306 */
307 244131 const Type *Type::toPtr(const ASTNode *node) const {
308
2/2
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 12 taken 244127 times.
244131 if (is(TY_DYN))
309
2/4
✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 32 not taken.
✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 29 not taken.
12 throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead");
310
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 244127 times.
244127 if (isRef())
311 throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead");
312
313 // Create new type chain
314
1/2
✓ Branch 22 → 23 taken 244127 times.
✗ Branch 22 → 50 not taken.
244127 TypeChain newTypeChain = typeChain;
315
1/2
✓ Branch 23 → 24 taken 244127 times.
✗ Branch 23 → 47 not taken.
244127 newTypeChain.emplace_back(TY_PTR);
316
317 // Register new type or return if already registered
318
1/2
✓ Branch 24 → 25 taken 244127 times.
✗ Branch 24 → 48 not taken.
488254 return TypeRegistry::getOrInsert(newTypeChain);
319 244127 }
320
321 /**
322 * Get the reference type of the current type as a new type
323 *
324 * @param node AST node for error messages
325 * @return Reference type of the current type
326 */
327 114111 const Type *Type::toRef(const ASTNode *node) const {
328
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 114111 times.
114111 if (is(TY_DYN))
329 throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead");
330
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 114111 times.
114111 if (isRef())
331 throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed");
332
333 // Create new type chain
334
1/2
✓ Branch 22 → 23 taken 114111 times.
✗ Branch 22 → 50 not taken.
114111 TypeChain newTypeChain = typeChain;
335
1/2
✓ Branch 23 → 24 taken 114111 times.
✗ Branch 23 → 47 not taken.
114111 newTypeChain.emplace_back(TY_REF);
336
337 // Register new type or return if already registered
338
1/2
✓ Branch 24 → 25 taken 114111 times.
✗ Branch 24 → 48 not taken.
228222 return TypeRegistry::getOrInsert(newTypeChain);
339 114111 }
340
341 /**
342 * Get the array type of the current type as a new type
343 *
344 * @param node AST node for error messages
345 * @param size Size of the array
346 * @param skipDynCheck Skip check if array base type is dyn
347 * @return Array type of the current type
348 */
349 1849 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
350
6/6
✓ Branch 2 → 3 taken 1183 times.
✓ Branch 2 → 6 taken 666 times.
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 1181 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 16 taken 1847 times.
1849 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
351
2/4
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 26 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 23 not taken.
6 throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead");
352
353 // Create new type chain
354
1/2
✓ Branch 16 → 17 taken 1847 times.
✗ Branch 16 → 36 not taken.
1847 TypeChain newTypeChain = typeChain;
355
1/2
✓ Branch 17 → 18 taken 1847 times.
✗ Branch 17 → 32 not taken.
1847 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
356
357 // Register new type or return if already registered
358
1/2
✓ Branch 18 → 19 taken 1847 times.
✗ Branch 18 → 34 not taken.
3694 return TypeRegistry::getOrInsert(newTypeChain);
359 1847 }
360
361 /**
362 * Retrieve the base type of an array or a pointer
363 *
364 * @return Base type
365 */
366 1420143 const Type *Type::getContained() const {
367
2/2
✓ Branch 3 → 4 taken 3340 times.
✓ Branch 3 → 6 taken 1416803 times.
1420143 if (is(TY_STRING))
368
1/2
✓ Branch 4 → 5 taken 3340 times.
✗ Branch 4 → 18 not taken.
3340 return TypeRegistry::getOrInsert(TY_CHAR);
369
370 // Create new type chain
371
1/2
✓ Branch 6 → 7 taken 1416803 times.
✗ Branch 6 → 18 not taken.
1416803 TypeChain newTypeChain = typeChain;
372
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1416803 times.
1416803 assert(newTypeChain.size() > 1);
373 1416803 newTypeChain.pop_back();
374
375 // Register new type or return if already registered
376
1/2
✓ Branch 11 → 12 taken 1416803 times.
✗ Branch 11 → 16 not taken.
1416803 return TypeRegistry::getOrInsert(newTypeChain);
377 1416803 }
378
379 /**
380 * Replace the base type with another one
381 *
382 * @param newBaseType New base type
383 * @return The new type
384 */
385 155750 const Type *Type::replaceBase(const Type *newBaseType) const {
386
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 155750 times.
155750 assert(!typeChain.empty());
387
388 // Create new type
389
1/2
✓ Branch 5 → 6 taken 155750 times.
✗ Branch 5 → 27 not taken.
155750 TypeChain newTypeChain = newBaseType->typeChain;
390
4/4
✓ Branch 7 → 8 taken 7302 times.
✓ Branch 7 → 11 taken 148448 times.
✓ Branch 9 → 10 taken 144 times.
✓ Branch 9 → 11 taken 7158 times.
155750 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
391
2/2
✓ Branch 19 → 13 taken 19759 times.
✓ Branch 19 → 20 taken 155750 times.
175509 for (size_t i = 1; i < typeChain.size(); i++)
392
3/4
✓ Branch 13 → 14 taken 144 times.
✓ Branch 13 → 15 taken 19615 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 144 times.
19759 if (!doubleRef || i > 1)
393
2/4
✓ Branch 15 → 16 taken 19615 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 19615 times.
✗ Branch 16 → 25 not taken.
19615 newTypeChain.push_back(typeChain.at(i));
394
395 // Register new type or return if already registered
396
1/2
✓ Branch 20 → 21 taken 155750 times.
✗ Branch 20 → 25 not taken.
311500 return TypeRegistry::getOrInsert(newTypeChain);
397 155750 }
398
399 /**
400 * Remove reference wrapper from the current type
401 *
402 * @return Type without reference wrapper
403 */
404
1/2
✓ Branch 3 → 4 taken 335190 times.
✗ Branch 3 → 6 not taken.
335190 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
405
406 /**
407 * Retrieve the base type of the current type
408 *
409 * @return Base type
410 */
411 18579924 const Type *Type::getBase() const {
412
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 18579924 times.
18579924 assert(!typeChain.empty());
413
414 // Create new type chain
415
3/6
✓ Branch 9 → 10 taken 18579924 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 18579924 times.
✓ Branch 12 → 14 taken 18579924 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
55739772 const TypeChain newTypeChain = {typeChain.front()};
416
417 // Register new type or return if already registered
418
1/2
✓ Branch 14 → 15 taken 18579924 times.
✗ Branch 14 → 32 not taken.
37159848 return TypeRegistry::getOrInsert(newTypeChain);
419
1/6
✓ Branch 6 → 7 taken 18579924 times.
✗ Branch 6 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 30 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
37159848 }
420
421 /**
422 * Retrieve the same type, but with lambda captures
423 *
424 * @return Type with lambda captures
425 */
426 279 const Type *Type::getWithLambdaCaptures(bool enabled) const {
427
3/6
✓ Branch 2 → 3 taken 279 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 279 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 279 times.
279 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
428
429 // Create new type chain
430
1/2
✓ Branch 6 → 7 taken 279 times.
✗ Branch 6 → 16 not taken.
279 TypeChain newTypeChain = typeChain;
431 279 newTypeChain.front().data.hasCaptures = enabled;
432
433 // Register new type or return if already registered
434
1/2
✓ Branch 8 → 9 taken 279 times.
✗ Branch 8 → 14 not taken.
558 return TypeRegistry::getOrInsert(newTypeChain);
435 279 }
436
437 /**
438 * Retrieve the same type, but with the body scope removed
439 *
440 * @return Type with body scope removed
441 */
442 255100 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
443
3/6
✓ Branch 2 → 3 taken 255100 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 255100 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 255100 times.
255100 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION}));
444
445 // Create new type chain
446
1/2
✓ Branch 6 → 7 taken 255100 times.
✗ Branch 6 → 16 not taken.
255100 TypeChain newTypeChain = typeChain;
447 255100 newTypeChain.front().data.bodyScope = bodyScope;
448
449 // Register new type or return if already registered
450
1/2
✓ Branch 8 → 9 taken 255100 times.
✗ Branch 8 → 14 not taken.
510200 return TypeRegistry::getOrInsert(newTypeChain);
451 255100 }
452
453 /**
454 * Retrieve the same type, but with the given template types
455 *
456 * @return Type with new template types
457 */
458 36461 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
459
2/4
✓ Branch 2 → 3 taken 36461 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 36461 times.
36461 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION}));
460 36461 return getWithBaseTemplateTypes(templateTypes);
461 }
462
463 /**
464 * Retrieve the same type, but with the given base template types
465 *
466 * @return Type with new base template types
467 */
468 84096 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
469
3/6
✓ Branch 2 → 3 taken 84096 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 84096 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 84096 times.
84096 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION}));
470
471 // Create new type chain
472
1/2
✓ Branch 6 → 7 taken 84096 times.
✗ Branch 6 → 17 not taken.
84096 TypeChain newTypeChain = typeChain;
473
1/2
✓ Branch 8 → 9 taken 84096 times.
✗ Branch 8 → 15 not taken.
84096 newTypeChain.front().templateTypes = templateTypes;
474
475 // Register new type or return if already registered
476
1/2
✓ Branch 9 → 10 taken 84096 times.
✗ Branch 9 → 15 not taken.
168192 return TypeRegistry::getOrInsert(newTypeChain);
477 84096 }
478
479 /**
480 * Retrieve the same type, but with the param and return types removed
481 *
482 * @return Type with param and return types removed
483 */
484 94221 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
485
3/6
✓ Branch 2 → 3 taken 94221 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 94221 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 94221 times.
94221 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
486
487 // Create new type chain
488
1/2
✓ Branch 6 → 7 taken 94221 times.
✗ Branch 6 → 17 not taken.
94221 TypeChain newTypeChain = typeChain;
489
1/2
✓ Branch 8 → 9 taken 94221 times.
✗ Branch 8 → 15 not taken.
94221 newTypeChain.front().paramTypes = paramAndReturnTypes;
490
491 // Register new type or return if already registered
492
1/2
✓ Branch 9 → 10 taken 94221 times.
✗ Branch 9 → 15 not taken.
188442 return TypeRegistry::getOrInsert(newTypeChain);
493 94221 }
494
495 /**
496 * Return the LLVM type for this symbol type
497 *
498 * @param sourceFile Referenced source file
499 * @return Corresponding LLVM type
500 */
501 81659 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
502
2/4
✓ Branch 3 → 4 taken 81659 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 81659 times.
✗ Branch 5 → 7 not taken.
81659 assert(!typeChain.empty() && !is(TY_INVALID));
503
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 81657 times.
81659 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
504
505
10/12
✓ Branch 11 → 12 taken 81659 times.
✗ Branch 11 → 222 not taken.
✓ Branch 12 → 13 taken 41054 times.
✓ Branch 12 → 17 taken 40605 times.
✓ Branch 14 → 15 taken 995 times.
✓ Branch 14 → 18 taken 40059 times.
✓ Branch 15 → 16 taken 995 times.
✗ Branch 15 → 222 not taken.
✓ Branch 16 → 17 taken 142 times.
✓ Branch 16 → 18 taken 853 times.
✓ Branch 19 → 20 taken 40747 times.
✓ Branch 19 → 22 taken 40912 times.
81659 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
506 40747 return llvm::PointerType::get(context, 0);
507
508
2/2
✓ Branch 23 → 24 taken 853 times.
✓ Branch 23 → 32 taken 40059 times.
40912 if (isArray()) {
509
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 853 times.
853 assert(getArraySize() > 0);
510 853 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
511 853 return llvm::ArrayType::get(containedType, getArraySize());
512 }
513
514
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 40059 times.
40059 assert(!hasAnyGenericParts());
515
516
2/2
✓ Branch 36 → 37 taken 469 times.
✓ Branch 36 → 39 taken 39590 times.
40059 if (is(TY_DOUBLE))
517 469 return llvm::Type::getDoubleTy(context);
518
519
3/4
✓ Branch 39 → 40 taken 39590 times.
✗ Branch 39 → 223 not taken.
✓ Branch 40 → 41 taken 3741 times.
✓ Branch 40 → 43 taken 35849 times.
39590 if (isOneOf({TY_INT, TY_ENUM}))
520 3741 return llvm::Type::getInt32Ty(context);
521
522
2/2
✓ Branch 44 → 45 taken 294 times.
✓ Branch 44 → 47 taken 35555 times.
35849 if (is(TY_SHORT))
523 294 return llvm::Type::getInt16Ty(context);
524
525
2/2
✓ Branch 48 → 49 taken 2490 times.
✓ Branch 48 → 51 taken 33065 times.
35555 if (is(TY_LONG))
526 2490 return llvm::Type::getInt64Ty(context);
527
528
3/4
✓ Branch 51 → 52 taken 33065 times.
✗ Branch 51 → 224 not taken.
✓ Branch 52 → 53 taken 3024 times.
✓ Branch 52 → 55 taken 30041 times.
33065 if (isOneOf({TY_CHAR, TY_BYTE}))
529 3024 return llvm::Type::getInt8Ty(context);
530
531
2/2
✓ Branch 56 → 57 taken 3359 times.
✓ Branch 56 → 59 taken 26682 times.
30041 if (is(TY_BOOL))
532 3359 return llvm::Type::getInt1Ty(context);
533
534
3/4
✓ Branch 59 → 60 taken 26682 times.
✗ Branch 59 → 225 not taken.
✓ Branch 60 → 61 taken 25958 times.
✓ Branch 60 → 153 taken 724 times.
26682 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
535
1/2
✓ Branch 61 → 62 taken 25958 times.
✗ Branch 61 → 254 not taken.
25958 const Scope *structBodyScope = getBodyScope();
536
2/4
✓ Branch 63 → 64 taken 25958 times.
✗ Branch 63 → 254 not taken.
✓ Branch 64 → 65 taken 25958 times.
✗ Branch 64 → 254 not taken.
25958 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
537
1/2
✓ Branch 65 → 66 taken 25958 times.
✗ Branch 65 → 252 not taken.
25958 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
538
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 25958 times.
25958 assert(structSymbol != nullptr);
539
540 // Collect concrete field types
541 25958 std::string mangledName;
542 25958 std::vector<llvm::Type *> fieldTypes;
543 25958 bool isPacked = false;
544
2/2
✓ Branch 72 → 73 taken 23222 times.
✓ Branch 72 → 135 taken 2736 times.
25958 if (is(TY_STRUCT)) { // Struct
545
2/4
✓ Branch 73 → 74 taken 23222 times.
✗ Branch 73 → 248 not taken.
✓ Branch 74 → 75 taken 23222 times.
✗ Branch 74 → 248 not taken.
23222 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
546
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 23222 times.
23222 assert(spiceStruct != nullptr);
547
1/2
✓ Branch 77 → 78 taken 23222 times.
✗ Branch 77 → 226 not taken.
23222 mangledName = NameMangling::mangleStruct(*spiceStruct);
548
549
1/2
✓ Branch 80 → 81 taken 23222 times.
✗ Branch 80 → 248 not taken.
23222 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
550
1/2
✓ Branch 81 → 82 taken 23222 times.
✗ Branch 81 → 248 not taken.
23222 fieldTypes.reserve(totalFieldCount);
551
552 // If the struct implements interfaces, the first implicit field (added below via lookupField) is an interface
553 // type, which already lowers to a { ptr } struct carrying the vtable pointer. Only add an explicit ptr field
554 // here for structs without interfaces that still need a vtable (e.g. RTTI root types), to avoid duplicating it.
555
2/4
✓ Branch 82 → 83 taken 23222 times.
✗ Branch 82 → 248 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 23222 times.
23222 assert(structSymbol->declNode->isStructDef());
556
1/2
✓ Branch 85 → 86 taken 23222 times.
✗ Branch 85 → 87 not taken.
23222 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
557
3/4
✓ Branch 94 → 95 taken 23222 times.
✗ Branch 94 → 248 not taken.
✓ Branch 95 → 96 taken 218 times.
✓ Branch 95 → 99 taken 23004 times.
23222 if (spiceStruct->hasSynthesizedVTablePtr())
558
2/4
✓ Branch 96 → 97 taken 218 times.
✗ Branch 96 → 227 not taken.
✓ Branch 97 → 98 taken 218 times.
✗ Branch 97 → 227 not taken.
218 fieldTypes.push_back(llvm::PointerType::get(context, 0));
559
560 // Collect all field types
561
2/2
✓ Branch 113 → 100 taken 61944 times.
✓ Branch 113 → 114 taken 23222 times.
85166 for (size_t i = 0; i < totalFieldCount; i++) {
562
1/2
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 103 taken 61944 times.
61944 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
563
1/2
✗ Branch 106 → 107 not taken.
✓ Branch 106 → 108 taken 61944 times.
61944 assert(fieldSymbol != nullptr);
564
3/6
✓ Branch 108 → 109 taken 61944 times.
✗ Branch 108 → 228 not taken.
✓ Branch 110 → 111 taken 61944 times.
✗ Branch 110 → 228 not taken.
✓ Branch 111 → 112 taken 61944 times.
✗ Branch 111 → 228 not taken.
61944 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
565 }
566
567 // Check if the struct is declared as packed
568
12/18
✓ Branch 114 → 115 taken 220 times.
✓ Branch 114 → 121 taken 23002 times.
✓ Branch 117 → 118 taken 220 times.
✗ Branch 117 → 229 not taken.
✓ Branch 118 → 119 taken 220 times.
✗ Branch 118 → 229 not taken.
✓ Branch 119 → 120 taken 2 times.
✓ Branch 119 → 121 taken 218 times.
✓ Branch 122 → 123 taken 220 times.
✓ Branch 122 → 124 taken 23002 times.
✓ Branch 124 → 125 taken 220 times.
✓ Branch 124 → 127 taken 23002 times.
✓ Branch 127 → 128 taken 2 times.
✓ Branch 127 → 145 taken 23220 times.
✗ Branch 229 → 230 not taken.
✗ Branch 229 → 231 not taken.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 236 not taken.
23662 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
569
2/4
✓ Branch 130 → 131 taken 2 times.
✗ Branch 130 → 240 not taken.
✓ Branch 131 → 132 taken 2 times.
✗ Branch 131 → 238 not taken.
6 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
570 } else { // Interface
571
2/4
✓ Branch 135 → 136 taken 2736 times.
✗ Branch 135 → 248 not taken.
✓ Branch 136 → 137 taken 2736 times.
✗ Branch 136 → 248 not taken.
2736 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
572
1/2
✗ Branch 137 → 138 not taken.
✓ Branch 137 → 139 taken 2736 times.
2736 assert(spiceInterface != nullptr);
573
1/2
✓ Branch 139 → 140 taken 2736 times.
✗ Branch 139 → 244 not taken.
2736 mangledName = NameMangling::mangleInterface(*spiceInterface);
574
575 // vtable pointer
576
2/4
✓ Branch 142 → 143 taken 2736 times.
✗ Branch 142 → 245 not taken.
✓ Branch 143 → 144 taken 2736 times.
✗ Branch 143 → 245 not taken.
2736 fieldTypes.push_back(llvm::PointerType::get(context, 0));
577 }
578
579
1/2
✓ Branch 147 → 148 taken 25958 times.
✗ Branch 147 → 246 not taken.
25958 return llvm::StructType::create(context, fieldTypes, mangledName, isPacked);
580 25958 }
581
582
2/2
✓ Branch 154 → 155 taken 64 times.
✓ Branch 154 → 206 taken 660 times.
724 if (is(TY_UNION)) {
583 // A union is lowered to { i32 tag, [0 x MaxAlignTy] alignPad, [maxSize x i8] payload }. The tag tracks which field
584 // is currently active. The zero-length array contributes no bytes but forces the whole struct's (and therefore the
585 // payload's) ABI alignment to be at least as strict as the most-aligned field, so that every field can be safely
586 // loaded/stored at the payload's address regardless of its own alignment requirement. The payload itself is always
587 // a raw byte buffer (not a typed array), so that any field's value can be stored/loaded there directly, and any
588 // compile-time constant for it can be built uniformly as packed raw bytes, without needing a legal LLVM constant
589 // conversion between the payload's declared element type and a field's unrelated type.
590
1/2
✓ Branch 155 → 156 taken 64 times.
✗ Branch 155 → 267 not taken.
64 const Scope *unionBodyScope = getBodyScope();
591
2/4
✓ Branch 157 → 158 taken 64 times.
✗ Branch 157 → 267 not taken.
✓ Branch 158 → 159 taken 64 times.
✗ Branch 158 → 267 not taken.
64 const std::string unionSignature = Union::getSignature(getSubType(), getTemplateTypes());
592
1/2
✓ Branch 159 → 160 taken 64 times.
✗ Branch 159 → 265 not taken.
64 const SymbolTableEntry *unionSymbol = unionBodyScope->parent->lookupStrict(unionSignature);
593
1/2
✗ Branch 162 → 163 not taken.
✓ Branch 162 → 164 taken 64 times.
64 assert(unionSymbol != nullptr);
594
595
2/4
✓ Branch 164 → 165 taken 64 times.
✗ Branch 164 → 265 not taken.
✓ Branch 165 → 166 taken 64 times.
✗ Branch 165 → 265 not taken.
64 const Union *spiceUnion = unionSymbol->getQualType().getUnion(unionSymbol->declNode);
596
1/2
✗ Branch 166 → 167 not taken.
✓ Branch 166 → 168 taken 64 times.
64 assert(spiceUnion != nullptr);
597
1/2
✓ Branch 168 → 169 taken 64 times.
✗ Branch 168 → 265 not taken.
64 const std::string mangledName = NameMangling::mangleUnion(*spiceUnion);
598
599
1/2
✓ Branch 170 → 171 taken 64 times.
✗ Branch 170 → 263 not taken.
64 const llvm::DataLayout &dataLayout = sourceFile->targetMachine->createDataLayout();
600
1/2
✓ Branch 171 → 172 taken 64 times.
✗ Branch 171 → 261 not taken.
64 const size_t totalFieldCount = spiceUnion->scope->getFieldCount();
601
602 64 uint64_t maxSize = 0;
603 64 uint64_t maxAlign = 1;
604
1/2
✓ Branch 172 → 173 taken 64 times.
✗ Branch 172 → 261 not taken.
64 llvm::Type *maxAlignFieldType = llvm::Type::getInt8Ty(context);
605
2/2
✓ Branch 193 → 174 taken 380 times.
✓ Branch 193 → 194 taken 64 times.
444 for (size_t i = 0; i < totalFieldCount; i++) {
606
1/2
✓ Branch 174 → 175 taken 380 times.
✗ Branch 174 → 177 not taken.
380 const SymbolTableEntry *fieldSymbol = spiceUnion->scope->lookupField(i);
607
1/2
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 182 taken 380 times.
380 assert(fieldSymbol != nullptr);
608
2/4
✓ Branch 182 → 183 taken 380 times.
✗ Branch 182 → 257 not taken.
✓ Branch 184 → 185 taken 380 times.
✗ Branch 184 → 257 not taken.
380 llvm::Type *fieldType = sourceFile->getLLVMType(fieldSymbol->getQualType().getType());
609
2/4
✓ Branch 185 → 186 taken 380 times.
✗ Branch 185 → 255 not taken.
✓ Branch 186 → 187 taken 380 times.
✗ Branch 186 → 255 not taken.
380 const uint64_t fieldSize = dataLayout.getTypeAllocSize(fieldType);
610
1/2
✓ Branch 187 → 188 taken 380 times.
✗ Branch 187 → 256 not taken.
380 const uint64_t fieldAlign = dataLayout.getABITypeAlign(fieldType).value();
611 380 maxSize = std::max(maxSize, fieldSize);
612
2/2
✓ Branch 190 → 191 taken 78 times.
✓ Branch 190 → 192 taken 302 times.
380 if (fieldAlign > maxAlign) {
613 78 maxAlign = fieldAlign;
614 78 maxAlignFieldType = fieldType;
615 }
616 }
617
618
1/2
✓ Branch 194 → 195 taken 64 times.
✗ Branch 194 → 261 not taken.
64 llvm::Type *tagType = llvm::Type::getInt32Ty(context);
619
1/2
✓ Branch 195 → 196 taken 64 times.
✗ Branch 195 → 261 not taken.
64 llvm::Type *alignPadType = llvm::ArrayType::get(maxAlignFieldType, 0);
620
2/4
✓ Branch 196 → 197 taken 64 times.
✗ Branch 196 → 261 not taken.
✓ Branch 197 → 198 taken 64 times.
✗ Branch 197 → 261 not taken.
64 llvm::Type *payloadType = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), maxSize);
621
1/2
✓ Branch 200 → 201 taken 64 times.
✗ Branch 200 → 258 not taken.
64 return llvm::StructType::create(context, {tagType, alignPadType, payloadType}, mangledName);
622 64 }
623
624
2/4
✓ Branch 206 → 207 taken 660 times.
✗ Branch 206 → 268 not taken.
✓ Branch 207 → 208 taken 660 times.
✗ Branch 207 → 214 not taken.
660 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
625 // Lambda/function values are represented as a fat pointer with three slots:
626 // { fctPtr, capturePtr, captureSize }. The capture size (in bytes) travels with
627 // the value so that the std Lambda type can take ownership of the captures on the
628 // heap regardless of where the lambda came from. It is 0 if there is no owned
629 // capture struct (no captures, or a single capture stored inline in capturePtr).
630 660 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
631 660 llvm::IntegerType *int64Ty = llvm::Type::getInt64Ty(context);
632
1/2
✓ Branch 211 → 212 taken 660 times.
✗ Branch 211 → 269 not taken.
660 return llvm::StructType::get(context, {ptrTy, ptrTy, int64Ty});
633 }
634
635 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
636 }
637
638 /**
639 * Remove pointers / arrays / references if both types have them as far as possible.
640 *
641 * @param typeA Candidate type
642 * @param typeB Requested type
643 */
644 791327 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
645 // Unwrap both types as far as possible
646
2/2
✓ Branch 7 → 3 taken 65065 times.
✓ Branch 7 → 8 taken 791327 times.
856392 while (typeA->isSameContainerTypeAs(typeB)) {
647 65065 typeB = typeB->getContained();
648 65065 typeA = typeA->getContained();
649 }
650 791327 }
651
652 /**
653 * Remove pointers / arrays / references if both types have them as far as possible.
654 * Furthermore, remove reference wrappers if possible.
655 *
656 * @param typeA Candidate type
657 * @param typeB Requested type
658 */
659 775187 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
660 // Remove reference wrapper of front type if required
661
6/6
✓ Branch 3 → 4 taken 355380 times.
✓ Branch 3 → 7 taken 419807 times.
✓ Branch 5 → 6 taken 313763 times.
✓ Branch 5 → 7 taken 41617 times.
✓ Branch 8 → 9 taken 313763 times.
✓ Branch 8 → 11 taken 461424 times.
775187 if (typeA->isRef() && !typeB->isRef())
662 313763 typeA = typeA->removeReferenceWrapper();
663
664 // Remove reference wrapper of requested type if required
665
8/8
✓ Branch 12 → 13 taken 733570 times.
✓ Branch 12 → 18 taken 41617 times.
✓ Branch 14 → 15 taken 25920 times.
✓ Branch 14 → 18 taken 707650 times.
✓ Branch 16 → 17 taken 21427 times.
✓ Branch 16 → 18 taken 4493 times.
✓ Branch 19 → 20 taken 21427 times.
✓ Branch 19 → 22 taken 753760 times.
775187 if (!typeA->isRef() && typeB->isRef() && !typeA->isBase(TY_GENERIC))
666 21427 typeB = typeB->removeReferenceWrapper();
667
668 // Unwrap both types as far as possible
669 775187 unwrapBoth(typeA, typeB);
670 775187 }
671
672 /**
673 * Check if two types have the same type chain depth
674 *
675 * @param typeA First type
676 * @param typeB Second type
677 * @return Same depth or not
678 */
679 126499 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
680 126499 return typeA->typeChain.size() == typeB->typeChain.size();
681 }
682
683 } // namespace spice::compiler
684