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