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> ¶mTypeList = 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 ¶ms_, 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