GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 3 / 0 / 3
Functions: -% 0 / 0 / 0
Branches: 50.0% 8 / 0 / 16

src/SourceFile.h
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <filesystem>
6 #include <string>
7
8 #include <exception/AntlrThrowingErrorListener.h>
9 #include <global/RuntimeModuleManager.h>
10 #include <util/CompilerWarning.h>
11 #include <util/GlobalDefinitions.h>
12
13 #include <llvm/IR/IRBuilder.h>
14 #include <llvm/Target/TargetMachine.h>
15
16 // Ignore some warnings in ANTLR-generated code
17 #pragma GCC diagnostic push
18 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
19 #include <SpiceLexer.h>
20 #include <SpiceParser.h>
21 #pragma GCC diagnostic pop
22
23 namespace spice::compiler {
24
25 // Forward declarations
26 class GlobalResourceManager;
27 class EntryNode;
28 class ASTNode;
29 class Timer;
30 struct CliOptions;
31 class SymbolTableEntry;
32 class Scope;
33 class Function;
34 class Type;
35
36 enum CompileStageType : uint8_t {
37 NONE,
38 LEXER,
39 PARSER,
40 CST_VISUALIZER,
41 AST_BUILDER,
42 AST_VISUALIZER,
43 IMPORT_COLLECTOR,
44 SYMBOL_TABLE_BUILDER,
45 TYPE_CHECKER_PRE,
46 TYPE_CHECKER_POST,
47 DEP_GRAPH_VISUALIZER,
48 IR_GENERATOR,
49 IR_OPTIMIZER,
50 OBJECT_EMITTER,
51 FINISHED
52 };
53
54 enum CompileStageIOType : uint8_t {
55 IO_CODE,
56 IO_TOKENS,
57 IO_CST,
58 IO_AST,
59 IO_IR,
60 IO_OBJECT_FILE,
61 };
62
63 struct SourceFileAntlrCtx {
64 // Create error handlers for lexer and parser
65 std::unique_ptr<AntlrThrowingErrorListener> lexerErrorHandler;
66 std::unique_ptr<AntlrThrowingErrorListener> parserErrorHandler;
67 std::unique_ptr<antlr4::ANTLRInputStream> inputStream;
68 std::unique_ptr<SpiceLexer> lexer;
69 std::unique_ptr<antlr4::CommonTokenStream> tokenStream;
70 std::unique_ptr<SpiceParser> parser;
71 };
72
73 struct TimerOutput {
74 uint64_t lexer = 0;
75 uint64_t parser = 0;
76 uint64_t cstVisualizer = 0;
77 uint64_t astBuilder = 0;
78 uint64_t astVisualizer = 0;
79 uint64_t importCollector = 0;
80 uint64_t symbolTableBuilder = 0;
81 uint64_t typeCheckerPre = 0;
82 uint64_t typeCheckerPost = 0;
83 uint64_t depGraphVisualizer = 0;
84 uint64_t irGenerator = 0;
85 uint64_t irOptimizer = 0;
86 uint64_t objectEmitter = 0;
87 };
88
89 struct CompilerOutput {
90 std::string cstString;
91 std::string astString;
92 std::string symbolTableString;
93 std::string depGraphString;
94 std::string irString;
95 std::string irOptString;
96 std::string asmString;
97 std::string typesString;
98 std::string cacheStats;
99 std::vector<CompilerWarning> warnings;
100 TimerOutput times;
101 };
102
103 struct NameRegistryEntry {
104 std::string name;
105 uint64_t typeId; // Set for structs, interfaces, enums and aliases
106 SymbolTableEntry *targetEntry;
107 Scope *targetScope;
108 SymbolTableEntry *importEntry = nullptr;
109 };
110
111 class SourceFile {
112 public:
113 // Constructors
114 SourceFile(GlobalResourceManager &resourceManager, SourceFile *parent, std::string name, const std::filesystem::path &filePath,
115 bool stdFile);
116
117 // Prevent copy
118 SourceFile(const SourceFile &) = delete;
119 SourceFile &operator=(const SourceFile &) = delete;
120
121 // Friend classes
122 friend class RuntimeModuleManager;
123 friend class Type;
124
125 // Compiler pipeline triggers
126 void runLexer();
127 void runParser();
128 void runCSTVisualizer();
129 void runASTBuilder();
130 void runASTVisualizer();
131 void runImportCollector();
132 void runSymbolTableBuilder();
133
134 private:
135 void runTypeCheckerPre();
136 void runTypeCheckerPost();
137 void runPostTypeCheckingVerifier();
138
139 public:
140 void runDependencyGraphVisualizer();
141 void runIRGenerator();
142 void runDefaultIROptimizer();
143 void runPreLinkIROptimizer();
144 void runBitcodeLinker();
145 void runPostLinkIROptimizer();
146 void runObjectEmitter();
147 void concludeCompilation();
148
149 // Shortcuts
150 void runFrontEnd();
151 void runMiddleEnd();
152 void runBackEnd();
153
154 // Public methods
155 void addDependency(SourceFile *sourceFile, const std::string &dependencyName);
156 [[nodiscard]] bool imports(const SourceFile *sourceFile) const;
157 SourceFile *requestRuntimeModule(RuntimeModule runtimeModule);
158 bool isRuntimeModuleAvailable(RuntimeModule runtimeModule) const;
159 void addNameRegistryEntry(const std::string &symbolName, uint64_t typeId, SymbolTableEntry *entry, Scope *scope,
160 bool keepNewOnCollision = true, SymbolTableEntry *importEntry = nullptr);
161 [[nodiscard]] const NameRegistryEntry *getNameRegistryEntry(const std::string &symbolName) const;
162 [[nodiscard]] llvm::Type *getLLVMType(const Type *type);
163 void checkForSoftErrors() const;
164 void collectAndPrintWarnings();
165 const SourceFile *getRootSourceFile() const;
166 bool isRT(RuntimeModule runtimeModule) const;
167
4/8
✓ Branch 21 → 22 taken 1689 times.
✗ Branch 21 → 66 not taken.
✓ Branch 31 → 32 taken 344 times.
✗ Branch 31 → 73 not taken.
✓ Branch 33 → 34 taken 76 times.
✗ Branch 33 → 56 not taken.
✓ Branch 64 → 65 taken 161 times.
✗ Branch 64 → 149 not taken.
2589 ALWAYS_INLINE bool isStringRT() const { return isRT(STRING_RT); }
168
1/2
✓ Branch 17 → 18 taken 2089 times.
✗ Branch 17 → 66 not taken.
2089 ALWAYS_INLINE bool isMemoryRT() const { return isRT(MEMORY_RT); }
169
3/6
✓ Branch 21 → 22 taken 2242 times.
✗ Branch 21 → 119 not taken.
✓ Branch 110 → 111 taken 363 times.
✗ Branch 110 → 152 not taken.
✓ Branch 200 → 201 taken 479 times.
✗ Branch 200 → 310 not taken.
3084 ALWAYS_INLINE bool isRttiRT() const { return isRT(RTTI_RT); }
170
171 // Public fields
172 std::string name;
173 std::string fileName;
174 std::filesystem::path filePath;
175 std::string fileDir;
176 bool isStdFile = false;
177 bool isMainFile = true;
178 bool alwaysKeepSymbolsOnNameCollision = false;
179 bool ignoreWarnings = false;
180 bool restoredFromCache = false;
181 bool reVisitRequested = true;
182 CompileStageType previousStage = NONE;
183 SourceFileAntlrCtx antlrCtx;
184 CompilerOutput compilerOutput;
185 SourceFile *parent;
186 std::string cacheKey;
187 std::vector<std::filesystem::path> cachedObjectFilePaths;
188 std::vector<std::string> sourceLinkerFlags;
189 std::vector<std::filesystem::path> sourceAdditionalSourcePaths;
190 EntryNode *ast = nullptr;
191 std::unique_ptr<Scope> globalScope;
192 llvm::LLVMContext context;
193 llvm::IRBuilder<> builder;
194 std::unique_ptr<llvm::TargetMachine> targetMachine;
195 std::unique_ptr<llvm::Module> llvmModule;
196 std::map<std::string, SourceFile *> dependencies; // Has to be an ordered map to keep the compilation order deterministic
197 std::vector<const SourceFile *> dependants;
198 std::map<std::string, NameRegistryEntry> exportedNameRegistry;
199 std::vector<const Function *> testFunctions;
200
201 private:
202 // Private fields
203 GlobalResourceManager &resourceManager;
204 const CliOptions &cliOptions;
205 std::unordered_map<const Type *, llvm::Type *> typeToLLVMTypeMapping;
206 uint8_t importedRuntimeModules = 0;
207 uint8_t totalTypeCheckerRuns = 0;
208 // Cycle-safety guards: the pipeline drivers recurse over a dependency graph that may contain cycles (circular
209 // imports). These flags prevent re-entering a file that is already being processed in the same stage.
210 bool registriesMerged = false;
211 bool typeCheckerPreRunning = false;
212 bool typeCheckerPostRunning = false;
213 bool backEndStarted = false;
214 bool warningsCollected = false;
215
216 // Private methods
217 bool haveAllDependantsBeenTypeChecked() const;
218 [[nodiscard]] bool dependsOn(const SourceFile *other) const;
219 void mergeNameRegistries(const SourceFile &importedSourceFile, const std::string &importName);
220 void mergeNameRegistriesRecursive();
221 void dumpCacheStats();
222 void dumpCompilationStats() const;
223 void dumpOutput(const std::string &content, const std::string &caption, const std::string &fileSuffix) const;
224 void visualizerPreamble(std::stringstream &output) const;
225 void visualizerOutput(std::string outputName, const std::string &output) const;
226 void printStatusMessage(const char *stage, const CompileStageIOType &in, const CompileStageIOType &out, uint64_t stageRuntime,
227 unsigned short stageRuns = 0) const;
228 };
229
230 } // namespace spice::compiler
231