GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 98.4% 254 / 0 / 258
Functions: 100.0% 11 / 0 / 11
Branches: 53.6% 310 / 0 / 578

src/irgenerator/GenControlStructures.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4
5 #include <ast/ASTNodes.h>
6 #include <symboltablebuilder/ScopeHandle.h>
7
8 namespace spice::compiler {
9
10 16980 std::any IRGenerator::visitUnsafeBlockDef(const UnsafeBlockNode *node) {
11 // Change scope
12
2/4
✓ Branch 2 → 3 taken 16980 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 16980 times.
✗ Branch 3 → 12 not taken.
16980 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::UNSAFE_BODY, node);
13
14 // Visit instructions in the block
15
1/2
✓ Branch 5 → 6 taken 16980 times.
✗ Branch 5 → 16 not taken.
16980 visit(node->body);
16
17
1/2
✓ Branch 7 → 8 taken 16980 times.
✗ Branch 7 → 17 not taken.
33960 return nullptr;
18 16980 }
19
20 7383 std::any IRGenerator::visitForLoop(const ForLoopNode *node) {
21 // Create blocks
22
1/2
✓ Branch 2 → 3 taken 7383 times.
✗ Branch 2 → 73 not taken.
7383 const std::string codeLine = node->codeLoc.toPrettyLine();
23
2/4
✓ Branch 3 → 4 taken 7383 times.
✗ Branch 3 → 51 not taken.
✓ Branch 4 → 5 taken 7383 times.
✗ Branch 4 → 49 not taken.
7383 llvm::BasicBlock *bHead = createBlock("for.head." + codeLine);
24
2/4
✓ Branch 6 → 7 taken 7383 times.
✗ Branch 6 → 54 not taken.
✓ Branch 7 → 8 taken 7383 times.
✗ Branch 7 → 52 not taken.
7383 llvm::BasicBlock *bBody = createBlock("for.body." + codeLine);
25
2/4
✓ Branch 9 → 10 taken 7383 times.
✗ Branch 9 → 57 not taken.
✓ Branch 10 → 11 taken 7383 times.
✗ Branch 10 → 55 not taken.
7383 llvm::BasicBlock *bTail = createBlock("for.tail." + codeLine);
26
2/4
✓ Branch 12 → 13 taken 7383 times.
✗ Branch 12 → 60 not taken.
✓ Branch 13 → 14 taken 7383 times.
✗ Branch 13 → 58 not taken.
7383 llvm::BasicBlock *bExit = createBlock("for.exit." + codeLine);
27
28 // Change scope
29
2/4
✓ Branch 15 → 16 taken 7383 times.
✗ Branch 15 → 63 not taken.
✓ Branch 16 → 17 taken 7383 times.
✗ Branch 16 → 61 not taken.
7383 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::FOR_BODY, node);
30
31 // Save the break/continue targets, paired with the scope to clean up to when jumping there
32
1/2
✓ Branch 18 → 19 taken 7383 times.
✗ Branch 18 → 69 not taken.
7383 breakTargets.emplace_back(currentScope, bExit);
33
1/2
✓ Branch 19 → 20 taken 7383 times.
✗ Branch 19 → 69 not taken.
7383 continueTargets.emplace_back(currentScope, bTail);
34
35 // Init statement
36
1/2
✓ Branch 20 → 21 taken 7383 times.
✗ Branch 20 → 65 not taken.
7383 visit(node->initDecl);
37 // Create jump from original to head block
38
1/2
✓ Branch 22 → 23 taken 7383 times.
✗ Branch 22 → 69 not taken.
7383 insertJump(bHead);
39
40 // Switch to head block
41
1/2
✓ Branch 23 → 24 taken 7383 times.
✗ Branch 23 → 69 not taken.
7383 switchToBlock(bHead);
42 // Condition evaluation
43
1/2
✓ Branch 24 → 25 taken 7383 times.
✗ Branch 24 → 69 not taken.
7383 llvm::Value *condValue = resolveValueInExprScope(node->condAssign);
44 // Create conditional jump from head to body or exit block
45
1/2
✓ Branch 25 → 26 taken 7383 times.
✗ Branch 25 → 69 not taken.
7383 insertCondJump(condValue, bBody, bExit);
46
47 // Switch to body block
48
1/2
✓ Branch 26 → 27 taken 7383 times.
✗ Branch 26 → 69 not taken.
7383 switchToBlock(bBody);
49 // Visit body
50
1/2
✓ Branch 27 → 28 taken 7383 times.
✗ Branch 27 → 66 not taken.
7383 visit(node->body);
51 // Create jump from body to tail block
52
1/2
✓ Branch 29 → 30 taken 7383 times.
✗ Branch 29 → 69 not taken.
7383 insertJump(bTail);
53
54 // Switch to tail block
55
1/2
✓ Branch 30 → 31 taken 7383 times.
✗ Branch 30 → 69 not taken.
7383 switchToBlock(bTail);
56 // Inc statement
57
1/2
✓ Branch 31 → 32 taken 7383 times.
✗ Branch 31 → 67 not taken.
7383 visit(node->incAssign);
58 // Create jump from tail to head
59
1/2
✓ Branch 33 → 34 taken 7383 times.
✗ Branch 33 → 69 not taken.
7383 insertJump(bHead);
60
61 // Switch to exit block
62
1/2
✓ Branch 34 → 35 taken 7383 times.
✗ Branch 34 → 69 not taken.
7383 switchToBlock(bExit);
63
64 // Pop break/continue targets
65
1/2
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 7383 times.
7383 assert(breakTargets.back().block == bExit);
66 7383 breakTargets.pop_back();
67
1/2
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 7383 times.
7383 assert(continueTargets.back().block == bTail);
68 7383 continueTargets.pop_back();
69
70
1/2
✓ Branch 43 → 44 taken 7383 times.
✗ Branch 43 → 68 not taken.
14766 return nullptr;
71 7383 }
72
73 650 std::any IRGenerator::visitForeachLoop(const ForeachLoopNode *node) {
74 // Create blocks
75
1/2
✓ Branch 2 → 3 taken 650 times.
✗ Branch 2 → 283 not taken.
650 const std::string codeLine = node->codeLoc.toPrettyLine();
76
2/4
✓ Branch 3 → 4 taken 650 times.
✗ Branch 3 → 193 not taken.
✓ Branch 4 → 5 taken 650 times.
✗ Branch 4 → 191 not taken.
650 llvm::BasicBlock *bHead = createBlock("foreach.head." + codeLine);
77
2/4
✓ Branch 6 → 7 taken 650 times.
✗ Branch 6 → 196 not taken.
✓ Branch 7 → 8 taken 650 times.
✗ Branch 7 → 194 not taken.
650 llvm::BasicBlock *bBody = createBlock("foreach.body." + codeLine);
78
2/4
✓ Branch 9 → 10 taken 650 times.
✗ Branch 9 → 199 not taken.
✓ Branch 10 → 11 taken 650 times.
✗ Branch 10 → 197 not taken.
650 llvm::BasicBlock *bTail = createBlock("foreach.tail." + codeLine);
79
2/4
✓ Branch 12 → 13 taken 650 times.
✗ Branch 12 → 202 not taken.
✓ Branch 13 → 14 taken 650 times.
✗ Branch 13 → 200 not taken.
650 llvm::BasicBlock *bExit = createBlock("foreach.exit." + codeLine);
80
81 // Change scope
82
2/4
✓ Branch 15 → 16 taken 650 times.
✗ Branch 15 → 205 not taken.
✓ Branch 16 → 17 taken 650 times.
✗ Branch 16 → 203 not taken.
650 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::FOREACH_BODY, node);
83
84 // Save the break/continue targets, paired with the scope to clean up to when jumping there
85
1/2
✓ Branch 18 → 19 taken 650 times.
✗ Branch 18 → 279 not taken.
650 breakTargets.emplace_back(currentScope, bExit);
86
1/2
✓ Branch 19 → 20 taken 650 times.
✗ Branch 19 → 279 not taken.
650 continueTargets.emplace_back(currentScope, bTail);
87
88 // Resolve iterator
89 650 ExprNode *iteratorAssignNode = node->iteratorAssign;
90 llvm::Value *iteratorPtr;
91
2/2
✓ Branch 20 → 21 taken 592 times.
✓ Branch 20 → 66 taken 58 times.
650 if (node->getIteratorFct != nullptr) { // The iteratorAssignExpr is of type Iterable
92
1/2
✓ Branch 21 → 22 taken 592 times.
✗ Branch 21 → 227 not taken.
592 llvm::Value *iterablePtr = resolveAddress(iteratorAssignNode);
93
94 llvm::Value *iterator;
95 592 llvm::Value *iteratorAddr = nullptr;
96 592 const QualType &iteratorType = node->getIteratorFct->returnType;
97
10/16
✓ Branch 22 → 23 taken 592 times.
✗ Branch 22 → 207 not taken.
✓ Branch 25 → 26 taken 8 times.
✓ Branch 25 → 31 taken 584 times.
✓ Branch 26 → 27 taken 8 times.
✗ Branch 26 → 207 not taken.
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 207 not taken.
✓ Branch 29 → 30 taken 8 times.
✗ Branch 29 → 31 not taken.
✓ Branch 32 → 33 taken 8 times.
✓ Branch 32 → 34 taken 584 times.
✓ Branch 34 → 35 taken 8 times.
✓ Branch 34 → 49 taken 584 times.
✗ Branch 207 → 208 not taken.
✗ Branch 207 → 209 not taken.
1184 if (!node->getIteratorFct->isMethod() && node->getIteratorFct->getParamTypes().front().isArray()) { // Array as iterable
98 // Call iterate() function from std/iterator/array-iterator
99
1/2
✓ Branch 35 → 36 taken 8 times.
✗ Branch 35 → 227 not taken.
8 llvm::Function *iterateFct = stdFunctionManager.getIterateFct(node->getIteratorFct);
100
2/4
✓ Branch 36 → 37 taken 8 times.
✗ Branch 36 → 227 not taken.
✓ Branch 37 → 38 taken 8 times.
✗ Branch 37 → 227 not taken.
8 const size_t arraySize = iteratorAssignNode->getEvaluatedSymbolType(manIdx).getArraySize();
101
1/2
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 40 taken 8 times.
8 assert(arraySize > 0);
102
4/8
✓ Branch 40 → 41 taken 8 times.
✗ Branch 40 → 217 not taken.
✓ Branch 43 → 44 taken 8 times.
✗ Branch 43 → 214 not taken.
✓ Branch 44 → 45 taken 8 times.
✗ Branch 44 → 211 not taken.
✓ Branch 45 → 46 taken 8 times.
✗ Branch 45 → 211 not taken.
24 iterator = insertCall(iterateFct, {iterablePtr, builder.getInt64(arraySize)}, iteratorType, iteratorAddr);
103 } else { // Struct as iterable
104 // Call .getIterator() on iterable
105
1/2
✓ Branch 49 → 50 taken 584 times.
✗ Branch 49 → 227 not taken.
584 llvm::Function *getIteratorFct = stdFunctionManager.getIteratorFct(node->getIteratorFct);
106
3/6
✓ Branch 52 → 53 taken 584 times.
✗ Branch 52 → 222 not taken.
✓ Branch 53 → 54 taken 584 times.
✗ Branch 53 → 219 not taken.
✓ Branch 54 → 55 taken 584 times.
✗ Branch 54 → 219 not taken.
1752 iterator = insertCall(getIteratorFct, {iterablePtr}, iteratorType, iteratorAddr);
107 }
108
109 // Resolve address of iterator. If it is returned via memory or coerced, it already lives in memory
110 592 LLVMExprResult callResult = {.node = iteratorAssignNode};
111
1/2
✓ Branch 58 → 59 taken 592 times.
✗ Branch 58 → 60 not taken.
592 if (iteratorAddr != nullptr)
112 592 callResult.ptr = iteratorAddr;
113 else
114 ✗ callResult.value = iterator;
115
1/2
✓ Branch 61 → 62 taken 592 times.
✗ Branch 61 → 227 not taken.
592 iteratorPtr = resolveAddress(callResult);
116
117 // If an anonymous symbol exists, set its address
118
3/4
✓ Branch 62 → 63 taken 592 times.
✗ Branch 62 → 227 not taken.
✓ Branch 63 → 64 taken 2 times.
✓ Branch 63 → 65 taken 590 times.
592 if (const SymbolTableEntry *returnSymbol = currentScope->symbolTable.lookupAnonymous(iteratorAssignNode))
119
1/2
✓ Branch 64 → 65 taken 2 times.
✗ Branch 64 → 227 not taken.
2 updateAddress(returnSymbol, iteratorPtr);
120 } else { // The iteratorAssignExpr is of type Iterator
121
1/2
✓ Branch 66 → 67 taken 58 times.
✗ Branch 66 → 279 not taken.
58 iteratorPtr = resolveAddress(iteratorAssignNode);
122 }
123
124 // Check we have an idx
125 650 const DeclStmtNode *idxDeclNode = node->idxVarDecl;
126 650 const bool hasIdx = idxDeclNode != nullptr;
127 // Retrieve item ref type
128
3/4
✓ Branch 68 → 69 taken 44 times.
✓ Branch 68 → 70 taken 606 times.
✗ Branch 71 → 72 not taken.
✓ Branch 71 → 73 taken 650 times.
650 assert(hasIdx ? node->getIdxFct != nullptr : node->getFct != nullptr);
129
2/2
✓ Branch 73 → 74 taken 44 times.
✓ Branch 73 → 75 taken 606 times.
650 const QualType itemRefSTy = hasIdx ? node->getIdxFct->returnType : node->getFct->returnType;
130
131 // Visit idx variable declaration if required
132 650 const SymbolTableEntry *idxEntry = nullptr;
133 650 llvm::Value *idxAddress = nullptr;
134
2/2
✓ Branch 76 → 77 taken 44 times.
✓ Branch 76 → 83 taken 606 times.
650 if (hasIdx) {
135
1/2
✓ Branch 77 → 78 taken 44 times.
✗ Branch 77 → 228 not taken.
44 visit(idxDeclNode);
136 // Get address of idx variable
137
1/2
✓ Branch 79 → 80 taken 44 times.
✗ Branch 79 → 279 not taken.
44 idxEntry = idxDeclNode->entries.at(manIdx);
138
1/2
✓ Branch 80 → 81 taken 44 times.
✗ Branch 80 → 279 not taken.
44 idxAddress = getAddress(idxEntry);
139
1/2
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 44 times.
44 assert(idxAddress != nullptr);
140 }
141
142 // Visit item variable declaration
143 650 const DeclStmtNode *itemDeclNode = node->itemVarDecl;
144
1/2
✓ Branch 83 → 84 taken 650 times.
✗ Branch 83 → 229 not taken.
650 visit(itemDeclNode);
145 // Get address of item variable
146
1/2
✓ Branch 85 → 86 taken 650 times.
✗ Branch 85 → 279 not taken.
650 const SymbolTableEntry *itemEntry = itemDeclNode->entries.at(manIdx);
147
1/2
✓ Branch 86 → 87 taken 650 times.
✗ Branch 86 → 279 not taken.
650 llvm::Value *itemAddress = getAddress(itemEntry);
148
1/2
✗ Branch 87 → 88 not taken.
✓ Branch 87 → 89 taken 650 times.
650 assert(itemAddress != nullptr);
149
150 // Create jump from original to head block
151
1/2
✓ Branch 89 → 90 taken 650 times.
✗ Branch 89 → 279 not taken.
650 insertJump(bHead);
152
153 // Switch to head block
154
1/2
✓ Branch 90 → 91 taken 650 times.
✗ Branch 90 → 279 not taken.
650 switchToBlock(bHead);
155
1/2
✓ Branch 91 → 92 taken 650 times.
✗ Branch 91 → 279 not taken.
650 diGenerator.setSourceLocation(node);
156 // Call .isValid() on iterator
157
1/2
✗ Branch 92 → 93 not taken.
✓ Branch 92 → 94 taken 650 times.
650 assert(node->isValidFct);
158
1/2
✓ Branch 94 → 95 taken 650 times.
✗ Branch 94 → 279 not taken.
650 llvm::Function *isValidFct = stdFunctionManager.getIteratorIsValidFct(node->isValidFct);
159
4/8
✓ Branch 95 → 96 taken 650 times.
✗ Branch 95 → 232 not taken.
✓ Branch 97 → 98 taken 650 times.
✗ Branch 97 → 230 not taken.
✓ Branch 98 → 99 taken 650 times.
✗ Branch 98 → 230 not taken.
✓ Branch 99 → 100 taken 650 times.
✗ Branch 99 → 279 not taken.
650 llvm::Value *isValid = builder.CreateCall(isValidFct, iteratorPtr);
160 // Create conditional jump from head to body or exit block
161
1/2
✓ Branch 99 → 100 taken 650 times.
✗ Branch 99 → 279 not taken.
650 insertCondJump(isValid, bBody, bExit);
162
163 // Switch to body block
164
1/2
✓ Branch 100 → 101 taken 650 times.
✗ Branch 100 → 279 not taken.
650 switchToBlock(bBody);
165 // Get the current iterator values
166 650 LLVMExprResult itemResult;
167
2/2
✓ Branch 101 → 102 taken 44 times.
✓ Branch 101 → 142 taken 606 times.
650 if (hasIdx) {
168 // Allocate space to save pair
169 44 const QualType &pairSTy = node->getIdxFct->returnType;
170
1/2
✓ Branch 102 → 103 taken 44 times.
✗ Branch 102 → 262 not taken.
44 llvm::Type *pairTy = pairSTy.toLLVMType(sourceFile);
171 // Call .getIdx() on iterator. If the pair is returned via memory or coerced, it already lives in memory
172
1/2
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 44 times.
44 assert(node->getIdxFct);
173
1/2
✓ Branch 105 → 106 taken 44 times.
✗ Branch 105 → 262 not taken.
44 llvm::Function *getIdxFct = stdFunctionManager.getIteratorGetIdxFct(node->getIdxFct);
174 44 llvm::Value *pairPtr = nullptr;
175
3/6
✓ Branch 108 → 109 taken 44 times.
✗ Branch 108 → 236 not taken.
✓ Branch 109 → 110 taken 44 times.
✗ Branch 109 → 233 not taken.
✓ Branch 110 → 111 taken 44 times.
✗ Branch 110 → 233 not taken.
88 llvm::Value *pair = insertCall(getIdxFct, {iteratorPtr}, pairSTy, pairPtr);
176
1/2
✗ Branch 113 → 114 not taken.
✓ Branch 113 → 123 taken 44 times.
44 if (pairPtr == nullptr) {
177 ✗ pairPtr = insertAlloca(pairSTy, "pair.addr");
178 ✗ pair->setName("pair");
179 ✗ insertStore(pair, pairPtr);
180 }
181 // Store idx to idx var
182
2/4
✓ Branch 125 → 126 taken 44 times.
✗ Branch 125 → 250 not taken.
✓ Branch 126 → 127 taken 44 times.
✗ Branch 126 → 248 not taken.
44 llvm::Value *idxAddrInPair = insertStructGEP(pairTy, pairPtr, 0, "idx.addr");
183 44 LLVMExprResult idxResult = {.ptr = idxAddrInPair};
184
2/4
✓ Branch 129 → 130 taken 44 times.
✗ Branch 129 → 132 not taken.
✓ Branch 130 → 131 taken 44 times.
✗ Branch 130 → 132 not taken.
44 assert(idxAddress != nullptr && idxEntry != nullptr);
185
2/4
✓ Branch 133 → 134 taken 44 times.
✗ Branch 133 → 254 not taken.
✓ Branch 134 → 135 taken 44 times.
✗ Branch 134 → 254 not taken.
44 doAssignment(idxAddress, idxEntry, idxResult, QualType(TY_LONG), node, true);
186 // Store item to item var
187
2/4
✓ Branch 137 → 138 taken 44 times.
✗ Branch 137 → 258 not taken.
✓ Branch 138 → 139 taken 44 times.
✗ Branch 138 → 256 not taken.
88 itemResult.refPtr = insertStructGEP(pairTy, pairPtr, 1, "item.addr");
188 } else {
189 // Call .get() on iterator
190
1/2
✗ Branch 142 → 143 not taken.
✓ Branch 142 → 144 taken 606 times.
606 assert(node->getFct);
191
1/2
✓ Branch 144 → 145 taken 606 times.
✗ Branch 144 → 279 not taken.
606 llvm::Function *getFct = stdFunctionManager.getIteratorGetFct(node->getFct);
192
3/6
✓ Branch 145 → 146 taken 606 times.
✗ Branch 145 → 265 not taken.
✓ Branch 147 → 148 taken 606 times.
✗ Branch 147 → 263 not taken.
✓ Branch 148 → 149 taken 606 times.
✗ Branch 148 → 263 not taken.
606 itemResult.ptr = builder.CreateCall(getFct, iteratorPtr);
193 }
194
2/2
✓ Branch 150 → 151 taken 5 times.
✓ Branch 150 → 161 taken 645 times.
650 if (node->calledItemCopyCtor != nullptr) {
195 // Call copy ctor
196
1/2
✓ Branch 151 → 152 taken 5 times.
✗ Branch 151 → 279 not taken.
5 llvm::Value *rhsAddress = resolveAddress(itemResult);
197
1/2
✗ Branch 152 → 153 not taken.
✓ Branch 152 → 154 taken 5 times.
5 assert(rhsAddress != nullptr);
198
2/4
✓ Branch 156 → 157 taken 5 times.
✗ Branch 156 → 268 not taken.
✓ Branch 157 → 158 taken 5 times.
✗ Branch 157 → 266 not taken.
15 generateCtorOrDtorCall(itemEntry, node->calledItemCopyCtor, {rhsAddress});
199 } else {
200 // Perform normal assignment
201
1/2
✓ Branch 161 → 162 taken 645 times.
✗ Branch 161 → 273 not taken.
645 doAssignment(itemAddress, itemEntry, itemResult, itemRefSTy, node, true);
202 }
203 // Visit body
204
1/2
✓ Branch 163 → 164 taken 650 times.
✗ Branch 163 → 274 not taken.
650 visit(node->body);
205 // Create jump from body to tail block
206
1/2
✓ Branch 165 → 166 taken 650 times.
✗ Branch 165 → 279 not taken.
650 insertJump(bTail);
207
208 // Switch to tail block
209
1/2
✓ Branch 166 → 167 taken 650 times.
✗ Branch 166 → 279 not taken.
650 switchToBlock(bTail);
210
1/2
✓ Branch 167 → 168 taken 650 times.
✗ Branch 167 → 279 not taken.
650 diGenerator.setSourceLocation(node);
211 // Call .next() on iterator
212
1/2
✗ Branch 168 → 169 not taken.
✓ Branch 168 → 170 taken 650 times.
650 assert(node->nextFct);
213
1/2
✓ Branch 170 → 171 taken 650 times.
✗ Branch 170 → 279 not taken.
650 llvm::Function *nextFct = stdFunctionManager.getIteratorNextFct(node->nextFct);
214
4/8
✓ Branch 171 → 172 taken 650 times.
✗ Branch 171 → 277 not taken.
✓ Branch 173 → 174 taken 650 times.
✗ Branch 173 → 275 not taken.
✓ Branch 174 → 175 taken 650 times.
✗ Branch 174 → 275 not taken.
✓ Branch 175 → 176 taken 650 times.
✗ Branch 175 → 279 not taken.
650 builder.CreateCall(nextFct, iteratorPtr);
215 // Create jump from tail to head block
216
1/2
✓ Branch 175 → 176 taken 650 times.
✗ Branch 175 → 279 not taken.
650 insertJump(bHead);
217
218 // Switch to exit block
219
1/2
✓ Branch 176 → 177 taken 650 times.
✗ Branch 176 → 279 not taken.
650 switchToBlock(bExit);
220
221 // Pop break/continue targets
222
1/2
✗ Branch 178 → 179 not taken.
✓ Branch 178 → 180 taken 650 times.
650 assert(breakTargets.back().block == bExit);
223 650 breakTargets.pop_back();
224
1/2
✗ Branch 182 → 183 not taken.
✓ Branch 182 → 184 taken 650 times.
650 assert(continueTargets.back().block == bTail);
225 650 continueTargets.pop_back();
226
227
1/2
✓ Branch 185 → 186 taken 650 times.
✗ Branch 185 → 278 not taken.
1300 return nullptr;
228 650 }
229
230 2763 std::any IRGenerator::visitWhileLoop(const WhileLoopNode *node) {
231 // Create blocks
232
1/2
✓ Branch 2 → 3 taken 2763 times.
✗ Branch 2 → 59 not taken.
2763 const std::string codeLine = node->codeLoc.toPrettyLine();
233
2/4
✓ Branch 3 → 4 taken 2763 times.
✗ Branch 3 → 42 not taken.
✓ Branch 4 → 5 taken 2763 times.
✗ Branch 4 → 40 not taken.
2763 llvm::BasicBlock *bHead = createBlock("while.head." + codeLine);
234
2/4
✓ Branch 6 → 7 taken 2763 times.
✗ Branch 6 → 45 not taken.
✓ Branch 7 → 8 taken 2763 times.
✗ Branch 7 → 43 not taken.
2763 llvm::BasicBlock *bBody = createBlock("while.body." + codeLine);
235
2/4
✓ Branch 9 → 10 taken 2763 times.
✗ Branch 9 → 48 not taken.
✓ Branch 10 → 11 taken 2763 times.
✗ Branch 10 → 46 not taken.
2763 llvm::BasicBlock *bExit = createBlock("while.exit." + codeLine);
236
237 // Change scope
238
2/4
✓ Branch 12 → 13 taken 2763 times.
✗ Branch 12 → 51 not taken.
✓ Branch 13 → 14 taken 2763 times.
✗ Branch 13 → 49 not taken.
2763 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::WHILE_BODY, node);
239
240 // Save the break/continue targets, paired with the scope to clean up to when jumping there
241
1/2
✓ Branch 15 → 16 taken 2763 times.
✗ Branch 15 → 55 not taken.
2763 breakTargets.emplace_back(currentScope, bExit);
242
1/2
✓ Branch 16 → 17 taken 2763 times.
✗ Branch 16 → 55 not taken.
2763 continueTargets.emplace_back(currentScope, bHead);
243
244 // Jump to head block
245
1/2
✓ Branch 17 → 18 taken 2763 times.
✗ Branch 17 → 55 not taken.
2763 insertJump(bHead);
246
247 // Switch to head block
248
1/2
✓ Branch 18 → 19 taken 2763 times.
✗ Branch 18 → 55 not taken.
2763 switchToBlock(bHead);
249 // Evaluate condition
250
1/2
✓ Branch 19 → 20 taken 2763 times.
✗ Branch 19 → 55 not taken.
2763 llvm::Value *condValue = resolveValueInExprScope(node->condition);
251 // Jump to body or exit block, depending on the condition
252
1/2
✓ Branch 20 → 21 taken 2763 times.
✗ Branch 20 → 55 not taken.
2763 insertCondJump(condValue, bBody, bExit);
253
254 // Switch to body block
255
1/2
✓ Branch 21 → 22 taken 2763 times.
✗ Branch 21 → 55 not taken.
2763 switchToBlock(bBody);
256 // Visit body
257
1/2
✓ Branch 22 → 23 taken 2763 times.
✗ Branch 22 → 53 not taken.
2763 visit(node->body);
258 // Create jump to head block
259
1/2
✓ Branch 24 → 25 taken 2763 times.
✗ Branch 24 → 55 not taken.
2763 insertJump(bHead);
260
261 // Switch to exit block
262
1/2
✓ Branch 25 → 26 taken 2763 times.
✗ Branch 25 → 55 not taken.
2763 switchToBlock(bExit);
263
264 // Pop break/continue targets
265
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 2763 times.
2763 assert(breakTargets.back().block == bExit);
266 2763 breakTargets.pop_back();
267
1/2
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 2763 times.
2763 assert(continueTargets.back().block == bHead);
268 2763 continueTargets.pop_back();
269
270
1/2
✓ Branch 34 → 35 taken 2763 times.
✗ Branch 34 → 54 not taken.
5526 return nullptr;
271 2763 }
272
273 119 std::any IRGenerator::visitDoWhileLoop(const DoWhileLoopNode *node) {
274 // Create blocks
275
1/2
✓ Branch 2 → 3 taken 119 times.
✗ Branch 2 → 59 not taken.
119 const std::string codeLine = node->codeLoc.toPrettyLine();
276
2/4
✓ Branch 3 → 4 taken 119 times.
✗ Branch 3 → 42 not taken.
✓ Branch 4 → 5 taken 119 times.
✗ Branch 4 → 40 not taken.
119 llvm::BasicBlock *bBody = createBlock("dowhile.body." + codeLine);
277
2/4
✓ Branch 6 → 7 taken 119 times.
✗ Branch 6 → 45 not taken.
✓ Branch 7 → 8 taken 119 times.
✗ Branch 7 → 43 not taken.
119 llvm::BasicBlock *bFoot = createBlock("dowhile.foot." + codeLine);
278
2/4
✓ Branch 9 → 10 taken 119 times.
✗ Branch 9 → 48 not taken.
✓ Branch 10 → 11 taken 119 times.
✗ Branch 10 → 46 not taken.
119 llvm::BasicBlock *bExit = createBlock("dowhile.exit." + codeLine);
279
280 // Change scope
281
2/4
✓ Branch 12 → 13 taken 119 times.
✗ Branch 12 → 51 not taken.
✓ Branch 13 → 14 taken 119 times.
✗ Branch 13 → 49 not taken.
119 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::WHILE_BODY, node);
282
283 // Save the break/continue targets, paired with the scope to clean up to when jumping there
284
1/2
✓ Branch 15 → 16 taken 119 times.
✗ Branch 15 → 55 not taken.
119 breakTargets.emplace_back(currentScope, bExit);
285
1/2
✓ Branch 16 → 17 taken 119 times.
✗ Branch 16 → 55 not taken.
119 continueTargets.emplace_back(currentScope, bFoot);
286
287 // Jump to body block
288
1/2
✓ Branch 17 → 18 taken 119 times.
✗ Branch 17 → 55 not taken.
119 insertJump(bBody);
289
290 // Switch to body block
291
1/2
✓ Branch 18 → 19 taken 119 times.
✗ Branch 18 → 55 not taken.
119 switchToBlock(bBody);
292 // Visit body
293
1/2
✓ Branch 19 → 20 taken 119 times.
✗ Branch 19 → 53 not taken.
119 visit(node->body);
294 // Create jump to foot block
295
1/2
✓ Branch 21 → 22 taken 119 times.
✗ Branch 21 → 55 not taken.
119 insertJump(bFoot);
296
297 // Switch to head block
298
1/2
✓ Branch 22 → 23 taken 119 times.
✗ Branch 22 → 55 not taken.
119 switchToBlock(bFoot);
299 // Evaluate condition
300
1/2
✓ Branch 23 → 24 taken 119 times.
✗ Branch 23 → 55 not taken.
119 llvm::Value *condValue = resolveValueInExprScope(node->condition);
301 // Jump to body or exit block, depending on the condition
302
1/2
✓ Branch 24 → 25 taken 119 times.
✗ Branch 24 → 55 not taken.
119 insertCondJump(condValue, bBody, bExit);
303
304 // Switch to exit block
305
1/2
✓ Branch 25 → 26 taken 119 times.
✗ Branch 25 → 55 not taken.
119 switchToBlock(bExit);
306
307 // Pop break/continue targets
308
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 119 times.
119 assert(breakTargets.back().block == bExit);
309 119 breakTargets.pop_back();
310
1/2
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 119 times.
119 assert(continueTargets.back().block == bFoot);
311 119 continueTargets.pop_back();
312
313
1/2
✓ Branch 34 → 35 taken 119 times.
✗ Branch 34 → 54 not taken.
238 return nullptr;
314 119 }
315
316 38534 std::any IRGenerator::visitIfStmt(const IfStmtNode *node) {
317 // If we have a compile time decision, only evaluate the respective branch
318
8/10
✓ Branch 2 → 3 taken 38534 times.
✗ Branch 2 → 104 not taken.
✓ Branch 3 → 4 taken 38310 times.
✓ Branch 3 → 7 taken 224 times.
✓ Branch 4 → 5 taken 38310 times.
✗ Branch 4 → 104 not taken.
✓ Branch 5 → 6 taken 346 times.
✓ Branch 5 → 7 taken 37964 times.
✓ Branch 8 → 9 taken 346 times.
✓ Branch 8 → 19 taken 38188 times.
38534 if (node->doCompileThenBranch(manIdx) && !node->doCompileElseBranch(manIdx)) {
319
2/4
✓ Branch 9 → 10 taken 346 times.
✗ Branch 9 → 75 not taken.
✓ Branch 10 → 11 taken 346 times.
✗ Branch 10 → 73 not taken.
346 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::IF_ELSE_BODY, node);
320
1/2
✓ Branch 12 → 13 taken 346 times.
✗ Branch 12 → 77 not taken.
346 visit(node->thenBody);
321
2/4
✓ Branch 14 → 15 taken 346 times.
✗ Branch 14 → 78 not taken.
✓ Branch 15 → 16 taken 346 times.
✗ Branch 15 → 78 not taken.
346 return builder.getTrue();
322 346 }
323
7/10
✓ Branch 19 → 20 taken 38188 times.
✗ Branch 19 → 104 not taken.
✓ Branch 20 → 21 taken 224 times.
✓ Branch 20 → 24 taken 37964 times.
✓ Branch 21 → 22 taken 224 times.
✗ Branch 21 → 104 not taken.
✓ Branch 22 → 23 taken 224 times.
✗ Branch 22 → 24 not taken.
✓ Branch 25 → 26 taken 224 times.
✓ Branch 25 → 34 taken 37964 times.
38188 if (!node->doCompileThenBranch(manIdx) && node->doCompileElseBranch(manIdx)) {
324
2/2
✓ Branch 26 → 27 taken 4 times.
✓ Branch 26 → 30 taken 220 times.
224 if (node->elseStmt)
325
1/2
✓ Branch 27 → 28 taken 4 times.
✗ Branch 27 → 82 not taken.
4 visit(node->elseStmt);
326
2/4
✓ Branch 30 → 31 taken 224 times.
✗ Branch 30 → 83 not taken.
✓ Branch 31 → 32 taken 224 times.
✗ Branch 31 → 83 not taken.
448 return builder.getFalse();
327 }
328
329 // Create blocks
330
1/2
✓ Branch 34 → 35 taken 37964 times.
✗ Branch 34 → 104 not taken.
37964 const std::string codeLine = node->codeLoc.toPrettyLine();
331
2/4
✓ Branch 35 → 36 taken 37964 times.
✗ Branch 35 → 86 not taken.
✓ Branch 36 → 37 taken 37964 times.
✗ Branch 36 → 84 not taken.
37964 llvm::BasicBlock *bThen = createBlock("if.then." + codeLine);
332
6/10
✓ Branch 38 → 39 taken 2081 times.
✓ Branch 38 → 42 taken 35883 times.
✓ Branch 39 → 40 taken 2081 times.
✗ Branch 39 → 87 not taken.
✓ Branch 40 → 41 taken 2081 times.
✗ Branch 40 → 87 not taken.
✓ Branch 43 → 44 taken 2081 times.
✓ Branch 43 → 45 taken 35883 times.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
37964 llvm::BasicBlock *bElse = node->elseStmt ? createBlock("if.else." + codeLine) : nullptr;
333
2/4
✓ Branch 45 → 46 taken 37964 times.
✗ Branch 45 → 93 not taken.
✓ Branch 46 → 47 taken 37964 times.
✗ Branch 46 → 91 not taken.
37964 llvm::BasicBlock *bExit = createBlock("if.exit." + codeLine);
334
335 // Change scope
336
2/4
✓ Branch 48 → 49 taken 37964 times.
✗ Branch 48 → 96 not taken.
✓ Branch 49 → 50 taken 37964 times.
✗ Branch 49 → 94 not taken.
37964 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::IF_ELSE_BODY, node);
337
338 // Retrieve condition value
339
1/2
✓ Branch 51 → 52 taken 37964 times.
✗ Branch 51 → 100 not taken.
37964 llvm::Value *condValue = resolveValueInExprScope(node->condition);
340 // Check if condition is fulfilled
341
3/4
✓ Branch 52 → 53 taken 2081 times.
✓ Branch 52 → 54 taken 35883 times.
✓ Branch 55 → 56 taken 37964 times.
✗ Branch 55 → 100 not taken.
37964 insertCondJump(condValue, bThen, node->elseStmt ? bElse : bExit);
342
343 // Switch to then block
344
1/2
✓ Branch 56 → 57 taken 37964 times.
✗ Branch 56 → 100 not taken.
37964 switchToBlock(bThen);
345 // Visit then body
346
1/2
✓ Branch 57 → 58 taken 37964 times.
✗ Branch 57 → 98 not taken.
37964 visit(node->thenBody);
347 // Create jump from then to end block
348
1/2
✓ Branch 59 → 60 taken 37964 times.
✗ Branch 59 → 100 not taken.
37964 insertJump(bExit);
349
350 // Change scope back
351
1/2
✓ Branch 60 → 61 taken 37964 times.
✗ Branch 60 → 100 not taken.
37964 scopeHandle.leaveScopeEarly();
352
353
2/2
✓ Branch 61 → 62 taken 2081 times.
✓ Branch 61 → 66 taken 35883 times.
37964 if (node->elseStmt) {
354 // Switch to else block
355
1/2
✓ Branch 62 → 63 taken 2081 times.
✗ Branch 62 → 100 not taken.
2081 switchToBlock(bElse);
356 // Visit else block
357
1/2
✓ Branch 63 → 64 taken 2081 times.
✗ Branch 63 → 99 not taken.
2081 visit(node->elseStmt);
358 // Create jump from else to end block
359
1/2
✓ Branch 65 → 66 taken 2081 times.
✗ Branch 65 → 100 not taken.
2081 insertJump(bExit);
360 }
361
362 // Switch to exit block
363
1/2
✓ Branch 66 → 67 taken 37964 times.
✗ Branch 66 → 100 not taken.
37964 switchToBlock(bExit);
364
365 // Return conditional value as result for the 'if' stmt
366
1/2
✓ Branch 67 → 68 taken 37964 times.
✗ Branch 67 → 100 not taken.
37964 return condValue;
367 37964 }
368
369 2085 std::any IRGenerator::visitElseStmt(const ElseStmtNode *node) {
370
2/2
✓ Branch 2 → 3 taken 919 times.
✓ Branch 2 → 6 taken 1166 times.
2085 if (node->ifStmt) { // It is an else if branch
371
1/2
✓ Branch 3 → 4 taken 919 times.
✗ Branch 3 → 17 not taken.
919 visit(node->ifStmt);
372 } else { // It is an else branch
373 // Change scope
374
2/4
✓ Branch 6 → 7 taken 1166 times.
✗ Branch 6 → 20 not taken.
✓ Branch 7 → 8 taken 1166 times.
✗ Branch 7 → 18 not taken.
1166 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::IF_ELSE_BODY, node);
375
376 // Generate IR for nested statements
377
1/2
✓ Branch 9 → 10 taken 1166 times.
✗ Branch 9 → 22 not taken.
1166 visit(node->body);
378 1166 }
379
380
1/2
✓ Branch 13 → 14 taken 2085 times.
✗ Branch 13 → 26 not taken.
4170 return nullptr;
381 }
382
383 41 std::any IRGenerator::visitSwitchStmt(const SwitchStmtNode *node) {
384 // Create blocks
385 41 std::vector<llvm::BasicBlock *> bCases;
386
1/2
✓ Branch 3 → 4 taken 41 times.
✗ Branch 3 → 122 not taken.
41 bCases.reserve(node->caseBranches.size());
387
2/2
✓ Branch 23 → 6 taken 305 times.
✓ Branch 23 → 24 taken 41 times.
387 for (const auto caseBranch : node->caseBranches)
388
4/8
✓ Branch 8 → 9 taken 305 times.
✗ Branch 8 → 98 not taken.
✓ Branch 9 → 10 taken 305 times.
✗ Branch 9 → 96 not taken.
✓ Branch 10 → 11 taken 305 times.
✗ Branch 10 → 94 not taken.
✓ Branch 11 → 12 taken 305 times.
✗ Branch 11 → 94 not taken.
305 bCases.push_back(createBlock("switch.case." + caseBranch->codeLoc.toPrettyLine()));
389 41 llvm::BasicBlock *bDefault = nullptr;
390
2/2
✓ Branch 24 → 25 taken 25 times.
✓ Branch 24 → 31 taken 16 times.
41 if (node->hasDefaultBranch)
391
3/6
✓ Branch 25 → 26 taken 25 times.
✗ Branch 25 → 106 not taken.
✓ Branch 26 → 27 taken 25 times.
✗ Branch 26 → 104 not taken.
✓ Branch 27 → 28 taken 25 times.
✗ Branch 27 → 102 not taken.
25 bDefault = createBlock("switch.default." + node->defaultBranch->codeLoc.toPrettyLine());
392
1/2
✓ Branch 31 → 32 taken 41 times.
✗ Branch 31 → 122 not taken.
41 const std::string codeLine = node->codeLoc.toPrettyLine();
393
2/4
✓ Branch 32 → 33 taken 41 times.
✗ Branch 32 → 110 not taken.
✓ Branch 33 → 34 taken 41 times.
✗ Branch 33 → 108 not taken.
41 llvm::BasicBlock *bExit = createBlock("switch.exit." + codeLine);
394
395 // Save the break target. The scope to clean up to is set by each case/default branch as it is visited below,
396 // since it changes per branch (there is no single scope spanning the whole switch statement).
397
1/2
✓ Branch 35 → 36 taken 41 times.
✗ Branch 35 → 111 not taken.
41 breakTargets.emplace_back(nullptr, bExit);
398
399 // Visit switch expression
400
1/2
✓ Branch 36 → 37 taken 41 times.
✗ Branch 36 → 120 not taken.
41 llvm::Value *exprValue = resolveValue(node->assignExpr);
401
402 // Generate switch instruction
403
3/4
✓ Branch 38 → 39 taken 25 times.
✓ Branch 38 → 40 taken 16 times.
✓ Branch 41 → 42 taken 41 times.
✗ Branch 41 → 120 not taken.
41 llvm::SwitchInst *switchInst = builder.CreateSwitch(exprValue, bDefault ? bDefault : bExit, node->caseBranches.size());
404
405 // Generate case branches
406
2/2
✓ Branch 77 → 43 taken 305 times.
✓ Branch 77 → 78 taken 41 times.
346 for (size_t i = 0; i < node->caseBranches.size(); i++) {
407
1/2
✓ Branch 43 → 44 taken 305 times.
✗ Branch 43 → 117 not taken.
305 const CaseBranchNode *caseBranch = node->caseBranches.at(i);
408
409 // Push fallthrough block
410 305 llvm::BasicBlock *bFallthrough = bDefault;
411
2/2
✓ Branch 45 → 46 taken 264 times.
✓ Branch 45 → 48 taken 41 times.
305 if (i + 1 < node->caseBranches.size())
412
1/2
✓ Branch 46 → 47 taken 264 times.
✗ Branch 46 → 117 not taken.
264 bFallthrough = bCases.at(i + 1);
413
1/2
✓ Branch 48 → 49 taken 305 times.
✗ Branch 48 → 117 not taken.
305 fallthroughBlocks.push(bFallthrough);
414
415 // Switch to case block
416
2/4
✓ Branch 49 → 50 taken 305 times.
✗ Branch 49 → 117 not taken.
✓ Branch 50 → 51 taken 305 times.
✗ Branch 50 → 117 not taken.
305 switchToBlock(bCases.at(i));
417
418 // Visit case body
419
1/2
✓ Branch 51 → 52 taken 305 times.
✗ Branch 51 → 112 not taken.
305 visit(caseBranch);
420
421 // Create jump from case to exit block
422
1/2
✓ Branch 53 → 54 taken 305 times.
✗ Branch 53 → 117 not taken.
305 insertJump(bExit);
423
424 // Pop fallthrough block
425
1/2
✓ Branch 54 → 55 taken 305 times.
✗ Branch 54 → 117 not taken.
305 fallthroughBlocks.pop();
426
427 // Add case to switch instruction
428
2/2
✓ Branch 74 → 57 taken 315 times.
✓ Branch 74 → 75 taken 305 times.
925 for (const CaseConstantNode *caseConstantNode : caseBranch->caseConstants) {
429
2/4
✓ Branch 59 → 60 taken 315 times.
✗ Branch 59 → 115 not taken.
✓ Branch 60 → 61 taken 315 times.
✗ Branch 60 → 113 not taken.
315 const auto caseValue = std::any_cast<llvm::Constant *>(visit(caseConstantNode));
430
3/6
✓ Branch 62 → 63 taken 315 times.
✗ Branch 62 → 116 not taken.
✓ Branch 63 → 64 taken 315 times.
✗ Branch 63 → 116 not taken.
✓ Branch 64 → 65 taken 315 times.
✗ Branch 64 → 116 not taken.
315 switchInst->addCase(llvm::cast<llvm::ConstantInt>(caseValue), bCases.at(i));
431 }
432 }
433
434 // Generate default branch
435
2/2
✓ Branch 78 → 79 taken 25 times.
✓ Branch 78 → 83 taken 16 times.
41 if (node->hasDefaultBranch) {
436 // Switch to default block
437
1/2
✓ Branch 79 → 80 taken 25 times.
✗ Branch 79 → 120 not taken.
25 switchToBlock(bDefault);
438
439 // Visit default body
440
1/2
✓ Branch 80 → 81 taken 25 times.
✗ Branch 80 → 118 not taken.
25 visit(node->defaultBranch);
441
442 // Create jump from default to exit block
443
1/2
✓ Branch 82 → 83 taken 25 times.
✗ Branch 82 → 120 not taken.
25 insertJump(bExit);
444 }
445
446 // Switch to exit block
447
1/2
✓ Branch 83 → 84 taken 41 times.
✗ Branch 83 → 120 not taken.
41 switchToBlock(bExit);
448
449 // Pop break target
450
1/2
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 41 times.
41 assert(breakTargets.back().block == bExit);
451 41 breakTargets.pop_back();
452
453
1/2
✓ Branch 88 → 89 taken 41 times.
✗ Branch 88 → 119 not taken.
82 return nullptr;
454 41 }
455
456 305 std::any IRGenerator::visitCaseBranch(const CaseBranchNode *node) {
457 // Change to case body scope
458
2/4
✓ Branch 2 → 3 taken 305 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 305 times.
✗ Branch 3 → 13 not taken.
305 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::CASE_BODY);
459
460 // A 'break' within this branch targets the enclosing switch; point it at this branch's own scope
461 305 breakTargets.back().scope = currentScope;
462
463 // Visit case body
464
1/2
✓ Branch 6 → 7 taken 305 times.
✗ Branch 6 → 17 not taken.
305 visit(node->body);
465
466
1/2
✓ Branch 8 → 9 taken 305 times.
✗ Branch 8 → 18 not taken.
610 return nullptr;
467 305 }
468
469 25 std::any IRGenerator::visitDefaultBranch(const DefaultBranchNode *node) {
470 // Change to default body scope
471
2/4
✓ Branch 2 → 3 taken 25 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 25 times.
✗ Branch 3 → 13 not taken.
25 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::DEFAULT_BODY);
472
473 // A 'break' within this branch targets the enclosing switch; point it at this branch's own scope
474 25 breakTargets.back().scope = currentScope;
475
476 // Visit case body
477
1/2
✓ Branch 6 → 7 taken 25 times.
✗ Branch 6 → 17 not taken.
25 visit(node->body);
478
479
1/2
✓ Branch 8 → 9 taken 25 times.
✗ Branch 8 → 18 not taken.
50 return nullptr;
480 25 }
481
482 177 std::any IRGenerator::visitAnonymousBlockStmt(const AnonymousBlockStmtNode *node) {
483 // Change scope
484 177 node->bodyScope->parent = currentScope; // Needed for nested scopes in generic functions
485 177 node->bodyScope->symbolTable.parent = &currentScope->symbolTable; // Needed for nested scopes in generic functions
486
2/4
✓ Branch 2 → 3 taken 177 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 177 times.
✗ Branch 3 → 12 not taken.
177 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::ANONYMOUS_BLOCK_BODY, node);
487
488 // Visit instructions in the block
489
1/2
✓ Branch 5 → 6 taken 177 times.
✗ Branch 5 → 16 not taken.
177 visit(node->body);
490
491
1/2
✓ Branch 7 → 8 taken 177 times.
✗ Branch 7 → 17 not taken.
354 return nullptr;
492 177 }
493
494 } // namespace spice::compiler
495