GCC Code Coverage Report


Directory: ../
File: src/irgenerator/IRGenerator.h
Date: 2025-11-05 11:20:33
Coverage Exec Excl Total
Lines: 100.0% 3 0 3
Functions: -% 0 0 0
Branches: 45.6% 47 0 103

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include "driver/Driver.h"
6
7 #include <CompilerPass.h>
8 #include <ast/ParallelizableASTVisitor.h>
9 #include <irgenerator/DebugInfoGenerator.h>
10 #include <irgenerator/MetadataGenerator.h>
11 #include <irgenerator/OpRuleConversionManager.h>
12 #include <irgenerator/StdFunctionManager.h>
13 #include <symboltablebuilder/Scope.h>
14 #include <util/DeferredLogic.h>
15
16 namespace spice::compiler {
17
18 // Forward declarations
19 class ExprNode;
20
21 const char *const ANON_GLOBAL_STRING_NAME = "anon.string.";
22 const char *const ANON_GLOBAL_ARRAY_NAME = "anon.array.";
23 const char *const CAPTURES_PARAM_NAME = "captures";
24 static const std::string PRODUCER_STRING =
25 "spice version " + std::string(SPICE_VERSION) + " (https://github.com/spicelang/spice)";
26
27 enum class Likelihood : uint8_t {
28 UNSPECIFIED,
29 LIKELY,
30 UNLIKELY,
31 };
32
33 // Forward declarations
34 class SourceFile;
35
36 class IRGenerator final : CompilerPass, public ParallelizableASTVisitor {
37 public:
38 // Type definitions
39 using ParamInfoList = std::vector<std::pair<std::string, SymbolTableEntry *>>;
40
41 // Constructors
42 IRGenerator(GlobalResourceManager &resourceManager, SourceFile *sourceFile);
43
44 // Friend classes
45 friend class StdFunctionManager;
46 friend class OpRuleConversionManager;
47 friend class DebugInfoGenerator;
48 friend class MetadataGenerator;
49 friend class ScopeHandle;
50
51 // Visitor methods
52 // Top level definitions
53 std::any visitEntry(const EntryNode *node) override;
54 std::any visitMainFctDef(const MainFctDefNode *node) override;
55 std::any visitFctDef(const FctDefNode *node) override;
56 std::any visitProcDef(const ProcDefNode *node) override;
57 std::any visitStructDef(const StructDefNode *node) override;
58 std::any visitInterfaceDef(const InterfaceDefNode *node) override;
59 std::any visitEnumDef(const EnumDefNode *node) override;
60 std::any visitGenericTypeDef(const GenericTypeDefNode *node) override;
61 std::any visitAliasDef(const AliasDefNode *node) override;
62 std::any visitGlobalVarDef(const GlobalVarDefNode *node) override;
63 std::any visitExtDecl(const ExtDeclNode *node) override;
64 // Control structures
65 std::any visitUnsafeBlockDef(const UnsafeBlockNode *node) override;
66 std::any visitForLoop(const ForLoopNode *node) override;
67 std::any visitForeachLoop(const ForeachLoopNode *node) override;
68 std::any visitWhileLoop(const WhileLoopNode *node) override;
69 std::any visitDoWhileLoop(const DoWhileLoopNode *node) override;
70 std::any visitIfStmt(const IfStmtNode *node) override;
71 std::any visitElseStmt(const ElseStmtNode *node) override;
72 std::any visitSwitchStmt(const SwitchStmtNode *node) override;
73 std::any visitCaseBranch(const CaseBranchNode *node) override;
74 std::any visitDefaultBranch(const DefaultBranchNode *node) override;
75 std::any visitAssertStmt(const AssertStmtNode *node) override;
76 std::any visitAnonymousBlockStmt(const AnonymousBlockStmtNode *node) override;
77 // Statements
78 std::any visitStmtLst(const StmtLstNode *node) override;
79 std::any visitTypeAltsLst(const TypeAltsLstNode *node) override;
80 std::any visitDeclStmt(const DeclStmtNode *node) override;
81 std::any visitQualifierLst(const QualifierLstNode *node) override;
82 std::any visitModAttr(const ModAttrNode *node) override;
83 std::any visitTopLevelDefinitionAttr(const TopLevelDefinitionAttrNode *node) override;
84 std::any visitCaseConstant(const CaseConstantNode *node) override;
85 std::any visitReturnStmt(const ReturnStmtNode *node) override;
86 std::any visitBreakStmt(const BreakStmtNode *node) override;
87 std::any visitContinueStmt(const ContinueStmtNode *node) override;
88 std::any visitFallthroughStmt(const FallthroughStmtNode *node) override;
89 // Builtin functions
90 std::any visitBuiltinCall(const BuiltinCallNode *node) override;
91 std::any visitPrintfCall(const PrintfCallNode *node) override;
92 std::any visitSizeofCall(const SizeofCallNode *node) override;
93 std::any visitAlignofCall(const AlignofCallNode *node) override;
94 std::any visitTypeidCall(const TypeidCallNode *node) override;
95 std::any visitLenCall(const LenCallNode *node) override;
96 std::any visitPanicCall(const PanicCallNode *node) override;
97 std::any visitSysCall(const SysCallNode *node) override;
98 // Expressions
99 std::any visitAssignExpr(const AssignExprNode *node) override;
100 std::any visitTernaryExpr(const TernaryExprNode *node) override;
101 std::any visitLogicalOrExpr(const LogicalOrExprNode *node) override;
102 std::any visitLogicalAndExpr(const LogicalAndExprNode *node) override;
103 std::any visitBitwiseOrExpr(const BitwiseOrExprNode *node) override;
104 std::any visitBitwiseXorExpr(const BitwiseXorExprNode *node) override;
105 std::any visitBitwiseAndExpr(const BitwiseAndExprNode *node) override;
106 std::any visitEqualityExpr(const EqualityExprNode *node) override;
107 std::any visitRelationalExpr(const RelationalExprNode *node) override;
108 std::any visitShiftExpr(const ShiftExprNode *node) override;
109 std::any visitAdditiveExpr(const AdditiveExprNode *node) override;
110 std::any visitMultiplicativeExpr(const MultiplicativeExprNode *node) override;
111 std::any visitCastExpr(const CastExprNode *node) override;
112 std::any visitPrefixUnaryExpr(const PrefixUnaryExprNode *node) override;
113 std::any visitPostfixUnaryExpr(const PostfixUnaryExprNode *node) override;
114 std::any visitAtomicExpr(const AtomicExprNode *node) override;
115 // Values and types
116 std::any visitValue(const ValueNode *node) override;
117 std::any visitConstant(const ConstantNode *node) override;
118 std::any visitFctCall(const FctCallNode *node) override;
119 std::any visitArrayInitialization(const ArrayInitializationNode *node) override;
120 std::any visitStructInstantiation(const StructInstantiationNode *node) override;
121 std::any visitLambdaFunc(const LambdaFuncNode *node) override;
122 std::any visitLambdaProc(const LambdaProcNode *node) override;
123 std::any visitLambdaExpr(const LambdaExprNode *node) override;
124 std::any visitDataType(const DataTypeNode *node) override;
125
126 // Public methods
127
20/44
✓ Branch 9 → 10 taken 9 times.
✗ Branch 9 → 62 not taken.
✓ Branch 12 → 13 taken 9 times.
✗ Branch 12 → 65 not taken.
✓ Branch 14 → 15 taken 16 times.
✗ Branch 14 → 80 not taken.
✓ Branch 16 → 17 taken 9 times.
✗ Branch 16 → 88 not taken.
✓ Branch 19 → 20 taken 16 times.
✗ Branch 19 → 107 not taken.
✓ Branch 25 → 26 taken 241 times.
✗ Branch 25 → 180 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 87 not taken.
✓ Branch 35 → 36 taken 341 times.
✗ Branch 35 → 79 not taken.
✓ Branch 39 → 40 taken 341 times.
✗ Branch 39 → 88 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 94 not taken.
✓ Branch 52 → 53 taken 2 times.
✗ Branch 52 → 111 not taken.
✓ Branch 54 → 55 taken 246 times.
✗ Branch 54 → 119 not taken.
✓ Branch 72 → 73 taken 2212 times.
✗ Branch 72 → 413 not taken.
✓ Branch 76 → 77 taken 2212 times.
✗ Branch 76 → 535 not taken.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 112 not taken.
✗ Branch 86 → 87 not taken.
✗ Branch 86 → 116 not taken.
✓ Branch 90 → 91 taken 51 times.
✗ Branch 90 → 121 not taken.
✓ Branch 95 → 96 taken 51 times.
✗ Branch 95 → 125 not taken.
✓ Branch 109 → 110 taken 2 times.
✗ Branch 109 → 222 not taken.
✓ Branch 133 → 134 taken 2 times.
✗ Branch 133 → 229 not taken.
✓ Branch 370 → 371 taken 82 times.
✗ Branch 370 → 526 not taken.
✓ Branch 375 → 376 taken 82 times.
✗ Branch 375 → 533 not taken.
9645 llvm::AllocaInst *insertAlloca(llvm::Type *llvmType, std::string varName = "");
128 llvm::AllocaInst *insertAlloca(const QualType &qualType, const std::string &varName = "");
129 llvm::LoadInst *insertLoad(llvm::Type *llvmType, llvm::Value *ptr, bool isVolatile = false,
130 const std::string &varName = "") const;
131 llvm::LoadInst *insertLoad(const QualType &qualType, llvm::Value *ptr, bool isVolatile = false,
132 const std::string &varName = "");
133 llvm::StoreInst *insertStore(llvm::Value *val, llvm::Value *ptr, bool isVolatile = false) const;
134 void insertStore(llvm::Value *val, llvm::Value *ptr, const QualType &qualType, bool isVolatile = false);
135 llvm::Value *insertInBoundsGEP(llvm::Type *type, llvm::Value *basePtr, llvm::ArrayRef<llvm::Value *> indices,
136
8/19
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 88 not taken.
✓ Branch 28 → 29 taken 13 times.
✗ Branch 28 → 68 not taken.
✓ Branch 38 → 39 taken 238 times.
✗ Branch 38 → 143 not taken.
✓ Branch 43 → 44 taken 336 times.
✗ Branch 43 → 147 not taken.
✗ Branch 43 → 188 not taken.
✓ Branch 56 → 57 taken 2784 times.
✗ Branch 56 → 197 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 119 not taken.
✓ Branch 70 → 71 taken 3 times.
✗ Branch 70 → 127 not taken.
✓ Branch 166 → 167 taken 1 time.
✗ Branch 166 → 247 not taken.
✓ Branch 171 → 172 taken 1 time.
✗ Branch 171 → 251 not taken.
9417 std::string varName = "") const;
137
19/40
✓ Branch 36 → 37 taken 171 times.
✗ Branch 36 → 64 not taken.
✗ Branch 36 → 97 not taken.
✓ Branch 39 → 40 taken 77 times.
✗ Branch 39 → 150 not taken.
✓ Branch 51 → 52 taken 838 times.
✗ Branch 51 → 402 not taken.
✓ Branch 53 → 54 taken 18 times.
✗ Branch 53 → 115 not taken.
✓ Branch 55 → 56 taken 838 times.
✗ Branch 55 → 407 not taken.
✓ Branch 56 → 57 taken 667 times.
✗ Branch 56 → 124 not taken.
✓ Branch 57 → 58 taken 18 times.
✗ Branch 57 → 119 not taken.
✓ Branch 65 → 66 taken 70 times.
✗ Branch 65 → 100 not taken.
✗ Branch 65 → 125 not taken.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 136 not taken.
✓ Branch 76 → 77 taken 43 times.
✗ Branch 76 → 130 not taken.
✓ Branch 83 → 84 taken 362 times.
✗ Branch 83 → 131 not taken.
✗ Branch 83 → 136 not taken.
✓ Branch 86 → 87 taken 82 times.
✗ Branch 86 → 184 not taken.
✗ Branch 86 → 421 not taken.
✓ Branch 87 → 88 taken 135 times.
✓ Branch 87 → 90 taken 212 times.
✓ Branch 87 → 91 taken 15 times.
✓ Branch 90 → 91 taken 363 times.
✗ Branch 90 → 165 not taken.
✗ Branch 90 → 535 not taken.
✓ Branch 95 → 96 taken 16 times.
✗ Branch 95 → 427 not taken.
✓ Branch 112 → 113 taken 2561 times.
✗ Branch 112 → 180 not taken.
✓ Branch 116 → 117 taken 284 times.
✓ Branch 116 → 119 taken 2277 times.
15669 llvm::Value *insertStructGEP(llvm::Type *type, llvm::Value *basePtr, unsigned index, std::string varName = "") const;
138 llvm::Value *resolveValue(const ExprNode *node);
139 llvm::Value *resolveValue(const ExprNode *node, LLVMExprResult &exprResult);
140 llvm::Value *resolveValue(const QualType &qualType, LLVMExprResult &exprResult);
141 llvm::Value *resolveAddress(const ASTNode *node);
142 llvm::Value *resolveAddress(LLVMExprResult &exprResult);
143 [[nodiscard]] llvm::Constant *getDefaultValueForSymbolType(const QualType &symbolType);
144 [[nodiscard]] static std::string getIRString(llvm::Module *llvmModule, const CliOptions &cliOptions);
145
146 private:
147 // Private methods
148 llvm::Constant *getConst(const CompileTimeValue &compileTimeValue, const QualType &type, const ASTNode *node) const;
149 llvm::BasicBlock *createBlock(const std::string &blockName = "") const;
150 void switchToBlock(llvm::BasicBlock *block, llvm::Function *parentFct = nullptr);
151 void terminateBlock(const StmtLstNode *stmtLstNode);
152 void insertJump(llvm::BasicBlock *targetBlock);
153 void insertCondJump(llvm::Value *condition, llvm::BasicBlock *trueBlock, llvm::BasicBlock *falseBlock,
154 Likelihood likelihood = Likelihood::UNSPECIFIED);
155 void verifyFunction(const llvm::Function *fct, const CodeLoc &codeLoc) const;
156 void verifyModule(const CodeLoc &codeLoc) const;
157 LLVMExprResult doAssignment(const ASTNode *lhsNode, const ExprNode *rhsNode, const ASTNode *node);
158 LLVMExprResult doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, const ExprNode *rhsNode, const ASTNode *node,
159 bool isDecl = false);
160 LLVMExprResult doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, LLVMExprResult &rhs, const QualType &rhsSType,
161 const ASTNode *node, bool isDecl);
162 void generateShallowCopy(llvm::Value *oldAddress, llvm::Type *varType, llvm::Value *targetAddress, bool isVolatile) const;
163 void autoDeReferencePtr(llvm::Value *&ptr, QualType &symbolType);
164 llvm::GlobalVariable *createGlobalConst(const std::string &baseName, llvm::Constant *constant) const;
165 llvm::GlobalVariable *createGlobalStringConst(const std::string &baseName, const std::string &value) const;
166 llvm::GlobalVariable *createGlobalStringConst(const std::string &baseName, const std::string &value,
167 const CodeLoc &codeLoc) const;
168 [[nodiscard]] std::string getUnusedGlobalName(const std::string &baseName) const;
169 static void materializeConstant(LLVMExprResult &exprResult);
170 const std::vector<const Function *> &getOpFctPointers(const ASTNode *node) const;
171 llvm::Value *buildFatFctPtr(Scope *bodyScope, llvm::Type *capturesStructType, llvm::Value *lambda);
172 llvm::Type *buildCapturesContainerType(const CaptureMap &captures) const;
173 void unpackCapturesToLocalVariables(const CaptureMap &captures, llvm::Value *val, llvm::Type *structType);
174
175 // Generate implicit
176 llvm::Value *doImplicitCast(llvm::Value *src, QualType dstSTy, QualType srcSTy);
177 void generateScopeCleanup(const StmtLstNode *node) const;
178 void generateFctDecl(const Function *fct, const std::vector<llvm::Value *> &args) const;
179 llvm::CallInst *generateFctCall(const Function *fct, const std::vector<llvm::Value *> &args) const;
180 llvm::Value *generateFctDeclAndCall(const Function *fct, const std::vector<llvm::Value *> &args) const;
181 void generateProcDeclAndCall(const Function *proc, const std::vector<llvm::Value *> &args) const;
182 void generateCtorOrDtorCall(const SymbolTableEntry *entry, const Function *ctorOrDtor,
183 const std::vector<llvm::Value *> &args) const;
184 void generateCtorOrDtorCall(llvm::Value *structAddr, const Function *ctorOrDtor, const std::vector<llvm::Value *> &args) const;
185 void generateDeallocCall(llvm::Value *variableAddress) const;
186 llvm::Function *generateImplicitFunction(const std::function<void(void)> &generateBody, const Function *spiceFunc);
187 llvm::Function *generateImplicitProcedure(const std::function<void(void)> &generateBody, const Function *spiceProc);
188 void generateCtorBodyPreamble(Scope *bodyScope);
189 void generateDefaultCtor(const Function *ctorFunction);
190 void generateCopyCtorBodyPreamble(const Function *copyCtorFunction);
191 void generateDefaultCopyCtor(const Function *copyCtorFunction);
192 void generateDtorBodyPreamble(const Function *dtorFunction) const;
193 void generateDefaultDtor(const Function *dtorFunction);
194 void generateTestMain();
195
196 // Generate target dependent
197 std::string getSysCallAsmString(uint8_t numRegs) const;
198 std::string getSysCallConstraintString(uint8_t numRegs) const;
199
200 // Generate VTable
201 llvm::Constant *generateTypeInfoName(StructBase *spiceStruct) const;
202 llvm::Constant *generateTypeInfo(StructBase *spiceStruct) const;
203 llvm::Constant *generateVTable(StructBase *spiceStruct) const;
204 void generateVTableInitializer(const StructBase *spiceStruct) const;
205
206 // Generate code instrumentation
207 void enableFunctionInstrumentation(llvm::Function *function) const;
208
209 // Private members
210 llvm::LLVMContext &context;
211 llvm::IRBuilder<> &builder;
212 llvm::Module *module;
213 OpRuleConversionManager conversionManager;
214 const StdFunctionManager stdFunctionManager;
215 DebugInfoGenerator diGenerator = DebugInfoGenerator(this);
216 MetadataGenerator mdGenerator = MetadataGenerator(this);
217 struct CommonLLVMTypes {
218 llvm::StructType *fatPtrType = nullptr;
219 } llvmTypes;
220 std::vector<llvm::BasicBlock *> breakBlocks;
221 std::vector<llvm::BasicBlock *> continueBlocks;
222 std::stack<llvm::BasicBlock *> fallthroughBlocks;
223 llvm::BasicBlock *allocaInsertBlock = nullptr;
224 llvm::AllocaInst *allocaInsertInst = nullptr;
225 bool blockAlreadyTerminated = false;
226 bool isInCtorBody = false;
227 std::vector<DeferredLogic> deferredVTableInitializations;
228 };
229
230 } // namespace spice::compiler
231