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 | 1485 | std::any IRGenerator::visitBuiltinCall(const BuiltinCallNode *node) { | |
15 |
2/2✓ Branch 0 (2→3) taken 711 times.
✓ Branch 1 (2→4) taken 774 times.
|
1485 | if (node->printfCall) |
16 | 711 | return visit(node->printfCall); | |
17 |
2/2✓ Branch 0 (4→5) taken 127 times.
✓ Branch 1 (4→6) taken 647 times.
|
774 | if (node->sizeofCall) |
18 | 127 | return visit(node->sizeofCall); | |
19 |
2/2✓ Branch 0 (6→7) taken 11 times.
✓ Branch 1 (6→8) taken 636 times.
|
647 | if (node->alignofCall) |
20 | 11 | return visit(node->alignofCall); | |
21 |
2/2✓ Branch 0 (8→9) taken 2 times.
✓ Branch 1 (8→10) taken 634 times.
|
636 | if (node->typeidCall) |
22 | 2 | return visit(node->typeidCall); | |
23 |
2/2✓ Branch 0 (10→11) taken 49 times.
✓ Branch 1 (10→12) taken 585 times.
|
634 | if (node->lenCall) |
24 | 49 | return visit(node->lenCall); | |
25 |
2/2✓ Branch 0 (12→13) taken 584 times.
✓ Branch 1 (12→14) taken 1 times.
|
585 | if (node->panicCall) |
26 | 584 | return visit(node->panicCall); | |
27 |
1/2✓ Branch 0 (14→15) taken 1 times.
✗ Branch 1 (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 | 711 | std::any IRGenerator::visitPrintfCall(const PrintfCallNode *node) { | |
34 | // Retrieve printf function | ||
35 |
1/2✓ Branch 0 (2→3) taken 711 times.
✗ Branch 1 (2→114) not taken.
|
711 | llvm::Function *printfFct = stdFunctionManager.getPrintfFct(); |
36 | |||
37 | // Push the template string as first argument | ||
38 | 711 | std::vector<llvm::Value *> printfArgs; | |
39 |
2/4✓ Branch 0 (5→6) taken 711 times.
✗ Branch 1 (5→75) not taken.
✓ Branch 2 (6→7) taken 711 times.
✗ Branch 3 (6→73) not taken.
|
1422 | llvm::Constant *templateString = createGlobalStringConst("printf.str.", node->templatedString, node->codeLoc); |
40 |
1/2✓ Branch 0 (9→10) taken 711 times.
✗ Branch 1 (9→79) not taken.
|
711 | printfArgs.push_back(templateString); |
41 | |||
42 | // Collect replacement arguments | ||
43 |
2/2✓ Branch 0 (62→12) taken 603 times.
✓ Branch 1 (62→63) taken 711 times.
|
1314 | for (const AssignExprNode *arg : node->args) { |
44 | // Retrieve type of argument | ||
45 |
1/2✓ Branch 0 (13→14) taken 603 times.
✗ Branch 1 (13→106) not taken.
|
603 | const QualType argSymbolType = arg->getEvaluatedSymbolType(manIdx); |
46 | |||
47 | // Re-map some values | ||
48 | llvm::Value *argVal; | ||
49 |
2/4✓ Branch 0 (14→15) taken 603 times.
✗ Branch 1 (14→106) not taken.
✗ Branch 2 (15→16) not taken.
✓ Branch 3 (15→28) taken 603 times.
|
603 | 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 0 (28→29) taken 603 times.
✗ Branch 1 (28→88) not taken.
✓ Branch 2 (29→30) taken 603 times.
✗ Branch 3 (29→88) not taken.
✓ Branch 4 (30→31) taken 58 times.
✓ Branch 5 (30→48) taken 545 times.
|
603 | } else if (argSymbolType.getBase().isStringObj()) { |
55 |
1/2✓ Branch 0 (31→32) taken 58 times.
✗ Branch 1 (31→106) not taken.
|
58 | llvm::Value *argValPtr = resolveAddress(arg); |
56 |
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); |
57 |
1/2✓ Branch 0 (37→38) taken 58 times.
✗ Branch 1 (37→90) not taken.
|
58 | argValPtr = insertStructGEP(argBaseType, argValPtr, 0); |
58 |
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); |
59 | } else { | ||
60 |
1/2✓ Branch 0 (48→49) taken 545 times.
✗ Branch 1 (48→106) not taken.
|
545 | argVal = resolveValue(arg); |
61 | } | ||
62 | |||
63 | // Extend all integer types lower than 32 bit to 32 bit | ||
64 |
4/6✓ Branch 0 (50→51) taken 603 times.
✗ Branch 1 (50→103) not taken.
✓ Branch 2 (51→52) taken 603 times.
✗ Branch 3 (51→102) not taken.
✓ Branch 4 (52→53) taken 83 times.
✓ Branch 5 (52→59) taken 520 times.
|
603 | if (argSymbolType.removeReferenceWrapper().isOneOf({TY_SHORT, TY_BYTE, TY_CHAR, TY_BOOL})) |
65 |
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()); |
66 | |||
67 |
1/2✓ Branch 0 (59→60) taken 603 times.
✗ Branch 1 (59→106) not taken.
|
603 | printfArgs.push_back(argVal); |
68 | } | ||
69 | |||
70 | // Call printf function | ||
71 |
3/6✓ Branch 0 (63→64) taken 711 times.
✗ Branch 1 (63→110) not taken.
✓ Branch 2 (65→66) taken 711 times.
✗ Branch 3 (65→108) not taken.
✓ Branch 4 (66→67) taken 711 times.
✗ Branch 5 (66→108) not taken.
|
711 | llvm::CallInst *returnValue = builder.CreateCall(printfFct, printfArgs); |
72 | |||
73 | // Add noundef attribute to template string | ||
74 |
1/2✓ Branch 0 (67→68) taken 711 times.
✗ Branch 1 (67→112) not taken.
|
711 | returnValue->addParamAttr(0, llvm::Attribute::NoUndef); |
75 | |||
76 |
1/2✓ Branch 0 (68→69) taken 711 times.
✗ Branch 1 (68→111) not taken.
|
1422 | return LLVMExprResult{.value = returnValue}; |
77 | 711 | } | |
78 | |||
79 | 127 | std::any IRGenerator::visitSizeofCall(const SizeofCallNode *node) { | |
80 | llvm::Type *type; | ||
81 |
2/2✓ Branch 0 (2→3) taken 111 times.
✓ Branch 1 (2→7) taken 16 times.
|
127 | if (node->isType) { // Size of type |
82 |
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)); |
83 | } else { // Size of value | ||
84 |
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); |
85 | } | ||
86 | // Calculate size at compile-time | ||
87 |
1/2✓ Branch 0 (11→12) taken 127 times.
✗ Branch 1 (11→22) not taken.
|
127 | const llvm::TypeSize sizeInBytes = module->getDataLayout().getTypeAllocSize(type); |
88 | |||
89 | // Return size value | ||
90 |
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); |
91 |
1/2✓ Branch 0 (14→15) taken 127 times.
✗ Branch 1 (14→21) not taken.
|
254 | return LLVMExprResult{.value = sizeValue}; |
92 | } | ||
93 | |||
94 | 11 | std::any IRGenerator::visitAlignofCall(const AlignofCallNode *node) { | |
95 | llvm::Type *type; | ||
96 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→7) taken 10 times.
|
11 | if (node->isType) { // Align of type |
97 |
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)); |
98 | } else { // Align of value | ||
99 |
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); |
100 | } | ||
101 | // Calculate size at compile-time | ||
102 |
1/2✓ Branch 0 (11→12) taken 11 times.
✗ Branch 1 (11→22) not taken.
|
11 | const llvm::Align alignmentInBytes = module->getDataLayout().getABITypeAlign(type); |
103 | |||
104 | // Return align value | ||
105 |
1/2✓ Branch 0 (13→14) taken 11 times.
✗ Branch 1 (13→22) not taken.
|
11 | llvm::Value *alignValue = builder.getInt64(alignmentInBytes.value()); |
106 |
1/2✓ Branch 0 (14→15) taken 11 times.
✗ Branch 1 (14→21) not taken.
|
22 | return LLVMExprResult{.value = alignValue}; |
107 | } | ||
108 | |||
109 | 2 | std::any IRGenerator::visitTypeidCall(const TypeidCallNode *node) { | |
110 | // Return type id value | ||
111 |
1/2✓ Branch 0 (2→3) taken 2 times.
✗ Branch 1 (2→11) not taken.
|
2 | const QualType qualType = node->assignExpr->getEvaluatedSymbolType(manIdx); |
112 |
1/2✓ Branch 0 (4→5) taken 2 times.
✗ Branch 1 (4→11) not taken.
|
2 | const uint64_t typeId = TypeRegistry::getTypeHash(*qualType.getType()); |
113 |
1/2✓ Branch 0 (5→6) taken 2 times.
✗ Branch 1 (5→11) not taken.
|
2 | llvm::Value *typeIdValue = builder.getInt64(typeId); |
114 |
1/2✓ Branch 0 (6→7) taken 2 times.
✗ Branch 1 (6→10) not taken.
|
4 | return LLVMExprResult{.value = typeIdValue}; |
115 | } | ||
116 | |||
117 | 49 | std::any IRGenerator::visitLenCall(const LenCallNode *node) { | |
118 | // Check if the length is fixed and known via the symbol type | ||
119 |
1/2✓ Branch 0 (2→3) taken 49 times.
✗ Branch 1 (2→32) not taken.
|
49 | QualType symbolType = node->assignExpr->getEvaluatedSymbolType(manIdx); |
120 |
1/2✓ Branch 0 (3→4) taken 49 times.
✗ Branch 1 (3→26) not taken.
|
49 | symbolType = symbolType.removeReferenceWrapper(); |
121 | |||
122 | llvm::Value *lengthValue; | ||
123 |
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)) { |
124 |
1/2✓ Branch 0 (6→7) taken 25 times.
✗ Branch 1 (6→32) not taken.
|
25 | llvm::Function *getRawLengthFct = stdFunctionManager.getStringGetRawLengthStringFct(); |
125 |
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)); |
126 | } else { | ||
127 |
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); |
128 | // Return length value | ||
129 |
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()); |
130 | } | ||
131 |
1/2✓ Branch 0 (22→23) taken 49 times.
✗ Branch 1 (22→31) not taken.
|
98 | return LLVMExprResult{.value = lengthValue}; |
132 | } | ||
133 | |||
134 | 584 | std::any IRGenerator::visitPanicCall(const PanicCallNode *node) { | |
135 |
1/2✓ Branch 0 (2→3) taken 584 times.
✗ Branch 1 (2→142) not taken.
|
584 | llvm::PointerType *ptrTy = builder.getPtrTy(); |
136 | |||
137 | // Get value for stderr | ||
138 | llvm::Value *stdErr; | ||
139 |
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") { |
140 | ✗ | llvm::Function *getAcrtIOFuncFct = stdFunctionManager.getAcrtIOFuncFct(); | |
141 | ✗ | stdErr = builder.CreateCall(getAcrtIOFuncFct, {builder.getInt32(/*constant for stderr*/ 2)}); | |
142 | } else { | ||
143 | 584 | constexpr auto globalName = "stderr"; | |
144 |
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); |
145 |
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); |
146 |
1/2✓ Branch 0 (16→17) taken 584 times.
✗ Branch 1 (16→142) not taken.
|
584 | stdErrPtr->setLinkage(llvm::GlobalVariable::ExternalLinkage); |
147 | 584 | stdErrPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local); | |
148 |
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)); |
149 |
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); |
150 | } | ||
151 | |||
152 | // Create constant for error message | ||
153 |
1/2✓ Branch 0 (27→28) taken 584 times.
✗ Branch 1 (27→142) not taken.
|
584 | const std::string codeLoc = node->codeLoc.toPrettyString(); |
154 |
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"; |
155 |
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)); |
156 | |||
157 | // Get actual error message | ||
158 |
1/2✓ Branch 0 (47→48) taken 584 times.
✗ Branch 1 (47→138) not taken.
|
584 | llvm::Value *errorObjPtr = resolveAddress(node->assignExpr); |
159 |
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); |
160 |
1/2✓ Branch 0 (53→54) taken 584 times.
✗ Branch 1 (53→117) not taken.
|
584 | llvm::Value *errorMessagePtr = insertStructGEP(errorObjTy, errorObjPtr, 1); |
161 |
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); |
162 | |||
163 | // Print the error message to stderr | ||
164 |
1/2✓ Branch 0 (62→63) taken 584 times.
✗ Branch 1 (62→138) not taken.
|
584 | llvm::Function *fprintfFct = stdFunctionManager.getFPrintfFct(); |
165 |
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}); |
166 | |||
167 | // Generate call to exit() | ||
168 |
1/2✓ Branch 0 (67→68) taken 584 times.
✗ Branch 1 (67→138) not taken.
|
584 | llvm::Function *exitFct = stdFunctionManager.getExitFct(); |
169 |
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)); |
170 | // Create unreachable instruction | ||
171 |
1/2✓ Branch 0 (73→74) taken 584 times.
✗ Branch 1 (73→138) not taken.
|
584 | builder.CreateUnreachable(); |
172 | // Unreachable counts as terminator | ||
173 |
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()); |
174 | |||
175 |
1/2✓ Branch 0 (76→77) taken 584 times.
✗ Branch 1 (76→137) not taken.
|
1168 | return nullptr; |
176 | 584 | } | |
177 | |||
178 | 1 | std::any IRGenerator::visitSysCall(const SysCallNode *node) { | |
179 | // Determine the required number of operands. | ||
180 | // (We assume at least one argument is provided: the syscall number.) | ||
181 | 1 | const auto requiredRegs = static_cast<uint8_t>(node->args.size()); | |
182 |
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); |
183 | |||
184 | // Create the asm and constraint strings based on the required number of registers. | ||
185 |
1/2✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→79) not taken.
|
1 | const std::string asmString = getSysCallAsmString(requiredRegs); |
186 |
1/2✓ Branch 0 (8→9) taken 1 times.
✗ Branch 1 (8→77) not taken.
|
1 | const std::string constraints = getSysCallConstraintString(requiredRegs); |
187 | |||
188 | // Create the LLVM function type for the inline asm with only the needed operands. | ||
189 |
1/2✓ Branch 0 (9→10) taken 1 times.
✗ Branch 1 (9→75) not taken.
|
1 | llvm::Type *int64Ty = builder.getInt64Ty(); |
190 |
1/2✓ Branch 0 (12→13) taken 1 times.
✗ Branch 1 (12→55) not taken.
|
1 | const std::vector argTypes(requiredRegs, int64Ty); |
191 |
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); |
192 |
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); |
193 | |||
194 | // Build the argument list (each provided argument is converted to i64). | ||
195 | 1 | std::vector<llvm::Value *> argValues; | |
196 |
1/2✓ Branch 0 (20→21) taken 1 times.
✗ Branch 1 (20→71) not taken.
|
1 | argValues.reserve(requiredRegs); |
197 |
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++) { |
198 |
1/2✓ Branch 0 (22→23) taken 4 times.
✗ Branch 1 (22→71) not taken.
|
4 | const AssignExprNode *argNode = node->args.at(i); |
199 |
1/2✓ Branch 0 (23→24) taken 4 times.
✗ Branch 1 (23→71) not taken.
|
4 | const QualType &argType = argNode->getEvaluatedSymbolType(manIdx); |
200 |
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})); |
201 |
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})) |
202 |
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())); |
203 | else | ||
204 |
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())); |
205 | } | ||
206 | |||
207 | // Generate the call using only the required number of arguments. | ||
208 |
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); |
209 | |||
210 |
1/2✓ Branch 0 (47→48) taken 1 times.
✗ Branch 1 (47→70) not taken.
|
2 | return LLVMExprResult{.value = result}; |
211 | 1 | } | |
212 | |||
213 | } // namespace spice::compiler | ||
214 |