• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "lmir_builder.h"
17 #include "mir_builder.h"
18 
19 namespace maple {
20 namespace litecg {
21 
22 // not exposed any longer
GetPrimitiveType(PrimType type)23 inline Type *GetPrimitiveType(PrimType type)
24 {
25     return GlobalTables::GetTypeTable().GetPrimType(type);
26 }
27 
CreateModuleWithName(const std::string & name)28 Module *CreateModuleWithName(const std::string &name)
29 {
30     return new Module(name);
31 }
32 
ReleaseModule(Module * module)33 void ReleaseModule(Module *module)
34 {
35     if (module != nullptr) {
36         delete module;
37         module = nullptr;
38     }
39     // clean current globals
40     GlobalTables::Reset();
41     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> &paramTypeList = 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 &params_, 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