GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenTopLevelDefinitions.cpp
Date: 2025-02-05 01:09:36
Exec Total Coverage
Lines: 352 361 97.5%
Functions: 14 14 100.0%
Branches: 447 780 57.3%

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