GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 99.6% 248 / 0 / 249
Functions: 100.0% 11 / 0 / 11
Branches: 54.2% 312 / 0 / 576

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