Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 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 <exception/CompilerError.h> | ||
10 | #include <exception/SemanticError.h> | ||
11 | #include <global/TypeRegistry.h> | ||
12 | #include <irgenerator/NameMangling.h> | ||
13 | #include <model/Struct.h> | ||
14 | #include <symboltablebuilder/Scope.h> | ||
15 | #include <symboltablebuilder/SymbolTableEntry.h> | ||
16 | |||
17 | #include <llvm/IR/Module.h> | ||
18 | #include <llvm/IR/Type.h> | ||
19 | |||
20 | namespace spice::compiler { | ||
21 | |||
22 |
3/10✓ Branch 2 taken 7449427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7449427 times.
✓ Branch 5 taken 7449427 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
22348281 | Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {} |
23 | |||
24 |
4/12✓ Branch 1 taken 1253 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1253 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1253 times.
✓ Branch 8 taken 1253 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
3759 | Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {} |
25 | |||
26 | 855 | Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data, | |
27 | 855 | const QualTypeList &templateTypes) | |
28 |
5/14✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 855 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 855 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 855 times.
✓ Branch 11 taken 855 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
2565 | : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {} |
29 | |||
30 | 1302474 | Type::Type(TypeChain typeChain) : typeChain(std::move(typeChain)) {} | |
31 | |||
32 | /** | ||
33 | * Get the super type of the current type | ||
34 | * | ||
35 | * @return Super type | ||
36 | */ | ||
37 | 6835218 | SuperType Type::getSuperType() const { | |
38 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6835218 times.
|
6835218 | assert(!typeChain.empty()); |
39 | 6835218 | return typeChain.back().superType; | |
40 | } | ||
41 | |||
42 | /** | ||
43 | * Get the sub type of the current type | ||
44 | * | ||
45 | * @return Sub type | ||
46 | */ | ||
47 | 208148 | const std::string &Type::getSubType() const { | |
48 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 208148 times.
|
208148 | assert(!typeChain.empty()); |
49 |
2/4✓ Branch 1 taken 208148 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 208148 times.
|
208148 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC})); |
50 | 208148 | return typeChain.back().subType; | |
51 | } | ||
52 | |||
53 | /** | ||
54 | * Get the array size of the current type | ||
55 | * | ||
56 | * @return Array size | ||
57 | */ | ||
58 | 522 | unsigned int Type::getArraySize() const { | |
59 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
|
522 | assert(getSuperType() == TY_ARRAY); |
60 | 522 | return typeChain.back().data.arraySize; | |
61 | } | ||
62 | |||
63 | /** | ||
64 | * Get the body scope of the current type | ||
65 | * | ||
66 | * @return Body scope | ||
67 | */ | ||
68 | 99885 | Scope *Type::getBodyScope() const { | |
69 |
2/4✓ Branch 1 taken 99885 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 99885 times.
|
99885 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
70 | 99885 | return typeChain.back().data.bodyScope; | |
71 | } | ||
72 | |||
73 | /** | ||
74 | * Get the pointer type of the current type as a new type | ||
75 | * | ||
76 | * @param node AST node for error messages | ||
77 | * @return Pointer type of the current type | ||
78 | */ | ||
79 | 10774 | const Type *Type::toPtr(const ASTNode *node) const { | |
80 | // Do not allow pointers of dyn | ||
81 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10772 times.
|
10774 | if (is(TY_DYN)) |
82 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
6 | throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead"); |
83 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10772 times.
|
10772 | if (isRef()) |
84 | ✗ | throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead"); | |
85 | |||
86 | // Create new type chain | ||
87 |
1/2✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
|
10772 | TypeChain newTypeChain = typeChain; |
88 |
1/2✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
|
10772 | newTypeChain.emplace_back(TY_PTR); |
89 | |||
90 | // Register new type or return if already registered | ||
91 |
1/2✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
|
21544 | return TypeRegistry::getOrInsert(newTypeChain); |
92 | 10772 | } | |
93 | |||
94 | /** | ||
95 | * Get the reference type of the current type as a new type | ||
96 | * | ||
97 | * @param node AST node for error messages | ||
98 | * @return Reference type of the current type | ||
99 | */ | ||
100 | 11992 | const Type *Type::toRef(const ASTNode *node) const { | |
101 | // Do not allow references of dyn | ||
102 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11992 times.
|
11992 | if (is(TY_DYN)) |
103 | ✗ | throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead"); | |
104 | // Do not allow references of references | ||
105 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11992 times.
|
11992 | if (isRef()) |
106 | ✗ | throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed"); | |
107 | |||
108 | // Create new type chain | ||
109 |
1/2✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
|
11992 | TypeChain newTypeChain = typeChain; |
110 |
1/2✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
|
11992 | newTypeChain.emplace_back(TY_REF); |
111 | |||
112 | // Register new type or return if already registered | ||
113 |
1/2✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
|
23984 | return TypeRegistry::getOrInsert(newTypeChain); |
114 | 11992 | } | |
115 | |||
116 | /** | ||
117 | * Get the array type of the current type as a new type | ||
118 | * | ||
119 | * @param node AST node for error messages | ||
120 | * @param size Size of the array | ||
121 | * @return Array type of the current type | ||
122 | */ | ||
123 | 201 | const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck /*=false*/) const { | |
124 | // Do not allow arrays of dyn | ||
125 |
6/6✓ Branch 0 taken 135 times.
✓ Branch 1 taken 66 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 134 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 200 times.
|
201 | if (!skipDynCheck && typeChain.back().superType == TY_DYN) |
126 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
3 | throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead"); |
127 | |||
128 | // Create new type chain | ||
129 |
1/2✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
|
200 | TypeChain newTypeChain = typeChain; |
130 |
1/2✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
|
200 | newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size}); |
131 | |||
132 | // Register new type or return if already registered | ||
133 |
1/2✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
|
400 | return TypeRegistry::getOrInsert(newTypeChain); |
134 | 200 | } | |
135 | |||
136 | /** | ||
137 | * Retrieve the base type of an array or a pointer | ||
138 | * | ||
139 | * @return Base type | ||
140 | */ | ||
141 | 75447 | const Type *Type::getContained() const { | |
142 |
2/2✓ Branch 1 taken 1226 times.
✓ Branch 2 taken 74221 times.
|
75447 | if (is(TY_STRING)) |
143 |
1/2✓ Branch 1 taken 1226 times.
✗ Branch 2 not taken.
|
1226 | return TypeRegistry::getOrInsert(TY_CHAR); |
144 | |||
145 | // Create new type chain | ||
146 |
1/2✓ Branch 1 taken 74221 times.
✗ Branch 2 not taken.
|
74221 | TypeChain newTypeChain = typeChain; |
147 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 74221 times.
|
74221 | assert(newTypeChain.size() > 1); |
148 | 74221 | newTypeChain.pop_back(); | |
149 | |||
150 | // Register new type or return if already registered | ||
151 |
1/2✓ Branch 1 taken 74221 times.
✗ Branch 2 not taken.
|
74221 | return TypeRegistry::getOrInsert(newTypeChain); |
152 | 74221 | } | |
153 | |||
154 | /** | ||
155 | * Replace the base type with another one | ||
156 | * | ||
157 | * @param newBaseType New base type | ||
158 | * @return The new type | ||
159 | */ | ||
160 | 10152 | const Type *Type::replaceBase(const Type *newBaseType) const { | |
161 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10152 times.
|
10152 | assert(!typeChain.empty()); |
162 | |||
163 | // Create new type | ||
164 |
1/2✓ Branch 1 taken 10152 times.
✗ Branch 2 not taken.
|
10152 | TypeChain newTypeChain = newBaseType->typeChain; |
165 |
4/4✓ Branch 1 taken 393 times.
✓ Branch 2 taken 9759 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 379 times.
|
10152 | const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF; |
166 |
2/2✓ Branch 1 taken 1703 times.
✓ Branch 2 taken 10152 times.
|
11855 | for (size_t i = 1; i < typeChain.size(); i++) |
167 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1689 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
1703 | if (!doubleRef || i > 1) |
168 |
2/4✓ Branch 1 taken 1689 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1689 times.
✗ Branch 5 not taken.
|
1689 | newTypeChain.push_back(typeChain.at(i)); |
169 | |||
170 | // Register new type or return if already registered | ||
171 |
1/2✓ Branch 1 taken 10152 times.
✗ Branch 2 not taken.
|
20304 | return TypeRegistry::getOrInsert(newTypeChain); |
172 | 10152 | } | |
173 | |||
174 | /** | ||
175 | * Remove reference wrapper from the current type | ||
176 | * | ||
177 | * @return Type without reference wrapper | ||
178 | */ | ||
179 |
1/2✓ Branch 1 taken 20593 times.
✗ Branch 2 not taken.
|
20593 | const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; } |
180 | |||
181 | /** | ||
182 | * Return the LLVM type for this symbol type | ||
183 | * | ||
184 | * @param sourceFile Referenced source file | ||
185 | * @return Corresponding LLVM type | ||
186 | */ | ||
187 | 5171 | llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion) | |
188 |
2/4✓ Branch 1 taken 5171 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5171 times.
✗ Branch 5 not taken.
|
5171 | assert(!typeChain.empty() && !is(TY_INVALID)); |
189 | 5171 | llvm::LLVMContext &context = sourceFile->llvmModule->getContext(); | |
190 | |||
191 |
2/2✓ Branch 1 taken 64 times.
✓ Branch 2 taken 5107 times.
|
5171 | if (is(TY_DOUBLE)) |
192 | 64 | return llvm::Type::getDoubleTy(context); | |
193 | |||
194 |
3/4✓ Branch 1 taken 5107 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 492 times.
✓ Branch 4 taken 4615 times.
|
5107 | if (isOneOf({TY_INT, TY_ENUM})) |
195 | 492 | return llvm::Type::getInt32Ty(context); | |
196 | |||
197 |
2/2✓ Branch 1 taken 61 times.
✓ Branch 2 taken 4554 times.
|
4615 | if (is(TY_SHORT)) |
198 | 61 | return llvm::Type::getInt16Ty(context); | |
199 | |||
200 |
2/2✓ Branch 1 taken 320 times.
✓ Branch 2 taken 4234 times.
|
4554 | if (is(TY_LONG)) |
201 | 320 | return llvm::Type::getInt64Ty(context); | |
202 | |||
203 |
3/4✓ Branch 1 taken 4234 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 164 times.
✓ Branch 4 taken 4070 times.
|
4234 | if (isOneOf({TY_CHAR, TY_BYTE})) |
204 | 164 | return llvm::Type::getInt8Ty(context); | |
205 | |||
206 |
2/2✓ Branch 1 taken 307 times.
✓ Branch 2 taken 3763 times.
|
4070 | if (is(TY_BOOL)) |
207 | 307 | return llvm::Type::getInt1Ty(context); | |
208 | |||
209 |
3/4✓ Branch 1 taken 3763 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1318 times.
✓ Branch 4 taken 2445 times.
|
3763 | if (isOneOf({TY_STRUCT, TY_INTERFACE})) { |
210 |
1/2✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
|
1318 | const Scope *structBodyScope = getBodyScope(); |
211 |
2/4✓ Branch 2 taken 1318 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1318 times.
✗ Branch 6 not taken.
|
1318 | const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes()); |
212 |
1/2✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
|
1318 | const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature); |
213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1318 times.
|
1318 | assert(structSymbol != nullptr); |
214 | |||
215 | // Collect concrete field types | ||
216 | llvm::StructType *structType; | ||
217 | 1318 | std::vector<llvm::Type *> fieldTypes; | |
218 | 1318 | bool isPacked = false; | |
219 |
2/2✓ Branch 1 taken 1176 times.
✓ Branch 2 taken 142 times.
|
1318 | if (is(TY_STRUCT)) { // Struct |
220 |
2/4✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1176 times.
✗ Branch 5 not taken.
|
1176 | const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode); |
221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1176 times.
|
1176 | assert(spiceStruct != nullptr); |
222 |
1/2✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
|
1176 | const std::string mangledName = NameMangling::mangleStruct(*spiceStruct); |
223 |
1/2✓ Branch 2 taken 1176 times.
✗ Branch 3 not taken.
|
1176 | structType = llvm::StructType::create(context, mangledName); |
224 | |||
225 |
1/2✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
|
1176 | const size_t totalFieldCount = spiceStruct->scope->getFieldCount(); |
226 |
1/2✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
|
1176 | fieldTypes.reserve(totalFieldCount); |
227 | |||
228 | // If the struct has no interface types, but a vtable was requested, add another ptr field type | ||
229 |
2/4✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1176 times.
|
1176 | assert(structSymbol->declNode->isStructDef()); |
230 |
1/2✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
|
1176 | const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode); |
231 |
4/4✓ Branch 0 taken 935 times.
✓ Branch 1 taken 241 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 899 times.
|
1176 | if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable) |
232 |
2/4✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
233 | |||
234 | // Collect all field types | ||
235 |
2/2✓ Branch 0 taken 3134 times.
✓ Branch 1 taken 1176 times.
|
4310 | for (size_t i = 0; i < totalFieldCount; i++) { |
236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3134 times.
|
3134 | const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i); |
237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3134 times.
|
3134 | assert(fieldSymbol != nullptr); |
238 |
3/6✓ Branch 1 taken 3134 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3134 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3134 times.
✗ Branch 9 not taken.
|
3134 | fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType())); |
239 | } | ||
240 | |||
241 | // Check if the struct is declared as packed | ||
242 |
15/24✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 1139 times.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 37 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 37 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 36 times.
✓ Branch 19 taken 37 times.
✓ Branch 20 taken 1139 times.
✓ Branch 22 taken 37 times.
✓ Branch 23 taken 1139 times.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 1175 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
|
1250 | if (structDeclNode->attrs() && structDeclNode->attrs()->attrLst()->hasAttr(ATTR_CORE_COMPILER_PACKED)) |
243 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | isPacked = structDeclNode->attrs()->attrLst()->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue; |
244 | 1176 | } else { // Interface | |
245 |
2/4✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
|
142 | const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode); |
246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
|
142 | assert(spiceInterface != nullptr); |
247 |
1/2✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
|
142 | const std::string mangledName = NameMangling::mangleInterface(*spiceInterface); |
248 |
1/2✓ Branch 2 taken 142 times.
✗ Branch 3 not taken.
|
142 | structType = llvm::StructType::create(context, mangledName); |
249 | |||
250 |
2/4✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
|
142 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
251 | 142 | } | |
252 | |||
253 | // Set field types to struct type | ||
254 |
1/2✓ Branch 2 taken 1318 times.
✗ Branch 3 not taken.
|
1318 | structType->setBody(fieldTypes, isPacked); |
255 | |||
256 | 1318 | return structType; | |
257 | 1318 | } | |
258 | |||
259 |
9/10✓ Branch 1 taken 2445 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 125 times.
✓ Branch 4 taken 2320 times.
✓ Branch 6 taken 55 times.
✓ Branch 7 taken 70 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 35 times.
✓ Branch 11 taken 2340 times.
✓ Branch 12 taken 105 times.
|
2445 | if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0)) |
260 | 2340 | return llvm::PointerType::get(context, 0); | |
261 | |||
262 |
3/4✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 35 times.
|
105 | if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
263 | 70 | llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0); | |
264 |
1/2✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
|
70 | return llvm::StructType::get(context, {ptrTy, ptrTy}); |
265 | } | ||
266 | |||
267 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | if (isArray()) { |
268 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
|
35 | assert(getArraySize() > 0); |
269 | 35 | llvm::Type *containedType = sourceFile->getLLVMType(getContained()); | |
270 | 35 | return llvm::ArrayType::get(containedType, getArraySize()); | |
271 | } | ||
272 | |||
273 | − | throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true)); // GCOVR_EXCL_LINE | |
274 | } | ||
275 | |||
276 | /** | ||
277 | * Check if the base type of the current type chain is of a certain super type | ||
278 | * | ||
279 | * @param superType Super type to check for | ||
280 | * @return Applicable or not | ||
281 | */ | ||
282 | 370339 | bool Type::isBase(SuperType superType) const { | |
283 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 370339 times.
|
370339 | assert(!typeChain.empty()); |
284 | 370339 | return typeChain.front().superType == superType; | |
285 | } | ||
286 | |||
287 | /** | ||
288 | * Check if the current type is a primitive type | ||
289 | * | ||
290 | * @return Primitive type or not | ||
291 | */ | ||
292 |
1/2✓ Branch 1 taken 63053 times.
✗ Branch 2 not taken.
|
63053 | bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); } |
293 | |||
294 | /** | ||
295 | * Check if the current type is a pointer type | ||
296 | * | ||
297 | * @return Pointer type or not | ||
298 | */ | ||
299 | 222584 | bool Type::isPtr() const { return getSuperType() == TY_PTR; } | |
300 | |||
301 | /** | ||
302 | * Check if the current type is a reference type | ||
303 | * | ||
304 | * @return Reference type or not | ||
305 | */ | ||
306 | 641357 | bool Type::isRef() const { return getSuperType() == TY_REF; } | |
307 | |||
308 | /** | ||
309 | * Check if the current type is an array type | ||
310 | * | ||
311 | * @return Array type or not | ||
312 | */ | ||
313 | 114175 | bool Type::isArray() const { return getSuperType() == TY_ARRAY; } | |
314 | |||
315 | /** | ||
316 | * Check if the current type is of the same container type like the other type. | ||
317 | * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types. | ||
318 | * | ||
319 | * @param other Other symbol type | ||
320 | * @return Same container type or not | ||
321 | */ | ||
322 | 69887 | bool Type::isSameContainerTypeAs(const Type *other) const { | |
323 |
4/4✓ Branch 1 taken 1654 times.
✓ Branch 2 taken 68233 times.
✓ Branch 4 taken 1347 times.
✓ Branch 5 taken 307 times.
|
69887 | const bool bothPtr = isPtr() && other->isPtr(); |
324 |
3/4✓ Branch 1 taken 4302 times.
✓ Branch 2 taken 65585 times.
✓ Branch 4 taken 4302 times.
✗ Branch 5 not taken.
|
69887 | const bool bothRef = isRef() && other->isRef(); |
325 |
3/4✓ Branch 1 taken 50 times.
✓ Branch 2 taken 69837 times.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
|
69887 | const bool bothArray = isArray() && other->isArray(); |
326 |
6/6✓ Branch 0 taken 68540 times.
✓ Branch 1 taken 1347 times.
✓ Branch 2 taken 64238 times.
✓ Branch 3 taken 4302 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 64188 times.
|
69887 | return bothPtr || bothRef || bothArray; |
327 | } | ||
328 | |||
329 | /** | ||
330 | * Retrieve the base type of the current type | ||
331 | * | ||
332 | * @return Base type | ||
333 | */ | ||
334 | 1160846 | const Type *Type::getBase() const { | |
335 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1160846 times.
|
1160846 | assert(!typeChain.empty()); |
336 | |||
337 | // Create new type chain | ||
338 |
3/6✓ Branch 1 taken 1160846 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1160846 times.
✓ Branch 4 taken 1160846 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3482538 | const TypeChain newTypeChain = {typeChain.front()}; |
339 | |||
340 | // Register new type or return if already registered | ||
341 |
1/2✓ Branch 1 taken 1160846 times.
✗ Branch 2 not taken.
|
2321692 | return TypeRegistry::getOrInsert(newTypeChain); |
342 |
1/6✓ Branch 2 taken 1160846 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
2321692 | } |
343 | |||
344 | /** | ||
345 | * Retrieve the same type, but with lambda captures | ||
346 | * | ||
347 | * @return Type with lambda captures | ||
348 | */ | ||
349 | 42 | const Type *Type::getWithLambdaCaptures(bool enabled) const { | |
350 |
3/6✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 42 times.
|
42 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
351 | |||
352 | // Create new type chain | ||
353 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
42 | TypeChain newTypeChain = typeChain; |
354 | 42 | newTypeChain.front().data.hasCaptures = enabled; | |
355 | |||
356 | // Register new type or return if already registered | ||
357 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
84 | return TypeRegistry::getOrInsert(newTypeChain); |
358 | 42 | } | |
359 | |||
360 | /** | ||
361 | * Retrieve the same type, but with the body scope removed | ||
362 | * | ||
363 | * @return Type with body scope removed | ||
364 | */ | ||
365 | 19609 | const Type *Type::getWithBodyScope(Scope *bodyScope) const { | |
366 |
3/6✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19609 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19609 times.
|
19609 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
367 | |||
368 | // Create new type chain | ||
369 |
1/2✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
|
19609 | TypeChain newTypeChain = typeChain; |
370 | 19609 | newTypeChain.front().data.bodyScope = bodyScope; | |
371 | |||
372 | // Register new type or return if already registered | ||
373 |
1/2✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
|
39218 | return TypeRegistry::getOrInsert(newTypeChain); |
374 | 19609 | } | |
375 | |||
376 | /** | ||
377 | * Retrieve the same type, but with the given template types | ||
378 | * | ||
379 | * @return Type with new template types | ||
380 | */ | ||
381 | 2656 | const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const { | |
382 |
2/4✓ Branch 1 taken 2656 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2656 times.
|
2656 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
383 | 2656 | return getWithBaseTemplateTypes(templateTypes); | |
384 | } | ||
385 | |||
386 | /** | ||
387 | * Retrieve the same type, but with the given base template types | ||
388 | * | ||
389 | * @return Type with new base template types | ||
390 | */ | ||
391 | 6284 | const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const { | |
392 |
3/6✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6284 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6284 times.
|
6284 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
393 | |||
394 | // Create new type chain | ||
395 |
1/2✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
|
6284 | TypeChain newTypeChain = typeChain; |
396 |
1/2✓ Branch 2 taken 6284 times.
✗ Branch 3 not taken.
|
6284 | newTypeChain.front().templateTypes = templateTypes; |
397 | |||
398 | // Register new type or return if already registered | ||
399 |
1/2✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
|
12568 | return TypeRegistry::getOrInsert(newTypeChain); |
400 | 6284 | } | |
401 | |||
402 | /** | ||
403 | * Retrieve the same type, but with the param and return types removed | ||
404 | * | ||
405 | * @return Type with param and return types removed | ||
406 | */ | ||
407 | 8356 | const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList ¶mAndReturnTypes) const { | |
408 |
3/6✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8356 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8356 times.
|
8356 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
409 | |||
410 | // Create new type chain | ||
411 |
1/2✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
|
8356 | TypeChain newTypeChain = typeChain; |
412 |
1/2✓ Branch 2 taken 8356 times.
✗ Branch 3 not taken.
|
8356 | newTypeChain.front().paramTypes = paramAndReturnTypes; |
413 | |||
414 | // Register new type or return if already registered | ||
415 |
1/2✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
|
16712 | return TypeRegistry::getOrInsert(newTypeChain); |
416 | 8356 | } | |
417 | |||
418 | /** | ||
419 | * Checks if the base type is generic itself or has generic parts in its template types | ||
420 | * | ||
421 | * @return Contains generic parts or not | ||
422 | */ | ||
423 | 282985 | bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion) | |
424 |
1/2✓ Branch 1 taken 282985 times.
✗ Branch 2 not taken.
|
282985 | const Type *baseType = getBase(); |
425 | |||
426 | // Check if the type itself is generic | ||
427 |
2/2✓ Branch 1 taken 39038 times.
✓ Branch 2 taken 243947 times.
|
282985 | if (baseType->is(TY_GENERIC)) |
428 | 39038 | return true; | |
429 | |||
430 | // Check if the type has generic template types | ||
431 |
1/2✓ Branch 2 taken 243947 times.
✗ Branch 3 not taken.
|
243947 | const auto templateTypes = baseType->getTemplateTypes(); |
432 |
3/4✓ Branch 1 taken 243947 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13741 times.
✓ Branch 4 taken 230206 times.
|
317080 | if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
433 | 13741 | return true; | |
434 | |||
435 | // Check param and return types or functions/procedures | ||
436 |
3/4✓ Branch 1 taken 230206 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 514 times.
✓ Branch 4 taken 229692 times.
|
230206 | if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
437 |
2/4✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 514 times.
✗ Branch 5 not taken.
|
514 | const auto paramTypes = baseType->getFunctionParamAndReturnTypes(); |
438 |
3/4✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 104 times.
✓ Branch 4 taken 410 times.
|
1344 | if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
439 | 104 | return true; | |
440 |
2/2✓ Branch 1 taken 410 times.
✓ Branch 2 taken 104 times.
|
514 | } |
441 | |||
442 | 230102 | return false; // Does not have generic parts | |
443 | 243947 | } | |
444 | |||
445 | /** | ||
446 | * Retrieve template types of the current type | ||
447 | * | ||
448 | * @return Vector of template types | ||
449 | */ | ||
450 | 317936 | const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; } | |
451 | |||
452 | /** | ||
453 | * Check if the current type is of a certain super type | ||
454 | * | ||
455 | * @return Applicable or not | ||
456 | */ | ||
457 | 4940681 | bool Type::is(SuperType superType) const { return getSuperType() == superType; } | |
458 | |||
459 | /** | ||
460 | * Check if the current type is one of a list of super types | ||
461 | * | ||
462 | * @return Applicable or not | ||
463 | */ | ||
464 | 1034592 | bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const { | |
465 | 3402645 | return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); }); | |
466 | } | ||
467 | |||
468 | /** | ||
469 | * Get the name of the symbol type as a string | ||
470 | * | ||
471 | * @param withSize Include the array size for sized types | ||
472 | * @return Symbol type name | ||
473 | */ | ||
474 | 619699 | void Type::getName(std::stringstream &name, bool withSize) const { // NOLINT(misc-no-recursion) | |
475 | // Loop through all chain elements | ||
476 |
2/2✓ Branch 4 taken 788878 times.
✓ Branch 5 taken 619699 times.
|
1408577 | for (const TypeChainElement &chainElement : typeChain) |
477 |
2/4✓ Branch 1 taken 788878 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 788878 times.
✗ Branch 5 not taken.
|
788878 | name << chainElement.getName(withSize); |
478 | 619699 | } | |
479 | |||
480 | /** | ||
481 | * Get the name of the symbol type as a string | ||
482 | * | ||
483 | * @param withSize Include the array size for sized types | ||
484 | * @param ignorePublic Ignore any potential public specifier | ||
485 | * @return Symbol type name | ||
486 | */ | ||
487 | 10544 | std::string Type::getName(bool withSize) const { | |
488 |
1/2✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
|
10544 | std::stringstream name; |
489 |
1/2✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
|
10544 | getName(name, withSize); |
490 |
1/2✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
|
21088 | return name.str(); |
491 | 10544 | } | |
492 | |||
493 | /** | ||
494 | * Get the return type of a function type | ||
495 | * | ||
496 | * @return Function return type | ||
497 | */ | ||
498 | 21 | const QualType &Type::getFunctionReturnType() const { | |
499 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
|
21 | assert(is(TY_FUNCTION)); |
500 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
|
21 | assert(!typeChain.back().paramTypes.empty()); |
501 | 21 | return typeChain.back().paramTypes.front(); | |
502 | } | ||
503 | |||
504 | /** | ||
505 | * Get the param types of a function or procedure type | ||
506 | * | ||
507 | * @return Function param types | ||
508 | */ | ||
509 | 97 | QualTypeList Type::getFunctionParamTypes() const { | |
510 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
|
97 | assert(isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
511 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
|
97 | if (typeChain.back().paramTypes.empty()) |
512 | ✗ | return {}; | |
513 |
1/2✓ Branch 6 taken 97 times.
✗ Branch 7 not taken.
|
291 | return {typeChain.back().paramTypes.begin() + 1, typeChain.back().paramTypes.end()}; |
514 | } | ||
515 | |||
516 | /** | ||
517 | * Check if a function or procedure type has captures | ||
518 | * | ||
519 | * @return Has captures | ||
520 | */ | ||
521 | 134 | bool Type::hasLambdaCaptures() const { | |
522 |
2/4✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 134 times.
|
134 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
523 | 134 | return typeChain.front().data.hasCaptures; | |
524 | } | ||
525 | |||
526 | /** | ||
527 | * Get the param and return types of a function or procedure base type | ||
528 | * | ||
529 | * @return Function param and return types (first is return type, rest are param types) | ||
530 | */ | ||
531 | 613 | const QualTypeList &Type::getFunctionParamAndReturnTypes() const { | |
532 |
2/4✓ Branch 2 taken 613 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 613 times.
|
613 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
533 | 613 | return typeChain.front().paramTypes; | |
534 | } | ||
535 | |||
536 | /** | ||
537 | * Check for the matching compatibility of two types. | ||
538 | * Useful for struct and function matching as well as assignment type validation and function arg matching. | ||
539 | * | ||
540 | * @param otherType Type to compare against | ||
541 | * @param ignoreArraySize Ignore array sizes | ||
542 | * @return Matching or not | ||
543 | */ | ||
544 | 79883 | bool Type::matches(const Type *otherType, bool ignoreArraySize) const { | |
545 | // If the size does not match, it is not equal | ||
546 |
2/2✓ Branch 2 taken 5365 times.
✓ Branch 3 taken 74518 times.
|
79883 | if (typeChain.size() != otherType->typeChain.size()) |
547 | 5365 | return false; | |
548 | |||
549 | // Compare the elements | ||
550 |
2/2✓ Branch 1 taken 79461 times.
✓ Branch 2 taken 51436 times.
|
130897 | for (size_t i = 0; i < typeChain.size(); i++) { |
551 | 79461 | const TypeChainElement &lhsElement = typeChain.at(i); | |
552 | 79461 | const TypeChainElement &rhsElement = otherType->typeChain.at(i); | |
553 | |||
554 | // Ignore differences in array size | ||
555 |
5/6✓ Branch 0 taken 56305 times.
✓ Branch 1 taken 23156 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 56304 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
79461 | if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY) |
556 | 1 | continue; | |
557 | |||
558 | // Not both types are arrays -> compare them as usual | ||
559 |
2/2✓ Branch 1 taken 23082 times.
✓ Branch 2 taken 56378 times.
|
79460 | if (lhsElement != rhsElement) |
560 | 23082 | return false; | |
561 | } | ||
562 | |||
563 | // Ignore or compare specifiers | ||
564 | 51436 | return true; | |
565 | } | ||
566 | |||
567 | /** | ||
568 | * Remove pointers / arrays / references if both types have them as far as possible. | ||
569 | * Furthermore, remove reference wrappers if possible. | ||
570 | * | ||
571 | * @param typeA Candidate type | ||
572 | * @param typeB Requested type | ||
573 | */ | ||
574 | 62031 | void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) { | |
575 | // Remove reference wrapper of front type if required | ||
576 |
6/6✓ Branch 1 taken 21467 times.
✓ Branch 2 taken 40564 times.
✓ Branch 4 taken 17165 times.
✓ Branch 5 taken 4302 times.
✓ Branch 6 taken 17165 times.
✓ Branch 7 taken 44866 times.
|
62031 | if (typeA->isRef() && !typeB->isRef()) |
577 | 17165 | typeA = typeA->removeReferenceWrapper(); | |
578 | |||
579 | // Remove reference wrapper of requested type if required | ||
580 |
8/8✓ Branch 1 taken 57729 times.
✓ Branch 2 taken 4302 times.
✓ Branch 4 taken 3738 times.
✓ Branch 5 taken 53991 times.
✓ Branch 8 taken 3428 times.
✓ Branch 9 taken 310 times.
✓ Branch 10 taken 3428 times.
✓ Branch 11 taken 58603 times.
|
62031 | if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC)) |
581 | 3428 | typeB = typeB->removeReferenceWrapper(); | |
582 | |||
583 | // Unwrap both types as far as possible | ||
584 |
2/2✓ Branch 1 taken 5499 times.
✓ Branch 2 taken 62031 times.
|
67530 | while (typeA->isSameContainerTypeAs(typeB)) { |
585 | 5499 | typeB = typeB->getContained(); | |
586 | 5499 | typeA = typeA->getContained(); | |
587 | } | ||
588 | 62031 | } | |
589 | |||
590 | /** | ||
591 | * Check if two types have the same type chain depth | ||
592 | * | ||
593 | * @param typeA First type | ||
594 | * @param typeB Second type | ||
595 | * @return Same depth or not | ||
596 | */ | ||
597 | 13391 | bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) { | |
598 | 13391 | return typeA->typeChain.size() == typeB->typeChain.size(); | |
599 | } | ||
600 | |||
601 | } // namespace spice::compiler | ||
602 |