GCC Code Coverage Report


Directory: ../
File: src/SourceFile.h
Date: 2025-02-05 01:09:36
Exec Total Coverage
Lines: 3 3 100.0%
Functions: 0 0 -%
Branches: 6 12 50.0%

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <string>
6
7 #include <ast/ASTNodes.h>
8 #include <exception/AntlrThrowingErrorListener.h>
9 #include <global/RuntimeModuleManager.h>
10 #include <symboltablebuilder/Scope.h>
11 #include <util/CompilerWarning.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
32 enum CompileStageType : uint8_t {
33 NONE,
34 LEXER,
35 PARSER,
36 CST_VISUALIZER,
37 AST_BUILDER,
38 AST_VISUALIZER,
39 IMPORT_COLLECTOR,
40 SYMBOL_TABLE_BUILDER,
41 TYPE_CHECKER_PRE,
42 TYPE_CHECKER_POST,
43 DEP_GRAPH_VISUALIZER,
44 IR_GENERATOR,
45 IR_OPTIMIZER,
46 OBJECT_EMITTER,
47 FINISHED
48 };
49
50 enum CompileStageIOType : uint8_t {
51 IO_CODE,
52 IO_TOKENS,
53 IO_CST,
54 IO_AST,
55 IO_IR,
56 IO_OBJECT_FILE,
57 };
58
59 struct SourceFileAntlrCtx {
60 // Create error handlers for lexer and parser
61 std::unique_ptr<AntlrThrowingErrorListener> lexerErrorHandler;
62 std::unique_ptr<AntlrThrowingErrorListener> parserErrorHandler;
63 std::unique_ptr<antlr4::ANTLRInputStream> inputStream;
64 std::unique_ptr<SpiceLexer> lexer;
65 std::unique_ptr<antlr4::CommonTokenStream> tokenStream;
66 std::unique_ptr<SpiceParser> parser;
67 };
68
69 struct TimerOutput {
70 uint64_t lexer = 0;
71 uint64_t parser = 0;
72 uint64_t cstVisualizer = 0;
73 uint64_t astBuilder = 0;
74 uint64_t astVisualizer = 0;
75 uint64_t importCollector = 0;
76 uint64_t symbolTableBuilder = 0;
77 uint64_t typeCheckerPre = 0;
78 uint64_t typeCheckerPost = 0;
79 uint64_t depGraphVisualizer = 0;
80 uint64_t irGenerator = 0;
81 uint64_t irOptimizer = 0;
82 uint64_t objectEmitter = 0;
83 };
84
85 struct CompilerOutput {
86 std::string cstString;
87 std::string astString;
88 std::string symbolTableString;
89 std::string depGraphString;
90 std::string irString;
91 std::string irOptString;
92 std::string asmString;
93 std::string typesString;
94 std::vector<CompilerWarning> warnings;
95 TimerOutput times;
96 };
97
98 struct NameRegistryEntry {
99 std::string name;
100 uint64_t typeId; // Set for structs, interfaces, enums and aliases
101 SymbolTableEntry *targetEntry;
102 Scope *targetScope;
103 SymbolTableEntry *importEntry = nullptr;
104 };
105
106 class SourceFile {
107 public:
108 // Constructors
109 SourceFile(GlobalResourceManager &resourceManager, SourceFile *parent, std::string name, const std::filesystem::path &filePath,
110 bool stdFile);
111 SourceFile(const SourceFile &) = delete;
112
113 // Friend classes
114 friend class RuntimeModuleManager;
115
116 // Compiler pipeline triggers
117 void runLexer();
118 void runParser();
119 void runCSTVisualizer();
120 void runASTBuilder();
121 void runASTVisualizer();
122 void runImportCollector();
123 void runSymbolTableBuilder();
124
125 private:
126 void runTypeCheckerPre();
127 void runTypeCheckerPost();
128
129 public:
130 void runDependencyGraphVisualizer();
131 void runIRGenerator();
132 void runDefaultIROptimizer();
133 void runPreLinkIROptimizer();
134 void runBitcodeLinker();
135 void runPostLinkIROptimizer();
136 void runObjectEmitter();
137 void concludeCompilation();
138
139 // Shortcuts
140 void runFrontEnd();
141 void runMiddleEnd();
142 void runBackEnd();
143
144 // Public methods
145 void addDependency(SourceFile *sourceFile, const ASTNode *declNode, const std::string &dependencyName, const std::string &path);
146 [[nodiscard]] bool imports(const SourceFile *sourceFile) const;
147 [[nodiscard]] bool isAlreadyImported(const std::string &filePathSearch, std::stack<const SourceFile *> &circle) const;
148 SourceFile *requestRuntimeModule(RuntimeModule runtimeModule);
149 bool isRuntimeModuleAvailable(RuntimeModule runtimeModule) const;
150 void addNameRegistryEntry(const std::string &symbolName, uint64_t typeId, SymbolTableEntry *entry, Scope *scope,
151 bool keepNewOnCollision = true, SymbolTableEntry *importEntry = nullptr);
152 [[nodiscard]] const NameRegistryEntry *getNameRegistryEntry(const std::string &symbolName) const;
153 [[nodiscard]] llvm::Type *getLLVMType(const Type *type);
154 void checkForSoftErrors() const;
155 void collectAndPrintWarnings();
156 const SourceFile *getRootSourceFile() const;
157 bool isRT(RuntimeModule runtimeModule) const;
158
3/6
✓ Branch 0 (37→38) taken 1026 times.
✗ Branch 1 (37→214) not taken.
✓ Branch 2 (31→32) taken 154 times.
✗ Branch 3 (31→73) not taken.
✓ Branch 4 (31→32) taken 23 times.
✗ Branch 5 (31→61) not taken.
1259 ALWAYS_INLINE bool isStringRT() const { return isRT(STRING_RT); }
159
1/2
✓ Branch 0 (16→17) taken 955 times.
✗ Branch 1 (16→58) not taken.
955 ALWAYS_INLINE bool isMemoryRT() const { return isRT(MEMORY_RT); }
160
2/4
✓ Branch 0 (79→80) taken 354 times.
✗ Branch 1 (79→118) not taken.
✓ Branch 2 (176→177) taken 144 times.
✗ Branch 3 (176→282) not taken.
498 ALWAYS_INLINE bool isRttiRT() const { return isRT(RTTI_RT); }
161
162 // Public fields
163 std::string name;
164 std::string fileName;
165 std::filesystem::path filePath;
166 std::string fileDir;
167 bool isStdFile = false;
168 bool isMainFile = true;
169 bool alwaysKeepSymbolsOnNameCollision = false;
170 bool ignoreWarnings = false;
171 bool restoredFromCache = false;
172 bool reVisitRequested = true;
173 CompileStageType previousStage = NONE;
174 SourceFileAntlrCtx antlrCtx;
175 CompilerOutput compilerOutput;
176 SourceFile *parent;
177 std::string cacheKey;
178 EntryNode *ast = nullptr;
179 std::unique_ptr<Scope> globalScope;
180 llvm::LLVMContext context;
181 llvm::IRBuilder<> builder;
182 std::unique_ptr<llvm::TargetMachine> targetMachine;
183 std::unique_ptr<llvm::Module> llvmModule;
184 std::map<std::string, SourceFile *> dependencies; // Has to be an ordered map to keep the compilation order deterministic
185 std::vector<const SourceFile *> dependants;
186 std::unordered_map<std::string, NameRegistryEntry> exportedNameRegistry;
187 std::vector<const Function *> testFunctions;
188
189 private:
190 // Private fields
191 GlobalResourceManager &resourceManager;
192 const CliOptions &cliOptions;
193 std::unordered_map<const Type *, llvm::Type *> typeToLLVMTypeMapping;
194 uint8_t importedRuntimeModules = 0;
195 uint8_t totalTypeCheckerRuns = 0;
196
197 // Private methods
198 bool haveAllDependantsBeenTypeChecked() const;
199 void mergeNameRegistries(const SourceFile &importedSourceFile, const std::string &importName);
200 void dumpOutput(const std::string &content, const std::string &caption, const std::string &fileSuffix) const;
201 void visualizerPreamble(std::stringstream &output) const;
202 void visualizerOutput(std::string outputName, const std::string &output) const;
203 void printStatusMessage(const char *stage, const CompileStageIOType &in, const CompileStageIOType &out, uint64_t stageRuntime,
204 unsigned short stageRuns = 0) const;
205 };
206
207 } // namespace spice::compiler
208