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