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