GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenBuiltinFunctions.cpp
Date: 2025-11-19 19:39:29
Coverage Exec Excl Total
Lines: 96.7% 116 1 121
Functions: 100.0% 8 0 8
Branches: 53.6% 177 0 330

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "IRGenerator.h"
4 #include "global/TypeRegistry.h"
5
6 #include <ast/ASTNodes.h>
7 #include <global/GlobalResourceManager.h>
8 #include <llvm/IR/InlineAsm.h>
9
10 #include <llvm/IR/Module.h>
11
12 namespace spice::compiler {
13
14 1728 std::any IRGenerator::visitBuiltinCall(const BuiltinCallNode *node) {
15
2/2
✓ Branch 2 → 3 taken 785 times.
✓ Branch 2 → 4 taken 943 times.
1728 if (node->printfCall)
16 785 return visit(node->printfCall);
17
2/2
✓ Branch 4 → 5 taken 157 times.
✓ Branch 4 → 6 taken 786 times.
943 if (node->sizeofCall)
18 157 return visit(node->sizeofCall);
19
2/2
✓ Branch 6 → 7 taken 11 times.
✓ Branch 6 → 8 taken 775 times.
786 if (node->alignofCall)
20 11 return visit(node->alignofCall);
21
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 773 times.
775 if (node->typeidCall)
22 2 return visit(node->typeidCall);
23
2/2
✓ Branch 10 → 11 taken 59 times.
✓ Branch 10 → 12 taken 714 times.
773 if (node->lenCall)
24 59 return visit(node->lenCall);
25
2/2
✓ Branch 12 → 13 taken 713 times.
✓ Branch 12 → 14 taken 1 time.
714 if (node->panicCall)
26 713 return visit(node->panicCall);
27
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 16 not taken.
1 if (node->sysCall)
28 1 return visit(node->sysCall);
29 assert_fail("Unknown builtin call"); // LCOV_EXCL_LINE
30 return nullptr; // LCOV_EXCL_LINE
31 }
32
33 785 std::any IRGenerator::visitPrintfCall(const PrintfCallNode *node) {
34 // Retrieve printf function
35
1/2
✓ Branch 2 → 3 taken 785 times.
✗ Branch 2 → 119 not taken.
785 llvm::Function *printfFct = stdFunctionManager.getPrintfFct();
36
37 // Push the template string as first argument
38 785 std::vector<llvm::Value *> printfArgs;
39
2/4
✓ Branch 5 → 6 taken 785 times.
✗ Branch 5 → 80 not taken.
✓ Branch 6 → 7 taken 785 times.
✗ Branch 6 → 78 not taken.
1570 llvm::Constant *templateString = createGlobalStringConst("printf.str.", node->templatedString, node->codeLoc);
40
1/2
✓ Branch 9 → 10 taken 785 times.
✗ Branch 9 → 84 not taken.
785 printfArgs.push_back(templateString);
41
42 // Collect replacement arguments
43
2/2
✓ Branch 62 → 12 taken 643 times.
✓ Branch 62 → 63 taken 785 times.
1428 for (const AssignExprNode *arg : node->args) {
44 // Retrieve type of argument
45
1/2
✓ Branch 13 → 14 taken 643 times.
✗ Branch 13 → 111 not taken.
643 const QualType argSymbolType = arg->getEvaluatedSymbolType(manIdx);
46
47 // Re-map some values
48 llvm::Value *argVal;
49
2/4
✓ Branch 14 → 15 taken 643 times.
✗ Branch 14 → 111 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 28 taken 643 times.
643 if (argSymbolType.isArray()) {
50 llvm::Value *argValPtr = resolveAddress(arg);
51 llvm::Value *indices[2] = {builder.getInt64(0), builder.getInt32(0)};
52 llvm::Type *argType = argSymbolType.toLLVMType(sourceFile);
53 argVal = insertInBoundsGEP(argType, argValPtr, indices);
54
4/6
✓ Branch 28 → 29 taken 643 times.
✗ Branch 28 → 93 not taken.
✓ Branch 29 → 30 taken 643 times.
✗ Branch 29 → 93 not taken.
✓ Branch 30 → 31 taken 61 times.
✓ Branch 30 → 48 taken 582 times.
643 } else if (argSymbolType.getBase().isStringObj()) {
55
1/2
✓ Branch 31 → 32 taken 61 times.
✗ Branch 31 → 111 not taken.
61 llvm::Value *argValPtr = resolveAddress(arg);
56
2/4
✓ Branch 32 → 33 taken 61 times.
✗ Branch 32 → 94 not taken.
✓ Branch 33 → 34 taken 61 times.
✗ Branch 33 → 94 not taken.
61 llvm::Type *argBaseType = argSymbolType.getBase().toLLVMType(sourceFile);
57
1/2
✓ Branch 37 → 38 taken 61 times.
✗ Branch 37 → 95 not taken.
61 argValPtr = insertStructGEP(argBaseType, argValPtr, 0);
58
3/6
✓ Branch 42 → 43 taken 61 times.
✗ Branch 42 → 103 not taken.
✓ Branch 43 → 44 taken 61 times.
✗ Branch 43 → 101 not taken.
✓ Branch 44 → 45 taken 61 times.
✗ Branch 44 → 101 not taken.
122 argVal = insertLoad(builder.getPtrTy(), argValPtr);
59 } else {
60
1/2
✓ Branch 48 → 49 taken 582 times.
✗ Branch 48 → 111 not taken.
582 argVal = resolveValue(arg);
61 }
62
63 // Extend all integer types lower than 32 bit to 32 bit
64
4/6
✓ Branch 50 → 51 taken 643 times.
✗ Branch 50 → 108 not taken.
✓ Branch 51 → 52 taken 643 times.
✗ Branch 51 → 107 not taken.
✓ Branch 52 → 53 taken 95 times.
✓ Branch 52 → 59 taken 548 times.
643 if (argSymbolType.removeReferenceWrapper().isOneOf({TY_SHORT, TY_BYTE, TY_CHAR, TY_BOOL}))
65
5/10
✓ Branch 53 → 54 taken 95 times.
✗ Branch 53 → 110 not taken.
✓ Branch 54 → 55 taken 95 times.
✗ Branch 54 → 109 not taken.
✓ Branch 55 → 56 taken 95 times.
✗ Branch 55 → 109 not taken.
✓ Branch 56 → 57 taken 95 times.
✗ Branch 56 → 109 not taken.
✓ Branch 57 → 58 taken 95 times.
✗ Branch 57 → 109 not taken.
95 argVal = builder.CreateIntCast(argVal, builder.getInt32Ty(), argSymbolType.removeReferenceWrapper().isSigned());
66
67
1/2
✓ Branch 59 → 60 taken 643 times.
✗ Branch 59 → 111 not taken.
643 printfArgs.push_back(argVal);
68 }
69
70 // Call printf function
71
3/6
✓ Branch 63 → 64 taken 785 times.
✗ Branch 63 → 115 not taken.
✓ Branch 65 → 66 taken 785 times.
✗ Branch 65 → 113 not taken.
✓ Branch 66 → 67 taken 785 times.
✗ Branch 66 → 113 not taken.
785 llvm::CallInst *callInst = builder.CreateCall(printfFct, printfArgs);
72
73 // Add noundef attribute to return value and all arguments
74
1/2
✓ Branch 67 → 68 taken 785 times.
✗ Branch 67 → 117 not taken.
785 callInst->addRetAttr(llvm::Attribute::NoUndef);
75
2/2
✓ Branch 72 → 69 taken 1428 times.
✓ Branch 72 → 73 taken 785 times.
2213 for (size_t i = 0; i < printfArgs.size(); i++)
76
1/2
✓ Branch 69 → 70 taken 1428 times.
✗ Branch 69 → 117 not taken.
1428 callInst->addParamAttr(i, llvm::Attribute::NoUndef);
77
78
1/2
✓ Branch 73 → 74 taken 785 times.
✗ Branch 73 → 116 not taken.
1570 return LLVMExprResult{.value = callInst};
79 785 }
80
81 157 std::any IRGenerator::visitSizeofCall(const SizeofCallNode *node) {
82 llvm::Type *type;
83
2/2
✓ Branch 2 → 3 taken 134 times.
✓ Branch 2 → 7 taken 23 times.
157 if (node->isType) { // Size of type
84
2/4
✓ Branch 3 → 4 taken 134 times.
✗ Branch 3 → 20 not taken.
✓ Branch 4 → 5 taken 134 times.
✗ Branch 4 → 18 not taken.
134 type = any_cast<llvm::Type *>(visit(node->dataType));
85 } else { // Size of value
86
2/4
✓ Branch 7 → 8 taken 23 times.
✗ Branch 7 → 22 not taken.
✓ Branch 8 → 9 taken 23 times.
✗ Branch 8 → 22 not taken.
23 type = node->assignExpr->getEvaluatedSymbolType(manIdx).toLLVMType(sourceFile);
87 }
88 // Calculate size at compile-time
89
1/2
✓ Branch 11 → 12 taken 157 times.
✗ Branch 11 → 22 not taken.
157 const llvm::TypeSize sizeInBytes = module->getDataLayout().getTypeAllocSize(type);
90
91 // Return size value
92
2/4
✓ Branch 12 → 13 taken 157 times.
✗ Branch 12 → 22 not taken.
✓ Branch 13 → 14 taken 157 times.
✗ Branch 13 → 22 not taken.
157 llvm::Value *sizeValue = builder.getInt64(sizeInBytes);
93
1/2
✓ Branch 14 → 15 taken 157 times.
✗ Branch 14 → 21 not taken.
314 return LLVMExprResult{.value = sizeValue};
94 }
95
96 11 std::any IRGenerator::visitAlignofCall(const AlignofCallNode *node) {
97 llvm::Type *type;
98
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 7 taken 10 times.
11 if (node->isType) { // Align of type
99
2/4
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 20 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 18 not taken.
1 type = any_cast<llvm::Type *>(visit(node->dataType));
100 } else { // Align of value
101
2/4
✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 22 not taken.
✓ Branch 8 → 9 taken 10 times.
✗ Branch 8 → 22 not taken.
10 type = node->assignExpr->getEvaluatedSymbolType(manIdx).toLLVMType(sourceFile);
102 }
103 // Calculate size at compile-time
104
1/2
✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 22 not taken.
11 const llvm::Align alignmentInBytes = module->getDataLayout().getABITypeAlign(type);
105
106 // Return align value
107
1/2
✓ Branch 13 → 14 taken 11 times.
✗ Branch 13 → 22 not taken.
11 llvm::Value *alignValue = builder.getInt64(alignmentInBytes.value());
108
1/2
✓ Branch 14 → 15 taken 11 times.
✗ Branch 14 → 21 not taken.
22 return LLVMExprResult{.value = alignValue};
109 }
110
111 2 std::any IRGenerator::visitTypeidCall(const TypeidCallNode *node) {
112 // Return type id value
113
1/2
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 11 not taken.
2 const QualType qualType = node->assignExpr->getEvaluatedSymbolType(manIdx);
114
1/2
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 11 not taken.
2 const uint64_t typeId = TypeRegistry::getTypeHash(*qualType.getType());
115
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 11 not taken.
2 llvm::Value *typeIdValue = builder.getInt64(typeId);
116
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 10 not taken.
4 return LLVMExprResult{.value = typeIdValue};
117 }
118
119 59 std::any IRGenerator::visitLenCall(const LenCallNode *node) {
120 // Check if the length is fixed and known via the symbol type
121
1/2
✓ Branch 2 → 3 taken 59 times.
✗ Branch 2 → 32 not taken.
59 QualType symbolType = node->assignExpr->getEvaluatedSymbolType(manIdx);
122
1/2
✓ Branch 3 → 4 taken 59 times.
✗ Branch 3 → 26 not taken.
59 symbolType = symbolType.removeReferenceWrapper();
123
124 llvm::Value *lengthValue;
125
3/4
✓ Branch 4 → 5 taken 59 times.
✗ Branch 4 → 32 not taken.
✓ Branch 5 → 6 taken 35 times.
✓ Branch 5 → 13 taken 24 times.
59 if (symbolType.is(TY_STRING)) {
126
1/2
✓ Branch 6 → 7 taken 35 times.
✗ Branch 6 → 32 not taken.
35 llvm::Function *getRawLengthFct = stdFunctionManager.getStringGetRawLengthStringFct();
127
4/8
✓ Branch 7 → 8 taken 35 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 35 times.
✗ Branch 8 → 28 not taken.
✓ Branch 10 → 11 taken 35 times.
✗ Branch 10 → 27 not taken.
✓ Branch 11 → 12 taken 35 times.
✗ Branch 11 → 27 not taken.
35 lengthValue = builder.CreateCall(getRawLengthFct, resolveValue(node->assignExpr));
128 } else {
129
4/8
✓ Branch 13 → 14 taken 24 times.
✗ Branch 13 → 32 not taken.
✓ Branch 14 → 15 taken 24 times.
✗ Branch 14 → 18 not taken.
✓ Branch 15 → 16 taken 24 times.
✗ Branch 15 → 32 not taken.
✓ Branch 16 → 17 taken 24 times.
✗ Branch 16 → 18 not taken.
24 assert(symbolType.isArray() && symbolType.getArraySize() != ARRAY_SIZE_UNKNOWN);
130 // Return length value
131
2/4
✓ Branch 19 → 20 taken 24 times.
✗ Branch 19 → 32 not taken.
✓ Branch 20 → 21 taken 24 times.
✗ Branch 20 → 32 not taken.
24 lengthValue = builder.getInt64(symbolType.getArraySize());
132 }
133
1/2
✓ Branch 22 → 23 taken 59 times.
✗ Branch 22 → 31 not taken.
118 return LLVMExprResult{.value = lengthValue};
134 }
135
136 713 std::any IRGenerator::visitPanicCall(const PanicCallNode *node) {
137
1/2
✓ Branch 2 → 3 taken 713 times.
✗ Branch 2 → 151 not taken.
713 llvm::PointerType *ptrTy = builder.getPtrTy();
138
139 // Get value for stderr
140 llvm::Value *stdErr;
141
2/2
✓ Branch 4 → 5 taken 11 times.
✓ Branch 4 → 12 taken 702 times.
713 if (cliOptions.targetTriple.isOSWindows()) {
142
1/2
✓ Branch 5 → 6 taken 11 times.
✗ Branch 5 → 151 not taken.
11 llvm::Function *getAcrtIOFuncFct = stdFunctionManager.getAcrtIOFuncFct();
143
4/8
✓ Branch 6 → 7 taken 11 times.
✗ Branch 6 → 92 not taken.
✓ Branch 7 → 8 taken 11 times.
✗ Branch 7 → 90 not taken.
✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 89 not taken.
✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 89 not taken.
11 stdErr = builder.CreateCall(getAcrtIOFuncFct, {builder.getInt32(/*constant for stderr*/ 2)});
144 } else {
145
3/4
✓ Branch 12 → 13 taken 702 times.
✗ Branch 12 → 151 not taken.
✓ Branch 13 → 14 taken 11 times.
✓ Branch 13 → 15 taken 691 times.
702 const char *globalName = cliOptions.targetTriple.isOSDarwin() ? "__stderrp" : "stderr";
146
2/4
✓ Branch 16 → 17 taken 702 times.
✗ Branch 16 → 93 not taken.
✓ Branch 17 → 18 taken 702 times.
✗ Branch 17 → 93 not taken.
702 module->getOrInsertGlobal(globalName, ptrTy);
147
2/4
✓ Branch 18 → 19 taken 702 times.
✗ Branch 18 → 94 not taken.
✓ Branch 19 → 20 taken 702 times.
✗ Branch 19 → 94 not taken.
702 llvm::GlobalVariable *stdErrPtr = module->getNamedGlobal(globalName);
148
1/2
✓ Branch 20 → 21 taken 702 times.
✗ Branch 20 → 151 not taken.
702 stdErrPtr->setLinkage(llvm::GlobalVariable::ExternalLinkage);
149 702 stdErrPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local);
150
2/4
✓ Branch 22 → 23 taken 702 times.
✗ Branch 22 → 95 not taken.
✓ Branch 23 → 24 taken 702 times.
✗ Branch 23 → 95 not taken.
702 stdErrPtr->setAlignment(llvm::MaybeAlign(8));
151
2/4
✓ Branch 26 → 27 taken 702 times.
✗ Branch 26 → 98 not taken.
✓ Branch 27 → 28 taken 702 times.
✗ Branch 27 → 96 not taken.
1404 stdErr = insertLoad(ptrTy, stdErrPtr);
152 }
153
154 // Create constant for error message
155
1/2
✓ Branch 31 → 32 taken 713 times.
✗ Branch 31 → 151 not taken.
713 const std::string codeLoc = node->codeLoc.toPrettyString();
156
5/10
✓ Branch 32 → 33 taken 713 times.
✗ Branch 32 → 112 not taken.
✓ Branch 33 → 34 taken 713 times.
✗ Branch 33 → 108 not taken.
✓ Branch 34 → 35 taken 713 times.
✗ Branch 34 → 106 not taken.
✓ Branch 35 → 36 taken 713 times.
✗ Branch 35 → 104 not taken.
✓ Branch 36 → 37 taken 713 times.
✗ Branch 36 → 102 not taken.
713 const std::string templateStr = "Program panicked at " + codeLoc + ": %s\n" + node->getErrorMessage() + "\n";
157
4/8
✓ Branch 43 → 44 taken 713 times.
✗ Branch 43 → 119 not taken.
✓ Branch 44 → 45 taken 713 times.
✗ Branch 44 → 117 not taken.
✓ Branch 45 → 46 taken 713 times.
✗ Branch 45 → 115 not taken.
✓ Branch 47 → 48 taken 713 times.
✗ Branch 47 → 114 not taken.
1426 llvm::GlobalVariable *globalString = builder.CreateGlobalString(templateStr, getUnusedGlobalName(ANON_GLOBAL_STRING_NAME));
158
159 // If the output should be comparable, fix alignment to 4 bytes
160
1/2
✓ Branch 51 → 52 taken 713 times.
✗ Branch 51 → 55 not taken.
713 if (cliOptions.comparableOutput)
161
2/4
✓ Branch 52 → 53 taken 713 times.
✗ Branch 52 → 125 not taken.
✓ Branch 53 → 54 taken 713 times.
✗ Branch 53 → 125 not taken.
713 globalString->setAlignment(llvm::Align(4));
162
163 // Get actual error message
164
1/2
✓ Branch 55 → 56 taken 713 times.
✗ Branch 55 → 147 not taken.
713 llvm::Value *errorObjPtr = resolveAddress(node->assignExpr);
165
2/4
✓ Branch 56 → 57 taken 713 times.
✗ Branch 56 → 147 not taken.
✓ Branch 57 → 58 taken 713 times.
✗ Branch 57 → 147 not taken.
713 llvm::Type *errorObjTy = node->assignExpr->getEvaluatedSymbolType(manIdx).toLLVMType(sourceFile);
166
1/2
✓ Branch 61 → 62 taken 713 times.
✗ Branch 61 → 126 not taken.
713 llvm::Value *errorMessagePtr = insertStructGEP(errorObjTy, errorObjPtr, 1);
167
2/4
✓ Branch 66 → 67 taken 713 times.
✗ Branch 66 → 134 not taken.
✓ Branch 67 → 68 taken 713 times.
✗ Branch 67 → 132 not taken.
713 llvm::Value *errorMessage = insertLoad(ptrTy, errorMessagePtr);
168
169 // Print the error message to stderr
170
1/2
✓ Branch 70 → 71 taken 713 times.
✗ Branch 70 → 147 not taken.
713 llvm::Function *fprintfFct = stdFunctionManager.getFPrintfFct();
171
3/6
✓ Branch 71 → 72 taken 713 times.
✗ Branch 71 → 141 not taken.
✓ Branch 73 → 74 taken 713 times.
✗ Branch 73 → 138 not taken.
✓ Branch 74 → 75 taken 713 times.
✗ Branch 74 → 138 not taken.
713 builder.CreateCall(fprintfFct, {stdErr, globalString, errorMessage});
172
173 // Cleanup the scope before calling exit()
174 // Unreachable below counts as terminator
175
2/4
✓ Branch 75 → 76 taken 713 times.
✗ Branch 75 → 147 not taken.
✓ Branch 76 → 77 taken 713 times.
✗ Branch 76 → 147 not taken.
713 terminateBlock(node->getNextOuterStmtLst());
176
177 // Generate call to exit()
178
1/2
✓ Branch 77 → 78 taken 713 times.
✗ Branch 77 → 147 not taken.
713 llvm::Function *exitFct = stdFunctionManager.getExitFct();
179
4/8
✓ Branch 78 → 79 taken 713 times.
✗ Branch 78 → 145 not taken.
✓ Branch 79 → 80 taken 713 times.
✗ Branch 79 → 143 not taken.
✓ Branch 81 → 82 taken 713 times.
✗ Branch 81 → 142 not taken.
✓ Branch 82 → 83 taken 713 times.
✗ Branch 82 → 142 not taken.
713 builder.CreateCall(exitFct, builder.getInt32(EXIT_FAILURE));
180 // Create unreachable instruction
181
1/2
✓ Branch 83 → 84 taken 713 times.
✗ Branch 83 → 147 not taken.
713 builder.CreateUnreachable();
182
183
1/2
✓ Branch 84 → 85 taken 713 times.
✗ Branch 84 → 146 not taken.
1426 return nullptr;
184 713 }
185
186 1 std::any IRGenerator::visitSysCall(const SysCallNode *node) {
187 // Determine the required number of operands.
188 // (We assume at least one argument is provided: the syscall number.)
189 1 const auto requiredRegs = static_cast<uint8_t>(node->args.size());
190
2/4
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 6 not taken.
1 assert(requiredRegs >= 1 && requiredRegs <= 6);
191
192 // Create the asm and constraint strings based on the required number of registers.
193
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 79 not taken.
1 const std::string asmString = getSysCallAsmString(requiredRegs);
194
1/2
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 77 not taken.
1 const std::string constraints = getSysCallConstraintString(requiredRegs);
195
196 // Create the LLVM function type for the inline asm with only the needed operands.
197
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 75 not taken.
1 llvm::Type *int64Ty = builder.getInt64Ty();
198
1/2
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 55 not taken.
1 const std::vector argTypes(requiredRegs, int64Ty);
199
2/4
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 58 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 58 not taken.
1 llvm::FunctionType *fctType = llvm::FunctionType::get(builder.getVoidTy(), argTypes, false);
200
1/2
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 59 not taken.
1 llvm::InlineAsm *inlineAsm = llvm::InlineAsm::get(fctType, asmString, constraints, true);
201
202 // Build the argument list (each provided argument is converted to i64).
203 1 std::vector<llvm::Value *> argValues;
204
1/2
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 71 not taken.
1 argValues.reserve(requiredRegs);
205
2/2
✓ Branch 42 → 22 taken 4 times.
✓ Branch 42 → 43 taken 1 time.
5 for (uint8_t i = 0; i < requiredRegs; i++) {
206
1/2
✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 71 not taken.
4 const AssignExprNode *argNode = node->args.at(i);
207
1/2
✓ Branch 23 → 24 taken 4 times.
✗ Branch 23 → 71 not taken.
4 const QualType &argType = argNode->getEvaluatedSymbolType(manIdx);
208
2/4
✓ Branch 24 → 25 taken 4 times.
✗ Branch 24 → 61 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 4 times.
4 assert(argType.isOneOf({TY_INT, TY_LONG, TY_SHORT, TY_BOOL, TY_BYTE, TY_PTR, TY_STRING}));
209
3/4
✓ Branch 27 → 28 taken 4 times.
✗ Branch 27 → 62 not taken.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 35 taken 3 times.
4 if (argType.isOneOf({TY_PTR, TY_STRING}))
210
5/10
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 63 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 63 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 63 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 63 not taken.
✓ Branch 33 → 34 taken 1 time.
✗ Branch 33 → 63 not taken.
1 argValues.push_back(builder.CreatePtrToInt(resolveValue(argNode), builder.getInt64Ty()));
211 else
212
5/10
✓ Branch 35 → 36 taken 3 times.
✗ Branch 35 → 65 not taken.
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 65 not taken.
✓ Branch 37 → 38 taken 3 times.
✗ Branch 37 → 65 not taken.
✓ Branch 38 → 39 taken 3 times.
✗ Branch 38 → 65 not taken.
✓ Branch 39 → 40 taken 3 times.
✗ Branch 39 → 65 not taken.
3 argValues.push_back(builder.CreateZExt(resolveValue(argNode), builder.getInt64Ty()));
213 }
214
215 // Generate the call using only the required number of arguments.
216
3/6
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 69 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 67 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 67 not taken.
1 llvm::Value *result = builder.CreateCall(inlineAsm, argValues);
217
218
1/2
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 70 not taken.
2 return LLVMExprResult{.value = result};
219 1 }
220
221 } // namespace spice::compiler
222