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