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