GCC Code Coverage Report


Directory: ../
File: src/irgenerator/IRGenerator.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 318 331 96.1%
Functions: 33 33 100.0%
Branches: 388 634 61.2%

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 #include <llvm/IR/Verifier.h>
7
8 #include <SourceFile.h>
9 #include <global/GlobalResourceManager.h>
10 #include <irgenerator/NameMangling.h>
11 #include <symboltablebuilder/SymbolTableBuilder.h>
12
13 namespace spice::compiler {
14
15 678 IRGenerator::IRGenerator(GlobalResourceManager &resourceManager, SourceFile *sourceFile)
16 678 : CompilerPass(resourceManager, sourceFile), context(cliOptions.useLTO ? resourceManager.ltoContext : sourceFile->context),
17
1/2
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
678 builder(sourceFile->builder), module(sourceFile->llvmModule.get()), conversionManager(sourceFile, this),
18
5/8
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 676 times.
✓ Branch 5 taken 678 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 678 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 678 times.
✗ Branch 15 not taken.
1356 stdFunctionManager(sourceFile, resourceManager, module) {
19 // Attach information to the module
20
1/2
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
678 module->setTargetTriple(cliOptions.targetTriple);
21
2/4
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 678 times.
✗ Branch 6 not taken.
678 module->setDataLayout(sourceFile->targetMachine->createDataLayout());
22
23 // Initialize debug info generator
24
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 665 times.
678 if (cliOptions.generateDebugInfo)
25
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 diGenerator.initialize(sourceFile->fileName, sourceFile->fileDir);
26 678 }
27
28 678 std::any IRGenerator::visitEntry(const EntryNode *node) {
29 // Generate IR
30
1/2
✓ Branch 1 taken 678 times.
✗ Branch 2 not taken.
678 visitChildren(node);
31
32 // Generate test main if required
33
4/4
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 464 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 212 times.
678 if (sourceFile->isMainFile && cliOptions.generateTestMain)
34 2 generateTestMain();
35
36 // Execute deferred VTable initializations
37
2/2
✓ Branch 5 taken 249 times.
✓ Branch 6 taken 678 times.
927 for (DeferredLogic &deferredVTableInit : deferredVTableInitializations)
38
1/2
✓ Branch 1 taken 249 times.
✗ Branch 2 not taken.
249 deferredVTableInit.execute();
39
40 // Finalize debug info generator
41 678 diGenerator.finalize();
42
43 // Verify module
44 678 verifyModule(node->codeLoc);
45
46
1/2
✓ Branch 1 taken 678 times.
✗ Branch 2 not taken.
678 return nullptr;
47 }
48
49 22602 llvm::Value *IRGenerator::insertAlloca(llvm::Type *llvmType, std::string varName) {
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22602 times.
22602 if (!cliOptions.namesForIRValues)
51 varName = "";
52
53
2/2
✓ Branch 0 taken 16283 times.
✓ Branch 1 taken 6319 times.
22602 if (allocaInsertInst != nullptr) { // If there is already an alloca inst, insert right after that
54
2/4
✓ Branch 1 taken 16283 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16283 times.
✗ Branch 5 not taken.
16283 llvm::AllocaInst *allocaInst = builder.CreateAlloca(llvmType, nullptr, varName);
55
1/2
✓ Branch 2 taken 16283 times.
✗ Branch 3 not taken.
16283 allocaInst->setDebugLoc(llvm::DebugLoc());
56 16283 allocaInst->moveAfter(allocaInsertInst);
57 16283 allocaInsertInst = allocaInst;
58 } else { // This is the first alloca inst in the current function -> insert at the entry block
59 // Save current basic block and move insert cursor to entry block of the current function
60 6319 llvm::BasicBlock *currentBlock = builder.GetInsertBlock();
61 6319 builder.SetInsertPoint(allocaInsertBlock);
62
63 // Allocate the size of the given LLVM type
64
2/4
✓ Branch 1 taken 6319 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6319 times.
✗ Branch 5 not taken.
6319 allocaInsertInst = builder.CreateAlloca(llvmType, nullptr, varName);
65
1/2
✓ Branch 2 taken 6319 times.
✗ Branch 3 not taken.
6319 allocaInsertInst->setDebugLoc(llvm::DebugLoc());
66
67 // Restore old basic block
68 6319 builder.SetInsertPoint(currentBlock);
69 }
70
71 // Insert lifetime start marker
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22602 times.
22602 if (cliOptions.useLifetimeMarkers) {
73 const uint64_t sizeInBytes = module->getDataLayout().getTypeAllocSize(llvmType);
74 builder.CreateLifetimeStart(allocaInsertInst, builder.getInt64(sizeInBytes));
75 }
76
77 22602 return allocaInsertInst;
78 }
79
80 47154 llvm::Value *IRGenerator::insertLoad(llvm::Type *llvmType, llvm::Value *ptr, bool isVolatile, const std::string &varName) const {
81
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 47154 times.
47154 assert(ptr->getType()->isPointerTy());
82
5/14
✓ Branch 0 taken 47154 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 47154 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 47154 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 47154 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 47154 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
47154 return builder.CreateLoad(llvmType, ptr, isVolatile, cliOptions.namesForIRValues ? varName : "");
83 }
84
85 25757 void IRGenerator::insertStore(llvm::Value *val, llvm::Value *ptr, bool isVolatile) const {
86
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 25757 times.
25757 assert(ptr->getType()->isPointerTy());
87 25757 builder.CreateStore(val, ptr, isVolatile);
88 25757 }
89
90 16833 llvm::Value *IRGenerator::insertInBoundsGEP(llvm::Type *type, llvm::Value *basePtr, llvm::ArrayRef<llvm::Value *> indices,
91 std::string varName) const {
92
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 16833 times.
16833 assert(basePtr->getType()->isPointerTy());
93
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16833 times.
16833 assert(!indices.empty());
94
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 16833 times.
✓ Branch 6 taken 16575 times.
✓ Branch 7 taken 15239 times.
✓ Branch 9 taken 16575 times.
✗ Branch 10 not taken.
48647 assert(std::ranges::all_of(indices, [](llvm::Value *index) {
95 llvm::Type *indexType = index->getType();
96 return indexType->isIntegerTy(32) || indexType->isIntegerTy(64);
97 }));
98
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16833 times.
16833 if (!cliOptions.namesForIRValues)
100 varName = "";
101
102 // Insert GEP
103
2/4
✓ Branch 1 taken 16833 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16833 times.
✗ Branch 5 not taken.
16833 return builder.CreateInBoundsGEP(type, basePtr, indices, varName);
104 }
105
106 380 llvm::Value *IRGenerator::insertStructGEP(llvm::Type *type, llvm::Value *basePtr, unsigned int index, std::string varName) const {
107
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
380 assert(basePtr->getType()->isPointerTy());
108
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!cliOptions.namesForIRValues)
110 varName = "";
111
112 // If we use index 0 we can use the base pointer directly
113
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 124 times.
380 if (index == 0)
114 256 return basePtr;
115
116 // Insert GEP
117
2/4
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 124 times.
✗ Branch 5 not taken.
124 return builder.CreateStructGEP(type, basePtr, index, varName);
118 }
119
120 23404 llvm::Value *IRGenerator::resolveValue(const ASTNode *node) {
121 // Visit the given AST node
122
2/4
✓ Branch 1 taken 23404 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23404 times.
✗ Branch 5 not taken.
23404 auto exprResult = any_cast<LLVMExprResult>(visit(node));
123
1/2
✓ Branch 1 taken 23404 times.
✗ Branch 2 not taken.
46808 return resolveValue(node, exprResult);
124 }
125
126 27719 llvm::Value *IRGenerator::resolveValue(const ASTNode *node, LLVMExprResult &exprResult) const {
127 27719 return resolveValue(node->getEvaluatedSymbolType(manIdx), exprResult);
128 }
129
130 59992 llvm::Value *IRGenerator::resolveValue(const QualType &qualType, LLVMExprResult &exprResult) const {
131 // Check if the value is already present
132
2/2
✓ Branch 0 taken 20577 times.
✓ Branch 1 taken 39415 times.
59992 if (exprResult.value != nullptr)
133 20577 return exprResult.value;
134
135 // Check if a constant is present
136
2/2
✓ Branch 0 taken 9476 times.
✓ Branch 1 taken 29939 times.
39415 if (exprResult.constant != nullptr) {
137 9476 materializeConstant(exprResult);
138 9476 return exprResult.value;
139 }
140
141
3/4
✓ Branch 0 taken 417 times.
✓ Branch 1 taken 29522 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 417 times.
29939 assert(exprResult.ptr != nullptr || exprResult.refPtr != nullptr);
142
143 // De-reference if reference type
144
1/2
✓ Branch 1 taken 29939 times.
✗ Branch 2 not taken.
29939 const QualType referencedType = qualType.removeReferenceWrapper();
145
4/4
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 29518 times.
✓ Branch 2 taken 417 times.
✓ Branch 3 taken 4 times.
29939 if (exprResult.refPtr != nullptr && exprResult.ptr == nullptr)
146
6/10
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 417 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 412 times.
✓ Branch 8 taken 417 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 417 times.
✗ Branch 12 not taken.
834 exprResult.ptr = insertLoad(builder.getPtrTy(), exprResult.refPtr, exprResult.entry && exprResult.entry->isVolatile);
147
148 // Load the value from the pointer
149
1/2
✓ Branch 1 taken 29939 times.
✗ Branch 2 not taken.
29939 llvm::Type *valueTy = referencedType.toLLVMType(sourceFile);
150
6/8
✓ Branch 1 taken 29939 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27644 times.
✓ Branch 4 taken 2295 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 27634 times.
✓ Branch 8 taken 29939 times.
✗ Branch 9 not taken.
29939 exprResult.value = insertLoad(valueTy, exprResult.ptr, exprResult.entry && exprResult.entry->isVolatile);
151
152 29939 return exprResult.value;
153 }
154
155 1326 llvm::Value *IRGenerator::resolveAddress(const ASTNode *node) {
156 // Visit the given AST node
157
2/4
✓ Branch 1 taken 1326 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1326 times.
✗ Branch 5 not taken.
1326 auto exprResult = any_cast<LLVMExprResult>(visit(node));
158
1/2
✓ Branch 1 taken 1326 times.
✗ Branch 2 not taken.
2652 return resolveAddress(exprResult);
159 }
160
161 14701 llvm::Value *IRGenerator::resolveAddress(LLVMExprResult &exprResult) {
162 // Check if an address is already present
163
2/2
✓ Branch 0 taken 12146 times.
✓ Branch 1 taken 2555 times.
14701 if (exprResult.ptr != nullptr)
164 12146 return exprResult.ptr;
165
166 // Check if the reference address is already present
167
3/4
✓ Branch 0 taken 1908 times.
✓ Branch 1 taken 647 times.
✓ Branch 2 taken 1908 times.
✗ Branch 3 not taken.
2555 if (exprResult.refPtr != nullptr && exprResult.ptr == nullptr) {
168
6/10
✓ Branch 1 taken 1908 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1903 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1903 times.
✓ Branch 8 taken 1908 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1908 times.
✗ Branch 12 not taken.
1908 exprResult.ptr = insertLoad(builder.getPtrTy(), exprResult.refPtr, exprResult.entry && exprResult.entry->isVolatile);
169 1908 return exprResult.ptr;
170 }
171
172 // If not, store the value or constant
173 647 materializeConstant(exprResult);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 647 times.
647 assert(exprResult.value != nullptr);
175
7/12
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 645 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 645 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 647 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 645 times.
✓ Branch 14 taken 2 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1292 exprResult.ptr = insertAlloca(exprResult.value->getType(), exprResult.entry ? exprResult.entry->name : "");
176
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 645 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
647 insertStore(exprResult.value, exprResult.ptr, exprResult.entry && exprResult.entry->isVolatile);
177
178 647 return exprResult.ptr;
179 }
180
181 2161 llvm::Constant *IRGenerator::getDefaultValueForSymbolType(const QualType &symbolType) { // NOLINT(misc-no-recursion)
182 // Double
183
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2157 times.
2161 if (symbolType.is(TY_DOUBLE))
184
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 return llvm::ConstantFP::get(context, llvm::APFloat(0.0));
185
186 // Int
187
2/2
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 1861 times.
2157 if (symbolType.is(TY_INT))
188 296 return builder.getInt32(0);
189
190 // Short
191
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1849 times.
1861 if (symbolType.is(TY_SHORT))
192 12 return builder.getInt16(0);
193
194 // Long
195
2/2
✓ Branch 1 taken 779 times.
✓ Branch 2 taken 1070 times.
1849 if (symbolType.is(TY_LONG))
196 779 return builder.getInt64(0);
197
198 // Byte or char
199
3/4
✓ Branch 1 taken 1070 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 1052 times.
1070 if (symbolType.isOneOf({TY_BYTE, TY_CHAR}))
200 18 return builder.getInt8(0);
201
202 // String
203
2/2
✓ Branch 1 taken 346 times.
✓ Branch 2 taken 706 times.
1052 if (symbolType.is(TY_STRING))
204
3/6
✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 346 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 346 times.
✗ Branch 8 not taken.
346 return builder.CreateGlobalStringPtr("", "", 0, module);
205
206 // Bool
207
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 681 times.
706 if (symbolType.is(TY_BOOL))
208 25 return builder.getFalse();
209
210 // Pointer or reference
211
3/4
✓ Branch 1 taken 681 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 608 times.
✓ Branch 4 taken 73 times.
681 if (symbolType.isOneOf({TY_PTR, TY_REF}))
212 608 return llvm::Constant::getNullValue(builder.getPtrTy());
213
214 // Array
215
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 57 times.
73 if (symbolType.isArray()) {
216 // Get array size
217
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 const size_t arraySize = symbolType.getArraySize();
218
219 // Get default value for item
220
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 llvm::Constant *defaultItemValue = getDefaultValueForSymbolType(symbolType.getContained());
221
222 // Retrieve array and item type
223
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 llvm::Type *itemType = symbolType.getContained().toLLVMType(sourceFile);
224
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 llvm::ArrayType *arrayType = llvm::ArrayType::get(itemType, arraySize);
225
226 // Create a constant array with n times the default value
227
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 const std::vector<llvm::Constant *> itemConstants(arraySize, defaultItemValue);
228
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 return llvm::ConstantArray::get(arrayType, itemConstants);
229 16 }
230
231 // Function or procedure
232
3/4
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 29 times.
57 if (symbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
233
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
28 if (!llvmTypes.fatPtrType)
234
3/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
7 llvmTypes.fatPtrType = llvm::StructType::get(context, {builder.getPtrTy(), builder.getPtrTy()});
235
236
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 llvm::Constant *ptrDefaultValue = getDefaultValueForSymbolType(QualType(TY_PTR));
237
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 return llvm::ConstantStruct::get(llvmTypes.fatPtrType, {ptrDefaultValue, ptrDefaultValue});
238 }
239
240 // Struct
241
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 1 times.
29 if (symbolType.is(TY_STRUCT)) {
242 // Retrieve field count
243
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 Scope *structScope = symbolType.getBodyScope();
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 assert(structScope != nullptr);
245
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 const size_t fieldCount = structScope->getFieldCount();
246
247 // Get default values for all fields of the struct
248 28 std::vector<llvm::Constant *> fieldConstants;
249
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 fieldConstants.reserve(fieldCount);
250
251 // Add default value for each struct field
252
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 28 times.
93 for (size_t i = 0; i < fieldCount; i++) {
253 // Get entry of the field
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 const SymbolTableEntry *fieldEntry = structScope->lookupField(i);
255
3/6
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 65 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 65 times.
✗ Branch 6 not taken.
65 assert(fieldEntry != nullptr && fieldEntry->isField());
256
257 // Retrieve default field value
258 llvm::Constant *defaultFieldValue;
259
7/10
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 65 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 60 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 60 times.
65 if (const auto fieldNode = dynamic_cast<FieldNode *>(fieldEntry->declNode); fieldNode && fieldNode->defaultValue())
260
4/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
5 defaultFieldValue = getConst(fieldNode->defaultValue()->getCompileTimeValue(), fieldEntry->getQualType(), fieldNode);
261 else
262
2/4
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
60 defaultFieldValue = getDefaultValueForSymbolType(fieldEntry->getQualType());
263
264
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 fieldConstants.push_back(defaultFieldValue);
265 }
266
267
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 const auto structType = reinterpret_cast<llvm::StructType *>(symbolType.toLLVMType(sourceFile));
268
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 return llvm::ConstantStruct::get(structType, fieldConstants);
269 28 }
270
271 // Interface
272
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (symbolType.is(TY_INTERFACE)) {
273 1 const auto structType = reinterpret_cast<llvm::StructType *>(symbolType.toLLVMType(sourceFile));
274 1 return llvm::ConstantStruct::get(structType, llvm::Constant::getNullValue(builder.getPtrTy()));
275 }
276
277 throw CompilerError(INTERNAL_ERROR, "Cannot determine default value for symbol type"); // GCOV_EXCL_LINE
278 }
279
280 9711 llvm::Constant *IRGenerator::getConst(const CompileTimeValue &compileTimeValue, const QualType &type, const ASTNode *node) const {
281
2/2
✓ Branch 1 taken 169 times.
✓ Branch 2 taken 9542 times.
9711 if (type.is(TY_DOUBLE))
282
2/4
✓ Branch 1 taken 169 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 169 times.
✗ Branch 5 not taken.
169 return llvm::ConstantFP::get(context, llvm::APFloat(compileTimeValue.doubleValue));
283
284
2/2
✓ Branch 1 taken 2448 times.
✓ Branch 2 taken 7094 times.
9542 if (type.is(TY_INT))
285 2448 return builder.getInt32(compileTimeValue.intValue);
286
287
2/2
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 6924 times.
7094 if (type.is(TY_SHORT))
288 170 return builder.getInt16(compileTimeValue.shortValue);
289
290
2/2
✓ Branch 1 taken 4270 times.
✓ Branch 2 taken 2654 times.
6924 if (type.is(TY_LONG))
291 4270 return builder.getInt64(compileTimeValue.longValue);
292
293
3/4
✓ Branch 1 taken 2654 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 576 times.
✓ Branch 4 taken 2078 times.
2654 if (type.isOneOf({TY_BYTE, TY_CHAR}))
294 576 return builder.getInt8(compileTimeValue.charValue);
295
296
2/2
✓ Branch 1 taken 1001 times.
✓ Branch 2 taken 1077 times.
2078 if (type.is(TY_STRING)) {
297 1001 const std::string &stringValue = resourceManager.compileTimeStringValues.at(compileTimeValue.stringValueOffset);
298
2/4
✓ Branch 1 taken 1001 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1001 times.
✗ Branch 5 not taken.
3003 return createGlobalStringConst(ANON_GLOBAL_STRING_NAME, stringValue, node->codeLoc);
299 }
300
301
1/2
✓ Branch 1 taken 1077 times.
✗ Branch 2 not taken.
1077 if (type.is(TY_BOOL))
302 1077 return builder.getInt1(compileTimeValue.boolValue);
303
304 if (type.is(TY_PTR))
305 return llvm::Constant::getNullValue(builder.getPtrTy());
306
307 throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE
308 }
309
310 19473 llvm::BasicBlock *IRGenerator::createBlock(const std::string &blockName /*=""*/) const {
311
2/4
✓ Branch 1 taken 19473 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19473 times.
✗ Branch 5 not taken.
19473 return llvm::BasicBlock::Create(context, blockName);
312 }
313
314 19473 void IRGenerator::switchToBlock(llvm::BasicBlock *block, llvm::Function *parentFct /*=nullptr*/) {
315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19473 times.
19473 assert(block->getParent() == nullptr); // Ensure that the block was not added to a function already
316 // If no parent function were passed, use the current function
317
2/2
✓ Branch 0 taken 13126 times.
✓ Branch 1 taken 6347 times.
19473 if (!parentFct)
318 13126 parentFct = builder.GetInsertBlock()->getParent();
319 // Append block to current function
320 19473 parentFct->insert(parentFct->end(), block);
321 // Set insert point to the block
322 19473 builder.SetInsertPoint(block);
323 19473 blockAlreadyTerminated = false;
324 19473 }
325
326 5746 void IRGenerator::terminateBlock(const StmtLstNode *stmtLstNode) {
327 5746 diGenerator.setSourceLocation(stmtLstNode->closingBraceCodeLoc);
328 5746 generateScopeCleanup(stmtLstNode);
329 5746 blockAlreadyTerminated = true;
330 5746 }
331
332 7622 void IRGenerator::insertJump(llvm::BasicBlock *targetBlock) {
333
2/2
✓ Branch 0 taken 2441 times.
✓ Branch 1 taken 5181 times.
7622 if (blockAlreadyTerminated)
334 2441 return;
335 5181 builder.CreateBr(targetBlock);
336 5181 blockAlreadyTerminated = true;
337 }
338
339 5243 void IRGenerator::insertCondJump(llvm::Value *condition, llvm::BasicBlock *trueBlock, llvm::BasicBlock *falseBlock,
340 Likeliness likeliness /*=UNSPECIFIED*/) {
341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5243 times.
5243 if (blockAlreadyTerminated)
342 return;
343 5243 llvm::BranchInst *jumpInst = builder.CreateCondBr(condition, trueBlock, falseBlock);
344 5243 blockAlreadyTerminated = true;
345
346
2/2
✓ Branch 0 taken 653 times.
✓ Branch 1 taken 4590 times.
5243 if (likeliness != UNSPECIFIED) {
347 653 const bool likely = likeliness == LIKELY;
348 653 llvm::Metadata *name = llvm::MDString::get(context, "branch_weights");
349
1/2
✓ Branch 0 taken 653 times.
✗ Branch 1 not taken.
653 llvm::Metadata *trueBranchWeight = llvm::ConstantAsMetadata::get(builder.getInt32(likely ? 2000 : 1));
350
1/2
✓ Branch 0 taken 653 times.
✗ Branch 1 not taken.
653 llvm::Metadata *falseBranchWeight = llvm::ConstantAsMetadata::get(builder.getInt32(likely ? 1 : 2000));
351
1/2
✓ Branch 2 taken 653 times.
✗ Branch 3 not taken.
653 const auto profMetadata = llvm::MDNode::get(context, {name, trueBranchWeight, falseBranchWeight});
352
2/4
✓ Branch 1 taken 653 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 653 times.
✗ Branch 5 not taken.
653 jumpInst->setMetadata("prof", profMetadata);
353 }
354 }
355
356 6347 void IRGenerator::verifyFunction(const llvm::Function *fct, const CodeLoc &codeLoc) const {
357 // Skip the verifying step if the verifier was disabled manually or debug info is emitted
358
3/4
✓ Branch 0 taken 6347 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
✓ Branch 3 taken 6214 times.
6347 if (cliOptions.disableVerifier || cliOptions.generateDebugInfo)
359 133 return;
360
361 // Verify function
362 6214 std::string output;
363
1/2
✓ Branch 1 taken 6214 times.
✗ Branch 2 not taken.
6214 llvm::raw_string_ostream oss(output);
364 if (llvm::verifyFunction(*fct, &oss)) // LCOV_EXCL_LINE
365 throw CompilerError(codeLoc, INVALID_FUNCTION, output); // LCOV_EXCL_LINE
366 6214 }
367
368 678 void IRGenerator::verifyModule(const CodeLoc &codeLoc) const {
369 // Skip the verifying step if the verifier was disabled manually or debug info is emitted
370
3/4
✓ Branch 0 taken 678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 665 times.
678 if (cliOptions.disableVerifier || cliOptions.generateDebugInfo)
371 13 return;
372
373 // Verify module
374 665 std::string output;
375
1/2
✓ Branch 1 taken 665 times.
✗ Branch 2 not taken.
665 llvm::raw_string_ostream oss(output);
376 if (llvm::verifyModule(*module, &oss)) // LCOV_EXCL_LINE
377 throw CompilerError(codeLoc, INVALID_MODULE, output); // LCOV_EXCL_LINE
378 665 }
379
380 3949 LLVMExprResult IRGenerator::doAssignment(const ASTNode *lhsNode, const ASTNode *rhsNode, const ASTNode *node) {
381 // Get entry of left side
382
2/4
✓ Branch 1 taken 3949 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3949 times.
✗ Branch 5 not taken.
3949 auto [value, constant, ptr, refPtr, entry, _] = std::any_cast<LLVMExprResult>(visit(lhsNode));
383
6/8
✓ Branch 0 taken 3418 times.
✓ Branch 1 taken 531 times.
✓ Branch 3 taken 3418 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3418 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 167 times.
✓ Branch 9 taken 3251 times.
3949 llvm::Value *lhsAddress = entry != nullptr && entry->getQualType().isRef() ? refPtr : ptr;
384
1/2
✓ Branch 1 taken 3949 times.
✗ Branch 2 not taken.
7898 return doAssignment(lhsAddress, entry, rhsNode, node);
385 }
386
387 9506 LLVMExprResult IRGenerator::doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, const ASTNode *rhsNode,
388 const ASTNode *node, bool isDecl) {
389 // Get symbol type of right side
390
1/2
✓ Branch 1 taken 9506 times.
✗ Branch 2 not taken.
9506 const QualType &rhsSType = rhsNode->getEvaluatedSymbolType(manIdx);
391
2/4
✓ Branch 1 taken 9506 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9506 times.
✗ Branch 5 not taken.
9506 auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode));
392
1/2
✓ Branch 1 taken 9506 times.
✗ Branch 2 not taken.
19012 return doAssignment(lhsAddress, lhsEntry, rhs, rhsSType, node, isDecl);
393 }
394
395 9596 LLVMExprResult IRGenerator::doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, LLVMExprResult &rhs,
396 const QualType &rhsSType, const ASTNode *node, bool isDecl) {
397 // Deduce some information about the assignment
398
4/4
✓ Branch 0 taken 9065 times.
✓ Branch 1 taken 531 times.
✓ Branch 4 taken 353 times.
✓ Branch 5 taken 8712 times.
9596 const bool isRefAssign = lhsEntry != nullptr && lhsEntry->getQualType().isRef();
399
8/10
✓ Branch 0 taken 9243 times.
✓ Branch 1 taken 353 times.
✓ Branch 3 taken 9243 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 9243 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1031 times.
✓ Branch 9 taken 8212 times.
✓ Branch 11 taken 120 times.
✓ Branch 12 taken 911 times.
9596 const bool needsCopy = !isRefAssign && rhsSType.removeReferenceWrapper().is(TY_STRUCT) && !rhs.isTemporary();
400
401
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 9243 times.
9596 if (isRefAssign) {
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 353 times.
353 assert(lhsEntry != nullptr);
403
2/2
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 167 times.
353 if (isDecl) { // Reference gets initially assigned
404 // Get address of right side
405 186 llvm::Value *rhsAddress = resolveAddress(rhs);
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186 times.
186 assert(rhsAddress != nullptr);
407
408 // Store lhs pointer to rhs
409
3/6
✓ Branch 1 taken 186 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 186 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 186 times.
✗ Branch 8 not taken.
186 llvm::Value *refAddress = insertAlloca(builder.getPtrTy());
410 186 lhsEntry->updateAddress(refAddress);
411 186 insertStore(rhsAddress, refAddress);
412
413 186 return LLVMExprResult{.value = rhsAddress, .ptr = refAddress, .entry = lhsEntry};
414 }
415
416 // Reference to reference assignment (only for struct fields that are not initialized yet)
417
8/8
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 115 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 114 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 114 times.
✓ Branch 9 taken 53 times.
167 if (rhsSType.isRef() && rhs.entry && lhsEntry->isField()) {
418 // Get address of right side
419 114 llvm::Value *referencedAddress = resolveAddress(rhs);
420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 assert(referencedAddress != nullptr);
421
422 // Store the rhs* to the lhs**
423 114 insertStore(referencedAddress, lhsAddress);
424
425 114 return LLVMExprResult{.value = referencedAddress, .ptr = lhsAddress, .entry = lhsEntry};
426 }
427
428 // Load referenced address
429
3/6
✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 53 times.
✗ Branch 8 not taken.
106 lhsAddress = insertLoad(builder.getPtrTy(), lhsAddress);
430 }
431
432 // Check if we need to copy the rhs to the lhs. This happens for structs
433
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 9176 times.
9296 if (needsCopy) {
434 // Get address of right side
435
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 llvm::Value *rhsAddress = resolveAddress(rhs);
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 assert(rhsAddress != nullptr);
437
438 // Allocate new memory if the lhs address does not exist
439
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 118 times.
120 if (!lhsAddress) {
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(lhsEntry != nullptr);
441
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
2 lhsAddress = insertAlloca(lhsEntry->getQualType().toLLVMType(sourceFile));
442
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 lhsEntry->updateAddress(lhsAddress);
443 }
444
445 // Check if we have a copy ctor
446
2/4
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
120 const QualType rhsSTypeNonRef = rhsSType.removeReferenceWrapper().toNonConst();
447
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 Scope *structScope = rhsSTypeNonRef.getBodyScope();
448
2/4
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
360 const ArgList args = {{rhsSTypeNonRef.toConstRef(node), rhs.isTemporary()}};
449
2/4
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
120 const Function *copyCtor = FunctionManager::lookup(structScope, CTOR_FUNCTION_NAME, rhsSTypeNonRef, args, true);
450
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 78 times.
120 if (copyCtor != nullptr) {
451 // Call copy ctor
452
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
126 generateCtorOrDtorCall(lhsAddress, copyCtor, {rhsAddress});
453
2/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
78 } else if (rhsSTypeNonRef.isTriviallyCopyable(node)) {
454 // Create shallow copy
455
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 llvm::Type *rhsType = rhsSTypeNonRef.toLLVMType(sourceFile);
456
6/10
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 73 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 73 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
83 const std::string copyName = lhsEntry ? lhsEntry->name : "";
457
4/6
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
✓ Branch 5 taken 78 times.
✗ Branch 6 not taken.
78 generateShallowCopy(rhsAddress, rhsType, lhsAddress, lhsEntry && lhsEntry->isVolatile);
458 78 } else {
459 const std::string structName = rhsSTypeNonRef.getName();
460 const std::string msg = "Cannot copy struct '" + structName + "', as it is not trivially copyable and has no copy ctor";
461 throw SemanticError(node, COPY_CTOR_REQUIRED, msg);
462 }
463 120 return LLVMExprResult{.ptr = lhsAddress, .entry = lhsEntry};
464 120 }
465
466
7/8
✓ Branch 0 taken 5459 times.
✓ Branch 1 taken 3717 times.
✓ Branch 3 taken 771 times.
✓ Branch 4 taken 4688 times.
✓ Branch 6 taken 771 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 771 times.
✓ Branch 9 taken 8405 times.
9176 if (isDecl && rhsSType.is(TY_STRUCT) && rhs.isTemporary()) {
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 771 times.
771 assert(lhsEntry != nullptr);
468 // Directly set the address to the lhs entry
469 771 llvm::Value *rhsAddress = resolveAddress(rhs);
470 771 lhsEntry->updateAddress(rhsAddress);
471 771 rhs.entry = lhsEntry;
472 771 return rhs;
473 }
474
475 // Allocate new memory if the lhs address does not exist
476
2/2
✓ Branch 0 taken 4656 times.
✓ Branch 1 taken 3749 times.
8405 if (!lhsAddress) {
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4656 times.
4656 assert(lhsEntry != nullptr);
478
4/8
✓ Branch 1 taken 4656 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4656 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4656 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4656 times.
✗ Branch 11 not taken.
4656 lhsAddress = insertAlloca(lhsEntry->getQualType().toLLVMType(sourceFile));
479 4656 lhsEntry->updateAddress(lhsAddress);
480 }
481
482 // Check if we try to assign an array by value to a pointer. Here we have to store the address of the first element to the lhs
483
10/10
✓ Branch 0 taken 7895 times.
✓ Branch 1 taken 510 times.
✓ Branch 4 taken 1559 times.
✓ Branch 5 taken 6336 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 1554 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 8404 times.
8405 if (lhsEntry && lhsEntry->getQualType().isPtr() && rhsSType.isArray() && rhsSType.getArraySize() != ARRAY_SIZE_UNKNOWN) {
484 // Get address of right side
485
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 llvm::Value *rhsAddress = resolveAddress(rhs);
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(rhsAddress != nullptr);
487
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 llvm::Type *elementTy = rhsSType.toLLVMType(sourceFile);
488
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 llvm::Value *indices[2] = {builder.getInt64(0), builder.getInt32(0)};
489
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 llvm::Value *firstItemAddress = insertInBoundsGEP(elementTy, rhsAddress, indices);
490
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 insertStore(firstItemAddress, lhsAddress);
491 1 return LLVMExprResult{.value = rhsAddress, .ptr = lhsAddress, .entry = lhsEntry};
492 }
493
494 // We can load the value from the right side and store it to the left side
495 // Retrieve value of the right side
496 8404 llvm::Value *rhsValue = resolveValue(rhsSType, rhs);
497 // Store the value to the address
498 8404 insertStore(rhsValue, lhsAddress);
499 8404 return LLVMExprResult{.value = rhsValue, .ptr = lhsAddress, .entry = lhsEntry};
500 }
501
502 155 void IRGenerator::generateShallowCopy(llvm::Value *oldAddress, llvm::Type *varType, llvm::Value *targetAddress,
503 bool isVolatile) const {
504 // Retrieve size to copy
505
1/2
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
155 const llvm::TypeSize typeSize = module->getDataLayout().getTypeAllocSize(varType);
506
507 // Create values for memcpy intrinsic
508
2/4
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
155 llvm::Value *structSize = builder.getInt64(typeSize);
509
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
155 llvm::Value *copyVolatile = builder.getInt1(isVolatile);
510
511 // Call memcpy intrinsic to execute the shallow copy
512
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
155 llvm::Function *memcpyFct = stdFunctionManager.getMemcpyIntrinsic();
513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
155 assert(targetAddress != nullptr);
514
3/6
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 155 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 155 times.
✗ Branch 9 not taken.
155 builder.CreateCall(memcpyFct, {targetAddress, oldAddress, structSize, copyVolatile});
515 155 }
516
517 16278 void IRGenerator::autoDeReferencePtr(llvm::Value *&ptr, QualType &symbolType) const {
518
6/6
✓ Branch 1 taken 16892 times.
✓ Branch 2 taken 12388 times.
✓ Branch 4 taken 614 times.
✓ Branch 5 taken 16278 times.
✓ Branch 6 taken 13002 times.
✓ Branch 7 taken 16278 times.
29280 while (symbolType.isPtr() || symbolType.isRef()) {
519
3/6
✓ Branch 1 taken 13002 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13002 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13002 times.
✗ Branch 8 not taken.
13002 ptr = insertLoad(symbolType.toLLVMType(sourceFile), ptr);
520
1/2
✓ Branch 1 taken 13002 times.
✗ Branch 2 not taken.
13002 symbolType = symbolType.getContained();
521 }
522 16278 }
523
524 44 llvm::GlobalVariable *IRGenerator::createGlobalConst(const std::string &baseName, llvm::Constant *constant) const {
525 // Get unused name
526
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 const std::string globalName = getUnusedGlobalName(baseName);
527 // Create global
528
1/2
✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
44 module->getOrInsertGlobal(globalName, constant->getType());
529
1/2
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
44 llvm::GlobalVariable *global = module->getNamedGlobal(globalName);
530 // Set initializer to the given constant
531
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 global->setInitializer(constant);
532 44 global->setConstant(true);
533
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 global->setLinkage(llvm::GlobalValue::PrivateLinkage);
534 44 global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
535 44 return global;
536 44 }
537
538 1607 llvm::Constant *IRGenerator::createGlobalStringConst(const std::string &baseName, const std::string &value,
539 const CodeLoc &codeLoc) const {
540 // Get unused name
541
1/2
✓ Branch 1 taken 1607 times.
✗ Branch 2 not taken.
1607 const std::string globalName = getUnusedGlobalName(baseName);
542 // Create global
543
2/4
✓ Branch 1 taken 1607 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1607 times.
✗ Branch 6 not taken.
1607 llvm::Constant *globalAddr = builder.CreateGlobalStringPtr(value, globalName, 0, module);
544
1/2
✓ Branch 2 taken 1607 times.
✗ Branch 3 not taken.
1607 llvm::GlobalVariable *global = module->getNamedGlobal(globalName);
545 // Create debug info
546
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1593 times.
1607 if (cliOptions.generateDebugInfo)
547
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 diGenerator.generateGlobalStringDebugInfo(global, globalName, value.length(), codeLoc);
548 1607 return globalAddr;
549 1607 }
550
551 2652 std::string IRGenerator::getUnusedGlobalName(const std::string &baseName) const {
552 // Find an unused global name
553 2652 std::string globalName;
554 2652 unsigned int suffixNumber = 0;
555 do {
556
1/2
✓ Branch 2 taken 30701 times.
✗ Branch 3 not taken.
30701 globalName = baseName + std::to_string(suffixNumber);
557 30701 suffixNumber++;
558
3/4
✓ Branch 2 taken 30701 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28049 times.
✓ Branch 5 taken 2652 times.
30701 } while (module->getNamedGlobal(globalName) != nullptr);
559 2652 return globalName;
560 }
561
562 10123 void IRGenerator::materializeConstant(LLVMExprResult &exprResult) {
563 // Skip results, that do not contain a constant or already have a value
564
3/4
✓ Branch 0 taken 9763 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9763 times.
10123 if (exprResult.value != nullptr || exprResult.constant == nullptr)
565 360 return;
566
567 // Default case: the value to the constant
568 9763 exprResult.value = exprResult.constant;
569 }
570
571 709 std::string IRGenerator::getIRString(llvm::Module *llvmModule, bool withoutTargetData) {
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 709 times.
709 assert(llvmModule != nullptr); // Make sure the module hasn't been moved away
573
574 // Backup target triple and data layout
575
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 const std::string targetTriple = llvmModule->getTargetTriple();
576
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 const std::string targetDataLayout = llvmModule->getDataLayoutStr();
577 // Remove target triple and data layout
578
1/2
✓ Branch 0 taken 709 times.
✗ Branch 1 not taken.
709 if (withoutTargetData) {
579
2/4
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 709 times.
✗ Branch 5 not taken.
709 llvmModule->setTargetTriple("");
580
2/4
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 709 times.
✗ Branch 5 not taken.
709 llvmModule->setDataLayout("");
581 }
582
583 // Get IR string
584 709 std::string output;
585
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 llvm::raw_string_ostream oss(output);
586
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 llvmModule->print(oss, nullptr);
587
588 // Restore target triple and data layout
589
1/2
✓ Branch 0 taken 709 times.
✗ Branch 1 not taken.
709 if (withoutTargetData) {
590
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 llvmModule->setTargetTriple(targetTriple);
591
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 llvmModule->setDataLayout(targetDataLayout);
592 }
593
594 1418 return output;
595 709 }
596
597 /**
598 * Returns the operator function list for the current manifestation and the given node
599 *
600 * @param node Node to retrieve the op fct pointer list from
601 * @return Op fct pointer list
602 */
603 10595 const std::vector<const Function *> &IRGenerator::getOpFctPointers(const ASTNode *node) const {
604
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10595 times.
10595 assert(node->getOpFctPointers()->size() > manIdx);
605 10595 return node->getOpFctPointers()->at(manIdx);
606 }
607
608 } // namespace spice::compiler
609