GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 7 / 0 / 7
Functions: -% 0 / 0 / 0
Branches: 43.2% 102 / 0 / 236

src/irgenerator/IRGenerator.h
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <stack>
6 #include <unordered_map>
7
8 #include <CompilerPass.h>
9 #include <ast/ASTNodes.h>
10 #include <ast/ParallelizableASTVisitor.h>
11 #include <irgenerator/DebugInfoGenerator.h>
12 #include <irgenerator/MetadataGenerator.h>
13 #include <irgenerator/OpRuleConversionManager.h>
14 #include <irgenerator/StdFunctionManager.h>
15 #include <model/StructBase.h>
16 #include <symboltablebuilder/Scope.h>
17 #include <util/DeferredLogic.h>
18
19 namespace spice::compiler {
20
21 // Forward declarations
22 class ExprNode;
23 class Function;
24
25 const char *const ANON_GLOBAL_STRING_NAME = "anon.string.";
26 const char *const ANON_GLOBAL_ARRAY_NAME = "anon.array.";
27 const char *const CAPTURES_PARAM_NAME = "captures";
28 extern const std::string PRODUCER_STRING;
29
30 enum class Likelihood : uint8_t {
31 UNSPECIFIED,
32 LIKELY,
33 UNLIKELY,
34 };
35
36 struct CommonLLVMTypes {
37 llvm::StructType *lambdaFatPtrType = nullptr;
38 };
39
40 // A break/continue target: the scope to run cleanup (dtor calls) up to (inclusive) before jumping, since the
41 // jump skips the normal fall-through cleanup of enclosing scopes, paired with the block to jump to.
42 struct BreakContinueTarget {
43 Scope *scope;
44 llvm::BasicBlock *block;
45 };
46
47 // Forward declarations
48 class SourceFile;
49
50 class IRGenerator final : CompilerPass, public ParallelizableASTVisitor {
51 public:
52 // Type definitions
53 using ParamInfoList = std::vector<std::pair<std::string, const SymbolTableEntry *>>;
54
55 // Constructors
56 IRGenerator(GlobalResourceManager &resourceManager, SourceFile *sourceFile);
57
58 // Friend classes
59 friend class StdFunctionManager;
60 friend class OpRuleConversionManager;
61 friend class DebugInfoGenerator;
62 friend class MetadataGenerator;
63 friend class ScopeHandle;
64
65 // Visitor methods
66 // Top level definitions
67 std::any visitEntry(const EntryNode *node) override;
68 std::any visitMainFctDef(const MainFctDefNode *node) override;
69 std::any visitFctDef(const FctDefNode *node) override;
70 std::any visitProcDef(const ProcDefNode *node) override;
71 std::any visitStructDef(const StructDefNode *node) override;
72 std::any visitInterfaceDef(const InterfaceDefNode *node) override;
73 std::any visitUnionDef(const UnionDefNode *node) override;
74 std::any visitEnumDef(const EnumDefNode *node) override;
75 std::any visitGenericTypeDef(const GenericTypeDefNode *node) override;
76 std::any visitAliasDef(const AliasDefNode *node) override;
77 std::any visitGlobalVarDef(const GlobalVarDefNode *node) override;
78 std::any visitExtDecl(const ExtDeclNode *node) override;
79 // Control structures
80 std::any visitUnsafeBlockDef(const UnsafeBlockNode *node) override;
81 std::any visitForLoop(const ForLoopNode *node) override;
82 std::any visitForeachLoop(const ForeachLoopNode *node) override;
83 std::any visitWhileLoop(const WhileLoopNode *node) override;
84 std::any visitDoWhileLoop(const DoWhileLoopNode *node) override;
85 std::any visitIfStmt(const IfStmtNode *node) override;
86 std::any visitElseStmt(const ElseStmtNode *node) override;
87 std::any visitSwitchStmt(const SwitchStmtNode *node) override;
88 std::any visitCaseBranch(const CaseBranchNode *node) override;
89 std::any visitDefaultBranch(const DefaultBranchNode *node) override;
90 std::any visitAssertStmt(const AssertStmtNode *node) override;
91 std::any visitAnonymousBlockStmt(const AnonymousBlockStmtNode *node) override;
92 // Statements
93 std::any visitStmtLst(const StmtLstNode *node) override;
94 std::any visitTypeAltsLst(const TypeAltsLstNode *node) override;
95 std::any visitDeclStmt(const DeclStmtNode *node) override;
96 std::any visitQualifierLst(const QualifierLstNode *node) override;
97 std::any visitModAttr(const ModAttrNode *node) override;
98 std::any visitTopLevelDefinitionAttr(const TopLevelDefAttrNode *node) override;
99 std::any visitCaseConstant(const CaseConstantNode *node) override;
100 std::any visitReturnStmt(const ReturnStmtNode *node) override;
101 std::any visitBreakStmt(const BreakStmtNode *node) override;
102 std::any visitContinueStmt(const ContinueStmtNode *node) override;
103 std::any visitFallthroughStmt(const FallthroughStmtNode *node) override;
104 // Expressions
105 std::any visitAssignExpr(const AssignExprNode *node) override;
106 std::any visitTernaryExpr(const TernaryExprNode *node) override;
107 std::any visitLogicalOrExpr(const LogicalOrExprNode *node) override;
108 std::any visitLogicalAndExpr(const LogicalAndExprNode *node) override;
109 std::any visitBitwiseOrExpr(const BitwiseOrExprNode *node) override;
110 std::any visitBitwiseXorExpr(const BitwiseXorExprNode *node) override;
111 std::any visitBitwiseAndExpr(const BitwiseAndExprNode *node) override;
112 std::any visitEqualityExpr(const EqualityExprNode *node) override;
113 std::any visitRelationalExpr(const RelationalExprNode *node) override;
114 std::any visitShiftExpr(const ShiftExprNode *node) override;
115 std::any visitAdditiveExpr(const AdditiveExprNode *node) override;
116 std::any visitMultiplicativeExpr(const MultiplicativeExprNode *node) override;
117 std::any visitCastExpr(const CastExprNode *node) override;
118 std::any visitPrefixUnaryExpr(const PrefixUnaryExprNode *node) override;
119 std::any visitPostfixUnaryExpr(const PostfixUnaryExprNode *node) override;
120 std::any visitAtomicExpr(const AtomicExprNode *node) override;
121 // Values and types
122 std::any visitValue(const ValueNode *node) override;
123 std::any visitConstant(const ConstantNode *node) override;
124 std::any visitFctCall(const FctCallNode *node) override;
125 std::any visitArrayInitialization(const ArrayInitializationNode *node) override;
126 std::any visitStructInstantiation(const StructInstantiationNode *node) override;
127 std::any visitLambdaFunc(const LambdaFuncNode *node) override;
128 std::any visitLambdaProc(const LambdaProcNode *node) override;
129 std::any visitLambdaExpr(const LambdaExprNode *node) override;
130 std::any visitDataType(const DataTypeNode *node) override;
131
132 // Public methods
133
20/44
✓ Branch 8 → 9 taken 336 times.
✗ Branch 8 → 61 not taken.
✓ Branch 11 → 12 taken 490 times.
✗ Branch 11 → 67 not taken.
✓ Branch 14 → 15 taken 2049 times.
✗ Branch 14 → 90 not taken.
✓ Branch 15 → 16 taken 490 times.
✗ Branch 15 → 90 not taken.
✓ Branch 19 → 20 taken 2049 times.
✗ Branch 19 → 117 not taken.
✓ Branch 21 → 22 taken 6225 times.
✗ Branch 21 → 267 not taken.
✓ Branch 28 → 29 taken 2 times.
✗ Branch 28 → 97 not taken.
✓ Branch 35 → 36 taken 4238 times.
✗ Branch 35 → 81 not taken.
✓ Branch 39 → 40 taken 4238 times.
✗ Branch 39 → 90 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 104 not taken.
✓ Branch 68 → 69 taken 4 times.
✗ Branch 68 → 127 not taken.
✓ Branch 79 → 80 taken 3319 times.
✗ Branch 79 → 168 not taken.
✗ Branch 98 → 99 not taken.
✗ Branch 98 → 129 not taken.
✗ Branch 103 → 104 not taken.
✗ Branch 103 → 133 not taken.
✓ Branch 107 → 108 taken 744 times.
✗ Branch 107 → 138 not taken.
✓ Branch 112 → 113 taken 744 times.
✗ Branch 112 → 142 not taken.
✓ Branch 118 → 119 taken 20131 times.
✗ Branch 118 → 491 not taken.
✓ Branch 122 → 123 taken 20131 times.
✗ Branch 122 → 630 not taken.
✓ Branch 216 → 217 taken 4 times.
✗ Branch 216 → 460 not taken.
✓ Branch 240 → 241 taken 4 times.
✗ Branch 240 → 467 not taken.
✓ Branch 430 → 431 taken 1618 times.
✗ Branch 430 → 621 not taken.
✓ Branch 435 → 436 taken 1618 times.
✗ Branch 435 → 628 not taken.
117498 llvm::AllocaInst *insertAlloca(llvm::Type *llvmType, const std::string &varName = "");
134
6/18
✓ Branch 46 → 47 taken 8 times.
✗ Branch 46 → 157 not taken.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 82 not taken.
✓ Branch 74 → 75 taken 42 times.
✗ Branch 74 → 170 not taken.
✓ Branch 76 → 77 taken 12 times.
✗ Branch 76 → 279 not taken.
✓ Branch 80 → 81 taken 12 times.
✗ Branch 80 → 283 not taken.
✓ Branch 91 → 92 taken 49310 times.
✗ Branch 91 → 286 not taken.
✓ Branch 106 → 107 taken 12 times.
✗ Branch 106 → 184 not taken.
✗ Branch 132 → 133 not taken.
✗ Branch 132 → 198 not taken.
✗ Branch 137 → 138 not taken.
✗ Branch 137 → 202 not taken.
148160 llvm::AllocaInst *insertAlloca(const QualType &qualType, const std::string &varName = "");
135 llvm::LoadInst *insertLoad(llvm::Type *llvmType, llvm::Value *ptr, bool isVolatile = false,
136
28/60
✓ Branch 12 → 13 taken 40718 times.
✗ Branch 12 → 37 not taken.
✓ Branch 18 → 19 taken 4581 times.
✗ Branch 18 → 36 not taken.
✗ Branch 18 → 102 not taken.
✓ Branch 20 → 21 taken 336 times.
✗ Branch 20 → 74 not taken.
✓ Branch 24 → 25 taken 40 times.
✗ Branch 24 → 54 not taken.
✓ Branch 28 → 29 taken 5318 times.
✗ Branch 28 → 58 not taken.
✗ Branch 28 → 139 not taken.
✓ Branch 30 → 31 taken 17667 times.
✗ Branch 30 → 46 not taken.
✓ Branch 33 → 34 taken 2936 times.
✗ Branch 33 → 150 not taken.
✓ Branch 45 → 46 taken 14 times.
✗ Branch 45 → 86 not taken.
✓ Branch 46 → 47 taken 5111 times.
✗ Branch 46 → 117 not taken.
✓ Branch 49 → 50 taken 72 times.
✗ Branch 49 → 115 not taken.
✓ Branch 50 → 51 taken 5111 times.
✗ Branch 50 → 137 not taken.
✓ Branch 51 → 52 taken 731 times.
✗ Branch 51 → 273 not taken.
✓ Branch 53 → 54 taken 176 times.
✗ Branch 53 → 116 not taken.
✓ Branch 56 → 57 taken 320 times.
✗ Branch 56 → 93 not taken.
✓ Branch 77 → 78 taken 310 times.
✗ Branch 77 → 177 not taken.
✓ Branch 83 → 84 taken 8 times.
✗ Branch 83 → 161 not taken.
✓ Branch 85 → 86 taken 796 times.
✗ Branch 85 → 162 not taken.
✓ Branch 92 → 93 taken 30 times.
✗ Branch 92 → 388 not taken.
✓ Branch 97 → 98 taken 30 times.
✗ Branch 97 → 392 not taken.
✓ Branch 98 → 99 taken 6 times.
✗ Branch 98 → 190 not taken.
✓ Branch 102 → 103 taken 6 times.
✗ Branch 102 → 173 not taken.
✓ Branch 107 → 108 taken 6940 times.
✗ Branch 107 → 177 not taken.
✓ Branch 123 → 124 taken 66 times.
✗ Branch 123 → 193 not taken.
✓ Branch 130 → 131 taken 10 times.
✗ Branch 130 → 195 not taken.
✗ Branch 145 → 146 not taken.
✗ Branch 145 → 231 not taken.
✓ Branch 147 → 148 taken 72 times.
✗ Branch 147 → 196 not taken.
✓ Branch 174 → 175 taken 32 times.
✗ Branch 174 → 512 not taken.
✓ Branch 178 → 179 taken 32 times.
✗ Branch 178 → 516 not taken.
✓ Branch 197 → 198 taken 2216 times.
✗ Branch 197 → 302 not taken.
256728 const std::string &varName = "") const;
137 llvm::LoadInst *insertLoad(const QualType &qualType, llvm::Value *ptr, bool isVolatile = false,
138
3/14
✓ Branch 5 → 6 taken 168180 times.
✗ Branch 5 → 21 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 59 not taken.
✓ Branch 9 → 10 taken 168180 times.
✗ Branch 9 → 25 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 63 not taken.
✓ Branch 27 → 28 taken 349169 times.
✗ Branch 27 → 42 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 75 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 79 not taken.
1552047 const std::string &varName = "");
139 llvm::StoreInst *insertStore(llvm::Value *val, llvm::Value *ptr, bool isVolatile = false) const;
140 void insertStore(llvm::Value *val, llvm::Value *ptr, const QualType &qualType, bool isVolatile = false);
141 llvm::Value *insertInBoundsGEP(llvm::Type *type, llvm::Value *basePtr, llvm::ArrayRef<llvm::Value *> indices,
142
9/21
✓ Branch 28 → 29 taken 482 times.
✗ Branch 28 → 68 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 101 not taken.
✓ Branch 38 → 39 taken 2936 times.
✗ Branch 38 → 146 not taken.
✓ Branch 43 → 44 taken 5299 times.
✗ Branch 43 → 150 not taken.
✗ Branch 43 → 365 not taken.
✓ Branch 54 → 55 taken 15555 times.
✗ Branch 54 → 374 not taken.
✓ Branch 74 → 75 taken 4 times.
✗ Branch 74 → 135 not taken.
✓ Branch 86 → 87 taken 6 times.
✗ Branch 86 → 143 not taken.
✓ Branch 93 → 94 taken 156 times.
✗ Branch 93 → 475 not taken.
✓ Branch 117 → 118 taken 6 times.
✗ Branch 117 → 293 not taken.
✓ Branch 122 → 123 taken 6 times.
✗ Branch 122 → 297 not taken.
64524 const std::string &varName = "") const;
143
26/53
✓ Branch 36 → 37 taken 2382 times.
✗ Branch 36 → 64 not taken.
✓ Branch 38 → 39 taken 1444 times.
✗ Branch 38 → 126 not taken.
✗ Branch 38 → 149 not taken.
✓ Branch 40 → 41 taken 5111 times.
✗ Branch 40 → 111 not taken.
✓ Branch 47 → 48 taken 176 times.
✗ Branch 47 → 110 not taken.
✓ Branch 52 → 53 taken 14 times.
✗ Branch 52 → 91 not taken.
✓ Branch 56 → 57 taken 90 times.
✗ Branch 56 → 121 not taken.
✓ Branch 60 → 61 taken 90 times.
✗ Branch 60 → 125 not taken.
✓ Branch 64 → 65 taken 14602 times.
✗ Branch 64 → 99 not taken.
✗ Branch 64 → 462 not taken.
✓ Branch 73 → 74 taken 279 times.
✗ Branch 73 → 134 not taken.
✓ Branch 76 → 77 taken 1646 times.
✗ Branch 76 → 97 not taken.
✓ Branch 80 → 81 taken 1925 times.
✗ Branch 80 → 101 not taken.
✗ Branch 80 → 140 not taken.
✓ Branch 84 → 85 taken 203 times.
✓ Branch 84 → 88 taken 76 times.
✓ Branch 85 → 86 taken 618 times.
✗ Branch 85 → 183 not taken.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 174 not taken.
✓ Branch 91 → 92 taken 10 times.
✗ Branch 91 → 167 not taken.
✓ Branch 92 → 93 taken 279 times.
✗ Branch 92 → 146 not taken.
✓ Branch 93 → 94 taken 3990 times.
✗ Branch 93 → 168 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 204 not taken.
✓ Branch 115 → 116 taken 22282 times.
✗ Branch 115 → 183 not taken.
✓ Branch 119 → 120 taken 12428 times.
✓ Branch 119 → 122 taken 9854 times.
✓ Branch 132 → 133 taken 6362 times.
✗ Branch 132 → 199 not taken.
✓ Branch 136 → 137 taken 4380 times.
✓ Branch 136 → 139 taken 1982 times.
✓ Branch 140 → 141 taken 72 times.
✗ Branch 140 → 190 not taken.
✓ Branch 227 → 228 taken 229 times.
✗ Branch 227 → 529 not taken.
✓ Branch 233 → 234 taken 229 times.
✗ Branch 233 → 535 not taken.
180282 llvm::Value *insertStructGEP(llvm::Type *type, llvm::Value *basePtr, unsigned index, const std::string &varName = "") const;
144 llvm::Value *resolveValue(const ExprNode *node);
145 llvm::Value *resolveValue(const ExprNode *node, LLVMExprResult &exprResult);
146 llvm::Value *resolveValue(const QualType &qualType, LLVMExprResult &exprResult);
147 llvm::Value *resolveAddress(const ASTNode *node);
148 llvm::Value *resolveAddress(LLVMExprResult &exprResult);
149 [[nodiscard]] llvm::Constant *getDefaultValueForSymbolType(const QualType &symbolType);
150 [[nodiscard]] static std::string getIRString(llvm::Module *llvmModule, const CliOptions &cliOptions);
151 // Address management for symbol table entries
152 [[nodiscard]] llvm::Value *getAddress(const SymbolTableEntry *entry);
153 void updateAddress(const SymbolTableEntry *entry, llvm::Value *address);
154 void pushAddress(const SymbolTableEntry *entry, llvm::Value *address);
155 void popAddress(const SymbolTableEntry *entry);
156 // LLVM function management for Spice functions
157 [[nodiscard]] llvm::Function *getLLVMFunction(const Function *spiceFunc);
158 void setLLVMFunction(const Function *spiceFunc, llvm::Function *llvmFunction);
159
160 // Builtin function handlers
161 std::any visitBuiltinCall(const FctCallNode *node);
162 std::any visitBuiltinPrintfCall(const FctCallNode *node);
163 std::any visitBuiltinLenCall(const FctCallNode *node);
164 std::any visitBuiltinPanicCall(const FctCallNode *node);
165 std::any visitBuiltinSyscallCall(const FctCallNode *node);
166 std::any visitBuiltinNewCall(const FctCallNode *node);
167 std::any visitBuiltinPlacementNewCall(const FctCallNode *node);
168 std::any visitBuiltinErrTraceBufferCall(const FctCallNode *node);
169 std::any visitBuiltinStdErrCall(const FctCallNode *node);
170 std::any visitBuiltinFrameAddressCall(const FctCallNode *node);
171
172 private:
173 // Private methods
174 [[nodiscard]] llvm::Value *getStdErrValue() const;
175 llvm::Constant *getConst(const CompileTimeValue &compileTimeValue, const QualType &type, const ASTNode *node) const;
176 llvm::Constant *packConstantAsByteArray(llvm::Constant *value, llvm::ArrayType *byteArrayType) const;
177
10/26
✓ Branch 63 → 64 taken 187 times.
✗ Branch 63 → 150 not taken.
✗ Branch 63 → 157 not taken.
✗ Branch 63 → 194 not taken.
✓ Branch 64 → 65 taken 943 times.
✗ Branch 64 → 161 not taken.
✓ Branch 67 → 68 taken 187 times.
✗ Branch 67 → 168 not taken.
✗ Branch 67 → 176 not taken.
✗ Branch 67 → 237 not taken.
✓ Branch 68 → 69 taken 943 times.
✗ Branch 68 → 200 not taken.
✓ Branch 85 → 86 taken 1920 times.
✗ Branch 85 → 139 not taken.
✗ Branch 85 → 141 not taken.
✓ Branch 89 → 90 taken 1920 times.
✗ Branch 89 → 155 not taken.
✗ Branch 89 → 157 not taken.
✓ Branch 100 → 101 taken 32356 times.
✗ Branch 100 → 197 not taken.
✓ Branch 104 → 105 taken 32356 times.
✗ Branch 104 → 214 not taken.
✓ Branch 120 → 121 taken 53068 times.
✗ Branch 120 → 265 not taken.
✓ Branch 124 → 125 taken 53068 times.
✗ Branch 124 → 306 not taken.
265422 llvm::BasicBlock *createBlock(const std::string &blockName = "") const;
178 void switchToBlock(llvm::BasicBlock *block, llvm::Function *parentFct = nullptr);
179 void terminateBlock(const StmtLstNode *stmtLstNode);
180 void insertJump(llvm::BasicBlock *targetBlock);
181 void insertCondJump(llvm::Value *condition, llvm::BasicBlock *trueBlock, llvm::BasicBlock *falseBlock,
182 Likelihood likelihood = Likelihood::UNSPECIFIED);
183 void verifyFunction(const llvm::Function *fct, const CodeLoc &codeLoc) const;
184 void verifyModule(const CodeLoc &codeLoc) const;
185 LLVMExprResult doAssignment(const ASTNode *lhsNode, const ExprNode *rhsNode, const ASTNode *node);
186 LLVMExprResult doAssignment(llvm::Value *lhsAddress, const SymbolTableEntry *lhsEntry, const ExprNode *rhsNode,
187 const ASTNode *node, bool isDecl = false);
188 LLVMExprResult doAssignment(llvm::Value *lhsAddress, const SymbolTableEntry *lhsEntry, LLVMExprResult &rhs,
189 const QualType &rhsSType, const ASTNode *node, bool isDecl);
190 void generateShallowCopy(llvm::Value *oldAddress, llvm::Type *varType, llvm::Value *targetAddress, bool isVolatile) const;
191 void autoDeReferencePtr(llvm::Value *&ptr, QualType &symbolType);
192 llvm::GlobalVariable *createGlobalConst(const std::string &baseName, llvm::Constant *constant) const;
193 llvm::GlobalVariable *createGlobalStringConst(const std::string &baseName, const std::string &value) const;
194 llvm::GlobalVariable *createGlobalStringConst(const std::string &baseName, const std::string &value,
195 const CodeLoc &codeLoc) const;
196 [[nodiscard]] std::string getUnusedGlobalName(const std::string &baseName) const;
197 static void materializeConstant(LLVMExprResult &exprResult);
198 const std::vector<const Function *> &getOpFctPointers(const ASTNode *node) const;
199 llvm::Value *buildFatFctPtr(Scope *bodyScope, llvm::Type *capturesStructType, llvm::Value *lambda);
200 llvm::Function *getOrCreateFatFctPtrThunk(llvm::Function *target);
201 llvm::Type *buildCapturesContainerType(const CaptureMap &captures) const;
202 void unpackCapturesToLocalVariables(const CaptureMap &captures, llvm::Value *val, llvm::Type *structType);
203 bool bindDecayedArrayParam(llvm::Argument &arg, const std::string &paramName, const SymbolTableEntry *paramSymbol);
204 llvm::Value *materializeDecayedArrayArg(llvm::Value *argValue, const QualType &paramType);
205 void setParamAttrs(llvm::Function *function, const ParamInfoList &paramInfo) const;
206 void setFunctionReturnValAttrs(llvm::Function *function, const QualType &returnType) const;
207 void setCallArgAttrs(llvm::CallInst *callInst, const Function *spiceFunc, const QualTypeList &paramSTypes) const;
208 void setCallReturnValAttrs(llvm::CallInst *callInst, const QualType &returnType) const;
209 llvm::Attribute::AttrKind getExtAttrKindForType(const QualType &type) const;
210 bool isSymbolDSOLocal(bool isPublic) const;
211 llvm::GlobalValue::LinkageTypes getSymbolLinkageType(bool isPublic) const;
212 llvm::GlobalValue::LinkageTypes getVTableLinkageType(bool isPublic) const;
213 void attachComdatToSymbol(llvm::GlobalVariable *global, const std::string &comdatName, bool isPublic) const;
214 void addCommonFctAttrs(llvm::Function *fct, bool isAlwaysInline = false) const;
215
216 // Generate implicit
217 llvm::Value *doImplicitCast(llvm::Value *src, QualType dstSTy, QualType srcSTy);
218 llvm::Value *getUpcastedStructPtr(llvm::Value *structPtr, const QualType &dstType, const QualType &srcType) const;
219 void generateScopeCleanup(const StmtLstNode *node);
220 void generateScopeCleanupUpTo(const ASTNode *node, const Scope *targetScope);
221 void generateFctDecl(const Function *fct, const std::vector<llvm::Value *> &args) const;
222 llvm::CallInst *generateFctCall(const Function *fct, const std::vector<llvm::Value *> &args) const;
223 llvm::Value *generateFctDeclAndCall(const Function *fct, const std::vector<llvm::Value *> &args) const;
224 void generateProcDeclAndCall(const Function *proc, const std::vector<llvm::Value *> &args) const;
225 void generateCtorOrDtorCall(const SymbolTableEntry *entry, const Function *ctorOrDtor,
226 const std::vector<llvm::Value *> &args);
227 void generateCtorOrDtorCall(llvm::Value *structAddr, const Function *ctorOrDtor, const std::vector<llvm::Value *> &args) const;
228 void generateDeallocCall(llvm::Value *variableAddress) const;
229 llvm::Function *generateImplicitFunction(const std::function<void(void)> &generateBody, const Function *spiceFunc);
230 llvm::Function *generateImplicitProcedure(const std::function<void(void)> &generateBody, const Function *spiceProc);
231 void generateCtorBodyPreamble(Scope *bodyScope);
232 void generateDefaultCtor(const Function *ctorFunction);
233 void generateCopyCtorBodyPreamble(const Function *copyCtorFunction);
234 void generateDefaultCopyCtor(const Function *copyCtorFunction);
235 void generateMoveCtorBodyPreamble(const Function *moveCtorFunction);
236 void generateDefaultMoveCtor(const Function *moveCtorFunction);
237 void generateDtorBodyPreamble(const Function *dtorFunction);
238 void generateDefaultDtor(const Function *dtorFunction);
239 void generateTestMain();
240
241 // Generate target dependent
242 std::string getSysCallAsmString(uint8_t numRegs) const;
243 std::string getSysCallConstraintString(uint8_t numRegs) const;
244
245 // Generate VTable
246 llvm::Constant *generateTypeInfoName(StructBase *spiceStruct) const;
247 llvm::Constant *generateTypeInfo(StructBase *spiceStruct) const;
248 llvm::Constant *generateVTable(StructBase *spiceStruct) const;
249 void generateVTableInitializer(const StructBase *spiceStruct);
250
251 // Generate code instrumentation
252 void enableFunctionInstrumentation(llvm::Function *function) const;
253
254 // Private members
255 llvm::LLVMContext &context;
256 llvm::IRBuilder<> &builder;
257 llvm::Module *module;
258 OpRuleConversionManager conversionManager;
259 const StdFunctionManager stdFunctionManager;
260 DebugInfoGenerator diGenerator = DebugInfoGenerator(this);
261 MetadataGenerator mdGenerator = MetadataGenerator(this);
262 CommonLLVMTypes llvmTypes;
263 std::vector<BreakContinueTarget> breakTargets;
264 std::vector<BreakContinueTarget> continueTargets;
265 std::stack<llvm::BasicBlock *> fallthroughBlocks;
266 llvm::BasicBlock *allocaInsertBlock = nullptr;
267 llvm::AllocaInst *allocaInsertInst = nullptr;
268 bool blockAlreadyTerminated = false;
269 bool isInCtorBody = false;
270 std::vector<DeferredLogic> deferredVTableInitializations;
271 // IR-side state: separate from semantic objects to keep the type-checker model clean
272 std::unordered_map<const SymbolTableEntry *, std::stack<llvm::Value *>> addressMap;
273 std::unordered_map<const Function *, llvm::Function *> llvmFunctions;
274 };
275
276 } // namespace spice::compiler
277