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 |