• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MIR_BUILDER_H
17 #define MAPLE_IR_INCLUDE_MIR_BUILDER_H
18 #include <string>
19 #include <utility>
20 #include <vector>
21 #include <map>
22 #ifdef _WIN32
23 #include <pthread.h>
24 #endif
25 #include "opcodes.h"
26 #include "prim_types.h"
27 #include "mir_type.h"
28 #include "mir_const.h"
29 #include "mir_symbol.h"
30 #include "mir_nodes.h"
31 #include "mir_module.h"
32 #include "mir_preg.h"
33 #include "mir_function.h"
34 #include "printing.h"
35 #include "intrinsic_op.h"
36 #include "opcode_info.h"
37 #include "global_tables.h"
38 
39 namespace maple {
40 using ArgPair = std::pair<std::string, MIRType *>;
41 using ArgVector = MapleVector<ArgPair>;
42 class MIRBuilder {
43 public:
44     enum MatchStyle {
45         kUpdateFieldID = 0,  // do not match but traverse to update fieldID
46         kMatchTopField = 1,  // match top level field only
47         kMatchAnyField = 2,  // match any field
48         kParentFirst = 4,    // traverse parent first
49         kFoundInChild = 8,   // found in child
50     };
51 
MIRBuilder(MIRModule * module)52     explicit MIRBuilder(MIRModule *module)
53         : mirModule(module), incompleteTypeRefedSet(mirModule->GetMPAllocator().Adapter())
54     {
55     }
56 
57     virtual ~MIRBuilder() = default;
58 
SetCurrentFunction(MIRFunction & fun)59     virtual void SetCurrentFunction(MIRFunction &fun)
60     {
61         mirModule->SetCurFunction(&fun);
62     }
63 
GetCurrentFunction()64     virtual MIRFunction *GetCurrentFunction() const
65     {
66         return mirModule->CurFunction();
67     }
GetCurrentFunctionNotNull()68     MIRFunction *GetCurrentFunctionNotNull() const
69     {
70         MIRFunction *func = GetCurrentFunction();
71         CHECK_FATAL(func != nullptr, "nullptr check");
72         return func;
73     }
74 
GetMirModule()75     MIRModule &GetMirModule()
76     {
77         return *mirModule;
78     }
79 
GetIncompleteTypeRefedSet()80     const MapleSet<TyIdx> &GetIncompleteTypeRefedSet() const
81     {
82         return incompleteTypeRefedSet;
83     }
84 
GetExtraFieldsTuples()85     std::vector<std::tuple<uint32, uint32, uint32, uint32>> &GetExtraFieldsTuples()
86     {
87         return extraFieldsTuples;
88     }
89 
GetLineNum()90     unsigned int GetLineNum() const
91     {
92         return lineNum;
93     }
SetLineNum(unsigned int num)94     void SetLineNum(unsigned int num)
95     {
96         lineNum = num;
97     }
98 
GetOrCreateStringIndex(const std::string & str)99     GStrIdx GetOrCreateStringIndex(const std::string &str) const
100     {
101         return GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(str);
102     }
103 
GetOrCreateStringIndex(GStrIdx strIdx,const std::string & str)104     GStrIdx GetOrCreateStringIndex(GStrIdx strIdx, const std::string &str) const
105     {
106         std::string firstString(GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx));
107         firstString += str;
108         return GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(firstString);
109     }
110 
GetStringIndex(const std::string & str)111     GStrIdx GetStringIndex(const std::string &str) const
112     {
113         return GlobalTables::GetStrTable().GetStrIdxFromName(str);
114     }
115 
116     MIRFunction *GetOrCreateFunction(const std::string &, TyIdx);
117     MIRFunction *GetFunctionFromSymbol(const MIRSymbol &funcst);
118     MIRFunction *GetFunctionFromName(const std::string &);
119     // for creating Function.
GetFunctionArgument(MIRFunction & fun,uint32 index)120     MIRSymbol *GetFunctionArgument(MIRFunction &fun, uint32 index) const
121     {
122         CHECK(index < fun.GetFormalCount(), "index out of range in GetFunctionArgument");
123         return fun.GetFormal(index);
124     }
125 
126     MIRFunction *CreateFunction(const std::string &name, const MIRType &returnType, const ArgVector &arguments,
127                                 bool isVarg = false, bool createBody = true) const;
UpdateFunction(MIRFunction &,const MIRType *,const ArgVector &)128     virtual void UpdateFunction(MIRFunction &, const MIRType *, const ArgVector &) {}
129     virtual MIRSymbol *GetOrCreateLocalDecl(const std::string &str, const MIRType &type);
130     MIRSymbol *GetLocalDecl(const std::string &str);
131     MIRSymbol *GetOrCreateDeclInFunc(const std::string &str, const MIRType &type, MIRFunction &func);
132     // for creating Expression
133     ConstvalNode *CreateConstval(MIRConst *constVal);
134     ConstvalNode *CreateIntConst(uint64, PrimType);
GetConstInt(int val)135     ConstvalNode *GetConstInt(int val)
136     {
137         return CreateIntConst(val, PTY_i32);
138     }
139 
GetConstUInt1(bool val)140     ConstvalNode *GetConstUInt1(bool val)
141     {
142         return CreateIntConst(val, PTY_u1);
143     }
144 
GetConstUInt8(uint8 val)145     ConstvalNode *GetConstUInt8(uint8 val)
146     {
147         return CreateIntConst(val, PTY_u8);
148     }
149 
GetConstUInt16(uint16 val)150     ConstvalNode *GetConstUInt16(uint16 val)
151     {
152         return CreateIntConst(val, PTY_u16);
153     }
154 
GetConstUInt32(uint32 val)155     ConstvalNode *GetConstUInt32(uint32 val)
156     {
157         return CreateIntConst(val, PTY_u32);
158     }
159 
GetConstUInt64(uint64 val)160     ConstvalNode *GetConstUInt64(uint64 val)
161     {
162         return CreateIntConst(val, PTY_u64);
163     }
164 
165     AddrofNode *CreateExprAddrof(FieldID fieldID, const MIRSymbol &symbol, MemPool *memPool = nullptr);
166     AddrofNode *CreateExprAddrof(FieldID fieldID, StIdx symbolStIdx, MemPool *memPool = nullptr);
167     AddrofNode *CreateExprDread(const MIRType &type, FieldID fieldID, const MIRSymbol &symbol);
168     AddrofNode *CreateExprDread(PrimType ptyp, FieldID fieldID, const MIRSymbol &symbol);
169     virtual AddrofNode *CreateExprDread(MIRSymbol &symbol);
170     RegreadNode *CreateExprRegread(PrimType pty, PregIdx regIdx);
171     IreadNode *CreateExprIread(const MIRType &returnType, const MIRType &ptrType, FieldID fieldID, BaseNode *addr);
172     BinaryNode *CreateExprBinary(Opcode opcode, const MIRType &type, BaseNode *opnd0, BaseNode *opnd1);
CreateExprBinary(Opcode opcode,PrimType pty,BaseNode * opnd0,BaseNode * opnd1)173     BinaryNode *CreateExprBinary(Opcode opcode, PrimType pty, BaseNode *opnd0, BaseNode *opnd1)
174     {
175         MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(pty));
176         return CreateExprBinary(opcode, *ty, opnd0, opnd1);
177     }
178     CompareNode *CreateExprCompare(Opcode opcode, const MIRType &type, const MIRType &opndType, BaseNode *opnd0,
179                                    BaseNode *opnd1);
180     UnaryNode *CreateExprUnary(Opcode opcode, const MIRType &type, BaseNode *opnd);
181     TypeCvtNode *CreateExprTypeCvt(Opcode o, PrimType toPrimType, PrimType fromPrimType, BaseNode &opnd);
182     TypeCvtNode *CreateExprTypeCvt(Opcode o, const MIRType &type, const MIRType &fromtype, BaseNode *opnd);
183     ExtractbitsNode *CreateExprExtractbits(Opcode o, PrimType type, uint32 bOffset, uint32 bSize, BaseNode *opnd);
184     RetypeNode *CreateExprRetype(const MIRType &type, const MIRType &fromType, BaseNode *opnd);
185     RetypeNode *CreateExprRetype(const MIRType &type, PrimType fromType, BaseNode *opnd);
186     IntrinsicopNode *CreateExprIntrinsicop(MIRIntrinsicID id, Opcode op, PrimType primType, TyIdx tyIdx,
187                                            const MapleVector<BaseNode *> &ops);
188     IntrinsicopNode *CreateExprIntrinsicop(MIRIntrinsicID idx, Opcode opcode, const MIRType &type,
189                                            const MapleVector<BaseNode *> &ops);
190     // for creating Statement.
191     NaryStmtNode *CreateStmtReturn(BaseNode *rVal);
192     UnaryStmtNode *CreateStmtUnary(Opcode op, BaseNode *rVal);
193     DassignNode *CreateStmtDassign(const MIRSymbol &var, FieldID fieldID, BaseNode *src);
194     DassignNode *CreateStmtDassign(StIdx sIdx, FieldID fieldID, BaseNode *src);
195     RegassignNode *CreateStmtRegassign(PrimType pty, PregIdx regIdx, BaseNode *src);
196     IassignNode *CreateStmtIassign(const MIRType &type, FieldID fieldID, BaseNode *addr, BaseNode *src);
197     CallNode *CreateStmtCall(PUIdx puIdx, const MapleVector<BaseNode *> &args, Opcode opcode = OP_call);
198 
199     IcallNode *CreateStmtTailIcall(const MapleVector<BaseNode *> &args);
200     IcallNode *CreateStmtIcall(const MapleVector<BaseNode *> &args);
201     IcallNode *CreateStmtIcallAssigned(const MapleVector<BaseNode *> &args, const MIRSymbol &ret);
202     IcallNode *CreateStmtIcallAssigned(const MapleVector<BaseNode *> &args, PregIdx pregIdx);
203     IcallNode *CreateStmtIcallproto(const MapleVector<BaseNode *> &args, const TyIdx &prototypeIdx);
204     // For Call
205     IntrinsiccallNode *CreateStmtIntrinsicCall(MIRIntrinsicID idx, const MapleVector<BaseNode *> &arguments,
206                                                TyIdx tyIdx = TyIdx());
207     CallNode *CreateStmtCallRegassigned(PUIdx, const MapleVector<BaseNode *> &, PregIdx, Opcode);
208     IntrinsiccallNode *CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &arguments,
209                                                        PregIdx retPregIdx1, PregIdx retPregIdx2);
210     IfStmtNode *CreateStmtIf(BaseNode *cond);
211     SwitchNode *CreateStmtSwitch(BaseNode *opnd, LabelIdx defaultLabel, const CaseVector &switchTable);
212     GotoNode *CreateStmtGoto(Opcode o, LabelIdx labIdx);
213     LabelNode *CreateStmtLabel(LabelIdx labIdx);
214     StmtNode *CreateStmtComment(const std::string &comment);
215     CondGotoNode *CreateStmtCondGoto(BaseNode *cond, Opcode op, LabelIdx labIdx);
216     MIRSymbol *CreatePregFormalSymbol(TyIdx, PregIdx, MIRFunction &) const;
217     // for creating symbol
218     MIRSymbol *CreateSymbol(TyIdx, const std::string &, MIRSymKind, MIRStorageClass, MIRFunction *, uint8) const;
219     MIRSymbol *CreateSymbol(TyIdx, GStrIdx, MIRSymKind, MIRStorageClass, MIRFunction *, uint8) const;
220     virtual MemPool *GetCurrentFuncCodeMp();
221     virtual MapleAllocator *GetCurrentFuncCodeMpAllocator();
222 
GlobalLock()223     virtual void GlobalLock() {}
GlobalUnlock()224     virtual void GlobalUnlock() {}
225 
SetCurrentDebugComment(const std::string & comment)226     void SetCurrentDebugComment(const std::string &comment)
227     {
228         currComment = GetMirModule().CurFunction()->AddNewDebugComment(comment);
229     }
230 
ClearCurrentDebugComment()231     void ClearCurrentDebugComment()
232     {
233         currComment = nullptr;
234     }
235 
236 private:
237     MIRSymbol *GetOrCreateLocalDecl(const std::string &str, TyIdx tyIdx, MIRSymbolTable &symbolTable,
238                                     bool &created) const;
239     template <class T, typename... Arguments>
NewNode(Arguments &&...args)240     T *NewNode(Arguments &&... args)
241     {
242         static_assert(std::is_base_of_v<BaseNode, T>);
243         T *stmt =  GetCurrentFuncCodeMp()->New<T>(args...);
244         stmt->SetDebugComment(currComment);
245         return stmt;
246     }
247 
248     MIRModule *mirModule;
249     MapleSet<TyIdx> incompleteTypeRefedSet;
250     // <className strIdx, fieldname strIdx, typename strIdx, attr list strIdx>
251     std::vector<std::tuple<uint32, uint32, uint32, uint32>> extraFieldsTuples;
252     unsigned int lineNum = 0;
253     const MapleString *currComment { nullptr };
254 };
255 
256 class MIRBuilderExt : public MIRBuilder {
257 public:
258     explicit MIRBuilderExt(MIRModule *module);
259     virtual ~MIRBuilderExt() = default;
260 
SetCurrentFunction(MIRFunction & func)261     void SetCurrentFunction(MIRFunction &func) override
262     {
263         curFunction = &func;
264     }
265 
GetCurrentFunction()266     MIRFunction *GetCurrentFunction() const override
267     {
268         return curFunction;
269     }
270 
271 private:
272     MIRFunction *curFunction = nullptr;
273 };
274 }  // namespace maple
275 #endif  // MAPLE_IR_INCLUDE_MIR_BUILDER_H