| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2025 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "IRGenerator.h" | ||
| 4 | |||
| 5 | #include <llvm/IR/Module.h> | ||
| 6 | #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 | 908 | IRGenerator::IRGenerator(GlobalResourceManager &resourceManager, SourceFile *sourceFile) | |
| 16 | 908 | : CompilerPass(resourceManager, sourceFile), context(cliOptions.useLTO ? resourceManager.ltoContext : sourceFile->context), | |
| 17 |
1/2✓ Branch 8 → 9 taken 908 times.
✗ Branch 8 → 62 not taken.
|
908 | builder(sourceFile->builder), module(sourceFile->llvmModule.get()), conversionManager(sourceFile, this), |
| 18 |
6/10✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 906 times.
✓ Branch 9 → 10 taken 908 times.
✗ Branch 9 → 62 not taken.
✓ Branch 10 → 11 taken 908 times.
✗ Branch 10 → 62 not taken.
✓ Branch 11 → 12 taken 908 times.
✗ Branch 11 → 60 not taken.
✓ Branch 15 → 16 taken 908 times.
✗ Branch 15 → 56 not taken.
|
1816 | stdFunctionManager(sourceFile, resourceManager, module) { |
| 19 | // Attach information to the module | ||
| 20 |
1/2✓ Branch 17 → 18 taken 908 times.
✗ Branch 17 → 41 not taken.
|
908 | module->setTargetTriple(cliOptions.targetTriple); |
| 21 |
2/4✓ Branch 21 → 22 taken 908 times.
✗ Branch 21 → 44 not taken.
✓ Branch 22 → 23 taken 908 times.
✗ Branch 22 → 42 not taken.
|
908 | module->setDataLayout(sourceFile->targetMachine->createDataLayout()); |
| 22 |
1/2✓ Branch 24 → 25 taken 908 times.
✗ Branch 24 → 52 not taken.
|
908 | module->setPICLevel(llvm::PICLevel::BigPIC); |
| 23 |
1/2✓ Branch 25 → 26 taken 908 times.
✗ Branch 25 → 52 not taken.
|
908 | module->setPIELevel(llvm::PIELevel::Large); |
| 24 |
1/2✓ Branch 26 → 27 taken 908 times.
✗ Branch 26 → 52 not taken.
|
908 | module->setUwtable(llvm::UWTableKind::Default); |
| 25 |
1/2✓ Branch 27 → 28 taken 908 times.
✗ Branch 27 → 52 not taken.
|
908 | module->setFramePointer(llvm::FramePointerKind::All); |
| 26 | |||
| 27 | // Add module identifier metadata | ||
| 28 |
2/4✓ Branch 28 → 29 taken 908 times.
✗ Branch 28 → 45 not taken.
✓ Branch 29 → 30 taken 908 times.
✗ Branch 29 → 45 not taken.
|
908 | llvm::NamedMDNode *identifierMetadata = module->getOrInsertNamedMetadata("llvm.ident"); |
| 29 |
3/6✓ Branch 31 → 32 taken 908 times.
✗ Branch 31 → 46 not taken.
✓ Branch 33 → 34 taken 908 times.
✗ Branch 33 → 46 not taken.
✓ Branch 34 → 35 taken 908 times.
✗ Branch 34 → 46 not taken.
|
908 | identifierMetadata->addOperand(llvm::MDNode::get(context, llvm::MDString::get(context, PRODUCER_STRING))); |
| 30 | |||
| 31 | // Initialize debug info generator | ||
| 32 |
2/2✓ Branch 35 → 36 taken 19 times.
✓ Branch 35 → 40 taken 889 times.
|
908 | if (cliOptions.instrumentation.generateDebugInfo) |
| 33 |
2/4✓ Branch 36 → 37 taken 19 times.
✗ Branch 36 → 51 not taken.
✓ Branch 37 → 38 taken 19 times.
✗ Branch 37 → 49 not taken.
|
19 | diGenerator.initialize(sourceFile->fileName, sourceFile->fileDir); |
| 34 | 908 | } | |
| 35 | |||
| 36 | 908 | std::any IRGenerator::visitEntry(const EntryNode *node) { | |
| 37 | // Generate IR | ||
| 38 |
1/2✓ Branch 2 → 3 taken 908 times.
✗ Branch 2 → 19 not taken.
|
908 | visitChildren(node); |
| 39 | |||
| 40 | // Generate test main if required | ||
| 41 |
4/4✓ Branch 4 → 5 taken 242 times.
✓ Branch 4 → 7 taken 666 times.
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 7 taken 240 times.
|
908 | if (sourceFile->isMainFile && cliOptions.generateTestMain) |
| 42 | 2 | generateTestMain(); | |
| 43 | |||
| 44 | // Execute deferred VTable initializations | ||
| 45 |
2/2✓ Branch 13 → 9 taken 363 times.
✓ Branch 13 → 14 taken 908 times.
|
1271 | for (DeferredLogic &deferredVTableInit : deferredVTableInitializations) |
| 46 |
1/2✓ Branch 10 → 11 taken 363 times.
✗ Branch 10 → 20 not taken.
|
363 | deferredVTableInit.execute(); |
| 47 | |||
| 48 | // Finalize debug info generator | ||
| 49 | 908 | diGenerator.finalize(); | |
| 50 | |||
| 51 | // Verify module | ||
| 52 | 908 | verifyModule(node->codeLoc); | |
| 53 | |||
| 54 |
1/2✓ Branch 16 → 17 taken 908 times.
✗ Branch 16 → 21 not taken.
|
908 | return nullptr; |
| 55 | } | ||
| 56 | |||
| 57 | 33636 | llvm::AllocaInst *IRGenerator::insertAlloca(llvm::Type *llvmType, std::string varName) { | |
| 58 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 33636 times.
|
33636 | if (!cliOptions.namesForIRValues) |
| 59 | ✗ | varName = ""; | |
| 60 | |||
| 61 |
2/2✓ Branch 4 → 5 taken 23514 times.
✓ Branch 4 → 12 taken 10122 times.
|
33636 | if (allocaInsertInst != nullptr) { // If there is already an alloca inst, insert right after that |
| 62 |
2/4✓ Branch 5 → 6 taken 23514 times.
✗ Branch 5 → 29 not taken.
✓ Branch 6 → 7 taken 23514 times.
✗ Branch 6 → 29 not taken.
|
23514 | llvm::AllocaInst *allocaInst = builder.CreateAlloca(llvmType, nullptr, varName); |
| 63 |
1/2✓ Branch 8 → 9 taken 23514 times.
✗ Branch 8 → 30 not taken.
|
23514 | allocaInst->setDebugLoc(llvm::DebugLoc()); |
| 64 | 23514 | allocaInst->moveAfter(allocaInsertInst); | |
| 65 | 23514 | allocaInsertInst = allocaInst; | |
| 66 | } else { // This is the first alloca inst in the current function -> insert at the entry block | ||
| 67 | // Save current basic block and move insert cursor to entry block of the current function | ||
| 68 | 10122 | llvm::BasicBlock *currentBlock = builder.GetInsertBlock(); | |
| 69 | 10122 | builder.SetInsertPoint(allocaInsertBlock, allocaInsertBlock->begin()); | |
| 70 | |||
| 71 | // Allocate the size of the given LLVM type | ||
| 72 |
2/4✓ Branch 15 → 16 taken 10122 times.
✗ Branch 15 → 33 not taken.
✓ Branch 16 → 17 taken 10122 times.
✗ Branch 16 → 33 not taken.
|
10122 | allocaInsertInst = builder.CreateAlloca(llvmType, nullptr, varName); |
| 73 |
1/2✓ Branch 18 → 19 taken 10122 times.
✗ Branch 18 → 34 not taken.
|
10122 | allocaInsertInst->setDebugLoc(llvm::DebugLoc()); |
| 74 | |||
| 75 | // Restore old basic block | ||
| 76 | 10122 | builder.SetInsertPoint(currentBlock); | |
| 77 | } | ||
| 78 | |||
| 79 | // Insert lifetime start marker | ||
| 80 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 27 taken 33636 times.
|
33636 | if (cliOptions.useLifetimeMarkers) { |
| 81 | ✗ | const uint64_t sizeInBytes = module->getDataLayout().getTypeAllocSize(llvmType); | |
| 82 | ✗ | builder.CreateLifetimeStart(allocaInsertInst, builder.getInt64(sizeInBytes)); | |
| 83 | } | ||
| 84 | |||
| 85 | 33636 | return allocaInsertInst; | |
| 86 | } | ||
| 87 | |||
| 88 | 29407 | llvm::AllocaInst *IRGenerator::insertAlloca(const QualType &qualType, const std::string &varName) { | |
| 89 | 29407 | llvm::Type *llvmType = qualType.toLLVMType(sourceFile); | |
| 90 |
2/4✓ Branch 3 → 4 taken 29407 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 29407 times.
✗ Branch 4 → 10 not taken.
|
29407 | llvm::AllocaInst *alloca = insertAlloca(llvmType, varName); |
| 91 | |||
| 92 | // Insert type metadata | ||
| 93 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 29407 times.
|
29407 | if (cliOptions.useTBAAMetadata) |
| 94 | ✗ | mdGenerator.generateTypeMetadata(allocaInsertInst, qualType); | |
| 95 | |||
| 96 | 29407 | return alloca; | |
| 97 | } | ||
| 98 | |||
| 99 | 67390 | llvm::LoadInst *IRGenerator::insertLoad(llvm::Type *llvmType, llvm::Value *ptr, bool isVolatile, | |
| 100 | const std::string &varName) const { | ||
| 101 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 67390 times.
|
67390 | assert(ptr->getType()->isPointerTy()); |
| 102 |
5/14✓ Branch 6 → 7 taken 67390 times.
✗ Branch 6 → 8 not taken.
✓ Branch 7 → 11 taken 67390 times.
✗ Branch 7 → 22 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 22 not taken.
✓ Branch 11 → 12 taken 67390 times.
✗ Branch 11 → 20 not taken.
✓ Branch 12 → 13 taken 67390 times.
✗ Branch 12 → 20 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 18 taken 67390 times.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 25 not taken.
|
67390 | return builder.CreateLoad(llvmType, ptr, isVolatile, cliOptions.namesForIRValues ? varName : ""); |
| 103 | } | ||
| 104 | |||
| 105 | 60588 | llvm::LoadInst *IRGenerator::insertLoad(const QualType &qualType, llvm::Value *ptr, bool isVolatile, const std::string &varName) { | |
| 106 | 60588 | llvm::Type *llvmType = qualType.toLLVMType(sourceFile); | |
| 107 | 60588 | llvm::LoadInst *load = insertLoad(llvmType, ptr, isVolatile, varName); | |
| 108 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 60588 times.
|
60588 | if (cliOptions.useTBAAMetadata) |
| 109 | ✗ | mdGenerator.generateTBAAMetadata(load, qualType); | |
| 110 | 60588 | return load; | |
| 111 | } | ||
| 112 | |||
| 113 | 34858 | llvm::StoreInst *IRGenerator::insertStore(llvm::Value *val, llvm::Value *ptr, bool isVolatile) const { | |
| 114 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 34858 times.
|
34858 | assert(ptr->getType()->isPointerTy()); |
| 115 | 34858 | return builder.CreateStore(val, ptr, isVolatile); | |
| 116 | } | ||
| 117 | |||
| 118 | 11364 | void IRGenerator::insertStore(llvm::Value *val, llvm::Value *ptr, const QualType &qualType, bool isVolatile) { | |
| 119 | 11364 | llvm::StoreInst *store = insertStore(val, ptr, isVolatile); | |
| 120 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11364 times.
|
11364 | if (cliOptions.useTBAAMetadata) |
| 121 | ✗ | mdGenerator.generateTBAAMetadata(store, qualType); | |
| 122 | 11364 | } | |
| 123 | |||
| 124 | 18099 | llvm::Value *IRGenerator::insertInBoundsGEP(llvm::Type *type, llvm::Value *basePtr, llvm::ArrayRef<llvm::Value *> indices, | |
| 125 | std::string varName) const { | ||
| 126 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 18099 times.
|
18099 | assert(basePtr->getType()->isPointerTy()); |
| 127 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 18099 times.
|
18099 | assert(!indices.empty()); |
| 128 |
4/6✓ Branch 4 → 5 taken 17790 times.
✓ Branch 4 → 7 taken 15846 times.
✓ Branch 6 → 7 taken 17790 times.
✗ Branch 6 → 8 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 18099 times.
|
51735 | assert(std::ranges::all_of(indices, [](const llvm::Value *index) { |
| 129 | const llvm::Type *indexType = index->getType(); | ||
| 130 | return indexType->isIntegerTy(32) || indexType->isIntegerTy(64); | ||
| 131 | })); | ||
| 132 | |||
| 133 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 18099 times.
|
18099 | if (!cliOptions.namesForIRValues) |
| 134 | ✗ | varName = ""; | |
| 135 | |||
| 136 | // Insert GEP | ||
| 137 |
2/4✓ Branch 14 → 15 taken 18099 times.
✗ Branch 14 → 19 not taken.
✓ Branch 15 → 16 taken 18099 times.
✗ Branch 15 → 19 not taken.
|
18099 | return builder.CreateInBoundsGEP(type, basePtr, indices, varName); |
| 138 | } | ||
| 139 | |||
| 140 | 5251 | llvm::Value *IRGenerator::insertStructGEP(llvm::Type *type, llvm::Value *basePtr, unsigned int index, std::string varName) const { | |
| 141 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 5251 times.
|
5251 | assert(basePtr->getType()->isPointerTy()); |
| 142 | |||
| 143 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 5251 times.
|
5251 | if (!cliOptions.namesForIRValues) |
| 144 | ✗ | varName = ""; | |
| 145 | |||
| 146 | // If we use index 0 we can use the base pointer directly | ||
| 147 |
2/2✓ Branch 8 → 9 taken 1834 times.
✓ Branch 8 → 10 taken 3417 times.
|
5251 | if (index == 0) |
| 148 | 1834 | return basePtr; | |
| 149 | |||
| 150 | // Insert GEP | ||
| 151 |
2/4✓ Branch 10 → 11 taken 3417 times.
✗ Branch 10 → 15 not taken.
✓ Branch 11 → 12 taken 3417 times.
✗ Branch 11 → 15 not taken.
|
3417 | return builder.CreateStructGEP(type, basePtr, index, varName); |
| 152 | } | ||
| 153 | |||
| 154 | 38449 | llvm::Value *IRGenerator::resolveValue(const ExprNode *node) { | |
| 155 | // Visit the given AST node | ||
| 156 |
2/4✓ Branch 2 → 3 taken 38449 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 38449 times.
✗ Branch 3 → 9 not taken.
|
38449 | auto exprResult = any_cast<LLVMExprResult>(visit(node)); |
| 157 |
1/2✓ Branch 5 → 6 taken 38449 times.
✗ Branch 5 → 12 not taken.
|
76898 | return resolveValue(node, exprResult); |
| 158 | } | ||
| 159 | |||
| 160 | 44449 | llvm::Value *IRGenerator::resolveValue(const ExprNode *node, LLVMExprResult &exprResult) { | |
| 161 | 44449 | return resolveValue(node->getEvaluatedSymbolType(manIdx), exprResult); | |
| 162 | } | ||
| 163 | |||
| 164 | 87746 | llvm::Value *IRGenerator::resolveValue(const QualType &qualType, LLVMExprResult &exprResult) { | |
| 165 | // Check if the value is already present | ||
| 166 |
2/2✓ Branch 2 → 3 taken 29054 times.
✓ Branch 2 → 4 taken 58692 times.
|
87746 | if (exprResult.value != nullptr) |
| 167 | 29054 | return exprResult.value; | |
| 168 | |||
| 169 | // Check if a constant is present | ||
| 170 |
2/2✓ Branch 4 → 5 taken 15104 times.
✓ Branch 4 → 7 taken 43588 times.
|
58692 | if (exprResult.constant != nullptr) { |
| 171 | 15104 | materializeConstant(exprResult); | |
| 172 | 15104 | return exprResult.value; | |
| 173 | } | ||
| 174 | |||
| 175 |
3/4✓ Branch 7 → 8 taken 538 times.
✓ Branch 7 → 10 taken 43050 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 538 times.
|
43588 | assert(exprResult.ptr != nullptr || exprResult.refPtr != nullptr); |
| 176 | |||
| 177 | // De-reference if reference type | ||
| 178 |
4/4✓ Branch 10 → 11 taken 40179 times.
✓ Branch 10 → 13 taken 3409 times.
✓ Branch 11 → 12 taken 10 times.
✓ Branch 11 → 13 taken 40169 times.
|
43588 | const bool isVolatile = exprResult.entry && exprResult.entry->isVolatile; |
| 179 |
4/4✓ Branch 14 → 15 taken 542 times.
✓ Branch 14 → 24 taken 43046 times.
✓ Branch 15 → 16 taken 538 times.
✓ Branch 15 → 24 taken 4 times.
|
43588 | if (exprResult.refPtr != nullptr && exprResult.ptr == nullptr) |
| 180 |
3/6✓ Branch 18 → 19 taken 538 times.
✗ Branch 18 → 36 not taken.
✓ Branch 19 → 20 taken 538 times.
✗ Branch 19 → 34 not taken.
✓ Branch 20 → 21 taken 538 times.
✗ Branch 20 → 34 not taken.
|
1076 | exprResult.ptr = insertLoad(builder.getPtrTy(), exprResult.refPtr, isVolatile); |
| 181 | |||
| 182 | // Load the value from the pointer | ||
| 183 |
1/2✓ Branch 24 → 25 taken 43588 times.
✗ Branch 24 → 46 not taken.
|
43588 | const QualType referencedType = qualType.removeReferenceWrapper(); |
| 184 |
2/4✓ Branch 27 → 28 taken 43588 times.
✗ Branch 27 → 42 not taken.
✓ Branch 28 → 29 taken 43588 times.
✗ Branch 28 → 40 not taken.
|
43588 | exprResult.value = insertLoad(referencedType, exprResult.ptr, isVolatile); |
| 185 | |||
| 186 | 43588 | return exprResult.value; | |
| 187 | } | ||
| 188 | |||
| 189 | 2849 | llvm::Value *IRGenerator::resolveAddress(const ASTNode *node) { | |
| 190 | // Visit the given AST node | ||
| 191 |
2/4✓ Branch 2 → 3 taken 2849 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 2849 times.
✗ Branch 3 → 9 not taken.
|
2849 | auto exprResult = any_cast<LLVMExprResult>(visit(node)); |
| 192 |
1/2✓ Branch 5 → 6 taken 2849 times.
✗ Branch 5 → 12 not taken.
|
5698 | return resolveAddress(exprResult); |
| 193 | } | ||
| 194 | |||
| 195 | 20759 | llvm::Value *IRGenerator::resolveAddress(LLVMExprResult &exprResult) { | |
| 196 | // Check if an address is already present | ||
| 197 |
2/2✓ Branch 2 → 3 taken 17373 times.
✓ Branch 2 → 4 taken 3386 times.
|
20759 | if (exprResult.ptr != nullptr) |
| 198 | 17373 | return exprResult.ptr; | |
| 199 | |||
| 200 | // Check if the reference address is already present | ||
| 201 |
3/4✓ Branch 4 → 5 taken 2643 times.
✓ Branch 4 → 7 taken 743 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 2643 times.
|
3386 | const bool isVolatile = exprResult.entry && exprResult.entry->isVolatile; |
| 202 |
3/4✓ Branch 8 → 9 taken 2642 times.
✓ Branch 8 → 18 taken 744 times.
✓ Branch 9 → 10 taken 2642 times.
✗ Branch 9 → 18 not taken.
|
3386 | if (exprResult.refPtr != nullptr && exprResult.ptr == nullptr) { |
| 203 |
3/6✓ Branch 12 → 13 taken 2642 times.
✗ Branch 12 → 37 not taken.
✓ Branch 13 → 14 taken 2642 times.
✗ Branch 13 → 35 not taken.
✓ Branch 14 → 15 taken 2642 times.
✗ Branch 14 → 35 not taken.
|
2642 | exprResult.ptr = insertLoad(builder.getPtrTy(), exprResult.refPtr, isVolatile); |
| 204 | 2642 | return exprResult.ptr; | |
| 205 | } | ||
| 206 | |||
| 207 | // If not, store the value or constant | ||
| 208 | 744 | materializeConstant(exprResult); | |
| 209 |
1/2✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 744 times.
|
744 | assert(exprResult.value != nullptr); |
| 210 |
7/12✓ Branch 21 → 22 taken 6 times.
✓ Branch 21 → 23 taken 738 times.
✓ Branch 22 → 26 taken 6 times.
✗ Branch 22 → 43 not taken.
✓ Branch 25 → 26 taken 738 times.
✗ Branch 25 → 43 not taken.
✓ Branch 27 → 28 taken 744 times.
✗ Branch 27 → 41 not taken.
✓ Branch 29 → 30 taken 738 times.
✓ Branch 29 → 32 taken 6 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 46 not taken.
|
1482 | exprResult.ptr = insertAlloca(exprResult.value->getType(), exprResult.entry ? exprResult.entry->name : ""); |
| 211 | 744 | insertStore(exprResult.value, exprResult.ptr, isVolatile); | |
| 212 | |||
| 213 | 744 | return exprResult.ptr; | |
| 214 | } | ||
| 215 | |||
| 216 | 2462 | llvm::Constant *IRGenerator::getDefaultValueForSymbolType(const QualType &symbolType) { // NOLINT(misc-no-recursion) | |
| 217 | // Double | ||
| 218 |
2/2✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 9 taken 2458 times.
|
2462 | if (symbolType.is(TY_DOUBLE)) |
| 219 |
2/4✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 132 not taken.
✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 130 not taken.
|
4 | return llvm::ConstantFP::get(context, llvm::APFloat(0.0)); |
| 220 | |||
| 221 | // Int | ||
| 222 |
2/2✓ Branch 10 → 11 taken 335 times.
✓ Branch 10 → 13 taken 2123 times.
|
2458 | if (symbolType.is(TY_INT)) |
| 223 | 335 | return builder.getInt32(0); | |
| 224 | |||
| 225 | // Short | ||
| 226 |
2/2✓ Branch 14 → 15 taken 12 times.
✓ Branch 14 → 17 taken 2111 times.
|
2123 | if (symbolType.is(TY_SHORT)) |
| 227 | 12 | return builder.getInt16(0); | |
| 228 | |||
| 229 | // Long | ||
| 230 |
2/2✓ Branch 18 → 19 taken 908 times.
✓ Branch 18 → 21 taken 1203 times.
|
2111 | if (symbolType.is(TY_LONG)) |
| 231 | 908 | return builder.getInt64(0); | |
| 232 | |||
| 233 | // Byte or char | ||
| 234 |
3/4✓ Branch 21 → 22 taken 1203 times.
✗ Branch 21 → 133 not taken.
✓ Branch 22 → 23 taken 20 times.
✓ Branch 22 → 25 taken 1183 times.
|
1203 | if (symbolType.isOneOf({TY_BYTE, TY_CHAR})) |
| 235 | 20 | return builder.getInt8(0); | |
| 236 | |||
| 237 | // String | ||
| 238 |
2/2✓ Branch 26 → 27 taken 359 times.
✓ Branch 26 → 35 taken 824 times.
|
1183 | if (symbolType.is(TY_STRING)) { |
| 239 |
3/6✓ Branch 27 → 28 taken 359 times.
✗ Branch 27 → 135 not taken.
✓ Branch 28 → 29 taken 359 times.
✗ Branch 28 → 134 not taken.
✓ Branch 29 → 30 taken 359 times.
✗ Branch 29 → 134 not taken.
|
359 | llvm::GlobalVariable *globalString = builder.CreateGlobalString("", ""); |
| 240 |
1/2✓ Branch 30 → 31 taken 359 times.
✗ Branch 30 → 34 not taken.
|
359 | if (cliOptions.comparableOutput) |
| 241 |
2/4✓ Branch 31 → 32 taken 359 times.
✗ Branch 31 → 136 not taken.
✓ Branch 32 → 33 taken 359 times.
✗ Branch 32 → 136 not taken.
|
359 | globalString->setAlignment(llvm::Align(4)); |
| 242 | 359 | return globalString; | |
| 243 | } | ||
| 244 | |||
| 245 | // Bool | ||
| 246 |
2/2✓ Branch 36 → 37 taken 33 times.
✓ Branch 36 → 39 taken 791 times.
|
824 | if (symbolType.is(TY_BOOL)) |
| 247 | 33 | return builder.getFalse(); | |
| 248 | |||
| 249 | // Pointer or reference | ||
| 250 |
3/4✓ Branch 39 → 40 taken 791 times.
✗ Branch 39 → 137 not taken.
✓ Branch 40 → 41 taken 730 times.
✓ Branch 40 → 44 taken 61 times.
|
791 | if (symbolType.isOneOf({TY_PTR, TY_REF})) |
| 251 | 730 | return llvm::Constant::getNullValue(builder.getPtrTy()); | |
| 252 | |||
| 253 | // Array | ||
| 254 |
2/2✓ Branch 45 → 46 taken 15 times.
✓ Branch 45 → 61 taken 46 times.
|
61 | if (symbolType.isArray()) { |
| 255 | // Get array size | ||
| 256 |
1/2✓ Branch 46 → 47 taken 15 times.
✗ Branch 46 → 146 not taken.
|
15 | const size_t arraySize = symbolType.getArraySize(); |
| 257 | |||
| 258 | // Get default value for item | ||
| 259 |
2/4✓ Branch 47 → 48 taken 15 times.
✗ Branch 47 → 138 not taken.
✓ Branch 48 → 49 taken 15 times.
✗ Branch 48 → 138 not taken.
|
15 | llvm::Constant *defaultItemValue = getDefaultValueForSymbolType(symbolType.getContained()); |
| 260 | |||
| 261 | // Retrieve array and item type | ||
| 262 |
2/4✓ Branch 49 → 50 taken 15 times.
✗ Branch 49 → 139 not taken.
✓ Branch 50 → 51 taken 15 times.
✗ Branch 50 → 139 not taken.
|
15 | llvm::Type *itemType = symbolType.getContained().toLLVMType(sourceFile); |
| 263 |
1/2✓ Branch 51 → 52 taken 15 times.
✗ Branch 51 → 146 not taken.
|
15 | llvm::ArrayType *arrayType = llvm::ArrayType::get(itemType, arraySize); |
| 264 | |||
| 265 | // Create a constant array with n times the default value | ||
| 266 |
1/2✓ Branch 54 → 55 taken 15 times.
✗ Branch 54 → 140 not taken.
|
15 | const std::vector itemConstants(arraySize, defaultItemValue); |
| 267 |
1/2✓ Branch 57 → 58 taken 15 times.
✗ Branch 57 → 143 not taken.
|
15 | return llvm::ConstantArray::get(arrayType, itemConstants); |
| 268 | 15 | } | |
| 269 | |||
| 270 | // Function or procedure | ||
| 271 |
3/4✓ Branch 61 → 62 taken 46 times.
✗ Branch 61 → 147 not taken.
✓ Branch 62 → 63 taken 16 times.
✓ Branch 62 → 75 taken 30 times.
|
46 | if (symbolType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
| 272 |
2/2✓ Branch 63 → 64 taken 9 times.
✓ Branch 63 → 69 taken 7 times.
|
16 | if (!llvmTypes.fatPtrType) |
| 273 |
3/6✓ Branch 64 → 65 taken 9 times.
✗ Branch 64 → 148 not taken.
✓ Branch 65 → 66 taken 9 times.
✗ Branch 65 → 148 not taken.
✓ Branch 67 → 68 taken 9 times.
✗ Branch 67 → 148 not taken.
|
9 | llvmTypes.fatPtrType = llvm::StructType::get(context, {builder.getPtrTy(), builder.getPtrTy()}); |
| 274 | |||
| 275 |
2/4✓ Branch 69 → 70 taken 16 times.
✗ Branch 69 → 150 not taken.
✓ Branch 70 → 71 taken 16 times.
✗ Branch 70 → 150 not taken.
|
16 | llvm::Constant *ptrDefaultValue = getDefaultValueForSymbolType(QualType(TY_PTR)); |
| 276 |
1/2✓ Branch 72 → 73 taken 16 times.
✗ Branch 72 → 151 not taken.
|
16 | return llvm::ConstantStruct::get(llvmTypes.fatPtrType, {ptrDefaultValue, ptrDefaultValue}); |
| 277 | } | ||
| 278 | |||
| 279 | // Struct | ||
| 280 |
2/2✓ Branch 76 → 77 taken 29 times.
✓ Branch 76 → 114 taken 1 time.
|
30 | if (symbolType.is(TY_STRUCT)) { |
| 281 | // Retrieve field count | ||
| 282 |
1/2✓ Branch 77 → 78 taken 29 times.
✗ Branch 77 → 158 not taken.
|
29 | Scope *structScope = symbolType.getBodyScope(); |
| 283 |
1/2✗ Branch 78 → 79 not taken.
✓ Branch 78 → 80 taken 29 times.
|
29 | assert(structScope != nullptr); |
| 284 |
1/2✓ Branch 80 → 81 taken 29 times.
✗ Branch 80 → 158 not taken.
|
29 | const size_t fieldCount = structScope->getFieldCount(); |
| 285 | |||
| 286 | // Get default values for all fields of the struct | ||
| 287 | 29 | std::vector<llvm::Constant *> fieldConstants; | |
| 288 |
1/2✓ Branch 81 → 82 taken 29 times.
✗ Branch 81 → 156 not taken.
|
29 | fieldConstants.reserve(fieldCount); |
| 289 | |||
| 290 | // Add default value for each struct field | ||
| 291 |
2/2✓ Branch 107 → 83 taken 66 times.
✓ Branch 107 → 108 taken 29 times.
|
95 | for (size_t i = 0; i < fieldCount; i++) { |
| 292 | // Get entry of the field | ||
| 293 |
1/2✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 66 times.
|
66 | const SymbolTableEntry *fieldEntry = structScope->lookupField(i); |
| 294 |
3/6✓ Branch 88 → 89 taken 66 times.
✗ Branch 88 → 92 not taken.
✓ Branch 89 → 90 taken 66 times.
✗ Branch 89 → 154 not taken.
✓ Branch 90 → 91 taken 66 times.
✗ Branch 90 → 92 not taken.
|
66 | assert(fieldEntry != nullptr && fieldEntry->isField()); |
| 295 | |||
| 296 | // Retrieve default field value | ||
| 297 | llvm::Constant *defaultFieldValue; | ||
| 298 |
4/6✓ Branch 93 → 94 taken 66 times.
✗ Branch 93 → 95 not taken.
✓ Branch 96 → 97 taken 66 times.
✗ Branch 96 → 102 not taken.
✓ Branch 97 → 98 taken 5 times.
✓ Branch 97 → 102 taken 61 times.
|
66 | if (const auto fieldNode = dynamic_cast<FieldNode *>(fieldEntry->declNode); fieldNode && fieldNode->defaultValue) |
| 299 |
3/6✓ Branch 98 → 99 taken 5 times.
✗ Branch 98 → 154 not taken.
✓ Branch 99 → 100 taken 5 times.
✗ Branch 99 → 153 not taken.
✓ Branch 100 → 101 taken 5 times.
✗ Branch 100 → 153 not taken.
|
5 | defaultFieldValue = getConst(fieldNode->defaultValue->getCompileTimeValue(), fieldEntry->getQualType(), fieldNode); |
| 300 | else | ||
| 301 |
2/4✓ Branch 102 → 103 taken 61 times.
✗ Branch 102 → 154 not taken.
✓ Branch 103 → 104 taken 61 times.
✗ Branch 103 → 154 not taken.
|
61 | defaultFieldValue = getDefaultValueForSymbolType(fieldEntry->getQualType()); |
| 302 | |||
| 303 |
1/2✓ Branch 105 → 106 taken 66 times.
✗ Branch 105 → 154 not taken.
|
66 | fieldConstants.push_back(defaultFieldValue); |
| 304 | } | ||
| 305 | |||
| 306 |
1/2✓ Branch 108 → 109 taken 29 times.
✗ Branch 108 → 156 not taken.
|
29 | const auto structType = reinterpret_cast<llvm::StructType *>(symbolType.toLLVMType(sourceFile)); |
| 307 |
1/2✓ Branch 110 → 111 taken 29 times.
✗ Branch 110 → 155 not taken.
|
29 | return llvm::ConstantStruct::get(structType, fieldConstants); |
| 308 | 29 | } | |
| 309 | |||
| 310 | // Interface | ||
| 311 |
1/2✓ Branch 115 → 116 taken 1 time.
✗ Branch 115 → 121 not taken.
|
1 | if (symbolType.is(TY_INTERFACE)) { |
| 312 | 1 | const auto structType = reinterpret_cast<llvm::StructType *>(symbolType.toLLVMType(sourceFile)); | |
| 313 | 1 | return llvm::ConstantStruct::get(structType, llvm::Constant::getNullValue(builder.getPtrTy())); | |
| 314 | } | ||
| 315 | |||
| 316 | − | throw CompilerError(INTERNAL_ERROR, "Cannot determine default value for symbol type"); // GCOV_EXCL_LINE | |
| 317 | } | ||
| 318 | |||
| 319 | 15271 | llvm::Constant *IRGenerator::getConst(const CompileTimeValue &compileTimeValue, const QualType &type, const ASTNode *node) const { | |
| 320 |
2/2✓ Branch 3 → 4 taken 383 times.
✓ Branch 3 → 9 taken 14888 times.
|
15271 | if (type.is(TY_DOUBLE)) |
| 321 |
2/4✓ Branch 4 → 5 taken 383 times.
✗ Branch 4 → 56 not taken.
✓ Branch 5 → 6 taken 383 times.
✗ Branch 5 → 54 not taken.
|
383 | return llvm::ConstantFP::get(context, llvm::APFloat(compileTimeValue.doubleValue)); |
| 322 | |||
| 323 |
2/2✓ Branch 10 → 11 taken 3080 times.
✓ Branch 10 → 13 taken 11808 times.
|
14888 | if (type.is(TY_INT)) |
| 324 | 3080 | return builder.getInt32(compileTimeValue.intValue); | |
| 325 | |||
| 326 |
2/2✓ Branch 14 → 15 taken 576 times.
✓ Branch 14 → 17 taken 11232 times.
|
11808 | if (type.is(TY_SHORT)) |
| 327 | 576 | return builder.getInt16(compileTimeValue.shortValue); | |
| 328 | |||
| 329 |
2/2✓ Branch 18 → 19 taken 5619 times.
✓ Branch 18 → 21 taken 5613 times.
|
11232 | if (type.is(TY_LONG)) |
| 330 | 5619 | return builder.getInt64(compileTimeValue.longValue); | |
| 331 | |||
| 332 |
3/4✓ Branch 21 → 22 taken 5613 times.
✗ Branch 21 → 57 not taken.
✓ Branch 22 → 23 taken 2254 times.
✓ Branch 22 → 25 taken 3359 times.
|
5613 | if (type.isOneOf({TY_BYTE, TY_CHAR})) |
| 333 | 2254 | return builder.getInt8(compileTimeValue.charValue); | |
| 334 | |||
| 335 |
2/2✓ Branch 26 → 27 taken 2025 times.
✓ Branch 26 → 36 taken 1334 times.
|
3359 | if (type.is(TY_STRING)) { |
| 336 | 2025 | const std::string &stringValue = resourceManager.compileTimeStringValues.at(compileTimeValue.stringValueOffset); | |
| 337 |
2/4✓ Branch 30 → 31 taken 2025 times.
✗ Branch 30 → 60 not taken.
✓ Branch 31 → 32 taken 2025 times.
✗ Branch 31 → 58 not taken.
|
6075 | return createGlobalStringConst(ANON_GLOBAL_STRING_NAME, stringValue, node->codeLoc); |
| 338 | } | ||
| 339 | |||
| 340 |
1/2✓ Branch 37 → 38 taken 1334 times.
✗ Branch 37 → 40 not taken.
|
1334 | if (type.is(TY_BOOL)) |
| 341 | 1334 | return builder.getInt1(compileTimeValue.boolValue); | |
| 342 | |||
| 343 | ✗ | if (type.is(TY_PTR)) | |
| 344 | ✗ | return llvm::Constant::getNullValue(builder.getPtrTy()); | |
| 345 | |||
| 346 | − | throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE | |
| 347 | } | ||
| 348 | |||
| 349 | 30543 | llvm::BasicBlock *IRGenerator::createBlock(const std::string &blockName /*=""*/) const { | |
| 350 |
2/4✓ Branch 2 → 3 taken 30543 times.
✗ Branch 2 → 7 not taken.
✓ Branch 3 → 4 taken 30543 times.
✗ Branch 3 → 7 not taken.
|
30543 | return llvm::BasicBlock::Create(context, blockName); |
| 351 | } | ||
| 352 | |||
| 353 | 30543 | void IRGenerator::switchToBlock(llvm::BasicBlock *block, llvm::Function *parentFct /*=nullptr*/) { | |
| 354 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30543 times.
|
30543 | assert(block->getParent() == nullptr); // Ensure that the block was not added to a function already |
| 355 | // If no parent function were passed, use the current function | ||
| 356 |
2/2✓ Branch 5 → 6 taken 20383 times.
✓ Branch 5 → 8 taken 10160 times.
|
30543 | if (!parentFct) |
| 357 | 20383 | parentFct = builder.GetInsertBlock()->getParent(); | |
| 358 | // Append block to current function | ||
| 359 | 30543 | parentFct->insert(parentFct->end(), block); | |
| 360 | // Set insert point to the block | ||
| 361 | 30543 | builder.SetInsertPoint(block); | |
| 362 | 30543 | blockAlreadyTerminated = false; | |
| 363 | 30543 | } | |
| 364 | |||
| 365 | 9565 | void IRGenerator::terminateBlock(const StmtLstNode *stmtLstNode) { | |
| 366 | 9565 | diGenerator.setSourceLocation(stmtLstNode->closingBraceCodeLoc); | |
| 367 | 9565 | generateScopeCleanup(stmtLstNode); | |
| 368 | 9565 | blockAlreadyTerminated = true; | |
| 369 | 9565 | } | |
| 370 | |||
| 371 | 11648 | void IRGenerator::insertJump(llvm::BasicBlock *targetBlock) { | |
| 372 |
2/2✓ Branch 2 → 3 taken 3342 times.
✓ Branch 2 → 4 taken 8306 times.
|
11648 | if (blockAlreadyTerminated) |
| 373 | 3342 | return; | |
| 374 | 8306 | builder.CreateBr(targetBlock); | |
| 375 | 8306 | blockAlreadyTerminated = true; | |
| 376 | } | ||
| 377 | |||
| 378 | 8416 | void IRGenerator::insertCondJump(llvm::Value *condition, llvm::BasicBlock *trueBlock, llvm::BasicBlock *falseBlock, | |
| 379 | Likelihood likelihood /*=UNSPECIFIED*/) { | ||
| 380 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 8416 times.
|
8416 | if (blockAlreadyTerminated) |
| 381 | ✗ | return; | |
| 382 | 8416 | llvm::BranchInst *jumpInst = builder.CreateCondBr(condition, trueBlock, falseBlock); | |
| 383 | 8416 | blockAlreadyTerminated = true; | |
| 384 | |||
| 385 |
2/2✓ Branch 5 → 6 taken 760 times.
✓ Branch 5 → 7 taken 7656 times.
|
8416 | if (likelihood != Likelihood::UNSPECIFIED) |
| 386 | 760 | mdGenerator.generateBranchWeightsMetadata(jumpInst, likelihood); | |
| 387 | } | ||
| 388 | |||
| 389 | 10160 | void IRGenerator::verifyFunction(const llvm::Function *fct, const CodeLoc &codeLoc) const { | |
| 390 | // Skip the verifying step if the verifier was disabled manually or debug info is emitted | ||
| 391 |
3/4✓ Branch 2 → 3 taken 10160 times.
✗ Branch 2 → 4 not taken.
✓ Branch 3 → 4 taken 192 times.
✓ Branch 3 → 5 taken 9968 times.
|
10160 | if (cliOptions.disableVerifier || cliOptions.instrumentation.generateDebugInfo) |
| 392 | 192 | return; | |
| 393 | |||
| 394 | // Verify function | ||
| 395 | 9968 | std::string output; | |
| 396 |
1/2✓ Branch 6 → 7 taken 9968 times.
✗ Branch 6 → 21 not taken.
|
9968 | llvm::raw_string_ostream oss(output); |
| 397 | − | if (llvm::verifyFunction(*fct, &oss)) // LCOV_EXCL_LINE | |
| 398 | − | throw CompilerError(codeLoc, INVALID_FUNCTION, output); // LCOV_EXCL_LINE | |
| 399 | 9968 | } | |
| 400 | |||
| 401 | 908 | void IRGenerator::verifyModule(const CodeLoc &codeLoc) const { | |
| 402 | // Skip the verifying step if the verifier was disabled manually or debug info is emitted | ||
| 403 |
3/4✓ Branch 2 → 3 taken 908 times.
✗ Branch 2 → 4 not taken.
✓ Branch 3 → 4 taken 19 times.
✓ Branch 3 → 5 taken 889 times.
|
908 | if (cliOptions.disableVerifier || cliOptions.instrumentation.generateDebugInfo) |
| 404 | 19 | return; | |
| 405 | |||
| 406 | // Verify module | ||
| 407 | 889 | std::string output; | |
| 408 |
1/2✓ Branch 6 → 7 taken 889 times.
✗ Branch 6 → 21 not taken.
|
889 | llvm::raw_string_ostream oss(output); |
| 409 | − | if (llvm::verifyModule(*module, &oss)) // LCOV_EXCL_LINE | |
| 410 | − | throw CompilerError(codeLoc, INVALID_MODULE, output); // LCOV_EXCL_LINE | |
| 411 | 889 | } | |
| 412 | |||
| 413 | 5337 | LLVMExprResult IRGenerator::doAssignment(const ASTNode *lhsNode, const ExprNode *rhsNode, const ASTNode *node) { | |
| 414 | // Get entry of left side | ||
| 415 |
2/4✓ Branch 2 → 3 taken 5337 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 5337 times.
✗ Branch 3 → 15 not taken.
|
5337 | auto [value, constant, ptr, refPtr, entry, _] = std::any_cast<LLVMExprResult>(visit(lhsNode)); |
| 416 |
6/8✓ Branch 5 → 6 taken 4575 times.
✓ Branch 5 → 10 taken 762 times.
✓ Branch 6 → 7 taken 4575 times.
✗ Branch 6 → 18 not taken.
✓ Branch 7 → 8 taken 4575 times.
✗ Branch 7 → 18 not taken.
✓ Branch 8 → 9 taken 236 times.
✓ Branch 8 → 10 taken 4339 times.
|
5337 | llvm::Value *lhsAddress = entry != nullptr && entry->getQualType().isRef() ? refPtr : ptr; |
| 417 |
1/2✓ Branch 11 → 12 taken 5337 times.
✗ Branch 11 → 18 not taken.
|
10674 | return doAssignment(lhsAddress, entry, rhsNode, node); |
| 418 | } | ||
| 419 | |||
| 420 | 12472 | LLVMExprResult IRGenerator::doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, const ExprNode *rhsNode, | |
| 421 | const ASTNode *node, bool isDecl) { | ||
| 422 | // Get symbol type of right side | ||
| 423 |
1/2✓ Branch 2 → 3 taken 12472 times.
✗ Branch 2 → 13 not taken.
|
12472 | const QualType &rhsSType = rhsNode->getEvaluatedSymbolType(manIdx); |
| 424 |
2/4✓ Branch 3 → 4 taken 12472 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 12472 times.
✗ Branch 4 → 10 not taken.
|
12472 | auto rhs = std::any_cast<LLVMExprResult>(visit(rhsNode)); |
| 425 |
1/2✓ Branch 6 → 7 taken 12472 times.
✗ Branch 6 → 13 not taken.
|
24944 | return doAssignment(lhsAddress, lhsEntry, rhs, rhsSType, node, isDecl); |
| 426 | } | ||
| 427 | |||
| 428 | 12587 | LLVMExprResult IRGenerator::doAssignment(llvm::Value *lhsAddress, SymbolTableEntry *lhsEntry, LLVMExprResult &rhs, | |
| 429 | const QualType &rhsSType, const ASTNode *node, bool isDecl) { | ||
| 430 | // Deduce some information about the assignment | ||
| 431 |
4/4✓ Branch 2 → 3 taken 11825 times.
✓ Branch 2 → 7 taken 762 times.
✓ Branch 5 → 6 taken 477 times.
✓ Branch 5 → 7 taken 11348 times.
|
12587 | const bool isRefAssign = lhsEntry != nullptr && lhsEntry->getQualType().isRef(); |
| 432 |
8/10✓ Branch 8 → 9 taken 12110 times.
✓ Branch 8 → 15 taken 477 times.
✓ Branch 9 → 10 taken 12110 times.
✗ Branch 9 → 177 not taken.
✓ Branch 10 → 11 taken 12110 times.
✗ Branch 10 → 177 not taken.
✓ Branch 11 → 12 taken 1365 times.
✓ Branch 11 → 15 taken 10745 times.
✓ Branch 13 → 14 taken 174 times.
✓ Branch 13 → 15 taken 1191 times.
|
12587 | const bool needsCopy = !isRefAssign && rhsSType.removeReferenceWrapper().is(TY_STRUCT) && !rhs.isTemporary(); |
| 433 | |||
| 434 |
2/2✓ Branch 16 → 17 taken 477 times.
✓ Branch 16 → 57 taken 12110 times.
|
12587 | if (isRefAssign) { |
| 435 |
1/2✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 477 times.
|
477 | assert(lhsEntry != nullptr); |
| 436 |
2/2✓ Branch 19 → 20 taken 241 times.
✓ Branch 19 → 33 taken 236 times.
|
477 | if (isDecl) { // Reference gets initially assigned |
| 437 | // Get address of right side | ||
| 438 | 241 | llvm::Value *rhsAddress = resolveAddress(rhs); | |
| 439 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 241 times.
|
241 | assert(rhsAddress != nullptr); |
| 440 | |||
| 441 | // Store lhs pointer to rhs | ||
| 442 |
2/4✓ Branch 26 → 27 taken 241 times.
✗ Branch 26 → 178 not taken.
✓ Branch 27 → 28 taken 241 times.
✗ Branch 27 → 178 not taken.
|
241 | llvm::Value *refAddress = insertAlloca(builder.getPtrTy()); |
| 443 | 241 | lhsEntry->updateAddress(refAddress); | |
| 444 | 241 | insertStore(rhsAddress, refAddress); | |
| 445 | |||
| 446 | 241 | return LLVMExprResult{.value = rhsAddress, .ptr = refAddress, .entry = lhsEntry}; | |
| 447 | } | ||
| 448 | |||
| 449 | // Reference to reference assignment (only for struct fields that are not initialized yet) | ||
| 450 | // These are only allowed inside a ctor body. In other cases, the value of the reference gets assigned, not the ref itself. | ||
| 451 |
6/8✓ Branch 33 → 34 taken 163 times.
✓ Branch 33 → 40 taken 73 times.
✓ Branch 35 → 36 taken 163 times.
✗ Branch 35 → 40 not taken.
✓ Branch 36 → 37 taken 157 times.
✓ Branch 36 → 40 taken 6 times.
✓ Branch 38 → 39 taken 157 times.
✗ Branch 38 → 40 not taken.
|
236 | const bool isInitialFieldRefAssign = isInCtorBody && rhsSType.isRef() && rhs.entry && lhsEntry->isField(); |
| 452 | // Assigning the result variable | ||
| 453 | 236 | const bool isReturnValAssign = lhsEntry->name == RETURN_VARIABLE_NAME; | |
| 454 |
4/4✓ Branch 42 → 43 taken 79 times.
✓ Branch 42 → 44 taken 157 times.
✓ Branch 43 → 44 taken 2 times.
✓ Branch 43 → 49 taken 77 times.
|
236 | if (isInitialFieldRefAssign || isReturnValAssign) { |
| 455 | // Get address of right side | ||
| 456 | 159 | llvm::Value *referencedAddress = resolveAddress(rhs); | |
| 457 |
1/2✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 159 times.
|
159 | assert(referencedAddress != nullptr); |
| 458 | |||
| 459 | // Store the rhs* to the lhs** | ||
| 460 | 159 | insertStore(referencedAddress, lhsAddress); | |
| 461 | |||
| 462 | 159 | return LLVMExprResult{.value = referencedAddress, .ptr = lhsAddress, .entry = lhsEntry}; | |
| 463 | } | ||
| 464 | |||
| 465 | // Load referenced address | ||
| 466 |
3/6✓ Branch 51 → 52 taken 77 times.
✗ Branch 51 → 186 not taken.
✓ Branch 52 → 53 taken 77 times.
✗ Branch 52 → 184 not taken.
✓ Branch 53 → 54 taken 77 times.
✗ Branch 53 → 184 not taken.
|
154 | lhsAddress = insertLoad(builder.getPtrTy(), lhsAddress); |
| 467 | } | ||
| 468 | |||
| 469 | // Check if we need to copy the rhs to the lhs. This happens for structs | ||
| 470 |
2/2✓ Branch 57 → 58 taken 174 times.
✓ Branch 57 → 123 taken 12013 times.
|
12187 | if (needsCopy) { |
| 471 | // Get address of right side | ||
| 472 |
1/2✓ Branch 58 → 59 taken 174 times.
✗ Branch 58 → 237 not taken.
|
174 | llvm::Value *rhsAddress = resolveAddress(rhs); |
| 473 |
1/2✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 174 times.
|
174 | assert(rhsAddress != nullptr); |
| 474 | |||
| 475 | // Allocate new memory if the lhs address does not exist | ||
| 476 |
2/2✓ Branch 61 → 62 taken 4 times.
✓ Branch 61 → 72 taken 170 times.
|
174 | if (!lhsAddress) { |
| 477 |
1/2✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 4 times.
|
4 | assert(lhsEntry != nullptr); |
| 478 |
3/6✓ Branch 66 → 67 taken 4 times.
✗ Branch 66 → 192 not taken.
✓ Branch 67 → 68 taken 4 times.
✗ Branch 67 → 190 not taken.
✓ Branch 68 → 69 taken 4 times.
✗ Branch 68 → 190 not taken.
|
4 | lhsAddress = insertAlloca(lhsEntry->getQualType()); |
| 479 |
1/2✓ Branch 71 → 72 taken 4 times.
✗ Branch 71 → 237 not taken.
|
4 | lhsEntry->updateAddress(lhsAddress); |
| 480 | } | ||
| 481 | |||
| 482 | // Check if we have a copy ctor | ||
| 483 |
2/4✓ Branch 72 → 73 taken 174 times.
✗ Branch 72 → 196 not taken.
✓ Branch 73 → 74 taken 174 times.
✗ Branch 73 → 196 not taken.
|
174 | const QualType rhsSTypeNonRef = rhsSType.removeReferenceWrapper().toNonConst(); |
| 484 |
1/2✓ Branch 74 → 75 taken 174 times.
✗ Branch 74 → 237 not taken.
|
174 | Scope *structScope = rhsSTypeNonRef.getBodyScope(); |
| 485 |
2/4✓ Branch 75 → 76 taken 174 times.
✗ Branch 75 → 201 not taken.
✓ Branch 80 → 81 taken 174 times.
✗ Branch 80 → 197 not taken.
|
522 | const ArgList args = {{rhsSTypeNonRef.toConstRef(node), rhs.isTemporary()}}; |
| 486 |
2/4✓ Branch 84 → 85 taken 174 times.
✗ Branch 84 → 205 not taken.
✓ Branch 85 → 86 taken 174 times.
✗ Branch 85 → 203 not taken.
|
174 | const Function *copyCtor = FunctionManager::lookup(structScope, CTOR_FUNCTION_NAME, rhsSTypeNonRef, args, true); |
| 487 |
2/2✓ Branch 88 → 89 taken 73 times.
✓ Branch 88 → 96 taken 101 times.
|
174 | if (copyCtor != nullptr) { |
| 488 | // Call copy ctor | ||
| 489 |
2/4✓ Branch 91 → 92 taken 73 times.
✗ Branch 91 → 211 not taken.
✓ Branch 92 → 93 taken 73 times.
✗ Branch 92 → 209 not taken.
|
219 | generateCtorOrDtorCall(lhsAddress, copyCtor, {rhsAddress}); |
| 490 |
2/4✓ Branch 96 → 97 taken 101 times.
✗ Branch 96 → 235 not taken.
✓ Branch 97 → 98 taken 101 times.
✗ Branch 97 → 114 not taken.
|
101 | } else if (rhsSTypeNonRef.isTriviallyCopyable(node)) { |
| 491 | // Create shallow copy | ||
| 492 |
1/2✓ Branch 98 → 99 taken 101 times.
✗ Branch 98 → 223 not taken.
|
101 | llvm::Type *rhsType = rhsSTypeNonRef.toLLVMType(sourceFile); |
| 493 |
6/10✓ Branch 99 → 100 taken 96 times.
✓ Branch 99 → 101 taken 5 times.
✓ Branch 100 → 104 taken 96 times.
✗ Branch 100 → 216 not taken.
✓ Branch 103 → 104 taken 5 times.
✗ Branch 103 → 216 not taken.
✓ Branch 104 → 105 taken 5 times.
✓ Branch 104 → 107 taken 96 times.
✗ Branch 216 → 217 not taken.
✗ Branch 216 → 219 not taken.
|
106 | const std::string copyName = lhsEntry ? lhsEntry->name : ""; |
| 494 |
4/6✓ Branch 107 → 108 taken 96 times.
✓ Branch 107 → 110 taken 5 times.
✗ Branch 108 → 109 not taken.
✓ Branch 108 → 110 taken 96 times.
✓ Branch 111 → 112 taken 101 times.
✗ Branch 111 → 221 not taken.
|
101 | generateShallowCopy(rhsAddress, rhsType, lhsAddress, lhsEntry && lhsEntry->isVolatile); |
| 495 | 101 | } else { | |
| 496 | ✗ | const std::string structName = rhsSTypeNonRef.getName(); | |
| 497 | ✗ | const std::string msg = "Cannot copy struct '" + structName + "', as it is not trivially copyable and has no copy ctor"; | |
| 498 | ✗ | throw SemanticError(node, COPY_CTOR_REQUIRED, msg); | |
| 499 | ✗ | } | |
| 500 | 174 | return LLVMExprResult{.ptr = lhsAddress, .entry = lhsEntry}; | |
| 501 | 174 | } | |
| 502 | |||
| 503 |
7/8✓ Branch 123 → 124 taken 7005 times.
✓ Branch 123 → 129 taken 5008 times.
✓ Branch 125 → 126 taken 888 times.
✓ Branch 125 → 129 taken 6117 times.
✓ Branch 127 → 128 taken 888 times.
✗ Branch 127 → 129 not taken.
✓ Branch 130 → 131 taken 888 times.
✓ Branch 130 → 136 taken 11125 times.
|
12013 | if (isDecl && rhsSType.is(TY_STRUCT) && rhs.isTemporary()) { |
| 504 |
1/2✗ Branch 131 → 132 not taken.
✓ Branch 131 → 133 taken 888 times.
|
888 | assert(lhsEntry != nullptr); |
| 505 | // Directly set the address to the lhs entry (temp stealing) | ||
| 506 | 888 | llvm::Value *rhsAddress = resolveAddress(rhs); | |
| 507 | 888 | lhsEntry->updateAddress(rhsAddress); | |
| 508 | 888 | rhs.entry = lhsEntry; | |
| 509 | 888 | return rhs; | |
| 510 | } | ||
| 511 | |||
| 512 | // Allocate new memory if the lhs address does not exist | ||
| 513 |
2/2✓ Branch 136 → 137 taken 6086 times.
✓ Branch 136 → 147 taken 5039 times.
|
11125 | if (!lhsAddress) { |
| 514 |
1/2✗ Branch 137 → 138 not taken.
✓ Branch 137 → 139 taken 6086 times.
|
6086 | assert(lhsEntry != nullptr); |
| 515 |
3/6✓ Branch 141 → 142 taken 6086 times.
✗ Branch 141 → 240 not taken.
✓ Branch 142 → 143 taken 6086 times.
✗ Branch 142 → 238 not taken.
✓ Branch 143 → 144 taken 6086 times.
✗ Branch 143 → 238 not taken.
|
6086 | lhsAddress = insertAlloca(lhsEntry->getQualType()); |
| 516 | 6086 | lhsEntry->updateAddress(lhsAddress); | |
| 517 | } | ||
| 518 | |||
| 519 | // 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 | ||
| 520 |
10/10✓ Branch 147 → 148 taken 10383 times.
✓ Branch 147 → 156 taken 742 times.
✓ Branch 150 → 151 taken 2106 times.
✓ Branch 150 → 156 taken 8277 times.
✓ Branch 152 → 153 taken 5 times.
✓ Branch 152 → 156 taken 2101 times.
✓ Branch 154 → 155 taken 1 time.
✓ Branch 154 → 156 taken 4 times.
✓ Branch 157 → 158 taken 1 time.
✓ Branch 157 → 173 taken 11124 times.
|
11125 | if (lhsEntry && lhsEntry->getQualType().isPtr() && rhsSType.isArray() && rhsSType.getArraySize() != ARRAY_SIZE_UNKNOWN) { |
| 521 | // Get address of right side | ||
| 522 |
1/2✓ Branch 158 → 159 taken 1 time.
✗ Branch 158 → 251 not taken.
|
1 | llvm::Value *rhsAddress = resolveAddress(rhs); |
| 523 |
1/2✗ Branch 159 → 160 not taken.
✓ Branch 159 → 161 taken 1 time.
|
1 | assert(rhsAddress != nullptr); |
| 524 |
1/2✓ Branch 161 → 162 taken 1 time.
✗ Branch 161 → 251 not taken.
|
1 | llvm::Type *elementTy = rhsSType.toLLVMType(sourceFile); |
| 525 |
2/4✓ Branch 162 → 163 taken 1 time.
✗ Branch 162 → 251 not taken.
✓ Branch 163 → 164 taken 1 time.
✗ Branch 163 → 251 not taken.
|
1 | llvm::Value *indices[2] = {builder.getInt64(0), builder.getInt32(0)}; |
| 526 |
1/2✓ Branch 168 → 169 taken 1 time.
✗ Branch 168 → 244 not taken.
|
1 | llvm::Value *firstItemAddress = insertInBoundsGEP(elementTy, rhsAddress, indices); |
| 527 |
1/2✓ Branch 171 → 172 taken 1 time.
✗ Branch 171 → 251 not taken.
|
1 | insertStore(firstItemAddress, lhsAddress); |
| 528 | 1 | return LLVMExprResult{.value = rhsAddress, .ptr = lhsAddress, .entry = lhsEntry}; | |
| 529 | } | ||
| 530 | |||
| 531 | // We can load the value from the right side and store it to the left side | ||
| 532 | // Retrieve value of the right side | ||
| 533 | 11124 | llvm::Value *rhsValue = resolveValue(rhsSType, rhs); | |
| 534 | // Store the value to the address | ||
| 535 | 11124 | insertStore(rhsValue, lhsAddress, rhsSType); | |
| 536 | 11124 | return LLVMExprResult{.value = rhsValue, .ptr = lhsAddress, .entry = lhsEntry}; | |
| 537 | } | ||
| 538 | |||
| 539 | 138 | void IRGenerator::generateShallowCopy(llvm::Value *oldAddress, llvm::Type *varType, llvm::Value *targetAddress, | |
| 540 | bool isVolatile) const { | ||
| 541 | // Retrieve size to copy | ||
| 542 |
1/2✓ Branch 3 → 4 taken 138 times.
✗ Branch 3 → 19 not taken.
|
138 | const llvm::TypeSize typeSize = module->getDataLayout().getTypeAllocSize(varType); |
| 543 | |||
| 544 | // Create values for memcpy intrinsic | ||
| 545 |
2/4✓ Branch 4 → 5 taken 138 times.
✗ Branch 4 → 19 not taken.
✓ Branch 5 → 6 taken 138 times.
✗ Branch 5 → 19 not taken.
|
138 | llvm::Value *structSize = builder.getInt64(typeSize); |
| 546 |
1/2✓ Branch 6 → 7 taken 138 times.
✗ Branch 6 → 19 not taken.
|
138 | llvm::Value *copyVolatile = builder.getInt1(isVolatile); |
| 547 | |||
| 548 | // Call memcpy intrinsic to execute the shallow copy | ||
| 549 |
1/2✓ Branch 7 → 8 taken 138 times.
✗ Branch 7 → 19 not taken.
|
138 | llvm::Function *memcpyFct = stdFunctionManager.getMemcpyIntrinsic(); |
| 550 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 138 times.
|
138 | assert(targetAddress != nullptr); |
| 551 |
3/6✓ Branch 10 → 11 taken 138 times.
✗ Branch 10 → 18 not taken.
✓ Branch 12 → 13 taken 138 times.
✗ Branch 12 → 15 not taken.
✓ Branch 13 → 14 taken 138 times.
✗ Branch 13 → 15 not taken.
|
138 | builder.CreateCall(memcpyFct, {targetAddress, oldAddress, structSize, copyVolatile}); |
| 552 | 138 | } | |
| 553 | |||
| 554 | 21650 | void IRGenerator::autoDeReferencePtr(llvm::Value *&ptr, QualType &symbolType) { | |
| 555 |
6/6✓ Branch 12 → 13 taken 22530 times.
✓ Branch 12 → 15 taken 16120 times.
✓ Branch 14 → 15 taken 880 times.
✓ Branch 14 → 16 taken 21650 times.
✓ Branch 17 → 3 taken 17000 times.
✓ Branch 17 → 18 taken 21650 times.
|
38650 | while (symbolType.isPtr() || symbolType.isRef()) { |
| 556 |
2/4✓ Branch 5 → 6 taken 17000 times.
✗ Branch 5 → 21 not taken.
✓ Branch 6 → 7 taken 17000 times.
✗ Branch 6 → 19 not taken.
|
17000 | ptr = insertLoad(symbolType, ptr); |
| 557 |
1/2✓ Branch 9 → 10 taken 17000 times.
✗ Branch 9 → 25 not taken.
|
17000 | symbolType = symbolType.getContained(); |
| 558 | } | ||
| 559 | 21650 | } | |
| 560 | |||
| 561 | 52 | llvm::GlobalVariable *IRGenerator::createGlobalConst(const std::string &baseName, llvm::Constant *constant) const { | |
| 562 | // Get unused name | ||
| 563 |
1/2✓ Branch 2 → 3 taken 52 times.
✗ Branch 2 → 19 not taken.
|
52 | const std::string globalName = getUnusedGlobalName(baseName); |
| 564 | // Create global | ||
| 565 |
1/2✓ Branch 5 → 6 taken 52 times.
✗ Branch 5 → 15 not taken.
|
52 | module->getOrInsertGlobal(globalName, constant->getType()); |
| 566 |
1/2✓ Branch 7 → 8 taken 52 times.
✗ Branch 7 → 16 not taken.
|
52 | llvm::GlobalVariable *global = module->getNamedGlobal(globalName); |
| 567 | // Set initializer to the given constant | ||
| 568 |
1/2✓ Branch 8 → 9 taken 52 times.
✗ Branch 8 → 17 not taken.
|
52 | global->setInitializer(constant); |
| 569 | 52 | global->setConstant(true); | |
| 570 |
1/2✓ Branch 10 → 11 taken 52 times.
✗ Branch 10 → 17 not taken.
|
52 | global->setLinkage(llvm::GlobalValue::PrivateLinkage); |
| 571 | 52 | global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); | |
| 572 | 52 | return global; | |
| 573 | 52 | } | |
| 574 | |||
| 575 | 2784 | llvm::GlobalVariable *IRGenerator::createGlobalStringConst(const std::string &baseName, const std::string &value) const { | |
| 576 | // Get unused name | ||
| 577 |
1/2✓ Branch 2 → 3 taken 2784 times.
✗ Branch 2 → 21 not taken.
|
2784 | const std::string globalName = getUnusedGlobalName(baseName); |
| 578 | // Create global | ||
| 579 |
2/4✓ Branch 3 → 4 taken 2784 times.
✗ Branch 3 → 16 not taken.
✓ Branch 5 → 6 taken 2784 times.
✗ Branch 5 → 15 not taken.
|
2784 | builder.CreateGlobalString(value, globalName, 0, module); |
| 580 |
1/2✓ Branch 7 → 8 taken 2784 times.
✗ Branch 7 → 17 not taken.
|
2784 | llvm::GlobalVariable *global = module->getNamedGlobal(globalName); |
| 581 | // If the output should be comparable, fix alignment to 4 bytes | ||
| 582 |
1/2✓ Branch 8 → 9 taken 2784 times.
✗ Branch 8 → 12 not taken.
|
2784 | if (cliOptions.comparableOutput) |
| 583 |
2/4✓ Branch 9 → 10 taken 2784 times.
✗ Branch 9 → 18 not taken.
✓ Branch 10 → 11 taken 2784 times.
✗ Branch 10 → 18 not taken.
|
2784 | global->setAlignment(llvm::Align(4)); |
| 584 | 2784 | return global; | |
| 585 | 2784 | } | |
| 586 | |||
| 587 | 2784 | llvm::GlobalVariable *IRGenerator::createGlobalStringConst(const std::string &baseName, const std::string &value, | |
| 588 | const CodeLoc &codeLoc) const { | ||
| 589 | 2784 | llvm::GlobalVariable *global = createGlobalStringConst(baseName, value); | |
| 590 | // Create debug info | ||
| 591 |
2/2✓ Branch 3 → 4 taken 43 times.
✓ Branch 3 → 10 taken 2741 times.
|
2784 | if (cliOptions.instrumentation.generateDebugInfo) |
| 592 |
3/6✓ Branch 5 → 6 taken 43 times.
✗ Branch 5 → 14 not taken.
✓ Branch 6 → 7 taken 43 times.
✗ Branch 6 → 14 not taken.
✓ Branch 7 → 8 taken 43 times.
✗ Branch 7 → 12 not taken.
|
43 | diGenerator.generateGlobalStringDebugInfo(global, global->getName().str(), value.length(), codeLoc); |
| 593 | 2784 | return global; | |
| 594 | } | ||
| 595 | |||
| 596 | 4263 | std::string IRGenerator::getUnusedGlobalName(const std::string &baseName) const { | |
| 597 | // Find an unused global name | ||
| 598 | 4263 | std::string globalName; | |
| 599 | 4263 | unsigned int suffixNumber = 0; | |
| 600 | do { | ||
| 601 |
1/2✓ Branch 5 → 6 taken 48432 times.
✗ Branch 5 → 15 not taken.
|
48432 | globalName = baseName + std::to_string(suffixNumber); |
| 602 | 48432 | suffixNumber++; | |
| 603 |
3/4✓ Branch 10 → 11 taken 48432 times.
✗ Branch 10 → 19 not taken.
✓ Branch 11 → 12 taken 44169 times.
✓ Branch 11 → 13 taken 4263 times.
|
48432 | } while (module->getNamedGlobal(globalName) != nullptr); |
| 604 | 4263 | return globalName; | |
| 605 | ✗ | } | |
| 606 | |||
| 607 | 15848 | void IRGenerator::materializeConstant(LLVMExprResult &exprResult) { | |
| 608 | // Skip results, that do not contain a constant or already have a value | ||
| 609 |
3/4✓ Branch 2 → 3 taken 15460 times.
✓ Branch 2 → 4 taken 388 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 15460 times.
|
15848 | if (exprResult.value != nullptr || exprResult.constant == nullptr) |
| 610 | 388 | return; | |
| 611 | |||
| 612 | // Default case: the value to the constant | ||
| 613 | 15460 | exprResult.value = exprResult.constant; | |
| 614 | } | ||
| 615 | |||
| 616 | 1742 | std::string IRGenerator::getIRString(llvm::Module *llvmModule, const CliOptions &cliOptions) { | |
| 617 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1742 times.
|
1742 | assert(llvmModule != nullptr); // Make sure the module hasn't been moved away |
| 618 | |||
| 619 | // Backup target triple and data layout | ||
| 620 |
1/2✓ Branch 5 → 6 taken 1742 times.
✗ Branch 5 → 41 not taken.
|
1742 | const llvm::Triple targetTriple = llvmModule->getTargetTriple(); |
| 621 |
1/2✓ Branch 7 → 8 taken 1742 times.
✗ Branch 7 → 39 not taken.
|
1742 | const std::string targetDataLayout = llvmModule->getDataLayoutStr(); |
| 622 | // Remove target triple and data layout | ||
| 623 |
1/2✓ Branch 8 → 9 taken 1742 times.
✗ Branch 8 → 15 not taken.
|
1742 | if (cliOptions.comparableOutput) { |
| 624 | 1742 | llvmModule->setTargetTriple(llvm::Triple()); | |
| 625 |
2/4✓ Branch 12 → 13 taken 1742 times.
✗ Branch 12 → 30 not taken.
✓ Branch 13 → 14 taken 1742 times.
✗ Branch 13 → 30 not taken.
|
1742 | llvmModule->setDataLayout(""); |
| 626 | } | ||
| 627 | |||
| 628 | // Get IR string | ||
| 629 | 1742 | std::string output; | |
| 630 |
1/2✓ Branch 16 → 17 taken 1742 times.
✗ Branch 16 → 35 not taken.
|
1742 | llvm::raw_string_ostream oss(output); |
| 631 |
1/2✓ Branch 17 → 18 taken 1742 times.
✗ Branch 17 → 33 not taken.
|
1742 | llvmModule->print(oss, nullptr); |
| 632 | |||
| 633 | // Restore target triple and data layout | ||
| 634 |
1/2✓ Branch 18 → 19 taken 1742 times.
✗ Branch 18 → 25 not taken.
|
1742 | if (cliOptions.comparableOutput) { |
| 635 |
1/2✓ Branch 19 → 20 taken 1742 times.
✗ Branch 19 → 31 not taken.
|
1742 | llvmModule->setTargetTriple(targetTriple); |
| 636 |
1/2✓ Branch 23 → 24 taken 1742 times.
✗ Branch 23 → 32 not taken.
|
1742 | llvmModule->setDataLayout(targetDataLayout); |
| 637 | } | ||
| 638 | |||
| 639 | 1742 | return output; | |
| 640 | 1742 | } | |
| 641 | |||
| 642 | /** | ||
| 643 | * Returns the operator function list for the current manifestation and the given node | ||
| 644 | * | ||
| 645 | * @param node Node to retrieve the op fct pointer list from | ||
| 646 | * @return Op fct pointer list | ||
| 647 | */ | ||
| 648 | 17474 | const std::vector<const Function *> &IRGenerator::getOpFctPointers(const ASTNode *node) const { | |
| 649 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 17474 times.
|
17474 | assert(node->getOpFctPointers()->size() > manIdx); |
| 650 | 17474 | return node->getOpFctPointers()->at(manIdx); | |
| 651 | } | ||
| 652 | |||
| 653 | } // namespace spice::compiler | ||
| 654 |