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 ¶ms, 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