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 10087506 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 10087506 times.
✓ Branch 7 → 9 taken 10087506 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.
|
30262518 | Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {} |
| 26 | |||
| 27 |
4/12✓ Branch 4 → 5 taken 12457 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 12457 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 12457 times.
✓ Branch 8 → 10 taken 12457 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.
|
37371 | Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {} |
| 28 | |||
| 29 | 14309 | 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 14309 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 14309 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 14309 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 14309 times.
✓ Branch 9 → 11 taken 14309 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.
|
42927 | : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {} |
| 32 | |||
| 33 | 42241116 | 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 | 105934167 | SuperType Type::getSuperType() const { | |
| 41 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 105934167 times.
|
105934167 | assert(!typeChain.empty()); |
| 42 | 105934167 | return typeChain.back().superType; | |
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 46 | * Get the sub type of the current type | ||
| 47 | * | ||
| 48 | * @return Sub type | ||
| 49 | */ | ||
| 50 | 2377177 | const std::string &Type::getSubType() const { | |
| 51 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2377177 times.
|
2377177 | assert(!typeChain.empty()); |
| 52 |
2/4✓ Branch 5 → 6 taken 2377177 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2377177 times.
|
2377177 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION, TY_ENUM, TY_GENERIC})); |
| 53 | 2377177 | return typeChain.back().subType; | |
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Get the array size of the current type | ||
| 58 | * | ||
| 59 | * @return Array size | ||
| 60 | */ | ||
| 61 | 12220 | unsigned int Type::getArraySize() const { | |
| 62 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 12220 times.
|
12220 | assert(isArray()); |
| 63 | 12220 | return typeChain.back().data.arraySize; | |
| 64 | } | ||
| 65 | |||
| 66 | /** | ||
| 67 | * Get the body scope of the current type | ||
| 68 | * | ||
| 69 | * @return Body scope | ||
| 70 | */ | ||
| 71 | 8740470 | Scope *Type::getBodyScope() const { | |
| 72 |
2/4✓ Branch 2 → 3 taken 8740470 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8740470 times.
|
8740470 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION})); |
| 73 | 8740470 | 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 | 11094 | const QualTypeList &Type::getFunctionParamAndReturnTypes() const { | |
| 105 |
2/4✓ Branch 3 → 4 taken 11094 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 11094 times.
|
11094 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 106 | 11094 | 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 | 4126847 | 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 | 81470359 | 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 | 22165352 | bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const { | |
| 146 | 63734253 | 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 | 41469105 | bool Type::isBase(SuperType superType) const { | |
| 156 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 41469105 times.
|
41469105 | assert(!typeChain.empty()); |
| 157 | 41469105 | 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 1129782 times.
✗ Branch 2 → 6 not taken.
|
1129782 | 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 | 863405 | bool Type::isExtendedPrimitive() const { | |
| 177 |
6/8✓ Branch 2 → 3 taken 863405 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 321634 times.
✓ Branch 3 → 6 taken 541771 times.
✓ Branch 4 → 5 taken 321634 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 243673 times.
✓ Branch 5 → 7 taken 77961 times.
|
863405 | 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 | 4082767 | 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 | 8795544 | 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 | 2356325 | 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 | 3397367 | bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion) | |
| 207 |
1/2✓ Branch 2 → 3 taken 3397367 times.
✗ Branch 2 → 34 not taken.
|
3397367 | const Type *baseType = getBase(); |
| 208 | |||
| 209 | // Check if the type itself is generic | ||
| 210 |
2/2✓ Branch 4 → 5 taken 549569 times.
✓ Branch 4 → 6 taken 2847798 times.
|
3397367 | if (baseType->is(TY_GENERIC)) |
| 211 | 549569 | return true; | |
| 212 | |||
| 213 | // Check if the type has generic template types | ||
| 214 |
1/2✓ Branch 7 → 8 taken 2847798 times.
✗ Branch 7 → 34 not taken.
|
2847798 | const auto templateTypes = baseType->getTemplateTypes(); |
| 215 |
3/4✓ Branch 8 → 9 taken 2847798 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 234881 times.
✓ Branch 9 → 11 taken 2612917 times.
|
3488344 | if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
| 216 | 234881 | return true; | |
| 217 | |||
| 218 | // Check param and return types or functions/procedures | ||
| 219 |
3/4✓ Branch 11 → 12 taken 2612917 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 10265 times.
✓ Branch 12 → 24 taken 2602652 times.
|
2612917 | 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 | 2612471 | return false; // Does not have generic parts | |
| 226 | 2847798 | } | |
| 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 | 891429 | bool Type::isSameContainerTypeAs(const Type *other) const { | |
| 236 |
4/4✓ Branch 3 → 4 taken 31372 times.
✓ Branch 3 → 7 taken 860057 times.
✓ Branch 5 → 6 taken 28861 times.
✓ Branch 5 → 7 taken 2511 times.
|
891429 | const bool bothPtr = isPtr() && other->isPtr(); |
| 237 |
4/4✓ Branch 9 → 10 taken 56415 times.
✓ Branch 9 → 13 taken 835014 times.
✓ Branch 11 → 12 taken 42081 times.
✓ Branch 11 → 13 taken 14334 times.
|
891429 | const bool bothRef = isRef() && other->isRef(); |
| 238 |
3/4✓ Branch 15 → 16 taken 856 times.
✓ Branch 15 → 19 taken 890573 times.
✓ Branch 17 → 18 taken 856 times.
✗ Branch 17 → 19 not taken.
|
891429 | const bool bothArray = isArray() && other->isArray(); |
| 239 |
6/6✓ Branch 20 → 21 taken 862568 times.
✓ Branch 20 → 23 taken 28861 times.
✓ Branch 21 → 22 taken 820487 times.
✓ Branch 21 → 23 taken 42081 times.
✓ Branch 22 → 23 taken 856 times.
✓ Branch 22 → 24 taken 819631 times.
|
891429 | 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 | 1028944 | 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 121338 times.
✓ Branch 4 → 6 taken 907606 times.
|
1028944 | if (typeChain.size() != otherType->typeChain.size()) |
| 253 | 121338 | return false; | |
| 254 | |||
| 255 | // Compare the elements | ||
| 256 |
2/2✓ Branch 18 → 7 taken 1009736 times.
✓ Branch 18 → 19 taken 609912 times.
|
1619648 | for (size_t i = 0; i < typeChain.size(); i++) { |
| 257 | 1009736 | const TypeChainElement &lhsElement = typeChain.at(i); | |
| 258 | 1009736 | const TypeChainElement &rhsElement = otherType->typeChain.at(i); | |
| 259 | |||
| 260 | // Ignore differences in array size | ||
| 261 |
5/6✓ Branch 9 → 10 taken 612501 times.
✓ Branch 9 → 13 taken 397235 times.
✓ Branch 10 → 11 taken 10 times.
✓ Branch 10 → 13 taken 612491 times.
✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 13 not taken.
|
1009736 | 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 297694 times.
✓ Branch 14 → 16 taken 712032 times.
|
1009726 | if (lhsElement != rhsElement) |
| 266 | 297694 | return false; | |
| 267 | } | ||
| 268 | |||
| 269 | 609912 | 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 | 5494972 | 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 7208570 times.
✓ Branch 18 → 19 taken 5494972 times.
|
18198514 | for (const TypeChainElement &chainElement : typeChain) |
| 284 |
2/4✓ Branch 6 → 7 taken 7208570 times.
✗ Branch 6 → 22 not taken.
✓ Branch 7 → 8 taken 7208570 times.
✗ Branch 7 → 20 not taken.
|
7208570 | name << chainElement.getName(withSize, ignorePublic, withAliases); |
| 285 | 5494972 | } | |
| 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 | 119301 | std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const { | |
| 296 |
1/2✓ Branch 2 → 3 taken 119301 times.
✗ Branch 2 → 11 not taken.
|
119301 | std::stringstream name; |
| 297 |
1/2✓ Branch 3 → 4 taken 119301 times.
✗ Branch 3 → 9 not taken.
|
119301 | getName(name, withSize, ignorePublic, withAliases); |
| 298 |
1/2✓ Branch 4 → 5 taken 119301 times.
✗ Branch 4 → 9 not taken.
|
238602 | return name.str(); |
| 299 | 119301 | } | |
| 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 | 247475 | const Type *Type::toPtr(const ASTNode *node) const { | |
| 308 |
2/2✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 12 taken 247471 times.
|
247475 | 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 247471 times.
|
247471 | 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 247471 times.
✗ Branch 22 → 50 not taken.
|
247471 | TypeChain newTypeChain = typeChain; |
| 315 |
1/2✓ Branch 23 → 24 taken 247471 times.
✗ Branch 23 → 47 not taken.
|
247471 | newTypeChain.emplace_back(TY_PTR); |
| 316 | |||
| 317 | // Register new type or return if already registered | ||
| 318 |
1/2✓ Branch 24 → 25 taken 247471 times.
✗ Branch 24 → 48 not taken.
|
494942 | return TypeRegistry::getOrInsert(newTypeChain); |
| 319 | 247471 | } | |
| 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 | 115401 | const Type *Type::toRef(const ASTNode *node) const { | |
| 328 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 115401 times.
|
115401 | 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 115401 times.
|
115401 | 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 115401 times.
✗ Branch 22 → 50 not taken.
|
115401 | TypeChain newTypeChain = typeChain; |
| 335 |
1/2✓ Branch 23 → 24 taken 115401 times.
✗ Branch 23 → 47 not taken.
|
115401 | newTypeChain.emplace_back(TY_REF); |
| 336 | |||
| 337 | // Register new type or return if already registered | ||
| 338 |
1/2✓ Branch 24 → 25 taken 115401 times.
✗ Branch 24 → 48 not taken.
|
230802 | return TypeRegistry::getOrInsert(newTypeChain); |
| 339 | 115401 | } | |
| 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 | 1889 | const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const { | |
| 350 |
6/6✓ Branch 2 → 3 taken 1221 times.
✓ Branch 2 → 6 taken 668 times.
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 1219 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 16 taken 1887 times.
|
1889 | 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 1887 times.
✗ Branch 16 → 36 not taken.
|
1887 | TypeChain newTypeChain = typeChain; |
| 355 |
1/2✓ Branch 17 → 18 taken 1887 times.
✗ Branch 17 → 32 not taken.
|
1887 | 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 1887 times.
✗ Branch 18 → 34 not taken.
|
3774 | return TypeRegistry::getOrInsert(newTypeChain); |
| 359 | 1887 | } | |
| 360 | |||
| 361 | /** | ||
| 362 | * Retrieve the base type of an array or a pointer | ||
| 363 | * | ||
| 364 | * @return Base type | ||
| 365 | */ | ||
| 366 | 1442256 | const Type *Type::getContained() const { | |
| 367 |
2/2✓ Branch 3 → 4 taken 3456 times.
✓ Branch 3 → 6 taken 1438800 times.
|
1442256 | if (is(TY_STRING)) |
| 368 |
1/2✓ Branch 4 → 5 taken 3456 times.
✗ Branch 4 → 18 not taken.
|
3456 | return TypeRegistry::getOrInsert(TY_CHAR); |
| 369 | |||
| 370 | // Create new type chain | ||
| 371 |
1/2✓ Branch 6 → 7 taken 1438800 times.
✗ Branch 6 → 18 not taken.
|
1438800 | TypeChain newTypeChain = typeChain; |
| 372 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1438800 times.
|
1438800 | assert(newTypeChain.size() > 1); |
| 373 | 1438800 | newTypeChain.pop_back(); | |
| 374 | |||
| 375 | // Register new type or return if already registered | ||
| 376 |
1/2✓ Branch 11 → 12 taken 1438800 times.
✗ Branch 11 → 16 not taken.
|
1438800 | return TypeRegistry::getOrInsert(newTypeChain); |
| 377 | 1438800 | } | |
| 378 | |||
| 379 | /** | ||
| 380 | * Replace the base type with another one | ||
| 381 | * | ||
| 382 | * @param newBaseType New base type | ||
| 383 | * @return The new type | ||
| 384 | */ | ||
| 385 | 156928 | const Type *Type::replaceBase(const Type *newBaseType) const { | |
| 386 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 156928 times.
|
156928 | assert(!typeChain.empty()); |
| 387 | |||
| 388 | // Create new type | ||
| 389 |
1/2✓ Branch 5 → 6 taken 156928 times.
✗ Branch 5 → 27 not taken.
|
156928 | TypeChain newTypeChain = newBaseType->typeChain; |
| 390 |
4/4✓ Branch 7 → 8 taken 7336 times.
✓ Branch 7 → 11 taken 149592 times.
✓ Branch 9 → 10 taken 144 times.
✓ Branch 9 → 11 taken 7192 times.
|
156928 | const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF; |
| 391 |
2/2✓ Branch 19 → 13 taken 19929 times.
✓ Branch 19 → 20 taken 156928 times.
|
176857 | for (size_t i = 1; i < typeChain.size(); i++) |
| 392 |
3/4✓ Branch 13 → 14 taken 144 times.
✓ Branch 13 → 15 taken 19785 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 144 times.
|
19929 | if (!doubleRef || i > 1) |
| 393 |
2/4✓ Branch 15 → 16 taken 19785 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 19785 times.
✗ Branch 16 → 25 not taken.
|
19785 | newTypeChain.push_back(typeChain.at(i)); |
| 394 | |||
| 395 | // Register new type or return if already registered | ||
| 396 |
1/2✓ Branch 20 → 21 taken 156928 times.
✗ Branch 20 → 25 not taken.
|
313856 | return TypeRegistry::getOrInsert(newTypeChain); |
| 397 | 156928 | } | |
| 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 341560 times.
✗ Branch 3 → 6 not taken.
|
341560 | 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 | 18721837 | const Type *Type::getBase() const { | |
| 412 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 18721837 times.
|
18721837 | assert(!typeChain.empty()); |
| 413 | |||
| 414 | // Create new type chain | ||
| 415 |
3/6✓ Branch 9 → 10 taken 18721837 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 18721837 times.
✓ Branch 12 → 14 taken 18721837 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
|
56165511 | const TypeChain newTypeChain = {typeChain.front()}; |
| 416 | |||
| 417 | // Register new type or return if already registered | ||
| 418 |
1/2✓ Branch 14 → 15 taken 18721837 times.
✗ Branch 14 → 32 not taken.
|
37443674 | return TypeRegistry::getOrInsert(newTypeChain); |
| 419 |
1/6✓ Branch 6 → 7 taken 18721837 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.
|
37443674 | } |
| 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 | 257474 | const Type *Type::getWithBodyScope(Scope *bodyScope) const { | |
| 443 |
3/6✓ Branch 2 → 3 taken 257474 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 257474 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 257474 times.
|
257474 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION})); |
| 444 | |||
| 445 | // Create new type chain | ||
| 446 |
1/2✓ Branch 6 → 7 taken 257474 times.
✗ Branch 6 → 16 not taken.
|
257474 | TypeChain newTypeChain = typeChain; |
| 447 | 257474 | newTypeChain.front().data.bodyScope = bodyScope; | |
| 448 | |||
| 449 | // Register new type or return if already registered | ||
| 450 |
1/2✓ Branch 8 → 9 taken 257474 times.
✗ Branch 8 → 14 not taken.
|
514948 | return TypeRegistry::getOrInsert(newTypeChain); |
| 451 | 257474 | } | |
| 452 | |||
| 453 | /** | ||
| 454 | * Retrieve the same type, but with the given template types | ||
| 455 | * | ||
| 456 | * @return Type with new template types | ||
| 457 | */ | ||
| 458 | 36739 | const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const { | |
| 459 |
2/4✓ Branch 2 → 3 taken 36739 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 36739 times.
|
36739 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION})); |
| 460 | 36739 | 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 | 84716 | const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const { | |
| 469 |
3/6✓ Branch 2 → 3 taken 84716 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 84716 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 84716 times.
|
84716 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE, TY_UNION})); |
| 470 | |||
| 471 | // Create new type chain | ||
| 472 |
1/2✓ Branch 6 → 7 taken 84716 times.
✗ Branch 6 → 17 not taken.
|
84716 | TypeChain newTypeChain = typeChain; |
| 473 |
1/2✓ Branch 8 → 9 taken 84716 times.
✗ Branch 8 → 15 not taken.
|
84716 | newTypeChain.front().templateTypes = templateTypes; |
| 474 | |||
| 475 | // Register new type or return if already registered | ||
| 476 |
1/2✓ Branch 9 → 10 taken 84716 times.
✗ Branch 9 → 15 not taken.
|
169432 | return TypeRegistry::getOrInsert(newTypeChain); |
| 477 | 84716 | } | |
| 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 | 95765 | const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList ¶mAndReturnTypes) const { | |
| 485 |
3/6✓ Branch 2 → 3 taken 95765 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 95765 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 95765 times.
|
95765 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 486 | |||
| 487 | // Create new type chain | ||
| 488 |
1/2✓ Branch 6 → 7 taken 95765 times.
✗ Branch 6 → 17 not taken.
|
95765 | TypeChain newTypeChain = typeChain; |
| 489 |
1/2✓ Branch 8 → 9 taken 95765 times.
✗ Branch 8 → 15 not taken.
|
95765 | newTypeChain.front().paramTypes = paramAndReturnTypes; |
| 490 | |||
| 491 | // Register new type or return if already registered | ||
| 492 |
1/2✓ Branch 9 → 10 taken 95765 times.
✗ Branch 9 → 15 not taken.
|
191530 | return TypeRegistry::getOrInsert(newTypeChain); |
| 493 | 95765 | } | |
| 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 | 82721 | llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion) | |
| 502 |
2/4✓ Branch 3 → 4 taken 82721 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 82721 times.
✗ Branch 5 → 7 not taken.
|
82721 | assert(!typeChain.empty() && !is(TY_INVALID)); |
| 503 |
2/2✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 82719 times.
|
82721 | llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context; |
| 504 | |||
| 505 |
10/12✓ Branch 11 → 12 taken 82721 times.
✗ Branch 11 → 222 not taken.
✓ Branch 12 → 13 taken 41596 times.
✓ Branch 12 → 17 taken 41125 times.
✓ Branch 14 → 15 taken 1029 times.
✓ Branch 14 → 18 taken 40567 times.
✓ Branch 15 → 16 taken 1029 times.
✗ Branch 15 → 222 not taken.
✓ Branch 16 → 17 taken 142 times.
✓ Branch 16 → 18 taken 887 times.
✓ Branch 19 → 20 taken 41267 times.
✓ Branch 19 → 22 taken 41454 times.
|
82721 | if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0)) |
| 506 | 41267 | return llvm::PointerType::get(context, 0); | |
| 507 | |||
| 508 |
2/2✓ Branch 23 → 24 taken 887 times.
✓ Branch 23 → 32 taken 40567 times.
|
41454 | if (isArray()) { |
| 509 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 887 times.
|
887 | assert(getArraySize() > 0); |
| 510 | 887 | llvm::Type *containedType = sourceFile->getLLVMType(getContained()); | |
| 511 | 887 | return llvm::ArrayType::get(containedType, getArraySize()); | |
| 512 | } | ||
| 513 | |||
| 514 |
1/2✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 40567 times.
|
40567 | assert(!hasAnyGenericParts()); |
| 515 | |||
| 516 |
2/2✓ Branch 36 → 37 taken 469 times.
✓ Branch 36 → 39 taken 40098 times.
|
40567 | if (is(TY_DOUBLE)) |
| 517 | 469 | return llvm::Type::getDoubleTy(context); | |
| 518 | |||
| 519 |
3/4✓ Branch 39 → 40 taken 40098 times.
✗ Branch 39 → 223 not taken.
✓ Branch 40 → 41 taken 3815 times.
✓ Branch 40 → 43 taken 36283 times.
|
40098 | if (isOneOf({TY_INT, TY_ENUM})) |
| 520 | 3815 | return llvm::Type::getInt32Ty(context); | |
| 521 | |||
| 522 |
2/2✓ Branch 44 → 45 taken 296 times.
✓ Branch 44 → 47 taken 35987 times.
|
36283 | if (is(TY_SHORT)) |
| 523 | 296 | return llvm::Type::getInt16Ty(context); | |
| 524 | |||
| 525 |
2/2✓ Branch 48 → 49 taken 2540 times.
✓ Branch 48 → 51 taken 33447 times.
|
35987 | if (is(TY_LONG)) |
| 526 | 2540 | return llvm::Type::getInt64Ty(context); | |
| 527 | |||
| 528 |
3/4✓ Branch 51 → 52 taken 33447 times.
✗ Branch 51 → 224 not taken.
✓ Branch 52 → 53 taken 3094 times.
✓ Branch 52 → 55 taken 30353 times.
|
33447 | if (isOneOf({TY_CHAR, TY_BYTE})) |
| 529 | 3094 | return llvm::Type::getInt8Ty(context); | |
| 530 | |||
| 531 |
2/2✓ Branch 56 → 57 taken 3427 times.
✓ Branch 56 → 59 taken 26926 times.
|
30353 | if (is(TY_BOOL)) |
| 532 | 3427 | return llvm::Type::getInt1Ty(context); | |
| 533 | |||
| 534 |
3/4✓ Branch 59 → 60 taken 26926 times.
✗ Branch 59 → 225 not taken.
✓ Branch 60 → 61 taken 26202 times.
✓ Branch 60 → 153 taken 724 times.
|
26926 | if (isOneOf({TY_STRUCT, TY_INTERFACE})) { |
| 535 |
1/2✓ Branch 61 → 62 taken 26202 times.
✗ Branch 61 → 254 not taken.
|
26202 | const Scope *structBodyScope = getBodyScope(); |
| 536 |
2/4✓ Branch 63 → 64 taken 26202 times.
✗ Branch 63 → 254 not taken.
✓ Branch 64 → 65 taken 26202 times.
✗ Branch 64 → 254 not taken.
|
26202 | const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes()); |
| 537 |
1/2✓ Branch 65 → 66 taken 26202 times.
✗ Branch 65 → 252 not taken.
|
26202 | const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature); |
| 538 |
1/2✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 26202 times.
|
26202 | assert(structSymbol != nullptr); |
| 539 | |||
| 540 | // Collect concrete field types | ||
| 541 | 26202 | std::string mangledName; | |
| 542 | 26202 | std::vector<llvm::Type *> fieldTypes; | |
| 543 | 26202 | bool isPacked = false; | |
| 544 |
2/2✓ Branch 72 → 73 taken 23446 times.
✓ Branch 72 → 135 taken 2756 times.
|
26202 | if (is(TY_STRUCT)) { // Struct |
| 545 |
2/4✓ Branch 73 → 74 taken 23446 times.
✗ Branch 73 → 248 not taken.
✓ Branch 74 → 75 taken 23446 times.
✗ Branch 74 → 248 not taken.
|
23446 | const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode); |
| 546 |
1/2✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 23446 times.
|
23446 | assert(spiceStruct != nullptr); |
| 547 |
1/2✓ Branch 77 → 78 taken 23446 times.
✗ Branch 77 → 226 not taken.
|
23446 | mangledName = NameMangling::mangleStruct(*spiceStruct); |
| 548 | |||
| 549 |
1/2✓ Branch 80 → 81 taken 23446 times.
✗ Branch 80 → 248 not taken.
|
23446 | const size_t totalFieldCount = spiceStruct->scope->getFieldCount(); |
| 550 |
1/2✓ Branch 81 → 82 taken 23446 times.
✗ Branch 81 → 248 not taken.
|
23446 | 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 23446 times.
✗ Branch 82 → 248 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 23446 times.
|
23446 | assert(structSymbol->declNode->isStructDef()); |
| 556 |
1/2✓ Branch 85 → 86 taken 23446 times.
✗ Branch 85 → 87 not taken.
|
23446 | const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode); |
| 557 |
3/4✓ Branch 94 → 95 taken 23446 times.
✗ Branch 94 → 248 not taken.
✓ Branch 95 → 96 taken 222 times.
✓ Branch 95 → 99 taken 23224 times.
|
23446 | if (spiceStruct->hasSynthesizedVTablePtr()) |
| 558 |
2/4✓ Branch 96 → 97 taken 222 times.
✗ Branch 96 → 227 not taken.
✓ Branch 97 → 98 taken 222 times.
✗ Branch 97 → 227 not taken.
|
222 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
| 559 | |||
| 560 | // Collect all field types | ||
| 561 |
2/2✓ Branch 113 → 100 taken 62564 times.
✓ Branch 113 → 114 taken 23446 times.
|
86010 | for (size_t i = 0; i < totalFieldCount; i++) { |
| 562 |
1/2✗ Branch 100 → 101 not taken.
✓ Branch 100 → 103 taken 62564 times.
|
62564 | const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i); |
| 563 |
1/2✗ Branch 106 → 107 not taken.
✓ Branch 106 → 108 taken 62564 times.
|
62564 | assert(fieldSymbol != nullptr); |
| 564 |
3/6✓ Branch 108 → 109 taken 62564 times.
✗ Branch 108 → 228 not taken.
✓ Branch 110 → 111 taken 62564 times.
✗ Branch 110 → 228 not taken.
✓ Branch 111 → 112 taken 62564 times.
✗ Branch 111 → 228 not taken.
|
62564 | 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 224 times.
✓ Branch 114 → 121 taken 23222 times.
✓ Branch 117 → 118 taken 224 times.
✗ Branch 117 → 229 not taken.
✓ Branch 118 → 119 taken 224 times.
✗ Branch 118 → 229 not taken.
✓ Branch 119 → 120 taken 2 times.
✓ Branch 119 → 121 taken 222 times.
✓ Branch 122 → 123 taken 224 times.
✓ Branch 122 → 124 taken 23222 times.
✓ Branch 124 → 125 taken 224 times.
✓ Branch 124 → 127 taken 23222 times.
✓ Branch 127 → 128 taken 2 times.
✓ Branch 127 → 145 taken 23444 times.
✗ Branch 229 → 230 not taken.
✗ Branch 229 → 231 not taken.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 236 not taken.
|
23894 | 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 2756 times.
✗ Branch 135 → 248 not taken.
✓ Branch 136 → 137 taken 2756 times.
✗ Branch 136 → 248 not taken.
|
2756 | const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode); |
| 572 |
1/2✗ Branch 137 → 138 not taken.
✓ Branch 137 → 139 taken 2756 times.
|
2756 | assert(spiceInterface != nullptr); |
| 573 |
1/2✓ Branch 139 → 140 taken 2756 times.
✗ Branch 139 → 244 not taken.
|
2756 | mangledName = NameMangling::mangleInterface(*spiceInterface); |
| 574 | |||
| 575 | // vtable pointer | ||
| 576 |
2/4✓ Branch 142 → 143 taken 2756 times.
✗ Branch 142 → 245 not taken.
✓ Branch 143 → 144 taken 2756 times.
✗ Branch 143 → 245 not taken.
|
2756 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
| 577 | } | ||
| 578 | |||
| 579 |
1/2✓ Branch 147 → 148 taken 26202 times.
✗ Branch 147 → 246 not taken.
|
26202 | return llvm::StructType::create(context, fieldTypes, mangledName, isPacked); |
| 580 | 26202 | } | |
| 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 | 803779 | void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) { | |
| 645 | // Unwrap both types as far as possible | ||
| 646 |
2/2✓ Branch 7 → 3 taken 65779 times.
✓ Branch 7 → 8 taken 803779 times.
|
869558 | while (typeA->isSameContainerTypeAs(typeB)) { |
| 647 | 65779 | typeB = typeB->getContained(); | |
| 648 | 65779 | typeA = typeA->getContained(); | |
| 649 | } | ||
| 650 | 803779 | } | |
| 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 | 787609 | 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 361882 times.
✓ Branch 3 → 7 taken 425727 times.
✓ Branch 5 → 6 taken 319883 times.
✓ Branch 5 → 7 taken 41999 times.
✓ Branch 8 → 9 taken 319883 times.
✓ Branch 8 → 11 taken 467726 times.
|
787609 | if (typeA->isRef() && !typeB->isRef()) |
| 662 | 319883 | typeA = typeA->removeReferenceWrapper(); | |
| 663 | |||
| 664 | // Remove reference wrapper of requested type if required | ||
| 665 |
8/8✓ Branch 12 → 13 taken 745610 times.
✓ Branch 12 → 18 taken 41999 times.
✓ Branch 14 → 15 taken 26198 times.
✓ Branch 14 → 18 taken 719412 times.
✓ Branch 16 → 17 taken 21677 times.
✓ Branch 16 → 18 taken 4521 times.
✓ Branch 19 → 20 taken 21677 times.
✓ Branch 19 → 22 taken 765932 times.
|
787609 | if (!typeA->isRef() && typeB->isRef() && !typeA->isBase(TY_GENERIC)) |
| 666 | 21677 | typeB = typeB->removeReferenceWrapper(); | |
| 667 | |||
| 668 | // Unwrap both types as far as possible | ||
| 669 | 787609 | unwrapBoth(typeA, typeB); | |
| 670 | 787609 | } | |
| 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 | 129095 | bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) { | |
| 680 | 129095 | return typeA->typeChain.size() == typeB->typeChain.size(); | |
| 681 | } | ||
| 682 | |||
| 683 | } // namespace spice::compiler | ||
| 684 |