GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenTopLevelDefinitions.cpp
Date: 2025-12-19 06:54:40
Coverage Exec Excl Total
Lines: 96.9% 372 0 384
Functions: 100.0% 17 0 17
Branches: 58.0% 455 0 784

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4
5 #include <llvm/IR/Module.h>
6 #include <llvm/Target/TargetLoweringObjectFile.h>
7
8 #include <SourceFile.h>
9 #include <ast/ASTNodes.h>
10 #include <ast/Attributes.h>
11 #include <driver/Driver.h>
12 #include <irgenerator/NameMangling.h>
13 #include <symboltablebuilder/SymbolTableBuilder.h>
14
15 namespace spice::compiler {
16
17 253 std::any IRGenerator::visitMainFctDef(const MainFctDefNode *node) {
18 // Ignore main function definitions if this is not the main source file
19
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 253 times.
253 if (!sourceFile->isMainFile)
20 return nullptr;
21
22 // Do not generate main function if it is explicitly specified
23
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 252 times.
253 if (cliOptions.noEntryFct)
24
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 134 not taken.
1 return nullptr;
25
26 // Change scope to function scope
27 252 currentScope = node->bodyScope;
28
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 252 times.
252 assert(currentScope != nullptr);
29
30 // Visit parameters
31 252 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
32 252 QualTypeList paramSymbolTypes;
33 252 std::vector<llvm::Type *> paramTypes;
34
2/2
✓ Branch 10 → 11 taken 4 times.
✓ Branch 10 → 34 taken 248 times.
252 if (node->takesArgs) {
35 4 const size_t numOfParams = node->paramLst->params.size();
36
1/2
✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 183 not taken.
4 paramInfoList.reserve(numOfParams);
37
1/2
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 183 not taken.
4 paramSymbolTypes.reserve(numOfParams);
38
1/2
✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 183 not taken.
4 paramTypes.reserve(numOfParams);
39
2/2
✓ Branch 32 → 17 taken 8 times.
✓ Branch 32 → 33 taken 4 times.
12 for (DeclStmtNode *param : node->paramLst->params) {
40 // Get symbol table entry of param
41
1/2
✓ Branch 18 → 19 taken 8 times.
✗ Branch 18 → 138 not taken.
8 SymbolTableEntry *paramSymbol = node->bodyScope->lookupStrict(param->varName);
42
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 8 times.
8 assert(paramSymbol != nullptr);
43 // Retrieve type of param
44
2/4
✓ Branch 23 → 24 taken 8 times.
✗ Branch 23 → 137 not taken.
✓ Branch 24 → 25 taken 8 times.
✗ Branch 24 → 135 not taken.
8 auto paramType = any_cast<llvm::Type *>(visit(param->dataType));
45 // Add it to the lists
46
1/2
✓ Branch 26 → 27 taken 8 times.
✗ Branch 26 → 138 not taken.
8 paramInfoList.emplace_back(param->varName, paramSymbol);
47
2/4
✓ Branch 27 → 28 taken 8 times.
✗ Branch 27 → 138 not taken.
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 138 not taken.
8 paramSymbolTypes.push_back(paramSymbol->getQualType());
48
1/2
✓ Branch 29 → 30 taken 8 times.
✗ Branch 29 → 138 not taken.
8 paramTypes.push_back(paramType);
49 }
50 }
51
52 // Build the function
53
1/2
✓ Branch 34 → 35 taken 252 times.
✗ Branch 34 → 183 not taken.
252 llvm::Type *returnType = builder.getInt32Ty();
54
1/2
✓ Branch 36 → 37 taken 252 times.
✗ Branch 36 → 140 not taken.
252 llvm::FunctionType *fctType = llvm::FunctionType::get(returnType, paramTypes, false);
55
2/4
✓ Branch 37 → 38 taken 252 times.
✗ Branch 37 → 141 not taken.
✓ Branch 38 → 39 taken 252 times.
✗ Branch 38 → 141 not taken.
252 llvm::Function *fct = llvm::Function::Create(fctType, llvm::Function::ExternalLinkage, MAIN_FUNCTION_NAME, module);
56 252 fct->setDSOLocal(true);
57
58 // Add function attributes
59
1/2
✓ Branch 40 → 41 taken 252 times.
✗ Branch 40 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::MustProgress);
60
1/2
✓ Branch 41 → 42 taken 252 times.
✗ Branch 41 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::NoInline);
61
1/2
✓ Branch 42 → 43 taken 252 times.
✗ Branch 42 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::NoRecurse);
62
1/2
✓ Branch 43 → 44 taken 252 times.
✗ Branch 43 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::NoUnwind);
63
1/2
✓ Branch 44 → 45 taken 252 times.
✗ Branch 44 → 46 not taken.
252 if (cliOptions.optLevel == OptLevel::O0)
64
1/2
✓ Branch 45 → 48 taken 252 times.
✗ Branch 45 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::OptimizeNone);
65 else if (cliOptions.optLevel >= OptLevel::Os)
66 fct->addFnAttr(llvm::Attribute::OptimizeForSize);
67
2/4
✓ Branch 48 → 49 taken 252 times.
✗ Branch 48 → 183 not taken.
✓ Branch 49 → 50 taken 252 times.
✗ Branch 49 → 183 not taken.
252 fct->addFnAttr(llvm::Attribute::getWithUWTableKind(context, llvm::UWTableKind::Default));
68
1/2
✓ Branch 50 → 51 taken 252 times.
✗ Branch 50 → 183 not taken.
252 enableFunctionInstrumentation(fct);
69
70 // Add return value attributes
71
1/2
✓ Branch 51 → 52 taken 252 times.
✗ Branch 51 → 183 not taken.
252 fct->addRetAttr(llvm::Attribute::NoUndef);
72
73 // Add return value attributes
74
1/2
✓ Branch 52 → 53 taken 252 times.
✗ Branch 52 → 183 not taken.
252 fct->addRetAttr(llvm::Attribute::NoUndef);
75
76 // Add debug info
77
2/2
✓ Branch 53 → 54 taken 6 times.
✓ Branch 53 → 59 taken 246 times.
252 if (cliOptions.instrumentation.generateDebugInfo) {
78 6 const auto nonConstNode = const_cast<MainFctDefNode *>(node);
79
1/2
✓ Branch 54 → 55 taken 6 times.
✗ Branch 54 → 144 not taken.
6 const Function spiceFunc = FunctionManager::createMainFunction(node->entry, paramSymbolTypes, nonConstNode);
80
1/2
✓ Branch 55 → 56 taken 6 times.
✗ Branch 55 → 142 not taken.
6 diGenerator.generateFunctionDebugInfo(fct, &spiceFunc);
81
1/2
✓ Branch 56 → 57 taken 6 times.
✗ Branch 56 → 142 not taken.
6 diGenerator.setSourceLocation(node);
82 6 }
83
84 // Create entry block
85
2/4
✓ Branch 61 → 62 taken 252 times.
✗ Branch 61 → 147 not taken.
✓ Branch 62 → 63 taken 252 times.
✗ Branch 62 → 145 not taken.
252 llvm::BasicBlock *bEntry = createBlock();
86
1/2
✓ Branch 65 → 66 taken 252 times.
✗ Branch 65 → 183 not taken.
252 switchToBlock(bEntry, fct);
87
88 // Reset alloca insert markers to this block
89 252 allocaInsertBlock = bEntry;
90 252 allocaInsertInst = nullptr;
91
92 // Allocate result variable
93
3/6
✓ Branch 68 → 69 taken 252 times.
✗ Branch 68 → 154 not taken.
✓ Branch 69 → 70 taken 252 times.
✗ Branch 69 → 151 not taken.
✓ Branch 70 → 71 taken 252 times.
✗ Branch 70 → 151 not taken.
252 llvm::Value *resultAddress = insertAlloca(QualType(TY_INT), RETURN_VARIABLE_NAME);
94 // Update the symbol table entry
95
1/2
✓ Branch 75 → 76 taken 252 times.
✗ Branch 75 → 160 not taken.
756 SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
96
1/2
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 252 times.
252 assert(resultEntry != nullptr);
97
1/2
✓ Branch 83 → 84 taken 252 times.
✗ Branch 83 → 183 not taken.
252 resultEntry->updateAddress(resultAddress);
98 // Generate debug info
99
2/4
✓ Branch 86 → 87 taken 252 times.
✗ Branch 86 → 166 not taken.
✓ Branch 87 → 88 taken 252 times.
✗ Branch 87 → 164 not taken.
504 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddress);
100 // Store the default result value
101
3/6
✓ Branch 90 → 91 taken 252 times.
✗ Branch 90 → 170 not taken.
✓ Branch 91 → 92 taken 252 times.
✗ Branch 91 → 170 not taken.
✓ Branch 92 → 93 taken 252 times.
✗ Branch 92 → 170 not taken.
252 insertStore(builder.getInt32(0), resultAddress, QualType(TY_INT));
102
103 // Store function argument values
104
3/4
✓ Branch 93 → 94 taken 252 times.
✗ Branch 93 → 174 not taken.
✓ Branch 110 → 96 taken 8 times.
✓ Branch 110 → 111 taken 252 times.
260 for (auto &arg : fct->args()) {
105 // Get information about the parameter
106 8 const size_t argNumber = arg.getArgNo();
107
2/4
✓ Branch 97 → 98 taken 8 times.
✗ Branch 97 → 173 not taken.
✓ Branch 98 → 99 taken 8 times.
✗ Branch 98 → 173 not taken.
8 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
108
1/2
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 103 taken 8 times.
8 assert(paramSymbol != nullptr);
109 // Allocate space for it
110
2/4
✓ Branch 103 → 104 taken 8 times.
✗ Branch 103 → 171 not taken.
✓ Branch 104 → 105 taken 8 times.
✗ Branch 104 → 171 not taken.
8 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
111 // Update the symbol table entry
112
1/2
✓ Branch 105 → 106 taken 8 times.
✗ Branch 105 → 171 not taken.
8 paramSymbol->updateAddress(paramAddress);
113 // Store the value at the new address
114
1/2
✓ Branch 106 → 107 taken 8 times.
✗ Branch 106 → 171 not taken.
8 insertStore(&arg, paramAddress);
115 // Generate debug info
116
1/2
✓ Branch 107 → 108 taken 8 times.
✗ Branch 107 → 171 not taken.
8 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
117 8 }
118
119 // Visit function body
120
1/2
✓ Branch 111 → 112 taken 252 times.
✗ Branch 111 → 175 not taken.
252 visit(node->body);
121
122 // Create return statement if the block is not terminated yet
123
2/2
✓ Branch 113 → 114 taken 249 times.
✓ Branch 113 → 123 taken 3 times.
252 if (!blockAlreadyTerminated) {
124
4/8
✓ Branch 116 → 117 taken 249 times.
✗ Branch 116 → 178 not taken.
✓ Branch 117 → 118 taken 249 times.
✗ Branch 117 → 176 not taken.
✓ Branch 118 → 119 taken 249 times.
✗ Branch 118 → 176 not taken.
✓ Branch 119 → 120 taken 249 times.
✗ Branch 119 → 176 not taken.
249 llvm::Value *result = insertLoad(fct->getReturnType(), resultEntry->getAddress());
125
1/2
✓ Branch 122 → 123 taken 249 times.
✗ Branch 122 → 183 not taken.
249 builder.CreateRet(result);
126 }
127
128 // Conclude debug info for function
129
1/2
✓ Branch 123 → 124 taken 252 times.
✗ Branch 123 → 183 not taken.
252 diGenerator.concludeFunctionDebugInfo();
130
131 // Verify function
132
1/2
✓ Branch 124 → 125 taken 252 times.
✗ Branch 124 → 183 not taken.
252 verifyFunction(fct, node->codeLoc);
133
134 // Change back to root scope
135 252 currentScope = rootScope;
136
1/2
✗ Branch 125 → 126 not taken.
✓ Branch 125 → 127 taken 252 times.
252 assert(currentScope != nullptr);
137
138
1/2
✓ Branch 127 → 128 taken 252 times.
✗ Branch 127 → 182 not taken.
252 return nullptr;
139 252 }
140
141 7651 std::any IRGenerator::visitFctDef(const FctDefNode *node) {
142 // Loop through manifestations
143 7651 manIdx = 0; // Reset the symbolTypeIndex
144
2/2
✓ Branch 208 → 4 taken 9480 times.
✓ Branch 208 → 209 taken 7651 times.
17131 for (Function *manifestation : node->manifestations) {
145
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 9480 times.
9480 assert(manifestation->entry != nullptr);
146
147 // Check if the manifestation is substantiated or not public and not used by anybody
148
2/4
✓ Branch 7 → 8 taken 9480 times.
✗ Branch 7 → 296 not taken.
✓ Branch 8 → 9 taken 9480 times.
✗ Branch 8 → 296 not taken.
9480 const bool isPublic = manifestation->entry->getQualType().isPublic();
149
9/10
✓ Branch 9 → 10 taken 9480 times.
✗ Branch 9 → 296 not taken.
✓ Branch 10 → 11 taken 7333 times.
✓ Branch 10 → 13 taken 2147 times.
✓ Branch 11 → 12 taken 185 times.
✓ Branch 11 → 14 taken 7148 times.
✓ Branch 12 → 13 taken 7 times.
✓ Branch 12 → 14 taken 178 times.
✓ Branch 15 → 16 taken 2154 times.
✓ Branch 15 → 17 taken 7326 times.
9480 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
150 2154 manIdx++; // Increment symbolTypeIndex
151 2154 continue;
152 }
153
154 // Change to struct scope
155
2/2
✓ Branch 20 → 21 taken 3337 times.
✓ Branch 20 → 29 taken 3989 times.
7326 if (manifestation->isMethod()) {
156 3337 const QualType &thisType = manifestation->thisType;
157
3/6
✓ Branch 21 → 22 taken 3337 times.
✗ Branch 21 → 216 not taken.
✓ Branch 22 → 23 taken 3337 times.
✗ Branch 22 → 216 not taken.
✓ Branch 23 → 24 taken 3337 times.
✗ Branch 23 → 216 not taken.
3337 const std::string scopeName = Struct::getScopeName(thisType.getSubType(), thisType.getTemplateTypes());
158
1/2
✓ Branch 24 → 25 taken 3337 times.
✗ Branch 24 → 214 not taken.
3337 currentScope = currentScope->getChildScope(scopeName);
159
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 3337 times.
3337 assert(currentScope != nullptr);
160 3337 }
161
162 // Change scope
163
2/4
✓ Branch 29 → 30 taken 7326 times.
✗ Branch 29 → 219 not taken.
✓ Branch 30 → 31 taken 7326 times.
✗ Branch 30 → 217 not taken.
7326 currentScope = currentScope->getChildScope(manifestation->getScopeName());
164
1/2
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 7326 times.
7326 assert(currentScope != nullptr);
165
166 // Get 'this' entry
167 7326 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
168 7326 std::vector<llvm::Type *> paramTypes;
169
1/2
✓ Branch 34 → 35 taken 7326 times.
✗ Branch 34 → 292 not taken.
7326 SymbolTableEntry *thisEntry = nullptr;
170
2/2
✓ Branch 37 → 38 taken 3337 times.
✓ Branch 37 → 52 taken 3989 times.
7326 if (manifestation->isMethod()) {
171
1/2
✓ Branch 40 → 41 taken 3337 times.
✗ Branch 40 → 222 not taken.
10011 thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
172
1/2
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 3337 times.
3337 assert(thisEntry != nullptr);
173
1/2
✓ Branch 48 → 49 taken 3337 times.
✗ Branch 48 → 292 not taken.
3337 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
174
2/4
✓ Branch 49 → 50 taken 3337 times.
✗ Branch 49 → 226 not taken.
✓ Branch 50 → 51 taken 3337 times.
✗ Branch 50 → 226 not taken.
3337 paramTypes.push_back(builder.getPtrTy());
175 }
176
177 // Visit parameters
178 7326 size_t argIdx = 0;
179
2/2
✓ Branch 52 → 53 taken 5790 times.
✓ Branch 52 → 82 taken 1536 times.
7326 if (node->hasParams) {
180 5790 const size_t numOfParams = manifestation->paramList.size();
181
1/2
✓ Branch 54 → 55 taken 5790 times.
✗ Branch 54 → 292 not taken.
5790 paramInfoList.reserve(numOfParams);
182
1/2
✓ Branch 55 → 56 taken 5790 times.
✗ Branch 55 → 292 not taken.
5790 paramTypes.reserve(numOfParams);
183
2/2
✓ Branch 81 → 57 taken 8744 times.
✓ Branch 81 → 82 taken 5790 times.
14534 for (; argIdx < numOfParams; argIdx++) {
184
1/2
✓ Branch 57 → 58 taken 8744 times.
✗ Branch 57 → 232 not taken.
8744 const DeclStmtNode *param = node->paramLst->params.at(argIdx);
185 // Get symbol table entry of param
186
1/2
✓ Branch 58 → 59 taken 8744 times.
✗ Branch 58 → 232 not taken.
8744 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
187
1/2
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 63 taken 8744 times.
8744 assert(paramSymbol != nullptr);
188
2/4
✓ Branch 63 → 64 taken 8744 times.
✗ Branch 63 → 229 not taken.
✓ Branch 64 → 65 taken 8744 times.
✗ Branch 64 → 227 not taken.
8744 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
189 // Pass the information if captures are taken for function/procedure types
190
6/10
✓ Branch 66 → 67 taken 8744 times.
✗ Branch 66 → 230 not taken.
✓ Branch 67 → 68 taken 3 times.
✓ Branch 67 → 71 taken 8741 times.
✓ Branch 68 → 69 taken 3 times.
✗ Branch 68 → 230 not taken.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 3 times.
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 77 taken 8744 times.
8744 if (paramSymbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramSymbolType.hasLambdaCaptures())
191 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
192 // Retrieve type of param
193
1/2
✓ Branch 77 → 78 taken 8744 times.
✗ Branch 77 → 232 not taken.
8744 llvm::Type *paramType = paramSymbolType.toLLVMType(sourceFile);
194 // Add it to the lists
195
1/2
✓ Branch 78 → 79 taken 8744 times.
✗ Branch 78 → 232 not taken.
8744 paramInfoList.emplace_back(param->varName, paramSymbol);
196
1/2
✓ Branch 79 → 80 taken 8744 times.
✗ Branch 79 → 232 not taken.
8744 paramTypes.push_back(paramType);
197 }
198 }
199
200 // Get return type
201
1/2
✓ Branch 82 → 83 taken 7326 times.
✗ Branch 82 → 292 not taken.
7326 llvm::Type *returnType = manifestation->returnType.toLLVMType(sourceFile);
202
203 // Get function linkage
204 7326 bool externalLinkage = isPublic;
205
12/18
✓ Branch 83 → 84 taken 378 times.
✓ Branch 83 → 90 taken 6948 times.
✓ Branch 86 → 87 taken 378 times.
✗ Branch 86 → 233 not taken.
✓ Branch 87 → 88 taken 378 times.
✗ Branch 87 → 233 not taken.
✓ Branch 88 → 89 taken 12 times.
✓ Branch 88 → 90 taken 366 times.
✓ Branch 91 → 92 taken 378 times.
✓ Branch 91 → 93 taken 6948 times.
✓ Branch 93 → 94 taken 378 times.
✓ Branch 93 → 96 taken 6948 times.
✓ Branch 96 → 97 taken 12 times.
✓ Branch 96 → 104 taken 7314 times.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 235 not taken.
✗ Branch 237 → 238 not taken.
✗ Branch 237 → 240 not taken.
8082 if (node->attrs && node->attrs->attrLst->hasAttr(ATTR_TEST))
206
2/4
✓ Branch 99 → 100 taken 12 times.
✗ Branch 99 → 244 not taken.
✓ Branch 100 → 101 taken 12 times.
✗ Branch 100 → 242 not taken.
36 externalLinkage |= node->attrs->attrLst->getAttrValueByName(ATTR_TEST)->boolValue;
207 7326 const llvm::GlobalValue::LinkageTypes linkage =
208
2/2
✓ Branch 104 → 105 taken 7158 times.
✓ Branch 104 → 106 taken 168 times.
7326 externalLinkage ? llvm::Function::ExternalLinkage : llvm::Function::PrivateLinkage;
209
210 // Create function or implement declared function
211
1/2
✓ Branch 107 → 108 taken 7326 times.
✗ Branch 107 → 292 not taken.
7326 const std::string mangledName = manifestation->getMangledName();
212
1/2
✓ Branch 109 → 110 taken 7326 times.
✗ Branch 109 → 248 not taken.
7326 llvm::FunctionType *funcType = llvm::FunctionType::get(returnType, paramTypes, false);
213
1/2
✓ Branch 111 → 112 taken 7326 times.
✗ Branch 111 → 249 not taken.
7326 module->getOrInsertFunction(mangledName, funcType);
214
1/2
✓ Branch 113 → 114 taken 7326 times.
✗ Branch 113 → 250 not taken.
7326 llvm::Function *func = module->getFunction(mangledName);
215
1/2
✓ Branch 114 → 115 taken 7326 times.
✗ Branch 114 → 290 not taken.
7326 node->entry->updateAddress(func);
216 7326 manifestation->llvmFunction = func;
217
2/4
✓ Branch 115 → 116 taken 7326 times.
✗ Branch 115 → 290 not taken.
✗ Branch 116 → 117 not taken.
✓ Branch 116 → 118 taken 7326 times.
7326 assert(func->empty());
218
219 // Set attributes to function
220 7326 func->setDSOLocal(true);
221
1/2
✓ Branch 119 → 120 taken 7326 times.
✗ Branch 119 → 290 not taken.
7326 func->setLinkage(linkage);
222
4/6
✓ Branch 120 → 121 taken 7326 times.
✗ Branch 120 → 290 not taken.
✓ Branch 121 → 122 taken 7326 times.
✗ Branch 121 → 290 not taken.
✓ Branch 122 → 123 taken 2485 times.
✓ Branch 122 → 124 taken 4841 times.
7326 if (manifestation->entry->getQualType().isInline())
223
1/2
✓ Branch 123 → 124 taken 2485 times.
✗ Branch 123 → 290 not taken.
2485 func->addFnAttr(llvm::Attribute::AlwaysInline);
224
1/2
✓ Branch 124 → 125 taken 7326 times.
✗ Branch 124 → 290 not taken.
7326 enableFunctionInstrumentation(func);
225 // Set attributes to function parameters and return value
226
1/2
✓ Branch 125 → 126 taken 7326 times.
✗ Branch 125 → 290 not taken.
7326 setParamAttrs(func, paramInfoList);
227
1/2
✓ Branch 126 → 127 taken 7326 times.
✗ Branch 126 → 290 not taken.
7326 setFunctionReturnValAttrs(func, manifestation->returnType);
228
229 // Add debug info
230
1/2
✓ Branch 127 → 128 taken 7326 times.
✗ Branch 127 → 290 not taken.
7326 diGenerator.generateFunctionDebugInfo(func, manifestation);
231
1/2
✓ Branch 128 → 129 taken 7326 times.
✗ Branch 128 → 290 not taken.
7326 diGenerator.setSourceLocation(node);
232
233 // Create entry block
234
2/4
✓ Branch 131 → 132 taken 7326 times.
✗ Branch 131 → 253 not taken.
✓ Branch 132 → 133 taken 7326 times.
✗ Branch 132 → 251 not taken.
7326 llvm::BasicBlock *bEntry = createBlock();
235
1/2
✓ Branch 135 → 136 taken 7326 times.
✗ Branch 135 → 290 not taken.
7326 switchToBlock(bEntry, func);
236
237 // Reset alloca insert markers to this block
238 7326 allocaInsertBlock = bEntry;
239 7326 allocaInsertInst = nullptr;
240
241 // Declare result variable
242
2/4
✓ Branch 138 → 139 taken 7326 times.
✗ Branch 138 → 259 not taken.
✓ Branch 139 → 140 taken 7326 times.
✗ Branch 139 → 257 not taken.
7326 llvm::Value *resultAddr = insertAlloca(manifestation->returnType, RETURN_VARIABLE_NAME);
243
1/2
✓ Branch 144 → 145 taken 7326 times.
✗ Branch 144 → 265 not taken.
21978 SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
244
1/2
✗ Branch 150 → 151 not taken.
✓ Branch 150 → 152 taken 7326 times.
7326 assert(resultEntry != nullptr);
245
1/2
✓ Branch 152 → 153 taken 7326 times.
✗ Branch 152 → 290 not taken.
7326 resultEntry->updateAddress(resultAddr);
246 // Generate debug info
247
2/4
✓ Branch 155 → 156 taken 7326 times.
✗ Branch 155 → 271 not taken.
✓ Branch 156 → 157 taken 7326 times.
✗ Branch 156 → 269 not taken.
14652 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddr);
248
249 // Store function argument values
250
3/4
✓ Branch 159 → 160 taken 7326 times.
✗ Branch 159 → 278 not taken.
✓ Branch 177 → 162 taken 12081 times.
✓ Branch 177 → 178 taken 7326 times.
19407 for (auto &arg : func->args()) {
251 // Get information about the parameter
252 12081 const size_t argNumber = arg.getArgNo();
253
2/4
✓ Branch 163 → 164 taken 12081 times.
✗ Branch 163 → 277 not taken.
✓ Branch 164 → 165 taken 12081 times.
✗ Branch 164 → 277 not taken.
12081 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
254
1/2
✗ Branch 167 → 168 not taken.
✓ Branch 167 → 169 taken 12081 times.
12081 assert(paramSymbol != nullptr);
255 // Allocate space for it
256
2/4
✓ Branch 169 → 170 taken 12081 times.
✗ Branch 169 → 275 not taken.
✓ Branch 170 → 171 taken 12081 times.
✗ Branch 170 → 275 not taken.
12081 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
257 // Update the symbol table entry
258
1/2
✓ Branch 171 → 172 taken 12081 times.
✗ Branch 171 → 275 not taken.
12081 paramSymbol->updateAddress(paramAddress);
259 // Set source location
260
1/2
✓ Branch 172 → 173 taken 12081 times.
✗ Branch 172 → 275 not taken.
12081 diGenerator.setSourceLocation(paramSymbol->declNode);
261 // Store the value at the new address
262
1/2
✓ Branch 173 → 174 taken 12081 times.
✗ Branch 173 → 275 not taken.
12081 insertStore(&arg, paramAddress);
263 // Generate debug info to declare variable
264
1/2
✓ Branch 174 → 175 taken 12081 times.
✗ Branch 174 → 275 not taken.
12081 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
265 12081 }
266
267 // Store the default values for optional function args
268
2/2
✓ Branch 178 → 179 taken 5790 times.
✓ Branch 178 → 189 taken 1536 times.
7326 if (node->paramLst) {
269
1/2
✓ Branch 179 → 180 taken 5790 times.
✗ Branch 179 → 282 not taken.
5790 const std::vector<DeclStmtNode *> params = node->paramLst->params;
270
2/2
✓ Branch 186 → 181 taken 609 times.
✓ Branch 186 → 187 taken 5790 times.
6399 for (; argIdx < params.size(); argIdx++)
271
2/4
✓ Branch 181 → 182 taken 609 times.
✗ Branch 181 → 279 not taken.
✓ Branch 182 → 183 taken 609 times.
✗ Branch 182 → 279 not taken.
609 visit(params.at(argIdx));
272 5790 }
273
274 // Visit function body
275
1/2
✓ Branch 189 → 190 taken 7326 times.
✗ Branch 189 → 283 not taken.
7326 visit(node->body);
276
277 // Create return statement if the block is not terminated yet
278
2/2
✓ Branch 191 → 192 taken 332 times.
✓ Branch 191 → 200 taken 6994 times.
7326 if (!blockAlreadyTerminated) {
279
3/6
✓ Branch 194 → 195 taken 332 times.
✗ Branch 194 → 286 not taken.
✓ Branch 195 → 196 taken 332 times.
✗ Branch 195 → 284 not taken.
✓ Branch 196 → 197 taken 332 times.
✗ Branch 196 → 284 not taken.
332 llvm::Value *result = insertLoad(returnType, resultEntry->getAddress());
280
1/2
✓ Branch 199 → 200 taken 332 times.
✗ Branch 199 → 290 not taken.
332 builder.CreateRet(result);
281 }
282
283 // Conclude debug info for function
284
1/2
✓ Branch 200 → 201 taken 7326 times.
✗ Branch 200 → 290 not taken.
7326 diGenerator.concludeFunctionDebugInfo();
285
286 // Verify function
287
1/2
✓ Branch 201 → 202 taken 7326 times.
✗ Branch 201 → 290 not taken.
7326 verifyFunction(func, node->codeLoc);
288
289 // Change to root scope
290 7326 currentScope = rootScope;
291
292 7326 manIdx++; // Increment symbolTypeIndex
293 7326 }
294 7651 manIdx = 0; // Reset the symbolTypeIndex
295
296 // Ensure that we are at the root scope again
297
1/2
✗ Branch 209 → 210 not taken.
✓ Branch 209 → 211 taken 7651 times.
7651 assert(currentScope == rootScope);
298
299
1/2
✓ Branch 211 → 212 taken 7651 times.
✗ Branch 211 → 298 not taken.
7651 return nullptr;
300 }
301
302 3929 std::any IRGenerator::visitProcDef(const ProcDefNode *node) {
303 // Loop through manifestations
304 3929 manIdx = 0; // Reset the symbolTypeIndex
305
2/2
✓ Branch 162 → 4 taken 5754 times.
✓ Branch 162 → 163 taken 3929 times.
9683 for (Function *manifestation : node->manifestations) {
306
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 5754 times.
5754 assert(manifestation->entry != nullptr);
307
308 // Check if the manifestation is substantiated or not public and not used by anybody
309
2/4
✓ Branch 7 → 8 taken 5754 times.
✗ Branch 7 → 212 not taken.
✓ Branch 8 → 9 taken 5754 times.
✗ Branch 8 → 212 not taken.
5754 const bool isPublic = manifestation->entry->getQualType().isPublic();
310
9/10
✓ Branch 9 → 10 taken 5754 times.
✗ Branch 9 → 212 not taken.
✓ Branch 10 → 11 taken 3775 times.
✓ Branch 10 → 13 taken 1979 times.
✓ Branch 11 → 12 taken 1047 times.
✓ Branch 11 → 14 taken 2728 times.
✓ Branch 12 → 13 taken 7 times.
✓ Branch 12 → 14 taken 1040 times.
✓ Branch 15 → 16 taken 1986 times.
✓ Branch 15 → 17 taken 3768 times.
5754 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
311 1986 manIdx++; // Increment symbolTypeIndex
312 1986 continue;
313 }
314
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 3768 times.
3768 assert(manifestation->alreadyTypeChecked);
315
316 // Change to struct scope
317
2/2
✓ Branch 22 → 23 taken 2748 times.
✓ Branch 22 → 31 taken 1020 times.
3768 if (manifestation->isMethod()) {
318 2748 const QualType &thisType = manifestation->thisType;
319
3/6
✓ Branch 23 → 24 taken 2748 times.
✗ Branch 23 → 170 not taken.
✓ Branch 24 → 25 taken 2748 times.
✗ Branch 24 → 170 not taken.
✓ Branch 25 → 26 taken 2748 times.
✗ Branch 25 → 170 not taken.
2748 const std::string scopeName = Struct::getScopeName(thisType.getSubType(), thisType.getTemplateTypes());
320
1/2
✓ Branch 26 → 27 taken 2748 times.
✗ Branch 26 → 168 not taken.
2748 currentScope = currentScope->getChildScope(scopeName);
321
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 2748 times.
2748 assert(currentScope != nullptr);
322 2748 }
323
324 // Change scope
325
2/4
✓ Branch 31 → 32 taken 3768 times.
✗ Branch 31 → 173 not taken.
✓ Branch 32 → 33 taken 3768 times.
✗ Branch 32 → 171 not taken.
3768 currentScope = currentScope->getChildScope(manifestation->getScopeName());
326
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 3768 times.
3768 assert(currentScope != nullptr);
327
328 // Get 'this' entry
329 3768 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
330
1/2
✓ Branch 36 → 37 taken 3768 times.
✗ Branch 36 → 208 not taken.
3768 std::vector<llvm::Type *> paramTypes;
331
2/2
✓ Branch 39 → 40 taken 2748 times.
✓ Branch 39 → 54 taken 1020 times.
3768 if (manifestation->isMethod()) {
332
1/2
✓ Branch 42 → 43 taken 2748 times.
✗ Branch 42 → 176 not taken.
8244 SymbolTableEntry *thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
333
1/2
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 2748 times.
2748 assert(thisEntry != nullptr);
334
1/2
✓ Branch 50 → 51 taken 2748 times.
✗ Branch 50 → 181 not taken.
2748 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
335
2/4
✓ Branch 51 → 52 taken 2748 times.
✗ Branch 51 → 180 not taken.
✓ Branch 52 → 53 taken 2748 times.
✗ Branch 52 → 180 not taken.
2748 paramTypes.push_back(builder.getPtrTy());
336 }
337
338 // Visit parameters
339 3768 size_t argIdx = 0;
340
2/2
✓ Branch 54 → 55 taken 2820 times.
✓ Branch 54 → 84 taken 948 times.
3768 if (node->hasParams) {
341 2820 const size_t numOfParams = manifestation->paramList.size();
342
1/2
✓ Branch 56 → 57 taken 2820 times.
✗ Branch 56 → 208 not taken.
2820 paramInfoList.reserve(numOfParams);
343
1/2
✓ Branch 57 → 58 taken 2820 times.
✗ Branch 57 → 208 not taken.
2820 paramTypes.reserve(numOfParams);
344
2/2
✓ Branch 83 → 59 taken 5124 times.
✓ Branch 83 → 84 taken 2820 times.
7944 for (; argIdx < numOfParams; argIdx++) {
345
1/2
✓ Branch 59 → 60 taken 5124 times.
✗ Branch 59 → 187 not taken.
5124 const DeclStmtNode *param = node->paramLst->params.at(argIdx);
346 // Get symbol table entry of param
347
1/2
✓ Branch 60 → 61 taken 5124 times.
✗ Branch 60 → 187 not taken.
5124 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
348
1/2
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 5124 times.
5124 assert(paramSymbol != nullptr);
349
2/4
✓ Branch 65 → 66 taken 5124 times.
✗ Branch 65 → 184 not taken.
✓ Branch 66 → 67 taken 5124 times.
✗ Branch 66 → 182 not taken.
5124 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
350 // Pass the information if captures are taken for function/procedure types
351
8/10
✓ Branch 68 → 69 taken 5124 times.
✗ Branch 68 → 185 not taken.
✓ Branch 69 → 70 taken 21 times.
✓ Branch 69 → 73 taken 5103 times.
✓ Branch 70 → 71 taken 21 times.
✗ Branch 70 → 185 not taken.
✓ Branch 71 → 72 taken 3 times.
✓ Branch 71 → 73 taken 18 times.
✓ Branch 74 → 75 taken 3 times.
✓ Branch 74 → 79 taken 5121 times.
5124 if (paramSymbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramSymbolType.hasLambdaCaptures())
352
3/6
✓ Branch 75 → 76 taken 3 times.
✗ Branch 75 → 186 not taken.
✓ Branch 76 → 77 taken 3 times.
✗ Branch 76 → 186 not taken.
✓ Branch 77 → 78 taken 3 times.
✗ Branch 77 → 186 not taken.
3 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
353 // Retrieve type of param
354
1/2
✓ Branch 79 → 80 taken 5124 times.
✗ Branch 79 → 187 not taken.
5124 llvm::Type *paramType = paramSymbolType.toLLVMType(sourceFile);
355 // Add it to the lists
356
1/2
✓ Branch 80 → 81 taken 5124 times.
✗ Branch 80 → 187 not taken.
5124 paramInfoList.emplace_back(param->varName, paramSymbol);
357
1/2
✓ Branch 81 → 82 taken 5124 times.
✗ Branch 81 → 187 not taken.
5124 paramTypes.push_back(paramType);
358 }
359 }
360
361 // Get return type
362
1/2
✓ Branch 84 → 85 taken 3768 times.
✗ Branch 84 → 208 not taken.
3768 llvm::Type *returnType = builder.getVoidTy();
363
364 // Get procedure linkage
365
2/2
✓ Branch 85 → 86 taken 2728 times.
✓ Branch 85 → 87 taken 1040 times.
3768 const llvm::GlobalValue::LinkageTypes linkage = isPublic ? llvm::Function::ExternalLinkage : llvm::Function::PrivateLinkage;
366
367 // Create procedure or implement declared procedure
368
1/2
✓ Branch 88 → 89 taken 3768 times.
✗ Branch 88 → 208 not taken.
3768 const std::string mangledName = manifestation->getMangledName();
369
1/2
✓ Branch 90 → 91 taken 3768 times.
✗ Branch 90 → 188 not taken.
3768 llvm::FunctionType *procType = llvm::FunctionType::get(returnType, paramTypes, false);
370
1/2
✓ Branch 92 → 93 taken 3768 times.
✗ Branch 92 → 189 not taken.
3768 module->getOrInsertFunction(mangledName, procType);
371
1/2
✓ Branch 94 → 95 taken 3768 times.
✗ Branch 94 → 190 not taken.
3768 llvm::Function *proc = module->getFunction(mangledName);
372
1/2
✓ Branch 95 → 96 taken 3768 times.
✗ Branch 95 → 206 not taken.
3768 node->entry->updateAddress(proc);
373 3768 manifestation->llvmFunction = proc;
374
2/4
✓ Branch 96 → 97 taken 3768 times.
✗ Branch 96 → 206 not taken.
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 99 taken 3768 times.
3768 assert(proc->empty());
375
376 // Set attributes to procedure
377 3768 proc->setDSOLocal(true);
378
1/2
✓ Branch 100 → 101 taken 3768 times.
✗ Branch 100 → 206 not taken.
3768 proc->setLinkage(linkage);
379
4/6
✓ Branch 101 → 102 taken 3768 times.
✗ Branch 101 → 206 not taken.
✓ Branch 102 → 103 taken 3768 times.
✗ Branch 102 → 206 not taken.
✓ Branch 103 → 104 taken 306 times.
✓ Branch 103 → 105 taken 3462 times.
3768 if (manifestation->entry->getQualType().isInline())
380
1/2
✓ Branch 104 → 105 taken 306 times.
✗ Branch 104 → 206 not taken.
306 proc->addFnAttr(llvm::Attribute::AlwaysInline);
381
1/2
✓ Branch 105 → 106 taken 3768 times.
✗ Branch 105 → 206 not taken.
3768 enableFunctionInstrumentation(proc);
382
383 // Set attributes to function parameters
384
1/2
✓ Branch 106 → 107 taken 3768 times.
✗ Branch 106 → 206 not taken.
3768 setParamAttrs(proc, paramInfoList);
385
386 // Add debug info
387
1/2
✓ Branch 107 → 108 taken 3768 times.
✗ Branch 107 → 206 not taken.
3768 diGenerator.generateFunctionDebugInfo(proc, manifestation);
388
1/2
✓ Branch 108 → 109 taken 3768 times.
✗ Branch 108 → 206 not taken.
3768 diGenerator.setSourceLocation(node);
389
390 // Create entry block
391
2/4
✓ Branch 111 → 112 taken 3768 times.
✗ Branch 111 → 193 not taken.
✓ Branch 112 → 113 taken 3768 times.
✗ Branch 112 → 191 not taken.
3768 llvm::BasicBlock *bEntry = createBlock();
392
1/2
✓ Branch 115 → 116 taken 3768 times.
✗ Branch 115 → 206 not taken.
3768 switchToBlock(bEntry, proc);
393
394 // Reset alloca insert markers to this block
395 3768 allocaInsertBlock = bEntry;
396 3768 allocaInsertInst = nullptr;
397
398 // Store procedure argument values
399
3/4
✓ Branch 116 → 117 taken 3768 times.
✗ Branch 116 → 200 not taken.
✓ Branch 134 → 119 taken 7872 times.
✓ Branch 134 → 135 taken 3768 times.
11640 for (auto &arg : proc->args()) {
400 // Get information about the parameter
401 7872 const size_t argNumber = arg.getArgNo();
402
2/4
✓ Branch 120 → 121 taken 7872 times.
✗ Branch 120 → 199 not taken.
✓ Branch 121 → 122 taken 7872 times.
✗ Branch 121 → 199 not taken.
7872 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
403
1/2
✗ Branch 124 → 125 not taken.
✓ Branch 124 → 126 taken 7872 times.
7872 assert(paramSymbol != nullptr);
404 // Allocate space for it
405
2/4
✓ Branch 126 → 127 taken 7872 times.
✗ Branch 126 → 197 not taken.
✓ Branch 127 → 128 taken 7872 times.
✗ Branch 127 → 197 not taken.
7872 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
406 // Update the symbol table entry
407
1/2
✓ Branch 128 → 129 taken 7872 times.
✗ Branch 128 → 197 not taken.
7872 paramSymbol->updateAddress(paramAddress);
408 // Set source location
409
1/2
✓ Branch 129 → 130 taken 7872 times.
✗ Branch 129 → 197 not taken.
7872 diGenerator.setSourceLocation(paramSymbol->declNode);
410 // Store the value at the new address
411
1/2
✓ Branch 130 → 131 taken 7872 times.
✗ Branch 130 → 197 not taken.
7872 insertStore(&arg, paramAddress);
412 // Generate debug info to declare variable
413
1/2
✓ Branch 131 → 132 taken 7872 times.
✗ Branch 131 → 197 not taken.
7872 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
414 7872 }
415
416 // Store the default values for optional procedure args
417
2/2
✓ Branch 135 → 136 taken 2820 times.
✓ Branch 135 → 146 taken 948 times.
3768 if (node->paramLst) {
418
1/2
✓ Branch 136 → 137 taken 2820 times.
✗ Branch 136 → 204 not taken.
2820 const std::vector<DeclStmtNode *> params = node->paramLst->params;
419
2/2
✓ Branch 143 → 138 taken 194 times.
✓ Branch 143 → 144 taken 2820 times.
3014 for (; argIdx < params.size(); argIdx++)
420
2/4
✓ Branch 138 → 139 taken 194 times.
✗ Branch 138 → 201 not taken.
✓ Branch 139 → 140 taken 194 times.
✗ Branch 139 → 201 not taken.
194 visit(params.at(argIdx));
421 2820 }
422
423 // Generate special ctor preamble before generating the body to store VTable, default field values, etc. if required
424
2/2
✓ Branch 146 → 147 taken 1288 times.
✓ Branch 146 → 148 taken 2480 times.
3768 if (node->isCtor) {
425 1288 isInCtorBody = true;
426
1/2
✓ Branch 147 → 148 taken 1288 times.
✗ Branch 147 → 206 not taken.
1288 generateCtorBodyPreamble(currentScope);
427 }
428
429 // Visit procedure body
430
1/2
✓ Branch 148 → 149 taken 3768 times.
✗ Branch 148 → 205 not taken.
3768 visit(node->body);
431
432
2/2
✓ Branch 150 → 151 taken 1288 times.
✓ Branch 150 → 152 taken 2480 times.
3768 if (node->isCtor)
433 1288 isInCtorBody = false;
434
435 // Create return statement if the block is not terminated yet
436
2/2
✓ Branch 152 → 153 taken 3667 times.
✓ Branch 152 → 154 taken 101 times.
3768 if (!blockAlreadyTerminated)
437
1/2
✓ Branch 153 → 154 taken 3667 times.
✗ Branch 153 → 206 not taken.
3667 builder.CreateRetVoid();
438
439 // Conclude debug info for procedure
440
1/2
✓ Branch 154 → 155 taken 3768 times.
✗ Branch 154 → 206 not taken.
3768 diGenerator.concludeFunctionDebugInfo();
441
442 // Verify procedure
443
1/2
✓ Branch 155 → 156 taken 3768 times.
✗ Branch 155 → 206 not taken.
3768 verifyFunction(proc, node->codeLoc);
444
445 // Change to root scope
446 3768 currentScope = rootScope;
447
448 3768 manIdx++; // Increment symbolTypeIndex
449 3768 }
450 3929 manIdx = 0; // Reset the symbolTypeIndex
451
452 // Ensure that we are at the root scope again
453
1/2
✗ Branch 163 → 164 not taken.
✓ Branch 163 → 165 taken 3929 times.
3929 assert(currentScope == rootScope);
454
455
1/2
✓ Branch 165 → 166 taken 3929 times.
✗ Branch 165 → 214 not taken.
3929 return nullptr;
456 }
457
458 11094 void IRGenerator::setParamAttrs(llvm::Function *function, const ParamInfoList &paramInfo) const {
459
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 11094 times.
11094 assert(function->arg_size() == paramInfo.size());
460
2/2
✓ Branch 30 → 7 taken 19953 times.
✓ Branch 30 → 31 taken 11094 times.
31047 for (size_t i = 0; i < paramInfo.size(); i++) {
461 19953 const QualType &paramType = paramInfo.at(i).second->getQualType();
462
463 // NoUndef attribute
464 19953 function->addParamAttr(i, llvm::Attribute::NoUndef);
465
466
2/2
✓ Branch 11 → 12 taken 6456 times.
✓ Branch 11 → 25 taken 13497 times.
19953 if (paramType.isPtr()) {
467 // NonNull attribute
468 6456 function->addParamAttr(i, llvm::Attribute::NonNull);
469 // Dereferenceable attribute
470
2/4
✓ Branch 13 → 14 taken 6456 times.
✗ Branch 13 → 32 not taken.
✓ Branch 14 → 15 taken 6456 times.
✗ Branch 14 → 32 not taken.
6456 llvm::Type *pointeeType = paramType.getContained().toLLVMType(sourceFile);
471
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 6456 times.
6456 assert(pointeeType != nullptr);
472
3/6
✓ Branch 18 → 19 taken 6456 times.
✗ Branch 18 → 33 not taken.
✓ Branch 19 → 20 taken 6456 times.
✗ Branch 19 → 33 not taken.
✓ Branch 20 → 21 taken 6456 times.
✗ Branch 20 → 33 not taken.
6456 function->addDereferenceableParamAttr(i, module->getDataLayout().getTypeStoreSize(pointeeType));
473 // Alignment attribute
474 6456 function->addParamAttr(i, llvm::Attribute::getWithAlignment(context, module->getDataLayout().getABITypeAlign(pointeeType)));
475 }
476
477 // ZExt or SExt attribute
478
2/2
✓ Branch 26 → 27 taken 3839 times.
✓ Branch 26 → 28 taken 16114 times.
19953 if (const llvm::Attribute::AttrKind extAttrKind = getExtAttrKindForType(paramType); extAttrKind != llvm::Attribute::None)
479 3839 function->addParamAttr(i, extAttrKind);
480 }
481 11094 }
482
483 7326 void IRGenerator::setFunctionReturnValAttrs(llvm::Function *function, const QualType &returnType) const {
484
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 7326 times.
7326 if (returnType.is(TY_DYN))
485 return;
486
487 // NoUndef attribute
488 7326 function->addRetAttr(llvm::Attribute::NoUndef);
489 // ZExt or SExt attribute
490
2/2
✓ Branch 7 → 8 taken 3375 times.
✓ Branch 7 → 9 taken 3951 times.
7326 if (const llvm::Attribute::AttrKind extAttrKind = getExtAttrKindForType(returnType); extAttrKind != llvm::Attribute::None)
491 3375 function->addRetAttr(extAttrKind);
492 }
493
494 68985 llvm::Attribute::AttrKind IRGenerator::getExtAttrKindForType(const QualType &type) const {
495
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 68985 times.
68985 if (type.is(TY_DYN))
496 return llvm::Attribute::None;
497
498 68985 const llvm::Type *llvmType = type.toLLVMType(sourceFile);
499
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 68985 times.
68985 const unsigned int maxExtWidth = cliOptions.targetTriple.isPPC() ? 64 : 32;
500
6/6
✓ Branch 11 → 12 taken 31170 times.
✓ Branch 11 → 15 taken 37815 times.
✓ Branch 13 → 14 taken 15986 times.
✓ Branch 13 → 15 taken 15184 times.
✓ Branch 16 → 17 taken 15986 times.
✓ Branch 16 → 22 taken 52999 times.
68985 if (llvmType->isIntegerTy() && llvmType->getIntegerBitWidth() < maxExtWidth)
501
2/2
✓ Branch 18 → 19 taken 1708 times.
✓ Branch 18 → 20 taken 14278 times.
15986 return type.isSigned() ? llvm::Attribute::SExt : llvm::Attribute::ZExt;
502 52999 return llvm::Attribute::None;
503 }
504
505 626 std::any IRGenerator::visitStructDef(const StructDefNode *node) {
506 // Get all substantiated structs which result from this struct def
507
1/2
✓ Branch 2 → 3 taken 626 times.
✗ Branch 2 → 115 not taken.
626 std::vector<Struct *> manifestations = node->structManifestations;
508
509 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
510 908 const auto comp = [](const Struct *lhs, const Struct *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
511
1/2
✓ Branch 3 → 4 taken 626 times.
✗ Branch 3 → 113 not taken.
626 std::ranges::sort(manifestations, comp);
512
513
2/2
✓ Branch 71 → 6 taken 1080 times.
✓ Branch 71 → 72 taken 626 times.
1706 for (Struct *spiceStruct : manifestations) {
514 // Skip structs, that are not fully substantiated
515
3/4
✓ Branch 7 → 8 taken 1080 times.
✗ Branch 7 → 110 not taken.
✓ Branch 8 → 9 taken 304 times.
✓ Branch 8 → 10 taken 776 times.
1080 if (!spiceStruct->isFullySubstantiated())
516 305 continue;
517
518 // Do not generate this struct if it is private and used by nobody
519
8/10
✓ Branch 10 → 11 taken 6 times.
✓ Branch 10 → 15 taken 770 times.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 110 not taken.
✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 110 not taken.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 5 times.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 775 times.
776 if (!spiceStruct->used && !spiceStruct->entry->getQualType().isPublic())
520 1 continue;
521
522 // Change scope to struct scope, specific to substantiation
523 775 currentScope = spiceStruct->scope;
524
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 775 times.
775 assert(currentScope);
525
526 // Set LLVM type to the struct entry
527 775 const SymbolTableEntry *structEntry = spiceStruct->entry;
528
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 775 times.
775 assert(structEntry != nullptr);
529
530 // Generate VTable if required
531
2/2
✓ Branch 22 → 23 taken 211 times.
✓ Branch 22 → 26 taken 564 times.
775 if (node->emitVTable) {
532
1/2
✓ Branch 23 → 24 taken 211 times.
✗ Branch 23 → 110 not taken.
211 generateVTable(spiceStruct);
533
1/2
✓ Branch 24 → 25 taken 211 times.
✗ Branch 24 → 76 not taken.
422 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceStruct); }, false);
534 }
535
536 // Generate default ctor if required
537
1/2
✓ Branch 26 → 27 taken 775 times.
✗ Branch 26 → 110 not taken.
775 const QualType &thisType = structEntry->getQualType();
538
2/4
✓ Branch 30 → 31 taken 775 times.
✗ Branch 30 → 80 not taken.
✓ Branch 31 → 32 taken 775 times.
✗ Branch 31 → 78 not taken.
2325 const Function *ctorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, {}, true);
539
4/4
✓ Branch 35 → 36 taken 311 times.
✓ Branch 35 → 38 taken 464 times.
✓ Branch 36 → 37 taken 39 times.
✓ Branch 36 → 38 taken 272 times.
775 if (ctorFunc != nullptr && ctorFunc->implicitDefault)
540
1/2
✓ Branch 37 → 38 taken 39 times.
✗ Branch 37 → 110 not taken.
39 generateDefaultCtor(ctorFunc);
541
542 // Generate default copy ctor if required
543
2/4
✓ Branch 38 → 39 taken 775 times.
✗ Branch 38 → 91 not taken.
✓ Branch 42 → 43 taken 775 times.
✗ Branch 42 → 87 not taken.
2325 const ArgList args = {{thisType.toConstRef(node), false /* always non-temporary */}};
544
2/4
✓ Branch 46 → 47 taken 775 times.
✗ Branch 46 → 95 not taken.
✓ Branch 47 → 48 taken 775 times.
✗ Branch 47 → 93 not taken.
775 const Function *copyCtorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, args, true);
545
4/4
✓ Branch 50 → 51 taken 210 times.
✓ Branch 50 → 53 taken 565 times.
✓ Branch 51 → 52 taken 97 times.
✓ Branch 51 → 53 taken 113 times.
775 if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault)
546
1/2
✓ Branch 52 → 53 taken 97 times.
✗ Branch 52 → 108 not taken.
97 generateDefaultCopyCtor(copyCtorFunc);
547
548 // Generate default dtor if required
549
2/4
✓ Branch 56 → 57 taken 775 times.
✗ Branch 56 → 101 not taken.
✓ Branch 57 → 58 taken 775 times.
✗ Branch 57 → 99 not taken.
2325 const Function *dtorFunc = FunctionManager::lookup(currentScope, DTOR_FUNCTION_NAME, thisType, {}, true);
550
4/4
✓ Branch 61 → 62 taken 221 times.
✓ Branch 61 → 64 taken 554 times.
✓ Branch 62 → 63 taken 113 times.
✓ Branch 62 → 64 taken 108 times.
775 if (dtorFunc != nullptr && dtorFunc->implicitDefault)
551
1/2
✓ Branch 63 → 64 taken 113 times.
✗ Branch 63 → 108 not taken.
113 generateDefaultDtor(dtorFunc);
552
553 // Return to root scope
554 775 currentScope = rootScope;
555
1/2
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 66 taken 775 times.
775 assert(currentScope);
556 775 }
557
558
1/2
✓ Branch 72 → 73 taken 626 times.
✗ Branch 72 → 112 not taken.
1252 return nullptr;
559 626 }
560
561 88 std::any IRGenerator::visitInterfaceDef(const InterfaceDefNode *node) {
562 // Get all substantiated structs which result from this struct def
563
1/2
✓ Branch 2 → 3 taken 88 times.
✗ Branch 2 → 34 not taken.
88 std::vector<Interface *> manifestations = node->interfaceManifestations;
564
565 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
566 318 const auto comp = [](const Interface *lhs, const Interface *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
567
1/2
✓ Branch 3 → 4 taken 88 times.
✗ Branch 3 → 32 not taken.
88 std::ranges::sort(manifestations, comp);
568
569
2/2
✓ Branch 23 → 6 taken 247 times.
✓ Branch 23 → 24 taken 88 times.
335 for (Interface *spiceInterface : manifestations) {
570 // Skip interfaces, that are not fully substantiated
571
3/4
✓ Branch 7 → 8 taken 247 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 71 times.
✓ Branch 8 → 10 taken 176 times.
247 if (!spiceInterface->isFullySubstantiated())
572 71 continue;
573
574 // Do not generate this interface if it is private and used by nobody
575
7/10
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 15 taken 175 times.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 30 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 30 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 15 not taken.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 175 times.
176 if (!spiceInterface->used && !spiceInterface->entry->getQualType().isPublic())
576 1 continue;
577
578 // Generate VTable information
579
1/2
✓ Branch 18 → 19 taken 175 times.
✗ Branch 18 → 30 not taken.
175 generateVTable(spiceInterface);
580
1/2
✓ Branch 19 → 20 taken 175 times.
✗ Branch 19 → 28 not taken.
350 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceInterface); }, false);
581 }
582
583
1/2
✓ Branch 24 → 25 taken 88 times.
✗ Branch 24 → 31 not taken.
176 return nullptr;
584 88 }
585
586 64 std::any IRGenerator::visitEnumDef(const EnumDefNode *node) {
587
1/2
✓ Branch 2 → 3 taken 64 times.
✗ Branch 2 → 5 not taken.
64 return nullptr; // Noop (enums are high-level semantic-only structures)
588 }
589
590 900 std::any IRGenerator::visitGenericTypeDef(const GenericTypeDefNode *node) {
591
1/2
✓ Branch 2 → 3 taken 900 times.
✗ Branch 2 → 5 not taken.
900 return nullptr; // Noop (generic types are high-level semantic-only structures)
592 }
593
594 68 std::any IRGenerator::visitAliasDef(const AliasDefNode *node) {
595
1/2
✓ Branch 2 → 3 taken 68 times.
✗ Branch 2 → 5 not taken.
68 return nullptr; // Noop (alias definitions are high-level semantic-only structures)
596 }
597
598 1167 std::any IRGenerator::visitGlobalVarDef(const GlobalVarDefNode *node) {
599 // Retrieve some information about the variable
600
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1167 times.
1167 assert(node->entry != nullptr);
601 1167 const QualType &entryType = node->entry->getQualType();
602 1167 const bool isPublic = entryType.isPublic();
603 1167 const bool isConst = entryType.isConst();
604
605 // Get correct type and linkage type
606
2/4
✓ Branch 7 → 8 taken 1167 times.
✗ Branch 7 → 39 not taken.
✓ Branch 8 → 9 taken 1167 times.
✗ Branch 8 → 37 not taken.
1167 const auto varType = std::any_cast<llvm::Type *>(visit(node->dataType));
607
2/2
✓ Branch 10 → 11 taken 611 times.
✓ Branch 10 → 12 taken 556 times.
1167 const auto linkage = isPublic ? llvm::GlobalValue::ExternalLinkage : llvm::GlobalValue::PrivateLinkage;
608
609 // Create global var
610
1/2
✓ Branch 14 → 15 taken 1167 times.
✗ Branch 14 → 40 not taken.
1167 llvm::Value *varAddress = module->getOrInsertGlobal(node->varName, varType);
611
1/2
✓ Branch 16 → 17 taken 1167 times.
✗ Branch 16 → 41 not taken.
1167 llvm::GlobalVariable *var = module->getNamedGlobal(node->varName);
612 // Set some attributes, based on the given information
613 1167 var->setLinkage(linkage);
614 1167 var->setConstant(isConst);
615 1167 var->setDSOLocal(true);
616
617 // Set initializer
618
1/2
✓ Branch 20 → 21 taken 1167 times.
✗ Branch 20 → 25 not taken.
1167 if (node->hasValue) { // Set the constant value as variable initializer
619
2/4
✓ Branch 21 → 22 taken 1167 times.
✗ Branch 21 → 44 not taken.
✓ Branch 22 → 23 taken 1167 times.
✗ Branch 22 → 42 not taken.
1167 const auto constantValue = std::any_cast<llvm::Constant *>(visit(node->constant));
620 1167 var->setInitializer(constantValue);
621 } else if (cliOptions.buildMode != BuildMode::RELEASE) { // Set the default value as variable initializer
622 assert(cliOptions.buildMode == BuildMode::DEBUG || cliOptions.buildMode == BuildMode::TEST);
623 llvm::Constant *constantValue = getDefaultValueForSymbolType(node->entry->getQualType());
624 var->setInitializer(constantValue);
625 }
626
627 1167 node->entry->updateAddress(varAddress);
628
629 // Add debug info
630 1167 diGenerator.generateGlobalVarDebugInfo(var, node->entry);
631
632
1/2
✓ Branch 34 → 35 taken 1167 times.
✗ Branch 34 → 45 not taken.
1167 return nullptr;
633 }
634
635 996 std::any IRGenerator::visitExtDecl(const ExtDeclNode *node) {
636 // Get return type
637 996 const Function *spiceFunc = node->extFunction;
638
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 996 times.
996 assert(spiceFunc != nullptr);
639
1/2
✓ Branch 4 → 5 taken 996 times.
✗ Branch 4 → 91 not taken.
996 llvm::Type *returnType = builder.getVoidTy();
640
3/4
✓ Branch 5 → 6 taken 996 times.
✗ Branch 5 → 91 not taken.
✓ Branch 6 → 7 taken 656 times.
✓ Branch 6 → 9 taken 340 times.
996 if (!spiceFunc->returnType.is(TY_DYN))
641
1/2
✓ Branch 7 → 8 taken 656 times.
✗ Branch 7 → 91 not taken.
656 returnType = spiceFunc->returnType.toLLVMType(sourceFile);
642
643 // Get arg types
644 996 std::vector<llvm::Type *> argTypes;
645
1/2
✓ Branch 10 → 11 taken 996 times.
✗ Branch 10 → 89 not taken.
996 argTypes.reserve(spiceFunc->paramList.size());
646
3/4
✓ Branch 11 → 12 taken 996 times.
✗ Branch 11 → 67 not taken.
✓ Branch 19 → 14 taken 1955 times.
✓ Branch 19 → 20 taken 996 times.
2951 for (const QualType &paramType : spiceFunc->getParamTypes())
647
2/4
✓ Branch 15 → 16 taken 1955 times.
✗ Branch 15 → 64 not taken.
✓ Branch 16 → 17 taken 1955 times.
✗ Branch 16 → 64 not taken.
2951 argTypes.push_back(paramType.toLLVMType(sourceFile));
648
649 // Declare function
650
4/4
✓ Branch 21 → 22 taken 955 times.
✓ Branch 21 → 24 taken 41 times.
✓ Branch 22 → 23 taken 17 times.
✓ Branch 22 → 24 taken 938 times.
996 const bool isVarArg = node->argTypeLst && node->argTypeLst->hasEllipsis;
651
1/2
✓ Branch 26 → 27 taken 996 times.
✗ Branch 26 → 68 not taken.
996 llvm::FunctionType *functionType = llvm::FunctionType::get(returnType, argTypes, isVarArg);
652
1/2
✓ Branch 27 → 28 taken 996 times.
✗ Branch 27 → 89 not taken.
996 const std::string mangledName = spiceFunc->getMangledName();
653
1/2
✓ Branch 29 → 30 taken 996 times.
✗ Branch 29 → 69 not taken.
996 module->getOrInsertFunction(mangledName, functionType);
654
1/2
✓ Branch 31 → 32 taken 996 times.
✗ Branch 31 → 70 not taken.
996 llvm::Function *fct = module->getFunction(mangledName);
655
656 // Add noundef attribute to all parameters
657
2/2
✓ Branch 36 → 33 taken 1955 times.
✓ Branch 36 → 37 taken 996 times.
2951 for (size_t i = 0; i < argTypes.size(); i++)
658
1/2
✓ Branch 33 → 34 taken 1955 times.
✗ Branch 33 → 87 not taken.
1955 fct->addParamAttr(i, llvm::Attribute::NoUndef);
659
660 // If the function should be imported as dll, add the dll attribute
661
10/18
✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 44 taken 995 times.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 71 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 71 not taken.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 1 time.
✓ Branch 45 → 46 taken 1 time.
✓ Branch 45 → 47 taken 995 times.
✓ Branch 47 → 48 taken 1 time.
✓ Branch 47 → 50 taken 995 times.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 59 taken 996 times.
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 73 not taken.
✗ Branch 75 → 76 not taken.
✗ Branch 75 → 78 not taken.
998 if (node->attrs && node->attrs->attrLst->hasAttr(ATTR_CORE_LINKER_DLL))
662 if (node->attrs->attrLst->getAttrValueByName(ATTR_CORE_LINKER_DLL)->boolValue)
663 fct->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
664
665
1/2
✓ Branch 59 → 60 taken 996 times.
✗ Branch 59 → 86 not taken.
1992 return nullptr;
666 996 }
667
668 } // namespace spice::compiler
669