• 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 #ifndef MAPLE_LITECG_LMIR_BUILDER_H
17 #define MAPLE_LITECG_LMIR_BUILDER_H
18 
19 #include <cstdint>
20 #include <vector>
21 #include <map>
22 #include <string>
23 #include <utility>
24 #include <unordered_map>
25 
26 /*
27   LMIR API exported.
28 
29   LMIR, the low-level MIR, will serve as the canonical input for LiteCG.
30 
31   Currently, it only contains the minimum set of features enough to
32   support eCompiler scenarioes. Later it will grow to be a complete core
33   set, but still with "just enough" features for general cases.
34 
35   Additional features, will be defined with x-extension strategy.
36 
37   The motivation of LMIR, is to hide the whole complexity of MIR interfaces,
38   and this should make integration of maple components easier.
39  */
40 namespace maple {
41 
42 /* import types for MIR: this is basically a simplification
43    we just need declaration, not headers.
44  */
45 class MIRBuilder;  // currently we just delegate MIRBuilder
46 class MIRModule;
47 class MIRFunction;
48 class MIRType;
49 class MIRStructType;
50 class MIRArrayType;
51 class MIRFuncType;
52 class MIRConst;
53 class MIRAggConst;
54 class MIRSymbol;
55 class StmtNode;
56 class BaseNode;
57 class BlockNode;
58 class MIRPreg;
59 
60 namespace litecg {
61 
62 // Our type abstraction. currently delegate to MIR
63 
64 using String = std::string;
65 
66 using Module = MIRModule;
67 using Function = MIRFunction;
68 
69 // Note: Type is base class of all other Types
70 using Type = MIRType;              // base class of all Types
71 using StructType = MIRStructType;  //    |__ StructType
72 using ArrayType = MIRArrayType;
73 using Const = MIRConst;
74 using StructConst = MIRAggConst;
75 using ArrayConst = MIRAggConst;
76 using Var = MIRSymbol;
77 using Stmt = StmtNode;
78 using BB = BlockNode;  // A temporary faked BB
79 
80 using Param = std::pair<const String, Type *>;
81 using Params = std::vector<Param>;
82 using FieldOffset = std::pair<int32_t, int32_t>;  // (byteoffset, bitoffset)
83 using PregIdx = int32_t;
84 
85 // enumerations
86 enum class MIRIntrinsic {
87 #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) INTRN_##STR,
88 #include "intrinsics.def"
89 #undef DEF_MIR_INTRINSIC
90 };
91 using IntrinsicId = MIRIntrinsic;
92 /* available intrinsic should be list here. like:
93    INTRN_memcpy, INTRN_memset, etc.
94  */
95 class Expr {
96 public:
Expr(BaseNode * baseNode,Type * nodeType)97     Expr(BaseNode *baseNode, Type *nodeType) : node(baseNode), type(nodeType) {}
98 
Expr()99     Expr() : node(nullptr), type(nullptr) {}
100 
101     ~Expr() = default;
102 
GetNode()103     BaseNode *GetNode()
104     {
105         return node;
106     }
107 
GetNode()108     BaseNode *GetNode() const
109     {
110         return node;
111     }
112 
GetType()113     Type *GetType()
114     {
115         return type;
116     }
117 
GetType()118     Type *GetType() const
119     {
120         return type;
121     }
122 
123     bool IsDread() const;
124     bool IsRegread() const;
125     bool IsConstValue() const;
126 
127 private:
128     BaseNode *node;
129     Type *type;
130 };
131 
132 enum LiteCGValueKind {
133     kPregKind,
134     kSymbolKind,
135     kConstKind,
136 };
137 
138 struct LiteCGValue {
139     PregIdx pregIdx;
140     MIRSymbol *symbol;
141     MIRConst *constVal;
142     LiteCGValueKind kind;
143 };
144 
145 using Args = std::vector<Expr>;
146 
147 enum FuncAttr {     // visibility of the defined function
148     FUNC_global,    // function has global visibility
149     FUNC_weak,      // weak function defined in this module
150     FUNC_internal,  // function defined and only used in this module
151 };
152 
153 enum GlobalRegister {
154     kSregSp = -1,
155     kSregFp = -2,
156 };
157 
158 enum ConvAttr {
159     CCall,
160     Web_Kit_JS_Call,
161     GHC_Call,
162 };
163 
164 enum GlobalVarAttr {
165     VAR_external,  // global variable declaration (no definition)
166     VAR_weak,      // weak function defined in this module
167     VAR_internal,  // variable defined and only used in this module
168     VAR_global,    // exported variable defined in this module
169     VAR_readonly,  // this is additional flag, default is R/W
170 };
171 
172 enum IntCmpCondition {
173     kEQ,
174     kNE,
175     kULT,
176     kULE,
177     kUGT,
178     kUGE,
179     kSLT,
180     kSLE,
181     kSGT,
182     kSGE,
183 };
184 
185 enum FloatCmpCondition {
186     kOLT,
187     kOLE,
188     kOGT,
189     kOGE,
190     kONE,
191     kOEQ,
192 };
193 
194 enum LiteCGTypeKind {
195     kLiteCGTypeInvalid,
196     kLiteCGTypeUnknown,
197     kLiteCGTypeScalar,
198     kLiteCGTypeBitField,
199     kLiteCGTypeArray,
200     kLiteCGTypeFArray,
201     kLiteCGTypeJArray,
202     kLiteCGTypeStruct,
203     kLiteCGTypeUnion,
204     kLiteCGTypeClass,
205     kLiteCGTypeInterface,
206     kLiteCGTypeStructIncomplete,
207     kLiteCGTypeClassIncomplete,
208     kLiteCGTypeConstString,
209     kLiteCGTypeInterfaceIncomplete,
210     kLiteCGTypePointer,
211     kLiteCGTypeFunction,
212     kLiteCGTypeVoid,
213     kLiteCGTypeByName,
214     kLiteCGTypeParam,
215     kLiteCGTypeInstantVector,
216     kLiteCGTypeGenericInstant,
217 };
218 
219 // FieldAttr: do we need to support volatile here?
220 // using FieldAttr = AttrKind
221 /* used attribute for field:
222    ATTR_volatile
223  */
224 
225 using FieldId = uint32_t;
226 /* Use FieldId from MIR directly: it's a uint32_t, but with special meaning
227    for FieldId == 0: refer to the "whole" of the type
228    To avoid conflict with MIR type define, here using type name "FieldId"
229  */
230 
231 Module *CreateModuleWithName(const std::string &name);
232 void ReleaseModule(Module *module);
233 
234 /**
235  * a simplified, specialized MapleIR builder for LiteCG
236  * The basic IR set
237  *
238  * General rule for the interface:
239  *  + if function returns value type, then returns type is value type
240  *  + otherwise if the return value can be null, return type is pointer
241  *    caller should check for null
242  *  + otherwise the return type is reference.
243  *
244  *  + for compound IR (need to be constructed with a sequence of calls,
245  *      e.g., struct type/const, array const, function, switch), using
246  *    specific builder class to do the "chained" construction.
247  *
248  */
249 class LMIRBuilder {
250 public:
251     LMIRBuilder(Module &module);
252     ~LMIRBuilder() = default;
253 
254     void DumpIRToFile(const std::string fileName);
255 
256     LiteCGTypeKind LiteCGGetTypeKind(Type *type) const;
257     void SetCallStmtDeoptBundleInfo(Stmt &icallNode, const std::unordered_map<int, LiteCGValue> &deoptBundleInfo);
258 
259     // Type creation (currently all in global scope)
260     /*
261        For primitive types, using LMIRBuilder's public member:
262        i8Type, u8Type, etc.
263      */
264 
265     // derived type creation
266     Type *CreatePtrType(Type *mirType);
267     Type *CreateRefType(Type *mirType);
268 
269     bool IsHeapPointerType(Type *mirType) const;
270 
271     // (multi-dim) array of fixed size array
272     ArrayType *CreateArrayType(Type *elemType, std::vector<uint32_t> &dimSize);
273 
274     /* using StructTypeBuilder interface for StructType creation
275          auto structType = CreateStructType("mystruct")
276                              .Field("field1", i32Type)
277                              .Field("field2", i64Type)
278                              .Done();
279      */
280     Type *GetStructType(const String &name);  // query for existing struct type
281 
282     // usage of this function has precondition, should be documented
283     FieldOffset GetFieldOffset(StructType *structType, FieldId fieldId);
284 
285     // for function pointer
286     Type *CreateFuncType(std::vector<Type *> params, Type *retType, bool isVarg);
287 
288     Type *LiteCGGetPointedType(Type *type);
289 
290     std::vector<Type *> LiteCGGetFuncParamTypes(Type *type);
291 
292     Type *LiteCGGetFuncReturnType(Type *type);
293     // still need interface for AddressOfFunction
294 
295     // Function declaration and definition
296     /* using FunctionBuilder interface for Function creation:
297          // i32 myfunc(i32 param1, i64 param2) { }
298          auto structType = DefineFunction("myfunc")
299                              .Param(i32Type, "param1")
300                              .Param(i64Type, "param2")
301                              .Ret(i32Type)               // optional for void
302                              .Done();
303 
304          // i32 myfunc1(i32 param1, i64 param2);
305          auto structType = DeclareFunction("myfunc1")
306                              .Param(i32Type, "param1")
307                              .Param(i64Type, "param2")
308                              .Ret(i32Type)
309                              .Done();
310      */
311 
312     // This is to enable forwarded call before its definition
313     // can return null. caller should check for null.
314     Function *GetFunc(const String &name);  // get a function by its unique name
315 
316     // when a function is set as current function (of the module), local
317     // declarations and statements are insert into it.
318     void SetCurFunc(Function &function);
319 
320     Function &GetCurFunction() const;
321 
322     void RenameFormal2Preg(Function &func);
323 
324     MIRPreg *LiteCGGetPreg(Function &func, int32_t pRegNo);
325     Expr LiteCGGetPregFP(Function &func);
326     Expr LiteCGGetPregSP();
327 
328     // var creation
329     // refine the interface for attributes here. and also storage-class?
330     // initialized to zero if defined here, by default not exported
331     Var &CreateGlobalVar(Type *type, const String &name, GlobalVarAttr attr = VAR_internal);
332     // initialized to const, by default not exported
333     Var &CreateGlobalVar(Type *type, const String &name, Const &init, GlobalVarAttr attr = VAR_internal);
334     Var *GetGlobalVar(const String &name);
335 
336     Var &CreateLocalVar(Type *type, const String &name);
337     Var *GetLocalVar(const String &name);
338     Var *GetLocalVarFromExpr(Expr inExpr);
339     void SetFunctionDerived2BaseRef(PregIdx derived, PregIdx base);
340     PregIdx GetPregIdxFromExpr(const Expr &expr);
341     Var &GetParam(Function &function, size_t index) const;
342     Expr GenExprFromVar(Var &var);
343 
344     Const &CreateIntConst(Type *type, int64_t val);
345     Const &CreateFloatConst(float val);
346     Const &CreateDoubleConst(double val);
347     Const &CreateStrConst(const String &constStr);
348     Const *GetConstFromExpr(const Expr &expr);
349 
350     // In MIR, the const for struct & array are the same. But we separate it here.
351     /* using StructConstBuilder interface for StructConst creation:
352          auto structConst = CreateStructConst(structType)
353                               .Field(1, CreateIntConst(i32Type, 0))
354                               .Filed(2, CreateIntConst(i64Type, 0))
355                               .Done();
356      */
357 
358     /* using ArrayConstBuilder interface for ArrayConst creation:
359        Note: the elements should be added consequentially, and match the dim size.
360          auto arrayConst = CreateArrayConst(arrayType)
361                               .Element(CreateIntConst(i32Type, 0))
362                               .Element(CreateIntConst(i32Type, 0))
363                               .Done();
364        or using the following form:
365          auto arrayConst = CreateArrayConst(arrayType).Dim({0, 0}).Done();
366      */
367 
368     /*
369       BB is the container node for a sequence or linear statements,
370       if needLabel == true, implicitly create a label node as its first statement.
371       BB also servers as target for Gotos, when it's a goto target, it
372       should have needLabel == true
373      */
374     BB &CreateBB(bool needLabel = true);
375     void AppendStmt(BB &bb, Stmt &stmt);              // append stmt to the back of BB
376     void AppendStmtBeforeBranch(BB &bb, Stmt &stmt);  // append stmt after the first non-jump stmt in back of BB
377     bool IsEmptyBB(BB &bb);
378     void AppendBB(BB &bb);    // append BB to the back of current function;
379     void AppendToLast(BB &bb);
380     BB &GetLastPosBB();
381     BB &GetLastAppendedBB();  // get last appended BB of current function
382 
383     void SetStmtCallConv(Stmt &stmt, ConvAttr convAttr);
384 
385     // statements
386     Stmt &Goto(BB &dest);  // jump without condition
387     /* conditional goto:
388        when inverseCond == true, using (!cond) as condition
389 
390        1. if(cond)-then form code should be generated this way:
391 
392          if(!cond) goto BB_end    // CondGoto(cond, BB_end, true);
393          BB_ifTrue: {...}
394          BB_end: {...}
395 
396        2. if-then-else form code should be generated this way:
397          if(cond) goto BB_ifTrue  // CondGoto(cond, BB_ifTrue);
398          BB_ifFalse: {
399            ...
400            goto BB_end            // should be generated in BB_ifFalse
401          }
402          BB_ifTrue: {...}
403          BB_end: {...}
404      */
405     Stmt &CondGoto(Var &cond, BB &target, bool inverseCond = false);
406     Stmt &CondGoto(Expr cond, BB &target, bool inverseCond = false);
407 
408     /* using SwitchBuilder interface for switch statement creation
409          auto switchStmt = Switch(type, cond, defaultBB)
410                              .Case(0, bb1)
411                              .Case(1, bb2)
412                              .Done();
413      */
414 
415     // when result is nullptr, don't need the result (or no result)
416     Stmt &Call(Function &func, Args &args, Var *result = nullptr);
417 
418     Stmt &Call(Function &func, Args &args, PregIdx pregIdx);
419 
420     Stmt &ICall(Expr funcAddr, Args &args, Var *result = nullptr);
421 
422     Stmt &ICall(Expr funcAddr, Args &args, PregIdx pregIdx);
423 
424     // when result is nullptr, don't need the result (or no result)
425     Stmt &IntrinsicCall(IntrinsicId func, Args &valueArgs, Var *result = nullptr);
426 
427     Stmt &Return(Expr returnVal);
428 
429     // debug info
430     Stmt &Comment(std::string comment);
431 
432     Stmt &Dassign(Expr src, Var &var, FieldId fieldId = 0);
433     Stmt &Iassign(Expr src, Expr addr, Type *baseType, FieldId fieldId = 0);
434 
435     // expressions
436     Expr Dread(Var &var);  // do we need other forms?
Dread(Var * var)437     inline Expr Dread(Var *var)
438     {  // shortcut for read from local-var
439         return Dread(*var);
440     }
441 
442     Expr DreadWithField(Var &var, FieldId id);
443 
444     Expr Iread(Type *type, Expr addr, Type *baseType, FieldId fieldId = 0);
445     PregIdx CreatePreg(Type *mtype);
446     Stmt &Regassign(Expr src, PregIdx reg);
447     Expr Regread(PregIdx pregIdx);
448     Expr Addrof(Var &var);           // do we need other forms?
449     Expr ConstVal(Const &constVal);  // a const operand
450 
451     Expr Lnot(Type *type, Expr src);
452     Expr Bnot(Type *type, Expr src);
453     Expr Sqrt(Type *type, Expr src);
454 
455     Expr Add(Type *type, Expr src1, Expr src2);
456     Expr Sub(Type *type, Expr src1, Expr src2);
457     Expr Mul(Type *type, Expr src1, Expr src2);
458     Expr UDiv(Type *type, Expr src1, Expr src2);  // unsigned
459     Expr SDiv(Type *type, Expr src1, Expr src2);  // signed
460     Expr URem(Type *type, Expr src1, Expr src2);  // unsigned
461     Expr SRem(Type *type, Expr src1, Expr src2);  // signed
462     Expr Shl(Type *type, Expr src1, Expr src2);
463     Expr LShr(Type *type, Expr src1, Expr src2);
464     Expr AShr(Type *type, Expr src1, Expr src2);
465     Expr And(Type *type, Expr src1, Expr src2);
466     Expr Or(Type *type, Expr src1, Expr src2);
467     Expr Xor(Type *type, Expr src1, Expr src2);
468 
469     Expr ICmpEQ(Type *type, Expr src1, Expr src2);
470     Expr ICmpNE(Type *type, Expr src1, Expr src2);
471     // unsigned compare
472     Expr ICmpULT(Type *type, Expr src1, Expr src2);
473     Expr ICmpULE(Type *type, Expr src1, Expr src2);
474     Expr ICmpUGT(Type *type, Expr src1, Expr src2);
475     Expr ICmpUGE(Type *type, Expr src1, Expr src2);
476     // signed compare
477     Expr ICmpSLT(Type *type, Expr src1, Expr src2);
478     Expr ICmpSLE(Type *type, Expr src1, Expr src2);
479     Expr ICmpSGT(Type *type, Expr src1, Expr src2);
480     Expr ICmpSGE(Type *type, Expr src1, Expr src2);
481     Expr ICmp(Type *type, Expr src1, Expr src2, IntCmpCondition cond);
482     Expr FCmp(Type *type, Expr src1, Expr src2, FloatCmpCondition cond);
483 
484     // Type conversion
485     // Type of opnd should be consistent with fromType: no implicient conversion
486     Expr Trunc(Type *fromType, Type *toType, Expr opnd);
487     Expr ZExt(Type *fromType, Type *toType, Expr opnd);
488     Expr SExt(Type *fromType, Type *toType, Expr opnd);
489     Expr BitCast(Type *fromType, Type *toType, Expr opnd);
490     Expr Cvt(Type *fromType, Type *toType, Expr opnd);
491 
492     Expr Select(Type *type, Expr cond, Expr ifTrue, Expr ifFalse);
493 
494     void SetFuncFrameResverdSlot(int slot);
495     void SetFuncFramePointer(const String &val);
496 
497 public:
498     // helper classes for compound IR entity building
499     class SwitchBuilder {
500     public:
SwitchBuilder(LMIRBuilder & builder_,Type * type_,Expr cond_,BB & defaultBB_)501         SwitchBuilder(LMIRBuilder &builder_, Type *type_, Expr cond_, BB &defaultBB_)
502             : builder(builder_), type(type_), cond(cond_), defaultBB(defaultBB_)
503         {
504         }
505 
Case(int64_t value,BB & bb)506         SwitchBuilder &Case(int64_t value, BB &bb)
507         {
508             cases.push_back(std::make_pair(value, &bb));
509             return *this;
510         }
511 
Done()512         Stmt &Done()
513         {
514             return builder.CreateSwitchInternal(type, cond, defaultBB, cases);
515         }
516 
517     private:
518         LMIRBuilder &builder;
519         Type *type;
520         Expr cond;
521         BB &defaultBB;
522         std::vector<std::pair<int64_t, BB *>> cases;
523     };
524 
Switch(Type * type,Expr cond,BB & defaultBB)525     SwitchBuilder Switch(Type *type, Expr cond, BB &defaultBB)
526     {
527         return SwitchBuilder(*this, type, cond, defaultBB);
528     }
529 
530     class StructTypeBuilder {
531     public:
StructTypeBuilder(LMIRBuilder & builder_,const String & name_)532         StructTypeBuilder(LMIRBuilder &builder_, const String &name_) : builder(builder_), name(name_) {}
533 
Field(std::string_view fieldName,Type * fieldType)534         StructTypeBuilder &Field(std::string_view fieldName, Type *fieldType)
535         {
536             // field type attribute?
537             fields.push_back(std::make_pair(fieldName, fieldType));
538             return *this;
539         }
540 
Done()541         Type *Done()
542         {
543             return builder.CreateStructTypeInternal(name, fields);
544         }
545 
546     private:
547         LMIRBuilder &builder;
548         const String &name;
549         std::vector<std::pair<std::string_view, Type *>> fields;
550     };
551 
CreateStructType(const String & name)552     StructTypeBuilder CreateStructType(const String &name)
553     {
554         return StructTypeBuilder(*this, name);
555     }
556 
557     class StructConstBuilder {
558     public:
StructConstBuilder(LMIRBuilder & builder_,StructType * type_)559         StructConstBuilder(LMIRBuilder &builder_, StructType *type_) : builder(builder_)
560         {
561             structConst = &builder_.CreateStructConstInternal(type_);
562         }
563 
Field(FieldId fieldId,Const & field)564         StructConstBuilder &Field(FieldId fieldId, Const &field)
565         {
566             builder.AddConstItemInternal(*structConst, fieldId, field);
567             return *this;
568         }
569 
Done()570         StructConst &Done()
571         {
572             return *structConst;
573         }
574 
575     private:
576         LMIRBuilder &builder;
577         StructConst *structConst;
578     };
579 
CreateStructConst(StructType * type)580     StructConstBuilder CreateStructConst(StructType *type)
581     {
582         return StructConstBuilder(*this, type);
583     }
584 
585     class ArrayConstBuilder {
586     public:
ArrayConstBuilder(LMIRBuilder & builder_,ArrayType * type_)587         ArrayConstBuilder(LMIRBuilder &builder_, ArrayType *type_) : builder(builder_)
588         {
589             arrayConst = &builder.CreateArrayConstInternal(type_);
590         }
591 
Element(Const & element)592         ArrayConstBuilder &Element(Const &element)
593         {
594             builder.AddConstItemInternal(*arrayConst, element);
595             return *this;
596         }
597 
598         template <class T>
Dim(const std::vector<T> init)599         ArrayConstBuilder &Dim(const std::vector<T> init)
600         {
601             for (const auto &value : init) {
602                 // fix the element type.
603                 Const &element = builder.CreateIntConst(builder.i32Type, static_cast<int64_t>(value));
604                 Element(element);
605             }
606             return *this;
607         }
608 
609         template <class T>
Dim(std::initializer_list<T> literal)610         ArrayConstBuilder &Dim(std::initializer_list<T> literal)
611         {
612             return Dim(std::vector<T>(literal));
613         }
614 
Done()615         ArrayConst &Done()
616         {
617             return *arrayConst;
618         }
619 
620     private:
621         LMIRBuilder &builder;
622         ArrayConst *arrayConst;
623     };
624 
CreateArrayConst(ArrayType * type)625     ArrayConstBuilder CreateArrayConst(ArrayType *type)
626     {
627         return ArrayConstBuilder(*this, type);
628     }
629 
630     class FunctionBuilder {
631     public:
FunctionBuilder(LMIRBuilder & builder_,const String & name_,bool needBody_)632         FunctionBuilder(LMIRBuilder &builder_, const String &name_, bool needBody_)
633             : builder(builder_), name(name_), needBody(needBody_)
634         {
635             attr = FUNC_internal;
636             convAttr = CCall;
637             isVargs = false;
638         }
639 
640         // optional: indicate the function has variable args
Vargs()641         FunctionBuilder &Vargs()
642         {
643             isVargs = true;
644             return *this;
645         }
646 
Param(Type * type,const String paramName)647         FunctionBuilder &Param(Type *type, const String paramName)
648         {
649             params.push_back(std::make_pair(paramName, type));
650             return *this;
651         }
652 
653         // optional: if not called, return nothing (return void)
Return(Type * type)654         FunctionBuilder &Return(Type *type)
655         {
656             retType = type;
657             return *this;
658         }
659 
660         // optional: if not called, default to FUNC_local
Attribute(FuncAttr attr_)661         FunctionBuilder &Attribute(FuncAttr attr_)
662         {
663             attr = attr_;
664             return *this;
665         }
666 
667         // optional: if not called, default to Func_CCall
CallConvAttribute(ConvAttr convAttr_)668         FunctionBuilder &CallConvAttribute(ConvAttr convAttr_)
669         {
670             convAttr = convAttr_;
671             return *this;
672         }
673 
Done()674         Function &Done()
675         {
676             return builder.CreateFunctionInternal(name, retType, params, isVargs, needBody, attr, convAttr);
677         }
678 
679     private:
680         LMIRBuilder &builder;
681         const String &name;
682         Type *retType;
683         FuncAttr attr;
684         ConvAttr convAttr;
685         bool isVargs;
686         bool needBody;  // indicate whether is a declaration or definition.
687         Params params;
688     };
689 
690     // only declare the function in current module (means it's an external function)
DeclareFunction(const String & name)691     FunctionBuilder DeclareFunction(const String &name)
692     {
693         return FunctionBuilder(*this, name, false);
694     }
695 
696     // define the function in current module
DefineFunction(const String & name)697     FunctionBuilder DefineFunction(const String &name)
698     {
699         return FunctionBuilder(*this, name, true);
700     }
701 
702 public:
703     // builtin types: primitive types (all MIR primitive types except PTY_ptr)
704     Type *i8Type;
705     Type *i16Type;
706     Type *i32Type;
707     Type *i64Type;
708     Type *i128Type;
709     Type *u1Type;
710     Type *u8Type;
711     Type *u16Type;
712     Type *u32Type;
713     Type *u64Type;
714     Type *u128Type;
715     Type *voidType;
716     Type *f32Type;
717     Type *f64Type;
718 
719     // builtin types: commonly used derived types
720     Type *strType;
721     Type *i64PtrType;
722     Type *i64RefType;
723 
724 private:
725     Stmt &CreateSwitchInternal(Type *type, Expr cond, BB &defaultBB, std::vector<std::pair<int64_t, BB *>> &cases);
726     Type *CreateStructTypeInternal(const String &name, std::vector<std::pair<std::string_view, Type *>> &fields);
727     StructConst &CreateStructConstInternal(StructType *type);
728     void AddConstItemInternal(StructConst &structConst, FieldId fieldId, Const &field);
729     void AddConstItemInternal(ArrayConst &structConst, Const &element);
730     ArrayConst &CreateArrayConstInternal(ArrayType *type);
731     Function &CreateFunctionInternal(const String &name, Type *retType, Params &params, bool isVargs, bool needBody,
732                                      FuncAttr attr, ConvAttr convAttr);
733 
734 private:
735     MIRBuilder &mirBuilder;  // The real IR-builder: current implementation
736     Module &module;          // and the module to process
737 };
738 
739 }  // namespace litecg
740 }  // namespace maple
741 #endif  // MAPLE_LITECG_LMIR_BUILDER_H
742