GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 5 / 1 / 6
Functions: 100.0% 1 / 0 / 1
Branches: 75.0% 3 / 0 / 4

src/typechecker/Builtins.h
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <array>
6
7 #include <irgenerator/IRGenerator.h>
8 #include <typechecker/TypeChecker.h>
9
10 namespace spice::compiler {
11
12 using TypeCheckerVisitMethod = std::any (TypeChecker::*)(FctCallNode *node) const;
13 using IRGeneratorVisitMethod = std::any (IRGenerator::*)(const FctCallNode *node);
14
15 // Represents a compiler builtin function
16 struct BuiltinFunctionInfo {
17 TypeCheckerVisitMethod typeCheckerVisitMethod = nullptr;
18 IRGeneratorVisitMethod irGeneratorVisitMethod = nullptr;
19 unsigned int minTemplateTypes = 0;
20 unsigned int maxTemplateTypes = 0;
21 unsigned int minArgTypes = 0;
22 unsigned int maxArgTypes = 0;
23 bool allTemplateTypesOrAllArgTypes = false;
24 bool isFunctionTerminator = false;
25 };
26
27 struct BuiltinFunctionEntry {
28 std::string_view name;
29 BuiltinFunctionInfo info;
30 };
31
32 // Constants
33 // Documented builtins
34 static constexpr std::string_view BUILTIN_FCT_NAME_PRINTF = "printf";
35 static constexpr std::string_view BUILTIN_FCT_NAME_SIZEOF = "sizeof";
36 static constexpr std::string_view BUILTIN_FCT_NAME_ALIGNOF = "alignof";
37 static constexpr std::string_view BUILTIN_FCT_NAME_TYPEID = "typeid";
38 static constexpr std::string_view BUILTIN_FCT_NAME_TYPENAME = "typename";
39 static constexpr std::string_view BUILTIN_FCT_NAME_LEN = "len";
40 static constexpr std::string_view BUILTIN_FCT_NAME_PANIC = "panic";
41 static constexpr std::string_view BUILTIN_FCT_NAME_SYSCALL = "syscall";
42 // Undocumented builtins (intended to be primarily used via std wrapper functions)
43 static constexpr std::string_view BUILTIN_FCT_NAME_OFFSETOF = "__offsetof";
44 static constexpr std::string_view BUILTIN_FCT_NAME_IS_SAME = "__is_same";
45 static constexpr std::string_view BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE = "__implements_interface";
46 static constexpr std::string_view BUILTIN_FCT_NAME_GET_BUILD_VAR = "__get_build_var";
47 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_CONSTRUCTIBLE = "__is_trivially_constructible";
48 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_COPYABLE = "__is_trivially_copyable";
49 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_DESTRUCTIBLE = "__is_trivially_destructible";
50 static constexpr std::string_view BUILTIN_FCT_NAME_NEW = "__new";
51 static constexpr std::string_view BUILTIN_FCT_NAME_PLACEMENT_NEW = "__placement_new";
52
53 static constexpr std::array BUILTIN_FUNCTIONS = {
54 BuiltinFunctionEntry{
55 BUILTIN_FCT_NAME_PRINTF,
56 BuiltinFunctionInfo{
57 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPrintfCall,
58 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPrintfCall,
59 .minArgTypes = 1,
60 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
61 },
62 },
63 BuiltinFunctionEntry{
64 BUILTIN_FCT_NAME_SIZEOF,
65 BuiltinFunctionInfo{
66 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSizeOfCall,
67 .maxTemplateTypes = 1,
68 .maxArgTypes = 1,
69 .allTemplateTypesOrAllArgTypes = true,
70 },
71 },
72 BuiltinFunctionEntry{
73 BUILTIN_FCT_NAME_ALIGNOF,
74 BuiltinFunctionInfo{
75 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinAlignOfCall,
76 .maxTemplateTypes = 1,
77 .maxArgTypes = 1,
78 .allTemplateTypesOrAllArgTypes = true,
79 },
80 },
81 BuiltinFunctionEntry{
82 BUILTIN_FCT_NAME_OFFSETOF,
83 BuiltinFunctionInfo{
84 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinOffsetOfCall,
85 .minArgTypes = 2,
86 .maxArgTypes = 2,
87 },
88 },
89 BuiltinFunctionEntry{
90 BUILTIN_FCT_NAME_TYPEID,
91 BuiltinFunctionInfo{
92 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinTypeIdCall,
93 .maxTemplateTypes = 1,
94 .maxArgTypes = 1,
95 .allTemplateTypesOrAllArgTypes = true,
96 },
97 },
98 BuiltinFunctionEntry{
99 BUILTIN_FCT_NAME_TYPENAME,
100 BuiltinFunctionInfo{
101 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinTypeNameCall,
102 .maxTemplateTypes = 1,
103 .maxArgTypes = 1,
104 .allTemplateTypesOrAllArgTypes = true,
105 },
106 },
107 BuiltinFunctionEntry{
108 BUILTIN_FCT_NAME_LEN,
109 BuiltinFunctionInfo{
110 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinLenCall,
111 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinLenCall,
112 .minArgTypes = 1,
113 .maxArgTypes = 1,
114 },
115 },
116 BuiltinFunctionEntry{
117 BUILTIN_FCT_NAME_PANIC,
118 BuiltinFunctionInfo{
119 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPanicCall,
120 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPanicCall,
121 .minArgTypes = 1,
122 .maxArgTypes = 1,
123 .isFunctionTerminator = true,
124 },
125 },
126 BuiltinFunctionEntry{
127 BUILTIN_FCT_NAME_SYSCALL,
128 BuiltinFunctionInfo{
129 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSyscallCall,
130 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinSyscallCall,
131 .minArgTypes = 1,
132 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
133 .maxArgTypes = 6,
134 },
135 },
136 BuiltinFunctionEntry{
137 BUILTIN_FCT_NAME_IS_SAME,
138 BuiltinFunctionInfo{
139 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsSameCall,
140 .minTemplateTypes = 2,
141 .maxTemplateTypes = std::numeric_limits<unsigned int>::max(),
142 },
143 },
144 BuiltinFunctionEntry{
145 BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE,
146 BuiltinFunctionInfo{
147 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinImplementsInterfaceCall,
148 .minTemplateTypes = 2,
149 .maxTemplateTypes = 2,
150 },
151 },
152 BuiltinFunctionEntry{
153 BUILTIN_FCT_NAME_GET_BUILD_VAR,
154 BuiltinFunctionInfo{
155 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinGetBuildVarCall,
156 .minTemplateTypes = 1,
157 .maxTemplateTypes = 1,
158 .minArgTypes = 1,
159 .maxArgTypes = 2,
160 },
161 },
162 BuiltinFunctionEntry{
163 BUILTIN_FCT_NAME_IS_TRIVIALLY_CONSTRUCTIBLE,
164 BuiltinFunctionInfo{
165 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyConstructible,
166 .minTemplateTypes = 1,
167 .maxTemplateTypes = 1,
168 },
169 },
170 BuiltinFunctionEntry{
171 BUILTIN_FCT_NAME_IS_TRIVIALLY_COPYABLE,
172 BuiltinFunctionInfo{
173 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyCopyable,
174 .minTemplateTypes = 1,
175 .maxTemplateTypes = 1,
176 },
177 },
178 BuiltinFunctionEntry{
179 BUILTIN_FCT_NAME_IS_TRIVIALLY_DESTRUCTIBLE,
180 BuiltinFunctionInfo{
181 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyDestructible,
182 .minTemplateTypes = 1,
183 .maxTemplateTypes = 1,
184 },
185 },
186 BuiltinFunctionEntry{
187 BUILTIN_FCT_NAME_NEW,
188 BuiltinFunctionInfo{
189 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinNewCall,
190 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinNewCall,
191 .minTemplateTypes = 1,
192 .maxTemplateTypes = 1,
193 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
194 },
195 },
196 BuiltinFunctionEntry{
197 BUILTIN_FCT_NAME_PLACEMENT_NEW,
198 BuiltinFunctionInfo{
199 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPlacementNewCall,
200 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPlacementNewCall,
201 .minTemplateTypes = 1,
202 .maxTemplateTypes = 1,
203 .minArgTypes = 1,
204 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
205 },
206 },
207 };
208
209 5 static const std::unordered_map<std::string_view, BuiltinFunctionInfo> BUILTIN_FUNCTIONS_MAP = [] {
210 5 std::unordered_map<std::string_view, BuiltinFunctionInfo> map;
211
2/2
✓ Branch 6 → 4 taken 85 times.
✓ Branch 6 → 7 taken 5 times.
90 for (const auto &[name, info] : BUILTIN_FUNCTIONS)
212
1/2
✓ Branch 4 → 5 taken 85 times.
✗ Branch 4 → 9 not taken.
85 map.emplace(name, info);
213 5 return map;
214 }(); // LCOV_EXCL_LINE - Coverage tool false positive
215
216 // Validate builtins at compile time
217 static consteval bool validateBuiltins() {
218 return std::ranges::all_of(BUILTIN_FUNCTIONS, [](const BuiltinFunctionEntry &entry) {
219 const auto &[name, info] = entry;
220 return !name.empty() && info.minTemplateTypes <= info.maxTemplateTypes && info.minArgTypes <= info.maxArgTypes;
221 });
222 }
223 static_assert(validateBuiltins(), "Invalid builtin function definitions");
224
225 } // namespace spice::compiler
226