Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include "IRGenerator.h" | ||
4 | |||
5 | #include <ast/ASTNodes.h> | ||
6 | |||
7 | #include <llvm/IR/Module.h> | ||
8 | |||
9 | namespace spice::compiler { | ||
10 | |||
11 | 43019 | std::any IRGenerator::visitAssignExpr(const AssignExprNode *node) { | |
12 | 43019 | diGenerator.setSourceLocation(node); | |
13 | |||
14 | // Visit ternary expression | ||
15 |
2/2✓ Branch 1 taken 38571 times.
✓ Branch 2 taken 4448 times.
|
43019 | if (node->ternaryExpr()) |
16 | 38571 | return visit(node->ternaryExpr()); | |
17 | |||
18 | // Assign or compound assign operation | ||
19 |
1/2✓ Branch 0 taken 4448 times.
✗ Branch 1 not taken.
|
4448 | if (node->op != AssignExprNode::OP_NONE) { |
20 |
1/2✓ Branch 1 taken 4448 times.
✗ Branch 2 not taken.
|
4448 | const PrefixUnaryExprNode *lhsNode = node->lhs(); |
21 |
1/2✓ Branch 1 taken 4448 times.
✗ Branch 2 not taken.
|
4448 | const AssignExprNode *rhsNode = node->rhs(); |
22 | |||
23 | // Normal assignment | ||
24 |
2/2✓ Branch 0 taken 3949 times.
✓ Branch 1 taken 499 times.
|
4448 | if (node->op == AssignExprNode::OP_ASSIGN) |
25 |
2/4✓ Branch 1 taken 3949 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3949 times.
✗ Branch 5 not taken.
|
3949 | return doAssignment(lhsNode, rhsNode, node); |
26 | |||
27 | // Compound assignment | ||
28 | // Get symbol types of left and right side | ||
29 |
1/2✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
|
499 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
30 |
1/2✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
|
499 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
31 | |||
32 | // Retrieve rhs | ||
33 |
2/4✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 499 times.
✗ Branch 5 not taken.
|
499 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
34 | // Retrieve lhs | ||
35 |
2/4✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 499 times.
✗ Branch 5 not taken.
|
499 | auto lhs = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
36 | |||
37 | 499 | LLVMExprResult result; | |
38 |
10/11✓ Branch 0 taken 205 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 207 times.
✗ Branch 10 not taken.
|
499 | switch (node->op) { |
39 | 205 | case AssignExprNode::OP_PLUS_EQUAL: | |
40 |
1/2✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
|
205 | result = conversionManager.getPlusEqualInst(node, lhs, lhsSTy, rhs, rhsSTy, 0); |
41 | 205 | break; | |
42 | 27 | case AssignExprNode::OP_MINUS_EQUAL: | |
43 |
1/2✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
|
27 | result = conversionManager.getMinusEqualInst(node, lhs, lhsSTy, rhs, rhsSTy, 0); |
44 | 27 | break; | |
45 | 15 | case AssignExprNode::OP_MUL_EQUAL: | |
46 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | result = conversionManager.getMulEqualInst(node, lhs, lhsSTy, rhs, rhsSTy, 0); |
47 | 15 | break; | |
48 | 35 | case AssignExprNode::OP_DIV_EQUAL: | |
49 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | result = conversionManager.getDivEqualInst(node, lhs, lhsSTy, rhs, rhsSTy, 0); |
50 | 35 | break; | |
51 | 5 | case AssignExprNode::OP_REM_EQUAL: | |
52 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | result = conversionManager.getRemEqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
53 | 5 | break; | |
54 | 1 | case AssignExprNode::OP_SHL_EQUAL: | |
55 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | result = conversionManager.getSHLEqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
56 | 1 | break; | |
57 | 2 | case AssignExprNode::OP_SHR_EQUAL: | |
58 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | result = conversionManager.getSHREqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
59 | 2 | break; | |
60 | 1 | case AssignExprNode::OP_AND_EQUAL: | |
61 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | result = conversionManager.getAndEqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
62 | 1 | break; | |
63 | 1 | case AssignExprNode::OP_OR_EQUAL: | |
64 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | result = conversionManager.getOrEqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
65 | 1 | break; | |
66 | 207 | case AssignExprNode::OP_XOR_EQUAL: | |
67 |
1/2✓ Branch 1 taken 207 times.
✗ Branch 2 not taken.
|
207 | result = conversionManager.getXorEqualInst(node, lhs, lhsSTy, rhs, rhsSTy); |
68 | 207 | break; | |
69 | − | default: // GCOV_EXCL_LINE | |
70 | − | throw CompilerError(UNHANDLED_BRANCH, "Assign op fall-through"); // GCOV_EXCL_LINE | |
71 | } | ||
72 | |||
73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
|
499 | if (result.ptr) { // The operation allocated more memory |
74 | ✗ | if (lhs.entry) | |
75 | ✗ | lhs.entry->updateAddress(result.ptr); | |
76 |
2/2✓ Branch 0 taken 379 times.
✓ Branch 1 taken 120 times.
|
499 | } else if (result.value) { // The operation only updated the value |
77 | // Store the result | ||
78 | 379 | lhs.value = result.value; | |
79 |
5/6✓ Branch 0 taken 171 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 169 times.
✓ Branch 5 taken 379 times.
✗ Branch 6 not taken.
|
379 | insertStore(lhs.value, lhs.ptr, lhs.entry && lhs.entry->isVolatile); |
80 | } | ||
81 |
1/2✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
|
998 | return LLVMExprResult{.value = lhs.value, .ptr = lhs.ptr, .refPtr = lhs.refPtr, .entry = lhs.entry}; |
82 | } | ||
83 | |||
84 | // This is a fallthrough case -> throw an error | ||
85 | − | throw CompilerError(UNHANDLED_BRANCH, "AssignStmt fall-through"); // GCOV_EXCL_LINE | |
86 | } | ||
87 | |||
88 | 38789 | std::any IRGenerator::visitTernaryExpr(const TernaryExprNode *node) { | |
89 | 38789 | diGenerator.setSourceLocation(node); | |
90 | |||
91 | // Check if only one operand is present -> loop through | ||
92 |
3/4✓ Branch 1 taken 38789 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 38526 times.
✓ Branch 6 taken 263 times.
|
38789 | if (node->operands().size() == 1) |
93 |
2/4✓ Branch 1 taken 38526 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 38526 times.
✗ Branch 6 not taken.
|
77052 | return visit(node->operands().front()); |
94 | |||
95 | // It is a ternary | ||
96 | // Retrieve the condition value | ||
97 |
2/4✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 263 times.
✗ Branch 6 not taken.
|
263 | llvm::Value *condValue = resolveValue(node->operands()[0]); |
98 | |||
99 | // Get the values of true and false | ||
100 | llvm::Value *trueValue; | ||
101 | llvm::Value *falseValue; | ||
102 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 262 times.
|
263 | if (node->isShortened) { |
103 | 1 | trueValue = condValue; | |
104 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | falseValue = resolveValue(node->operands()[1]); |
105 | } else { | ||
106 |
2/4✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 262 times.
✗ Branch 6 not taken.
|
262 | trueValue = resolveValue(node->operands()[1]); |
107 |
2/4✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 262 times.
✗ Branch 6 not taken.
|
262 | falseValue = resolveValue(node->operands()[2]); |
108 | } | ||
109 | |||
110 |
2/4✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 263 times.
✗ Branch 5 not taken.
|
263 | llvm::Value *resultValue = builder.CreateSelect(condValue, trueValue, falseValue); |
111 |
1/2✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
|
526 | return LLVMExprResult{.value = resultValue}; |
112 | } | ||
113 | |||
114 | 39314 | std::any IRGenerator::visitLogicalOrExpr(const LogicalOrExprNode *node) { | |
115 |
1/2✓ Branch 1 taken 39314 times.
✗ Branch 2 not taken.
|
39314 | diGenerator.setSourceLocation(node); |
116 | |||
117 | // Check if only one operand is present -> loop through | ||
118 |
3/4✓ Branch 1 taken 39314 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39073 times.
✓ Branch 6 taken 241 times.
|
39314 | if (node->operands().size() == 1) |
119 |
2/4✓ Branch 1 taken 39073 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39073 times.
✗ Branch 6 not taken.
|
78146 | return visit(node->operands().front()); |
120 | |||
121 | // It is a logical or expression | ||
122 | // Create exit block for short-circuiting | ||
123 |
1/2✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
|
241 | const std::string codeLoc = node->codeLoc.toPrettyLineAndColumn(); |
124 |
2/4✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
|
241 | llvm::BasicBlock *bExit = createBlock("lor.exit." + codeLoc); |
125 | |||
126 | // Visit the first operand | ||
127 |
2/4✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 241 times.
✗ Branch 6 not taken.
|
241 | llvm::Value *firstOperandValue = resolveValue(node->operands().front()); |
128 | |||
129 | // Prepare an array for value-to-block-mapping | ||
130 | 241 | std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> shortCircuitBlocks; | |
131 |
2/4✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 241 times.
✗ Branch 6 not taken.
|
241 | shortCircuitBlocks.reserve(node->operands().size()); |
132 | // The first element is the first operand value with the original block | ||
133 |
1/2✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
|
241 | shortCircuitBlocks.emplace_back(builder.GetInsertBlock(), firstOperandValue); |
134 | // Create a block for each additional operand and save it to the mapping | ||
135 |
3/4✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 265 times.
✓ Branch 6 taken 241 times.
|
506 | for (size_t i = 1; i < node->operands().size(); i++) |
136 |
6/12✓ Branch 1 taken 265 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 265 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 265 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 265 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 265 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 265 times.
✗ Branch 17 not taken.
|
265 | shortCircuitBlocks.emplace_back(createBlock("lor." + std::to_string(i) + "." + codeLoc), nullptr); |
137 | // Create conditional jump to the exit block if the first operand was true, otherwise to the next block | ||
138 |
2/4✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
|
241 | insertCondJump(firstOperandValue, bExit, shortCircuitBlocks.at(1).first); |
139 | |||
140 | // Create block for each operand | ||
141 |
3/4✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 265 times.
✓ Branch 6 taken 241 times.
|
506 | for (size_t i = 1; i < node->operands().size(); i++) { |
142 | // Switch to the next block | ||
143 |
2/4✓ Branch 1 taken 265 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 265 times.
✗ Branch 5 not taken.
|
265 | switchToBlock(shortCircuitBlocks.at(i).first); |
144 | // Evaluate operand and save the result in the mapping | ||
145 |
3/6✓ Branch 1 taken 265 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 265 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 265 times.
✗ Branch 9 not taken.
|
265 | shortCircuitBlocks.at(i).second = resolveValue(node->operands()[i]); |
146 | // Replace the array entry with the current insert block, since the insert block could have changed in the meantime | ||
147 |
1/2✓ Branch 2 taken 265 times.
✗ Branch 3 not taken.
|
265 | shortCircuitBlocks.at(i).first = builder.GetInsertBlock(); |
148 | // Check if there are more blocks to process | ||
149 |
3/4✓ Branch 1 taken 265 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 241 times.
✓ Branch 6 taken 24 times.
|
265 | if (i == node->operands().size() - 1) { |
150 | // Insert a simple jump to the exit block for the last block | ||
151 |
1/2✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
|
241 | insertJump(bExit); |
152 | } else { | ||
153 | // Create conditional jump to the exit block if the first operand was true, otherwise to the next block | ||
154 |
3/6✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
|
24 | insertCondJump(shortCircuitBlocks.at(i).second, bExit, shortCircuitBlocks.at(i + 1).first); |
155 | } | ||
156 | } | ||
157 | |||
158 | // Get the result with the phi node | ||
159 |
1/2✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
|
241 | switchToBlock(bExit); |
160 |
3/6✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 241 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 241 times.
✗ Branch 10 not taken.
|
241 | llvm::PHINode *result = builder.CreatePHI(firstOperandValue->getType(), node->operands().size(), "lor_phi"); |
161 |
2/2✓ Branch 7 taken 506 times.
✓ Branch 8 taken 241 times.
|
747 | for (const auto &[incomingBlock, value] : shortCircuitBlocks) |
162 |
1/2✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
|
506 | result->addIncoming(value, incomingBlock); |
163 | |||
164 | // Return the result | ||
165 |
1/2✓ Branch 1 taken 241 times.
✗ Branch 2 not taken.
|
241 | return LLVMExprResult{.value = result}; |
166 | 241 | } | |
167 | |||
168 | 39579 | std::any IRGenerator::visitLogicalAndExpr(const LogicalAndExprNode *node) { | |
169 |
1/2✓ Branch 1 taken 39579 times.
✗ Branch 2 not taken.
|
39579 | diGenerator.setSourceLocation(node); |
170 | |||
171 | // Check if only one operand is present -> loop through | ||
172 |
3/4✓ Branch 1 taken 39579 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39523 times.
✓ Branch 6 taken 56 times.
|
39579 | if (node->operands().size() == 1) |
173 |
2/4✓ Branch 1 taken 39523 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39523 times.
✗ Branch 6 not taken.
|
79046 | return visit(node->operands().front()); |
174 | |||
175 | // It is a logical and expression | ||
176 | // Create exit block for short-circuiting | ||
177 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | const std::string codeLoc = node->codeLoc.toPrettyLineAndColumn(); |
178 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | llvm::BasicBlock *bExit = createBlock("land.exit." + codeLoc); |
179 | |||
180 | // Visit the first operand | ||
181 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 56 times.
✗ Branch 6 not taken.
|
56 | llvm::Value *firstOperandValue = resolveValue(node->operands().front()); |
182 | |||
183 | // Prepare an array for value-to-block-mapping | ||
184 | 56 | std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> shortCircuitBlocks; | |
185 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 56 times.
✗ Branch 6 not taken.
|
56 | shortCircuitBlocks.reserve(node->operands().size()); |
186 | // The first element is the first operand value with the original block | ||
187 |
1/2✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | shortCircuitBlocks.emplace_back(builder.GetInsertBlock(), firstOperandValue); |
188 | // Create a block for each additional operand and save it to the mapping | ||
189 |
3/4✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 61 times.
✓ Branch 6 taken 56 times.
|
117 | for (size_t i = 1; i < node->operands().size(); i++) |
190 |
6/12✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 61 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 61 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 61 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 61 times.
✗ Branch 17 not taken.
|
61 | shortCircuitBlocks.emplace_back(createBlock("land." + std::to_string(i) + "." + codeLoc), nullptr); |
191 | // Create conditional jump to the exit block if the first operand was true, otherwise to the next block | ||
192 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | insertCondJump(firstOperandValue, shortCircuitBlocks.at(1).first, bExit); |
193 | |||
194 | // Create block for each operand | ||
195 |
3/4✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 61 times.
✓ Branch 6 taken 56 times.
|
117 | for (size_t i = 1; i < node->operands().size(); i++) { |
196 | // Switch to the next block | ||
197 |
2/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
|
61 | switchToBlock(shortCircuitBlocks.at(i).first); |
198 | // Evaluate operand and save the result in the mapping | ||
199 |
3/6✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 61 times.
✗ Branch 9 not taken.
|
61 | shortCircuitBlocks.at(i).second = resolveValue(node->operands()[i]); |
200 | // Replace the array entry with the current insert block, since the insert block could have changed in the meantime | ||
201 |
1/2✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
|
61 | shortCircuitBlocks.at(i).first = builder.GetInsertBlock(); |
202 | // Check if there are more blocks to process | ||
203 |
3/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 5 times.
|
61 | if (i == node->operands().size() - 1) { |
204 | // Insert a simple jump to the exit block for the last block | ||
205 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | insertJump(bExit); |
206 | } else { | ||
207 | // Create conditional jump to the exit block if the operand was true, otherwise to the next block | ||
208 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
|
5 | insertCondJump(shortCircuitBlocks.at(i).second, shortCircuitBlocks.at(i + 1).first, bExit); |
209 | } | ||
210 | } | ||
211 | |||
212 | // Get the result with the phi node | ||
213 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | switchToBlock(bExit); |
214 |
3/6✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 56 times.
✗ Branch 10 not taken.
|
56 | llvm::PHINode *result = builder.CreatePHI(firstOperandValue->getType(), node->operands().size(), "land_phi"); |
215 |
2/2✓ Branch 7 taken 117 times.
✓ Branch 8 taken 56 times.
|
173 | for (const auto &[incomingBlock, value] : shortCircuitBlocks) |
216 |
1/2✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
|
117 | result->addIncoming(value, incomingBlock); |
217 | |||
218 | // Return the result | ||
219 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | return LLVMExprResult{.value = result}; |
220 | 56 | } | |
221 | |||
222 | 39640 | std::any IRGenerator::visitBitwiseOrExpr(const BitwiseOrExprNode *node) { | |
223 |
1/2✓ Branch 1 taken 39640 times.
✗ Branch 2 not taken.
|
39640 | diGenerator.setSourceLocation(node); |
224 | |||
225 | // Check if only one operand is present -> loop through | ||
226 |
3/4✓ Branch 1 taken 39640 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39610 times.
✓ Branch 6 taken 30 times.
|
39640 | if (node->operands().size() == 1) |
227 |
2/4✓ Branch 1 taken 39610 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39610 times.
✗ Branch 6 not taken.
|
79220 | return visit(node->operands().front()); |
228 | |||
229 | // It is a bitwise or expression | ||
230 | // Evaluate first operand | ||
231 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | const BitwiseXorExprNode *lhsNode = node->operands().front(); |
232 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
233 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
234 | |||
235 | // Evaluate all additional operands | ||
236 |
3/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 30 times.
|
61 | for (size_t i = 1; i < node->operands().size(); i++) { |
237 | // Evaluate the operand | ||
238 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | const BitwiseXorExprNode *rhsNode = node->operands()[i]; |
239 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | const QualType rhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
240 |
2/4✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
|
31 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
241 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | result = conversionManager.getBitwiseOrInst(node, result, lhsSTy, rhs, rhsSTy, i - 1); |
242 | } | ||
243 | |||
244 | // Return result | ||
245 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | return result; |
246 | } | ||
247 | |||
248 | 39671 | std::any IRGenerator::visitBitwiseXorExpr(const BitwiseXorExprNode *node) { | |
249 |
1/2✓ Branch 1 taken 39671 times.
✗ Branch 2 not taken.
|
39671 | diGenerator.setSourceLocation(node); |
250 | |||
251 | // Check if only one operand is present -> loop through | ||
252 |
3/4✓ Branch 1 taken 39671 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39669 times.
✓ Branch 6 taken 2 times.
|
39671 | if (node->operands().size() == 1) |
253 |
2/4✓ Branch 1 taken 39669 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39669 times.
✗ Branch 6 not taken.
|
79338 | return visit(node->operands().front()); |
254 | |||
255 | // It is a bitwise xor expression | ||
256 | // Evaluate first operand | ||
257 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const BitwiseAndExprNode *lhsNode = node->operands().front(); |
258 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
259 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
260 | |||
261 | // Evaluate all additional operands | ||
262 |
3/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 2 times.
|
5 | for (size_t i = 1; i < node->operands().size(); i++) { |
263 | // Evaluate the operand | ||
264 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const BitwiseAndExprNode *rhsNode = node->operands()[i]; |
265 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const QualType rhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
266 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
267 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | result = conversionManager.getBitwiseXorInst(node, result, lhsSTy, rhs, rhsSTy); |
268 | } | ||
269 | |||
270 | // Return result | ||
271 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | return result; |
272 | } | ||
273 | |||
274 | 39674 | std::any IRGenerator::visitBitwiseAndExpr(const BitwiseAndExprNode *node) { | |
275 |
1/2✓ Branch 1 taken 39674 times.
✗ Branch 2 not taken.
|
39674 | diGenerator.setSourceLocation(node); |
276 | |||
277 | // Check if only one operand is present -> loop through | ||
278 |
3/4✓ Branch 1 taken 39674 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39646 times.
✓ Branch 6 taken 28 times.
|
39674 | if (node->operands().size() == 1) |
279 |
2/4✓ Branch 1 taken 39646 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39646 times.
✗ Branch 6 not taken.
|
79292 | return visit(node->operands().front()); |
280 | |||
281 | // It is a bitwise and expression | ||
282 | // Evaluate first operand | ||
283 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | const EqualityExprNode *lhsNode = node->operands().front(); |
284 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
285 |
2/4✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
28 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
286 | |||
287 | // Evaluate all additional operands | ||
288 |
3/4✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 29 times.
✓ Branch 6 taken 28 times.
|
57 | for (size_t i = 1; i < node->operands().size(); i++) { |
289 | // Evaluate the operand | ||
290 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | const EqualityExprNode *rhsNode = node->operands()[i]; |
291 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | const QualType rhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
292 |
2/4✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 29 times.
✗ Branch 5 not taken.
|
29 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
293 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | result = conversionManager.getBitwiseAndInst(rhsNode, result, lhsSTy, rhs, rhsSTy, i - 1); |
294 | } | ||
295 | |||
296 | // Return result | ||
297 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | return result; |
298 | } | ||
299 | |||
300 | 39703 | std::any IRGenerator::visitEqualityExpr(const EqualityExprNode *node) { | |
301 |
1/2✓ Branch 1 taken 39703 times.
✗ Branch 2 not taken.
|
39703 | diGenerator.setSourceLocation(node); |
302 | |||
303 | // Check if only one operand is present -> loop through | ||
304 |
3/4✓ Branch 1 taken 39703 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 36268 times.
✓ Branch 6 taken 3435 times.
|
39703 | if (node->operands().size() == 1) |
305 |
2/4✓ Branch 1 taken 36268 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 36268 times.
✗ Branch 6 not taken.
|
72536 | return visit(node->operands().front()); |
306 | |||
307 | // It is an equality expression | ||
308 | // Evaluate lhs | ||
309 |
1/2✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
|
3435 | const RelationalExprNode *lhsNode = node->operands()[0]; |
310 |
1/2✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
|
3435 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
311 |
2/4✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3435 times.
✗ Branch 5 not taken.
|
3435 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
312 | |||
313 | // Evaluate rhs | ||
314 |
1/2✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
|
3435 | const RelationalExprNode *rhsNode = node->operands()[1]; |
315 |
1/2✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
|
3435 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
316 |
2/4✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3435 times.
✗ Branch 5 not taken.
|
3435 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
317 | |||
318 | // Retrieve the result value, based on the exact operator | ||
319 |
2/3✓ Branch 0 taken 2219 times.
✓ Branch 1 taken 1216 times.
✗ Branch 2 not taken.
|
3435 | switch (node->op) { |
320 | 2219 | case EqualityExprNode::OP_EQUAL: | |
321 |
1/2✓ Branch 1 taken 2219 times.
✗ Branch 2 not taken.
|
2219 | result = conversionManager.getEqualInst(node, result, lhsSTy, rhs, rhsSTy, 0); |
322 | 2219 | break; | |
323 | 1216 | case EqualityExprNode::OP_NOT_EQUAL: | |
324 |
1/2✓ Branch 1 taken 1216 times.
✗ Branch 2 not taken.
|
1216 | result = conversionManager.getNotEqualInst(node, result, lhsSTy, rhs, rhsSTy, 0); |
325 | 1216 | break; | |
326 | − | default: // GCOV_EXCL_LINE | |
327 | − | throw CompilerError(UNHANDLED_BRANCH, "EqualityExpr fall-through"); // GCOV_EXCL_LINE | |
328 | } | ||
329 | |||
330 | // Return the result | ||
331 |
1/2✓ Branch 1 taken 3435 times.
✗ Branch 2 not taken.
|
3435 | return result; |
332 | } | ||
333 | |||
334 | 43138 | std::any IRGenerator::visitRelationalExpr(const RelationalExprNode *node) { | |
335 |
1/2✓ Branch 1 taken 43138 times.
✗ Branch 2 not taken.
|
43138 | diGenerator.setSourceLocation(node); |
336 | |||
337 | // Check if only one operand is present -> loop through | ||
338 |
3/4✓ Branch 1 taken 43138 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 40822 times.
✓ Branch 6 taken 2316 times.
|
43138 | if (node->operands().size() == 1) |
339 |
2/4✓ Branch 1 taken 40822 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 40822 times.
✗ Branch 6 not taken.
|
81644 | return visit(node->operands().front()); |
340 | |||
341 | // It is a relational expression | ||
342 | // Evaluate lhs | ||
343 |
1/2✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
|
2316 | const ShiftExprNode *lhsNode = node->operands()[0]; |
344 |
1/2✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
|
2316 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
345 |
2/4✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2316 times.
✗ Branch 5 not taken.
|
2316 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
346 | |||
347 | // Evaluate rhs | ||
348 |
1/2✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
|
2316 | const ShiftExprNode *rhsNode = node->operands()[1]; |
349 |
1/2✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
|
2316 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
350 |
2/4✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2316 times.
✗ Branch 5 not taken.
|
2316 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
351 | |||
352 | // Retrieve the result value, based on the exact operator | ||
353 |
4/5✓ Branch 0 taken 1344 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 236 times.
✓ Branch 3 taken 514 times.
✗ Branch 4 not taken.
|
2316 | switch (node->op) { |
354 | 1344 | case RelationalExprNode::OP_LESS: | |
355 |
1/2✓ Branch 1 taken 1344 times.
✗ Branch 2 not taken.
|
1344 | result = conversionManager.getLessInst(node, result, lhsSTy, rhs, rhsSTy); |
356 | 1344 | break; | |
357 | 222 | case RelationalExprNode::OP_GREATER: | |
358 |
1/2✓ Branch 1 taken 222 times.
✗ Branch 2 not taken.
|
222 | result = conversionManager.getGreaterInst(node, result, lhsSTy, rhs, rhsSTy); |
359 | 222 | break; | |
360 | 236 | case RelationalExprNode::OP_LESS_EQUAL: | |
361 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | result = conversionManager.getLessEqualInst(node, result, lhsSTy, rhs, rhsSTy); |
362 | 236 | break; | |
363 | 514 | case RelationalExprNode::OP_GREATER_EQUAL: | |
364 |
1/2✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
|
514 | result = conversionManager.getGreaterEqualInst(node, result, lhsSTy, rhs, rhsSTy); |
365 | 514 | break; | |
366 | − | default: // GCOV_EXCL_LINE | |
367 | − | throw CompilerError(UNHANDLED_BRANCH, "EqualityExpr fall-through"); // GCOV_EXCL_LINE | |
368 | } | ||
369 | |||
370 | // Return the result | ||
371 |
1/2✓ Branch 1 taken 2316 times.
✗ Branch 2 not taken.
|
2316 | return result; |
372 | } | ||
373 | |||
374 | 45454 | std::any IRGenerator::visitShiftExpr(const ShiftExprNode *node) { | |
375 |
1/2✓ Branch 1 taken 45454 times.
✗ Branch 2 not taken.
|
45454 | diGenerator.setSourceLocation(node); |
376 | |||
377 | // Check if only one operand is present -> loop through | ||
378 |
3/4✓ Branch 1 taken 45454 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45439 times.
✓ Branch 6 taken 15 times.
|
45454 | if (node->operands().size() == 1) |
379 |
2/4✓ Branch 1 taken 45439 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45439 times.
✗ Branch 6 not taken.
|
90878 | return visit(node->operands().front()); |
380 | |||
381 | // It is a shift expression | ||
382 | // Evaluate lhs | ||
383 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | const AdditiveExprNode *lhsNode = node->operands()[0]; |
384 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
385 |
2/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
|
15 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
386 | |||
387 | // Evaluate rhs | ||
388 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | const AdditiveExprNode *rhsNode = node->operands()[1]; |
389 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
390 |
2/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
|
15 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
391 | |||
392 | // Retrieve the result value, based on the exact operator | ||
393 |
2/3✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
15 | switch (node->op) { |
394 | 10 | case ShiftExprNode::OP_SHIFT_LEFT: | |
395 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | result = conversionManager.getShiftLeftInst(node, result, lhsSTy, rhs, rhsSTy, 0); |
396 | 10 | break; | |
397 | 5 | case ShiftExprNode::OP_SHIFT_RIGHT: | |
398 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | result = conversionManager.getShiftRightInst(node, result, lhsSTy, rhs, rhsSTy, 0); |
399 | 5 | break; | |
400 | − | default: // GCOV_EXCL_LINE | |
401 | − | throw CompilerError(UNHANDLED_BRANCH, "ShiftExpr fall-through"); // GCOV_EXCL_LINE | |
402 | } | ||
403 | |||
404 | // Return the result | ||
405 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | return result; |
406 | } | ||
407 | |||
408 | 45469 | std::any IRGenerator::visitAdditiveExpr(const AdditiveExprNode *node) { | |
409 |
1/2✓ Branch 1 taken 45469 times.
✗ Branch 2 not taken.
|
45469 | diGenerator.setSourceLocation(node); |
410 | |||
411 | // Check if only one operand is present -> loop through | ||
412 |
3/4✓ Branch 1 taken 45469 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 42725 times.
✓ Branch 6 taken 2744 times.
|
45469 | if (node->operands().size() == 1) |
413 |
2/4✓ Branch 1 taken 42725 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 42725 times.
✗ Branch 6 not taken.
|
85450 | return visit(node->operands().front()); |
414 | |||
415 | // It is an additive expression | ||
416 | // Evaluate first operand | ||
417 |
1/2✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
|
2744 | const MultiplicativeExprNode *lhsNode = node->operands()[0]; |
418 |
1/2✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
|
2744 | QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
419 |
2/4✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2744 times.
✗ Branch 5 not taken.
|
2744 | auto lhs = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
420 | |||
421 |
1/2✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
|
2744 | auto opQueue = node->opQueue; |
422 | 2744 | size_t operandIndex = 1; | |
423 |
2/2✓ Branch 1 taken 3115 times.
✓ Branch 2 taken 2744 times.
|
5859 | while (!opQueue.empty()) { |
424 | 3115 | const size_t operatorIndex = operandIndex - 1; | |
425 | // Evaluate next operand | ||
426 |
1/2✓ Branch 1 taken 3115 times.
✗ Branch 2 not taken.
|
3115 | const MultiplicativeExprNode *rhsNode = node->operands()[operandIndex++]; |
427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3115 times.
|
3115 | assert(rhsNode != nullptr); |
428 |
1/2✓ Branch 1 taken 3115 times.
✗ Branch 2 not taken.
|
3115 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
429 |
2/4✓ Branch 1 taken 3115 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3115 times.
✗ Branch 5 not taken.
|
3115 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
430 | |||
431 | // Retrieve the result, based on the exact operator | ||
432 |
2/3✓ Branch 1 taken 1971 times.
✓ Branch 2 taken 1144 times.
✗ Branch 3 not taken.
|
3115 | switch (opQueue.front().first) { |
433 | 1971 | case AdditiveExprNode::OP_PLUS: | |
434 |
1/2✓ Branch 1 taken 1971 times.
✗ Branch 2 not taken.
|
1971 | lhs = conversionManager.getPlusInst(node, lhs, lhsSTy, rhs, rhsSTy, operatorIndex); |
435 | 1971 | break; | |
436 | 1144 | case AdditiveExprNode::OP_MINUS: | |
437 |
1/2✓ Branch 1 taken 1144 times.
✗ Branch 2 not taken.
|
1144 | lhs = conversionManager.getMinusInst(node, lhs, lhsSTy, rhs, rhsSTy, operatorIndex); |
438 | 1144 | break; | |
439 | − | default: // GCOV_EXCL_LINE | |
440 | − | throw CompilerError(UNHANDLED_BRANCH, "AdditiveExpr fall-through"); // GCOV_EXCL_LINE | |
441 | } | ||
442 | |||
443 | // Retrieve the new lhs symbol type | ||
444 | 3115 | lhsSTy = opQueue.front().second; | |
445 | |||
446 | 3115 | opQueue.pop(); | |
447 | } | ||
448 | |||
449 | // Return the result | ||
450 |
1/2✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
|
2744 | return lhs; |
451 | 2744 | } | |
452 | |||
453 | 48584 | std::any IRGenerator::visitMultiplicativeExpr(const MultiplicativeExprNode *node) { | |
454 |
1/2✓ Branch 1 taken 48584 times.
✗ Branch 2 not taken.
|
48584 | diGenerator.setSourceLocation(node); |
455 | |||
456 | // Check if only one operand is present -> loop through | ||
457 |
3/4✓ Branch 1 taken 48584 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 47799 times.
✓ Branch 6 taken 785 times.
|
48584 | if (node->operands().size() == 1) |
458 |
2/4✓ Branch 1 taken 47799 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 47799 times.
✗ Branch 6 not taken.
|
95598 | return visit(node->operands().front()); |
459 | |||
460 | // It is an additive expression | ||
461 | // Evaluate first operand | ||
462 |
1/2✓ Branch 1 taken 785 times.
✗ Branch 2 not taken.
|
785 | const CastExprNode *lhsNode = node->operands()[0]; |
463 |
1/2✓ Branch 1 taken 785 times.
✗ Branch 2 not taken.
|
785 | QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
464 |
2/4✓ Branch 1 taken 785 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 785 times.
✗ Branch 5 not taken.
|
785 | auto result = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
465 | |||
466 |
1/2✓ Branch 1 taken 785 times.
✗ Branch 2 not taken.
|
785 | auto opQueue = node->opQueue; |
467 | 785 | size_t operandIndex = 1; | |
468 |
2/2✓ Branch 1 taken 805 times.
✓ Branch 2 taken 785 times.
|
1590 | while (!opQueue.empty()) { |
469 | 805 | const size_t operatorIndex = operandIndex - 1; | |
470 | // Evaluate next operand | ||
471 |
1/2✓ Branch 1 taken 805 times.
✗ Branch 2 not taken.
|
805 | const CastExprNode *rhsNode = node->operands()[operandIndex++]; |
472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 805 times.
|
805 | assert(rhsNode != nullptr); |
473 |
1/2✓ Branch 1 taken 805 times.
✗ Branch 2 not taken.
|
805 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
474 |
2/4✓ Branch 1 taken 805 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 805 times.
✗ Branch 5 not taken.
|
805 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
475 | |||
476 | // Retrieve the result, based on the exact operator | ||
477 |
3/4✓ Branch 1 taken 603 times.
✓ Branch 2 taken 193 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
|
805 | switch (opQueue.front().first) { |
478 | 603 | case MultiplicativeExprNode::OP_MUL: | |
479 |
1/2✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
|
603 | result = conversionManager.getMulInst(node, result, lhsSTy, rhs, rhsSTy, operatorIndex); |
480 | 603 | break; | |
481 | 193 | case MultiplicativeExprNode::OP_DIV: | |
482 |
1/2✓ Branch 1 taken 193 times.
✗ Branch 2 not taken.
|
193 | result = conversionManager.getDivInst(node, result, lhsSTy, rhs, rhsSTy, operatorIndex); |
483 | 193 | break; | |
484 | 9 | case MultiplicativeExprNode::OP_REM: | |
485 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | result = conversionManager.getRemInst(node, result, lhsSTy, rhs, rhsSTy); |
486 | 9 | break; | |
487 | − | default: // GCOV_EXCL_LINE | |
488 | − | throw CompilerError(UNHANDLED_BRANCH, "MultiplicativeExpr fall-through"); // GCOV_EXCL_LINE | |
489 | } | ||
490 | |||
491 | // Retrieve the new lhs symbol type | ||
492 | 805 | lhsSTy = opQueue.front().second; | |
493 | 805 | opQueue.pop(); | |
494 | } | ||
495 | |||
496 | // Return the result | ||
497 |
1/2✓ Branch 1 taken 785 times.
✗ Branch 2 not taken.
|
785 | return result; |
498 | 785 | } | |
499 | |||
500 | 49389 | std::any IRGenerator::visitCastExpr(const CastExprNode *node) { | |
501 |
1/2✓ Branch 1 taken 49389 times.
✗ Branch 2 not taken.
|
49389 | diGenerator.setSourceLocation(node); |
502 | |||
503 | // Check if only one operand is present -> loop through | ||
504 |
2/2✓ Branch 0 taken 47233 times.
✓ Branch 1 taken 2156 times.
|
49389 | if (!node->isCast) |
505 |
2/4✓ Branch 1 taken 47233 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47233 times.
✗ Branch 5 not taken.
|
47233 | return visit(node->prefixUnaryExpr()); |
506 | |||
507 | // It is a cast expression | ||
508 | // Retrieve target symbol type | ||
509 |
1/2✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
|
2156 | const QualType targetSTy = node->getEvaluatedSymbolType(manIdx); |
510 | |||
511 | // Evaluate rhs | ||
512 |
1/2✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
|
2156 | const PrefixUnaryExprNode *rhsNode = node->prefixUnaryExpr(); |
513 |
1/2✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
|
2156 | const QualType rhsSTy = rhsNode->getEvaluatedSymbolType(manIdx); |
514 |
2/4✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2156 times.
✗ Branch 5 not taken.
|
2156 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
515 | |||
516 | // Retrieve the result value | ||
517 |
1/2✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
|
2156 | const LLVMExprResult result = conversionManager.getCastInst(node, targetSTy, rhs, rhsSTy); |
518 | |||
519 | // Return the result | ||
520 |
1/2✓ Branch 1 taken 2156 times.
✗ Branch 2 not taken.
|
2156 | return result; |
521 | } | ||
522 | |||
523 | 54534 | std::any IRGenerator::visitPrefixUnaryExpr(const PrefixUnaryExprNode *node) { | |
524 |
1/2✓ Branch 1 taken 54534 times.
✗ Branch 2 not taken.
|
54534 | diGenerator.setSourceLocation(node); |
525 | |||
526 | // If no operator is applied, simply visit the atomic expression | ||
527 |
2/2✓ Branch 0 taken 53837 times.
✓ Branch 1 taken 697 times.
|
54534 | if (node->op == PrefixUnaryExprNode::OP_NONE) |
528 |
2/4✓ Branch 1 taken 53837 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53837 times.
✗ Branch 5 not taken.
|
53837 | return visit(node->postfixUnaryExpr()); |
529 | |||
530 | // Evaluate lhs | ||
531 |
1/2✓ Branch 1 taken 697 times.
✗ Branch 2 not taken.
|
697 | const PrefixUnaryExprNode *lhsNode = node->prefixUnary(); |
532 |
1/2✓ Branch 1 taken 697 times.
✗ Branch 2 not taken.
|
697 | const QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
533 |
2/4✓ Branch 1 taken 697 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 697 times.
✗ Branch 5 not taken.
|
697 | auto lhs = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
534 | |||
535 |
7/8✓ Branch 0 taken 16 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 520 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 75 times.
✓ Branch 6 taken 55 times.
✗ Branch 7 not taken.
|
697 | switch (node->op) { |
536 | 16 | case PrefixUnaryExprNode::OP_MINUS: { | |
537 | // Execute operation | ||
538 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lhs = conversionManager.getPrefixMinusInst(node, lhs, lhsSTy); |
539 | |||
540 | // This operator can not work in-place, so we need additional memory | ||
541 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | lhs.ptr = insertAlloca(lhs.value->getType()); |
542 | |||
543 | // Store the new value | ||
544 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | insertStore(lhs.value, lhs.ptr); |
545 | |||
546 | 16 | break; | |
547 | } | ||
548 | 26 | case PrefixUnaryExprNode::OP_PLUS_PLUS: { | |
549 | // Make sure the value is present | ||
550 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | resolveValue(lhsNode, lhs); |
551 | |||
552 | // Execute operation | ||
553 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | lhs.value = conversionManager.getPrefixPlusPlusInst(node, lhs, lhsSTy).value; |
554 | |||
555 | // If this operation happens on a volatile variable, store the value directly | ||
556 |
3/4✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
|
26 | if (lhs.entry && lhs.entry->isVolatile) |
557 | ✗ | insertStore(lhs.value, lhs.ptr, true); | |
558 | |||
559 | // Save to the existing address if possible, otherwise (e.g. for literals) allocate new space | ||
560 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
|
26 | if (!lhs.ptr) |
561 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | lhs.ptr = insertAlloca(lhs.value->getType()); |
562 | |||
563 | // Store the new value | ||
564 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | insertStore(lhs.value, lhs.ptr); |
565 | |||
566 | 26 | break; | |
567 | } | ||
568 | 4 | case PrefixUnaryExprNode::OP_MINUS_MINUS: { | |
569 | // Make sure the value is present | ||
570 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | resolveValue(lhsNode, lhs); |
571 | |||
572 | // Execute operation | ||
573 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | lhs.value = conversionManager.getPrefixMinusMinusInst(node, lhs, lhsSTy).value; |
574 | |||
575 | // If this operation happens on a volatile variable, store the value directly | ||
576 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
4 | if (lhs.entry && lhs.entry->isVolatile) |
577 | ✗ | insertStore(lhs.value, lhs.ptr, true); | |
578 | |||
579 | // Save to the existing address if possible, otherwise (e.g. for literals) allocate new space | ||
580 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (!lhs.ptr) |
581 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | lhs.ptr = insertAlloca(lhs.value->getType()); |
582 | |||
583 | // Store the new value | ||
584 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | insertStore(lhs.value, lhs.ptr); |
585 | |||
586 | 4 | break; | |
587 | } | ||
588 | 520 | case PrefixUnaryExprNode::OP_NOT: { | |
589 | // Make sure the value is present | ||
590 |
1/2✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
|
520 | resolveValue(lhsNode, lhs); |
591 | |||
592 | // Execute operation | ||
593 |
1/2✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
|
520 | lhs = conversionManager.getPrefixNotInst(node, lhs, lhsSTy); |
594 | |||
595 | // This operator can not work in-place, so we need additional memory | ||
596 |
2/4✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 520 times.
✗ Branch 6 not taken.
|
520 | lhs.ptr = insertAlloca(lhs.value->getType()); |
597 | |||
598 | // Store the new value | ||
599 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 520 times.
✗ Branch 6 not taken.
|
520 | insertStore(lhs.value, lhs.ptr, lhs.entry && lhs.entry->isVolatile); |
600 | |||
601 | 520 | break; | |
602 | } | ||
603 | 1 | case PrefixUnaryExprNode::OP_BITWISE_NOT: { | |
604 | // Make sure the value is present | ||
605 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | resolveValue(lhsNode, lhs); |
606 | |||
607 | // Execute operation | ||
608 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | lhs = conversionManager.getPrefixBitwiseNotInst(node, lhs, lhsSTy); |
609 | |||
610 | // This operator can not work in-place, so we need additional memory | ||
611 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | lhs.ptr = insertAlloca(lhs.value->getType()); |
612 | |||
613 | // Store the new value | ||
614 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | insertStore(lhs.value, lhs.ptr, lhs.entry && lhs.entry->isVolatile); |
615 | |||
616 | 1 | break; | |
617 | } | ||
618 | 75 | case PrefixUnaryExprNode::OP_DEREFERENCE: { | |
619 | // Make sure the value is present | ||
620 |
1/2✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
|
75 | resolveValue(lhsNode, lhs); |
621 | |||
622 | // Execute operation | ||
623 | 75 | lhs.ptr = lhs.value; | |
624 | |||
625 | // Reset the value | ||
626 | 75 | lhs.value = nullptr; | |
627 | |||
628 | 75 | break; | |
629 | } | ||
630 | 55 | case PrefixUnaryExprNode::OP_ADDRESS_OF: { | |
631 | // Make sure the address is present | ||
632 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | resolveAddress(lhs); |
633 | |||
634 | // Execute operation | ||
635 | 55 | lhs.value = lhs.ptr; | |
636 | |||
637 | // Reset the address | ||
638 | 55 | lhs.ptr = nullptr; | |
639 | |||
640 | 55 | break; | |
641 | } | ||
642 | − | default: // GCOV_EXCL_LINE | |
643 | − | throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExpr fall-through"); // GCOV_EXCL_LINE | |
644 | } | ||
645 | |||
646 |
1/2✓ Branch 1 taken 697 times.
✗ Branch 2 not taken.
|
697 | return lhs; |
647 | } | ||
648 | |||
649 | 68564 | std::any IRGenerator::visitPostfixUnaryExpr(const PostfixUnaryExprNode *node) { | |
650 |
1/2✓ Branch 1 taken 68564 times.
✗ Branch 2 not taken.
|
68564 | diGenerator.setSourceLocation(node); |
651 | |||
652 | // If no operator is applied, simply visit the atomic expression | ||
653 |
2/2✓ Branch 0 taken 53837 times.
✓ Branch 1 taken 14727 times.
|
68564 | if (node->op == PostfixUnaryExprNode::OP_NONE) |
654 |
2/4✓ Branch 1 taken 53837 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53837 times.
✗ Branch 5 not taken.
|
53837 | return visit(node->atomicExpr()); |
655 | |||
656 | // Evaluate lhs | ||
657 |
1/2✓ Branch 1 taken 14727 times.
✗ Branch 2 not taken.
|
14727 | const PostfixUnaryExprNode *lhsNode = node->postfixUnaryExpr(); |
658 |
1/2✓ Branch 1 taken 14727 times.
✗ Branch 2 not taken.
|
14727 | QualType lhsSTy = lhsNode->getEvaluatedSymbolType(manIdx); |
659 |
2/4✓ Branch 1 taken 14727 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14727 times.
✗ Branch 5 not taken.
|
14727 | auto lhs = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
660 | |||
661 |
4/5✓ Branch 0 taken 2118 times.
✓ Branch 1 taken 11133 times.
✓ Branch 2 taken 1234 times.
✓ Branch 3 taken 242 times.
✗ Branch 4 not taken.
|
14727 | switch (node->op) { |
662 | 2118 | case PostfixUnaryExprNode::OP_SUBSCRIPT: { | |
663 |
1/2✓ Branch 1 taken 2118 times.
✗ Branch 2 not taken.
|
2118 | lhsSTy = lhsSTy.removeReferenceWrapper(); |
664 | |||
665 | // Get the index value | ||
666 |
1/2✓ Branch 1 taken 2118 times.
✗ Branch 2 not taken.
|
2118 | const AssignExprNode *indexExpr = node->assignExpr(); |
667 |
1/2✓ Branch 1 taken 2118 times.
✗ Branch 2 not taken.
|
2118 | llvm::Value *indexValue = resolveValue(indexExpr); |
668 | // Come up with the address | ||
669 |
8/10✓ Branch 1 taken 2118 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 135 times.
✓ Branch 4 taken 1983 times.
✓ Branch 6 taken 135 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 95 times.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 95 times.
✓ Branch 11 taken 2023 times.
|
2118 | if (lhsSTy.isArray() && lhsSTy.getArraySize() != ARRAY_SIZE_UNKNOWN) { // Array |
670 | // Make sure the address is present | ||
671 |
1/2✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
|
95 | resolveAddress(lhs); |
672 | |||
673 | // Calculate address of array item | ||
674 |
1/2✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
|
95 | llvm::Type *lhsTy = lhsSTy.toLLVMType(sourceFile); |
675 |
1/2✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
|
95 | llvm::Value *indices[2] = {builder.getInt64(0), indexValue}; |
676 |
2/4✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 95 times.
✗ Branch 6 not taken.
|
190 | lhs.ptr = insertInBoundsGEP(lhsTy, lhs.ptr, indices); |
677 | } else { // Pointer | ||
678 | // Make sure the value is present | ||
679 |
1/2✓ Branch 1 taken 2023 times.
✗ Branch 2 not taken.
|
2023 | resolveValue(lhsNode, lhs); |
680 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2023 times.
|
2023 | assert(lhs.value != nullptr); |
681 | |||
682 | // Now the pointer is the value | ||
683 | 2023 | lhs.ptr = lhs.value; | |
684 | |||
685 |
2/4✓ Branch 1 taken 2023 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2023 times.
✗ Branch 5 not taken.
|
2023 | llvm::Type *lhsTy = lhsSTy.getContained().toLLVMType(sourceFile); |
686 | // Calculate address of pointer item | ||
687 |
2/4✓ Branch 1 taken 2023 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2023 times.
✗ Branch 6 not taken.
|
4046 | lhs.ptr = insertInBoundsGEP(lhsTy, lhs.ptr, indexValue); |
688 | } | ||
689 | |||
690 | // Reset value and entry | ||
691 | 2118 | lhs.value = nullptr; | |
692 | 2118 | lhs.entry = nullptr; | |
693 | 2118 | break; | |
694 | } | ||
695 | 11133 | case PostfixUnaryExprNode::OP_MEMBER_ACCESS: { | |
696 | // Get the address of the struct instance | ||
697 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | resolveAddress(lhs); |
698 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | lhsSTy = lhsSTy.removeReferenceWrapper(); |
699 | |||
700 | // Auto de-reference pointer | ||
701 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | autoDeReferencePtr(lhs.ptr, lhsSTy); |
702 |
2/4✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11133 times.
|
11133 | assert(lhsSTy.is(TY_STRUCT)); |
703 | |||
704 | // Retrieve struct scope | ||
705 | 11133 | const std::string &fieldName = node->identifier; | |
706 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | Scope *structScope = lhsSTy.getBodyScope(); |
707 | |||
708 | // Retrieve field entry | ||
709 | 11133 | std::vector<size_t> indexPath; | |
710 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | lhs.entry = structScope->symbolTable.lookupInComposedFields(fieldName, indexPath); |
711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11133 times.
|
11133 | assert(lhs.entry != nullptr); |
712 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | const QualType fieldSymbolType = lhs.entry->getQualType(); |
713 | |||
714 | // Get address of the field in the struct instance | ||
715 |
2/4✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11133 times.
✗ Branch 5 not taken.
|
22266 | std::vector<llvm::Value *> indices = {builder.getInt64(0)}; |
716 |
2/2✓ Branch 4 taken 11139 times.
✓ Branch 5 taken 11133 times.
|
22272 | for (const size_t index : indexPath) |
717 |
2/4✓ Branch 1 taken 11139 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11139 times.
✗ Branch 5 not taken.
|
11139 | indices.push_back(builder.getInt32(index)); |
718 |
1/2✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
|
11133 | const std::string name = fieldName + "_addr"; |
719 |
3/6✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 11133 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 11133 times.
✗ Branch 9 not taken.
|
11133 | llvm::Value *memberAddr = insertInBoundsGEP(lhsSTy.toLLVMType(sourceFile), lhs.ptr, indices, name); |
720 | |||
721 | // Set as ptr or refPtr, depending on the type | ||
722 |
3/4✓ Branch 1 taken 11133 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 142 times.
✓ Branch 4 taken 10991 times.
|
11133 | if (fieldSymbolType.isRef()) { |
723 | 142 | lhs.ptr = nullptr; | |
724 | 142 | lhs.refPtr = memberAddr; | |
725 | } else { | ||
726 | 10991 | lhs.ptr = memberAddr; | |
727 | 10991 | lhs.refPtr = nullptr; | |
728 | } | ||
729 | |||
730 | // Reset the value | ||
731 | 11133 | lhs.value = nullptr; | |
732 | 11133 | break; | |
733 | 11133 | } | |
734 | 1234 | case PostfixUnaryExprNode::OP_PLUS_PLUS: { | |
735 | // Make sure a value is present | ||
736 |
1/2✓ Branch 1 taken 1234 times.
✗ Branch 2 not taken.
|
1234 | resolveValue(lhsNode, lhs); |
737 | |||
738 | // Allocate new local variable if required | ||
739 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1232 times.
|
1234 | if (!lhs.ptr) { |
740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(lhs.value != nullptr); |
741 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | lhs.ptr = insertAlloca(lhs.value->getType()); |
742 | } | ||
743 | |||
744 | // Execute operation | ||
745 |
1/2✓ Branch 1 taken 1234 times.
✗ Branch 2 not taken.
|
1234 | const LLVMExprResult result = conversionManager.getPostfixPlusPlusInst(node, lhs, lhsSTy, 0); |
746 | |||
747 | // Save the new value to the old address | ||
748 |
3/4✓ Branch 1 taken 1234 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 1225 times.
|
1234 | if (conversionManager.callsOverloadedOpFct(node, 0)) { |
749 | 9 | lhs.value = result.value; | |
750 | 9 | lhs.ptr = result.ptr; | |
751 | } else { | ||
752 |
5/6✓ Branch 0 taken 1223 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1220 times.
✓ Branch 5 taken 1225 times.
✗ Branch 6 not taken.
|
1225 | insertStore(result.value, lhs.ptr, lhs.entry && lhs.entry->isVolatile); |
753 | 1225 | lhs.ptr = nullptr; | |
754 | } | ||
755 | 1234 | break; | |
756 | } | ||
757 | 242 | case PostfixUnaryExprNode::OP_MINUS_MINUS: { | |
758 | // Make sure a value is present | ||
759 |
1/2✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
|
242 | resolveValue(lhsNode, lhs); |
760 | |||
761 | // Allocate new local variable if required | ||
762 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 240 times.
|
242 | if (!lhs.ptr) { |
763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(lhs.value != nullptr); |
764 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | lhs.ptr = insertAlloca(lhs.value->getType()); |
765 | } | ||
766 | |||
767 | // Execute operation | ||
768 |
1/2✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
|
242 | const LLVMExprResult result = conversionManager.getPostfixMinusMinusInst(node, lhs, lhsSTy, 0); |
769 | |||
770 | // Save the new value to the old address | ||
771 |
3/4✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 236 times.
|
242 | if (conversionManager.callsOverloadedOpFct(node, 0)) { |
772 | 6 | lhs.value = result.value; | |
773 | 6 | lhs.ptr = result.ptr; | |
774 | } else { | ||
775 |
4/6✓ Branch 0 taken 234 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 234 times.
✓ Branch 5 taken 236 times.
✗ Branch 6 not taken.
|
236 | insertStore(result.value, lhs.ptr, lhs.entry && lhs.entry->isVolatile); |
776 | 236 | lhs.ptr = nullptr; | |
777 | } | ||
778 | 242 | break; | |
779 | } | ||
780 | − | default: // GCOV_EXCL_LINE | |
781 | − | throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExpr fall-through"); // GCOV_EXCL_LINE | |
782 | } | ||
783 | |||
784 |
1/2✓ Branch 1 taken 14727 times.
✗ Branch 2 not taken.
|
14727 | return lhs; |
785 | } | ||
786 | |||
787 | 53837 | std::any IRGenerator::visitAtomicExpr(const AtomicExprNode *node) { | |
788 |
1/2✓ Branch 1 taken 53837 times.
✗ Branch 2 not taken.
|
53837 | diGenerator.setSourceLocation(node); |
789 | |||
790 | // If constant | ||
791 |
3/4✓ Branch 1 taken 53837 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8982 times.
✓ Branch 4 taken 44855 times.
|
53837 | if (node->constant()) { |
792 |
3/6✓ Branch 1 taken 8982 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8982 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8982 times.
✗ Branch 8 not taken.
|
8982 | const auto constantValue = std::any_cast<llvm::Constant *>(visit(node->constant())); |
793 |
1/2✓ Branch 1 taken 8982 times.
✗ Branch 2 not taken.
|
17964 | return LLVMExprResult{.constant = constantValue}; |
794 | } | ||
795 | |||
796 | // If value | ||
797 |
3/4✓ Branch 1 taken 44855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10317 times.
✓ Branch 4 taken 34538 times.
|
44855 | if (node->value()) |
798 |
2/4✓ Branch 1 taken 10317 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10317 times.
✗ Branch 5 not taken.
|
10317 | return visit(node->value()); |
799 | |||
800 | // Is assign expression | ||
801 |
3/4✓ Branch 1 taken 34538 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 479 times.
✓ Branch 4 taken 34059 times.
|
34538 | if (node->assignExpr()) |
802 |
2/4✓ Branch 1 taken 479 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 479 times.
✗ Branch 5 not taken.
|
479 | return visit(node->assignExpr()); |
803 | |||
804 | // Check for builtin calls | ||
805 |
3/4✓ Branch 1 taken 34059 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 579 times.
✓ Branch 4 taken 33480 times.
|
34059 | if (node->printfCall()) |
806 |
2/4✓ Branch 1 taken 579 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 579 times.
✗ Branch 5 not taken.
|
579 | return visit(node->printfCall()); |
807 |
3/4✓ Branch 1 taken 33480 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 119 times.
✓ Branch 4 taken 33361 times.
|
33480 | if (node->sizeofCall()) |
808 |
2/4✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 119 times.
✗ Branch 5 not taken.
|
119 | return visit(node->sizeofCall()); |
809 |
3/4✓ Branch 1 taken 33361 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 33350 times.
|
33361 | if (node->alignofCall()) |
810 |
2/4✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
11 | return visit(node->alignofCall()); |
811 |
3/4✓ Branch 1 taken 33350 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 33315 times.
|
33350 | if (node->lenCall()) |
812 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
35 | return visit(node->lenCall()); |
813 |
3/4✓ Branch 1 taken 33315 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 348 times.
✓ Branch 4 taken 32967 times.
|
33315 | if (node->panicCall()) |
814 |
2/4✓ Branch 1 taken 348 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 348 times.
✗ Branch 5 not taken.
|
348 | return visit(node->panicCall()); |
815 |
3/4✓ Branch 1 taken 32967 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 32966 times.
|
32967 | if (node->sysCall()) |
816 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return visit(node->sysCall()); |
817 | |||
818 | // Identifier (local or global variable access) | ||
819 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32966 times.
|
32966 | assert(!node->identifierFragments.empty()); |
820 | |||
821 | // Get symbol table entry | ||
822 |
1/2✓ Branch 1 taken 32966 times.
✗ Branch 2 not taken.
|
32966 | const auto &[varEntry, accessScope, capture] = node->data.at(manIdx); |
823 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32966 times.
|
32966 | assert(varEntry != nullptr); |
824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32966 times.
|
32966 | assert(accessScope != nullptr); |
825 |
1/2✓ Branch 1 taken 32966 times.
✗ Branch 2 not taken.
|
32966 | const QualType varSymbolType = varEntry->getQualType(); |
826 |
1/2✓ Branch 1 taken 32966 times.
✗ Branch 2 not taken.
|
32966 | llvm::Type *varType = varSymbolType.toLLVMType(sourceFile); |
827 | |||
828 | // Check if external global variable | ||
829 |
7/8✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 31762 times.
✓ Branch 3 taken 1204 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 53 times.
✓ Branch 6 taken 1151 times.
✓ Branch 7 taken 53 times.
✓ Branch 8 taken 32913 times.
|
32966 | if (varEntry->global && accessScope->isImportedBy(rootScope)) { |
830 | // External global variables need to be declared and allocated in the current module | ||
831 |
1/2✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
|
53 | llvm::Value *varAddress = module->getOrInsertGlobal(varEntry->name, varType); |
832 |
1/2✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
|
53 | varEntry->updateAddress(varAddress); |
833 | } | ||
834 | |||
835 | // Check if enum item | ||
836 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 32735 times.
|
32966 | if (accessScope->type == ScopeType::ENUM) { |
837 |
1/2✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
|
231 | const auto itemNode = spice_pointer_cast<const EnumItemNode *>(varEntry->declNode); |
838 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
231 | llvm::Constant *constantItemValue = llvm::ConstantInt::get(varType, itemNode->itemValue); |
839 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
462 | return LLVMExprResult{.constant = constantItemValue, .entry = varEntry}; |
840 | } | ||
841 | |||
842 |
1/2✓ Branch 1 taken 32735 times.
✗ Branch 2 not taken.
|
32735 | llvm::Value *address = varEntry->getAddress(); |
843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32735 times.
|
32735 | assert(address != nullptr); |
844 | |||
845 | // If this is a function/procedure reference, return it as value | ||
846 |
7/8✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 31531 times.
✓ Branch 3 taken 1204 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1200 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 32731 times.
|
32735 | if (varEntry->global && varSymbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
847 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | llvm::Value *fatPtr = buildFatFctPtr(nullptr, nullptr, address); |
848 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | return LLVMExprResult{.ptr = fatPtr, .entry = varEntry}; |
849 | } | ||
850 | |||
851 | // Load the address of the referenced variable | ||
852 |
10/12✓ Branch 1 taken 32731 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30395 times.
✓ Branch 4 taken 2336 times.
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 30368 times.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 2345 times.
✓ Branch 13 taken 30386 times.
|
32731 | if (varSymbolType.isRef() || (capture && capture->getMode() == BY_REFERENCE)) |
853 |
1/2✓ Branch 1 taken 2345 times.
✗ Branch 2 not taken.
|
4690 | return LLVMExprResult{.refPtr = address, .entry = varEntry}; |
854 | |||
855 |
1/2✓ Branch 1 taken 30386 times.
✗ Branch 2 not taken.
|
60772 | return LLVMExprResult{.ptr = address, .entry = varEntry}; |
856 | } | ||
857 | |||
858 | } // namespace spice::compiler | ||
859 |