GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 83.3% 5 / 0 / 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
45 static constexpr std::array BUILTIN_FUNCTIONS = {
46 BuiltinFunctionEntry{
47 BUILTIN_FCT_NAME_PRINTF,
48 BuiltinFunctionInfo{
49 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPrintfCall,
50 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPrintfCall,
51 .minArgTypes = 1,
52 .maxArgTypes = std::numeric_limits<unsigned int>::max(),
53 },
54 },
55 BuiltinFunctionEntry{
56 BUILTIN_FCT_NAME_SIZEOF,
57 BuiltinFunctionInfo{
58 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSizeOfCall,
59 .maxTemplateTypes = 1,
60 .maxArgTypes = 1,
61 .allTemplateTypesOrAllArgTypes = true,
62 },
63 },
64 BuiltinFunctionEntry{
65 BUILTIN_FCT_NAME_ALIGNOF,
66 BuiltinFunctionInfo{
67 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinAlignOfCall,
68 .maxTemplateTypes = 1,
69 .maxArgTypes = 1,
70 .allTemplateTypesOrAllArgTypes = true,
71 },
72 },
73 BuiltinFunctionEntry{
74 BUILTIN_FCT_NAME_TYPEID,
75 BuiltinFunctionInfo{
76 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinTypeIdCall,
77 .maxTemplateTypes = 1,
78 .maxArgTypes = 1,
79 .allTemplateTypesOrAllArgTypes = true,
80 },
81 },
82 BuiltinFunctionEntry{
83 BUILTIN_FCT_NAME_LEN,
84 BuiltinFunctionInfo{
85 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinLenCall,
86 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinLenCall,
87 .minArgTypes = 1,
88 .maxArgTypes = 1,
89 },
90 },
91 BuiltinFunctionEntry{
92 BUILTIN_FCT_NAME_PANIC,
93 BuiltinFunctionInfo{
94 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinPanicCall,
95 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinPanicCall,
96 .minArgTypes = 1,
97 .maxArgTypes = 1,
98 .isFunctionTerminator = true,
99 },
100 },
101 BuiltinFunctionEntry{
102 BUILTIN_FCT_NAME_SYSCALL,
103 BuiltinFunctionInfo{
104 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinSyscallCall,
105 .irGeneratorVisitMethod = &IRGenerator::visitBuiltinSyscallCall,
106 .minArgTypes = 1,
107 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
108 .maxArgTypes = 6,
109 },
110 },
111 BuiltinFunctionEntry{
112 BUILTIN_FCT_NAME_IS_SAME,
113 BuiltinFunctionInfo{
114 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinIsSameCall,
115 .minTemplateTypes = 2,
116 .maxTemplateTypes = std::numeric_limits<unsigned int>::max(),
117 },
118 },
119 BuiltinFunctionEntry{
120 BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE,
121 BuiltinFunctionInfo{
122 .typeCheckerVisitMethod = &TypeChecker::visitBuiltinImplementsInterfaceCall,
123 .minTemplateTypes = 2,
124 .maxTemplateTypes = 2,
125 },
126 },
127 };
128
129 5 static const std::unordered_map<std::string_view, BuiltinFunctionInfo> BUILTIN_FUNCTIONS_MAP = [] {
130 5 std::unordered_map<std::string_view, BuiltinFunctionInfo> map;
131
2/2
✓ Branch 6 → 4 taken 45 times.
✓ Branch 6 → 7 taken 5 times.
50 for (const auto &[name, info] : BUILTIN_FUNCTIONS)
132
1/2
✓ Branch 4 → 5 taken 45 times.
✗ Branch 4 → 9 not taken.
45 map.emplace(name, info);
133 5 return map;
134 }();
135
136 // Validate builtins at compile time
137 static consteval bool validateBuiltins() {
138 return std::ranges::all_of(BUILTIN_FUNCTIONS, [](const BuiltinFunctionEntry &entry) {
139 const auto &[name, info] = entry;
140 return !name.empty() && info.minTemplateTypes <= info.maxTemplateTypes && info.minArgTypes <= info.maxArgTypes;
141 });
142 }
143 static_assert(validateBuiltins(), "Invalid builtin function definitions");
144
145 } // namespace spice::compiler
146