GCC Code Coverage Report


src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
75 / 77, 2 excl
97.4%
Branches:
55 / 60, 6 excl
91.7%
Functions:
10 / 11
90.9%

global/runtime-module-manager.spice
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 // Std imports
4 import "std/data/unordered-map";
5
6 // Own imports
7 import "@/source-file";
8 import "@/util/system-util";
9 import "@/global/global-resource-manager";
10 import "@/symboltablebuilder/qual-type";
11
12 // Constants
13 const string STRING_RT_IMPORT_NAME = "__rt_string";
14 const string RESULT_RT_IMPORT_NAME = "__rt_result";
15 const string ERROR_RT_IMPORT_NAME = "__rt_error";
16 const string ERROR_TRACE_RT_IMPORT_NAME = "__rt_error_trace";
17 const string MEMORY_RT_IMPORT_NAME = "__rt_memory";
18 const string RTTI_RT_IMPORT_NAME = "__rt_rtti";
19 const string STACK_TRACE_RT_IMPORT_NAME = "__rt_stack_trace";
20
21 public type RuntimeModule enum {
22 STRING_RT = 1,
23 RESULT_RT = 2,
24 ERROR_RT = 4,
25 ERROR_TRACE_RT = 8,
26 MEMORY_RT = 16,
27 RTTI_RT = 32,
28 STACK_TRACE_RT = 64
29 }
30
31 /**
32 * Get the runtime module, that is required when using the type with the given name
33 *
34 * @param typeName Type name
35 * @param runtimeModule Receives the runtime module, if found
36 * @return True if the type requires a runtime module
37 */
38 140855 public f<bool> getRuntimeModuleForTypeName(const String& typeName, RuntimeModule& runtimeModule) {
39
2/2
✓ Branch 0 taken 21494 times.
✓ Branch 1 taken 119361 times.
140855 if typeName == STROBJ_NAME {
40 21494 runtimeModule = RuntimeModule::STRING_RT;
41
2/2
✓ Branch 0 taken 3660 times.
✓ Branch 1 taken 115701 times.
140855 } else if typeName == RESULTOBJ_NAME {
42 3660 runtimeModule = RuntimeModule::RESULT_RT;
43
2/2
✓ Branch 0 taken 4627 times.
✓ Branch 1 taken 111074 times.
119361 } else if typeName == ERROBJ_NAME {
44 4627 runtimeModule = RuntimeModule::ERROR_RT;
45 4627 } else {
46 111074 return false;
47 8287 }
48 29781 return true;
49 }
50
51 /**
52 * Get the runtime module, that is required when calling the function with the given name
53 *
54 * @param functionName Function name
55 * @param runtimeModule Receives the runtime module, if found
56 * @return True if the function requires a runtime module
57 */
58 40741 public f<bool> getRuntimeModuleForFunctionName(const String& functionName, RuntimeModule& runtimeModule) {
59 // Memory RT
60
7/8
✓ Branch 0 taken 40218 times.
✓ Branch 1 taken 523 times.
✓ Branch 2 taken 40145 times.
✓ Branch 3 taken 73 times.
✓ Branch 4 taken 39906 times.
✓ Branch 5 taken 239 times.
✓ Branch 6 taken 39906 times.
✗ Branch 7 not taken.
40741 if functionName == "sAlloc" || functionName == "sAllocUnsafe" || functionName == "sRealloc" || functionName == "sReallocUnsafe"
61
8/8
✓ Branch 0 taken 39898 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 39815 times.
✓ Branch 3 taken 83 times.
✓ Branch 4 taken 39618 times.
✓ Branch 5 taken 197 times.
✓ Branch 6 taken 39159 times.
✓ Branch 7 taken 459 times.
39906 || functionName == "sCopy" || functionName == "sCopyUnsafe" || functionName == "sMove" || functionName == "sDestruct"
62
6/6
✓ Branch 0 taken 38424 times.
✓ Branch 1 taken 735 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 38342 times.
✓ Branch 4 taken 2399 times.
✓ Branch 5 taken 38342 times.
40741 || functionName == "sDealloc" || functionName == "sDelete" || functionName == "sCompare" {
63 2399 runtimeModule = RuntimeModule::MEMORY_RT;
64
4/4
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 37608 times.
✓ Branch 2 taken 1563 times.
✓ Branch 3 taken 36779 times.
40741 } else if functionName == "ok" || functionName == "err" { // Result RT
65 1563 runtimeModule = RuntimeModule::RESULT_RT;
66
4/6
✓ Branch 0 taken 36779 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36779 times.
✓ Branch 4 taken 332 times.
✓ Branch 5 taken 36447 times.
38342 } else if functionName == "sErrTraceReset" || functionName == "sErrTracePush" || functionName == "sErrTraceDump" { // Error Trace RT
67 332 runtimeModule = RuntimeModule::ERROR_TRACE_RT;
68
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 36446 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 36443 times.
36779 } else if functionName == "sDumpStacktrace" || functionName == "sGetStacktrace" { // Stack Trace RT
69 4 runtimeModule = RuntimeModule::STACK_TRACE_RT;
70 4 } else {
71 36443 return false;
72 1899 }
73 4298 return true;
74 }
75
76 /**
77 * Get the name of a top level definition, that identifies a source file as the given runtime module
78 *
79 * @param runtimeModule Runtime module
80 * @return Identifying top level name
81 */
82 45267 public f<string> getIdentifyingTopLevelName(RuntimeModule runtimeModule) {
83
7/8
✓ Branch 0 taken 26222 times.
✓ Branch 1 taken 5228 times.
✓ Branch 2 taken 4627 times.
✓ Branch 3 taken 332 times.
✓ Branch 4 taken 6350 times.
✓ Branch 5 taken 2489 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 19 times.
45267 switch runtimeModule {
84 26222 case RuntimeModule::STRING_RT: { return STROBJ_NAME; } // String struct
85 5228 case RuntimeModule::RESULT_RT: { return RESULTOBJ_NAME; } // Result struct
86 4627 case RuntimeModule::ERROR_RT: { return ERROBJ_NAME; } // Error struct
87 332 case RuntimeModule::ERROR_TRACE_RT: { return "sErrTracePush"; } // sErrTracePush function
88 6350 case RuntimeModule::MEMORY_RT: { return "sAlloc"; } // sAlloc function
89 2489 case RuntimeModule::RTTI_RT: { return TIOBJ_NAME; } // TypeInfo struct
90 19 case RuntimeModule::STACK_TRACE_RT: { return "sDumpStacktrace"; } // sDumpStacktrace function
91 − default: { panic(Error("Requested unknown runtime module")); } // LCOV_EXCL_LINE
92 }
93 ✗ }
94
95 type ModuleNamePair struct {
96 string importName
97 string fileName
98 }
99
100 766 public type RuntimeModuleManager struct {
101 GlobalResourceManager &resourceManager
102 UnorderedMap<RuntimeModule, SourceFile *> modules
103 }
104
105 1055 public p RuntimeModuleManager.ctor(GlobalResourceManager &resourceManager) {
106 1055 this.resourceManager = resourceManager;
107 1055 }
108
109 3522 public f<SourceFile *> RuntimeModuleManager.requestModule(SourceFile* parentSourceFile, RuntimeModule requestedModule) {
110 3522 const String importName = String(this.resolveNamePair(requestedModule).importName);
111
112 // Check if the requested module is available already, if not load it
113
2/2
✓ Branch 0 taken 2032 times.
✓ Branch 1 taken 1490 times.
3522 dyn rtFile = this.isModuleAvailable(requestedModule) ? this.getModule(requestedModule) : this.loadModule(parentSourceFile, requestedModule);
114
115 // Add the dependency to the parent source file
116 3522 parentSourceFile.addDependency(rtFile, importName);
117 3522 assert parentSourceFile.dependencies.contains(importName);
118 3522 SourceFile* runtimeFile = parentSourceFile.dependencies.get(importName);
119 3522 this.modules.upsert(requestedModule, runtimeFile);
120
121 // Merge the module name registry with the one of the source file
122 3522 parentSourceFile.mergeNameRegistries(*rtFile, importName);
123
124 // Tell the source file, that the requested runtime has been imported
125 3522 parentSourceFile.importedRuntimeModules |= requestedModule;
126
127 7044 return runtimeFile;
128 3522 }
129
130 20040 public f<SourceFile *> RuntimeModuleManager.getModule(RuntimeModule requestedModule) {
131 20040 assert this.modules.contains(requestedModule);
132 20040 return this.modules.get(requestedModule);
133 }
134
135 3522 public f<bool> RuntimeModuleManager.isModuleAvailable(RuntimeModule requestedModule) {
136 3522 return this.modules.contains(requestedModule);
137 }
138
139 1490 public f<SourceFile *> RuntimeModuleManager.loadModule(SourceFile* parentSourceFile, RuntimeModule requestedModule) {
140 1490 const ModuleNamePair namePair = this.resolveNamePair(requestedModule);
141 1490 const FilePath filePath = getStdDir() / "runtime" / (String(namePair.fileName) + ".spice");
142 1490 assert filePath != parentSourceFile.filePath;
143
144 // Instruct the global resource manager to create a new source file
145 1490 SourceFile* moduleSourceFile = this.resourceManager.createSourceFile(parentSourceFile, String(namePair.importName), filePath, true);
146 1490 moduleSourceFile.isMainFile = false;
147
148 // Run frontend and first type checker run for the loaded source file
149 1490 moduleSourceFile.runFrontEnd();
150 // Merge the runtime module's own dependency registries (deferred tail of the front-end, see SourceFile.runMiddleEnd)
151 1490 moduleSourceFile.mergeNameRegistriesRecursive();
152 1490 moduleSourceFile.runTypeCheckerPre();
153
154 2980 return moduleSourceFile;
155 1490 }
156
157 5012 public f<ModuleNamePair> RuntimeModuleManager.resolveNamePair(RuntimeModule requestedModule) {
158
7/8
✓ Branch 0 taken 1038 times.
✓ Branch 1 taken 683 times.
✓ Branch 2 taken 1291 times.
✓ Branch 3 taken 664 times.
✓ Branch 4 taken 610 times.
✓ Branch 5 taken 712 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
5012 switch requestedModule {
159 case RuntimeModule::STRING_RT: {
160 1038 return ModuleNamePair{STRING_RT_IMPORT_NAME, "string_rt"};
161 }
162 case RuntimeModule::RESULT_RT: {
163 683 return ModuleNamePair{RESULT_RT_IMPORT_NAME, "result_rt"};
164 }
165 case RuntimeModule::ERROR_RT: {
166 1291 return ModuleNamePair{ERROR_RT_IMPORT_NAME, "error_rt"};
167 }
168 case RuntimeModule::ERROR_TRACE_RT: {
169 664 return ModuleNamePair{ERROR_TRACE_RT_IMPORT_NAME, "error_trace_rt"};
170 }
171 case RuntimeModule::MEMORY_RT: {
172 610 return ModuleNamePair{MEMORY_RT_IMPORT_NAME, "memory_rt"};
173 }
174 case RuntimeModule::RTTI_RT: {
175 712 return ModuleNamePair{RTTI_RT_IMPORT_NAME, "rtti_rt"};
176 }
177 case RuntimeModule::STACK_TRACE_RT: {
178 14 return ModuleNamePair{STACK_TRACE_RT_IMPORT_NAME, "stack_trace_rt"};
179 }
180 default: { // LCOV_EXCL_LINE
181 − panic(Error("Requested unknown runtime module")); // LCOV_EXCL_LINE
182 } // LCOV_EXCL_LINE
183 }
184 ✗ }
185