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