GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.8% 387 / 0 / 400
Functions: 100.0% 19 / 0 / 19
Branches: 58.1% 464 / 0 / 798

src/irgenerator/GenTopLevelDefinitions.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <ast/Attributes.h>
8 #include <driver/Driver.h>
9 #include <symboltablebuilder/SymbolTableBuilder.h>
10 #include <typechecker/FunctionManager.h>
11
12 #include <llvm/IR/Module.h>
13 #include <llvm/Target/TargetLoweringObjectFile.h>
14
15 namespace spice::compiler {
16
17 409 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 → 6 taken 409 times.
409 if (!sourceFile->isMainFile)
20 return nullptr;
21
22 // Do not generate main function if it is explicitly specified
23
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 10 taken 408 times.
409 if (cliOptions.noEntryFct)
24
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 144 not taken.
2 return nullptr;
25
26 // Change scope to function scope
27 408 currentScope = node->bodyScope;
28
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 408 times.
408 assert(currentScope != nullptr);
29
30 // Visit parameters
31 408 std::vector<std::pair<std::string, const SymbolTableEntry *>> paramInfoList;
32 408 QualTypeList paramSymbolTypes;
33 408 std::vector<llvm::Type *> paramTypes;
34
2/2
✓ Branch 12 → 13 taken 7 times.
✓ Branch 12 → 42 taken 401 times.
408 if (node->takesArgs) {
35 7 const size_t numOfParams = node->paramLst->params.size();
36
1/2
✓ Branch 14 → 15 taken 7 times.
✗ Branch 14 → 195 not taken.
7 paramInfoList.reserve(numOfParams);
37
1/2
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 195 not taken.
7 paramSymbolTypes.reserve(numOfParams);
38
1/2
✓ Branch 16 → 17 taken 7 times.
✗ Branch 16 → 195 not taken.
7 paramTypes.reserve(numOfParams);
39
2/2
✓ Branch 40 → 19 taken 14 times.
✓ Branch 40 → 41 taken 7 times.
28 for (DeclStmtNode *param : node->paramLst->params) {
40 // Get symbol table entry of param
41
1/2
✓ Branch 21 → 22 taken 14 times.
✗ Branch 21 → 146 not taken.
14 const SymbolTableEntry *paramSymbol = node->bodyScope->lookupStrict(param->varName);
42
1/2
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 14 times.
14 assert(paramSymbol != nullptr);
43 // Retrieve type of param
44
1/2
✓ Branch 26 → 27 taken 14 times.
✗ Branch 26 → 146 not taken.
14 const QualType paramSymbolType = paramSymbol->getQualType();
45 // Add it to the lists
46
1/2
✓ Branch 27 → 28 taken 14 times.
✗ Branch 27 → 146 not taken.
14 paramInfoList.emplace_back(param->varName, paramSymbol);
47
1/2
✓ Branch 28 → 29 taken 14 times.
✗ Branch 28 → 146 not taken.
14 paramSymbolTypes.push_back(paramSymbolType);
48
2/4
✓ Branch 29 → 30 taken 14 times.
✗ Branch 29 → 145 not taken.
✓ Branch 30 → 31 taken 14 times.
✗ Branch 30 → 145 not taken.
14 paramTypes.push_back(paramSymbolType.getParamLLVMType(sourceFile));
49 }
50 }
51
52 // Build the function
53
1/2
✓ Branch 42 → 43 taken 408 times.
✗ Branch 42 → 195 not taken.
408 llvm::Type *returnType = builder.getInt32Ty();
54
1/2
✓ Branch 44 → 45 taken 408 times.
✗ Branch 44 → 148 not taken.
408 llvm::FunctionType *fctType = llvm::FunctionType::get(returnType, paramTypes, false);
55
2/4
✓ Branch 45 → 46 taken 408 times.
✗ Branch 45 → 149 not taken.
✓ Branch 46 → 47 taken 408 times.
✗ Branch 46 → 149 not taken.
408 llvm::Function *fct = llvm::Function::Create(fctType, llvm::Function::ExternalLinkage, MAIN_FUNCTION_NAME, module);
56 408 fct->setDSOLocal(true);
57
58 // Add function attributes. The main function is the entry point, so nobody can call or inline it.
59
1/2
✓ Branch 48 → 49 taken 408 times.
✗ Branch 48 → 195 not taken.
408 fct->addFnAttr(llvm::Attribute::MustProgress);
60
1/2
✓ Branch 49 → 50 taken 408 times.
✗ Branch 49 → 195 not taken.
408 fct->addFnAttr(llvm::Attribute::NoInline);
61
1/2
✓ Branch 50 → 51 taken 408 times.
✗ Branch 50 → 195 not taken.
408 fct->addFnAttr(llvm::Attribute::NoRecurse);
62
1/2
✓ Branch 51 → 52 taken 408 times.
✗ Branch 51 → 195 not taken.
408 addCommonFctAttrs(fct);
63
1/2
✓ Branch 52 → 53 taken 408 times.
✗ Branch 52 → 195 not taken.
408 enableFunctionInstrumentation(fct);
64
65 // Add return value attributes
66
1/2
✓ Branch 53 → 54 taken 408 times.
✗ Branch 53 → 195 not taken.
408 fct->addRetAttr(llvm::Attribute::NoUndef);
67
68 // Add debug info
69
2/2
✓ Branch 54 → 55 taken 6 times.
✓ Branch 54 → 60 taken 402 times.
408 if (cliOptions.instrumentation.generateDebugInfo) {
70 6 const auto nonConstNode = const_cast<MainFctDefNode *>(node);
71
1/2
✓ Branch 55 → 56 taken 6 times.
✗ Branch 55 → 152 not taken.
6 const Function spiceFunc = FunctionManager::createMainFunction(node->entry, paramSymbolTypes, nonConstNode);
72
1/2
✓ Branch 56 → 57 taken 6 times.
✗ Branch 56 → 150 not taken.
6 diGenerator.generateFunctionDebugInfo(fct, &spiceFunc);
73
1/2
✓ Branch 57 → 58 taken 6 times.
✗ Branch 57 → 150 not taken.
6 diGenerator.setSourceLocation(node);
74 6 }
75
76 // Create entry block
77
1/2
✓ Branch 63 → 64 taken 408 times.
✗ Branch 63 → 153 not taken.
408 llvm::BasicBlock *bEntry = createBlock();
78
1/2
✓ Branch 66 → 67 taken 408 times.
✗ Branch 66 → 195 not taken.
408 switchToBlock(bEntry, fct);
79
80 // Reset alloca insert markers to this block
81 408 allocaInsertBlock = bEntry;
82 408 allocaInsertInst = nullptr;
83
84 // Allocate result variable
85
3/6
✓ Branch 69 → 70 taken 408 times.
✗ Branch 69 → 162 not taken.
✓ Branch 70 → 71 taken 408 times.
✗ Branch 70 → 159 not taken.
✓ Branch 71 → 72 taken 408 times.
✗ Branch 71 → 159 not taken.
408 llvm::Value *resultAddress = insertAlloca(QualType(TY_INT), RETURN_VARIABLE_NAME);
86 // Update the symbol table entry
87
1/2
✓ Branch 76 → 77 taken 408 times.
✗ Branch 76 → 168 not taken.
1224 const SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
88
1/2
✗ Branch 82 → 83 not taken.
✓ Branch 82 → 84 taken 408 times.
408 assert(resultEntry != nullptr);
89
1/2
✓ Branch 84 → 85 taken 408 times.
✗ Branch 84 → 195 not taken.
408 updateAddress(resultEntry, resultAddress);
90 // Generate debug info
91
2/4
✓ Branch 87 → 88 taken 408 times.
✗ Branch 87 → 174 not taken.
✓ Branch 88 → 89 taken 408 times.
✗ Branch 88 → 172 not taken.
816 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddress);
92 // Store the default result value
93
3/6
✓ Branch 91 → 92 taken 408 times.
✗ Branch 91 → 178 not taken.
✓ Branch 92 → 93 taken 408 times.
✗ Branch 92 → 178 not taken.
✓ Branch 93 → 94 taken 408 times.
✗ Branch 93 → 178 not taken.
408 insertStore(builder.getInt32(0), resultAddress, QualType(TY_INT));
94
95 // Store function argument values
96
3/4
✓ Branch 94 → 95 taken 408 times.
✗ Branch 94 → 186 not taken.
✓ Branch 119 → 97 taken 14 times.
✓ Branch 119 → 120 taken 408 times.
422 for (auto &arg : fct->args()) {
97 // Get information about the parameter
98 14 const size_t argNumber = arg.getArgNo();
99
2/4
✓ Branch 98 → 99 taken 14 times.
✗ Branch 98 → 179 not taken.
✓ Branch 99 → 100 taken 14 times.
✗ Branch 99 → 179 not taken.
14 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
100
1/2
✗ Branch 102 → 103 not taken.
✓ Branch 102 → 104 taken 14 times.
14 assert(paramSymbol != nullptr);
101 // Decayed array params already carry the address of the array, so they do not need a local copy
102
2/4
✓ Branch 104 → 105 taken 14 times.
✗ Branch 104 → 179 not taken.
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 107 taken 14 times.
14 if (bindDecayedArrayParam(arg, paramName, paramSymbol))
103 continue;
104 // Allocate space for it
105
2/4
✓ Branch 107 → 108 taken 14 times.
✗ Branch 107 → 179 not taken.
✓ Branch 108 → 109 taken 14 times.
✗ Branch 108 → 179 not taken.
14 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
106 // Update the symbol table entry
107
1/2
✓ Branch 109 → 110 taken 14 times.
✗ Branch 109 → 179 not taken.
14 updateAddress(paramSymbol, paramAddress);
108 // Generate debug info
109
1/2
✓ Branch 110 → 111 taken 14 times.
✗ Branch 110 → 179 not taken.
14 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
110 // Store the value at the new address
111
1/2
✓ Branch 111 → 112 taken 14 times.
✗ Branch 111 → 179 not taken.
14 insertStore(&arg, paramAddress);
112
1/4
✓ Branch 113 → 114 taken 14 times.
✗ Branch 113 → 115 not taken.
✗ Branch 179 → 180 not taken.
✗ Branch 179 → 181 not taken.
14 }
113
114 // Visit function body
115
1/2
✓ Branch 120 → 121 taken 408 times.
✗ Branch 120 → 187 not taken.
408 visit(node->body);
116
117 // Create return statement if the block is not terminated yet
118
2/2
✓ Branch 122 → 123 taken 383 times.
✓ Branch 122 → 132 taken 25 times.
408 if (!blockAlreadyTerminated) {
119
3/6
✓ Branch 126 → 127 taken 383 times.
✗ Branch 126 → 188 not taken.
✓ Branch 127 → 128 taken 383 times.
✗ Branch 127 → 188 not taken.
✓ Branch 128 → 129 taken 383 times.
✗ Branch 128 → 188 not taken.
383 llvm::Value *result = insertLoad(fct->getReturnType(), getAddress(resultEntry));
120
1/2
✓ Branch 131 → 132 taken 383 times.
✗ Branch 131 → 195 not taken.
383 builder.CreateRet(result);
121 }
122
123 // Conclude debug info for function
124
1/2
✓ Branch 132 → 133 taken 408 times.
✗ Branch 132 → 195 not taken.
408 diGenerator.concludeFunctionDebugInfo();
125
126 // Verify function
127
1/2
✓ Branch 133 → 134 taken 408 times.
✗ Branch 133 → 195 not taken.
408 verifyFunction(fct, node->codeLoc);
128
129 // Change back to root scope
130 408 currentScope = rootScope;
131
1/2
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 408 times.
408 assert(currentScope != nullptr);
132
133
1/2
✓ Branch 136 → 137 taken 408 times.
✗ Branch 136 → 194 not taken.
408 return nullptr;
134 408 }
135
136 20194 std::any IRGenerator::visitFctDef(const FctDefNode *node) {
137 // Loop through manifestations
138 20194 manIdx = 0; // Reset the symbolTypeIndex
139
2/2
✓ Branch 215 → 4 taken 27400 times.
✓ Branch 215 → 216 taken 20194 times.
67788 for (const Function *manifestation : node->manifestations) {
140
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 27400 times.
27400 assert(manifestation->entry != nullptr);
141
142 // Check if the manifestation is substantiated or not public and not used by anybody
143
2/4
✓ Branch 8 → 9 taken 27400 times.
✗ Branch 8 → 307 not taken.
✓ Branch 9 → 10 taken 27400 times.
✗ Branch 9 → 307 not taken.
27400 const bool isPublic = manifestation->entry->getQualType().isPublic();
144
9/10
✓ Branch 10 → 11 taken 27400 times.
✗ Branch 10 → 307 not taken.
✓ Branch 11 → 12 taken 22414 times.
✓ Branch 11 → 14 taken 4986 times.
✓ Branch 12 → 13 taken 1160 times.
✓ Branch 12 → 15 taken 21254 times.
✓ Branch 13 → 14 taken 23 times.
✓ Branch 13 → 15 taken 1137 times.
✓ Branch 16 → 17 taken 5009 times.
✓ Branch 16 → 18 taken 22391 times.
27400 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
145 5009 manIdx++; // Increment symbolTypeIndex
146 5009 continue;
147 }
148
149 // Change to struct scope
150
2/2
✓ Branch 21 → 22 taken 13133 times.
✓ Branch 21 → 30 taken 9258 times.
22391 if (manifestation->isMethod()) {
151 13133 const QualType &thisType = manifestation->thisType;
152
3/6
✓ Branch 22 → 23 taken 13133 times.
✗ Branch 22 → 224 not taken.
✓ Branch 23 → 24 taken 13133 times.
✗ Branch 23 → 224 not taken.
✓ Branch 24 → 25 taken 13133 times.
✗ Branch 24 → 224 not taken.
13133 const std::string scopeName = Struct::getScopeName(thisType.getSubType(), thisType.getTemplateTypes());
153
1/2
✓ Branch 25 → 26 taken 13133 times.
✗ Branch 25 → 222 not taken.
13133 currentScope = currentScope->getChildScope(scopeName);
154
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 13133 times.
13133 assert(currentScope != nullptr);
155 13133 }
156
157 // Change scope
158
2/4
✓ Branch 30 → 31 taken 22391 times.
✗ Branch 30 → 227 not taken.
✓ Branch 31 → 32 taken 22391 times.
✗ Branch 31 → 225 not taken.
22391 currentScope = currentScope->getChildScope(manifestation->getScopeName());
159
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 22391 times.
22391 assert(currentScope != nullptr);
160
161 // Get 'this' entry
162 22391 std::vector<std::pair<std::string, const SymbolTableEntry *>> paramInfoList;
163
1/2
✓ Branch 35 → 36 taken 22391 times.
✗ Branch 35 → 303 not taken.
22391 std::vector<llvm::Type *> paramTypes;
164
2/2
✓ Branch 38 → 39 taken 13133 times.
✓ Branch 38 → 53 taken 9258 times.
22391 if (manifestation->isMethod()) {
165
1/2
✓ Branch 41 → 42 taken 13133 times.
✗ Branch 41 → 230 not taken.
39399 const SymbolTableEntry *thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
166
1/2
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 13133 times.
13133 assert(thisEntry != nullptr);
167
1/2
✓ Branch 49 → 50 taken 13133 times.
✗ Branch 49 → 235 not taken.
13133 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
168
2/4
✓ Branch 50 → 51 taken 13133 times.
✗ Branch 50 → 234 not taken.
✓ Branch 51 → 52 taken 13133 times.
✗ Branch 51 → 234 not taken.
13133 paramTypes.push_back(builder.getPtrTy());
169 }
170
171 // Visit parameters
172 22391 size_t argIdx = 0;
173
2/2
✓ Branch 53 → 54 taken 15819 times.
✓ Branch 53 → 72 taken 6572 times.
22391 if (node->hasParams) {
174 15819 const size_t numOfParams = manifestation->paramList.size();
175
1/2
✓ Branch 55 → 56 taken 15819 times.
✗ Branch 55 → 303 not taken.
15819 paramInfoList.reserve(numOfParams);
176
1/2
✓ Branch 56 → 57 taken 15819 times.
✗ Branch 56 → 303 not taken.
15819 paramTypes.reserve(numOfParams);
177
2/2
✓ Branch 71 → 58 taken 23082 times.
✓ Branch 71 → 72 taken 15819 times.
38901 for (; argIdx < numOfParams; argIdx++) {
178
1/2
✓ Branch 58 → 59 taken 23082 times.
✗ Branch 58 → 239 not taken.
23082 const DeclStmtNode *param = node->paramLst->params.at(argIdx);
179 // Get symbol table entry of param
180
1/2
✓ Branch 59 → 60 taken 23082 times.
✗ Branch 59 → 239 not taken.
23082 const SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
181
1/2
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 23082 times.
23082 assert(paramSymbol != nullptr);
182
2/4
✓ Branch 64 → 65 taken 23082 times.
✗ Branch 64 → 238 not taken.
✓ Branch 65 → 66 taken 23082 times.
✗ Branch 65 → 236 not taken.
23082 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
183 // Retrieve type of param
184
1/2
✓ Branch 67 → 68 taken 23082 times.
✗ Branch 67 → 239 not taken.
23082 llvm::Type *paramType = paramSymbolType.getParamLLVMType(sourceFile);
185 // Add it to the lists
186
1/2
✓ Branch 68 → 69 taken 23082 times.
✗ Branch 68 → 239 not taken.
23082 paramInfoList.emplace_back(param->varName, paramSymbol);
187
1/2
✓ Branch 69 → 70 taken 23082 times.
✗ Branch 69 → 239 not taken.
23082 paramTypes.push_back(paramType);
188 }
189 }
190
191 // Get return type
192
1/2
✓ Branch 72 → 73 taken 22391 times.
✗ Branch 72 → 303 not taken.
22391 llvm::Type *returnType = manifestation->returnType.toLLVMType(sourceFile);
193
194 // Get function linkage
195 22391 bool externalLinkage = isPublic;
196
12/18
✓ Branch 73 → 74 taken 815 times.
✓ Branch 73 → 80 taken 21576 times.
✓ Branch 76 → 77 taken 815 times.
✗ Branch 76 → 240 not taken.
✓ Branch 77 → 78 taken 815 times.
✗ Branch 77 → 240 not taken.
✓ Branch 78 → 79 taken 109 times.
✓ Branch 78 → 80 taken 706 times.
✓ Branch 81 → 82 taken 815 times.
✓ Branch 81 → 83 taken 21576 times.
✓ Branch 83 → 84 taken 815 times.
✓ Branch 83 → 86 taken 21576 times.
✓ Branch 86 → 87 taken 109 times.
✓ Branch 86 → 94 taken 22282 times.
✗ Branch 240 → 241 not taken.
✗ Branch 240 → 242 not taken.
✗ Branch 244 → 245 not taken.
✗ Branch 244 → 247 not taken.
24021 if (node->attrs && node->attrs->attrLst->hasAttr(ATTR_TEST))
197
2/4
✓ Branch 89 → 90 taken 109 times.
✗ Branch 89 → 251 not taken.
✓ Branch 90 → 91 taken 109 times.
✗ Branch 90 → 249 not taken.
327 externalLinkage |= node->attrs->attrLst->getAttrValueByName(ATTR_TEST)->boolValue;
198
2/2
✓ Branch 94 → 95 taken 21264 times.
✓ Branch 94 → 96 taken 1127 times.
22391 const auto linkage = externalLinkage ? llvm::Function::ExternalLinkage : llvm::Function::PrivateLinkage;
199
200 // Create function or implement declared function
201
1/2
✓ Branch 97 → 98 taken 22391 times.
✗ Branch 97 → 303 not taken.
22391 const std::string mangledName = manifestation->getMangledName();
202
1/2
✓ Branch 99 → 100 taken 22391 times.
✗ Branch 99 → 255 not taken.
22391 llvm::FunctionType *funcType = llvm::FunctionType::get(returnType, paramTypes, false);
203
1/2
✓ Branch 101 → 102 taken 22391 times.
✗ Branch 101 → 256 not taken.
22391 module->getOrInsertFunction(mangledName, funcType);
204
1/2
✓ Branch 103 → 104 taken 22391 times.
✗ Branch 103 → 257 not taken.
22391 llvm::Function *func = module->getFunction(mangledName);
205
1/2
✓ Branch 104 → 105 taken 22391 times.
✗ Branch 104 → 301 not taken.
22391 updateAddress(node->entry, func);
206
1/2
✓ Branch 105 → 106 taken 22391 times.
✗ Branch 105 → 301 not taken.
22391 setLLVMFunction(manifestation, func);
207
2/4
✓ Branch 106 → 107 taken 22391 times.
✗ Branch 106 → 301 not taken.
✗ Branch 107 → 108 not taken.
✓ Branch 107 → 109 taken 22391 times.
22391 assert(func->empty());
208
209 // Set attributes to function
210
1/2
✓ Branch 109 → 110 taken 22391 times.
✗ Branch 109 → 301 not taken.
22391 func->setDSOLocal(isSymbolDSOLocal(isPublic));
211
1/2
✓ Branch 111 → 112 taken 22391 times.
✗ Branch 111 → 301 not taken.
22391 func->setLinkage(linkage);
212
3/6
✓ Branch 112 → 113 taken 22391 times.
✗ Branch 112 → 301 not taken.
✓ Branch 113 → 114 taken 22391 times.
✗ Branch 113 → 301 not taken.
✓ Branch 114 → 115 taken 22391 times.
✗ Branch 114 → 301 not taken.
22391 addCommonFctAttrs(func, manifestation->entry->getQualType().isInline());
213
1/2
✓ Branch 115 → 116 taken 22391 times.
✗ Branch 115 → 301 not taken.
22391 enableFunctionInstrumentation(func);
214 // Set attributes to function parameters and return value
215
1/2
✓ Branch 116 → 117 taken 22391 times.
✗ Branch 116 → 301 not taken.
22391 setParamAttrs(func, paramInfoList);
216
1/2
✓ Branch 117 → 118 taken 22391 times.
✗ Branch 117 → 301 not taken.
22391 setFunctionReturnValAttrs(func, manifestation->returnType);
217
218 // Add debug info
219
1/2
✓ Branch 118 → 119 taken 22391 times.
✗ Branch 118 → 301 not taken.
22391 diGenerator.generateFunctionDebugInfo(func, manifestation);
220
1/2
✓ Branch 119 → 120 taken 22391 times.
✗ Branch 119 → 301 not taken.
22391 diGenerator.setSourceLocation(node);
221
222 // Create entry block
223
1/2
✓ Branch 123 → 124 taken 22391 times.
✗ Branch 123 → 258 not taken.
22391 llvm::BasicBlock *bEntry = createBlock();
224
1/2
✓ Branch 126 → 127 taken 22391 times.
✗ Branch 126 → 301 not taken.
22391 switchToBlock(bEntry, func);
225
226 // Reset alloca insert markers to this block
227 22391 allocaInsertBlock = bEntry;
228 22391 allocaInsertInst = nullptr;
229
230 // Declare result variable
231
2/4
✓ Branch 129 → 130 taken 22391 times.
✗ Branch 129 → 266 not taken.
✓ Branch 130 → 131 taken 22391 times.
✗ Branch 130 → 264 not taken.
22391 llvm::Value *resultAddr = insertAlloca(manifestation->returnType, RETURN_VARIABLE_NAME);
232
1/2
✓ Branch 135 → 136 taken 22391 times.
✗ Branch 135 → 272 not taken.
67173 const SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
233
1/2
✗ Branch 141 → 142 not taken.
✓ Branch 141 → 143 taken 22391 times.
22391 assert(resultEntry != nullptr);
234
1/2
✓ Branch 143 → 144 taken 22391 times.
✗ Branch 143 → 301 not taken.
22391 updateAddress(resultEntry, resultAddr);
235 // Generate debug info
236
2/4
✓ Branch 146 → 147 taken 22391 times.
✗ Branch 146 → 278 not taken.
✓ Branch 147 → 148 taken 22391 times.
✗ Branch 147 → 276 not taken.
44782 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddr);
237
238 // Store function argument values
239
3/4
✓ Branch 150 → 151 taken 22391 times.
✗ Branch 150 → 289 not taken.
✓ Branch 176 → 153 taken 36215 times.
✓ Branch 176 → 177 taken 22391 times.
58606 for (auto &arg : func->args()) {
240 // Get information about the parameter
241 36215 const size_t argNumber = arg.getArgNo();
242
2/4
✓ Branch 154 → 155 taken 36215 times.
✗ Branch 154 → 282 not taken.
✓ Branch 155 → 156 taken 36215 times.
✗ Branch 155 → 282 not taken.
36215 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
243
1/2
✗ Branch 158 → 159 not taken.
✓ Branch 158 → 160 taken 36215 times.
36215 assert(paramSymbol != nullptr);
244 // Decayed array params already carry the address of the array, so they do not need a local copy
245
3/4
✓ Branch 160 → 161 taken 36215 times.
✗ Branch 160 → 282 not taken.
✓ Branch 161 → 162 taken 9 times.
✓ Branch 161 → 163 taken 36206 times.
36215 if (bindDecayedArrayParam(arg, paramName, paramSymbol))
246 9 continue;
247 // Allocate space for it
248
2/4
✓ Branch 163 → 164 taken 36206 times.
✗ Branch 163 → 282 not taken.
✓ Branch 164 → 165 taken 36206 times.
✗ Branch 164 → 282 not taken.
36206 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
249 // Update the symbol table entry
250
1/2
✓ Branch 165 → 166 taken 36206 times.
✗ Branch 165 → 282 not taken.
36206 updateAddress(paramSymbol, paramAddress);
251 // Set source location
252
1/2
✓ Branch 166 → 167 taken 36206 times.
✗ Branch 166 → 282 not taken.
36206 diGenerator.setSourceLocation(paramSymbol->declNode);
253 // Generate debug info to declare variable
254
1/2
✓ Branch 167 → 168 taken 36206 times.
✗ Branch 167 → 282 not taken.
36206 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
255 // Store the value at the new address
256
1/2
✓ Branch 168 → 169 taken 36206 times.
✗ Branch 168 → 282 not taken.
36206 insertStore(&arg, paramAddress);
257
1/4
✓ Branch 170 → 171 taken 36215 times.
✗ Branch 170 → 172 not taken.
✗ Branch 282 → 283 not taken.
✗ Branch 282 → 284 not taken.
36215 }
258
259 // Store the default values for optional function args
260
2/2
✓ Branch 177 → 178 taken 15819 times.
✓ Branch 177 → 188 taken 6572 times.
22391 if (node->paramLst) {
261
1/2
✓ Branch 178 → 179 taken 15819 times.
✗ Branch 178 → 293 not taken.
15819 const std::vector<DeclStmtNode *> params = node->paramLst->params;
262
2/2
✓ Branch 185 → 180 taken 1628 times.
✓ Branch 185 → 186 taken 15819 times.
17447 for (; argIdx < params.size(); argIdx++)
263
2/4
✓ Branch 180 → 181 taken 1628 times.
✗ Branch 180 → 290 not taken.
✓ Branch 181 → 182 taken 1628 times.
✗ Branch 181 → 290 not taken.
1628 visit(params.at(argIdx));
264 15819 }
265
266 // Visit function body
267
1/2
✓ Branch 188 → 189 taken 22391 times.
✗ Branch 188 → 294 not taken.
22391 visit(node->body);
268
269 // Create return statement if the block is not terminated yet
270
2/2
✓ Branch 190 → 191 taken 993 times.
✓ Branch 190 → 199 taken 21398 times.
22391 if (!blockAlreadyTerminated) {
271
2/4
✓ Branch 194 → 195 taken 993 times.
✗ Branch 194 → 295 not taken.
✓ Branch 195 → 196 taken 993 times.
✗ Branch 195 → 295 not taken.
993 llvm::Value *result = insertLoad(returnType, getAddress(resultEntry));
272
1/2
✓ Branch 198 → 199 taken 993 times.
✗ Branch 198 → 301 not taken.
993 builder.CreateRet(result);
273 }
274
275 // Conclude debug info for function
276
1/2
✓ Branch 199 → 200 taken 22391 times.
✗ Branch 199 → 301 not taken.
22391 diGenerator.concludeFunctionDebugInfo();
277
278 // Verify function
279
1/2
✓ Branch 200 → 201 taken 22391 times.
✗ Branch 200 → 301 not taken.
22391 verifyFunction(func, node->codeLoc);
280
281 // Change to root scope
282 22391 currentScope = rootScope;
283
284 22391 manIdx++; // Increment symbolTypeIndex
285 22391 }
286 20194 manIdx = 0; // Reset the symbolTypeIndex
287
288 // Ensure that we are at the root scope again
289
1/2
✗ Branch 216 → 217 not taken.
✓ Branch 216 → 218 taken 20194 times.
20194 assert(currentScope == rootScope);
290
291
1/2
✓ Branch 218 → 219 taken 20194 times.
✗ Branch 218 → 309 not taken.
40388 return nullptr;
292 }
293
294 11227 std::any IRGenerator::visitProcDef(const ProcDefNode *node) {
295 // Loop through manifestations
296 11227 manIdx = 0; // Reset the symbolTypeIndex
297
2/2
✓ Branch 167 → 4 taken 17989 times.
✓ Branch 167 → 168 taken 11227 times.
40443 for (const Function *manifestation : node->manifestations) {
298
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 17989 times.
17989 assert(manifestation->entry != nullptr);
299
300 // Check if the manifestation is substantiated or not public and not used by anybody
301
2/4
✓ Branch 8 → 9 taken 17989 times.
✗ Branch 8 → 220 not taken.
✓ Branch 9 → 10 taken 17989 times.
✗ Branch 9 → 220 not taken.
17989 const bool isPublic = manifestation->entry->getQualType().isPublic();
302
9/10
✓ Branch 10 → 11 taken 17989 times.
✗ Branch 10 → 220 not taken.
✓ Branch 11 → 12 taken 12815 times.
✓ Branch 11 → 14 taken 5174 times.
✓ Branch 12 → 13 taken 1732 times.
✓ Branch 12 → 15 taken 11083 times.
✓ Branch 13 → 14 taken 18 times.
✓ Branch 13 → 15 taken 1714 times.
✓ Branch 16 → 17 taken 5192 times.
✓ Branch 16 → 18 taken 12797 times.
17989 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
303 5192 manIdx++; // Increment symbolTypeIndex
304 5192 continue;
305 }
306
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 12797 times.
12797 assert(manifestation->alreadyTypeChecked);
307
308 // Change to struct scope
309
2/2
✓ Branch 23 → 24 taken 10713 times.
✓ Branch 23 → 32 taken 2084 times.
12797 if (manifestation->isMethod()) {
310 10713 const QualType &thisType = manifestation->thisType;
311
3/6
✓ Branch 24 → 25 taken 10713 times.
✗ Branch 24 → 176 not taken.
✓ Branch 25 → 26 taken 10713 times.
✗ Branch 25 → 176 not taken.
✓ Branch 26 → 27 taken 10713 times.
✗ Branch 26 → 176 not taken.
10713 const std::string scopeName = Struct::getScopeName(thisType.getSubType(), thisType.getTemplateTypes());
312
1/2
✓ Branch 27 → 28 taken 10713 times.
✗ Branch 27 → 174 not taken.
10713 currentScope = currentScope->getChildScope(scopeName);
313
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 10713 times.
10713 assert(currentScope != nullptr);
314 10713 }
315
316 // Change scope
317
2/4
✓ Branch 32 → 33 taken 12797 times.
✗ Branch 32 → 179 not taken.
✓ Branch 33 → 34 taken 12797 times.
✗ Branch 33 → 177 not taken.
12797 currentScope = currentScope->getChildScope(manifestation->getScopeName());
318
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 12797 times.
12797 assert(currentScope != nullptr);
319
320 // Get 'this' entry
321 12797 std::vector<std::pair<std::string, const SymbolTableEntry *>> paramInfoList;
322
1/2
✓ Branch 37 → 38 taken 12797 times.
✗ Branch 37 → 216 not taken.
12797 std::vector<llvm::Type *> paramTypes;
323
2/2
✓ Branch 40 → 41 taken 10713 times.
✓ Branch 40 → 55 taken 2084 times.
12797 if (manifestation->isMethod()) {
324
1/2
✓ Branch 43 → 44 taken 10713 times.
✗ Branch 43 → 182 not taken.
32139 const SymbolTableEntry *thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
325
1/2
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 51 taken 10713 times.
10713 assert(thisEntry != nullptr);
326
1/2
✓ Branch 51 → 52 taken 10713 times.
✗ Branch 51 → 187 not taken.
10713 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
327
2/4
✓ Branch 52 → 53 taken 10713 times.
✗ Branch 52 → 186 not taken.
✓ Branch 53 → 54 taken 10713 times.
✗ Branch 53 → 186 not taken.
10713 paramTypes.push_back(builder.getPtrTy());
328 }
329
330 // Visit parameters
331 12797 size_t argIdx = 0;
332
2/2
✓ Branch 55 → 56 taken 9479 times.
✓ Branch 55 → 74 taken 3318 times.
12797 if (node->hasParams) {
333 9479 const size_t numOfParams = manifestation->paramList.size();
334
1/2
✓ Branch 57 → 58 taken 9479 times.
✗ Branch 57 → 216 not taken.
9479 paramInfoList.reserve(numOfParams);
335
1/2
✓ Branch 58 → 59 taken 9479 times.
✗ Branch 58 → 216 not taken.
9479 paramTypes.reserve(numOfParams);
336
2/2
✓ Branch 73 → 60 taken 13178 times.
✓ Branch 73 → 74 taken 9479 times.
22657 for (; argIdx < numOfParams; argIdx++) {
337
1/2
✓ Branch 60 → 61 taken 13178 times.
✗ Branch 60 → 191 not taken.
13178 const DeclStmtNode *param = node->paramLst->params.at(argIdx);
338 // Get symbol table entry of param
339
1/2
✓ Branch 61 → 62 taken 13178 times.
✗ Branch 61 → 191 not taken.
13178 const SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
340
1/2
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 66 taken 13178 times.
13178 assert(paramSymbol != nullptr);
341
2/4
✓ Branch 66 → 67 taken 13178 times.
✗ Branch 66 → 190 not taken.
✓ Branch 67 → 68 taken 13178 times.
✗ Branch 67 → 188 not taken.
13178 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
342 // Retrieve type of param
343
1/2
✓ Branch 69 → 70 taken 13178 times.
✗ Branch 69 → 191 not taken.
13178 llvm::Type *paramType = paramSymbolType.getParamLLVMType(sourceFile);
344 // Add it to the lists
345
1/2
✓ Branch 70 → 71 taken 13178 times.
✗ Branch 70 → 191 not taken.
13178 paramInfoList.emplace_back(param->varName, paramSymbol);
346
1/2
✓ Branch 71 → 72 taken 13178 times.
✗ Branch 71 → 191 not taken.
13178 paramTypes.push_back(paramType);
347 }
348 }
349
350 // Get return type
351
1/2
✓ Branch 74 → 75 taken 12797 times.
✗ Branch 74 → 216 not taken.
12797 llvm::Type *returnType = builder.getVoidTy();
352
353 // Create procedure or implement declared procedure
354
1/2
✓ Branch 75 → 76 taken 12797 times.
✗ Branch 75 → 216 not taken.
12797 const std::string mangledName = manifestation->getMangledName();
355
1/2
✓ Branch 77 → 78 taken 12797 times.
✗ Branch 77 → 192 not taken.
12797 llvm::FunctionType *procType = llvm::FunctionType::get(returnType, paramTypes, false);
356
1/2
✓ Branch 79 → 80 taken 12797 times.
✗ Branch 79 → 193 not taken.
12797 module->getOrInsertFunction(mangledName, procType);
357
1/2
✓ Branch 81 → 82 taken 12797 times.
✗ Branch 81 → 194 not taken.
12797 llvm::Function *proc = module->getFunction(mangledName);
358
1/2
✓ Branch 82 → 83 taken 12797 times.
✗ Branch 82 → 214 not taken.
12797 updateAddress(node->entry, proc);
359
1/2
✓ Branch 83 → 84 taken 12797 times.
✗ Branch 83 → 214 not taken.
12797 setLLVMFunction(manifestation, proc);
360
2/4
✓ Branch 84 → 85 taken 12797 times.
✗ Branch 84 → 214 not taken.
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 12797 times.
12797 assert(proc->empty());
361
362 // Set attributes to procedure
363
2/4
✓ Branch 87 → 88 taken 12797 times.
✗ Branch 87 → 214 not taken.
✓ Branch 88 → 89 taken 12797 times.
✗ Branch 88 → 214 not taken.
12797 proc->setLinkage(getSymbolLinkageType(isPublic));
364
1/2
✓ Branch 89 → 90 taken 12797 times.
✗ Branch 89 → 214 not taken.
12797 proc->setDSOLocal(isSymbolDSOLocal(isPublic));
365
3/6
✓ Branch 91 → 92 taken 12797 times.
✗ Branch 91 → 214 not taken.
✓ Branch 92 → 93 taken 12797 times.
✗ Branch 92 → 214 not taken.
✓ Branch 93 → 94 taken 12797 times.
✗ Branch 93 → 214 not taken.
12797 addCommonFctAttrs(proc, manifestation->entry->getQualType().isInline());
366
1/2
✓ Branch 94 → 95 taken 12797 times.
✗ Branch 94 → 214 not taken.
12797 enableFunctionInstrumentation(proc);
367
368 // Set attributes to function parameters
369
1/2
✓ Branch 95 → 96 taken 12797 times.
✗ Branch 95 → 214 not taken.
12797 setParamAttrs(proc, paramInfoList);
370
371 // Add debug info
372
1/2
✓ Branch 96 → 97 taken 12797 times.
✗ Branch 96 → 214 not taken.
12797 diGenerator.generateFunctionDebugInfo(proc, manifestation);
373
1/2
✓ Branch 97 → 98 taken 12797 times.
✗ Branch 97 → 214 not taken.
12797 diGenerator.setSourceLocation(node);
374
375 // Create entry block
376
1/2
✓ Branch 101 → 102 taken 12797 times.
✗ Branch 101 → 195 not taken.
12797 llvm::BasicBlock *bEntry = createBlock();
377
1/2
✓ Branch 104 → 105 taken 12797 times.
✗ Branch 104 → 214 not taken.
12797 switchToBlock(bEntry, proc);
378
379 // Reset alloca insert markers to this block
380 12797 allocaInsertBlock = bEntry;
381 12797 allocaInsertInst = nullptr;
382
383 // Store procedure argument values
384
3/4
✓ Branch 105 → 106 taken 12797 times.
✗ Branch 105 → 208 not taken.
✓ Branch 131 → 108 taken 23891 times.
✓ Branch 131 → 132 taken 12797 times.
36688 for (auto &arg : proc->args()) {
385 // Get information about the parameter
386 23891 const size_t argNumber = arg.getArgNo();
387
2/4
✓ Branch 109 → 110 taken 23891 times.
✗ Branch 109 → 201 not taken.
✓ Branch 110 → 111 taken 23891 times.
✗ Branch 110 → 201 not taken.
23891 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
388
1/2
✗ Branch 113 → 114 not taken.
✓ Branch 113 → 115 taken 23891 times.
23891 assert(paramSymbol != nullptr);
389 // Decayed array params already carry the address of the array, so they do not need a local copy
390
3/4
✓ Branch 115 → 116 taken 23891 times.
✗ Branch 115 → 201 not taken.
✓ Branch 116 → 117 taken 3 times.
✓ Branch 116 → 118 taken 23888 times.
23891 if (bindDecayedArrayParam(arg, paramName, paramSymbol))
391 3 continue;
392 // Allocate space for it
393
2/4
✓ Branch 118 → 119 taken 23888 times.
✗ Branch 118 → 201 not taken.
✓ Branch 119 → 120 taken 23888 times.
✗ Branch 119 → 201 not taken.
23888 llvm::Value *paramAddress = insertAlloca(paramSymbol->getQualType(), paramName);
394 // Update the symbol table entry
395
1/2
✓ Branch 120 → 121 taken 23888 times.
✗ Branch 120 → 201 not taken.
23888 updateAddress(paramSymbol, paramAddress);
396 // Set source location
397
1/2
✓ Branch 121 → 122 taken 23888 times.
✗ Branch 121 → 201 not taken.
23888 diGenerator.setSourceLocation(paramSymbol->declNode);
398 // Generate debug info to declare variable
399
1/2
✓ Branch 122 → 123 taken 23888 times.
✗ Branch 122 → 201 not taken.
23888 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
400 // Store the value at the new address
401
1/2
✓ Branch 123 → 124 taken 23888 times.
✗ Branch 123 → 201 not taken.
23888 insertStore(&arg, paramAddress);
402
1/4
✓ Branch 125 → 126 taken 23891 times.
✗ Branch 125 → 127 not taken.
✗ Branch 201 → 202 not taken.
✗ Branch 201 → 203 not taken.
23891 }
403
404 // Store the default values for optional procedure args
405
2/2
✓ Branch 132 → 133 taken 9479 times.
✓ Branch 132 → 143 taken 3318 times.
12797 if (node->paramLst) {
406
1/2
✓ Branch 133 → 134 taken 9479 times.
✗ Branch 133 → 212 not taken.
9479 const std::vector<DeclStmtNode *> params = node->paramLst->params;
407
2/2
✓ Branch 140 → 135 taken 720 times.
✓ Branch 140 → 141 taken 9479 times.
10199 for (; argIdx < params.size(); argIdx++)
408
2/4
✓ Branch 135 → 136 taken 720 times.
✗ Branch 135 → 209 not taken.
✓ Branch 136 → 137 taken 720 times.
✗ Branch 136 → 209 not taken.
720 visit(params.at(argIdx));
409 9479 }
410
411 // Generate special ctor preamble before generating the body to store VTable, default field values, etc. if required
412
2/2
✓ Branch 143 → 144 taken 5687 times.
✓ Branch 143 → 145 taken 7110 times.
12797 if (node->isCtor) {
413 5687 isInCtorBody = true;
414
1/2
✓ Branch 144 → 145 taken 5687 times.
✗ Branch 144 → 214 not taken.
5687 generateCtorBodyPreamble(currentScope);
415 }
416
417 // Visit procedure body
418
1/2
✓ Branch 145 → 146 taken 12797 times.
✗ Branch 145 → 213 not taken.
12797 visit(node->body);
419
420
2/2
✓ Branch 147 → 148 taken 5687 times.
✓ Branch 147 → 149 taken 7110 times.
12797 if (node->isCtor)
421 5687 isInCtorBody = false;
422
423 // Create return statement if the block is not terminated yet
424
2/2
✓ Branch 149 → 150 taken 12609 times.
✓ Branch 149 → 151 taken 188 times.
12797 if (!blockAlreadyTerminated)
425
1/2
✓ Branch 150 → 151 taken 12609 times.
✗ Branch 150 → 214 not taken.
12609 builder.CreateRetVoid();
426
427 // Conclude debug info for procedure
428
1/2
✓ Branch 151 → 152 taken 12797 times.
✗ Branch 151 → 214 not taken.
12797 diGenerator.concludeFunctionDebugInfo();
429
430 // Verify procedure
431
1/2
✓ Branch 152 → 153 taken 12797 times.
✗ Branch 152 → 214 not taken.
12797 verifyFunction(proc, node->codeLoc);
432
433 // Change to root scope
434 12797 currentScope = rootScope;
435
436 12797 manIdx++; // Increment symbolTypeIndex
437 12797 }
438 11227 manIdx = 0; // Reset the symbolTypeIndex
439
440 // Ensure that we are at the root scope again
441
1/2
✗ Branch 168 → 169 not taken.
✓ Branch 168 → 170 taken 11227 times.
11227 assert(currentScope == rootScope);
442
443
1/2
✓ Branch 170 → 171 taken 11227 times.
✗ Branch 170 → 222 not taken.
22454 return nullptr;
444 }
445
446 /**
447 * Bind a function argument that carries a decayed array to its parameter symbol. Since the argument already is the
448 * address of the array, it can be used as the address of the parameter directly, without allocating a local copy.
449 *
450 * @param arg Argument of the LLVM function
451 * @param paramName Name of the parameter
452 * @param paramSymbol Symbol table entry of the parameter
453 * @return Whether the argument was bound (false if the parameter does not carry a decayed array)
454 */
455 60234 bool IRGenerator::bindDecayedArrayParam(llvm::Argument &arg, const std::string &paramName,
456 const SymbolTableEntry *paramSymbol) {
457
6/6
✓ Branch 2 → 3 taken 60175 times.
✓ Branch 2 → 6 taken 59 times.
✓ Branch 5 → 6 taken 60162 times.
✓ Branch 5 → 7 taken 13 times.
✓ Branch 8 → 9 taken 60221 times.
✓ Branch 8 → 10 taken 13 times.
60234 if (paramSymbol == nullptr || !paramSymbol->getQualType().isDecayedArray())
458 60221 return false;
459
460
2/4
✓ Branch 10 → 11 taken 13 times.
✗ Branch 10 → 18 not taken.
✓ Branch 11 → 12 taken 13 times.
✗ Branch 11 → 18 not taken.
13 arg.setName(paramName);
461 13 updateAddress(paramSymbol, &arg);
462 // Set source location and generate debug info to declare the variable
463 13 diGenerator.setSourceLocation(paramSymbol->declNode);
464 13 diGenerator.generateLocalVarDebugInfo(paramName, &arg, arg.getArgNo() + 1);
465 13 return true;
466 }
467
468 /**
469 * Materialize an argument that is passed to a decayed array parameter, so that the callee receives the address of a
470 * writable array.
471 *
472 * Two cases need fixing up: if the argument was produced as the array itself instead of its address, it has to be put
473 * into memory. And if it was produced as the address of a read-only constant - array literals are emitted as global
474 * constants - it has to be copied into a mutable stack slot, because the callee may assign through the parameter. The
475 * latter matches how C frontends materialize array compound literals.
476 *
477 * @param argValue Value that was produced for the argument
478 * @param paramType Type of the parameter
479 * @return Address of the array to hand to the callee
480 */
481 17 llvm::Value *IRGenerator::materializeDecayedArrayArg(llvm::Value *argValue, const QualType &paramType) {
482
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 17 times.
17 assert(paramType.isDecayedArray());
483 17 llvm::Type *paramArrayType = paramType.toLLVMType(sourceFile);
484
485 // The array itself was produced (e.g. as the result of an implicit cast) -> put it into memory
486
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 17 taken 17 times.
17 if (!argValue->getType()->isPointerTy()) {
487 llvm::Value *argAddress = insertAlloca(paramArrayType, "arg.decay");
488 insertStore(argValue, argAddress);
489 return argAddress;
490 }
491
492 // Look through constant offsets, because the implicit array-to-array cast GEPs into the global constant
493 17 const auto *global = llvm::dyn_cast<llvm::GlobalVariable>(argValue->stripInBoundsConstantOffsets());
494
5/6
✓ Branch 19 → 20 taken 6 times.
✓ Branch 19 → 22 taken 11 times.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 6 times.
✓ Branch 24 → 25 taken 11 times.
✓ Branch 24 → 26 taken 6 times.
17 if (global == nullptr || !global->isConstant())
495 11 return argValue;
496
497 // Copy the constant into a mutable stack slot. Function matching does not enforce that the argument array has the
498 // same size as the parameter array, so copy the smaller of the two to never read past the end of the global.
499 6 const llvm::DataLayout &dataLayout = module->getDataLayout();
500 6 llvm::Type *globalType = global->getValueType();
501
4/8
✓ Branch 28 → 29 taken 6 times.
✗ Branch 28 → 51 not taken.
✓ Branch 29 → 30 taken 6 times.
✗ Branch 29 → 51 not taken.
✓ Branch 30 → 31 taken 6 times.
✗ Branch 30 → 50 not taken.
✓ Branch 31 → 32 taken 6 times.
✗ Branch 31 → 50 not taken.
6 const bool globalIsSmaller = dataLayout.getTypeAllocSize(globalType) < dataLayout.getTypeAllocSize(paramArrayType);
502
2/4
✓ Branch 34 → 35 taken 6 times.
✗ Branch 34 → 54 not taken.
✓ Branch 35 → 36 taken 6 times.
✗ Branch 35 → 52 not taken.
6 llvm::Value *argAddress = insertAlloca(paramArrayType, "arg.decay");
503
1/2
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 40 taken 6 times.
6 generateShallowCopy(argValue, globalIsSmaller ? globalType : paramArrayType, argAddress, false);
504 6 return argAddress;
505 }
506
507 35188 void IRGenerator::setParamAttrs(llvm::Function *function, const ParamInfoList &paramInfo) const {
508
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 35188 times.
35188 assert(function->arg_size() == paramInfo.size());
509
2/2
✓ Branch 30 → 7 taken 60106 times.
✓ Branch 30 → 31 taken 35188 times.
95294 for (size_t i = 0; i < paramInfo.size(); i++) {
510 60106 const QualType &paramType = paramInfo.at(i).second->getQualType();
511
512 // NoUndef attribute
513 60106 function->addParamAttr(i, llvm::Attribute::NoUndef);
514
515
2/2
✓ Branch 11 → 12 taken 26778 times.
✓ Branch 11 → 25 taken 33328 times.
60106 if (paramType.isPtr()) {
516 // NonNull attribute
517 26778 function->addParamAttr(i, llvm::Attribute::NonNull);
518 // Dereferenceable attribute
519
2/4
✓ Branch 13 → 14 taken 26778 times.
✗ Branch 13 → 32 not taken.
✓ Branch 14 → 15 taken 26778 times.
✗ Branch 14 → 32 not taken.
26778 llvm::Type *pointeeType = paramType.getContained().toLLVMType(sourceFile);
520
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 26778 times.
26778 assert(pointeeType != nullptr);
521
3/6
✓ Branch 18 → 19 taken 26778 times.
✗ Branch 18 → 33 not taken.
✓ Branch 19 → 20 taken 26778 times.
✗ Branch 19 → 33 not taken.
✓ Branch 20 → 21 taken 26778 times.
✗ Branch 20 → 33 not taken.
26778 function->addDereferenceableParamAttr(i, module->getDataLayout().getTypeStoreSize(pointeeType));
522 // Alignment attribute
523 26778 function->addParamAttr(i, llvm::Attribute::getWithAlignment(context, module->getDataLayout().getABITypeAlign(pointeeType)));
524 }
525
526 // ZExt or SExt attribute
527
2/2
✓ Branch 26 → 27 taken 6944 times.
✓ Branch 26 → 28 taken 53162 times.
60106 if (const llvm::Attribute::AttrKind extAttrKind = getExtAttrKindForType(paramType); extAttrKind != llvm::Attribute::None)
528 6944 function->addParamAttr(i, extAttrKind);
529 }
530 35188 }
531
532 22391 void IRGenerator::setFunctionReturnValAttrs(llvm::Function *function, const QualType &returnType) const {
533
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 22391 times.
22391 if (returnType.is(TY_DYN))
534 return;
535
536 // NoUndef attribute
537 22391 function->addRetAttr(llvm::Attribute::NoUndef);
538 // ZExt or SExt attribute
539
2/2
✓ Branch 7 → 8 taken 7940 times.
✓ Branch 7 → 9 taken 14451 times.
22391 if (const llvm::Attribute::AttrKind extAttrKind = getExtAttrKindForType(returnType); extAttrKind != llvm::Attribute::None)
540 7940 function->addRetAttr(extAttrKind);
541 }
542
543 217659 llvm::Attribute::AttrKind IRGenerator::getExtAttrKindForType(const QualType &type) const {
544
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 217659 times.
217659 if (type.is(TY_DYN))
545 return llvm::Attribute::None;
546
547 217659 const llvm::Type *llvmType = type.toLLVMType(sourceFile);
548
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 217659 times.
217659 const unsigned int maxExtWidth = cliOptions.targetTriple.isPPC() ? 64 : 32;
549
6/6
✓ Branch 11 → 12 taken 71174 times.
✓ Branch 11 → 15 taken 146485 times.
✓ Branch 13 → 14 taken 33561 times.
✓ Branch 13 → 15 taken 37613 times.
✓ Branch 16 → 17 taken 33561 times.
✓ Branch 16 → 22 taken 184098 times.
217659 if (llvmType->isIntegerTy() && llvmType->getIntegerBitWidth() < maxExtWidth)
550
2/2
✓ Branch 18 → 19 taken 2239 times.
✓ Branch 18 → 20 taken 31322 times.
33561 return type.isSigned() ? llvm::Attribute::SExt : llvm::Attribute::ZExt;
551 184098 return llvm::Attribute::None;
552 }
553
554 2960 std::any IRGenerator::visitStructDef(const StructDefNode *node) {
555 // Get all substantiated structs which result from this struct def
556
1/2
✓ Branch 2 → 3 taken 2960 times.
✗ Branch 2 → 128 not taken.
2960 std::vector<Struct *> manifestations = node->structManifestations;
557
558 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
559 5372 const auto comp = [](const Struct *lhs, const Struct *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
560
1/2
✓ Branch 3 → 4 taken 2960 times.
✗ Branch 3 → 126 not taken.
2960 std::ranges::sort(manifestations, comp);
561
562
2/2
✓ Branch 83 → 6 taken 5074 times.
✓ Branch 83 → 84 taken 2960 times.
10994 for (Struct *spiceStruct : manifestations) {
563 // Skip structs, that are not fully substantiated
564
3/4
✓ Branch 8 → 9 taken 5074 times.
✗ Branch 8 → 123 not taken.
✓ Branch 9 → 10 taken 784 times.
✓ Branch 9 → 11 taken 4290 times.
5074 if (!spiceStruct->isFullySubstantiated())
565 785 continue;
566
567 // Do not generate this struct if it is private and used by nobody
568
8/10
✓ Branch 11 → 12 taken 845 times.
✓ Branch 11 → 16 taken 3445 times.
✓ Branch 12 → 13 taken 845 times.
✗ Branch 12 → 123 not taken.
✓ Branch 13 → 14 taken 845 times.
✗ Branch 13 → 123 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 844 times.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 19 taken 4289 times.
4290 if (!spiceStruct->used && !spiceStruct->entry->getQualType().isPublic())
569 1 continue;
570
571 // Change scope to struct scope, specific to substantiation
572 4289 currentScope = spiceStruct->scope;
573
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 4289 times.
4289 assert(currentScope);
574
575 // Set LLVM type to the struct entry
576 4289 const SymbolTableEntry *structEntry = spiceStruct->entry;
577
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 4289 times.
4289 assert(structEntry != nullptr);
578
579 // Generate VTable if required
580
2/2
✓ Branch 23 → 24 taken 1141 times.
✓ Branch 23 → 27 taken 3148 times.
4289 if (node->emitVTable) {
581
1/2
✓ Branch 24 → 25 taken 1141 times.
✗ Branch 24 → 123 not taken.
1141 generateVTable(spiceStruct);
582
1/2
✓ Branch 25 → 26 taken 1141 times.
✗ Branch 25 → 89 not taken.
2282 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceStruct); }, false);
583 }
584
585 // Generate default ctor if required
586
1/2
✓ Branch 27 → 28 taken 4289 times.
✗ Branch 27 → 123 not taken.
4289 const QualType &thisType = structEntry->getQualType();
587
2/4
✓ Branch 31 → 32 taken 4289 times.
✗ Branch 31 → 93 not taken.
✓ Branch 32 → 33 taken 4289 times.
✗ Branch 32 → 91 not taken.
12867 const Function *ctorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, {}, true);
588
4/4
✓ Branch 36 → 37 taken 979 times.
✓ Branch 36 → 39 taken 3310 times.
✓ Branch 37 → 38 taken 118 times.
✓ Branch 37 → 39 taken 861 times.
4289 if (ctorFunc != nullptr && ctorFunc->implicitDefault)
589
1/2
✓ Branch 38 → 39 taken 118 times.
✗ Branch 38 → 123 not taken.
118 generateDefaultCtor(ctorFunc);
590
591 // Generate default copy ctor if required
592
2/4
✓ Branch 39 → 40 taken 4289 times.
✗ Branch 39 → 104 not taken.
✓ Branch 43 → 44 taken 4289 times.
✗ Branch 43 → 100 not taken.
12867 const ArgList args = {{thisType.toConstRef(node), false /* always non-temporary */}};
593
2/4
✓ Branch 47 → 48 taken 4289 times.
✗ Branch 47 → 108 not taken.
✓ Branch 48 → 49 taken 4289 times.
✗ Branch 48 → 106 not taken.
4289 const Function *copyCtorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, args, true);
594
4/4
✓ Branch 51 → 52 taken 2110 times.
✓ Branch 51 → 54 taken 2179 times.
✓ Branch 52 → 53 taken 1621 times.
✓ Branch 52 → 54 taken 489 times.
4289 if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault)
595
1/2
✓ Branch 53 → 54 taken 1621 times.
✗ Branch 53 → 121 not taken.
1621 generateDefaultCopyCtor(copyCtorFunc);
596
597 // Generate default move ctor if required. We can't use FunctionManager::lookup with a non-const ref arg
598 // here, because the lookup permits const-param-to-non-const-arg matching ("constify") and may return the
599 // copy ctor as a false positive. findMoveCtor scans the manifestations directly and only matches the
600 // strict move ctor signature.
601
5/6
✓ Branch 54 → 55 taken 4289 times.
✗ Branch 54 → 121 not taken.
✓ Branch 55 → 56 taken 78 times.
✓ Branch 55 → 58 taken 4211 times.
✓ Branch 56 → 57 taken 10 times.
✓ Branch 56 → 58 taken 68 times.
4289 if (const Function *moveCtorFunc = FunctionManager::findMoveCtor(currentScope); moveCtorFunc && moveCtorFunc->implicitDefault)
602
1/2
✓ Branch 57 → 58 taken 10 times.
✗ Branch 57 → 121 not taken.
10 generateDefaultMoveCtor(moveCtorFunc);
603
604 // Generate default dtor if required
605
2/4
✓ Branch 61 → 62 taken 4289 times.
✗ Branch 61 → 114 not taken.
✓ Branch 62 → 63 taken 4289 times.
✗ Branch 62 → 112 not taken.
12867 const Function *dtorFunc = FunctionManager::lookup(currentScope, DTOR_FUNCTION_NAME, thisType, {}, true);
606
4/4
✓ Branch 66 → 67 taken 2325 times.
✓ Branch 66 → 69 taken 1964 times.
✓ Branch 67 → 68 taken 1597 times.
✓ Branch 67 → 69 taken 728 times.
4289 if (dtorFunc != nullptr && dtorFunc->implicitDefault)
607
1/2
✓ Branch 68 → 69 taken 1597 times.
✗ Branch 68 → 121 not taken.
1597 generateDefaultDtor(dtorFunc);
608
609 // Return to root scope
610 4289 currentScope = rootScope;
611
1/2
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 4289 times.
4289 assert(currentScope);
612 4289 }
613
614
1/2
✓ Branch 84 → 85 taken 2960 times.
✗ Branch 84 → 125 not taken.
5920 return nullptr;
615 2960 }
616
617 357 std::any IRGenerator::visitInterfaceDef(const InterfaceDefNode *node) {
618 // Get all substantiated structs which result from this struct def
619
1/2
✓ Branch 2 → 3 taken 357 times.
✗ Branch 2 → 43 not taken.
357 std::vector<Interface *> manifestations = node->interfaceManifestations;
620
621 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
622 2648 const auto comp = [](const Interface *lhs, const Interface *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
623
1/2
✓ Branch 3 → 4 taken 357 times.
✗ Branch 3 → 41 not taken.
357 std::ranges::sort(manifestations, comp);
624
625
2/2
✓ Branch 31 → 6 taken 1319 times.
✓ Branch 31 → 32 taken 357 times.
2033 for (Interface *spiceInterface : manifestations) {
626 // Skip interfaces, that are not fully substantiated
627
3/4
✓ Branch 8 → 9 taken 1319 times.
✗ Branch 8 → 39 not taken.
✓ Branch 9 → 10 taken 153 times.
✓ Branch 9 → 11 taken 1166 times.
1319 if (!spiceInterface->isFullySubstantiated())
628 153 continue;
629
630 // Do not generate this interface if it is private and used by nobody
631
8/10
✓ Branch 11 → 12 taken 21 times.
✓ Branch 11 → 16 taken 1145 times.
✓ Branch 12 → 13 taken 21 times.
✗ Branch 12 → 39 not taken.
✓ Branch 13 → 14 taken 21 times.
✗ Branch 13 → 39 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 20 times.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 19 taken 1165 times.
1166 if (!spiceInterface->used && !spiceInterface->entry->getQualType().isPublic())
632 1 continue;
633
634 // Generate VTable information
635
1/2
✓ Branch 19 → 20 taken 1165 times.
✗ Branch 19 → 39 not taken.
1165 generateVTable(spiceInterface);
636
1/2
✓ Branch 20 → 21 taken 1165 times.
✗ Branch 20 → 37 not taken.
2330 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceInterface); }, false);
637 }
638
639
1/2
✓ Branch 32 → 33 taken 357 times.
✗ Branch 32 → 40 not taken.
714 return nullptr;
640 357 }
641
642 369 std::any IRGenerator::visitEnumDef(const EnumDefNode *node) {
643
1/2
✓ Branch 2 → 3 taken 369 times.
✗ Branch 2 → 6 not taken.
738 return nullptr; // Noop (enums are high-level semantic-only structures)
644 }
645
646 1941 std::any IRGenerator::visitGenericTypeDef(const GenericTypeDefNode *node) {
647
1/2
✓ Branch 2 → 3 taken 1941 times.
✗ Branch 2 → 6 not taken.
3882 return nullptr; // Noop (generic types are high-level semantic-only structures)
648 }
649
650 342 std::any IRGenerator::visitAliasDef(const AliasDefNode *node) {
651
1/2
✓ Branch 2 → 3 taken 342 times.
✗ Branch 2 → 6 not taken.
684 return nullptr; // Noop (alias definitions are high-level semantic-only structures)
652 }
653
654 2379 std::any IRGenerator::visitGlobalVarDef(const GlobalVarDefNode *node) {
655 // Retrieve some information about the variable
656
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2379 times.
2379 assert(node->entry != nullptr);
657 2379 const QualType &entryType = node->entry->getQualType();
658 2379 const bool isPublic = entryType.isPublic();
659 2379 const bool isConst = entryType.isConst();
660
661 // Get correct type and linkage type
662
2/4
✓ Branch 7 → 8 taken 2379 times.
✗ Branch 7 → 39 not taken.
✓ Branch 8 → 9 taken 2379 times.
✗ Branch 8 → 37 not taken.
2379 const auto varType = std::any_cast<llvm::Type *>(visit(node->dataType));
663
664 // Create global var
665
1/2
✓ Branch 11 → 12 taken 2379 times.
✗ Branch 11 → 40 not taken.
2379 llvm::Value *varAddress = module->getOrInsertGlobal(node->varName, varType);
666
1/2
✓ Branch 13 → 14 taken 2379 times.
✗ Branch 13 → 41 not taken.
2379 llvm::GlobalVariable *var = module->getNamedGlobal(node->varName);
667 // Set some attributes, based on the given information
668 2379 var->setConstant(isConst);
669 2379 var->setLinkage(getSymbolLinkageType(isPublic));
670 2379 var->setDSOLocal(isSymbolDSOLocal(isPublic));
671
672 // Set initializer
673
1/2
✓ Branch 19 → 20 taken 2379 times.
✗ Branch 19 → 24 not taken.
2379 if (node->hasValue) { // Set the constant value as variable initializer
674
2/4
✓ Branch 20 → 21 taken 2379 times.
✗ Branch 20 → 44 not taken.
✓ Branch 21 → 22 taken 2379 times.
✗ Branch 21 → 42 not taken.
2379 const auto constantValue = std::any_cast<llvm::Constant *>(visit(node->constant));
675 2379 var->setInitializer(constantValue);
676 } else if (cliOptions.buildMode != BuildMode::RELEASE) { // Set the default value as variable initializer
677 assert(cliOptions.buildMode == BuildMode::DEBUG || cliOptions.buildMode == BuildMode::TEST);
678 llvm::Constant *constantValue = getDefaultValueForSymbolType(node->entry->getQualType());
679 var->setInitializer(constantValue);
680 }
681
682 2379 updateAddress(node->entry, varAddress);
683
684 // Add debug info
685 2379 diGenerator.generateGlobalVarDebugInfo(var, node->entry);
686
687
1/2
✓ Branch 33 → 34 taken 2379 times.
✗ Branch 33 → 45 not taken.
4758 return nullptr;
688 }
689
690 3032 std::any IRGenerator::visitExtDecl(const ExtDeclNode *node) {
691 // Get return type
692 3032 const Function *spiceFunc = node->extFunction;
693
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3032 times.
3032 assert(spiceFunc != nullptr);
694
1/2
✓ Branch 4 → 5 taken 3032 times.
✗ Branch 4 → 100 not taken.
3032 llvm::Type *returnType = builder.getVoidTy();
695
3/4
✓ Branch 5 → 6 taken 3032 times.
✗ Branch 5 → 100 not taken.
✓ Branch 6 → 7 taken 2001 times.
✓ Branch 6 → 9 taken 1031 times.
3032 if (!spiceFunc->returnType.is(TY_DYN))
696
1/2
✓ Branch 7 → 8 taken 2001 times.
✗ Branch 7 → 100 not taken.
2001 returnType = spiceFunc->returnType.toLLVMType(sourceFile);
697
698 // Get arg types
699 3032 std::vector<llvm::Type *> argTypes;
700
1/2
✓ Branch 10 → 11 taken 3032 times.
✗ Branch 10 → 98 not taken.
3032 argTypes.reserve(spiceFunc->paramList.size());
701
3/4
✓ Branch 11 → 12 taken 3032 times.
✗ Branch 11 → 76 not taken.
✓ Branch 27 → 14 taken 6243 times.
✓ Branch 27 → 28 taken 3032 times.
12307 for (const QualType &paramType : spiceFunc->getParamTypes())
702
2/4
✓ Branch 16 → 17 taken 6243 times.
✗ Branch 16 → 73 not taken.
✓ Branch 17 → 18 taken 6243 times.
✗ Branch 17 → 73 not taken.
9275 argTypes.push_back(paramType.getParamLLVMType(sourceFile));
703
704 // Declare function
705
4/4
✓ Branch 29 → 30 taken 2826 times.
✓ Branch 29 → 32 taken 206 times.
✓ Branch 30 → 31 taken 58 times.
✓ Branch 30 → 32 taken 2768 times.
3032 const bool isVarArg = node->argTypeLst && node->argTypeLst->hasEllipsis;
706
1/2
✓ Branch 34 → 35 taken 3032 times.
✗ Branch 34 → 77 not taken.
3032 llvm::FunctionType *functionType = llvm::FunctionType::get(returnType, argTypes, isVarArg);
707
1/2
✓ Branch 35 → 36 taken 3032 times.
✗ Branch 35 → 98 not taken.
3032 const std::string mangledName = spiceFunc->getMangledName();
708
1/2
✓ Branch 37 → 38 taken 3032 times.
✗ Branch 37 → 78 not taken.
3032 module->getOrInsertFunction(mangledName, functionType);
709
1/2
✓ Branch 39 → 40 taken 3032 times.
✗ Branch 39 → 79 not taken.
3032 llvm::Function *fct = module->getFunction(mangledName);
710
711 // Add noundef attribute to all parameters
712
2/2
✓ Branch 44 → 41 taken 6243 times.
✓ Branch 44 → 45 taken 3032 times.
9275 for (size_t i = 0; i < argTypes.size(); i++)
713
1/2
✓ Branch 41 → 42 taken 6243 times.
✗ Branch 41 → 96 not taken.
6243 fct->addParamAttr(i, llvm::Attribute::NoUndef);
714
715 // If the function should be imported as dll, add the dll attribute
716
10/18
✓ Branch 45 → 46 taken 1 time.
✓ Branch 45 → 52 taken 3031 times.
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 80 not taken.
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 80 not taken.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 1 time.
✓ Branch 53 → 54 taken 1 time.
✓ Branch 53 → 55 taken 3031 times.
✓ Branch 55 → 56 taken 1 time.
✓ Branch 55 → 58 taken 3031 times.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 67 taken 3032 times.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 87 not taken.
3034 if (node->attrs && node->attrs->attrLst->hasAttr(ATTR_CORE_LINKER_DLL))
717 if (node->attrs->attrLst->getAttrValueByName(ATTR_CORE_LINKER_DLL)->boolValue)
718 fct->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
719
720
1/2
✓ Branch 67 → 68 taken 3032 times.
✗ Branch 67 → 95 not taken.
6064 return nullptr;
721 3032 }
722
723 } // namespace spice::compiler
724