• 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 #include "lmir_builder.h"
17 #include "mir_builder.h"
18 
19 namespace maple {
20 namespace litecg {
21 
22 // not exposed any longer
GetPrimitiveType(PrimType type)23 inline Type *GetPrimitiveType(PrimType type)
24 {
25     return GlobalTables::GetTypeTable().GetPrimType(type);
26 }
27 
CreateModuleWithName(const std::string & name)28 Module *CreateModuleWithName(const std::string &name)
29 {
30     return new Module(name);
31 }
32 
ReleaseModule(Module * module)33 void ReleaseModule(Module *module)
34 {
35     if (module != nullptr) {
36         delete module;
37         module = nullptr;
38     }
39     // clean current globals
40     GlobalTables::Reset();
41     memPoolCtrler.FreeFixedSizeMemBlockMemory();
42 }
43 
IsDread() const44 bool Expr::IsDread() const
45 {
46     return node->GetOpCode() == OP_dread;
47 }
48 
IsRegread() const49 bool Expr::IsRegread() const
50 {
51     return node->GetOpCode() == OP_regread;
52 }
53 
IsConstValue() const54 bool Expr::IsConstValue() const
55 {
56     return node->GetOpCode() == OP_constval;
57 }
58 
LMIRBuilder(Module & module_)59 LMIRBuilder::LMIRBuilder(Module &module_) : mirBuilder(*module_.GetMIRBuilder()), module(module_)
60 {
61     i8Type = GetPrimitiveType(PTY_i8);
62     i16Type = GetPrimitiveType(PTY_i16);
63     i32Type = GetPrimitiveType(PTY_i32);
64     i64Type = GetPrimitiveType(PTY_i64);
65     u1Type = GetPrimitiveType(PTY_u1);
66     u8Type = GetPrimitiveType(PTY_u8);
67     u16Type = GetPrimitiveType(PTY_u16);
68     u32Type = GetPrimitiveType(PTY_u32);
69     u64Type = GetPrimitiveType(PTY_u64);
70     voidType = GetPrimitiveType(PTY_void);
71     f32Type = GetPrimitiveType(PTY_f32);
72     f64Type = GetPrimitiveType(PTY_f64);
73 
74     // builtin types: commonly used derived types
75     strType = CreatePtrType(u8Type);  // u8PtrType
76     i64PtrType = CreatePtrType(i64Type);
77     i64RefType = CreateRefType(i64Type);
78     i64RefRefType = CreateRefType(i64RefType);
79 }
80 
81 #ifdef ARK_LITECG_DEBUG
DumpIRToFile(const std::string fileName)82 void LMIRBuilder::DumpIRToFile(const std::string fileName)
83 {
84     module.DumpToFile(fileName);
85 }
86 #endif
87 
LiteCGGetTypeKind(Type * type) const88 LiteCGTypeKind LMIRBuilder::LiteCGGetTypeKind(Type *type) const
89 {
90     switch (type->GetKind()) {
91         case MIRTypeKind::kTypeScalar:
92             return kLiteCGTypeScalar;
93         case MIRTypeKind::kTypeArray:
94             return kLiteCGTypeArray;
95         case MIRTypeKind::kTypePointer:
96             return kLiteCGTypePointer;
97         case MIRTypeKind::kTypeFunction:
98             return kLiteCGTypeFunction;
99         case MIRTypeKind::kTypeVoid:
100             return kLiteCGTypeVoid;
101         case MIRTypeKind::kTypeByName:
102             return kLiteCGTypeByName;
103         default:
104             return kLiteCGTypeUnknown;
105     }
106 }
107 
SetCallStmtDeoptBundleInfo(Stmt & callNode,const std::unordered_map<int,LiteCGValue> & deoptBundleInfo)108 void LMIRBuilder::SetCallStmtDeoptBundleInfo(Stmt &callNode,
109                                              const std::unordered_map<int, LiteCGValue> &deoptBundleInfo)
110 {
111     MapleUnorderedMap<int, MapleValue> deoptInfos(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
112     for (const auto itr : deoptBundleInfo) {
113         auto value = itr.second;
114         if (value.kind == kPregKind) {
115             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(std::get<PregIdx>(value.data))));
116         } else if (itr.second.kind == kSymbolKind) {
117             CHECK_FATAL(false, "symbol is not supported currently");
118             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(std::get<MIRSymbol*>(value.data))));
119         } else {
120             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(std::get<MIRConst*>(value.data))));
121         }
122     }
123     if (callNode.GetOpCode() == OP_call || callNode.GetOpCode() == OP_callassigned) {
124         static_cast<CallNode &>(callNode).SetDeoptBundleInfo(deoptInfos);
125     } else {
126         static_cast<IcallNode &>(callNode).SetDeoptBundleInfo(deoptInfos);
127     }
128 }
129 
CreatePtrType(Type * mirType)130 Type *LMIRBuilder::CreatePtrType(Type *mirType)
131 {
132     auto type = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType, PTY_ptr);
133     return type;
134 }
135 
CreateRefType(Type * mirType)136 Type *LMIRBuilder::CreateRefType(Type *mirType)
137 {
138     auto type = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType, PTY_ref);
139     return type;
140 }
141 
IsHeapPointerType(Type * mirType) const142 bool LMIRBuilder::IsHeapPointerType(Type *mirType) const
143 {
144     return mirType->GetPrimType() == PTY_ref;
145 }
146 
CreateFuncType(std::vector<Type * > params_,Type * retType,bool isVarg)147 Type *LMIRBuilder::CreateFuncType(std::vector<Type *> params_, Type *retType, bool isVarg)
148 {
149     std::vector<TyIdx> params;
150     std::vector<TypeAttrs> attrs;  // not used so far
151 
152     for (const auto param : params_) {
153         params.push_back(param->GetTypeIndex());
154         attrs.push_back(TypeAttrs());
155     }
156 
157     auto type = GlobalTables::GetTypeTable().GetOrCreateFunctionType(retType->GetTypeIndex(), params, attrs, isVarg);
158     return type;
159 }
160 
LiteCGGetPointedType(Type * type)161 Type *LMIRBuilder::LiteCGGetPointedType(Type *type)
162 {
163     if (type == nullptr || !type->IsMIRPtrType()) {
164         return nullptr;
165     }
166     return static_cast<MIRPtrType *>(type)->GetPointedFuncType();
167 }
168 
LiteCGGetFuncParamTypes(Type * type)169 std::vector<Type *> LMIRBuilder::LiteCGGetFuncParamTypes(Type *type)
170 {
171     DEBUG_ASSERT(static_cast<MIRFuncType *>(type) != nullptr, "nullptr check");
172     std::vector<TyIdx> &paramTypeList = static_cast<MIRFuncType *>(type)->GetParamTypeList();
173     std::vector<Type *> paramTypes;
174     for (const auto paramType : paramTypeList) {
175         paramTypes.push_back(GlobalTables::GetTypeTable().GetTypeFromTyIdx(paramType));
176     }
177     return paramTypes;
178 }
179 
LiteCGGetFuncReturnType(Type * type)180 Type *LMIRBuilder::LiteCGGetFuncReturnType(Type *type)
181 {
182     if (type == nullptr || !type->IsMIRFuncType()) {
183         return nullptr;
184     }
185     TyIdx retTypeIndex = static_cast<MIRFuncType *>(type)->GetRetTyIdx();
186     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTypeIndex);
187 }
188 
189 // not sure it's FUNCATTR_local or FUNCATTR_static
190 static const FuncAttrKind FuncAttrMapTable[] = {
191     // FUNC_global,   FUNC_weak,     FUNC_internal
192     FUNCATTR_extern, FUNCATTR_weak, FUNCATTR_local};
193 
194 static const FuncAttrKind FuncConvAttrMapTable[] = {
195     // CCall,         Web_Kit_JS_Call,     GHC_Call
196     FUNCATTR_ccall, FUNCATTR_webkitjscall, FUNCATTR_ghcall};
197 
198 static const StmtAttrKind StmtConvAttrMapTable[] = {STMTATTR_ccall, STMTATTR_webkitjscall};
199 
CreateFunctionInternal(const String & name,Type * retType,Params & params_,bool isVargs,bool needBody,FuncAttr attr,ConvAttr convAttr)200 Function &LMIRBuilder::CreateFunctionInternal(const String &name, Type *retType, Params &params_, bool isVargs,
201                                               bool needBody, FuncAttr attr, ConvAttr convAttr)
202 {
203     ArgVector params(module.GetMPAllocator().Adapter());
204     for (auto param : params_) {
205         params.push_back(param);
206     }
207     auto func = mirBuilder.CreateFunction(name, *retType, params, isVargs, needBody);
208     DEBUG_ASSERT(func != nullptr, "CreateFunction should not be nullptr");
209     auto &function = *func;
210     // check for attr
211     function.SetAttr(FuncAttrMapTable[attr]);
212     function.SetAttr(FuncConvAttrMapTable[convAttr]);
213     // It defines a function, add to module
214     if (needBody) {
215         module.AddFunction(&function);
216     }
217     return function;
218 }
219 
GetFunc(const String & name)220 Function *LMIRBuilder::GetFunc(const String &name)
221 {
222     return mirBuilder.GetFunctionFromName(name);
223 }
224 
SetCurFunc(Function & function)225 void LMIRBuilder::SetCurFunc(Function &function)
226 {
227     module.SetCurFunction(&function);
228 }
229 
GetCurFunction() const230 Function &LMIRBuilder::GetCurFunction() const
231 {
232     return *module.CurFunction();
233 }
234 
RenameFormal2Preg(Function & func)235 void LMIRBuilder::RenameFormal2Preg(Function &func)
236 {
237     if (!func.GetPregTab()) {
238         // func no body, skip rename
239         return;
240     }
241     auto &formalVec = func.GetFormalDefVec();
242     for (uint32 i = 0; i < formalVec.size(); i++) {
243         MIRSymbol *oldSym = formalVec[i].formalSym;
244         if (!oldSym || !IsPrimitiveScalar(oldSym->GetType()->GetPrimType())) {
245             continue;
246         }
247         PregIdx regid = CreatePreg(oldSym->GetType());
248         MIRSymbol *newSym = mirBuilder.CreatePregFormalSymbol(oldSym->GetTyIdx(), regid, func);
249         formalVec[i].formalSym = newSym;
250     }
251 }
252 
SetFuncFrameResverdSlot(int slot)253 void LMIRBuilder::SetFuncFrameResverdSlot(int slot)
254 {
255     CHECK_NULL_FATAL(module.CurFunction());
256     module.CurFunction()->GetFuncAttrs().SetFrameResverdSlot(slot);
257 }
258 
SetFuncFramePointer(const String & val)259 void LMIRBuilder::SetFuncFramePointer(const String &val)
260 {
261     DEBUG_ASSERT(module.CurFunction() != nullptr, "module.CurFunction() should not be nullptr");
262     module.CurFunction()->GetFuncAttrs().SetFramePointer(val);
263 }
264 
SetCurrentDebugComment(const std::string & comment)265 void LMIRBuilder::SetCurrentDebugComment(const std::string& comment)
266 {
267     mirBuilder.SetCurrentDebugComment(comment);
268 }
269 
ClearCurrentDebugComment()270 void LMIRBuilder::ClearCurrentDebugComment()
271 {
272     mirBuilder.ClearCurrentDebugComment();
273 }
274 
LiteCGGetPregFP(Function & func)275 Expr LMIRBuilder::LiteCGGetPregFP(Function &func)
276 {
277     return Regread(kSregFp);
278 }
279 
LiteCGGetPregSP()280 Expr LMIRBuilder::LiteCGGetPregSP()
281 {
282     return Regread(kSregSp);
283 }
284 
CreateLocalVar(Type * type,const String & name)285 Var &LMIRBuilder::CreateLocalVar(Type *type, const String &name)
286 {
287     DEBUG_ASSERT(type != nullptr, "type should not be null");
288     return *mirBuilder.GetOrCreateLocalDecl(name, *type);
289 }
290 
GetLocalVar(const String & name)291 Var *LMIRBuilder::GetLocalVar(const String &name)
292 {
293     return mirBuilder.GetLocalDecl(name);
294 }
295 
GetLocalVarFromExpr(Expr inExpr)296 Var *LMIRBuilder::GetLocalVarFromExpr(Expr inExpr)
297 {
298     auto *node = inExpr.GetNode();
299     if ((node == nullptr) || (node->GetOpCode() != OP_dread)) {
300         return nullptr;
301     }
302     return GetCurFunction().GetSymbolTabItem(static_cast<DreadNode *>(node)->GetStIdx().Idx(), true);
303 }
304 
SetFunctionDerived2BaseRef(PregIdx derived,PregIdx base)305 void LMIRBuilder::SetFunctionDerived2BaseRef(PregIdx derived, PregIdx base)
306 {
307     return GetCurFunction().SetDerived2BaseRef(derived, base);
308 }
309 
GetPregIdxFromExpr(const Expr & expr)310 PregIdx LMIRBuilder::GetPregIdxFromExpr(const Expr &expr)
311 {
312     auto *node = expr.GetNode();
313     if ((node == nullptr) || (node->GetOpCode() != OP_regread)) {
314         return 0;
315     }
316     return static_cast<RegreadNode *>(node)->GetRegIdx();
317 }
318 
GetParam(Function & function,size_t index) const319 Var &LMIRBuilder::GetParam(Function &function, size_t index) const
320 {
321     return *function.GetFormal(index);
322 }
323 
GenExprFromVar(Var & var)324 Expr LMIRBuilder::GenExprFromVar(Var &var)
325 {
326     if (var.IsPreg()) {
327         return Regread(var.GetPreg()->GetPregNo());
328     }
329     return Dread(var);
330 }
331 
CreateIntConst(Type * type,int64_t val)332 Const &LMIRBuilder::CreateIntConst(Type *type, int64_t val)
333 {
334     return *GlobalTables::GetIntConstTable().GetOrCreateIntConst(val, *type);
335 }
336 
CreateDoubleConst(double val)337 Const &LMIRBuilder::CreateDoubleConst(double val)
338 {
339     return *GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(val);
340 }
341 
GetConstFromExpr(const Expr & expr)342 Const *LMIRBuilder::GetConstFromExpr(const Expr &expr)
343 {
344     auto *node = expr.GetNode();
345     if ((node == nullptr) || (node->GetOpCode() != OP_constval)) {
346         return nullptr;
347     }
348     return static_cast<ConstvalNode *>(node)->GetConstVal();
349 }
350 
CreateBB(bool needLabel)351 BB &LMIRBuilder::CreateBB(bool needLabel)
352 {
353     // not sure block-node is a correct representation
354     // create block statement in current function
355     BB &bb = *module.CurFuncCodeMemPool()->New<BlockNode>();
356     if (needLabel) {
357         // generate implement label statement as the first statement
358         DEBUG_ASSERT(module.CurFunction() != nullptr, "module.CurFunction() should not be nullptr");
359         LabelIdx labelIdx = module.CurFunction()->GetLabelTab()->CreateLabel();
360         CHECK_NULL_FATAL(module.CurFunction());
361         (void)module.CurFunction()->GetLabelTab()->AddToStringLabelMap(labelIdx);
362         auto *labelStmt = module.CurFuncCodeMemPool()->New<LabelNode>();
363         labelStmt->SetLabelIdx(labelIdx);
364         bb.AddStatement(labelStmt);
365     }
366     return bb;
367 }
368 
AppendStmt(BB & bb,Stmt & stmt)369 void LMIRBuilder::AppendStmt(BB &bb, Stmt &stmt)
370 {
371     bb.AddStatement(&stmt);
372 }
373 
AppendStmtBeforeBranch(BB & bb,Stmt & stmt)374 void LMIRBuilder::AppendStmtBeforeBranch(BB &bb, Stmt &stmt)
375 {
376     bool inserted = false;
377     auto &nodes = bb.GetStmtNodes();
378     for (auto it = nodes.crbegin(); it != nodes.crend(); it++) {
379         auto &node = *it;
380         if (!node.IsCondBr() && (node.GetOpCode() != OP_goto)) {
381             bb.InsertAfter(&node, &stmt);
382             inserted = true;
383             break;
384         }
385     }
386     CHECK_FATAL(inserted, "PreBB must have a non jump stmt to insert PhiVarAssagin Stmt.");
387 }
388 
SetStmtCallConv(Stmt & stmt,ConvAttr convAttr)389 void LMIRBuilder::SetStmtCallConv(Stmt &stmt, ConvAttr convAttr)
390 {
391     stmt.SetAttr(StmtConvAttrMapTable[convAttr]);
392 }
393 
AppendBB(BB & bb)394 void LMIRBuilder::AppendBB(BB &bb)
395 {
396     DEBUG_ASSERT(module.CurFunction() != nullptr, "module.CurFunction() should not be nullptr");
397     module.CurFunction()->GetBody()->AddStatement(&bb);
398 }
399 
AppendToLast(BB & bb)400 void LMIRBuilder::AppendToLast(BB &bb)
401 {
402     DEBUG_ASSERT(module.CurFunction() != nullptr, "module.CurFunction() should not be nullptr");
403     module.CurFunction()->GetLastPosBody()->AddStatement(&bb);
404 }
405 
GetLastAppendedBB()406 BB &LMIRBuilder::GetLastAppendedBB()
407 {
408     CHECK_NULL_FATAL(module.CurFunction());
409     BB *pb = dynamic_cast<BB *>(module.CurFunction()->GetLastPosBody()->GetLast());
410     return *pb;
411 }
412 
GetLastPosBB()413 BB &LMIRBuilder::GetLastPosBB()
414 {
415     CHECK_NULL_FATAL(module.CurFunction());
416     return *module.CurFunction()->GetLastPosBody();
417 }
418 
GetBBLabelIdx(BB & bb)419 LabelIdx GetBBLabelIdx(BB &bb)
420 {
421     LabelNode *labelNode = dynamic_cast<LabelNode *>(bb.GetFirst());
422     DEBUG_ASSERT(labelNode != nullptr, "BB should have a label statment");
423 
424     return labelNode->GetLabelIdx();
425 }
426 
Goto(BB & dest)427 Stmt &LMIRBuilder::Goto(BB &dest)
428 {
429     return *mirBuilder.CreateStmtGoto(OP_goto, GetBBLabelIdx(dest));
430 }
431 
CondGoto(Expr cond,BB & target,bool inverseCond)432 Stmt &LMIRBuilder::CondGoto(Expr cond, BB &target, bool inverseCond)
433 {
434     auto opcode = inverseCond ? OP_brtrue : OP_brfalse;
435     return *mirBuilder.CreateStmtCondGoto(cond.GetNode(), opcode, GetBBLabelIdx(target));
436 }
437 
438 // not ready yet
CreateSwitchInternal(Type * type,Expr cond,BB & defaultBB,std::vector<std::pair<int64_t,BB * >> & cases)439 Stmt &LMIRBuilder::CreateSwitchInternal(Type *type, Expr cond, BB &defaultBB,
440                                         std::vector<std::pair<int64_t, BB *>> &cases)
441 {
442     CaseVector switchTable(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
443     for (auto caseBranch : cases) {
444         switchTable.push_back({caseBranch.first, GetBBLabelIdx(*caseBranch.second)});
445     }
446     return *mirBuilder.CreateStmtSwitch(cond.GetNode(), GetBBLabelIdx(defaultBB), switchTable);
447 }
448 
Call(Function & func,Args & args_,PregIdx pregIdx)449 Stmt &LMIRBuilder::Call(Function &func, Args &args_, PregIdx pregIdx)
450 {
451     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
452     for (const auto &arg : args_) {
453         args.emplace_back(arg.GetNode());
454     }
455     return *mirBuilder.CreateStmtCallRegassigned(func.GetPuidx(), args, pregIdx, OP_callassigned);
456 }
457 
PureCall(Expr funcAddr,Args & args_,Var * result)458 Stmt &LMIRBuilder::PureCall(Expr funcAddr, Args &args_, Var *result)
459 {
460     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
461     args.push_back(funcAddr.GetNode());
462     for (const auto &arg : args_) {
463         args.emplace_back(arg.GetNode());
464     }
465     return *mirBuilder.CreateStmtIntrinsicCall(MIRIntrinsicID::INTRN_JS_PURE_CALL, args);
466 }
467 
ICall(Expr funcAddr,Args & args_,Var * result)468 Stmt &LMIRBuilder::ICall(Expr funcAddr, Args &args_, Var *result)
469 {
470     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
471     args.push_back(funcAddr.GetNode());
472     for (const auto &arg : args_) {
473         args.emplace_back(arg.GetNode());
474     }
475 
476     if (result == nullptr) {
477         return *mirBuilder.CreateStmtIcall(args);
478     } else {
479         return *mirBuilder.CreateStmtIcallAssigned(args, *result);
480     }
481 }
482 
ICall(Expr funcAddr,Args & args_,PregIdx pregIdx)483 Stmt &LMIRBuilder::ICall(Expr funcAddr, Args &args_, PregIdx pregIdx)
484 {
485     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
486     args.push_back(funcAddr.GetNode());
487     for (const auto &arg : args_) {
488         args.emplace_back(arg.GetNode());
489     }
490     return *mirBuilder.CreateStmtIcallAssigned(args, pregIdx);
491 }
492 
IntrinsicCall(IntrinsicId func_,Args & args_,PregIdx retPregIdx1,PregIdx retPregIdx2)493 Stmt &LMIRBuilder::IntrinsicCall(IntrinsicId func_, Args &args_, PregIdx retPregIdx1, PregIdx retPregIdx2)
494 {
495     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
496     for (const auto &arg : args_) {
497         args.emplace_back(arg.GetNode());
498     }
499     auto func = static_cast<MIRIntrinsicID>(func_);
500     return *mirBuilder.CreateStmtIntrinsicCallAssigned(func, args, retPregIdx1, retPregIdx2);
501 }
502 
Return(Expr returnVal)503 Stmt &LMIRBuilder::Return(Expr returnVal)
504 {
505     return *mirBuilder.CreateStmtReturn(returnVal.GetNode());
506 }
507 
Comment(std::string comment)508 Stmt &LMIRBuilder::Comment(std::string comment)
509 {
510     return *mirBuilder.CreateStmtComment(comment);
511 }
512 
Dassign(Expr src,Var & var,FieldId fieldId)513 Stmt &LMIRBuilder::Dassign(Expr src, Var &var, FieldId fieldId)
514 {
515     return *mirBuilder.CreateStmtDassign(var, fieldId, src.GetNode());
516 }
517 
Iassign(Expr src,Expr addr,Type * baseType,FieldId fieldId)518 Stmt &LMIRBuilder::Iassign(Expr src, Expr addr, Type *baseType, FieldId fieldId)
519 {
520     return *mirBuilder.CreateStmtIassign(*baseType, fieldId, addr.GetNode(), src.GetNode());
521 }
522 
Dread(Var & var)523 Expr LMIRBuilder::Dread(Var &var)
524 {
525     return Expr(mirBuilder.CreateExprDread(var), var.GetType());
526 }
527 
IntrinsicOp(IntrinsicId id,Type * type,Args & args_)528 Expr LMIRBuilder::IntrinsicOp(IntrinsicId id, Type *type, Args &args_)
529 {
530     auto func = static_cast<MIRIntrinsicID>(id);
531     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
532     for (const auto &arg : args_) {
533         args.emplace_back(arg.GetNode());
534     }
535     return Expr(mirBuilder.CreateExprIntrinsicop(func, OP_intrinsicop, *type, args), type);
536 }
537 
Iread(Type * type,Expr addr,Type * baseType,FieldId fieldId)538 Expr LMIRBuilder::Iread(Type *type, Expr addr, Type *baseType, FieldId fieldId)
539 {
540     return Expr(mirBuilder.CreateExprIread(*type, *baseType, fieldId, addr.GetNode()), type);
541 }
542 
CreatePreg(Type * mtype)543 PregIdx LMIRBuilder::CreatePreg(Type *mtype)
544 {
545     DEBUG_ASSERT(mtype != nullptr, "type is null");
546     if ((mtype->GetPrimType() != PTY_ptr) && (mtype->GetPrimType() != PTY_ref)) {
547         // primitive type
548         return GetCurFunction().GetPregTab()->CreatePreg(mtype->GetPrimType());
549     }
550     return GetCurFunction().GetPregTab()->CreatePreg(mtype->GetPrimType(), mtype);
551 }
552 
Regassign(Expr src,PregIdx pregIdx)553 Stmt &LMIRBuilder::Regassign(Expr src, PregIdx pregIdx)
554 {
555     return *(mirBuilder.CreateStmtRegassign(src.GetType()->GetPrimType(), pregIdx, src.GetNode()));
556 }
557 
Regread(PregIdx pregIdx)558 Expr LMIRBuilder::Regread(PregIdx pregIdx)
559 {
560     MIRPreg *preg = GetCurFunction().GetPregTab()->PregFromPregIdx(pregIdx);
561     if (pregIdx < 0) {
562         // special register
563         return Expr(mirBuilder.CreateExprRegread(PTY_i64, pregIdx), i64Type);
564     }
565     if (preg->GetMIRType() != nullptr) {
566         return Expr(mirBuilder.CreateExprRegread(preg->GetPrimType(), pregIdx), preg->GetMIRType());
567     }
568     // the type of value in reg is primitive type
569     Type *type = GetPrimitiveType(preg->GetPrimType());
570     return Expr(mirBuilder.CreateExprRegread(preg->GetPrimType(), pregIdx), type);
571 }
572 
ConstVal(Const & constVal)573 Expr LMIRBuilder::ConstVal(Const &constVal)
574 {
575     return Expr(mirBuilder.CreateConstval(&constVal), &constVal.GetType());
576 }
577 
Lnot(Type * type,Expr src)578 Expr LMIRBuilder::Lnot(Type *type, Expr src)
579 {
580     return Expr(mirBuilder.CreateExprUnary(OP_lnot, *type, src.GetNode()), type);
581 }
582 
Bnot(Type * type,Expr src)583 Expr LMIRBuilder::Bnot(Type *type, Expr src)
584 {
585     return Expr(mirBuilder.CreateExprUnary(OP_bnot, *type, src.GetNode()), type);
586 }
587 
Sqrt(Type * type,Expr src)588 Expr LMIRBuilder::Sqrt(Type *type, Expr src)
589 {
590     return Expr(mirBuilder.CreateExprUnary(OP_sqrt, *type, src.GetNode()), type);
591 }
592 
Abs(Type * type,Expr src)593 Expr LMIRBuilder::Abs(Type *type, Expr src)
594 {
595     return Expr(mirBuilder.CreateExprUnary(OP_abs, *type, src.GetNode()), type);
596 }
597 
CreateBinOpInternal(MIRBuilder & mirBuilder,Opcode op,Type * type,Expr src1,Expr src2)598 inline Expr CreateBinOpInternal(MIRBuilder &mirBuilder, Opcode op, Type *type, Expr src1, Expr src2)
599 {
600     // we don't check for type mismatch and insert type-conversion here
601     return Expr(mirBuilder.CreateExprBinary(op, *type, src1.GetNode(), src2.GetNode()), type);
602 }
603 
Add(Type * type,Expr src1,Expr src2)604 Expr LMIRBuilder::Add(Type *type, Expr src1, Expr src2)
605 {
606     return CreateBinOpInternal(mirBuilder, OP_add, type, src1, src2);
607 }
608 
Sub(Type * type,Expr src1,Expr src2)609 Expr LMIRBuilder::Sub(Type *type, Expr src1, Expr src2)
610 {
611     return CreateBinOpInternal(mirBuilder, OP_sub, type, src1, src2);
612 }
613 
Mul(Type * type,Expr src1,Expr src2)614 Expr LMIRBuilder::Mul(Type *type, Expr src1, Expr src2)
615 {
616     return CreateBinOpInternal(mirBuilder, OP_mul, type, src1, src2);
617 }
618 
UDiv(Type * type,Expr src1,Expr src2)619 Expr LMIRBuilder::UDiv(Type *type, Expr src1, Expr src2)
620 {
621     return CreateBinOpInternal(mirBuilder, OP_div, type, src1, src2);
622 }
623 
SDiv(Type * type,Expr src1,Expr src2)624 Expr LMIRBuilder::SDiv(Type *type, Expr src1, Expr src2)
625 {
626     return CreateBinOpInternal(mirBuilder, OP_div, type, src1, src2);
627 }
628 
SRem(Type * type,Expr src1,Expr src2)629 Expr LMIRBuilder::SRem(Type *type, Expr src1, Expr src2)
630 {
631     return CreateBinOpInternal(mirBuilder, OP_rem, type, src1, src2);
632 }
633 
Shl(Type * type,Expr src1,Expr src2)634 Expr LMIRBuilder::Shl(Type *type, Expr src1, Expr src2)
635 {
636     return CreateBinOpInternal(mirBuilder, OP_shl, type, src1, src2);
637 }
638 
LShr(Type * type,Expr src1,Expr src2)639 Expr LMIRBuilder::LShr(Type *type, Expr src1, Expr src2)
640 {
641     return CreateBinOpInternal(mirBuilder, OP_lshr, type, src1, src2);
642 }
643 
AShr(Type * type,Expr src1,Expr src2)644 Expr LMIRBuilder::AShr(Type *type, Expr src1, Expr src2)
645 {
646     return CreateBinOpInternal(mirBuilder, OP_ashr, type, src1, src2);
647 }
648 
And(Type * type,Expr src1,Expr src2)649 Expr LMIRBuilder::And(Type *type, Expr src1, Expr src2)
650 {
651     return CreateBinOpInternal(mirBuilder, OP_band, type, src1, src2);
652 }
653 
Or(Type * type,Expr src1,Expr src2)654 Expr LMIRBuilder::Or(Type *type, Expr src1, Expr src2)
655 {
656     return CreateBinOpInternal(mirBuilder, OP_bior, type, src1, src2);
657 }
658 
Xor(Type * type,Expr src1,Expr src2)659 Expr LMIRBuilder::Xor(Type *type, Expr src1, Expr src2)
660 {
661     return CreateBinOpInternal(mirBuilder, OP_bxor, type, src1, src2);
662 }
663 
Min(Type * type,Expr src1,Expr src2)664 Expr LMIRBuilder::Min(Type *type, Expr src1, Expr src2)
665 {
666     return CreateBinOpInternal(mirBuilder, OP_min, type, src1, src2);
667 }
668 
Max(Type * type,Expr src1,Expr src2)669 Expr LMIRBuilder::Max(Type *type, Expr src1, Expr src2)
670 {
671     return CreateBinOpInternal(mirBuilder, OP_max, type, src1, src2);
672 }
673 
CreateExprCompare(MIRBuilder & mirBuilder,Opcode op,Type * type,Expr src1,Expr src2)674 inline Expr CreateExprCompare(MIRBuilder &mirBuilder, Opcode op, Type *type, Expr src1, Expr src2)
675 {
676     // we don't check for type mismatch and insert type-conversion here
677     DEBUG_ASSERT(type != nullptr, "type should not be nullptr");
678     DEBUG_ASSERT(src1.GetType() != nullptr, "src1.GetType() should not be nullptr");
679     return Expr(mirBuilder.CreateExprCompare(op, *type, *src1.GetType(), src1.GetNode(), src2.GetNode()), type);
680 }
681 
ICmp(Type * type,Expr src1,Expr src2,IntCmpCondition cond)682 Expr LMIRBuilder::ICmp(Type *type, Expr src1, Expr src2, IntCmpCondition cond)
683 {
684     Opcode opCode = OP_eq;
685     bool isSigned = true;
686     switch (cond) {
687         case kEQ:
688             opCode = OP_eq;
689             break;
690         case kNE:
691             opCode = OP_ne;
692             break;
693         case kULT:
694             isSigned = false;
695             opCode = OP_lt;
696             break;
697         case kULE:
698             isSigned = false;
699             opCode = OP_le;
700             break;
701         case kUGT:
702             isSigned = false;
703             opCode = OP_gt;
704             break;
705         case kUGE:
706             isSigned = false;
707             opCode = OP_ge;
708             break;
709         case kSLT:
710             opCode = OP_lt;
711             break;
712         case kSLE:
713             opCode = OP_le;
714             break;
715         case kSGT:
716             opCode = OP_gt;
717             break;
718         case kSGE:
719             opCode = OP_ge;
720             break;
721     }
722     PrimType originType = src1.GetNode()->GetPrimType();
723     PrimType newType = originType;
724     switch (originType) {
725         case PTY_i8:
726         case PTY_u8:
727             newType = isSigned ? PTY_i8 : PTY_u8;
728             break;
729         case PTY_i16:
730         case PTY_u16:
731             newType = isSigned ? PTY_i16 : PTY_u16;
732             break;
733         case PTY_i32:
734         case PTY_u32:
735             newType = isSigned ? PTY_i32 : PTY_u32;
736             break;
737         case PTY_i64:
738         case PTY_u64:
739             newType = isSigned ? PTY_i64 : PTY_u64;
740             break;
741         default:
742             break;
743     }
744     Expr cmpExpr = CreateExprCompare(mirBuilder, opCode, type, src1, src2);
745     static_cast<CompareNode *>(cmpExpr.GetNode())->SetOpndType(newType);
746     return cmpExpr;
747 }
748 
FCmp(Type * type,Expr src1,Expr src2,FloatCmpCondition cond)749 Expr LMIRBuilder::FCmp(Type *type, Expr src1, Expr src2, FloatCmpCondition cond)
750 {
751     Opcode opCode = OP_eq;
752     switch (cond) {
753         case kOLT:
754             opCode = OP_lt;
755             break;
756         case kOLE:
757             opCode = OP_le;
758             break;
759         case kOGT:
760             opCode = OP_gt;
761             break;
762         case kOGE:
763             opCode = OP_ge;
764             break;
765         case kOEQ:
766             opCode = OP_eq;
767             break;
768         case kONE:
769             opCode = OP_ne;
770             break;
771     }
772     return CreateExprCompare(mirBuilder, opCode, type, src1, src2);
773 }
774 
Trunc(Type * fromType,Type * toType,Expr opnd)775 Expr LMIRBuilder::Trunc(Type *fromType, Type *toType, Expr opnd)
776 {
777     if (fromType->GetPrimType() == toType->GetPrimType() &&
778         (fromType->GetPrimType() == PTY_f64 || fromType->GetPrimType() == PTY_f32)) {
779         return Expr(mirBuilder.CreateExprTypeCvt(OP_trunc, *toType, *fromType, opnd.GetNode()), toType);
780     }
781     return Expr(mirBuilder.CreateExprTypeCvt(OP_cvt, toType->GetPrimType(), fromType->GetPrimType(), *opnd.GetNode()),
782                 toType);
783 }
784 
ZExt(Type * fromType,Type * toType,Expr opnd)785 Expr LMIRBuilder::ZExt(Type *fromType, Type *toType, Expr opnd)
786 {
787     return Expr(mirBuilder.CreateExprExtractbits(OP_zext, toType->GetPrimType(), 0,
788                                                  GetPrimTypeActualBitSize(fromType->GetPrimType()), opnd.GetNode()),
789                 toType);
790 }
791 
Cvt(Type * fromType,Type * toType,Expr opnd)792 Expr LMIRBuilder::Cvt(Type *fromType, Type *toType, Expr opnd)
793 {
794     if (fromType->GetPrimType() != toType->GetPrimType()) {
795         return Expr(mirBuilder.CreateExprTypeCvt(OP_cvt, *toType, *fromType, opnd.GetNode()), toType);
796     }
797     return Expr(opnd.GetNode(), toType);
798 }
799 
SExt(Type * fromType,Type * toType,Expr opnd)800 Expr LMIRBuilder::SExt(Type *fromType, Type *toType, Expr opnd)
801 {
802     return Expr(mirBuilder.CreateExprExtractbits(OP_sext, toType->GetPrimType(), 0,
803                                                  GetPrimTypeActualBitSize(fromType->GetPrimType()), opnd.GetNode()),
804                 toType);
805 }
806 
Floor(Type * fromType,Type * toType,Expr opnd)807 Expr LMIRBuilder::Floor(Type *fromType, Type *toType, Expr opnd)
808 {
809     return Expr(mirBuilder.CreateExprTypeCvt(OP_floor, *toType, *fromType, opnd.GetNode()), toType);
810 }
811 
Ceil(Type * fromType,Type * toType,Expr opnd)812 Expr LMIRBuilder::Ceil(Type *fromType, Type *toType, Expr opnd)
813 {
814     return Expr(mirBuilder.CreateExprTypeCvt(OP_ceil, *toType, *fromType, opnd.GetNode()), toType);
815 }
816 
BitCast(Type * fromType,Type * toType,Expr opnd)817 Expr LMIRBuilder::BitCast(Type *fromType, Type *toType, Expr opnd)
818 {
819     return Expr(mirBuilder.CreateExprRetype(*toType, *fromType, opnd.GetNode()), toType);
820 }
821 }  // namespace litecg
822 }  // namespace maple
823