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