GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenTopLevelDefinitions.cpp
Date: 2025-03-05 01:50:32
Exec Total Coverage
Lines: 355 365 97.3%
Functions: 14 14 100.0%
Branches: 448 786 57.0%

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