• 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 }
42 
IsDread() const43 bool Expr::IsDread() const
44 {
45     return node->GetOpCode() == OP_dread;
46 }
47 
IsRegread() const48 bool Expr::IsRegread() const
49 {
50     return node->GetOpCode() == OP_regread;
51 }
52 
IsConstValue() const53 bool Expr::IsConstValue() const
54 {
55     return node->GetOpCode() == OP_constval;
56 }
57 
LMIRBuilder(Module & module_)58 LMIRBuilder::LMIRBuilder(Module &module_) : mirBuilder(*module_.GetMIRBuilder()), module(module_)
59 {
60     i8Type = GetPrimitiveType(PTY_i8);
61     i16Type = GetPrimitiveType(PTY_i16);
62     i32Type = GetPrimitiveType(PTY_i32);
63     i64Type = GetPrimitiveType(PTY_i64);
64     i128Type = GetPrimitiveType(PTY_i128);
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     u128Type = GetPrimitiveType(PTY_u128);
71     voidType = GetPrimitiveType(PTY_void);
72     f32Type = GetPrimitiveType(PTY_f32);
73     f64Type = GetPrimitiveType(PTY_f64);
74 
75     // builtin types: commonly used derived types
76     strType = CreatePtrType(u8Type);  // u8PtrType
77     i64PtrType = CreatePtrType(i64Type);
78     i64RefType = CreateRefType(i64Type);
79 }
80 
DumpIRToFile(const std::string fileName)81 void LMIRBuilder::DumpIRToFile(const std::string fileName)
82 {
83     module.DumpToFile(fileName);
84 }
85 
LiteCGGetTypeKind(Type * type) const86 LiteCGTypeKind LMIRBuilder::LiteCGGetTypeKind(Type *type) const
87 {
88     switch (type->GetKind()) {
89         case MIRTypeKind::kTypeInvalid:
90             return kLiteCGTypeInvalid;
91         case MIRTypeKind::kTypeUnknown:
92             return kLiteCGTypeUnknown;
93         case MIRTypeKind::kTypeScalar:
94             return kLiteCGTypeScalar;
95         case MIRTypeKind::kTypeBitField:
96             return kLiteCGTypeBitField;
97         case MIRTypeKind::kTypeArray:
98             return kLiteCGTypeArray;
99         case MIRTypeKind::kTypeFArray:
100             return kLiteCGTypeFArray;
101         case MIRTypeKind::kTypeJArray:
102             return kLiteCGTypeJArray;
103         case MIRTypeKind::kTypeStruct:
104             return kLiteCGTypeStruct;
105         case MIRTypeKind::kTypeUnion:
106             return kLiteCGTypeUnion;
107         case MIRTypeKind::kTypeClass:
108             return kLiteCGTypeClass;
109         case MIRTypeKind::kTypeInterface:
110             return kLiteCGTypeInterface;
111         case MIRTypeKind::kTypeStructIncomplete:
112             return kLiteCGTypeStructIncomplete;
113         case MIRTypeKind::kTypeClassIncomplete:
114             return kLiteCGTypeClassIncomplete;
115         case MIRTypeKind::kTypeConstString:
116             return kLiteCGTypeConstString;
117         case MIRTypeKind::kTypeInterfaceIncomplete:
118             return kLiteCGTypeInterfaceIncomplete;
119         case MIRTypeKind::kTypePointer:
120             return kLiteCGTypePointer;
121         case MIRTypeKind::kTypeFunction:
122             return kLiteCGTypeFunction;
123         case MIRTypeKind::kTypeVoid:
124             return kLiteCGTypeVoid;
125         case MIRTypeKind::kTypeByName:
126             return kLiteCGTypeByName;
127         case MIRTypeKind::kTypeParam:
128             return kLiteCGTypeParam;
129         case MIRTypeKind::kTypeInstantVector:
130             return kLiteCGTypeInstantVector;
131         case MIRTypeKind::kTypeGenericInstant:
132             return kLiteCGTypeGenericInstant;
133         default:
134             return kLiteCGTypeUnknown;
135     }
136 }
137 
SetCallStmtDeoptBundleInfo(Stmt & callNode,const std::unordered_map<int,LiteCGValue> & deoptBundleInfo)138 void LMIRBuilder::SetCallStmtDeoptBundleInfo(Stmt &callNode,
139                                              const std::unordered_map<int, LiteCGValue> &deoptBundleInfo)
140 {
141     MapleUnorderedMap<int, MapleValue> deoptInfos(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
142     for (const auto itr : deoptBundleInfo) {
143         auto value = itr.second;
144         if (value.kind == kPregKind) {
145             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(value.pregIdx)));
146         } else if (itr.second.kind == kSymbolKind) {
147             CHECK_FATAL(false, "symbol is not supported currently");
148             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(value.symbol)));
149         } else {
150             deoptInfos.insert(std::pair<int32_t, MapleValue>(itr.first, MapleValue(value.constVal)));
151         }
152     }
153     if (callNode.GetOpCode() == OP_call) {
154         static_cast<CallNode &>(callNode).SetDeoptBundleInfo(deoptInfos);
155     } else {
156         static_cast<IcallNode &>(callNode).SetDeoptBundleInfo(deoptInfos);
157     }
158 }
159 
CreatePtrType(Type * mirType)160 Type *LMIRBuilder::CreatePtrType(Type *mirType)
161 {
162     auto type = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType, PTY_ptr);
163     return type;
164 }
165 
CreateRefType(Type * mirType)166 Type *LMIRBuilder::CreateRefType(Type *mirType)
167 {
168     auto type = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType, PTY_ref);
169     return type;
170 }
171 
IsHeapPointerType(Type * mirType) const172 bool LMIRBuilder::IsHeapPointerType(Type *mirType) const
173 {
174     return mirType->GetPrimType() == PTY_ref;
175 }
176 
CreateArrayType(Type * elemType,std::vector<uint32_t> & dimSize)177 ArrayType *LMIRBuilder::CreateArrayType(Type *elemType, std::vector<uint32_t> &dimSize)
178 {
179     auto type = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dimSize.size(), dimSize.data());
180     return static_cast<ArrayType *>(type);
181 }
182 
CreateStructTypeInternal(const String & name,std::vector<std::pair<std::string_view,Type * >> & fields_)183 Type *LMIRBuilder::CreateStructTypeInternal(const String &name,
184                                             std::vector<std::pair<std::string_view, Type *>> &fields_)
185 {
186     FieldVector parentFields;  // parentFields not used.
187     // not sure about the cost
188     FieldVector fields;
189     for (auto field : fields_) {
190         auto strIdx = mirBuilder.GetOrCreateStringIndex(field.first.data());
191         fields.push_back(FieldPair(strIdx, TyIdxFieldAttrPair(field.second->GetTypeIndex(), FieldAttrs())));
192     }
193     auto type = GlobalTables::GetTypeTable().GetOrCreateStructType(name, fields, parentFields, module);
194     return type;
195 }
196 
GetStructType(const String & name)197 Type *LMIRBuilder::GetStructType(const String &name)
198 {
199     GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(name);
200     TyIdx typeIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(strIdx);
201     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx);
202     return type;
203 }
204 
CreateStructConstInternal(StructType * type)205 StructConst &LMIRBuilder::CreateStructConstInternal(StructType *type)
206 {
207     return *module.GetMemPool()->New<StructConst>(module, *type);
208 }
209 
CreateArrayConstInternal(ArrayType * type)210 ArrayConst &LMIRBuilder::CreateArrayConstInternal(ArrayType *type)
211 {
212     return *module.GetMemPool()->New<ArrayConst>(module, *type);
213 }
214 
GetFieldOffset(StructType * structType,FieldId fieldId)215 FieldOffset LMIRBuilder::GetFieldOffset(StructType *structType, FieldId fieldId)
216 {
217     // we should avoid access CG internals here
218     // return Globals::GetInstance()->GetBECommon()->GetFieldOffset(*structType, fieldId);
219     return std::pair<int32_t, int32_t>(0, 0);
220 }
221 
CreateFuncType(std::vector<Type * > params_,Type * retType,bool isVarg)222 Type *LMIRBuilder::CreateFuncType(std::vector<Type *> params_, Type *retType, bool isVarg)
223 {
224     std::vector<TyIdx> params;
225     std::vector<TypeAttrs> attrs;  // not used so far
226 
227     for (const auto param : params_) {
228         params.push_back(param->GetTypeIndex());
229         attrs.push_back(TypeAttrs());
230     }
231 
232     auto type = GlobalTables::GetTypeTable().GetOrCreateFunctionType(retType->GetTypeIndex(), params, attrs, isVarg);
233     return type;
234 }
235 
LiteCGGetPointedType(Type * type)236 Type *LMIRBuilder::LiteCGGetPointedType(Type *type)
237 {
238     if (type == nullptr || !type->IsMIRPtrType()) {
239         return nullptr;
240     }
241     return static_cast<MIRPtrType *>(type)->GetPointedFuncType();
242 }
243 
LiteCGGetFuncParamTypes(Type * type)244 std::vector<Type *> LMIRBuilder::LiteCGGetFuncParamTypes(Type *type)
245 {
246     std::vector<TyIdx> &paramTypeList = static_cast<MIRFuncType *>(type)->GetParamTypeList();
247     std::vector<Type *> paramTypes;
248     for (const auto paramType : paramTypeList) {
249         paramTypes.push_back(GlobalTables::GetTypeTable().GetTypeFromTyIdx(paramType));
250     }
251     return paramTypes;
252 }
253 
LiteCGGetFuncReturnType(Type * type)254 Type *LMIRBuilder::LiteCGGetFuncReturnType(Type *type)
255 {
256     if (type == nullptr || !type->IsMIRFuncType()) {
257         return nullptr;
258     }
259     TyIdx retTypeIndex = static_cast<MIRFuncType *>(type)->GetRetTyIdx();
260     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTypeIndex);
261 }
262 
263 // not sure it's FUNCATTR_local or FUNCATTR_static
264 static const FuncAttrKind FuncAttrMapTable[] = {
265     // FUNC_global,   FUNC_weak,     FUNC_internal
266     FUNCATTR_extern, FUNCATTR_weak, FUNCATTR_local};
267 
268 static const FuncAttrKind FuncConvAttrMapTable[] = {
269     // CCall,         Web_Kit_JS_Call,     GHC_Call
270     FUNCATTR_ccall, FUNCATTR_webkitjscall, FUNCATTR_ghcall};
271 
272 static const StmtAttrKind StmtConvAttrMapTable[] = {STMTATTR_ccall, STMTATTR_webkitjscall, STMTATTR_ghcall};
273 
CreateFunctionInternal(const String & name,Type * retType,Params & params_,bool isVargs,bool needBody,FuncAttr attr,ConvAttr convAttr)274 Function &LMIRBuilder::CreateFunctionInternal(const String &name, Type *retType, Params &params_, bool isVargs,
275                                               bool needBody, FuncAttr attr, ConvAttr convAttr)
276 {
277     ArgVector params(module.GetMPAllocator().Adapter());
278     for (auto param : params_) {
279         params.push_back(param);
280     }
281     auto &function = *mirBuilder.CreateFunction(name, *retType, params, isVargs, needBody);
282     // check for attr
283     function.SetAttr(FuncAttrMapTable[attr]);
284     function.SetAttr(FuncConvAttrMapTable[convAttr]);
285     // It defines a function, add to module
286     if (needBody) {
287         module.AddFunction(&function);
288     }
289     return function;
290 }
291 
GetFunc(const String & name)292 Function *LMIRBuilder::GetFunc(const String &name)
293 {
294     return mirBuilder.GetFunctionFromName(name);
295 }
296 
SetCurFunc(Function & function)297 void LMIRBuilder::SetCurFunc(Function &function)
298 {
299     module.SetCurFunction(&function);
300 }
301 
GetCurFunction() const302 Function &LMIRBuilder::GetCurFunction() const
303 {
304     return *module.CurFunction();
305 }
306 
RenameFormal2Preg(Function & func)307 void LMIRBuilder::RenameFormal2Preg(Function &func)
308 {
309     if (!func.GetPregTab()) {
310         // func no body, skip rename
311         return;
312     }
313     auto &formalVec = func.GetFormalDefVec();
314     for (uint32 i = 0; i < formalVec.size(); i++) {
315         MIRSymbol *oldSym = formalVec[i].formalSym;
316         if (!oldSym || !IsPrimitiveScalar(oldSym->GetType()->GetPrimType())) {
317             continue;
318         }
319         PregIdx regid = CreatePreg(oldSym->GetType());
320         MIRSymbol *newSym = mirBuilder.CreatePregFormalSymbol(oldSym->GetTyIdx(), regid, func);
321         formalVec[i].formalSym = newSym;
322     }
323 }
324 
SetFuncFrameResverdSlot(int slot)325 void LMIRBuilder::SetFuncFrameResverdSlot(int slot)
326 {
327     module.CurFunction()->GetFuncAttrs().SetFrameResverdSlot(slot);
328 }
329 
SetFuncFramePointer(const String & val)330 void LMIRBuilder::SetFuncFramePointer(const String &val)
331 {
332     module.CurFunction()->GetFuncAttrs().SetFramePointer(val);
333 }
334 
LiteCGGetPreg(Function & func,int32_t pRegNo)335 MIRPreg *LMIRBuilder::LiteCGGetPreg(Function &func, int32_t pRegNo)
336 {
337     return func.GetPregItem(pRegNo);
338 }
339 
LiteCGGetPregFP(Function & func)340 Expr LMIRBuilder::LiteCGGetPregFP(Function &func)
341 {
342     return Regread(kSregFp);
343 }
344 
LiteCGGetPregSP()345 Expr LMIRBuilder::LiteCGGetPregSP()
346 {
347     return Regread(kSregSp);
348 }
349 
350 // not sure it's FUNCATTR_local or FUNCATTR_static
351 static const AttrKind VarAttrMapTable[] = {
352     // VAR_external, VAR_weak, VAR_internal, VAR_global, VAR_readonly
353     ATTR_extern, ATTR_weak, ATTR_local, ATTR_extern, ATTR_readonly};
354 
CreateGlobalVar(Type * type,const String & name,GlobalVarAttr attr)355 Var &LMIRBuilder::CreateGlobalVar(Type *type, const String &name, GlobalVarAttr attr)
356 {
357     Var *var = mirBuilder.GetOrCreateSymbol(type->GetTypeIndex(), name, kStVar, kScGlobal, nullptr, kScopeGlobal,
358                                             false);  // sameType?
359     var->SetAttr(VarAttrMapTable[attr]);
360     return *var;
361 }
362 
CreateGlobalVar(Type * type,const String & name,Const & init,GlobalVarAttr attr)363 Var &LMIRBuilder::CreateGlobalVar(Type *type, const String &name, Const &init, GlobalVarAttr attr)
364 {
365     Var &var = CreateGlobalVar(type, name, attr);
366     var.SetKonst(&init);
367     return var;
368 }
369 
GetGlobalVar(const String & name)370 Var *LMIRBuilder::GetGlobalVar(const String &name)
371 {
372     return mirBuilder.GetGlobalDecl(name);
373 }
374 
CreateLocalVar(Type * type,const String & name)375 Var &LMIRBuilder::CreateLocalVar(Type *type, const String &name)
376 {
377     return *mirBuilder.GetOrCreateLocalDecl(name, *type);
378 }
379 
GetLocalVar(const String & name)380 Var *LMIRBuilder::GetLocalVar(const String &name)
381 {
382     return mirBuilder.GetLocalDecl(name);
383 }
384 
GetLocalVarFromExpr(Expr inExpr)385 Var *LMIRBuilder::GetLocalVarFromExpr(Expr inExpr)
386 {
387     auto *node = inExpr.GetNode();
388     if ((node == nullptr) || (node->GetOpCode() != OP_dread)) {
389         return nullptr;
390     }
391     return GetCurFunction().GetSymbolTabItem(static_cast<DreadNode *>(node)->GetStIdx().Idx(), true);
392 }
393 
SetFunctionDerived2BaseRef(PregIdx derived,PregIdx base)394 void LMIRBuilder::SetFunctionDerived2BaseRef(PregIdx derived, PregIdx base)
395 {
396     return GetCurFunction().SetDerived2BaseRef(derived, base);
397 }
398 
GetPregIdxFromExpr(const Expr & expr)399 PregIdx LMIRBuilder::GetPregIdxFromExpr(const Expr &expr)
400 {
401     auto *node = expr.GetNode();
402     if ((node == nullptr) || (node->GetOpCode() != OP_regread)) {
403         return 0;
404     }
405     return static_cast<RegreadNode *>(node)->GetRegIdx();
406 }
407 
GetParam(Function & function,size_t index) const408 Var &LMIRBuilder::GetParam(Function &function, size_t index) const
409 {
410     return *function.GetFormal(index);
411 }
412 
GenExprFromVar(Var & var)413 Expr LMIRBuilder::GenExprFromVar(Var &var)
414 {
415     if (var.IsPreg()) {
416         return Regread(var.GetPreg()->GetPregNo());
417     }
418     return Dread(var);
419 }
420 
CreateIntConst(Type * type,int64_t val)421 Const &LMIRBuilder::CreateIntConst(Type *type, int64_t val)
422 {
423     return *GlobalTables::GetIntConstTable().GetOrCreateIntConst(val, *type);
424 }
425 
CreateFloatConst(float val)426 Const &LMIRBuilder::CreateFloatConst(float val)
427 {
428     return *GlobalTables::GetFpConstTable().GetOrCreateFloatConst(val);
429 }
430 
CreateDoubleConst(double val)431 Const &LMIRBuilder::CreateDoubleConst(double val)
432 {
433     return *GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(val);
434 }
435 
CreateStrConst(const String & constStr)436 Const &LMIRBuilder::CreateStrConst(const String &constStr)
437 {
438     // fix the type for string const
439     return *module.GetMemPool()->New<MIRStrConst>(constStr, *strType);
440 }
441 
GetConstFromExpr(const Expr & expr)442 Const *LMIRBuilder::GetConstFromExpr(const Expr &expr)
443 {
444     auto *node = expr.GetNode();
445     if ((node == nullptr) || (node->GetOpCode() != OP_constval)) {
446         return nullptr;
447     }
448     return static_cast<ConstvalNode *>(node)->GetConstVal();
449 }
450 
CreateBB(bool needLabel)451 BB &LMIRBuilder::CreateBB(bool needLabel)
452 {
453     // not sure block-node is a correct representation
454     // create block statement in current function
455     BB &bb = *module.CurFuncCodeMemPool()->New<BlockNode>();
456     if (needLabel) {
457         // generate implement label statement as the first statement
458         LabelIdx labelIdx = module.CurFunction()->GetLabelTab()->CreateLabel();
459         (void)module.CurFunction()->GetLabelTab()->AddToStringLabelMap(labelIdx);
460         auto *labelStmt = module.CurFuncCodeMemPool()->New<LabelNode>();
461         labelStmt->SetLabelIdx(labelIdx);
462         bb.AddStatement(labelStmt);
463     }
464     return bb;
465 }
466 
AppendStmt(BB & bb,Stmt & stmt)467 void LMIRBuilder::AppendStmt(BB &bb, Stmt &stmt)
468 {
469     bb.AddStatement(&stmt);
470 }
471 
AppendStmtBeforeBranch(BB & bb,Stmt & stmt)472 void LMIRBuilder::AppendStmtBeforeBranch(BB &bb, Stmt &stmt)
473 {
474     bool inserted = false;
475     auto &nodes = bb.GetStmtNodes();
476     for (auto it = nodes.crbegin(); it != nodes.crend(); it++) {
477         auto &node = *it;
478         if (!node.IsCondBr() && (node.GetOpCode() != OP_goto)) {
479             bb.InsertAfter(&node, &stmt);
480             inserted = true;
481             break;
482         }
483     }
484     CHECK_FATAL(inserted, "PreBB must have a non jump stmt to insert PhiVarAssagin Stmt.");
485 }
486 
IsEmptyBB(BB & bb)487 bool LMIRBuilder::IsEmptyBB(BB &bb)
488 {
489     return bb.IsEmpty() || (bb.GetFirst() == bb.GetLast() && bb.GetFirst()->GetOpCode() == OP_label);
490 }
491 
SetStmtCallConv(Stmt & stmt,ConvAttr convAttr)492 void LMIRBuilder::SetStmtCallConv(Stmt &stmt, ConvAttr convAttr)
493 {
494     stmt.SetAttr(StmtConvAttrMapTable[convAttr]);
495 }
496 
AppendBB(BB & bb)497 void LMIRBuilder::AppendBB(BB &bb)
498 {
499     module.CurFunction()->GetBody()->AddStatement(&bb);
500 }
501 
AppendToLast(BB & bb)502 void LMIRBuilder::AppendToLast(BB &bb)
503 {
504     module.CurFunction()->GetLastPosBody()->AddStatement(&bb);
505 }
506 
GetLastAppendedBB()507 BB &LMIRBuilder::GetLastAppendedBB()
508 {
509     BB *pb = dynamic_cast<BB *>(module.CurFunction()->GetLastPosBody()->GetLast());
510     return *pb;
511 }
512 
GetLastPosBB()513 BB &LMIRBuilder::GetLastPosBB()
514 {
515     return *module.CurFunction()->GetLastPosBody();
516 }
517 
GetBBLabelIdx(BB & bb)518 LabelIdx GetBBLabelIdx(BB &bb)
519 {
520     LabelNode *labelNode = dynamic_cast<LabelNode *>(bb.GetFirst());
521     DEBUG_ASSERT(labelNode != nullptr, "BB should have a label statment");
522 
523     return labelNode->GetLabelIdx();
524 }
525 
Goto(BB & dest)526 Stmt &LMIRBuilder::Goto(BB &dest)
527 {
528     return *mirBuilder.CreateStmtGoto(OP_goto, GetBBLabelIdx(dest));
529 }
530 
CondGoto(Var & cond,BB & target,bool inverseCond)531 Stmt &LMIRBuilder::CondGoto(Var &cond, BB &target, bool inverseCond)
532 {
533     auto opcode = inverseCond ? OP_brtrue : OP_brfalse;
534     return *mirBuilder.CreateStmtCondGoto(Dread(cond).GetNode(), opcode, GetBBLabelIdx(target));
535 }
536 
CondGoto(Expr cond,BB & target,bool inverseCond)537 Stmt &LMIRBuilder::CondGoto(Expr cond, BB &target, bool inverseCond)
538 {
539     auto opcode = inverseCond ? OP_brtrue : OP_brfalse;
540     return *mirBuilder.CreateStmtCondGoto(cond.GetNode(), opcode, GetBBLabelIdx(target));
541 }
542 
543 // not ready yet
CreateSwitchInternal(Type * type,Expr cond,BB & defaultBB,std::vector<std::pair<int64_t,BB * >> & cases)544 Stmt &LMIRBuilder::CreateSwitchInternal(Type *type, Expr cond, BB &defaultBB,
545                                         std::vector<std::pair<int64_t, BB *>> &cases)
546 {
547     CaseVector switchTable(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
548     return *mirBuilder.CreateStmtSwitch(cond.GetNode(), GetBBLabelIdx(defaultBB), switchTable);
549 }
550 
Call(Function & func,Args & args_,Var * result)551 Stmt &LMIRBuilder::Call(Function &func, Args &args_, Var *result)
552 {
553     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
554     for (const auto &arg : args_) {
555         args.emplace_back(arg.GetNode());
556     }
557 
558     if (result == nullptr) {
559         return *mirBuilder.CreateStmtCall(func.GetPuidx(), args);
560     } else {
561         return *mirBuilder.CreateStmtCallAssigned(func.GetPuidx(), args, result);
562     }
563 }
564 
Call(Function & func,Args & args_,PregIdx pregIdx)565 Stmt &LMIRBuilder::Call(Function &func, Args &args_, PregIdx pregIdx)
566 {
567     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
568     for (const auto &arg : args_) {
569         args.emplace_back(arg.GetNode());
570     }
571     return *mirBuilder.CreateStmtCallRegassigned(func.GetPuidx(), args, pregIdx, OP_callassigned);
572 }
573 
ICall(Expr funcAddr,Args & args_,Var * result)574 Stmt &LMIRBuilder::ICall(Expr funcAddr, Args &args_, Var *result)
575 {
576     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
577     args.push_back(funcAddr.GetNode());
578     for (const auto &arg : args_) {
579         args.emplace_back(arg.GetNode());
580     }
581 
582     if (result == nullptr) {
583         return *mirBuilder.CreateStmtIcall(args);
584     } else {
585         return *mirBuilder.CreateStmtIcallAssigned(args, *result);
586     }
587 }
588 
ICall(Expr funcAddr,Args & args_,PregIdx pregIdx)589 Stmt &LMIRBuilder::ICall(Expr funcAddr, Args &args_, PregIdx pregIdx)
590 {
591     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
592     args.push_back(funcAddr.GetNode());
593     for (const auto &arg : args_) {
594         args.emplace_back(arg.GetNode());
595     }
596     return *mirBuilder.CreateStmtIcallAssigned(args, pregIdx);
597 }
598 
IntrinsicCall(IntrinsicId func_,Args & args_,Var * result)599 Stmt &LMIRBuilder::IntrinsicCall(IntrinsicId func_, Args &args_, Var *result)
600 {
601     MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
602     for (const auto &arg : args_) {
603         args.emplace_back(arg.GetNode());
604     }
605 
606     // need to fix the type for IntrinsicId
607     auto func = static_cast<MIRIntrinsicID>(func_);
608     if (result == nullptr) {
609         return *mirBuilder.CreateStmtIntrinsicCall(func, args);
610     } else {
611         return *mirBuilder.CreateStmtIntrinsicCallAssigned(func, args, result);
612     }
613 }
614 
Return(Expr returnVal)615 Stmt &LMIRBuilder::Return(Expr returnVal)
616 {
617     return *mirBuilder.CreateStmtReturn(returnVal.GetNode());
618 }
619 
Comment(std::string comment)620 Stmt &LMIRBuilder::Comment(std::string comment)
621 {
622     return *mirBuilder.CreateStmtComment(comment);
623 }
624 
Dassign(Expr src,Var & var,FieldId fieldId)625 Stmt &LMIRBuilder::Dassign(Expr src, Var &var, FieldId fieldId)
626 {
627     return *mirBuilder.CreateStmtDassign(var, fieldId, src.GetNode());
628 }
629 
Iassign(Expr src,Expr addr,Type * baseType,FieldId fieldId)630 Stmt &LMIRBuilder::Iassign(Expr src, Expr addr, Type *baseType, FieldId fieldId)
631 {
632     return *mirBuilder.CreateStmtIassign(*baseType, fieldId, addr.GetNode(), src.GetNode());
633 }
634 
Dread(Var & var)635 Expr LMIRBuilder::Dread(Var &var)
636 {
637     return Expr(mirBuilder.CreateExprDread(var), var.GetType());
638 }
639 
DreadWithField(Var & var,FieldId id)640 Expr LMIRBuilder::DreadWithField(Var &var, FieldId id)
641 {
642     auto *type = var.GetType();
643     CHECK_FATAL(type->IsStructType(), "DreadWithField: must be a struct type!");
644     auto *fldType = static_cast<MIRStructType *>(type)->GetFieldType(id);
645     return Expr(mirBuilder.CreateExprDread(*fldType, id, var), fldType);
646 }
647 
Iread(Type * type,Expr addr,Type * baseType,FieldId fieldId)648 Expr LMIRBuilder::Iread(Type *type, Expr addr, Type *baseType, FieldId fieldId)
649 {
650     return Expr(mirBuilder.CreateExprIread(*type, *baseType, fieldId, addr.GetNode()), type);
651 }
652 
CreatePreg(Type * mtype)653 PregIdx LMIRBuilder::CreatePreg(Type *mtype)
654 {
655     if ((mtype->GetPrimType() != PTY_ptr) && (mtype->GetPrimType() != PTY_ref)) {
656         // primitive type
657         return GetCurFunction().GetPregTab()->CreatePreg(mtype->GetPrimType());
658     }
659     return GetCurFunction().GetPregTab()->CreatePreg(mtype->GetPrimType(), mtype);
660 }
661 
Regassign(Expr src,PregIdx pregIdx)662 Stmt &LMIRBuilder::Regassign(Expr src, PregIdx pregIdx)
663 {
664     return *(mirBuilder.CreateStmtRegassign(src.GetType()->GetPrimType(), pregIdx, src.GetNode()));
665 }
666 
Regread(PregIdx pregIdx)667 Expr LMIRBuilder::Regread(PregIdx pregIdx)
668 {
669     MIRPreg *preg = GetCurFunction().GetPregTab()->PregFromPregIdx(pregIdx);
670     if (pregIdx < 0) {
671         // special register
672         return Expr(mirBuilder.CreateExprRegread(PTY_i64, pregIdx), i64Type);
673     }
674     if (preg->GetMIRType() != nullptr) {
675         return Expr(mirBuilder.CreateExprRegread(preg->GetPrimType(), pregIdx), preg->GetMIRType());
676     }
677     // the type of value in reg is primitive type
678     Type *type = GetPrimitiveType(preg->GetPrimType());
679     return Expr(mirBuilder.CreateExprRegread(preg->GetPrimType(), pregIdx), type);
680 }
681 
Addrof(Var & var)682 Expr LMIRBuilder::Addrof(Var &var)
683 {
684     return Expr(mirBuilder.CreateAddrof(var), var.GetType());
685 }
686 
ConstVal(Const & constVal)687 Expr LMIRBuilder::ConstVal(Const &constVal)
688 {
689     return Expr(mirBuilder.CreateConstval(&constVal), &constVal.GetType());
690 }
691 
Lnot(Type * type,Expr src)692 Expr LMIRBuilder::Lnot(Type *type, Expr src)
693 {
694     return Expr(mirBuilder.CreateExprUnary(OP_lnot, *type, src.GetNode()), type);
695 }
696 
Bnot(Type * type,Expr src)697 Expr LMIRBuilder::Bnot(Type *type, Expr src)
698 {
699     return Expr(mirBuilder.CreateExprUnary(OP_bnot, *type, src.GetNode()), type);
700 }
701 
Sqrt(Type * type,Expr src)702 Expr LMIRBuilder::Sqrt(Type *type, Expr src)
703 {
704     return Expr(mirBuilder.CreateExprUnary(OP_sqrt, *type, src.GetNode()), type);
705 }
706 
CreateBinOpInternal(MIRBuilder & mirBuilder,Opcode op,Type * type,Expr src1,Expr src2)707 inline Expr CreateBinOpInternal(MIRBuilder &mirBuilder, Opcode op, Type *type, Expr src1, Expr src2)
708 {
709     // we don't check for type mismatch and insert type-conversion here
710     return Expr(mirBuilder.CreateExprBinary(op, *type, src1.GetNode(), src2.GetNode()), type);
711 }
712 
Add(Type * type,Expr src1,Expr src2)713 Expr LMIRBuilder::Add(Type *type, Expr src1, Expr src2)
714 {
715     return CreateBinOpInternal(mirBuilder, OP_add, type, src1, src2);
716 }
717 
Sub(Type * type,Expr src1,Expr src2)718 Expr LMIRBuilder::Sub(Type *type, Expr src1, Expr src2)
719 {
720     return CreateBinOpInternal(mirBuilder, OP_sub, type, src1, src2);
721 }
722 
Mul(Type * type,Expr src1,Expr src2)723 Expr LMIRBuilder::Mul(Type *type, Expr src1, Expr src2)
724 {
725     return CreateBinOpInternal(mirBuilder, OP_mul, type, src1, src2);
726 }
727 
UDiv(Type * type,Expr src1,Expr src2)728 Expr LMIRBuilder::UDiv(Type *type, Expr src1, Expr src2)
729 {
730     return CreateBinOpInternal(mirBuilder, OP_div, type, src1, src2);
731 }
732 
SDiv(Type * type,Expr src1,Expr src2)733 Expr LMIRBuilder::SDiv(Type *type, Expr src1, Expr src2)
734 {
735     return CreateBinOpInternal(mirBuilder, OP_div, type, src1, src2);
736 }
737 
URem(Type * type,Expr src1,Expr src2)738 Expr LMIRBuilder::URem(Type *type, Expr src1, Expr src2)
739 {
740     return CreateBinOpInternal(mirBuilder, OP_rem, type, src1, src2);
741 }
742 
SRem(Type * type,Expr src1,Expr src2)743 Expr LMIRBuilder::SRem(Type *type, Expr src1, Expr src2)
744 {
745     return CreateBinOpInternal(mirBuilder, OP_rem, type, src1, src2);
746 }
747 
Shl(Type * type,Expr src1,Expr src2)748 Expr LMIRBuilder::Shl(Type *type, Expr src1, Expr src2)
749 {
750     return CreateBinOpInternal(mirBuilder, OP_shl, type, src1, src2);
751 }
752 
LShr(Type * type,Expr src1,Expr src2)753 Expr LMIRBuilder::LShr(Type *type, Expr src1, Expr src2)
754 {
755     return CreateBinOpInternal(mirBuilder, OP_lshr, type, src1, src2);
756 }
757 
AShr(Type * type,Expr src1,Expr src2)758 Expr LMIRBuilder::AShr(Type *type, Expr src1, Expr src2)
759 {
760     return CreateBinOpInternal(mirBuilder, OP_ashr, type, src1, src2);
761 }
762 
And(Type * type,Expr src1,Expr src2)763 Expr LMIRBuilder::And(Type *type, Expr src1, Expr src2)
764 {
765     return CreateBinOpInternal(mirBuilder, OP_band, type, src1, src2);
766 }
767 
Or(Type * type,Expr src1,Expr src2)768 Expr LMIRBuilder::Or(Type *type, Expr src1, Expr src2)
769 {
770     return CreateBinOpInternal(mirBuilder, OP_bior, type, src1, src2);
771 }
772 
Xor(Type * type,Expr src1,Expr src2)773 Expr LMIRBuilder::Xor(Type *type, Expr src1, Expr src2)
774 {
775     return CreateBinOpInternal(mirBuilder, OP_bxor, type, src1, src2);
776 }
777 
ICmpEQ(Type * type,Expr src1,Expr src2)778 Expr LMIRBuilder::ICmpEQ(Type *type, Expr src1, Expr src2)
779 {
780     return CreateBinOpInternal(mirBuilder, OP_eq, type, src1, src2);
781 }
782 
ICmpNE(Type * type,Expr src1,Expr src2)783 Expr LMIRBuilder::ICmpNE(Type *type, Expr src1, Expr src2)
784 {
785     return CreateBinOpInternal(mirBuilder, OP_ne, type, src1, src2);
786 }
787 
ICmpULT(Type * type,Expr src1,Expr src2)788 Expr LMIRBuilder::ICmpULT(Type *type, Expr src1, Expr src2)
789 {
790     return CreateBinOpInternal(mirBuilder, OP_lt, type, src1, src2);
791 }
792 
ICmpULE(Type * type,Expr src1,Expr src2)793 Expr LMIRBuilder::ICmpULE(Type *type, Expr src1, Expr src2)
794 {
795     return CreateBinOpInternal(mirBuilder, OP_le, type, src1, src2);
796 }
797 
ICmpUGT(Type * type,Expr src1,Expr src2)798 Expr LMIRBuilder::ICmpUGT(Type *type, Expr src1, Expr src2)
799 {
800     return CreateBinOpInternal(mirBuilder, OP_gt, type, src1, src2);
801 }
802 
ICmpUGE(Type * type,Expr src1,Expr src2)803 Expr LMIRBuilder::ICmpUGE(Type *type, Expr src1, Expr src2)
804 {
805     return CreateBinOpInternal(mirBuilder, OP_ge, type, src1, src2);
806 }
807 
ICmpSLT(Type * type,Expr src1,Expr src2)808 Expr LMIRBuilder::ICmpSLT(Type *type, Expr src1, Expr src2)
809 {
810     return CreateBinOpInternal(mirBuilder, OP_lt, type, src1, src2);
811 }
812 
ICmpSLE(Type * type,Expr src1,Expr src2)813 Expr LMIRBuilder::ICmpSLE(Type *type, Expr src1, Expr src2)
814 {
815     return CreateBinOpInternal(mirBuilder, OP_le, type, src1, src2);
816 }
817 
ICmpSGT(Type * type,Expr src1,Expr src2)818 Expr LMIRBuilder::ICmpSGT(Type *type, Expr src1, Expr src2)
819 {
820     return CreateBinOpInternal(mirBuilder, OP_gt, type, src1, src2);
821 }
822 
ICmpSGE(Type * type,Expr src1,Expr src2)823 Expr LMIRBuilder::ICmpSGE(Type *type, Expr src1, Expr src2)
824 {
825     return CreateBinOpInternal(mirBuilder, OP_ge, type, src1, src2);
826 }
827 
CreateExprCompare(MIRBuilder & mirBuilder,Opcode op,Type * type,Expr src1,Expr src2)828 inline Expr CreateExprCompare(MIRBuilder &mirBuilder, Opcode op, Type *type, Expr src1, Expr src2)
829 {
830     // we don't check for type mismatch and insert type-conversion here
831     return Expr(mirBuilder.CreateExprCompare(op, *type, *src1.GetType(), src1.GetNode(), src2.GetNode()), type);
832 }
833 
ICmp(Type * type,Expr src1,Expr src2,IntCmpCondition cond)834 Expr LMIRBuilder::ICmp(Type *type, Expr src1, Expr src2, IntCmpCondition cond)
835 {
836     Opcode opCode = OP_eq;
837     bool isSigned = true;
838     switch (cond) {
839         case kEQ:
840             opCode = OP_eq;
841             break;
842         case kNE:
843             opCode = OP_ne;
844             break;
845         case kULT:
846             isSigned = false;
847             opCode = OP_lt;
848             break;
849         case kULE:
850             isSigned = false;
851             opCode = OP_le;
852             break;
853         case kUGT:
854             isSigned = false;
855             opCode = OP_gt;
856             break;
857         case kUGE:
858             isSigned = false;
859             opCode = OP_ge;
860             break;
861         case kSLT:
862             opCode = OP_lt;
863             break;
864         case kSLE:
865             opCode = OP_le;
866             break;
867         case kSGT:
868             opCode = OP_gt;
869             break;
870         case kSGE:
871             opCode = OP_ge;
872             break;
873     }
874     PrimType originType = src1.GetNode()->GetPrimType();
875     PrimType newType = originType;
876     if (!isSigned) {
877         switch (originType) {
878             case PTY_i8:
879                 newType = PTY_u8;
880                 break;
881             case PTY_i16:
882                 newType = PTY_u16;
883                 break;
884             case PTY_i32:
885                 newType = PTY_u32;
886                 break;
887             case PTY_i64:
888                 newType = PTY_u64;
889                 break;
890             default:
891                 break;
892         }
893     }
894     Expr cmpExpr = CreateExprCompare(mirBuilder, opCode, type, src1, src2);
895     static_cast<CompareNode *>(cmpExpr.GetNode())->SetOpndType(newType);
896     return cmpExpr;
897 }
898 
FCmp(Type * type,Expr src1,Expr src2,FloatCmpCondition cond)899 Expr LMIRBuilder::FCmp(Type *type, Expr src1, Expr src2, FloatCmpCondition cond)
900 {
901     Opcode opCode = OP_eq;
902     switch (cond) {
903         case kOLT:
904             opCode = OP_lt;
905             break;
906         case kOLE:
907             opCode = OP_le;
908             break;
909         case kOGT:
910             opCode = OP_gt;
911             break;
912         case kOGE:
913             opCode = OP_ge;
914             break;
915         case kOEQ:
916             opCode = OP_eq;
917             break;
918         case kONE:
919             opCode = OP_ne;
920             break;
921     }
922     return CreateExprCompare(mirBuilder, opCode, type, src1, src2);
923 }
924 
Select(Type * type,Expr cond,Expr ifTrue,Expr ifFalse)925 Expr LMIRBuilder::Select(Type *type, Expr cond, Expr ifTrue, Expr ifFalse)
926 {
927     return Expr(mirBuilder.CreateExprTernary(OP_select, *type, cond.GetNode(), ifTrue.GetNode(), ifFalse.GetNode()),
928                 type);
929 }
930 
Trunc(Type * fromType,Type * toType,Expr opnd)931 Expr LMIRBuilder::Trunc(Type *fromType, Type *toType, Expr opnd)
932 {
933     return Expr(mirBuilder.CreateExprTypeCvt(OP_cvt, toType->GetPrimType(), fromType->GetPrimType(), *opnd.GetNode()),
934                 toType);
935 }
936 
ZExt(Type * fromType,Type * toType,Expr opnd)937 Expr LMIRBuilder::ZExt(Type *fromType, Type *toType, Expr opnd)
938 {
939     return Expr(mirBuilder.CreateExprExtractbits(OP_zext, toType->GetPrimType(), 0,
940                                                  GetPrimTypeActualBitSize(fromType->GetPrimType()), opnd.GetNode()),
941                 toType);
942 }
943 
Cvt(Type * fromType,Type * toType,Expr opnd)944 Expr LMIRBuilder::Cvt(Type *fromType, Type *toType, Expr opnd)
945 {
946     if (fromType->GetPrimType() != toType->GetPrimType()) {
947         return Expr(mirBuilder.CreateExprTypeCvt(OP_cvt, *toType, *fromType, opnd.GetNode()), toType);
948     }
949     return Expr(opnd.GetNode(), toType);
950 }
951 
SExt(Type * fromType,Type * toType,Expr opnd)952 Expr LMIRBuilder::SExt(Type *fromType, Type *toType, Expr opnd)
953 {
954     return Expr(mirBuilder.CreateExprExtractbits(OP_sext, toType->GetPrimType(), 0,
955                                                  GetPrimTypeActualBitSize(fromType->GetPrimType()), opnd.GetNode()),
956                 toType);
957 }
958 
BitCast(Type * fromType,Type * toType,Expr opnd)959 Expr LMIRBuilder::BitCast(Type *fromType, Type *toType, Expr opnd)
960 {
961     return Expr(mirBuilder.CreateExprRetype(*toType, *fromType, opnd.GetNode()), toType);
962 }
963 }  // namespace litecg
964 }  // namespace maple
965