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_LEN = "len";
39 static constexpr std::string_view BUILTIN_FCT_NAME_PANIC = "panic";
40 static constexpr std::string_view BUILTIN_FCT_NAME_SYSCALL = "syscall";
41 // Undocumented builtins (intended to be primarily used via std wrapper functions)
42 static constexpr std::string_view BUILTIN_FCT_NAME_IS_SAME = "__is_same";
43 static constexpr std::string_view BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE = "__implements_interface";
44 static constexpr std::string_view BUILTIN_FCT_NAME_GET_BUILD_VAR = "__get_build_var";
45 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_CONSTRUCTIBLE = "__is_trivially_constructible";
46 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_COPYABLE = "__is_trivially_copyable";
47 static constexpr std::string_view BUILTIN_FCT_NAME_IS_TRIVIALLY_DESTRUCTIBLE = "__is_trivially_destructible";
48 static constexpr std::string_view BUILTIN_FCT_NAME_NEW = "__new";
49 static constexpr std::string_view BUILTIN_FCT_NAME_PLACEMENT_NEW = "__placement_new";
50
51 static constexpr std::array BUILTIN_FUNCTIONS = {
52 BuiltinFunctionEntry{
53 BUILTIN_FCT_NAME_PRINTF,
54 BuiltinFunctionInfo{
55 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPrintfCall,
56 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPrintfCall,
57 .minArgTypes = 1,
58 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
59 },
60 },
61 BuiltinFunctionEntry{
62 BUILTIN_FCT_NAME_SIZEOF,
63 BuiltinFunctionInfo{
64 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSizeOfCall,
65 .maxTemplateTypes = 1,
66 .maxArgTypes = 1,
67 .allTemplateTypesOrAllArgTypes = true,
68 },
69 },
70 BuiltinFunctionEntry{
71 BUILTIN_FCT_NAME_ALIGNOF,
72 BuiltinFunctionInfo{
73 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinAlignOfCall,
74 .maxTemplateTypes = 1,
75 .maxArgTypes = 1,
76 .allTemplateTypesOrAllArgTypes = true,
77 },
78 },
79 BuiltinFunctionEntry{
80 BUILTIN_FCT_NAME_TYPEID,
81 BuiltinFunctionInfo{
82 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinTypeIdCall,
83 .maxTemplateTypes = 1,
84 .maxArgTypes = 1,
85 .allTemplateTypesOrAllArgTypes = true,
86 },
87 },
88 BuiltinFunctionEntry{
89 BUILTIN_FCT_NAME_LEN,
90 BuiltinFunctionInfo{
91 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinLenCall,
92 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinLenCall,
93 .minArgTypes = 1,
94 .maxArgTypes = 1,
95 },
96 },
97 BuiltinFunctionEntry{
98 BUILTIN_FCT_NAME_PANIC,
99 BuiltinFunctionInfo{
100 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPanicCall,
101 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPanicCall,
102 .minArgTypes = 1,
103 .maxArgTypes = 1,
104 .isFunctionTerminator = true,
105 },
106 },
107 BuiltinFunctionEntry{
108 BUILTIN_FCT_NAME_SYSCALL,
109 BuiltinFunctionInfo{
110 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSyscallCall,
111 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinSyscallCall,
112 .minArgTypes = 1,
113 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
114 .maxArgTypes = 6,
115 },
116 },
117 BuiltinFunctionEntry{
118 BUILTIN_FCT_NAME_IS_SAME,
119 BuiltinFunctionInfo{
120 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsSameCall,
121 .minTemplateTypes = 2,
122 .maxTemplateTypes = std::numeric_limits<unsigned int>::max(),
123 },
124 },
125 BuiltinFunctionEntry{
126 BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE,
127 BuiltinFunctionInfo{
128 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinImplementsInterfaceCall,
129 .minTemplateTypes = 2,
130 .maxTemplateTypes = 2,
131 },
132 },
133 BuiltinFunctionEntry{
134 BUILTIN_FCT_NAME_GET_BUILD_VAR,
135 BuiltinFunctionInfo{
136 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinGetBuildVarCall,
137 .minTemplateTypes = 1,
138 .maxTemplateTypes = 1,
139 .minArgTypes = 1,
140 .maxArgTypes = 2,
141 },
142 },
143 BuiltinFunctionEntry{
144 BUILTIN_FCT_NAME_IS_TRIVIALLY_CONSTRUCTIBLE,
145 BuiltinFunctionInfo{
146 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyConstructible,
147 .minTemplateTypes = 1,
148 .maxTemplateTypes = 1,
149 },
150 },
151 BuiltinFunctionEntry{
152 BUILTIN_FCT_NAME_IS_TRIVIALLY_COPYABLE,
153 BuiltinFunctionInfo{
154 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyCopyable,
155 .minTemplateTypes = 1,
156 .maxTemplateTypes = 1,
157 },
158 },
159 BuiltinFunctionEntry{
160 BUILTIN_FCT_NAME_IS_TRIVIALLY_DESTRUCTIBLE,
161 BuiltinFunctionInfo{
162 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsTriviallyDestructible,
163 .minTemplateTypes = 1,
164 .maxTemplateTypes = 1,
165 },
166 },
167 BuiltinFunctionEntry{
168 BUILTIN_FCT_NAME_NEW,
169 BuiltinFunctionInfo{
170 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinNewCall,
171 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinNewCall,
172 .minTemplateTypes = 1,
173 .maxTemplateTypes = 1,
174 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
175 },
176 },
177 BuiltinFunctionEntry{
178 BUILTIN_FCT_NAME_PLACEMENT_NEW,
179 BuiltinFunctionInfo{
180 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPlacementNewCall,
181 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPlacementNewCall,
182 .minTemplateTypes = 1,
183 .maxTemplateTypes = 1,
184 .minArgTypes = 1,
185 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
186 },
187 },
188 };
189
190 5 static const std::unordered_map<std::string_view, BuiltinFunctionInfo> BUILTIN_FUNCTIONS_MAP = [] {
191 5 std::unordered_map<std::string_view, BuiltinFunctionInfo> map;
192
2/2
✓ Branch 6 → 4 taken 75 times.
✓ Branch 6 → 7 taken 5 times.
80 for (const auto &[name, info] : BUILTIN_FUNCTIONS)
193
1/2
✓ Branch 4 → 5 taken 75 times.
✗ Branch 4 → 9 not taken.
75 map.emplace(name, info);
194 5 return map;
195 }(); // LCOV_EXCL_LINE - Coverage tool false positive
196
197 // Validate builtins at compile time
198 static consteval bool validateBuiltins() {
199 return std::ranges::all_of(BUILTIN_FUNCTIONS, [](const BuiltinFunctionEntry &entry) {
200 const auto &[name, info] = entry;
201 return !name.empty() && info.minTemplateTypes <= info.maxTemplateTypes && info.minArgTypes <= info.maxArgTypes;
202 });
203 }
204 static_assert(validateBuiltins(), "Invalid builtin function definitions");
205
206 } // namespace spice::compiler
207