GCC Code Coverage Report


Directory: ../
File: src/irgenerator/IRGenerator.h
Date: 2025-02-05 01:09:36
Exec Total Coverage
Lines: 3 3 100.0%
Functions: 0 0 -%
Branches: 34 70 48.6%

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