1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MAPLE_IR_INCLUDE_FUNC_DESC_H
17 #define MAPLE_IR_INCLUDE_FUNC_DESC_H
18 #include "mpl_logging.h"
19 namespace maple {
20 
21 enum class FI {
22     kUnknown = 0,
23     kPure,   // means this function will not modify any global memory.
24     kConst,  // means this function will not read/modify any global memory.
25 };
26 
27 static std::string kFIStr[] = {"kUnknown", "kPure", "kConst"};
28 
29 enum class RI {
30     kUnknown = 0,  // for ptr value, don't know anything.
31     kNoAlias,      // for ptr value, no alias with any other ptr when this method is returned. As in malloc.
32     kAliasParam0,  // for ptr value, it may alias with first param. As in memcpy.
33     kAliasParam1,
34     kAliasParam2,
35     kAliasParam3,
36     kAliasParam4,
37     kAliasParam5,
38 };
39 
40 static std::string kRIStr[] = {"kUnknown",     "kNoAlias",     "kAliasParam0", "kAliasParam1",
41                                "kAliasParam2", "kAliasParam3", "kAliasParam4", "kAliasParam5"};
42 
43 enum class PI {
44     kUnknown = 0,      // for ptr param, may read/write every level memory.
45     kReadWriteMemory,  // for ptr param, only read & write the memory it points to.
46     kWriteMemoryOnly,  // for ptr param, only write the memory it points to.
47     kReadMemoryOnly,   // for ptr param, only read the memory it points to.
48     kReadSelfOnly,     // for ptr param, only read the ptr itself, do not dereference.
49     kUnused,           // this param is not used in this function.
50 };
51 
52 static std::string kPIStr[] = {"kUnknown",        "kReadWriteMemory", "kWriteMemoryOnly",
53                                "kReadMemoryOnly", "kReadSelfOnly",    "kUnused"};
54 
55 // most function has less than 6 parameters.
56 const size_t kMaxParamCount = 6;
57 struct FuncDesc {
58     FI funcInfo {};
59     RI returnInfo {};
60     PI paramInfo[kMaxParamCount] {};
61     bool configed = false;
62 
InitToBestmaple::FuncDesc63     void InitToBest()
64     {
65         funcInfo = FI::kConst;
66         returnInfo = RI::kNoAlias;
67         for (size_t idx = 0; idx < kMaxParamCount; ++idx) {
68             paramInfo[idx] = PI::kUnused;
69         }
70     }
71 
Equalsmaple::FuncDesc72     bool Equals(const FuncDesc &desc) const
73     {
74         if (funcInfo != desc.funcInfo) {
75             return false;
76         }
77         if (returnInfo != desc.returnInfo) {
78             return false;
79         }
80         for (size_t idx = 0; idx < kMaxParamCount; ++idx) {
81             if (paramInfo[idx] != desc.paramInfo[idx]) {
82                 return false;
83             }
84         }
85         return true;
86     }
87 
IsConfigedmaple::FuncDesc88     bool IsConfiged() const
89     {
90         return configed;
91     }
92 
SetConfigedmaple::FuncDesc93     void SetConfiged()
94     {
95         configed = true;
96     }
97 
IsConstmaple::FuncDesc98     bool IsConst() const
99     {
100         return funcInfo == FI::kConst;
101     }
102 
IsPuremaple::FuncDesc103     bool IsPure() const
104     {
105         return funcInfo == FI::kPure;
106     }
107 
IsReturnNoAliasmaple::FuncDesc108     bool IsReturnNoAlias() const
109     {
110         return returnInfo == RI::kNoAlias;
111     }
IsReturnAliasmaple::FuncDesc112     bool IsReturnAlias() const
113     {
114         return returnInfo >= RI::kAliasParam0;
115     }
116 
EnumToIndexmaple::FuncDesc117     size_t EnumToIndex(const RI &ri) const
118     {
119         switch (ri) {
120             case RI::kAliasParam0:
121                 return 0;
122             case RI::kAliasParam1:
123                 return 1;
124             case RI::kAliasParam2:
125                 return 2; // 2 is kAliasParam2
126             case RI::kAliasParam3:
127                 return 3; // 3 is kAliasParam3
128             case RI::kAliasParam4:
129                 return 4; // 4 is kAliasParam4
130             case RI::kAliasParam5:
131                 return 5; // 5 is kAliasParam5
132             default: {
133                 CHECK_FATAL(false, "Impossible.");
134             }
135         }
136     }
137 
ReturnParamXmaple::FuncDesc138     size_t ReturnParamX() const
139     {
140         CHECK_FATAL(returnInfo >= RI::kAliasParam0, "Impossible.");
141         return EnumToIndex(returnInfo);
142     }
143 
GetParamInfomaple::FuncDesc144     PI GetParamInfo(size_t index) const
145     {
146         return paramInfo[index];
147     }
148 
IsArgReadSelfOnlymaple::FuncDesc149     bool IsArgReadSelfOnly(size_t index) const
150     {
151         if (index >= kMaxParamCount) {
152             return false;
153         }
154         return paramInfo[index] == PI::kReadSelfOnly;
155     }
156 
IsArgReadMemoryOnlymaple::FuncDesc157     bool IsArgReadMemoryOnly(size_t index) const
158     {
159         if (index >= kMaxParamCount) {
160             return false;
161         }
162         return paramInfo[index] == PI::kReadMemoryOnly;
163     }
164 
IsArgWriteMemoryOnlymaple::FuncDesc165     bool IsArgWriteMemoryOnly(size_t index) const
166     {
167         if (index >= kMaxParamCount) {
168             return false;
169         }
170         return paramInfo[index] == PI::kWriteMemoryOnly;
171     }
172 
IsArgUnusedmaple::FuncDesc173     bool IsArgUnused(size_t index) const
174     {
175         if (index >= kMaxParamCount) {
176             return false;
177         }
178         return paramInfo[index] == PI::kUnused;
179     }
180 
SetFuncInfomaple::FuncDesc181     void SetFuncInfo(const FI fi)
182     {
183         funcInfo = fi;
184     }
185 
SetFuncInfoNoBetterThanmaple::FuncDesc186     void SetFuncInfoNoBetterThan(const FI fi)
187     {
188         auto oldValue = static_cast<size_t>(funcInfo);
189         auto newValue = static_cast<size_t>(fi);
190         if (newValue < oldValue) {
191             SetFuncInfo(static_cast<FI>(newValue));
192         }
193     }
194 
SetReturnInfomaple::FuncDesc195     void SetReturnInfo(const RI ri)
196     {
197         returnInfo = ri;
198     }
199 
SetParamInfomaple::FuncDesc200     void SetParamInfo(const size_t idx, const PI pi)
201     {
202         if (idx >= kMaxParamCount) {
203             return;
204         }
205         paramInfo[idx] = pi;
206     }
207 
SetParamInfoNoBetterThanmaple::FuncDesc208     void SetParamInfoNoBetterThan(const size_t idx, const PI pi)
209     {
210         size_t oldValue = static_cast<size_t>(paramInfo[idx]);
211         size_t newValue = static_cast<size_t>(pi);
212         if (newValue < oldValue) {
213             SetParamInfo(idx, static_cast<PI>(newValue));
214         }
215     }
216 
Dumpmaple::FuncDesc217     void Dump(size_t numParam = kMaxParamCount)
218     {
219         auto dumpCount = numParam > kMaxParamCount ? kMaxParamCount : numParam;
220         LogInfo::MapleLogger() << kFIStr[static_cast<size_t>(funcInfo)] << " "
221                                << kRIStr[static_cast<size_t>(returnInfo)];
222         for (size_t i = 0; i < dumpCount; ++i) {
223             LogInfo::MapleLogger() << " " << kPIStr[static_cast<size_t>(paramInfo[i])];
224         }
225         LogInfo::MapleLogger() << "\n";
226     }
227 };
228 }  // namespace maple
229 #endif  // MAPLE_IR_INCLUDE_FUNC_DESC_H
230