GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.8% 225 / 1 / 231
Functions: 97.8% 45 / 0 / 46
Branches: 59.8% 268 / 6 / 454

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 <symboltablebuilder/Scope.h>
17 #include <symboltablebuilder/SymbolTableEntry.h>
18
19 #include <llvm/IR/Module.h>
20 #include <llvm/IR/Type.h>
21
22 namespace spice::compiler {
23
24
3/10
✓ Branch 5 → 6 taken 3461351 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 3461351 times.
✓ Branch 7 → 9 taken 3461351 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.
10384053 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
25
26
4/12
✓ Branch 4 → 5 taken 5447 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 5447 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 5447 times.
✓ Branch 8 → 10 taken 5447 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.
16341 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
27
28 4846 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
29 const QualTypeList &templateTypes)
30
5/14
✓ Branch 4 → 5 taken 4846 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 4846 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 4846 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 4846 times.
✓ Branch 9 → 11 taken 4846 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.
14538 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
31
32 14257516 Type::Type(TypeChain typeChain) : typeChain(std::move(typeChain)) {}
33
34 /**
35 * Get the super type of the current type
36 *
37 * @return Super type
38 */
39 34770891 SuperType Type::getSuperType() const {
40
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 34770891 times.
34770891 assert(!typeChain.empty());
41 34770891 return typeChain.back().superType;
42 }
43
44 /**
45 * Get the sub type of the current type
46 *
47 * @return Sub type
48 */
49 917425 const std::string &Type::getSubType() const {
50
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 917425 times.
917425 assert(!typeChain.empty());
51
2/4
✓ Branch 5 → 6 taken 917425 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 917425 times.
917425 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
52 917425 return typeChain.back().subType;
53 }
54
55 /**
56 * Get the array size of the current type
57 *
58 * @return Array size
59 */
60 1395 unsigned int Type::getArraySize() const {
61
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1395 times.
1395 assert(isArray());
62 1395 return typeChain.back().data.arraySize;
63 }
64
65 /**
66 * Get the body scope of the current type
67 *
68 * @return Body scope
69 */
70 2246838 Scope *Type::getBodyScope() const {
71
2/4
✓ Branch 2 → 3 taken 2246838 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2246838 times.
2246838 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
72 2246838 return typeChain.back().data.bodyScope;
73 }
74
75 /**
76 * Get the return type of function type
77 *
78 * @return Function return type
79 */
80 49 const QualType &Type::getFunctionReturnType() const {
81
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 49 times.
49 assert(is(TY_FUNCTION));
82
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 49 times.
49 assert(!typeChain.front().paramTypes.empty());
83 49 return typeChain.front().paramTypes.front();
84 }
85
86 /**
87 * Get the param types of a function or procedure type
88 *
89 * @return Function param types
90 */
91 238 QualTypeList Type::getFunctionParamTypes() const {
92
2/4
✓ Branch 2 → 3 taken 238 times.
✗ Branch 2 → 23 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 238 times.
238 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
93
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 238 times.
238 if (typeChain.front().paramTypes.empty())
94 return {};
95
1/2
✓ Branch 18 → 19 taken 238 times.
✗ Branch 18 → 24 not taken.
952 return {typeChain.front().paramTypes.begin() + 1, typeChain.front().paramTypes.end()};
96 }
97
98 /**
99 * Get the param and return types of a function or procedure base type
100 *
101 * @return Function param and return types (first is return type, rest are param types)
102 */
103 3847 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
104
2/4
✓ Branch 3 → 4 taken 3847 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 3847 times.
3847 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
105 3847 return typeChain.front().paramTypes;
106 }
107
108 /**
109 * Check if a function or procedure type has captures
110 *
111 * @return Has captures
112 */
113 239 bool Type::hasLambdaCaptures() const {
114
2/4
✓ Branch 3 → 4 taken 239 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 239 times.
239 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
115 239 return typeChain.front().data.hasCaptures;
116 }
117
118 /**
119 * Retrieve template types of the current type
120 *
121 * @return Vector of template types
122 */
123 1520454 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
124
125 /**
126 * Get the type chain depth of the current type
127 *
128 * @return Type chain depth
129 */
130 size_t Type::getTypeChainDepth() const { return typeChain.size(); }
131
132 /**
133 * Check if the current type is of a certain super type
134 *
135 * @return Applicable or not
136 */
137 26757711 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
138
139 /**
140 * Check if the current type is one of a list of super types
141 *
142 * @return Applicable or not
143 */
144 6973184 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
145 20118479 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
146 }
147
148 /**
149 * Check if the base type of the current type chain is of a certain super type
150 *
151 * @param superType Super type to check for
152 * @return Applicable or not
153 */
154 12549441 bool Type::isBase(SuperType superType) const {
155
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 12549441 times.
12549441 assert(!typeChain.empty());
156 12549441 return typeChain.front().superType == superType;
157 }
158
159 /**
160 * Check if the current type is a primitive type
161 *
162 * @return Primitive type or not
163 */
164
1/2
✓ Branch 2 → 3 taken 324568 times.
✗ Branch 2 → 6 not taken.
324568 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
165
166 /**
167 * Check if the type is an extended primitive type
168 * The definition of extended primitive types contains all primitive types plus the following:
169 * - structs
170 * - interfaces
171 * - functions/procedures
172 *
173 * @return Extended primitive or not
174 */
175
6/8
✓ Branch 2 → 3 taken 241553 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 101436 times.
✓ Branch 3 → 6 taken 140117 times.
✓ Branch 4 → 5 taken 101436 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 77502 times.
✓ Branch 5 → 7 taken 23934 times.
241553 bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); }
176
177 /**
178 * Check if the current type is a pointer type
179 *
180 * @return Pointer type or not
181 */
182 1302547 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
183
184 /**
185 * Check if the current type is a reference type
186 *
187 * @return Reference type or not
188 */
189 2924348 bool Type::isRef() const { return getSuperType() == TY_REF; }
190
191 /**
192 * Check if the current type is an array type
193 *
194 * @return Array type or not
195 */
196 455403 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
197
198 /**
199 * Checks if the base type is generic itself or has generic parts in its template types
200 *
201 * @return Contains generic parts or not
202 */
203 1327851 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
204
1/2
✓ Branch 2 → 3 taken 1327851 times.
✗ Branch 2 → 34 not taken.
1327851 const Type *baseType = getBase();
205
206 // Check if the type itself is generic
207
2/2
✓ Branch 4 → 5 taken 236406 times.
✓ Branch 4 → 6 taken 1091445 times.
1327851 if (baseType->is(TY_GENERIC))
208 236406 return true;
209
210 // Check if the type has generic template types
211
1/2
✓ Branch 7 → 8 taken 1091445 times.
✗ Branch 7 → 34 not taken.
1091445 const auto templateTypes = baseType->getTemplateTypes();
212
3/4
✓ Branch 8 → 9 taken 1091445 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 94760 times.
✓ Branch 9 → 11 taken 996685 times.
1409989 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
213 94760 return true;
214
215 // Check param and return types or functions/procedures
216
3/4
✓ Branch 11 → 12 taken 996685 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 3719 times.
✓ Branch 12 → 24 taken 992966 times.
996685 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
217
2/4
✓ Branch 13 → 14 taken 3719 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 3719 times.
✗ Branch 14 → 31 not taken.
3719 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
218
3/4
✓ Branch 15 → 16 taken 3719 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 233 times.
✓ Branch 16 → 18 taken 3486 times.
10125 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
219 233 return true;
220
2/2
✓ Branch 20 → 21 taken 3486 times.
✓ Branch 20 → 23 taken 233 times.
3719 }
221
222 996452 return false; // Does not have generic parts
223 1091445 }
224
225 /**
226 * Check if the current type is of the same container type like the other type.
227 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
228 *
229 * @param other Other symbol type
230 * @return Same container type or not
231 */
232 309681 bool Type::isSameContainerTypeAs(const Type *other) const {
233
4/4
✓ Branch 3 → 4 taken 8701 times.
✓ Branch 3 → 7 taken 300980 times.
✓ Branch 5 → 6 taken 7984 times.
✓ Branch 5 → 7 taken 717 times.
309681 const bool bothPtr = isPtr() && other->isPtr();
234
4/4
✓ Branch 9 → 10 taken 20602 times.
✓ Branch 9 → 13 taken 289079 times.
✓ Branch 11 → 12 taken 15106 times.
✓ Branch 11 → 13 taken 5496 times.
309681 const bool bothRef = isRef() && other->isRef();
235
3/4
✓ Branch 15 → 16 taken 387 times.
✓ Branch 15 → 19 taken 309294 times.
✓ Branch 17 → 18 taken 387 times.
✗ Branch 17 → 19 not taken.
309681 const bool bothArray = isArray() && other->isArray();
236
6/6
✓ Branch 20 → 21 taken 301697 times.
✓ Branch 20 → 23 taken 7984 times.
✓ Branch 21 → 22 taken 286591 times.
✓ Branch 21 → 23 taken 15106 times.
✓ Branch 22 → 23 taken 387 times.
✓ Branch 22 → 24 taken 286204 times.
309681 return bothPtr || bothRef || bothArray;
237 }
238
239 /**
240 * Check for the matching compatibility of two types.
241 * Useful for struct and function matching as well as assignment type validation and function arg matching.
242 *
243 * @param otherType Type to compare against
244 * @param ignoreArraySize Ignore array sizes
245 * @return Matching or not
246 */
247 367959 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
248 // If the size does not match, it is not equal
249
2/2
✓ Branch 4 → 5 taken 36195 times.
✓ Branch 4 → 6 taken 331764 times.
367959 if (typeChain.size() != otherType->typeChain.size())
250 36195 return false;
251
252 // Compare the elements
253
2/2
✓ Branch 18 → 7 taken 366726 times.
✓ Branch 18 → 19 taken 225949 times.
592675 for (size_t i = 0; i < typeChain.size(); i++) {
254 366726 const TypeChainElement &lhsElement = typeChain.at(i);
255 366726 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
256
257 // Ignore differences in array size
258
5/6
✓ Branch 9 → 10 taken 220252 times.
✓ Branch 9 → 13 taken 146474 times.
✓ Branch 10 → 11 taken 5 times.
✓ Branch 10 → 13 taken 220247 times.
✓ Branch 11 → 12 taken 5 times.
✗ Branch 11 → 13 not taken.
366726 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
259 5 continue;
260
261 // Not both types are arrays -> compare them as usual
262
2/2
✓ Branch 14 → 15 taken 105815 times.
✓ Branch 14 → 16 taken 260906 times.
366721 if (lhsElement != rhsElement)
263 105815 return false;
264 }
265
266 225949 return true;
267 }
268
269 /**
270 * Get the name of the symbol type as a string
271 *
272 * @param name Get name of type
273 * @param withSize Include the array size for sized types
274 * @param ignorePublic Ignore any potential public qualifier
275 * @param withAliases Print aliases as is and not decompose them
276 * @return Symbol type name
277 */
278 2179730 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
279 // Loop through all chain elements
280
2/2
✓ Branch 18 → 4 taken 2822672 times.
✓ Branch 18 → 19 taken 2179730 times.
7182132 for (const TypeChainElement &chainElement : typeChain)
281
2/4
✓ Branch 6 → 7 taken 2822672 times.
✗ Branch 6 → 22 not taken.
✓ Branch 7 → 8 taken 2822672 times.
✗ Branch 7 → 20 not taken.
2822672 name << chainElement.getName(withSize, ignorePublic, withAliases);
282 2179730 }
283
284 /**
285 * Get the name of the symbol type as a string
286 *
287 * @param withSize Include the array size for sized types
288 * @param ignorePublic Ignore any potential public qualifier
289 * @param withAliases Print aliases as is and not decompose them
290 * @return Symbol type name
291 */
292 46051 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
293
1/2
✓ Branch 2 → 3 taken 46051 times.
✗ Branch 2 → 11 not taken.
46051 std::stringstream name;
294
1/2
✓ Branch 3 → 4 taken 46051 times.
✗ Branch 3 → 9 not taken.
46051 getName(name, withSize, ignorePublic, withAliases);
295
1/2
✓ Branch 4 → 5 taken 46051 times.
✗ Branch 4 → 9 not taken.
92102 return name.str();
296 46051 }
297
298 /**
299 * Get the pointer type of the current type as a new type
300 *
301 * @param node AST node for error messages
302 * @return Pointer type of the current type
303 */
304 86997 const Type *Type::toPtr(const ASTNode *node) const {
305
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 12 taken 86995 times.
86997 if (is(TY_DYN))
306
2/4
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 32 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 29 not taken.
6 throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead");
307
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 86995 times.
86995 if (isRef())
308 throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead");
309
310 // Create new type chain
311
1/2
✓ Branch 22 → 23 taken 86995 times.
✗ Branch 22 → 50 not taken.
86995 TypeChain newTypeChain = typeChain;
312
1/2
✓ Branch 23 → 24 taken 86995 times.
✗ Branch 23 → 47 not taken.
86995 newTypeChain.emplace_back(TY_PTR);
313
314 // Register new type or return if already registered
315
1/2
✓ Branch 24 → 25 taken 86995 times.
✗ Branch 24 → 48 not taken.
173990 return TypeRegistry::getOrInsert(newTypeChain);
316 86995 }
317
318 /**
319 * Get the reference type of the current type as a new type
320 *
321 * @param node AST node for error messages
322 * @return Reference type of the current type
323 */
324 41799 const Type *Type::toRef(const ASTNode *node) const {
325
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 41799 times.
41799 if (is(TY_DYN))
326 throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead");
327
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 41799 times.
41799 if (isRef())
328 throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed");
329
330 // Create new type chain
331
1/2
✓ Branch 22 → 23 taken 41799 times.
✗ Branch 22 → 50 not taken.
41799 TypeChain newTypeChain = typeChain;
332
1/2
✓ Branch 23 → 24 taken 41799 times.
✗ Branch 23 → 47 not taken.
41799 newTypeChain.emplace_back(TY_REF);
333
334 // Register new type or return if already registered
335
1/2
✓ Branch 24 → 25 taken 41799 times.
✗ Branch 24 → 48 not taken.
83598 return TypeRegistry::getOrInsert(newTypeChain);
336 41799 }
337
338 /**
339 * Get the array type of the current type as a new type
340 *
341 * @param node AST node for error messages
342 * @param size Size of the array
343 * @param skipDynCheck Skip check if array base type is dyn
344 * @return Array type of the current type
345 */
346 576 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
347
6/6
✓ Branch 2 → 3 taken 252 times.
✓ Branch 2 → 6 taken 324 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 251 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 16 taken 575 times.
576 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
348
2/4
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 23 not taken.
3 throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead");
349
350 // Create new type chain
351
1/2
✓ Branch 16 → 17 taken 575 times.
✗ Branch 16 → 36 not taken.
575 TypeChain newTypeChain = typeChain;
352
1/2
✓ Branch 17 → 18 taken 575 times.
✗ Branch 17 → 32 not taken.
575 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
353
354 // Register new type or return if already registered
355
1/2
✓ Branch 18 → 19 taken 575 times.
✗ Branch 18 → 34 not taken.
1150 return TypeRegistry::getOrInsert(newTypeChain);
356 575 }
357
358 /**
359 * Retrieve the base type of an array or a pointer
360 *
361 * @return Base type
362 */
363 443847 const Type *Type::getContained() const {
364
2/2
✓ Branch 3 → 4 taken 2536 times.
✓ Branch 3 → 6 taken 441311 times.
443847 if (is(TY_STRING))
365
1/2
✓ Branch 4 → 5 taken 2536 times.
✗ Branch 4 → 18 not taken.
2536 return TypeRegistry::getOrInsert(TY_CHAR);
366
367 // Create new type chain
368
1/2
✓ Branch 6 → 7 taken 441311 times.
✗ Branch 6 → 18 not taken.
441311 TypeChain newTypeChain = typeChain;
369
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 441311 times.
441311 assert(newTypeChain.size() > 1);
370 441311 newTypeChain.pop_back();
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 11 → 12 taken 441311 times.
✗ Branch 11 → 16 not taken.
441311 return TypeRegistry::getOrInsert(newTypeChain);
374 441311 }
375
376 /**
377 * Replace the base type with another one
378 *
379 * @param newBaseType New base type
380 * @return The new type
381 */
382 72017 const Type *Type::replaceBase(const Type *newBaseType) const {
383
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 72017 times.
72017 assert(!typeChain.empty());
384
385 // Create new type
386
1/2
✓ Branch 5 → 6 taken 72017 times.
✗ Branch 5 → 27 not taken.
72017 TypeChain newTypeChain = newBaseType->typeChain;
387
4/4
✓ Branch 7 → 8 taken 4064 times.
✓ Branch 7 → 11 taken 67953 times.
✓ Branch 9 → 10 taken 59 times.
✓ Branch 9 → 11 taken 4005 times.
72017 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
388
2/2
✓ Branch 19 → 13 taken 9042 times.
✓ Branch 19 → 20 taken 72017 times.
81059 for (size_t i = 1; i < typeChain.size(); i++)
389
3/4
✓ Branch 13 → 14 taken 59 times.
✓ Branch 13 → 15 taken 8983 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 59 times.
9042 if (!doubleRef || i > 1)
390
2/4
✓ Branch 15 → 16 taken 8983 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 8983 times.
✗ Branch 16 → 25 not taken.
8983 newTypeChain.push_back(typeChain.at(i));
391
392 // Register new type or return if already registered
393
1/2
✓ Branch 20 → 21 taken 72017 times.
✗ Branch 20 → 25 not taken.
144034 return TypeRegistry::getOrInsert(newTypeChain);
394 72017 }
395
396 /**
397 * Remove reference wrapper from the current type
398 *
399 * @return Type without reference wrapper
400 */
401
1/2
✓ Branch 3 → 4 taken 106965 times.
✗ Branch 3 → 6 not taken.
106965 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
402
403 /**
404 * Retrieve the base type of the current type
405 *
406 * @return Base type
407 */
408 6314138 const Type *Type::getBase() const {
409
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6314138 times.
6314138 assert(!typeChain.empty());
410
411 // Create new type chain
412
3/6
✓ Branch 9 → 10 taken 6314138 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 6314138 times.
✓ Branch 12 → 14 taken 6314138 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
18942414 const TypeChain newTypeChain = {typeChain.front()};
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 14 → 15 taken 6314138 times.
✗ Branch 14 → 32 not taken.
12628276 return TypeRegistry::getOrInsert(newTypeChain);
416
1/6
✓ Branch 6 → 7 taken 6314138 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.
12628276 }
417
418 /**
419 * Retrieve the same type, but with lambda captures
420 *
421 * @return Type with lambda captures
422 */
423 81 const Type *Type::getWithLambdaCaptures(bool enabled) const {
424
3/6
✓ Branch 2 → 3 taken 81 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 81 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 81 times.
81 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
425
426 // Create new type chain
427
1/2
✓ Branch 6 → 7 taken 81 times.
✗ Branch 6 → 16 not taken.
81 TypeChain newTypeChain = typeChain;
428 81 newTypeChain.front().data.hasCaptures = enabled;
429
430 // Register new type or return if already registered
431
1/2
✓ Branch 8 → 9 taken 81 times.
✗ Branch 8 → 14 not taken.
162 return TypeRegistry::getOrInsert(newTypeChain);
432 81 }
433
434 /**
435 * Retrieve the same type, but with the body scope removed
436 *
437 * @return Type with body scope removed
438 */
439 100462 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
440
3/6
✓ Branch 2 → 3 taken 100462 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 100462 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 100462 times.
100462 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
441
442 // Create new type chain
443
1/2
✓ Branch 6 → 7 taken 100462 times.
✗ Branch 6 → 16 not taken.
100462 TypeChain newTypeChain = typeChain;
444 100462 newTypeChain.front().data.bodyScope = bodyScope;
445
446 // Register new type or return if already registered
447
1/2
✓ Branch 8 → 9 taken 100462 times.
✗ Branch 8 → 14 not taken.
200924 return TypeRegistry::getOrInsert(newTypeChain);
448 100462 }
449
450 /**
451 * Retrieve the same type, but with the given template types
452 *
453 * @return Type with new template types
454 */
455 15324 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
456
2/4
✓ Branch 2 → 3 taken 15324 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 15324 times.
15324 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
457 15324 return getWithBaseTemplateTypes(templateTypes);
458 }
459
460 /**
461 * Retrieve the same type, but with the given base template types
462 *
463 * @return Type with new base template types
464 */
465 37735 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
466
3/6
✓ Branch 2 → 3 taken 37735 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 37735 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 37735 times.
37735 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
467
468 // Create new type chain
469
1/2
✓ Branch 6 → 7 taken 37735 times.
✗ Branch 6 → 17 not taken.
37735 TypeChain newTypeChain = typeChain;
470
1/2
✓ Branch 8 → 9 taken 37735 times.
✗ Branch 8 → 15 not taken.
37735 newTypeChain.front().templateTypes = templateTypes;
471
472 // Register new type or return if already registered
473
1/2
✓ Branch 9 → 10 taken 37735 times.
✗ Branch 9 → 15 not taken.
75470 return TypeRegistry::getOrInsert(newTypeChain);
474 37735 }
475
476 /**
477 * Retrieve the same type, but with the param and return types removed
478 *
479 * @return Type with param and return types removed
480 */
481 33645 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
482
3/6
✓ Branch 2 → 3 taken 33645 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 33645 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 33645 times.
33645 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
483
484 // Create new type chain
485
1/2
✓ Branch 6 → 7 taken 33645 times.
✗ Branch 6 → 17 not taken.
33645 TypeChain newTypeChain = typeChain;
486
1/2
✓ Branch 8 → 9 taken 33645 times.
✗ Branch 8 → 15 not taken.
33645 newTypeChain.front().paramTypes = paramAndReturnTypes;
487
488 // Register new type or return if already registered
489
1/2
✓ Branch 9 → 10 taken 33645 times.
✗ Branch 9 → 15 not taken.
67290 return TypeRegistry::getOrInsert(newTypeChain);
490 33645 }
491
492 /**
493 * Return the LLVM type for this symbol type
494 *
495 * @param sourceFile Referenced source file
496 * @return Corresponding LLVM type
497 */
498 30695 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
499
2/4
✓ Branch 3 → 4 taken 30695 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 30695 times.
✗ Branch 5 → 7 not taken.
30695 assert(!typeChain.empty() && !is(TY_INVALID));
500
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 30693 times.
30695 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
501
502
10/12
✓ Branch 11 → 12 taken 30695 times.
✗ Branch 11 → 166 not taken.
✓ Branch 12 → 13 taken 15161 times.
✓ Branch 12 → 17 taken 15534 times.
✓ Branch 14 → 15 taken 187 times.
✓ Branch 14 → 18 taken 14974 times.
✓ Branch 15 → 16 taken 187 times.
✗ Branch 15 → 166 not taken.
✓ Branch 16 → 17 taken 59 times.
✓ Branch 16 → 18 taken 128 times.
✓ Branch 19 → 20 taken 15593 times.
✓ Branch 19 → 22 taken 15102 times.
30695 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
503 15593 return llvm::PointerType::get(context, 0);
504
505
2/2
✓ Branch 23 → 24 taken 128 times.
✓ Branch 23 → 32 taken 14974 times.
15102 if (isArray()) {
506
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 128 times.
128 assert(getArraySize() > 0);
507 128 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
508 128 return llvm::ArrayType::get(containedType, getArraySize());
509 }
510
511
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 14974 times.
14974 assert(!hasAnyGenericParts());
512
513
2/2
✓ Branch 36 → 37 taken 183 times.
✓ Branch 36 → 39 taken 14791 times.
14974 if (is(TY_DOUBLE))
514 183 return llvm::Type::getDoubleTy(context);
515
516
3/4
✓ Branch 39 → 40 taken 14791 times.
✗ Branch 39 → 167 not taken.
✓ Branch 40 → 41 taken 1445 times.
✓ Branch 40 → 43 taken 13346 times.
14791 if (isOneOf({TY_INT, TY_ENUM}))
517 1445 return llvm::Type::getInt32Ty(context);
518
519
2/2
✓ Branch 44 → 45 taken 143 times.
✓ Branch 44 → 47 taken 13203 times.
13346 if (is(TY_SHORT))
520 143 return llvm::Type::getInt16Ty(context);
521
522
2/2
✓ Branch 48 → 49 taken 1051 times.
✓ Branch 48 → 51 taken 12152 times.
13203 if (is(TY_LONG))
523 1051 return llvm::Type::getInt64Ty(context);
524
525
3/4
✓ Branch 51 → 52 taken 12152 times.
✗ Branch 51 → 168 not taken.
✓ Branch 52 → 53 taken 889 times.
✓ Branch 52 → 55 taken 11263 times.
12152 if (isOneOf({TY_CHAR, TY_BYTE}))
526 889 return llvm::Type::getInt8Ty(context);
527
528
2/2
✓ Branch 56 → 57 taken 1129 times.
✓ Branch 56 → 59 taken 10134 times.
11263 if (is(TY_BOOL))
529 1129 return llvm::Type::getInt1Ty(context);
530
531
3/4
✓ Branch 59 → 60 taken 10134 times.
✗ Branch 59 → 169 not taken.
✓ Branch 60 → 61 taken 9946 times.
✓ Branch 60 → 150 taken 188 times.
10134 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
532
1/2
✓ Branch 61 → 62 taken 9946 times.
✗ Branch 61 → 198 not taken.
9946 const Scope *structBodyScope = getBodyScope();
533
2/4
✓ Branch 63 → 64 taken 9946 times.
✗ Branch 63 → 198 not taken.
✓ Branch 64 → 65 taken 9946 times.
✗ Branch 64 → 198 not taken.
9946 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
534
1/2
✓ Branch 65 → 66 taken 9946 times.
✗ Branch 65 → 196 not taken.
9946 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
535
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 9946 times.
9946 assert(structSymbol != nullptr);
536
537 // Collect concrete field types
538 9946 std::string mangledName;
539 9946 std::vector<llvm::Type *> fieldTypes;
540 9946 bool isPacked = false;
541
2/2
✓ Branch 72 → 73 taken 8787 times.
✓ Branch 72 → 132 taken 1159 times.
9946 if (is(TY_STRUCT)) { // Struct
542
2/4
✓ Branch 73 → 74 taken 8787 times.
✗ Branch 73 → 192 not taken.
✓ Branch 74 → 75 taken 8787 times.
✗ Branch 74 → 192 not taken.
8787 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
543
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 8787 times.
8787 assert(spiceStruct != nullptr);
544
1/2
✓ Branch 77 → 78 taken 8787 times.
✗ Branch 77 → 170 not taken.
8787 mangledName = NameMangling::mangleStruct(*spiceStruct);
545
546
1/2
✓ Branch 80 → 81 taken 8787 times.
✗ Branch 80 → 192 not taken.
8787 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
547
1/2
✓ Branch 81 → 82 taken 8787 times.
✗ Branch 81 → 192 not taken.
8787 fieldTypes.reserve(totalFieldCount);
548
549 // If the struct has no interface types, but a vtable was requested, add another ptr field type
550
2/4
✓ Branch 82 → 83 taken 8787 times.
✗ Branch 82 → 192 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 8787 times.
8787 assert(structSymbol->declNode->isStructDef());
551
1/2
✓ Branch 85 → 86 taken 8787 times.
✗ Branch 85 → 87 not taken.
8787 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
552
4/4
✓ Branch 92 → 93 taken 6353 times.
✓ Branch 92 → 97 taken 2434 times.
✓ Branch 93 → 94 taken 88 times.
✓ Branch 93 → 97 taken 6265 times.
8787 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
553
2/4
✓ Branch 94 → 95 taken 88 times.
✗ Branch 94 → 171 not taken.
✓ Branch 95 → 96 taken 88 times.
✗ Branch 95 → 171 not taken.
88 fieldTypes.push_back(llvm::PointerType::get(context, 0));
554
555 // Collect all field types
556
2/2
✓ Branch 110 → 98 taken 22846 times.
✓ Branch 110 → 111 taken 8787 times.
31633 for (size_t i = 0; i < totalFieldCount; i++) {
557
1/2
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 100 taken 22846 times.
22846 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
558
1/2
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 22846 times.
22846 assert(fieldSymbol != nullptr);
559
3/6
✓ Branch 105 → 106 taken 22846 times.
✗ Branch 105 → 172 not taken.
✓ Branch 107 → 108 taken 22846 times.
✗ Branch 107 → 172 not taken.
✓ Branch 108 → 109 taken 22846 times.
✗ Branch 108 → 172 not taken.
22846 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
560 }
561
562 // Check if the struct is declared as packed
563
12/18
✓ Branch 111 → 112 taken 89 times.
✓ Branch 111 → 118 taken 8698 times.
✓ Branch 114 → 115 taken 89 times.
✗ Branch 114 → 173 not taken.
✓ Branch 115 → 116 taken 89 times.
✗ Branch 115 → 173 not taken.
✓ Branch 116 → 117 taken 1 time.
✓ Branch 116 → 118 taken 88 times.
✓ Branch 119 → 120 taken 89 times.
✓ Branch 119 → 121 taken 8698 times.
✓ Branch 121 → 122 taken 89 times.
✓ Branch 121 → 124 taken 8698 times.
✓ Branch 124 → 125 taken 1 time.
✓ Branch 124 → 142 taken 8786 times.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 175 not taken.
✗ Branch 177 → 178 not taken.
✗ Branch 177 → 180 not taken.
8965 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
564
2/4
✓ Branch 127 → 128 taken 1 time.
✗ Branch 127 → 184 not taken.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 182 not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
565 } else { // Interface
566
2/4
✓ Branch 132 → 133 taken 1159 times.
✗ Branch 132 → 192 not taken.
✓ Branch 133 → 134 taken 1159 times.
✗ Branch 133 → 192 not taken.
1159 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
567
1/2
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 1159 times.
1159 assert(spiceInterface != nullptr);
568
1/2
✓ Branch 136 → 137 taken 1159 times.
✗ Branch 136 → 188 not taken.
1159 mangledName = NameMangling::mangleInterface(*spiceInterface);
569
570 // vtable pointer
571
2/4
✓ Branch 139 → 140 taken 1159 times.
✗ Branch 139 → 189 not taken.
✓ Branch 140 → 141 taken 1159 times.
✗ Branch 140 → 189 not taken.
1159 fieldTypes.push_back(llvm::PointerType::get(context, 0));
572 }
573
574
1/2
✓ Branch 144 → 145 taken 9946 times.
✗ Branch 144 → 190 not taken.
9946 return llvm::StructType::create(context, fieldTypes, mangledName, isPacked);
575 9946 }
576
577
2/4
✓ Branch 150 → 151 taken 188 times.
✗ Branch 150 → 199 not taken.
✓ Branch 151 → 152 taken 188 times.
✗ Branch 151 → 158 not taken.
188 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
578 // Lambda/function values are represented as a fat pointer with three slots:
579 // { fctPtr, capturePtr, captureSize }. The capture size (in bytes) travels with
580 // the value so that the std Lambda type can take ownership of the captures on the
581 // heap regardless of where the lambda came from. It is 0 if there is no owned
582 // capture struct (no captures, or a single capture stored inline in capturePtr).
583 188 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
584 188 llvm::IntegerType *int64Ty = llvm::Type::getInt64Ty(context);
585
1/2
✓ Branch 155 → 156 taken 188 times.
✗ Branch 155 → 200 not taken.
188 return llvm::StructType::get(context, {ptrTy, ptrTy, int64Ty});
586 }
587
588 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
589 }
590
591 /**
592 * Remove pointers / arrays / references if both types have them as far as possible.
593 *
594 * @param typeA Candidate type
595 * @param typeB Requested type
596 */
597 280248 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
598 // Unwrap both types as far as possible
599
2/2
✓ Branch 7 → 3 taken 22178 times.
✓ Branch 7 → 8 taken 280248 times.
302426 while (typeA->isSameContainerTypeAs(typeB)) {
600 22178 typeB = typeB->getContained();
601 22178 typeA = typeA->getContained();
602 }
603 280248 }
604
605 /**
606 * Remove pointers / arrays / references if both types have them as far as possible.
607 * Furthermore, remove reference wrappers if possible.
608 *
609 * @param typeA Candidate type
610 * @param typeB Requested type
611 */
612 274615 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
613 // Remove reference wrapper of front type if required
614
6/6
✓ Branch 3 → 4 taken 114126 times.
✓ Branch 3 → 7 taken 160489 times.
✓ Branch 5 → 6 taken 99045 times.
✓ Branch 5 → 7 taken 15081 times.
✓ Branch 8 → 9 taken 99045 times.
✓ Branch 8 → 11 taken 175570 times.
274615 if (typeA->isRef() && !typeB->isRef())
615 99045 typeA = typeA->removeReferenceWrapper();
616
617 // Remove reference wrapper of requested type if required
618
8/8
✓ Branch 12 → 13 taken 259534 times.
✓ Branch 12 → 18 taken 15081 times.
✓ Branch 14 → 15 taken 10107 times.
✓ Branch 14 → 18 taken 249427 times.
✓ Branch 16 → 17 taken 7920 times.
✓ Branch 16 → 18 taken 2187 times.
✓ Branch 19 → 20 taken 7920 times.
✓ Branch 19 → 22 taken 266695 times.
274615 if (!typeA->isRef() && typeB->isRef() && !typeA->isBase(TY_GENERIC))
619 7920 typeB = typeB->removeReferenceWrapper();
620
621 // Unwrap both types as far as possible
622 274615 unwrapBoth(typeA, typeB);
623 274615 }
624
625 /**
626 * Check if two types have the same type chain depth
627 *
628 * @param typeA First type
629 * @param typeB Second type
630 * @return Same depth or not
631 */
632 45380 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
633 45380 return typeA->typeChain.size() == typeB->typeChain.size();
634 }
635
636 } // namespace spice::compiler
637