src/irgenerator/GenBuiltinFunctions.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "IRGenerator.h" | ||
| 4 | |||
| 5 | #include <ast/ASTNodes.h> | ||
| 6 | #include <driver/Driver.h> | ||
| 7 | #include <global/GlobalResourceManager.h> | ||
| 8 | #include <global/TypeRegistry.h> | ||
| 9 | #include <typechecker/Builtins.h> | ||
| 10 | #include <typechecker/TypeChecker.h> | ||
| 11 | |||
| 12 | #include <llvm/IR/InlineAsm.h> | ||
| 13 | #include <llvm/IR/Module.h> | ||
| 14 | |||
| 15 | namespace spice::compiler { | ||
| 16 | |||
| 17 | 1777 | std::any IRGenerator::visitBuiltinCall(const FctCallNode *node) { | |
| 18 | // If we have a compile time value, but the computation is still there, we can simply use this constant value | ||
| 19 |
2/2✓ Branch 3 → 4 taken 206 times.
✓ Branch 3 → 10 taken 1571 times.
|
1777 | if (node->hasCompileTimeValue(manIdx)) { |
| 20 |
2/4✓ Branch 5 → 6 taken 206 times.
✗ Branch 5 → 25 not taken.
✓ Branch 6 → 7 taken 206 times.
✗ Branch 6 → 25 not taken.
|
206 | llvm::Constant *value = getConst(node->getCompileTimeValue(manIdx), node->getEvaluatedSymbolType(manIdx), node); |
| 21 |
1/2✓ Branch 7 → 8 taken 206 times.
✗ Branch 7 → 26 not taken.
|
412 | return LLVMExprResult{.constant = value}; |
| 22 | } | ||
| 23 | |||
| 24 | // If we need to perform runtime actions, call the specified IRGenerator delegate | ||
| 25 |
2/4✓ Branch 11 → 12 taken 1571 times.
✗ Branch 11 → 27 not taken.
✓ Branch 12 → 13 taken 1571 times.
✗ Branch 12 → 14 not taken.
|
1571 | assert(BUILTIN_FUNCTIONS_MAP.contains(node->fqFunctionName) && "Builtin function not implemented!"); |
| 26 |
1/2✓ Branch 16 → 17 taken 1571 times.
✗ Branch 16 → 28 not taken.
|
1571 | const BuiltinFunctionInfo &info = BUILTIN_FUNCTIONS_MAP.find(node->fqFunctionName)->second; |
| 27 |
1/2✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1571 times.
|
1571 | assert(info.irGeneratorVisitMethod != nullptr); |
| 28 |
1/2✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 1571 times.
|
1571 | return (this->*info.irGeneratorVisitMethod)(node); |
| 29 | } | ||
| 30 | |||
| 31 | 806 | std::any IRGenerator::visitBuiltinPrintfCall(const FctCallNode *node) { | |
| 32 | // Retrieve templated string | ||
| 33 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 806 times.
|
806 | assert(node->hasArgs); |
| 34 | 806 | const ExprNode *firstArg = node->argLst->args.front(); | |
| 35 |
5/10✓ Branch 5 → 6 taken 806 times.
✗ Branch 5 → 133 not taken.
✓ Branch 6 → 7 taken 806 times.
✗ Branch 6 → 133 not taken.
✓ Branch 7 → 8 taken 806 times.
✗ Branch 7 → 11 not taken.
✓ Branch 8 → 9 taken 806 times.
✗ Branch 8 → 133 not taken.
✓ Branch 9 → 10 taken 806 times.
✗ Branch 9 → 11 not taken.
|
806 | assert(firstArg->getEvaluatedSymbolType(manIdx).is(TY_STRING) && firstArg->hasCompileTimeValue(manIdx)); |
| 36 |
1/2✓ Branch 12 → 13 taken 806 times.
✗ Branch 12 → 133 not taken.
|
806 | const size_t stringOffset = firstArg->getCompileTimeValue(manIdx).stringValueOffset; |
| 37 |
2/4✓ Branch 13 → 14 taken 806 times.
✗ Branch 13 → 133 not taken.
✓ Branch 14 → 15 taken 806 times.
✗ Branch 14 → 133 not taken.
|
806 | const std::string templatedString = resourceManager.compileTimeStringValues.at(stringOffset); |
| 38 | |||
| 39 | // Push the template string as first argument | ||
| 40 | 806 | std::vector<llvm::Value *> printfArgs; | |
| 41 |
2/4✓ Branch 17 → 18 taken 806 times.
✗ Branch 17 → 93 not taken.
✓ Branch 18 → 19 taken 806 times.
✗ Branch 18 → 91 not taken.
|
1612 | llvm::Constant *templateString = createGlobalStringConst("printf.str.", templatedString, node->codeLoc); |
| 42 |
1/2✓ Branch 21 → 22 taken 806 times.
✗ Branch 21 → 97 not taken.
|
806 | printfArgs.push_back(templateString); |
| 43 | |||
| 44 | // Collect replacement arguments | ||
| 45 |
2/2✓ Branch 73 → 23 taken 666 times.
✓ Branch 73 → 74 taken 806 times.
|
1472 | for (size_t argIdx = 1; argIdx < node->argLst->args.size(); argIdx++) { |
| 46 |
1/2✓ Branch 23 → 24 taken 666 times.
✗ Branch 23 → 124 not taken.
|
666 | const ExprNode *arg = node->argLst->args.at(argIdx); |
| 47 | // Retrieve type of argument | ||
| 48 |
1/2✓ Branch 24 → 25 taken 666 times.
✗ Branch 24 → 124 not taken.
|
666 | const QualType argSymbolType = arg->getEvaluatedSymbolType(manIdx); |
| 49 | |||
| 50 | // Re-map some values | ||
| 51 | llvm::Value *argVal; | ||
| 52 |
2/4✓ Branch 25 → 26 taken 666 times.
✗ Branch 25 → 124 not taken.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 39 taken 666 times.
|
666 | if (argSymbolType.isArray()) { |
| 53 | // ToDo: Check if GEP can be removed | ||
| 54 | ✗ | llvm::Value *argValPtr = resolveAddress(arg); | |
| 55 | ✗ | llvm::Value *indices[2] = {builder.getInt64(0), builder.getInt32(0)}; | |
| 56 | ✗ | llvm::Type *argType = argSymbolType.toLLVMType(sourceFile); | |
| 57 | ✗ | argVal = insertInBoundsGEP(argType, argValPtr, indices); | |
| 58 |
4/6✓ Branch 39 → 40 taken 666 times.
✗ Branch 39 → 106 not taken.
✓ Branch 40 → 41 taken 666 times.
✗ Branch 40 → 106 not taken.
✓ Branch 41 → 42 taken 61 times.
✓ Branch 41 → 59 taken 605 times.
|
666 | } else if (argSymbolType.getBase().isStringObj()) { |
| 59 |
1/2✓ Branch 42 → 43 taken 61 times.
✗ Branch 42 → 124 not taken.
|
61 | llvm::Value *argValPtr = resolveAddress(arg); |
| 60 |
2/4✓ Branch 43 → 44 taken 61 times.
✗ Branch 43 → 107 not taken.
✓ Branch 44 → 45 taken 61 times.
✗ Branch 44 → 107 not taken.
|
61 | llvm::Type *argBaseType = argSymbolType.getBase().toLLVMType(sourceFile); |
| 61 |
1/2✓ Branch 48 → 49 taken 61 times.
✗ Branch 48 → 108 not taken.
|
61 | argValPtr = insertStructGEP(argBaseType, argValPtr, 0); |
| 62 |
3/6✓ Branch 53 → 54 taken 61 times.
✗ Branch 53 → 116 not taken.
✓ Branch 54 → 55 taken 61 times.
✗ Branch 54 → 114 not taken.
✓ Branch 55 → 56 taken 61 times.
✗ Branch 55 → 114 not taken.
|
122 | argVal = insertLoad(builder.getPtrTy(), argValPtr); |
| 63 | } else { | ||
| 64 |
1/2✓ Branch 59 → 60 taken 605 times.
✗ Branch 59 → 124 not taken.
|
605 | argVal = resolveValue(arg); |
| 65 | } | ||
| 66 | |||
| 67 | // Extend all integer types lower than 32 bit to 32 bit | ||
| 68 |
4/6✓ Branch 61 → 62 taken 666 times.
✗ Branch 61 → 121 not taken.
✓ Branch 62 → 63 taken 666 times.
✗ Branch 62 → 120 not taken.
✓ Branch 63 → 64 taken 102 times.
✓ Branch 63 → 70 taken 564 times.
|
666 | if (argSymbolType.removeReferenceWrapper().isOneOf({TY_SHORT, TY_BYTE, TY_CHAR, TY_BOOL})) |
| 69 |
5/10✓ Branch 64 → 65 taken 102 times.
✗ Branch 64 → 123 not taken.
✓ Branch 65 → 66 taken 102 times.
✗ Branch 65 → 122 not taken.
✓ Branch 66 → 67 taken 102 times.
✗ Branch 66 → 122 not taken.
✓ Branch 67 → 68 taken 102 times.
✗ Branch 67 → 122 not taken.
✓ Branch 68 → 69 taken 102 times.
✗ Branch 68 → 122 not taken.
|
102 | argVal = builder.CreateIntCast(argVal, builder.getInt32Ty(), argSymbolType.removeReferenceWrapper().isSigned()); |
| 70 | |||
| 71 |
1/2✓ Branch 70 → 71 taken 666 times.
✗ Branch 70 → 124 not taken.
|
666 | printfArgs.push_back(argVal); |
| 72 | } | ||
| 73 | |||
| 74 | // Call printf function | ||
| 75 |
1/2✓ Branch 74 → 75 taken 806 times.
✗ Branch 74 → 129 not taken.
|
806 | llvm::Function *printfFct = stdFunctionManager.getPrintfFct(); |
| 76 |
3/6✓ Branch 75 → 76 taken 806 times.
✗ Branch 75 → 127 not taken.
✓ Branch 77 → 78 taken 806 times.
✗ Branch 77 → 125 not taken.
✓ Branch 78 → 79 taken 806 times.
✗ Branch 78 → 125 not taken.
|
806 | llvm::CallInst *callInst = builder.CreateCall(printfFct, printfArgs); |
| 77 | |||
| 78 | // Add noundef attribute to return value and all arguments | ||
| 79 |
1/2✓ Branch 79 → 80 taken 806 times.
✗ Branch 79 → 129 not taken.
|
806 | callInst->addRetAttr(llvm::Attribute::NoUndef); |
| 80 |
2/2✓ Branch 84 → 81 taken 1472 times.
✓ Branch 84 → 85 taken 806 times.
|
2278 | for (size_t i = 0; i < printfArgs.size(); i++) |
| 81 |
1/2✓ Branch 81 → 82 taken 1472 times.
✗ Branch 81 → 129 not taken.
|
1472 | callInst->addParamAttr(i, llvm::Attribute::NoUndef); |
| 82 | |||
| 83 |
1/2✓ Branch 85 → 86 taken 806 times.
✗ Branch 85 → 128 not taken.
|
1612 | return LLVMExprResult{.value = callInst}; |
| 84 | 806 | } | |
| 85 | |||
| 86 | 35 | std::any IRGenerator::visitBuiltinLenCall(const FctCallNode *node) { | |
| 87 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 35 times.
|
35 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_LEN); |
| 88 | |||
| 89 | // Check if the length is fixed and known via the symbol type | ||
| 90 | 35 | const ExprNode *argNode = node->argLst->args.front(); | |
| 91 |
1/2✓ Branch 7 → 8 taken 35 times.
✗ Branch 7 → 28 not taken.
|
35 | QualType symbolType = argNode->getEvaluatedSymbolType(manIdx); |
| 92 |
1/2✓ Branch 8 → 9 taken 35 times.
✗ Branch 8 → 22 not taken.
|
35 | symbolType = symbolType.removeReferenceWrapper(); |
| 93 |
2/4✓ Branch 9 → 10 taken 35 times.
✗ Branch 9 → 28 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 35 times.
|
35 | assert(symbolType.is(TY_STRING)); |
| 94 | |||
| 95 |
1/2✓ Branch 12 → 13 taken 35 times.
✗ Branch 12 → 28 not taken.
|
35 | llvm::Function *getRawLengthFct = stdFunctionManager.getStringGetRawLengthStringFct(); |
| 96 |
4/8✓ Branch 13 → 14 taken 35 times.
✗ Branch 13 → 26 not taken.
✓ Branch 14 → 15 taken 35 times.
✗ Branch 14 → 24 not taken.
✓ Branch 16 → 17 taken 35 times.
✗ Branch 16 → 23 not taken.
✓ Branch 17 → 18 taken 35 times.
✗ Branch 17 → 23 not taken.
|
35 | llvm::Value *lengthValue = builder.CreateCall(getRawLengthFct, resolveValue(argNode)); |
| 97 |
1/2✓ Branch 18 → 19 taken 35 times.
✗ Branch 18 → 27 not taken.
|
70 | return LLVMExprResult{.value = lengthValue}; |
| 98 | } | ||
| 99 | |||
| 100 | 729 | std::any IRGenerator::visitBuiltinPanicCall(const FctCallNode *node) { | |
| 101 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 729 times.
|
729 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PANIC); |
| 102 | |||
| 103 |
1/2✓ Branch 6 → 7 taken 729 times.
✗ Branch 6 → 158 not taken.
|
729 | llvm::PointerType *ptrTy = builder.getPtrTy(); |
| 104 | |||
| 105 | // Get value for stderr | ||
| 106 | llvm::Value *stdErr; | ||
| 107 |
2/2✓ Branch 8 → 9 taken 11 times.
✓ Branch 8 → 16 taken 718 times.
|
729 | if (cliOptions.targetTriple.isOSWindows()) { |
| 108 |
1/2✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 158 not taken.
|
11 | llvm::Function *getAcrtIOFuncFct = stdFunctionManager.getAcrtIOFuncFct(); |
| 109 |
4/8✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 99 not taken.
✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 97 not taken.
✓ Branch 13 → 14 taken 11 times.
✗ Branch 13 → 96 not taken.
✓ Branch 14 → 15 taken 11 times.
✗ Branch 14 → 96 not taken.
|
11 | stdErr = builder.CreateCall(getAcrtIOFuncFct, {builder.getInt32(/*constant for stderr*/ 2)}); |
| 110 | } else { | ||
| 111 |
3/4✓ Branch 16 → 17 taken 718 times.
✗ Branch 16 → 158 not taken.
✓ Branch 17 → 18 taken 11 times.
✓ Branch 17 → 19 taken 707 times.
|
718 | const char *globalName = cliOptions.targetTriple.isOSDarwin() ? "__stderrp" : "stderr"; |
| 112 |
2/4✓ Branch 20 → 21 taken 718 times.
✗ Branch 20 → 100 not taken.
✓ Branch 21 → 22 taken 718 times.
✗ Branch 21 → 100 not taken.
|
718 | module->getOrInsertGlobal(globalName, ptrTy); |
| 113 |
2/4✓ Branch 22 → 23 taken 718 times.
✗ Branch 22 → 101 not taken.
✓ Branch 23 → 24 taken 718 times.
✗ Branch 23 → 101 not taken.
|
718 | llvm::GlobalVariable *stdErrPtr = module->getNamedGlobal(globalName); |
| 114 |
1/2✓ Branch 24 → 25 taken 718 times.
✗ Branch 24 → 158 not taken.
|
718 | stdErrPtr->setLinkage(llvm::GlobalVariable::ExternalLinkage); |
| 115 | 718 | stdErrPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local); | |
| 116 |
2/4✓ Branch 26 → 27 taken 718 times.
✗ Branch 26 → 102 not taken.
✓ Branch 27 → 28 taken 718 times.
✗ Branch 27 → 102 not taken.
|
718 | stdErrPtr->setAlignment(llvm::MaybeAlign(8)); |
| 117 |
2/4✓ Branch 30 → 31 taken 718 times.
✗ Branch 30 → 105 not taken.
✓ Branch 31 → 32 taken 718 times.
✗ Branch 31 → 103 not taken.
|
1436 | stdErr = insertLoad(ptrTy, stdErrPtr); |
| 118 | } | ||
| 119 | |||
| 120 | // Create constant for error message | ||
| 121 |
1/2✓ Branch 35 → 36 taken 729 times.
✗ Branch 35 → 158 not taken.
|
729 | const std::string codeLoc = node->codeLoc.toPrettyString(); |
| 122 |
5/10✓ Branch 36 → 37 taken 729 times.
✗ Branch 36 → 119 not taken.
✓ Branch 37 → 38 taken 729 times.
✗ Branch 37 → 115 not taken.
✓ Branch 38 → 39 taken 729 times.
✗ Branch 38 → 113 not taken.
✓ Branch 39 → 40 taken 729 times.
✗ Branch 39 → 111 not taken.
✓ Branch 40 → 41 taken 729 times.
✗ Branch 40 → 109 not taken.
|
729 | const std::string templateStr = "Program panicked at " + codeLoc + ": %s\n" + node->getErrorMessage() + "\n"; |
| 123 |
4/8✓ Branch 47 → 48 taken 729 times.
✗ Branch 47 → 126 not taken.
✓ Branch 48 → 49 taken 729 times.
✗ Branch 48 → 124 not taken.
✓ Branch 49 → 50 taken 729 times.
✗ Branch 49 → 122 not taken.
✓ Branch 51 → 52 taken 729 times.
✗ Branch 51 → 121 not taken.
|
1458 | llvm::GlobalVariable *globalString = builder.CreateGlobalString(templateStr, getUnusedGlobalName(ANON_GLOBAL_STRING_NAME)); |
| 124 | |||
| 125 | // If the output should be comparable, fix alignment to 4 bytes | ||
| 126 |
1/2✓ Branch 55 → 56 taken 729 times.
✗ Branch 55 → 59 not taken.
|
729 | if (cliOptions.comparableOutput) |
| 127 |
2/4✓ Branch 56 → 57 taken 729 times.
✗ Branch 56 → 132 not taken.
✓ Branch 57 → 58 taken 729 times.
✗ Branch 57 → 132 not taken.
|
729 | globalString->setAlignment(llvm::Align(4)); |
| 128 | |||
| 129 | // Get actual error message | ||
| 130 |
1/2✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 729 times.
|
729 | assert(node->hasArgs); |
| 131 | 729 | const ExprNode *assignExpr = node->argLst->args.front(); | |
| 132 |
1/2✓ Branch 62 → 63 taken 729 times.
✗ Branch 62 → 154 not taken.
|
729 | llvm::Value *errorObjPtr = resolveAddress(assignExpr); |
| 133 |
2/4✓ Branch 63 → 64 taken 729 times.
✗ Branch 63 → 154 not taken.
✓ Branch 64 → 65 taken 729 times.
✗ Branch 64 → 154 not taken.
|
729 | llvm::Type *errorObjTy = assignExpr->getEvaluatedSymbolType(manIdx).toLLVMType(sourceFile); |
| 134 |
1/2✓ Branch 68 → 69 taken 729 times.
✗ Branch 68 → 133 not taken.
|
729 | llvm::Value *errorMessagePtr = insertStructGEP(errorObjTy, errorObjPtr, 1); |
| 135 |
2/4✓ Branch 73 → 74 taken 729 times.
✗ Branch 73 → 141 not taken.
✓ Branch 74 → 75 taken 729 times.
✗ Branch 74 → 139 not taken.
|
729 | llvm::Value *errorMessage = insertLoad(ptrTy, errorMessagePtr); |
| 136 | |||
| 137 | // Print the error message to stderr | ||
| 138 |
1/2✓ Branch 77 → 78 taken 729 times.
✗ Branch 77 → 154 not taken.
|
729 | llvm::Function *fprintfFct = stdFunctionManager.getFPrintfFct(); |
| 139 |
3/6✓ Branch 78 → 79 taken 729 times.
✗ Branch 78 → 148 not taken.
✓ Branch 80 → 81 taken 729 times.
✗ Branch 80 → 145 not taken.
✓ Branch 81 → 82 taken 729 times.
✗ Branch 81 → 145 not taken.
|
729 | builder.CreateCall(fprintfFct, {stdErr, globalString, errorMessage}); |
| 140 | |||
| 141 | // Cleanup the scope before calling exit() | ||
| 142 | // Unreachable below counts as terminator | ||
| 143 |
2/4✓ Branch 82 → 83 taken 729 times.
✗ Branch 82 → 154 not taken.
✓ Branch 83 → 84 taken 729 times.
✗ Branch 83 → 154 not taken.
|
729 | terminateBlock(node->getNextOuterStmtLst()); |
| 144 | |||
| 145 | // Generate call to exit() | ||
| 146 |
1/2✓ Branch 84 → 85 taken 729 times.
✗ Branch 84 → 154 not taken.
|
729 | llvm::Function *exitFct = stdFunctionManager.getExitFct(); |
| 147 |
4/8✓ Branch 85 → 86 taken 729 times.
✗ Branch 85 → 152 not taken.
✓ Branch 86 → 87 taken 729 times.
✗ Branch 86 → 150 not taken.
✓ Branch 88 → 89 taken 729 times.
✗ Branch 88 → 149 not taken.
✓ Branch 89 → 90 taken 729 times.
✗ Branch 89 → 149 not taken.
|
729 | builder.CreateCall(exitFct, builder.getInt32(EXIT_FAILURE)); |
| 148 | // Create unreachable instruction | ||
| 149 |
1/2✓ Branch 90 → 91 taken 729 times.
✗ Branch 90 → 154 not taken.
|
729 | builder.CreateUnreachable(); |
| 150 | |||
| 151 |
1/2✓ Branch 91 → 92 taken 729 times.
✗ Branch 91 → 153 not taken.
|
1458 | return nullptr; |
| 152 | 729 | } | |
| 153 | |||
| 154 | 1 | std::any IRGenerator::visitBuiltinSyscallCall(const FctCallNode *node) { | |
| 155 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_SYSCALL); |
| 156 | |||
| 157 | // Determine the required number of operands. | ||
| 158 | // (We assume at least one argument is provided: the syscall number) | ||
| 159 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1 time.
|
1 | assert(node->hasArgs); |
| 160 | 1 | const auto requiredRegs = static_cast<uint8_t>(node->argLst->args.size()); | |
| 161 |
2/4✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 12 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 12 not taken.
|
1 | assert(requiredRegs >= 1 && requiredRegs <= 6); |
| 162 | |||
| 163 | // Create the asm and constraint strings based on the required number of registers. | ||
| 164 |
1/2✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 85 not taken.
|
1 | const std::string asmString = getSysCallAsmString(requiredRegs); |
| 165 |
1/2✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 83 not taken.
|
1 | const std::string constraints = getSysCallConstraintString(requiredRegs); |
| 166 | |||
| 167 | // Create the LLVM function type for the inline asm with only the needed operands. | ||
| 168 |
1/2✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 81 not taken.
|
1 | llvm::Type *int64Ty = builder.getInt64Ty(); |
| 169 |
1/2✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 61 not taken.
|
1 | const std::vector argTypes(requiredRegs, int64Ty); |
| 170 |
2/4✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 64 not taken.
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 64 not taken.
|
1 | llvm::FunctionType *fctType = llvm::FunctionType::get(builder.getVoidTy(), argTypes, false); |
| 171 |
1/2✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 65 not taken.
|
1 | llvm::InlineAsm *inlineAsm = llvm::InlineAsm::get(fctType, asmString, constraints, true); |
| 172 | |||
| 173 | // Build the argument list (each provided argument is converted to i64). | ||
| 174 | 1 | std::vector<llvm::Value *> argValues; | |
| 175 |
1/2✓ Branch 26 → 27 taken 1 time.
✗ Branch 26 → 77 not taken.
|
1 | argValues.reserve(requiredRegs); |
| 176 |
2/2✓ Branch 48 → 28 taken 4 times.
✓ Branch 48 → 49 taken 1 time.
|
5 | for (uint8_t i = 0; i < requiredRegs; i++) { |
| 177 |
1/2✓ Branch 28 → 29 taken 4 times.
✗ Branch 28 → 77 not taken.
|
4 | const ExprNode *argNode = node->argLst->args.at(i); |
| 178 |
1/2✓ Branch 29 → 30 taken 4 times.
✗ Branch 29 → 77 not taken.
|
4 | const QualType &argType = argNode->getEvaluatedSymbolType(manIdx); |
| 179 |
2/4✓ Branch 30 → 31 taken 4 times.
✗ Branch 30 → 67 not taken.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 4 times.
|
4 | assert(argType.isOneOf({TY_INT, TY_LONG, TY_SHORT, TY_BOOL, TY_BYTE, TY_PTR, TY_STRING})); |
| 180 |
3/4✓ Branch 33 → 34 taken 4 times.
✗ Branch 33 → 68 not taken.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 41 taken 3 times.
|
4 | if (argType.isOneOf({TY_PTR, TY_STRING})) |
| 181 |
5/10✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 69 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 69 not taken.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 69 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 69 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 69 not taken.
|
1 | argValues.push_back(builder.CreatePtrToInt(resolveValue(argNode), builder.getInt64Ty())); |
| 182 | else | ||
| 183 |
5/10✓ Branch 41 → 42 taken 3 times.
✗ Branch 41 → 71 not taken.
✓ Branch 42 → 43 taken 3 times.
✗ Branch 42 → 71 not taken.
✓ Branch 43 → 44 taken 3 times.
✗ Branch 43 → 71 not taken.
✓ Branch 44 → 45 taken 3 times.
✗ Branch 44 → 71 not taken.
✓ Branch 45 → 46 taken 3 times.
✗ Branch 45 → 71 not taken.
|
3 | argValues.push_back(builder.CreateZExt(resolveValue(argNode), builder.getInt64Ty())); |
| 184 | } | ||
| 185 | |||
| 186 | // Generate the call using only the required number of arguments. | ||
| 187 |
3/6✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 75 not taken.
✓ Branch 51 → 52 taken 1 time.
✗ Branch 51 → 73 not taken.
✓ Branch 52 → 53 taken 1 time.
✗ Branch 52 → 73 not taken.
|
1 | llvm::Value *result = builder.CreateCall(inlineAsm, argValues); |
| 188 | |||
| 189 |
1/2✓ Branch 53 → 54 taken 1 time.
✗ Branch 53 → 76 not taken.
|
2 | return LLVMExprResult{.value = result}; |
| 190 | 1 | } | |
| 191 | |||
| 192 | } // namespace spice::compiler | ||
| 193 |