src/typechecker/TypeCheckBuiltinFunctions.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "TypeChecker.h" | ||
| 4 | |||
| 5 | #include <SourceFile.h> | ||
| 6 | #include <ast/ASTNodes.h> | ||
| 7 | #include <global/GlobalResourceManager.h> | ||
| 8 | #include <global/TypeRegistry.h> | ||
| 9 | #include <typechecker/Builtins.h> | ||
| 10 | #include <typechecker/MacroDefs.h> | ||
| 11 | |||
| 12 | namespace spice::compiler { | ||
| 13 | |||
| 14 | 1858 | std::any TypeChecker::visitBuiltinCall(FctCallNode *node) const { | |
| 15 |
2/4✓ Branch 3 → 4 taken 1858 times.
✗ Branch 3 → 68 not taken.
✓ Branch 4 → 5 taken 1858 times.
✗ Branch 4 → 6 not taken.
|
1858 | assert(BUILTIN_FUNCTIONS_MAP.contains(node->fqFunctionName) && "Builtin function not implemented!"); |
| 16 |
1/2✓ Branch 8 → 9 taken 1858 times.
✗ Branch 8 → 69 not taken.
|
1858 | const auto &info = BUILTIN_FUNCTIONS_MAP.find(node->fqFunctionName)->second; |
| 17 | |||
| 18 | 14 | const auto buildErrorMessage = [](unsigned int min, unsigned int max, unsigned int actual, const char *suffix) { | |
| 19 | 14 | std::string expectedStr; | |
| 20 |
2/2✓ Branch 3 → 4 taken 7 times.
✓ Branch 3 → 15 taken 7 times.
|
14 | if (min == max) |
| 21 |
5/8✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 8 taken 4 times.
✓ Branch 7 → 9 taken 3 times.
✗ Branch 7 → 46 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 14 taken 4 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 49 not taken.
|
13 | expectedStr = min == 0 ? "no" : std::to_string(min); |
| 22 | else | ||
| 23 |
5/10✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 60 not taken.
✓ Branch 18 → 19 taken 7 times.
✗ Branch 18 → 58 not taken.
✓ Branch 19 → 20 taken 7 times.
✗ Branch 19 → 56 not taken.
✓ Branch 20 → 21 taken 7 times.
✗ Branch 20 → 54 not taken.
✓ Branch 21 → 22 taken 7 times.
✗ Branch 21 → 52 not taken.
|
7 | expectedStr = "between " + std::to_string(min) + " and " + std::to_string(max) + " " + suffix; |
| 24 |
5/10✓ Branch 32 → 33 taken 14 times.
✗ Branch 32 → 79 not taken.
✓ Branch 33 → 34 taken 14 times.
✗ Branch 33 → 77 not taken.
✓ Branch 34 → 35 taken 14 times.
✗ Branch 34 → 75 not taken.
✓ Branch 35 → 36 taken 14 times.
✗ Branch 35 → 73 not taken.
✓ Branch 36 → 37 taken 14 times.
✗ Branch 36 → 71 not taken.
|
28 | return "This builtin expects " + expectedStr + " " + suffix + ", but got " + std::to_string(actual); |
| 25 | 14 | }; | |
| 26 | |||
| 27 | // Do basic checks of template types and args, based on the builtin function info | ||
| 28 |
2/2✓ Branch 10 → 11 taken 157 times.
✓ Branch 10 → 12 taken 1701 times.
|
1858 | const size_t numTemplateTypes = node->hasTemplateTypes ? node->templateTypeLst->dataTypes.size() : 0; |
| 29 |
4/4✓ Branch 13 → 14 taken 1856 times.
✓ Branch 13 → 15 taken 2 times.
✓ Branch 14 → 15 taken 5 times.
✓ Branch 14 → 22 taken 1851 times.
|
1858 | if (numTemplateTypes < info.minTemplateTypes || numTemplateTypes > info.maxTemplateTypes) { |
| 30 |
1/2✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 74 not taken.
|
7 | const auto msg = buildErrorMessage(info.minTemplateTypes, info.maxTemplateTypes, numTemplateTypes, "template type(s)"); |
| 31 |
3/6✓ Branch 16 → 17 taken 7 times.
✗ Branch 16 → 72 not taken.
✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 71 not taken.
✓ Branch 18 → 19 taken 7 times.
✗ Branch 18 → 71 not taken.
|
7 | SOFT_ERROR_ER(node, BUILTIN_TEMPLATE_TYPE_COUNT_MISMATCH, msg); |
| 32 | 7 | } | |
| 33 | |||
| 34 |
2/2✓ Branch 22 → 23 taken 1702 times.
✓ Branch 22 → 24 taken 149 times.
|
1851 | const size_t numArgs = node->hasArgs ? node->argLst->args.size() : 0; |
| 35 |
4/4✓ Branch 25 → 26 taken 1850 times.
✓ Branch 25 → 27 taken 1 time.
✓ Branch 26 → 27 taken 6 times.
✓ Branch 26 → 34 taken 1844 times.
|
1851 | if (numArgs < info.minArgTypes || numArgs > info.maxArgTypes) { |
| 36 |
1/2✓ Branch 27 → 28 taken 7 times.
✗ Branch 27 → 78 not taken.
|
7 | const auto msg = buildErrorMessage(info.minArgTypes, info.maxArgTypes, numArgs, "argument(s)"); |
| 37 |
3/6✓ Branch 28 → 29 taken 7 times.
✗ Branch 28 → 76 not taken.
✓ Branch 29 → 30 taken 7 times.
✗ Branch 29 → 75 not taken.
✓ Branch 30 → 31 taken 7 times.
✗ Branch 30 → 75 not taken.
|
7 | SOFT_ERROR_ER(node, BUILTIN_ARG_COUNT_MISMATCH, msg); |
| 38 | 7 | } | |
| 39 | |||
| 40 |
2/2✓ Branch 34 → 35 taken 180 times.
✓ Branch 34 → 59 taken 1664 times.
|
1844 | if (info.allTemplateTypesOrAllArgTypes) { |
| 41 |
4/4✓ Branch 35 → 36 taken 141 times.
✓ Branch 35 → 47 taken 39 times.
✓ Branch 36 → 37 taken 3 times.
✓ Branch 36 → 47 taken 138 times.
|
180 | if (numTemplateTypes > 0 && numArgs > 0) |
| 42 |
4/8✓ Branch 39 → 40 taken 3 times.
✗ Branch 39 → 81 not taken.
✓ Branch 40 → 41 taken 3 times.
✗ Branch 40 → 79 not taken.
✓ Branch 43 → 44 taken 3 times.
✗ Branch 43 → 85 not taken.
✓ Branch 44 → 45 taken 3 times.
✗ Branch 44 → 85 not taken.
|
9 | SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got both"); |
| 43 |
4/4✓ Branch 47 → 48 taken 39 times.
✓ Branch 47 → 59 taken 138 times.
✓ Branch 48 → 49 taken 3 times.
✓ Branch 48 → 59 taken 36 times.
|
177 | if (numTemplateTypes == 0 && numArgs == 0) |
| 44 |
4/8✓ Branch 51 → 52 taken 3 times.
✗ Branch 51 → 88 not taken.
✓ Branch 52 → 53 taken 3 times.
✗ Branch 52 → 86 not taken.
✓ Branch 55 → 56 taken 3 times.
✗ Branch 55 → 92 not taken.
✓ Branch 56 → 57 taken 3 times.
✗ Branch 56 → 92 not taken.
|
9 | SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got none"); |
| 45 | } | ||
| 46 | |||
| 47 | // If specified, call to TypeChecker delegate to execute further checks | ||
| 48 |
3/8✓ Branch 59 → 60 taken 1838 times.
✗ Branch 59 → 64 not taken.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 1838 times.
✓ Branch 63 → 65 taken 1838 times.
✗ Branch 63 → 93 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 93 not taken.
|
1838 | return info.typeCheckerVisitMethod != nullptr ? (this->*info.typeCheckerVisitMethod)(node) : nullptr; |
| 49 | } | ||
| 50 | |||
| 51 | 852 | std::any TypeChecker::visitBuiltinPrintfCall(FctCallNode *node) const { | |
| 52 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 852 times.
|
852 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PRINTF); |
| 53 | |||
| 54 | // Retrieve templated string | ||
| 55 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 852 times.
|
852 | assert(node->hasArgs); |
| 56 | 852 | const AssignExprNode *firstArg = node->argLst->args.front(); | |
| 57 |
5/10✓ Branch 9 → 10 taken 852 times.
✗ Branch 9 → 223 not taken.
✓ Branch 10 → 11 taken 852 times.
✗ Branch 10 → 223 not taken.
✓ Branch 11 → 12 taken 852 times.
✗ Branch 11 → 15 not taken.
✓ Branch 12 → 13 taken 852 times.
✗ Branch 12 → 223 not taken.
✓ Branch 13 → 14 taken 852 times.
✗ Branch 13 → 15 not taken.
|
852 | assert(firstArg->getEvaluatedSymbolType(manIdx).is(TY_STRING) && firstArg->hasCompileTimeValue(manIdx)); |
| 58 |
1/2✓ Branch 16 → 17 taken 852 times.
✗ Branch 16 → 223 not taken.
|
852 | const size_t stringOffset = firstArg->getCompileTimeValue(manIdx).stringValueOffset; |
| 59 |
2/4✓ Branch 17 → 18 taken 852 times.
✗ Branch 17 → 223 not taken.
✓ Branch 18 → 19 taken 852 times.
✗ Branch 18 → 223 not taken.
|
852 | const std::string templatedString = resourceManager.compileTimeStringValues.at(stringOffset); |
| 60 | |||
| 61 | // Check if assignment types match placeholder types | ||
| 62 | 852 | size_t placeholderCount = 0; | |
| 63 | 852 | size_t index = templatedString.find_first_of('%'); | |
| 64 |
5/6✓ Branch 133 → 134 taken 699 times.
✓ Branch 133 → 137 taken 845 times.
✓ Branch 135 → 136 taken 699 times.
✗ Branch 135 → 137 not taken.
✓ Branch 138 → 20 taken 699 times.
✓ Branch 138 → 139 taken 845 times.
|
1544 | while (index != std::string::npos && index != templatedString.size() - 1) { |
| 65 | // Check if there is another assignExpr | ||
| 66 |
2/2✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 32 taken 698 times.
|
699 | if (node->argLst->args.size() - 1 <= placeholderCount) |
| 67 |
4/8✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 161 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 159 not taken.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 165 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 165 not taken.
|
3 | SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains more placeholders than arguments") |
| 68 | |||
| 69 | // Get next assignment | ||
| 70 |
1/2✓ Branch 32 → 33 taken 698 times.
✗ Branch 32 → 211 not taken.
|
698 | const AssignExprNode *assignment = node->argLst->args.at(placeholderCount + 1); |
| 71 | // Visit assignment | ||
| 72 |
1/2✓ Branch 33 → 34 taken 698 times.
✗ Branch 33 → 211 not taken.
|
698 | QualType argType = assignment->getEvaluatedSymbolType(manIdx); |
| 73 |
2/8✓ Branch 34 → 35 taken 698 times.
✗ Branch 34 → 211 not taken.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 40 taken 698 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 166 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 166 not taken.
|
698 | HANDLE_UNRESOLVED_TYPE_ER(argType) |
| 74 |
1/2✓ Branch 40 → 41 taken 698 times.
✗ Branch 40 → 167 not taken.
|
698 | argType = argType.removeReferenceWrapper(); |
| 75 | |||
| 76 |
6/8✓ Branch 41 → 42 taken 698 times.
✗ Branch 41 → 211 not taken.
✓ Branch 42 → 43 taken 29 times.
✓ Branch 42 → 55 taken 351 times.
✓ Branch 42 → 67 taken 54 times.
✓ Branch 42 → 79 taken 258 times.
✓ Branch 42 → 100 taken 6 times.
✗ Branch 42 → 119 not taken.
|
698 | switch (templatedString.at(index + 1)) { |
| 77 | 29 | case 'c': { | |
| 78 |
3/4✓ Branch 43 → 44 taken 29 times.
✗ Branch 43 → 211 not taken.
✓ Branch 44 → 45 taken 1 time.
✓ Branch 44 → 54 taken 28 times.
|
29 | if (!argType.is(TY_CHAR)) |
| 79 |
5/10✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 172 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 170 not taken.
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 168 not taken.
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 174 not taken.
✓ Branch 51 → 52 taken 1 time.
✗ Branch 51 → 174 not taken.
|
1 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects char, but got " + argType.getName(false)) |
| 80 | 28 | placeholderCount++; | |
| 81 | 28 | break; | |
| 82 | } | ||
| 83 | 351 | case 'd': | |
| 84 | case 'i': | ||
| 85 | case 'l': | ||
| 86 | case 'o': | ||
| 87 | case 'u': | ||
| 88 | case 'x': | ||
| 89 | case 'X': { | ||
| 90 |
3/4✓ Branch 55 → 56 taken 351 times.
✗ Branch 55 → 175 not taken.
✓ Branch 56 → 57 taken 2 times.
✓ Branch 56 → 66 taken 349 times.
|
351 | if (!argType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_BOOL})) |
| 91 |
5/10✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 180 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 178 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 176 not taken.
✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 182 not taken.
✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 182 not taken.
|
2 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 92 | "The placeholder string expects int, short, long, byte or bool, but got " + argType.getName(false)) | ||
| 93 | 349 | placeholderCount++; | |
| 94 | 349 | break; | |
| 95 | } | ||
| 96 | 54 | case 'a': | |
| 97 | case 'A': | ||
| 98 | case 'f': | ||
| 99 | case 'F': | ||
| 100 | case 'e': | ||
| 101 | case 'E': | ||
| 102 | case 'g': | ||
| 103 | case 'G': { | ||
| 104 |
3/4✓ Branch 67 → 68 taken 54 times.
✗ Branch 67 → 211 not taken.
✓ Branch 68 → 69 taken 1 time.
✓ Branch 68 → 78 taken 53 times.
|
54 | if (!argType.is(TY_DOUBLE)) |
| 105 |
5/10✓ Branch 69 → 70 taken 1 time.
✗ Branch 69 → 187 not taken.
✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 185 not taken.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 183 not taken.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 189 not taken.
✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 189 not taken.
|
1 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects double, but got " + argType.getName(false)) |
| 106 | 53 | placeholderCount++; | |
| 107 | 53 | break; | |
| 108 | } | ||
| 109 | 258 | case 's': { | |
| 110 |
13/18✓ Branch 79 → 80 taken 258 times.
✗ Branch 79 → 211 not taken.
✓ Branch 80 → 81 taken 63 times.
✓ Branch 80 → 88 taken 195 times.
✓ Branch 81 → 82 taken 63 times.
✗ Branch 81 → 211 not taken.
✓ Branch 82 → 83 taken 2 times.
✓ Branch 82 → 88 taken 61 times.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 211 not taken.
✓ Branch 84 → 85 taken 1 time.
✓ Branch 84 → 88 taken 1 time.
✓ Branch 85 → 86 taken 1 time.
✗ Branch 85 → 211 not taken.
✓ Branch 86 → 87 taken 1 time.
✗ Branch 86 → 88 not taken.
✓ Branch 89 → 90 taken 1 time.
✓ Branch 89 → 99 taken 257 times.
|
258 | if (!argType.is(TY_STRING) && !argType.isStringObj() && !argType.isPtrTo(TY_CHAR) && !argType.isArrayOf(TY_CHAR)) |
| 111 |
5/10✓ Branch 90 → 91 taken 1 time.
✗ Branch 90 → 194 not taken.
✓ Branch 91 → 92 taken 1 time.
✗ Branch 91 → 192 not taken.
✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 190 not taken.
✓ Branch 95 → 96 taken 1 time.
✗ Branch 95 → 196 not taken.
✓ Branch 96 → 97 taken 1 time.
✗ Branch 96 → 196 not taken.
|
1 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 112 | "The placeholder string expects string, String, char* or char[], but got " + argType.getName(false)) | ||
| 113 | 257 | placeholderCount++; | |
| 114 | 257 | break; | |
| 115 | } | ||
| 116 | 6 | case 'p': { | |
| 117 |
9/14✓ Branch 100 → 101 taken 6 times.
✗ Branch 100 → 211 not taken.
✓ Branch 101 → 102 taken 1 time.
✓ Branch 101 → 107 taken 5 times.
✓ Branch 102 → 103 taken 1 time.
✗ Branch 102 → 211 not taken.
✓ Branch 103 → 104 taken 1 time.
✗ Branch 103 → 107 not taken.
✓ Branch 104 → 105 taken 1 time.
✗ Branch 104 → 211 not taken.
✓ Branch 105 → 106 taken 1 time.
✗ Branch 105 → 107 not taken.
✓ Branch 108 → 109 taken 1 time.
✓ Branch 108 → 118 taken 5 times.
|
6 | if (!argType.isPtr() && !argType.isArray() && !argType.is(TY_STRING)) |
| 118 |
5/10✓ Branch 109 → 110 taken 1 time.
✗ Branch 109 → 201 not taken.
✓ Branch 110 → 111 taken 1 time.
✗ Branch 110 → 199 not taken.
✓ Branch 111 → 112 taken 1 time.
✗ Branch 111 → 197 not taken.
✓ Branch 114 → 115 taken 1 time.
✗ Branch 114 → 203 not taken.
✓ Branch 115 → 116 taken 1 time.
✗ Branch 115 → 203 not taken.
|
1 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 119 | "The placeholder string expects pointer, array or string, but got " + argType.getName(false)) | ||
| 120 | 5 | placeholderCount++; | |
| 121 | 5 | break; | |
| 122 | } | ||
| 123 | ✗ | default: | |
| 124 | ✗ | SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder") | |
| 125 | } | ||
| 126 | 692 | index = templatedString.find_first_of('%', index + 2); // We can also skip the following char | |
| 127 | } | ||
| 128 | |||
| 129 | // Check if the number of placeholders matches the number of args | ||
| 130 |
2/2✓ Branch 140 → 141 taken 1 time.
✓ Branch 140 → 151 taken 844 times.
|
845 | if (placeholderCount < node->argLst->args.size() - 1) |
| 131 |
4/8✓ Branch 143 → 144 taken 1 time.
✗ Branch 143 → 214 not taken.
✓ Branch 144 → 145 taken 1 time.
✗ Branch 144 → 212 not taken.
✓ Branch 147 → 148 taken 1 time.
✗ Branch 147 → 218 not taken.
✓ Branch 148 → 149 taken 1 time.
✗ Branch 148 → 218 not taken.
|
3 | SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains less placeholders than arguments") |
| 132 | |||
| 133 |
3/6✓ Branch 151 → 152 taken 844 times.
✗ Branch 151 → 219 not taken.
✓ Branch 152 → 153 taken 844 times.
✗ Branch 152 → 219 not taken.
✓ Branch 153 → 154 taken 844 times.
✗ Branch 153 → 219 not taken.
|
844 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_INT), manIdx)}; |
| 134 | 852 | } | |
| 135 | |||
| 136 | 153 | std::any TypeChecker::visitBuiltinSizeOfCall(FctCallNode *node) const { | |
| 137 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 153 times.
|
153 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_SIZEOF); |
| 138 | |||
| 139 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 140 | 153 | QualType qualType; | |
| 141 |
2/2✓ Branch 6 → 7 taken 129 times.
✓ Branch 6 → 10 taken 24 times.
|
153 | if (node->hasTemplateTypes) { // Align of type |
| 142 |
1/2✓ Branch 8 → 9 taken 129 times.
✗ Branch 8 → 54 not taken.
|
129 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 143 | } else { // Align of value | ||
| 144 |
1/2✓ Branch 11 → 12 taken 24 times.
✗ Branch 11 → 54 not taken.
|
24 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 145 | } | ||
| 146 | |||
| 147 |
3/4✓ Branch 13 → 14 taken 153 times.
✗ Branch 13 → 40 not taken.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 25 taken 151 times.
|
153 | if (qualType.isOneOf({TY_UNRESOLVED, TY_DYN})) |
| 148 |
4/8✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 43 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 41 not taken.
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 47 not taken.
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 47 not taken.
|
6 | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use sizeof on a dyn or unresolved type"); |
| 149 | |||
| 150 |
1/2✓ Branch 25 → 26 taken 151 times.
✗ Branch 25 → 54 not taken.
|
151 | llvm::Type *type = qualType.toLLVMType(sourceFile); |
| 151 |
3/6✓ Branch 27 → 28 taken 151 times.
✗ Branch 27 → 50 not taken.
✓ Branch 28 → 29 taken 151 times.
✗ Branch 28 → 48 not taken.
✓ Branch 29 → 30 taken 151 times.
✗ Branch 29 → 48 not taken.
|
151 | const int64_t typeSize = sourceFile->targetMachine->createDataLayout().getTypeAllocSize(type); |
| 152 |
1/2✓ Branch 31 → 32 taken 151 times.
✗ Branch 31 → 54 not taken.
|
151 | node->data.at(manIdx).setCompileTimeValue({.longValue = typeSize}); |
| 153 | |||
| 154 |
3/6✓ Branch 33 → 34 taken 151 times.
✗ Branch 33 → 52 not taken.
✓ Branch 34 → 35 taken 151 times.
✗ Branch 34 → 52 not taken.
✓ Branch 35 → 36 taken 151 times.
✗ Branch 35 → 52 not taken.
|
151 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 155 | } | ||
| 156 | |||
| 157 | 13 | std::any TypeChecker::visitBuiltinAlignOfCall(FctCallNode *node) const { | |
| 158 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 13 times.
|
13 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_ALIGNOF); |
| 159 | |||
| 160 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 161 | 13 | QualType qualType; | |
| 162 |
2/2✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 10 taken 11 times.
|
13 | if (node->hasTemplateTypes) { // Align of type |
| 163 |
1/2✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 54 not taken.
|
2 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 164 | } else { // Align of value | ||
| 165 |
1/2✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 54 not taken.
|
11 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 166 | } | ||
| 167 | |||
| 168 |
3/4✓ Branch 13 → 14 taken 13 times.
✗ Branch 13 → 40 not taken.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 25 taken 11 times.
|
13 | if (qualType.isOneOf({TY_UNRESOLVED, TY_DYN})) |
| 169 |
4/8✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 43 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 41 not taken.
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 47 not taken.
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 47 not taken.
|
6 | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use alignof on a dyn or unresolved type"); |
| 170 | |||
| 171 |
1/2✓ Branch 25 → 26 taken 11 times.
✗ Branch 25 → 54 not taken.
|
11 | llvm::Type *type = qualType.toLLVMType(sourceFile); |
| 172 |
2/4✓ Branch 27 → 28 taken 11 times.
✗ Branch 27 → 50 not taken.
✓ Branch 28 → 29 taken 11 times.
✗ Branch 28 → 48 not taken.
|
11 | const int64_t typeAlignment = sourceFile->targetMachine->createDataLayout().getABITypeAlign(type).value(); |
| 173 |
1/2✓ Branch 31 → 32 taken 11 times.
✗ Branch 31 → 54 not taken.
|
11 | node->data.at(manIdx).setCompileTimeValue({.longValue = typeAlignment}); |
| 174 | |||
| 175 |
3/6✓ Branch 33 → 34 taken 11 times.
✗ Branch 33 → 52 not taken.
✓ Branch 34 → 35 taken 11 times.
✗ Branch 34 → 52 not taken.
✓ Branch 35 → 36 taken 11 times.
✗ Branch 35 → 52 not taken.
|
11 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 176 | } | ||
| 177 | |||
| 178 | 8 | std::any TypeChecker::visitBuiltinTypeIdCall(FctCallNode *node) const { | |
| 179 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 8 times.
|
8 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_TYPEID); |
| 180 | |||
| 181 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 182 | 8 | QualType qualType; | |
| 183 |
2/2✓ Branch 6 → 7 taken 7 times.
✓ Branch 6 → 10 taken 1 time.
|
8 | if (node->hasTemplateTypes) { // typeid of type |
| 184 |
1/2✓ Branch 8 → 9 taken 7 times.
✗ Branch 8 → 26 not taken.
|
7 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 185 | } else { // typeid of value | ||
| 186 |
1/2✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
|
1 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 187 | } | ||
| 188 |
1/2✓ Branch 14 → 15 taken 8 times.
✗ Branch 14 → 26 not taken.
|
8 | const uint64_t typeId = TypeRegistry::getTypeHash(*qualType.getType()); |
| 189 |
1/2✓ Branch 15 → 16 taken 8 times.
✗ Branch 15 → 26 not taken.
|
8 | node->data.at(manIdx).setCompileTimeValue({.longValue = std::bit_cast<int64_t>(typeId)}); |
| 190 | |||
| 191 |
3/6✓ Branch 18 → 19 taken 8 times.
✗ Branch 18 → 24 not taken.
✓ Branch 19 → 20 taken 8 times.
✗ Branch 19 → 24 not taken.
✓ Branch 20 → 21 taken 8 times.
✗ Branch 20 → 24 not taken.
|
8 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 192 | } | ||
| 193 | |||
| 194 | 60 | std::any TypeChecker::visitBuiltinLenCall(FctCallNode *node) const { | |
| 195 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 60 times.
|
60 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_LEN); |
| 196 | |||
| 197 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 198 |
1/2✓ Branch 7 → 8 taken 60 times.
✗ Branch 7 → 56 not taken.
|
60 | QualType argType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 199 |
1/2✓ Branch 8 → 9 taken 60 times.
✗ Branch 8 → 45 not taken.
|
60 | argType = argType.removeReferenceWrapper(); |
| 200 | |||
| 201 | // Check if arg is of type array | ||
| 202 |
8/10✓ Branch 9 → 10 taken 60 times.
✗ Branch 9 → 56 not taken.
✓ Branch 10 → 11 taken 36 times.
✓ Branch 10 → 14 taken 24 times.
✓ Branch 11 → 12 taken 36 times.
✗ Branch 11 → 56 not taken.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 35 times.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 27 taken 59 times.
|
60 | if (!argType.isArray() && !argType.is(TY_STRING)) |
| 203 |
4/8✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 48 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 46 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 52 not taken.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 52 not taken.
|
3 | SOFT_ERROR_ER(node->argLst->args.front(), EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays or strings") |
| 204 | |||
| 205 |
3/4✓ Branch 27 → 28 taken 59 times.
✗ Branch 27 → 56 not taken.
✓ Branch 28 → 29 taken 24 times.
✓ Branch 28 → 33 taken 35 times.
|
59 | if (argType.is(TY_ARRAY)) { |
| 206 |
2/4✓ Branch 29 → 30 taken 24 times.
✗ Branch 29 → 56 not taken.
✓ Branch 30 → 31 taken 24 times.
✗ Branch 30 → 53 not taken.
|
24 | node->data.at(manIdx).setCompileTimeValue({.longValue = argType.getArraySize()}); |
| 207 | } else { | ||
| 208 | // If we want to use the len builtin on a string, we need to import the string runtime module | ||
| 209 |
3/4✓ Branch 33 → 34 taken 35 times.
✗ Branch 33 → 56 not taken.
✓ Branch 36 → 37 taken 34 times.
✓ Branch 36 → 38 taken 1 time.
|
70 | if (!sourceFile->isStringRT()) |
| 210 |
1/2✓ Branch 37 → 38 taken 34 times.
✗ Branch 37 → 56 not taken.
|
34 | sourceFile->requestRuntimeModule(STRING_RT); |
| 211 | } | ||
| 212 | |||
| 213 |
3/6✓ Branch 38 → 39 taken 59 times.
✗ Branch 38 → 54 not taken.
✓ Branch 39 → 40 taken 59 times.
✗ Branch 39 → 54 not taken.
✓ Branch 40 → 41 taken 59 times.
✗ Branch 40 → 54 not taken.
|
59 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 214 | } | ||
| 215 | |||
| 216 | 744 | std::any TypeChecker::visitBuiltinPanicCall(FctCallNode *node) const { | |
| 217 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 744 times.
|
744 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PANIC); |
| 218 | |||
| 219 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 744 times.
|
744 | assert(node->hasArgs); |
| 220 | 744 | const AssignExprNode *assignExpr = node->argLst->args.front(); | |
| 221 |
1/2✓ Branch 9 → 10 taken 744 times.
✗ Branch 9 → 47 not taken.
|
744 | QualType argType = assignExpr->getEvaluatedSymbolType(manIdx); |
| 222 |
2/8✓ Branch 10 → 11 taken 744 times.
✗ Branch 10 → 47 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 744 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 36 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 36 not taken.
|
744 | HANDLE_UNRESOLVED_TYPE_ER(argType) |
| 223 |
1/2✓ Branch 16 → 17 taken 744 times.
✗ Branch 16 → 37 not taken.
|
744 | argType = argType.removeReferenceWrapper(); |
| 224 | |||
| 225 | // Check if arg is of type array | ||
| 226 |
2/4✓ Branch 17 → 18 taken 744 times.
✗ Branch 17 → 47 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 29 taken 744 times.
|
744 | if (!argType.isErrorObj()) |
| 227 | ✗ | SOFT_ERROR_ER(assignExpr, EXPECTED_ERROR_TYPE, "The panic builtin can only work with errors") | |
| 228 | |||
| 229 |
3/6✓ Branch 29 → 30 taken 744 times.
✗ Branch 29 → 45 not taken.
✓ Branch 30 → 31 taken 744 times.
✗ Branch 30 → 45 not taken.
✓ Branch 31 → 32 taken 744 times.
✗ Branch 31 → 45 not taken.
|
744 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_DYN), manIdx)}; |
| 230 | } | ||
| 231 | |||
| 232 | 1 | std::any TypeChecker::visitBuiltinSyscallCall(FctCallNode *node) const { | |
| 233 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_SYSCALL); |
| 234 | |||
| 235 | // Check if the syscall number if of type short | ||
| 236 | 1 | const AssignExprNode *sysCallNumberExpr = node->argLst->args.front(); | |
| 237 |
1/2✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 57 not taken.
|
1 | const QualType sysCallNumberType = sysCallNumberExpr->getEvaluatedSymbolType(manIdx); |
| 238 |
2/4✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 57 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 20 taken 1 time.
|
1 | if (!sysCallNumberType.is(TY_SHORT)) |
| 239 | ✗ | SOFT_ERROR_ER(sysCallNumberExpr, INVALID_SYSCALL_NUMBER_TYPE, "Syscall number must be of type short") | |
| 240 | |||
| 241 | // Check if the syscall number is out of range | ||
| 242 | // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/ | ||
| 243 |
2/4✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 57 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 34 taken 1 time.
|
1 | if (node->hasCompileTimeValue(manIdx)) { |
| 244 | ✗ | const unsigned short sysCallNumber = node->getCompileTimeValue(manIdx).shortValue; | |
| 245 | ✗ | if (sysCallNumber < 0 || sysCallNumber > 439) | |
| 246 | ✗ | SOFT_ERROR_ER(node, SYSCALL_NUMBER_OUT_OF_RANGE, "Only syscall numbers between 0 and 439 are supported") | |
| 247 | } | ||
| 248 | |||
| 249 |
3/6✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 55 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 55 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 55 not taken.
|
1 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 250 | } | ||
| 251 | |||
| 252 | 6 | std::any TypeChecker::visitBuiltinIsSameCall(FctCallNode *node) const { | |
| 253 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 6 times.
|
6 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_SAME); |
| 254 | |||
| 255 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 256 |
1/2✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 25 not taken.
|
6 | node->setCompileTimeValue({.boolValue = true}, manIdx); |
| 257 | 6 | const std::vector<DataTypeNode *> &dataTypeNodes = node->templateTypeLst->dataTypes; | |
| 258 |
1/2✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 30 not taken.
|
6 | const QualType firstType = dataTypeNodes.front()->getEvaluatedSymbolType(manIdx); |
| 259 |
2/2✓ Branch 18 → 10 taken 6 times.
✓ Branch 18 → 19 taken 2 times.
|
8 | for (size_t i = 1; i < dataTypeNodes.size(); i++) { |
| 260 |
2/4✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 27 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 27 not taken.
|
6 | const QualType qualType = dataTypeNodes.at(i)->getEvaluatedSymbolType(manIdx); |
| 261 |
3/4✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 27 not taken.
✓ Branch 13 → 14 taken 4 times.
✓ Branch 13 → 16 taken 2 times.
|
6 | if (!qualType.matches(firstType, false, true, false)) { |
| 262 |
1/2✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 26 not taken.
|
4 | node->setCompileTimeValue({.boolValue = false}, manIdx); |
| 263 | 4 | break; | |
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 |
3/6✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 28 not taken.
✓ Branch 20 → 21 taken 6 times.
✗ Branch 20 → 28 not taken.
✓ Branch 21 → 22 taken 6 times.
✗ Branch 21 → 28 not taken.
|
6 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 268 | } | ||
| 269 | |||
| 270 | 1 | std::any TypeChecker::visitBuiltinImplementsInterfaceCall(FctCallNode *node) const { | |
| 271 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE); |
| 272 | |||
| 273 |
1/2✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 28 not taken.
|
1 | const QualType interfaceType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 274 |
1/2✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 28 not taken.
|
1 | const QualType structType = node->templateTypeLst->dataTypes.back()->getEvaluatedSymbolType(manIdx); |
| 275 |
6/12✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 28 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 17 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 28 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 17 not taken.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 28 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
|
1 | const bool value = interfaceType.is(TY_INTERFACE) && structType.is(TY_STRUCT) && structType.doesImplement(interfaceType, node); |
| 276 |
1/2✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 25 not taken.
|
1 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 277 | |||
| 278 |
3/6✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 26 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 26 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 26 not taken.
|
1 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 279 | } | ||
| 280 | |||
| 281 | } // namespace spice::compiler | ||
| 282 |