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