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% 7 / 0 / 14

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