GCC Code Coverage Report


Directory: ../
File: src/irgenerator/StdFunctionManager.cpp
Date: 2025-11-04 23:06:20
Coverage Exec Excl Total
Lines: 90.5% 105 0 116
Functions: 90.0% 18 0 20
Branches: 48.5% 94 0 194

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "StdFunctionManager.h"
4
5 #include <llvm/IR/Module.h>
6
7 #include <SourceFile.h>
8 #include <global/GlobalResourceManager.h>
9 #include <irgenerator/NameMangling.h>
10 #include <model/Function.h>
11
12 namespace spice::compiler {
13
14 908 StdFunctionManager::StdFunctionManager(SourceFile *sourceFile, GlobalResourceManager &resourceManager, llvm::Module *module)
15
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 906 times.
908 : sourceFile(sourceFile), context(resourceManager.cliOptions.useLTO ? resourceManager.ltoContext : sourceFile->context),
16 908 builder(sourceFile->builder), module(module) {}
17
18 1494 llvm::Function *StdFunctionManager::getPrintfFct() const {
19
3/6
✓ Branch 2 → 3 taken 1494 times.
✗ Branch 2 → 17 not taken.
✓ Branch 4 → 5 taken 1494 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 1494 times.
✗ Branch 5 → 17 not taken.
1494 llvm::Function *printfFct = getFunction("printf", builder.getInt32Ty(), builder.getPtrTy(), true);
20 // Set attributes
21 1494 printfFct->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local);
22 1494 printfFct->addFnAttr(llvm::Attribute::NoFree);
23 1494 printfFct->addFnAttr(llvm::Attribute::NoUnwind);
24 1494 printfFct->addParamAttr(0, llvm::Attribute::getWithCaptureInfo(context, llvm::CaptureInfo::none()));
25 1494 printfFct->addParamAttr(0, llvm::Attribute::NoUndef);
26 1494 printfFct->addParamAttr(0, llvm::Attribute::ReadOnly);
27 1494 printfFct->addRetAttr(llvm::Attribute::NoUndef);
28 1494 return printfFct;
29 }
30
31 667 llvm::Function *StdFunctionManager::getFPrintfFct() const {
32
4/8
✓ Branch 2 → 3 taken 667 times.
✗ Branch 2 → 21 not taken.
✓ Branch 3 → 4 taken 667 times.
✗ Branch 3 → 21 not taken.
✓ Branch 5 → 6 taken 667 times.
✗ Branch 5 → 21 not taken.
✓ Branch 6 → 7 taken 667 times.
✗ Branch 6 → 21 not taken.
667 llvm::Function *fprintfFct = getFunction("fprintf", builder.getInt32Ty(), {builder.getPtrTy(), builder.getPtrTy()}, true);
33 // Set attributes
34 667 fprintfFct->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local);
35 667 fprintfFct->addFnAttr(llvm::Attribute::NoFree);
36 667 fprintfFct->addParamAttr(0, llvm::Attribute::getWithCaptureInfo(context, llvm::CaptureInfo::none()));
37 667 fprintfFct->addParamAttr(0, llvm::Attribute::NoUndef);
38 667 fprintfFct->addParamAttr(1, llvm::Attribute::getWithCaptureInfo(context, llvm::CaptureInfo::none()));
39 667 fprintfFct->addParamAttr(1, llvm::Attribute::NoUndef);
40 667 fprintfFct->addParamAttr(1, llvm::Attribute::ReadOnly);
41 667 fprintfFct->addRetAttr(llvm::Attribute::NoUndef);
42 667 return fprintfFct;
43 }
44
45 1427 llvm::Function *StdFunctionManager::getExitFct() const {
46
2/4
✓ Branch 2 → 3 taken 1427 times.
✗ Branch 2 → 10 not taken.
✓ Branch 4 → 5 taken 1427 times.
✗ Branch 4 → 10 not taken.
1427 llvm::Function *exitFct = getProcedure("exit", builder.getInt32Ty());
47 // Set attributes
48 1427 exitFct->addFnAttr(llvm::Attribute::Cold);
49 1427 exitFct->addFnAttr(llvm::Attribute::NoReturn);
50 1427 exitFct->addFnAttr(llvm::Attribute::NoUnwind);
51 1427 return exitFct;
52 }
53
54 llvm::Function *StdFunctionManager::getFreeFct() const {
55 llvm::Function *freeFct = getProcedure("free", builder.getPtrTy());
56 // Set attributes
57 freeFct->addFnAttr(llvm::Attribute::NoUnwind);
58 freeFct->addParamAttr(0, llvm::Attribute::getWithCaptureInfo(context, llvm::CaptureInfo::none()));
59 freeFct->addParamAttr(0, llvm::Attribute::NoUndef);
60 freeFct->addParamAttr(0, llvm::Attribute::ReadOnly);
61 return freeFct;
62 }
63
64 24 llvm::Function *StdFunctionManager::getMemcmpFct() const {
65 24 llvm::Type *ptrTy = builder.getPtrTy();
66
3/6
✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 10 not taken.
✓ Branch 5 → 6 taken 24 times.
✗ Branch 5 → 10 not taken.
✓ Branch 6 → 7 taken 24 times.
✗ Branch 6 → 10 not taken.
24 llvm::Function *memcmpFct = getFunction("memcmp", builder.getInt32Ty(), {ptrTy, ptrTy, builder.getInt64Ty()});
67 // Set attributes
68 24 memcmpFct->addFnAttr(llvm::Attribute::NoUnwind);
69 24 return memcmpFct;
70 }
71
72 138 llvm::Function *StdFunctionManager::getMemcpyIntrinsic() const {
73 138 llvm::Type *ptrTy = builder.getPtrTy();
74
3/6
✓ Branch 3 → 4 taken 138 times.
✗ Branch 3 → 13 not taken.
✓ Branch 4 → 5 taken 138 times.
✗ Branch 4 → 13 not taken.
✓ Branch 6 → 7 taken 138 times.
✗ Branch 6 → 13 not taken.
138 llvm::Function *memcpyFct = getProcedure("llvm.memcpy.p0.p0.i64", {ptrTy, ptrTy, builder.getInt64Ty(), builder.getInt1Ty()});
75 // Set attributes
76 138 memcpyFct->addFnAttr(llvm::Attribute::NoCallback);
77 138 memcpyFct->addFnAttr(llvm::Attribute::NoFree);
78 138 memcpyFct->addFnAttr(llvm::Attribute::NoUnwind);
79 138 memcpyFct->addFnAttr(llvm::Attribute::WillReturn);
80 138 return memcpyFct;
81 }
82
83 23 llvm::Function *StdFunctionManager::getStringGetRawLengthStringFct() const {
84
2/4
✓ Branch 2 → 3 taken 23 times.
✗ Branch 2 → 34 not taken.
✓ Branch 5 → 6 taken 23 times.
✗ Branch 5 → 31 not taken.
46 const ParamList paramLst = {{QualType(TY_STRING), false}};
85
4/8
✓ Branch 8 → 9 taken 23 times.
✗ Branch 8 → 43 not taken.
✓ Branch 9 → 10 taken 23 times.
✗ Branch 9 → 40 not taken.
✓ Branch 10 → 11 taken 23 times.
✗ Branch 10 → 39 not taken.
✓ Branch 13 → 14 taken 23 times.
✗ Branch 13 → 35 not taken.
69 const Function function("getRawLength", nullptr, QualType(TY_DYN), QualType(TY_LONG), paramLst, {}, nullptr);
86
1/2
✓ Branch 19 → 20 taken 23 times.
✗ Branch 19 → 51 not taken.
23 const std::string mangledName = NameMangling::mangleFunction(function);
87
3/6
✓ Branch 20 → 21 taken 23 times.
✗ Branch 20 → 47 not taken.
✓ Branch 22 → 23 taken 23 times.
✗ Branch 22 → 47 not taken.
✓ Branch 24 → 25 taken 23 times.
✗ Branch 24 → 47 not taken.
46 return getFunction(mangledName.c_str(), builder.getInt64Ty(), {builder.getPtrTy()});
88 23 }
89
90 155 llvm::Function *StdFunctionManager::getStringIsRawEqualStringStringFct() const {
91
3/6
✓ Branch 2 → 3 taken 155 times.
✗ Branch 2 → 36 not taken.
✓ Branch 3 → 4 taken 155 times.
✗ Branch 3 → 36 not taken.
✓ Branch 6 → 7 taken 155 times.
✗ Branch 6 → 33 not taken.
310 const ParamList paramLst = {{QualType(TY_STRING), false}, {QualType(TY_STRING), false}};
92
4/8
✓ Branch 9 → 10 taken 155 times.
✗ Branch 9 → 45 not taken.
✓ Branch 10 → 11 taken 155 times.
✗ Branch 10 → 42 not taken.
✓ Branch 11 → 12 taken 155 times.
✗ Branch 11 → 41 not taken.
✓ Branch 14 → 15 taken 155 times.
✗ Branch 14 → 37 not taken.
465 const Function function("isRawEqual", nullptr, QualType(TY_DYN), QualType(TY_BOOL), paramLst, {}, nullptr);
93
1/2
✓ Branch 20 → 21 taken 155 times.
✗ Branch 20 → 53 not taken.
155 const std::string mangledName = NameMangling::mangleFunction(function);
94
4/8
✓ Branch 21 → 22 taken 155 times.
✗ Branch 21 → 49 not taken.
✓ Branch 22 → 23 taken 155 times.
✗ Branch 22 → 49 not taken.
✓ Branch 24 → 25 taken 155 times.
✗ Branch 24 → 49 not taken.
✓ Branch 26 → 27 taken 155 times.
✗ Branch 26 → 49 not taken.
310 return getFunction(mangledName.c_str(), builder.getInt1Ty(), {builder.getPtrTy(), builder.getPtrTy()});
95 155 }
96
97 7 llvm::Function *StdFunctionManager::getAllocUnsafeLongFct() const {
98
1/2
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 58 not taken.
7 QualType unsignedLong(TY_LONG);
99
1/2
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 58 not taken.
7 unsignedLong.makeUnsigned();
100
1/2
✓ Branch 6 → 7 taken 7 times.
✗ Branch 6 → 33 not taken.
14 const ParamList paramLst = {{unsignedLong, false}};
101
5/10
✓ Branch 9 → 10 taken 7 times.
✗ Branch 9 → 46 not taken.
✓ Branch 10 → 11 taken 7 times.
✗ Branch 10 → 42 not taken.
✓ Branch 11 → 12 taken 7 times.
✗ Branch 11 → 42 not taken.
✓ Branch 12 → 13 taken 7 times.
✗ Branch 12 → 41 not taken.
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 37 not taken.
21 const Function function("sAllocUnsafe", nullptr, QualType(TY_DYN), QualType(TY_BYTE).toPtr(nullptr), paramLst, {}, nullptr);
102
1/2
✓ Branch 21 → 22 taken 7 times.
✗ Branch 21 → 54 not taken.
7 const std::string mangledName = NameMangling::mangleFunction(function);
103
3/6
✓ Branch 22 → 23 taken 7 times.
✗ Branch 22 → 50 not taken.
✓ Branch 24 → 25 taken 7 times.
✗ Branch 24 → 50 not taken.
✓ Branch 26 → 27 taken 7 times.
✗ Branch 26 → 50 not taken.
14 return getFunction(mangledName.c_str(), builder.getPtrTy(), {builder.getInt64Ty()});
104 7 }
105
106 73 llvm::Function *StdFunctionManager::getDeallocBytePtrRefFct() const {
107
4/8
✓ Branch 2 → 3 taken 73 times.
✗ Branch 2 → 35 not taken.
✓ Branch 3 → 4 taken 73 times.
✗ Branch 3 → 35 not taken.
✓ Branch 4 → 5 taken 73 times.
✗ Branch 4 → 35 not taken.
✓ Branch 7 → 8 taken 73 times.
✗ Branch 7 → 32 not taken.
146 const ParamList paramLst = {{QualType(TY_BYTE).toPtr(nullptr).toRef(nullptr), false}};
108
4/8
✓ Branch 10 → 11 taken 73 times.
✗ Branch 10 → 46 not taken.
✓ Branch 11 → 12 taken 73 times.
✗ Branch 11 → 43 not taken.
✓ Branch 12 → 13 taken 73 times.
✗ Branch 12 → 42 not taken.
✓ Branch 15 → 16 taken 73 times.
✗ Branch 15 → 38 not taken.
219 const Function function("sDealloc", nullptr, QualType(TY_DYN), QualType(TY_DYN), paramLst, {}, nullptr);
109
1/2
✓ Branch 21 → 22 taken 73 times.
✗ Branch 21 → 54 not taken.
73 const std::string mangledName = NameMangling::mangleFunction(function);
110
2/4
✓ Branch 22 → 23 taken 73 times.
✗ Branch 22 → 50 not taken.
✓ Branch 25 → 26 taken 73 times.
✗ Branch 25 → 50 not taken.
146 return getProcedure(mangledName.c_str(), {builder.getPtrTy()});
111 73 }
112
113 7 llvm::Function *StdFunctionManager::getIterateFct(const Function *spiceFunc) const {
114
1/2
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 17 not taken.
7 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
115
1/2
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 15 not taken.
7 llvm::Type *iteratorType = spiceFunc->returnType.toLLVMType(sourceFile);
116
3/6
✓ Branch 4 → 5 taken 7 times.
✗ Branch 4 → 13 not taken.
✓ Branch 5 → 6 taken 7 times.
✗ Branch 5 → 13 not taken.
✓ Branch 8 → 9 taken 7 times.
✗ Branch 8 → 13 not taken.
14 return getFunction(functionName.c_str(), iteratorType, {builder.getPtrTy(), builder.getInt64Ty()});
117 7 }
118
119 88 llvm::Function *StdFunctionManager::getIteratorFct(const Function *spiceFunc) const {
120
1/2
✓ Branch 2 → 3 taken 88 times.
✗ Branch 2 → 16 not taken.
88 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
121
1/2
✓ Branch 3 → 4 taken 88 times.
✗ Branch 3 → 14 not taken.
88 llvm::Type *iteratorType = spiceFunc->returnType.toLLVMType(sourceFile);
122
2/4
✓ Branch 4 → 5 taken 88 times.
✗ Branch 4 → 12 not taken.
✓ Branch 7 → 8 taken 88 times.
✗ Branch 7 → 12 not taken.
176 return getFunction(functionName.c_str(), iteratorType, builder.getPtrTy());
123 88 }
124
125 105 llvm::Function *StdFunctionManager::getIteratorGetFct(const Function *spiceFunc) const {
126
1/2
✓ Branch 2 → 3 taken 105 times.
✗ Branch 2 → 16 not taken.
105 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
127
3/6
✓ Branch 3 → 4 taken 105 times.
✗ Branch 3 → 12 not taken.
✓ Branch 5 → 6 taken 105 times.
✗ Branch 5 → 12 not taken.
✓ Branch 7 → 8 taken 105 times.
✗ Branch 7 → 12 not taken.
210 return getFunction(functionName.c_str(), builder.getPtrTy(), builder.getPtrTy());
128 105 }
129
130 5 llvm::Function *StdFunctionManager::getIteratorGetIdxFct(const Function *spiceFunc) const {
131
1/2
✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 16 not taken.
5 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
132
1/2
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 14 not taken.
5 llvm::Type *pairTy = spiceFunc->returnType.toLLVMType(sourceFile);
133
2/4
✓ Branch 4 → 5 taken 5 times.
✗ Branch 4 → 12 not taken.
✓ Branch 7 → 8 taken 5 times.
✗ Branch 7 → 12 not taken.
10 return getFunction(functionName.c_str(), pairTy, builder.getPtrTy());
134 5 }
135
136 110 llvm::Function *StdFunctionManager::getIteratorIsValidFct(const Function *spiceFunc) const {
137
1/2
✓ Branch 2 → 3 taken 110 times.
✗ Branch 2 → 16 not taken.
110 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
138
3/6
✓ Branch 3 → 4 taken 110 times.
✗ Branch 3 → 12 not taken.
✓ Branch 5 → 6 taken 110 times.
✗ Branch 5 → 12 not taken.
✓ Branch 7 → 8 taken 110 times.
✗ Branch 7 → 12 not taken.
220 return getFunction(functionName.c_str(), builder.getInt1Ty(), builder.getPtrTy());
139 110 }
140
141 110 llvm::Function *StdFunctionManager::getIteratorNextFct(const Function *spiceFunc) const {
142
1/2
✓ Branch 2 → 3 taken 110 times.
✗ Branch 2 → 15 not taken.
110 const std::string functionName = NameMangling::mangleFunction(*spiceFunc);
143
2/4
✓ Branch 3 → 4 taken 110 times.
✗ Branch 3 → 11 not taken.
✓ Branch 6 → 7 taken 110 times.
✗ Branch 6 → 11 not taken.
220 return getProcedure(functionName.c_str(), builder.getPtrTy());
144 110 }
145
146 llvm::Function *StdFunctionManager::getAcrtIOFuncFct() const {
147 llvm::Function *stdErrPFct = getFunction("__acrt_iob_func", builder.getPtrTy(), builder.getInt32Ty());
148 stdErrPFct->setDSOLocal(true);
149 return stdErrPFct;
150 }
151
152 4433 llvm::Function *StdFunctionManager::getFunction(const char *funcName, llvm::Type *returnType, llvm::ArrayRef<llvm::Type *> args,
153 bool varArg /*=false*/) const {
154 // Check if function already exists in the current module
155
2/4
✓ Branch 2 → 3 taken 4433 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 4433 times.
✗ Branch 3 → 14 not taken.
4433 llvm::Function *opFct = module->getFunction(funcName);
156
2/2
✓ Branch 4 → 5 taken 2973 times.
✓ Branch 4 → 6 taken 1460 times.
4433 if (opFct != nullptr)
157 2973 return opFct;
158
159 // Add function to the current module
160 1460 llvm::FunctionType *opFctTy = llvm::FunctionType::get(returnType, args, varArg);
161
2/4
✓ Branch 7 → 8 taken 1460 times.
✗ Branch 7 → 15 not taken.
✓ Branch 8 → 9 taken 1460 times.
✗ Branch 8 → 15 not taken.
1460 module->getOrInsertFunction(funcName, opFctTy);
162
2/4
✓ Branch 9 → 10 taken 1460 times.
✗ Branch 9 → 16 not taken.
✓ Branch 10 → 11 taken 1460 times.
✗ Branch 10 → 16 not taken.
1460 return module->getFunction(funcName);
163 }
164
165 1748 llvm::Function *StdFunctionManager::getProcedure(const char *procName, llvm::ArrayRef<llvm::Type *> args) const {
166 1748 return getFunction(procName, builder.getVoidTy(), args, false);
167 }
168
169 } // namespace spice::compiler
170