GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenTopLevelDefinitions.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 353 362 97.5%
Functions: 14 14 100.0%
Branches: 472 836 56.5%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4
5 #include <llvm/IR/Module.h>
6
7 #include <SourceFile.h>
8 #include <ast/ASTNodes.h>
9 #include <ast/Attributes.h>
10 #include <driver/Driver.h>
11 #include <irgenerator/NameMangling.h>
12 #include <symboltablebuilder/SymbolTableBuilder.h>
13
14 namespace spice::compiler {
15
16 213 std::any IRGenerator::visitMainFctDef(const MainFctDefNode *node) {
17 // Ignore main function definitions if this is not the main source file
18
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 213 times.
213 if (!sourceFile->isMainFile)
19 return nullptr;
20
21 // Do not generate main function if it is explicitly specified
22
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 212 times.
213 if (cliOptions.noEntryFct)
23
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return nullptr;
24
25 // Change scope to function scope
26 212 currentScope = node->bodyScope;
27
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 assert(currentScope != nullptr);
28
29 // Visit parameters
30 212 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
31 212 QualTypeList paramSymbolTypes;
32 212 std::vector<llvm::Type *> paramTypes;
33
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 208 times.
212 if (node->takesArgs) {
34
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 const size_t numOfParams = node->paramLst()->params().size();
35
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 paramInfoList.reserve(numOfParams);
36
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 paramSymbolTypes.reserve(numOfParams);
37
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 paramTypes.reserve(numOfParams);
38
4/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 4 times.
12 for (DeclStmtNode *param : node->paramLst()->params()) {
39 // Get symbol table entry of param
40
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 SymbolTableEntry *paramSymbol = node->bodyScope->lookupStrict(param->varName);
41
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(paramSymbol != nullptr);
42 // Retrieve type of param
43
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
8 auto paramType = any_cast<llvm::Type *>(visit(param->dataType()));
44 // Add it to the lists
45
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 paramInfoList.emplace_back(param->varName, paramSymbol);
46
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 paramSymbolTypes.push_back(paramSymbol->getQualType());
47
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 paramTypes.push_back(paramType);
48 4 }
49 }
50
51 // Build the function
52
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 llvm::Type *returnType = builder.getInt32Ty();
53
1/2
✓ Branch 2 taken 212 times.
✗ Branch 3 not taken.
212 llvm::FunctionType *fctType = llvm::FunctionType::get(returnType, paramTypes, false);
54
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 llvm::Function *fct = llvm::Function::Create(fctType, llvm::Function::ExternalLinkage, MAIN_FUNCTION_NAME, module);
55 212 fct->setDSOLocal(true);
56
57 // Add function attributes
58
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 fct->addFnAttr(llvm::Attribute::NoInline);
59
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 fct->addFnAttr(llvm::Attribute::NoUnwind);
60
1/2
✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
212 if (cliOptions.optLevel == OptLevel::O0)
61
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 fct->addFnAttr(llvm::Attribute::OptimizeNone);
62 else if (cliOptions.optLevel >= OptLevel::Os)
63 fct->addFnAttr(llvm::Attribute::OptimizeForSize);
64
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 fct->addFnAttr(llvm::Attribute::getWithUWTableKind(context, llvm::UWTableKind::Default));
65
66 // Add debug info
67
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 210 times.
212 if (cliOptions.generateDebugInfo) {
68 2 const auto nonConstNode = const_cast<MainFctDefNode *>(node);
69
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const Function spiceFunc = FunctionManager::createMainFunction(node->entry, paramSymbolTypes, nonConstNode);
70
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 diGenerator.generateFunctionDebugInfo(fct, &spiceFunc);
71
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 diGenerator.setSourceLocation(node);
72 2 }
73
74 // Create entry block
75
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 llvm::BasicBlock *bEntry = createBlock();
76
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 switchToBlock(bEntry, fct);
77
78 // Reset alloca insert markers to this block
79 212 allocaInsertBlock = bEntry;
80 212 allocaInsertInst = nullptr;
81
82 // Allocate result variable
83
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 llvm::Value *resultAddress = insertAlloca(returnType, RETURN_VARIABLE_NAME);
84 // Update the symbol table entry
85
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
636 SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 assert(resultEntry != nullptr);
87
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 resultEntry->updateAddress(resultAddress);
88 // Generate debug info
89
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
424 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddress);
90 // Store the default result value
91
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 insertStore(builder.getInt32(0), resultAddress);
92
93 // Store function argument values
94
3/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 212 times.
220 for (auto &arg : fct->args()) {
95 // Get information about the parameter
96 8 const size_t argNumber = arg.getArgNo();
97
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(paramSymbol != nullptr);
99 // Allocate space for it
100
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 llvm::Type *paramType = fctType->getParamType(argNumber);
101
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 llvm::Value *paramAddress = insertAlloca(paramType, paramName);
102 // Update the symbol table entry
103
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 paramSymbol->updateAddress(paramAddress);
104 // Store the value at the new address
105
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 insertStore(&arg, paramAddress);
106 // Generate debug info
107
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
108 8 }
109
110 // Visit function body
111
2/4
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
212 visit(node->body());
112
113 // Create return statement if the block is not terminated yet
114
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 3 times.
212 if (!blockAlreadyTerminated) {
115
4/8
✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 209 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 209 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 209 times.
✗ Branch 11 not taken.
209 llvm::Value *result = insertLoad(fct->getReturnType(), resultEntry->getAddress());
116
1/2
✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
209 builder.CreateRet(result);
117 }
118
119 // Conclude debug info for function
120
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 diGenerator.concludeFunctionDebugInfo();
121
122 // Verify function
123
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 verifyFunction(fct, node->codeLoc);
124
125 // Change back to root scope
126 212 currentScope = rootScope;
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 assert(currentScope != nullptr);
128
129
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 return nullptr;
130 212 }
131
132 3920 std::any IRGenerator::visitFctDef(const FctDefNode *node) {
133 // Loop through manifestations
134 3920 manIdx = 0; // Reset the symbolTypeIndex
135
2/2
✓ Branch 5 taken 5146 times.
✓ Branch 6 taken 3920 times.
9066 for (Function *manifestation : node->manifestations) {
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5146 times.
5146 assert(manifestation->entry != nullptr);
137
138 // Check if the manifestation is substantiated or not public and not used by anybody
139
2/4
✓ Branch 1 taken 5146 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5146 times.
✗ Branch 5 not taken.
5146 const bool isPublic = manifestation->entry->getQualType().isPublic();
140
9/10
✓ Branch 1 taken 5146 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3795 times.
✓ Branch 4 taken 1351 times.
✓ Branch 5 taken 139 times.
✓ Branch 6 taken 3656 times.
✓ Branch 7 taken 7 times.
✓ Branch 8 taken 132 times.
✓ Branch 9 taken 1358 times.
✓ Branch 10 taken 3788 times.
5146 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
141 1358 manIdx++; // Increment symbolTypeIndex
142 1358 continue;
143 }
144
145 // Change to struct scope
146
2/2
✓ Branch 0 taken 2416 times.
✓ Branch 1 taken 1372 times.
3788 if (manifestation->isMethod()) {
147 2416 const QualType &thisType = manifestation->thisType;
148
3/6
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2416 times.
✗ Branch 8 not taken.
2416 const std::string signature = Struct::getSignature(thisType.getSubType(), thisType.getTemplateTypes());
149
2/4
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
2416 currentScope = currentScope->getChildScope(STRUCT_SCOPE_PREFIX + signature);
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2416 times.
2416 assert(currentScope != nullptr);
151 2416 }
152
153 // Change scope
154
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
3788 currentScope = currentScope->getChildScope(manifestation->getSignature(false));
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3788 times.
3788 assert(currentScope != nullptr);
156
157 // Get 'this' entry
158 3788 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
159 3788 std::vector<llvm::Type *> paramTypes;
160
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 SymbolTableEntry *thisEntry = nullptr;
161
2/2
✓ Branch 0 taken 2416 times.
✓ Branch 1 taken 1372 times.
3788 if (manifestation->isMethod()) {
162
1/2
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
7248 thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2416 times.
2416 assert(thisEntry != nullptr);
164
1/2
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
2416 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
165
2/4
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
2416 paramTypes.push_back(builder.getPtrTy());
166 }
167
168 // Visit parameters
169 3788 size_t argIdx = 0;
170
2/2
✓ Branch 0 taken 2727 times.
✓ Branch 1 taken 1061 times.
3788 if (node->hasParams) {
171 2727 const size_t numOfParams = manifestation->paramList.size();
172
1/2
✓ Branch 1 taken 2727 times.
✗ Branch 2 not taken.
2727 paramInfoList.reserve(numOfParams);
173
1/2
✓ Branch 1 taken 2727 times.
✗ Branch 2 not taken.
2727 paramTypes.reserve(numOfParams);
174
2/2
✓ Branch 0 taken 4476 times.
✓ Branch 1 taken 2727 times.
7203 for (; argIdx < numOfParams; argIdx++) {
175
3/6
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4476 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4476 times.
✗ Branch 8 not taken.
4476 const DeclStmtNode *param = node->paramLst()->params().at(argIdx);
176 // Get symbol table entry of param
177
1/2
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
4476 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4476 times.
4476 assert(paramSymbol != nullptr);
179
2/4
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4476 times.
✗ Branch 5 not taken.
4476 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
180 // Pass the information if captures are taken for function/procedure types
181
6/10
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 4463 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4476 times.
4476 if (paramSymbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramSymbolType.hasLambdaCaptures())
182 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
183 // Retrieve type of param
184
1/2
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
4476 llvm::Type *paramType = paramSymbolType.toLLVMType(sourceFile);
185 // Add it to the lists
186
1/2
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
4476 paramInfoList.emplace_back(param->varName, paramSymbol);
187
1/2
✓ Branch 1 taken 4476 times.
✗ Branch 2 not taken.
4476 paramTypes.push_back(paramType);
188 }
189 }
190
191 // Get return type
192
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 llvm::Type *returnType = manifestation->returnType.toLLVMType(sourceFile);
193
194 // Check if function is explicitly inlined
195
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
3788 const bool explicitlyInlined = manifestation->entry->getQualType().isInline();
196 // Get function linkage
197 3788 bool externalLinkage = isPublic;
198
14/24
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 3779 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 9 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✓ Branch 20 taken 3779 times.
✓ Branch 22 taken 9 times.
✓ Branch 23 taken 3779 times.
✓ Branch 24 taken 9 times.
✓ Branch 25 taken 3779 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
3806 if (node->attrs() && node->attrs()->attrLst()->hasAttr(ATTR_TEST))
199
4/8
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
27 externalLinkage |= node->attrs()->attrLst()->getAttrValueByName(ATTR_TEST)->boolValue;
200
2/2
✓ Branch 0 taken 3664 times.
✓ Branch 1 taken 124 times.
3788 const llvm::GlobalValue::LinkageTypes linkage = externalLinkage ? llvm::Function::ExternalLinkage : llvm::Function::PrivateLinkage;
201
202 // Create function or implement declared function
203
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 const std::string mangledName = manifestation->getMangledName();
204
1/2
✓ Branch 2 taken 3788 times.
✗ Branch 3 not taken.
3788 llvm::FunctionType *funcType = llvm::FunctionType::get(returnType, paramTypes, false);
205
1/2
✓ Branch 2 taken 3788 times.
✗ Branch 3 not taken.
3788 module->getOrInsertFunction(mangledName, funcType);
206
1/2
✓ Branch 2 taken 3788 times.
✗ Branch 3 not taken.
3788 llvm::Function *func = module->getFunction(mangledName);
207
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 node->entry->updateAddress(func);
208 3788 manifestation->llvmFunction = func;
209
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3788 times.
3788 assert(func->empty());
210
211 // Set attributes to function
212 3788 func->setDSOLocal(true);
213
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 func->setLinkage(linkage);
214
2/2
✓ Branch 0 taken 995 times.
✓ Branch 1 taken 2793 times.
3788 if (explicitlyInlined)
215
1/2
✓ Branch 1 taken 995 times.
✗ Branch 2 not taken.
995 func->addFnAttr(llvm::Attribute::AlwaysInline);
216
217 // Set attributes to 'this' param
218
2/2
✓ Branch 0 taken 2416 times.
✓ Branch 1 taken 1372 times.
3788 if (manifestation->isMethod()) {
219
1/2
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
2416 func->addParamAttr(0, llvm::Attribute::NoUndef);
220
1/2
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
2416 func->addParamAttr(0, llvm::Attribute::NonNull);
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2416 times.
2416 assert(thisEntry != nullptr);
222
3/6
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2416 times.
✗ Branch 8 not taken.
2416 llvm::Type *structType = thisEntry->getQualType().getContained().toLLVMType(sourceFile);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2416 times.
2416 assert(structType != nullptr);
224
3/6
✓ Branch 2 taken 2416 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2416 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2416 times.
✗ Branch 9 not taken.
2416 func->addDereferenceableParamAttr(0, module->getDataLayout().getTypeStoreSize(structType));
225
3/6
✓ Branch 2 taken 2416 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2416 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2416 times.
✗ Branch 9 not taken.
2416 func->addParamAttr(0, llvm::Attribute::getWithAlignment(context, module->getDataLayout().getABITypeAlign(structType)));
226 }
227
228 // Add debug info
229
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 diGenerator.generateFunctionDebugInfo(func, manifestation);
230
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 diGenerator.setSourceLocation(node);
231
232 // Create entry block
233
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
3788 llvm::BasicBlock *bEntry = createBlock();
234
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 switchToBlock(bEntry, func);
235
236 // Reset alloca insert markers to this block
237 3788 allocaInsertBlock = bEntry;
238 3788 allocaInsertInst = nullptr;
239
240 // Declare result variable
241
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
3788 llvm::Value *resultAddr = insertAlloca(returnType, RETURN_VARIABLE_NAME);
242
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
11364 SymbolTableEntry *resultEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3788 times.
3788 assert(resultEntry != nullptr);
244
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 resultEntry->updateAddress(resultAddr);
245 // Generate debug info
246
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
7576 diGenerator.generateLocalVarDebugInfo(RETURN_VARIABLE_NAME, resultAddr);
247
248 // Store function argument values
249
3/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 6892 times.
✓ Branch 6 taken 3788 times.
10680 for (auto &arg : func->args()) {
250 // Get information about the parameter
251 6892 const size_t argNumber = arg.getArgNo();
252
2/4
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6892 times.
✗ Branch 5 not taken.
6892 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6892 times.
6892 assert(paramSymbol != nullptr);
254 // Allocate space for it
255
1/2
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
6892 llvm::Type *paramType = funcType->getParamType(argNumber);
256
2/4
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6892 times.
✗ Branch 5 not taken.
6892 llvm::Value *paramAddress = insertAlloca(paramType, paramName);
257 // Update the symbol table entry
258
1/2
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
6892 paramSymbol->updateAddress(paramAddress);
259 // Set source location
260
1/2
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
6892 diGenerator.setSourceLocation(paramSymbol->declNode);
261 // Store the value at the new address
262
1/2
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
6892 insertStore(&arg, paramAddress);
263 // Generate debug info to declare variable
264
1/2
✓ Branch 1 taken 6892 times.
✗ Branch 2 not taken.
6892 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
265 6892 }
266
267 // Store the default values for optional function args
268
3/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2727 times.
✓ Branch 4 taken 1061 times.
3788 if (node->paramLst()) {
269
2/4
✓ Branch 1 taken 2727 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2727 times.
✗ Branch 5 not taken.
2727 const std::vector<DeclStmtNode *> params = node->paramLst()->params();
270
2/2
✓ Branch 1 taken 419 times.
✓ Branch 2 taken 2727 times.
3146 for (; argIdx < params.size(); argIdx++)
271
2/4
✓ Branch 1 taken 419 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 419 times.
✗ Branch 5 not taken.
419 visit(params.at(argIdx));
272 2727 }
273
274 // Visit function body
275
2/4
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3788 times.
✗ Branch 5 not taken.
3788 visit(node->body());
276
277 // Create return statement if the block is not terminated yet
278
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 3614 times.
3788 if (!blockAlreadyTerminated) {
279
3/6
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 174 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 174 times.
✗ Branch 8 not taken.
174 llvm::Value *result = insertLoad(returnType, resultEntry->getAddress());
280
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
174 builder.CreateRet(result);
281 }
282
283 // Conclude debug info for function
284
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 diGenerator.concludeFunctionDebugInfo();
285
286 // Verify function
287
1/2
✓ Branch 1 taken 3788 times.
✗ Branch 2 not taken.
3788 verifyFunction(func, node->codeLoc);
288
289 // Change to root scope
290 3788 currentScope = rootScope;
291
292 3788 manIdx++; // Increment symbolTypeIndex
293 3788 }
294 3920 manIdx = 0; // Reset the symbolTypeIndex
295
296 // Ensure that we are at the root scope again
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3920 times.
3920 assert(currentScope == rootScope);
298
299
1/2
✓ Branch 1 taken 3920 times.
✗ Branch 2 not taken.
3920 return nullptr;
300 }
301
302 2472 std::any IRGenerator::visitProcDef(const ProcDefNode *node) {
303 // Loop through manifestations
304 2472 manIdx = 0; // Reset the symbolTypeIndex
305
2/2
✓ Branch 5 taken 3217 times.
✓ Branch 6 taken 2472 times.
5689 for (Function *manifestation : node->manifestations) {
306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3217 times.
3217 assert(manifestation->entry != nullptr);
307
308 // Check if the manifestation is substantiated or not public and not used by anybody
309
2/4
✓ Branch 1 taken 3217 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3217 times.
✗ Branch 5 not taken.
3217 const bool isPublic = manifestation->entry->getQualType().isPublic();
310
9/10
✓ Branch 1 taken 3217 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2185 times.
✓ Branch 4 taken 1032 times.
✓ Branch 5 taken 257 times.
✓ Branch 6 taken 1928 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 251 times.
✓ Branch 9 taken 1038 times.
✓ Branch 10 taken 2179 times.
3217 if (!manifestation->isFullySubstantiated() || (!isPublic && !manifestation->used)) {
311 1038 manIdx++; // Increment symbolTypeIndex
312 1038 continue;
313 }
314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2179 times.
2179 assert(manifestation->alreadyTypeChecked);
315
316 // Change to struct scope
317
2/2
✓ Branch 0 taken 2004 times.
✓ Branch 1 taken 175 times.
2179 if (manifestation->isMethod()) {
318 2004 const QualType &thisType = manifestation->thisType;
319
3/6
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2004 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2004 times.
✗ Branch 8 not taken.
2004 const std::string signature = Struct::getSignature(thisType.getSubType(), thisType.getTemplateTypes());
320
2/4
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2004 times.
✗ Branch 5 not taken.
2004 currentScope = currentScope->getChildScope(STRUCT_SCOPE_PREFIX + signature);
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004 times.
2004 assert(currentScope != nullptr);
322 2004 }
323
324 // Change scope
325
2/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2179 times.
✗ Branch 5 not taken.
2179 currentScope = currentScope->getChildScope(manifestation->getSignature(false));
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2179 times.
2179 assert(currentScope != nullptr);
327
328 // Get 'this' entry
329 2179 std::vector<std::pair<std::string, SymbolTableEntry *>> paramInfoList;
330 2179 std::vector<llvm::Type *> paramTypes;
331
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 SymbolTableEntry *thisEntry = nullptr;
332
2/2
✓ Branch 0 taken 2004 times.
✓ Branch 1 taken 175 times.
2179 if (manifestation->isMethod()) {
333
1/2
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
6012 thisEntry = currentScope->lookupStrict(THIS_VARIABLE_NAME);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004 times.
2004 assert(thisEntry != nullptr);
335
1/2
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
2004 paramInfoList.emplace_back(THIS_VARIABLE_NAME, thisEntry);
336
2/4
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2004 times.
✗ Branch 5 not taken.
2004 paramTypes.push_back(builder.getPtrTy());
337 }
338
339 // Visit parameters
340 2179 size_t argIdx = 0;
341
2/2
✓ Branch 0 taken 1502 times.
✓ Branch 1 taken 677 times.
2179 if (node->hasParams) {
342 1502 const size_t numOfParams = manifestation->paramList.size();
343
1/2
✓ Branch 1 taken 1502 times.
✗ Branch 2 not taken.
1502 paramInfoList.reserve(numOfParams);
344
1/2
✓ Branch 1 taken 1502 times.
✗ Branch 2 not taken.
1502 paramTypes.reserve(numOfParams);
345
2/2
✓ Branch 0 taken 1715 times.
✓ Branch 1 taken 1502 times.
3217 for (; argIdx < numOfParams; argIdx++) {
346
3/6
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1715 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1715 times.
✗ Branch 8 not taken.
1715 const DeclStmtNode *param = node->paramLst()->params().at(argIdx);
347 // Get symbol table entry of param
348
1/2
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
1715 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1715 times.
1715 assert(paramSymbol != nullptr);
350
2/4
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1715 times.
✗ Branch 5 not taken.
1715 const QualType paramSymbolType = manifestation->getParamTypes().at(argIdx);
351 // Pass the information if captures are taken for function/procedure types
352
8/10
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 1695 times.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 17 times.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 1712 times.
1715 if (paramSymbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramSymbolType.hasLambdaCaptures())
353
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
354 // Retrieve type of param
355
1/2
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
1715 llvm::Type *paramType = paramSymbolType.toLLVMType(sourceFile);
356 // Add it to the lists
357
1/2
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
1715 paramInfoList.emplace_back(param->varName, paramSymbol);
358
1/2
✓ Branch 1 taken 1715 times.
✗ Branch 2 not taken.
1715 paramTypes.push_back(paramType);
359 }
360 }
361
362 // Get return type
363
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 llvm::Type *returnType = builder.getVoidTy();
364
365 // Check if procedure is explicitly inlined
366
2/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2179 times.
✗ Branch 5 not taken.
2179 const bool explicitlyInlined = manifestation->entry->getQualType().isInline();
367 // Get procedure linkage
368
2/2
✓ Branch 0 taken 1928 times.
✓ Branch 1 taken 251 times.
2179 const llvm::GlobalValue::LinkageTypes linkage = isPublic ? llvm::Function::ExternalLinkage : llvm::Function::PrivateLinkage;
369
370 // Create procedure or implement declared procedure
371
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 const std::string mangledName = manifestation->getMangledName();
372
1/2
✓ Branch 2 taken 2179 times.
✗ Branch 3 not taken.
2179 llvm::FunctionType *procType = llvm::FunctionType::get(returnType, paramTypes, false);
373
1/2
✓ Branch 2 taken 2179 times.
✗ Branch 3 not taken.
2179 module->getOrInsertFunction(mangledName, procType);
374
1/2
✓ Branch 2 taken 2179 times.
✗ Branch 3 not taken.
2179 llvm::Function *proc = module->getFunction(mangledName);
375
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 node->entry->updateAddress(proc);
376 2179 manifestation->llvmFunction = proc;
377
2/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2179 times.
2179 assert(proc->empty());
378
379 // Set attributes to procedure
380 2179 proc->setDSOLocal(true);
381
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 proc->setLinkage(linkage);
382
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 1976 times.
2179 if (explicitlyInlined)
383
1/2
✓ Branch 1 taken 203 times.
✗ Branch 2 not taken.
203 proc->addFnAttr(llvm::Attribute::AlwaysInline);
384
385 // Set attributes to 'this' param
386
2/2
✓ Branch 0 taken 2004 times.
✓ Branch 1 taken 175 times.
2179 if (manifestation->isMethod()) {
387
1/2
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
2004 proc->addParamAttr(0, llvm::Attribute::NoUndef);
388
1/2
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
2004 proc->addParamAttr(0, llvm::Attribute::NonNull);
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004 times.
2004 assert(thisEntry != nullptr);
390
3/6
✓ Branch 1 taken 2004 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2004 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2004 times.
✗ Branch 8 not taken.
2004 llvm::Type *structType = thisEntry->getQualType().getContained().toLLVMType(sourceFile);
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004 times.
2004 assert(structType != nullptr);
392
3/6
✓ Branch 2 taken 2004 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2004 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2004 times.
✗ Branch 9 not taken.
2004 proc->addDereferenceableParamAttr(0, module->getDataLayout().getTypeStoreSize(structType));
393
3/6
✓ Branch 2 taken 2004 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2004 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2004 times.
✗ Branch 9 not taken.
2004 proc->addParamAttr(0, llvm::Attribute::getWithAlignment(context, module->getDataLayout().getABITypeAlign(structType)));
394 }
395
396 // Add debug info
397
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 diGenerator.generateFunctionDebugInfo(proc, manifestation);
398
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 diGenerator.setSourceLocation(node);
399
400 // Create entry block
401
2/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2179 times.
✗ Branch 5 not taken.
2179 llvm::BasicBlock *bEntry = createBlock();
402
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 switchToBlock(bEntry, proc);
403
404 // Reset alloca insert markers to this block
405 2179 allocaInsertBlock = bEntry;
406 2179 allocaInsertInst = nullptr;
407
408 // Store procedure argument values
409
3/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3719 times.
✓ Branch 6 taken 2179 times.
5898 for (auto &arg : proc->args()) {
410 // Get information about the parameter
411 3719 const size_t argNumber = arg.getArgNo();
412
2/4
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3719 times.
✗ Branch 5 not taken.
3719 auto [paramName, paramSymbol] = paramInfoList.at(argNumber);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3719 times.
3719 assert(paramSymbol != nullptr);
414 // Allocate space for it
415
1/2
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
3719 llvm::Type *paramType = procType->getParamType(argNumber);
416
2/4
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3719 times.
✗ Branch 5 not taken.
3719 llvm::Value *paramAddress = insertAlloca(paramType, paramName);
417 // Update the symbol table entry
418
1/2
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
3719 paramSymbol->updateAddress(paramAddress);
419 // Set source location
420
1/2
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
3719 diGenerator.setSourceLocation(paramSymbol->declNode);
421 // Store the value at the new address
422
1/2
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
3719 insertStore(&arg, paramAddress);
423 // Generate debug info to declare variable
424
1/2
✓ Branch 1 taken 3719 times.
✗ Branch 2 not taken.
3719 diGenerator.generateLocalVarDebugInfo(paramName, paramAddress, argNumber + 1);
425 3719 }
426
427 // Store the default values for optional procedure args
428
3/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1502 times.
✓ Branch 4 taken 677 times.
2179 if (node->paramLst()) {
429
2/4
✓ Branch 1 taken 1502 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1502 times.
✗ Branch 5 not taken.
1502 const std::vector<DeclStmtNode *> params = node->paramLst()->params();
430
2/2
✓ Branch 1 taken 126 times.
✓ Branch 2 taken 1502 times.
1628 for (; argIdx < params.size(); argIdx++)
431
2/4
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
126 visit(params.at(argIdx));
432 1502 }
433
434 // Generate special ctor preamble before generating the body to store VTable, default field values, etc. if required
435
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 1206 times.
2179 if (node->isCtor)
436
1/2
✓ Branch 1 taken 973 times.
✗ Branch 2 not taken.
973 generateCtorBodyPreamble(currentScope);
437
438 // Visit procedure body
439
2/4
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2179 times.
✗ Branch 5 not taken.
2179 visit(node->body());
440
441 // Create return statement if the block is not terminated yet
442
2/2
✓ Branch 0 taken 2100 times.
✓ Branch 1 taken 79 times.
2179 if (!blockAlreadyTerminated)
443
1/2
✓ Branch 1 taken 2100 times.
✗ Branch 2 not taken.
2100 builder.CreateRetVoid();
444
445 // Conclude debug info for procedure
446
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 diGenerator.concludeFunctionDebugInfo();
447
448 // Verify procedure
449
1/2
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
2179 verifyFunction(proc, node->codeLoc);
450
451 // Change to root scope
452 2179 currentScope = rootScope;
453
454 2179 manIdx++; // Increment symbolTypeIndex
455 2179 }
456 2472 manIdx = 0; // Reset the symbolTypeIndex
457
458 // Ensure that we are at the root scope again
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2472 times.
2472 assert(currentScope == rootScope);
460
461
1/2
✓ Branch 1 taken 2472 times.
✗ Branch 2 not taken.
2472 return nullptr;
462 }
463
464 457 std::any IRGenerator::visitStructDef(const StructDefNode *node) {
465 // Get all substantiated structs which result from this struct def
466
1/2
✓ Branch 1 taken 457 times.
✗ Branch 2 not taken.
457 std::vector<Struct *> manifestations = node->structManifestations;
467
468 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
469 604 const auto comp = [](const Struct *lhs, const Struct *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
470
1/2
✓ Branch 1 taken 457 times.
✗ Branch 2 not taken.
457 std::ranges::sort(manifestations, comp);
471
472
2/2
✓ Branch 5 taken 759 times.
✓ Branch 6 taken 457 times.
1216 for (Struct *spiceStruct : manifestations) {
473 // Skip structs, that are not fully substantiated
474
3/4
✓ Branch 1 taken 759 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
✓ Branch 4 taken 571 times.
759 if (!spiceStruct->isFullySubstantiated())
475 190 continue;
476
477 // Do not generate this struct if it is private and used by nobody
478
8/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 568 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 569 times.
571 if (!spiceStruct->used && !spiceStruct->entry->getQualType().isPublic())
479 2 continue;
480
481 // Change scope to struct scope, specific to substantiation
482 569 currentScope = spiceStruct->scope;
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 assert(currentScope);
484
485 // Set LLVM type to the struct entry
486 569 const SymbolTableEntry *structEntry = spiceStruct->entry;
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 assert(structEntry != nullptr);
488
489 // Generate VTable if required
490
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 428 times.
569 if (node->emitVTable) {
491
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
141 generateVTable(spiceStruct);
492
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
282 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceStruct); }, false);
493 }
494
495 // Generate default ctor if required
496
1/2
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
569 const QualType &thisType = structEntry->getQualType();
497
2/4
✓ Branch 2 taken 569 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 569 times.
✗ Branch 6 not taken.
1707 const Function *ctorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, {}, true);
498
4/4
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 207 times.
569 if (ctorFunc != nullptr && ctorFunc->implicitDefault)
499
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 generateDefaultCtor(ctorFunc);
500
501 // Generate default copy ctor if required
502
2/4
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 569 times.
✗ Branch 6 not taken.
1707 const ArgList args = {{thisType.toConstRef(node), false /* always non-temporary */}};
503
2/4
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 569 times.
✗ Branch 5 not taken.
569 const Function *copyCtorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, thisType, args, true);
504
4/4
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 91 times.
569 if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault)
505
1/2
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
79 generateDefaultCopyCtor(copyCtorFunc);
506
507 // Generate default dtor if required
508
2/4
✓ Branch 2 taken 569 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 569 times.
✗ Branch 6 not taken.
1707 const Function *dtorFunc = FunctionManager::lookup(currentScope, DTOR_FUNCTION_NAME, thisType, {}, true);
509
4/4
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 405 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 80 times.
569 if (dtorFunc != nullptr && dtorFunc->implicitDefault)
510
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 generateDefaultDtor(dtorFunc);
511
512 // Return to root scope
513 569 currentScope = rootScope;
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 assert(currentScope);
515 569 }
516
517
1/2
✓ Branch 1 taken 457 times.
✗ Branch 2 not taken.
914 return nullptr;
518 457 }
519
520 60 std::any IRGenerator::visitInterfaceDef(const InterfaceDefNode *node) {
521 // Get all substantiated structs which result from this struct def
522
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 std::vector<Interface *> manifestations = node->interfaceManifestations;
523
524 // Sort the manifestations to prevent generating the struct types in the wrong order (in case of dependencies between structs)
525 196 const auto comp = [](const Interface *lhs, const Interface *rhs) { return lhs->manifestationIndex < rhs->manifestationIndex; };
526
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 std::ranges::sort(manifestations, comp);
527
528
2/2
✓ Branch 5 taken 158 times.
✓ Branch 6 taken 60 times.
218 for (Interface *spiceInterface : manifestations) {
529 // Skip interfaces, that are not fully substantiated
530
3/4
✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 109 times.
158 if (!spiceInterface->isFullySubstantiated())
531 49 continue;
532
533 // Do not generate this interface if it is private and used by nobody
534
8/10
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 108 times.
109 if (!spiceInterface->used && !spiceInterface->entry->getQualType().isPublic())
535 1 continue;
536
537 // Generate VTable information
538
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 generateVTable(spiceInterface);
539
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
216 deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceInterface); }, false);
540 }
541
542
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
120 return nullptr;
543 60 }
544
545 37 std::any IRGenerator::visitEnumDef(const EnumDefNode *node) {
546
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 return nullptr; // Noop (enums are high-level semantic-only structures)
547 }
548
549 647 std::any IRGenerator::visitGenericTypeDef(const GenericTypeDefNode *node) {
550
1/2
✓ Branch 1 taken 647 times.
✗ Branch 2 not taken.
647 return nullptr; // Noop (generic types are high-level semantic-only structures)
551 }
552
553 29 std::any IRGenerator::visitAliasDef(const AliasDefNode *node) {
554
1/2
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
29 return nullptr; // Noop (alias definitions are high-level semantic-only structures)
555 }
556
557 709 std::any IRGenerator::visitGlobalVarDef(const GlobalVarDefNode *node) {
558 // Retrieve some information about the variable
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 709 times.
709 assert(node->entry != nullptr);
560 709 const QualType &entryType = node->entry->getQualType();
561 709 const bool isPublic = entryType.isPublic();
562 709 const bool isConst = entryType.isConst();
563
564 // Get correct type and linkage type
565
3/6
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 709 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 709 times.
✗ Branch 8 not taken.
709 const auto varType = std::any_cast<llvm::Type *>(visit(node->dataType()));
566
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 451 times.
709 const auto linkage = isPublic ? llvm::GlobalValue::ExternalLinkage : llvm::GlobalValue::PrivateLinkage;
567
568 // Create global var
569
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 llvm::Value *varAddress = module->getOrInsertGlobal(node->varName, varType);
570
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 llvm::GlobalVariable *var = module->getNamedGlobal(node->varName);
571 // Set some attributes, based on the given information
572 709 var->setLinkage(linkage);
573 709 var->setConstant(isConst);
574
575 // Set initializer
576
1/2
✓ Branch 0 taken 709 times.
✗ Branch 1 not taken.
709 if (node->hasValue) { // Set the constant value as variable initializer
577
3/6
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 709 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 709 times.
✗ Branch 8 not taken.
709 const auto constantValue = std::any_cast<llvm::Constant *>(visit(node->constant()));
578 709 var->setInitializer(constantValue);
579 } else if (cliOptions.buildMode == DEBUG) { // Set the default value as variable initializer
580 llvm::Constant *constantValue = getDefaultValueForSymbolType(node->entry->getQualType());
581 var->setInitializer(constantValue);
582 }
583
584 709 node->entry->updateAddress(varAddress);
585
586 // Add debug info
587 709 diGenerator.generateGlobalVarDebugInfo(var, node->entry);
588
589
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 return nullptr;
590 }
591
592 667 std::any IRGenerator::visitExtDecl(const ExtDeclNode *node) {
593 // Get return type
594 667 const Function *spiceFunc = node->extFunction;
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 667 times.
667 assert(spiceFunc != nullptr);
596
1/2
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
667 llvm::Type *returnType = builder.getVoidTy();
597
3/4
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 435 times.
✓ Branch 4 taken 232 times.
667 if (!spiceFunc->returnType.is(TY_DYN))
598
1/2
✓ Branch 1 taken 435 times.
✗ Branch 2 not taken.
435 returnType = spiceFunc->returnType.toLLVMType(sourceFile);
599
600 // Get arg types
601 667 std::vector<llvm::Type *> argTypes;
602
1/2
✓ Branch 2 taken 667 times.
✗ Branch 3 not taken.
667 argTypes.reserve(spiceFunc->paramList.size());
603
3/4
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 1272 times.
✓ Branch 8 taken 667 times.
1939 for (const QualType &paramType : spiceFunc->getParamTypes())
604
2/4
✓ Branch 1 taken 1272 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1272 times.
✗ Branch 5 not taken.
1939 argTypes.push_back(paramType.toLLVMType(sourceFile));
605
606 // Declare function
607
1/2
✓ Branch 2 taken 667 times.
✗ Branch 3 not taken.
667 llvm::FunctionType *functionType = llvm::FunctionType::get(returnType, argTypes, node->isVarArg);
608
1/2
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
667 const std::string mangledName = spiceFunc->getMangledName();
609
1/2
✓ Branch 2 taken 667 times.
✗ Branch 3 not taken.
667 module->getOrInsertFunction(mangledName, functionType);
610
1/2
✓ Branch 2 taken 667 times.
✗ Branch 3 not taken.
667 llvm::Function *fct = module->getFunction(mangledName);
611
612 // Add noundef attribute to all parameters
613
2/2
✓ Branch 1 taken 1272 times.
✓ Branch 2 taken 667 times.
1939 for (size_t i = 0; i < argTypes.size(); i++)
614
1/2
✓ Branch 1 taken 1272 times.
✗ Branch 2 not taken.
1272 fct->addParamAttr(i, llvm::Attribute::NoUndef);
615
616 // If the function should be imported as dll, add the dll attribute
617
13/24
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 666 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 666 times.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 666 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 667 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
669 if (node->attrs() && node->attrs()->attrLst()->hasAttr(ATTR_CORE_LINKER_DLL))
618 if (node->attrs()->attrLst()->getAttrValueByName(ATTR_CORE_LINKER_DLL)->boolValue)
619 fct->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
620
621
1/2
✓ Branch 1 taken 667 times.
✗ Branch 2 not taken.
1334 return nullptr;
622 667 }
623
624 } // namespace spice::compiler
625