GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/TypeSpecifiers.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 73 77 94.8%
Functions: 7 7 100.0%
Branches: 56 68 82.4%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "TypeSpecifiers.h"
4
5 #include <exception/CompilerError.h>
6 #include <symboltablebuilder/TypeChain.h>
7
8 namespace spice::compiler {
9
10 /**
11 * Get default type specifiers for a given super type
12 *
13 * @param superType Super type
14 * @return Default type specifiers
15 */
16 8082448 TypeSpecifiers TypeSpecifiers::of(uint16_t superType) {
17
5/6
✓ Branch 0 taken 160267 times.
✓ Branch 1 taken 405266 times.
✓ Branch 2 taken 115870 times.
✓ Branch 3 taken 1393 times.
✓ Branch 4 taken 7399652 times.
✗ Branch 5 not taken.
8082448 switch (superType) {
18 160267 case TY_DOUBLE: // fall-through
19 case TY_INT: // fall-through
20 case TY_SHORT: // fall-through
21 case TY_LONG:
22 160267 return {/*const*/ false, /*signed*/ true, /*unsigned*/ false, /*heap*/ false};
23 405266 case TY_BYTE: // fall-through
24 case TY_CHAR: // fall-through
25 case TY_STRING: // fall-through
26 case TY_BOOL: // fall-through
27 case TY_PTR: // fall-through
28 case TY_REF: // fall-through
29 case TY_ARRAY: // fall-through
30 case TY_STRUCT: // fall-through
31 case TY_INTERFACE: // fall-through
32 case TY_FUNCTION: // fall-through
33 case TY_PROCEDURE:
34 405266 return {/*const*/ false, /*signed*/ false, /*unsigned*/ true, /*heap*/ false};
35 115870 case TY_GENERIC:
36 // Generics must be non-signed and non-unsigned at the same time to ensure a proper function matching
37 115870 return {/*const*/ false, /*signed*/ false, /*unsigned*/ false, /*heap*/ false};
38 1393 case TY_ENUM: // fall-through
39 case TY_ALIAS: // fall-through
40 case TY_IMPORT:
41 1393 return {/*const*/ true, /*signed*/ false, /*unsigned*/ true, /*heap*/ false};
42 7399652 case TY_DYN: // fall-through
43 case TY_INVALID: // fall-through
44 case TY_UNRESOLVED:
45 // Return all-false specifiers to not match anything
46 7399652 return {/*const*/ false, /*signed*/ false, /*unsigned*/ false, /*heap*/ false};
47 default:
48 throw CompilerError(UNHANDLED_BRANCH, "Symbol specifier fallthrough"); // GCOV_EXCL_LINE
49 }
50 }
51
52 /**
53 * Merge two sets of type specifiers. If possible, prefer the opposite of the default of the super type
54 *
55 * @param other Other type specifiers object
56 * @return Merged specifiers object
57 */
58 11466 TypeSpecifiers TypeSpecifiers::merge(const TypeSpecifiers &other) const {
59 11466 TypeSpecifiers result;
60
6/8
✓ Branch 1 taken 11466 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11135 times.
✓ Branch 4 taken 331 times.
✓ Branch 6 taken 11135 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7906 times.
✓ Branch 9 taken 3229 times.
11466 const bool isGeneric = !getBit(BIT_INDEX_SIGNED) && !getBit(BIT_INDEX_UNSIGNED);
61
2/2
✓ Branch 0 taken 80262 times.
✓ Branch 1 taken 11466 times.
91728 for (uint8_t i = 0; i <= BIT_INDEX_MAX; i++) {
62
1/2
✓ Branch 1 taken 80262 times.
✗ Branch 2 not taken.
80262 const bool x = getBit(i);
63
1/2
✓ Branch 1 taken 80262 times.
✗ Branch 2 not taken.
80262 const bool y = other.getBit(i);
64
65
4/4
✓ Branch 0 taken 68796 times.
✓ Branch 1 taken 11466 times.
✓ Branch 2 taken 11466 times.
✓ Branch 3 taken 57330 times.
80262 if (i == BIT_INDEX_SIGNED || i == BIT_INDEX_UNSIGNED) {
66
3/4
✓ Branch 0 taken 15812 times.
✓ Branch 1 taken 7120 times.
✓ Branch 3 taken 22932 times.
✗ Branch 4 not taken.
22932 result.setBit(i, isGeneric ? y : x);
67 } else {
68
1/2
✓ Branch 1 taken 57330 times.
✗ Branch 2 not taken.
57330 result.setBit(i, x | y);
69 }
70 }
71 11466 return result;
72 }
73
74 /**
75 * Check if two sets of type specifiers match
76 *
77 * @param other The rhs specifiers
78 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
79 * @return Matching or not
80 */
81 20336 bool TypeSpecifiers::match(TypeSpecifiers other, bool allowConstify) const {
82 20336 const TypeSpecifiers thisSpecifiers = *this;
83
84 // If allowConstify is enabled, only allow to match lhs=const and rhs=non-const
85
6/6
✓ Branch 0 taken 20316 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1766 times.
✓ Branch 3 taken 18550 times.
✓ Branch 4 taken 686 times.
✓ Branch 5 taken 1080 times.
20336 if (allowConstify && thisSpecifiers.isConst && !other.isConst)
86 686 other.isConst = true;
87
88 // Check if specifiers are equal
89 20336 return thisSpecifiers == other;
90 }
91
92 /**
93 * Erase all specifiers that are set in the mask. This is used in type matching.
94 *
95 * @param mask Bitmask to erase with
96 */
97 3730 void TypeSpecifiers::eraseWithMask(const TypeSpecifiers &mask) {
98 // Zero out all bits that are set in the mask
99
2/2
✓ Branch 0 taken 26110 times.
✓ Branch 1 taken 3730 times.
29840 for (uint8_t i = 0; i <= BIT_INDEX_MAX; i++) {
100
2/2
✓ Branch 1 taken 739 times.
✓ Branch 2 taken 25371 times.
26110 if (mask.getBit(i)) {
101 // Zero out the bit
102 739 setBit(i, false);
103
104 // If we set the signed/unsigned bit to zero, we need to set the other to one
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 739 times.
739 if (i == BIT_INDEX_SIGNED) {
106 setBit(BIT_INDEX_UNSIGNED, true);
107
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 708 times.
739 } else if (i == BIT_INDEX_UNSIGNED) {
108 31 setBit(BIT_INDEX_SIGNED, true);
109 }
110 }
111 }
112 3730 }
113
114 20425 bool operator==(const TypeSpecifiers &lhs, const TypeSpecifiers &rhs) {
115 20425 const bool isConst = lhs.isConst == rhs.isConst;
116 20425 const bool isSigned = lhs.isSigned == rhs.isSigned;
117 20425 const bool isUnsigned = lhs.isUnsigned == rhs.isUnsigned;
118 20425 const bool isHeap = lhs.isHeap == rhs.isHeap;
119
6/8
✓ Branch 0 taken 20114 times.
✓ Branch 1 taken 311 times.
✓ Branch 2 taken 20114 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20114 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20026 times.
✓ Branch 7 taken 88 times.
20425 return isConst && isSigned && isUnsigned && isHeap;
120 }
121
122 209235 bool TypeSpecifiers::getBit(uint8_t index) const {
123
7/8
✓ Branch 0 taken 26662 times.
✓ Branch 1 taken 38128 times.
✓ Branch 2 taken 37797 times.
✓ Branch 3 taken 26662 times.
✓ Branch 4 taken 26662 times.
✓ Branch 5 taken 26662 times.
✓ Branch 6 taken 26662 times.
✗ Branch 7 not taken.
209235 switch (index) {
124 26662 case BIT_INDEX_CONST:
125 26662 return isConst;
126 38128 case BIT_INDEX_SIGNED:
127 38128 return isSigned;
128 37797 case BIT_INDEX_UNSIGNED:
129 37797 return isUnsigned;
130 26662 case BIT_INDEX_HEAP:
131 26662 return isHeap;
132 26662 case BIT_INDEX_PUBLIC:
133 26662 return isPublic;
134 26662 case BIT_INDEX_INLINE:
135 26662 return isInline;
136 26662 case BIT_INDEX_COMPOSITION:
137 26662 return isComposition;
138 default:
139 throw CompilerError(UNHANDLED_BRANCH, "Bit index fallthrough"); // GCOV_EXCL_LINE
140 }
141 }
142
143 81032 bool TypeSpecifiers::setBit(uint8_t index, bool value) {
144
7/8
✓ Branch 0 taken 12174 times.
✓ Branch 1 taken 11497 times.
✓ Branch 2 taken 11497 times.
✓ Branch 3 taken 11466 times.
✓ Branch 4 taken 11466 times.
✓ Branch 5 taken 11466 times.
✓ Branch 6 taken 11466 times.
✗ Branch 7 not taken.
81032 switch (index) {
145 12174 case BIT_INDEX_CONST:
146 12174 return isConst = value;
147 11497 case BIT_INDEX_SIGNED:
148 11497 return isSigned = value;
149 11497 case BIT_INDEX_UNSIGNED:
150 11497 return isUnsigned = value;
151 11466 case BIT_INDEX_HEAP:
152 11466 return isHeap = value;
153 11466 case BIT_INDEX_PUBLIC:
154 11466 return isPublic = value;
155 11466 case BIT_INDEX_INLINE:
156 11466 return isInline = value;
157 11466 case BIT_INDEX_COMPOSITION:
158 11466 return isComposition = value;
159 default:
160 throw CompilerError(UNHANDLED_BRANCH, "Bit index fallthrough"); // GCOV_EXCL_LINE
161 }
162 }
163
164 } // namespace spice::compiler
165