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