GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/SymbolTableEntry.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 39 39 100.0%
Functions: 10 10 100.0%
Branches: 36 62 58.1%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "SymbolTableEntry.h"
4
5 #include <ast/ASTNodes.h>
6 #include <exception/SemanticError.h>
7 #include <symboltablebuilder/Scope.h>
8 #include <util/CodeLoc.h>
9
10 namespace spice::compiler {
11
12 /**
13 * Retrieve the qualified type of this symbol
14 *
15 * @return Qualified type of this symbol
16 */
17 1510156 const QualType &SymbolTableEntry::getQualType() const { return qualType; }
18
19 /**
20 * Update the type of this symbol.
21 *
22 * @param newType New type of the current symbol
23 * @param overwriteExistingType Overwrites the existing type without throwing an error
24 */
25 47564 void SymbolTableEntry::updateType(const QualType &newType, [[maybe_unused]] bool overwriteExistingType) {
26
4/6
✓ Branch 0 taken 22998 times.
✓ Branch 1 taken 24566 times.
✓ Branch 3 taken 22998 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 22998 times.
47564 assert(overwriteExistingType || qualType.isOneOf({TY_INVALID, TY_DYN}));
27 47564 qualType = newType;
28 47564 }
29
30 /**
31 * Update the state of the current symbol
32 *
33 * @throws CompilerError When the state of the symbol is set to initialized before a concrete type was set
34 *
35 * @param newState New state of the current symbol
36 * @param node AST node where the update takes place
37 * @param force Force update. This can only be used compiler-internal
38 */
39 69316 void SymbolTableEntry::updateState(const LifecycleState &newState, const ASTNode *node, bool force) {
40 69316 const LifecycleState oldState = lifecycle.getCurrentState();
41 // Check if this is a constant variable and is already initialized
42 if (newState != DEAD && oldState != DECLARED && qualType.isConst() && !force) // GCOV_EXCL_LINE
43 throw CompilerError(INTERNAL_ERROR, "Not re-assignable variable '" + name + "'"); // GCOV_EXCL_LINE
44 if (newState == DEAD && oldState == DECLARED) // GCOV_EXCL_LINE
45 throw CompilerError(INTERNAL_ERROR, "Cannot destroy uninitialized variable '" + name + "'"); // GCOV_EXCL_LINE
46 if (newState == DEAD && oldState == DEAD) // GCOV_EXCL_LINE
47 throw CompilerError(INTERNAL_ERROR, "Cannot destroy already destroyed variable '" + name + "'"); // GCOV_EXCL_LINE
48
1/2
✓ Branch 1 taken 69316 times.
✗ Branch 2 not taken.
69316 lifecycle.addEvent({newState, node});
49 69316 }
50
51 /**
52 * Retrieve the code location where the symbol was declared
53 *
54 * @return Declaration code location
55 */
56 95 const CodeLoc &SymbolTableEntry::getDeclCodeLoc() const { return declNode->codeLoc; }
57
58 /**
59 * Retrieve the address of the assigned value
60 *
61 * @return Address of the value in memory
62 */
63
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 45441 times.
45442 llvm::Value *SymbolTableEntry::getAddress() const { return memAddress.empty() ? nullptr : memAddress.top(); }
64
65 /**
66 * Update the address of a symbol. This is used to save the allocated address where the symbol lives.
67 *
68 * @param address Address of the symbol in memory
69 */
70 33355 void SymbolTableEntry::updateAddress(llvm::Value *address) {
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33355 times.
33355 assert(address != nullptr);
72 // Ensure that structs fields get no addresses assigned, as the addresses are meant for the struct instances
73
5/8
✓ Branch 0 taken 28935 times.
✓ Branch 1 taken 4420 times.
✓ Branch 2 taken 28935 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4420 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4420 times.
33355 assert((scope->type != ScopeType::STRUCT && scope->type != ScopeType::INTERFACE) ||
74 qualType.isOneOf({TY_FUNCTION, TY_PROCEDURE}));
75
2/2
✓ Branch 1 taken 26694 times.
✓ Branch 2 taken 6661 times.
33355 if (memAddress.empty())
76 26694 memAddress.push(address);
77 else
78 6661 memAddress.top() = address;
79 33355 }
80
81 /**
82 * Push a new address to the stack
83 *
84 * @param address Address to push
85 */
86 22 void SymbolTableEntry::pushAddress(llvm::Value *address) {
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 assert(address != nullptr);
88 22 memAddress.push(address);
89 22 }
90
91 /**
92 * Remove the last address from the stack
93 */
94 22 void SymbolTableEntry::popAddress() {
95
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 assert(!memAddress.empty());
96 22 memAddress.pop();
97 22 }
98
99 /**
100 * Check if this symbol is a struct field
101 *
102 * @return Struct field or not
103 */
104 14721 bool SymbolTableEntry::isField() const {
105
4/6
✓ Branch 0 taken 13249 times.
✓ Branch 1 taken 1472 times.
✓ Branch 3 taken 13249 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13249 times.
✗ Branch 6 not taken.
14721 return scope->type == ScopeType::STRUCT && orderIndex < scope->getFieldCount() && !anonymous;
106 }
107
108 /**
109 * Stringify the current symbol to a human-readable form. Used to dump whole symbol tables with their contents.
110 *
111 * Example:
112 * {
113 * "name": "testIden",
114 * "type": "int[]*",
115 * "orderIndex": 4,
116 * "state": "initialized",
117 * "specifiers: [
118 * "const": true,
119 * "signed": false
120 * ],
121 * "isGlobal": false,
122 * "isVolatile": false
123 * }
124 *
125 * @return Symbol table entry as a JSON object
126 */
127 323095 nlohmann::ordered_json SymbolTableEntry::toJSON() const {
128 323095 nlohmann::json result;
129
2/4
✓ Branch 1 taken 323095 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323095 times.
✗ Branch 5 not taken.
323095 result["name"] = name;
130
3/6
✓ Branch 1 taken 323095 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323095 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 323095 times.
✗ Branch 8 not taken.
323095 result["type"] = qualType.getName(true);
131
3/6
✓ Branch 1 taken 323095 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323095 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 323095 times.
✗ Branch 8 not taken.
323095 result["codeLoc"] = declNode->codeLoc.toString();
132
1/2
✓ Branch 2 taken 323095 times.
✗ Branch 3 not taken.
323095 result["orderIndex"] = orderIndex;
133
3/6
✓ Branch 1 taken 323095 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323095 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 323095 times.
✗ Branch 8 not taken.
323095 result["state"] = lifecycle.getCurrentStateName();
134
1/2
✓ Branch 2 taken 323095 times.
✗ Branch 3 not taken.
323095 result["isGlobal"] = global;
135
1/2
✓ Branch 2 taken 323095 times.
✗ Branch 3 not taken.
323095 result["isVolatile"] = isVolatile;
136
1/2
✓ Branch 1 taken 323095 times.
✗ Branch 2 not taken.
646190 return result;
137 323095 }
138
139 } // namespace spice::compiler
140