GCC Code Coverage Report


Directory: ../
File: src/irgenerator/GenBuiltinFunctions.cpp
Date: 2025-03-05 01:50:32
Exec Total Coverage
Lines: 103 109 94.5%
Functions: 7 7 100.0%
Branches: 157 308 51.0%

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