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 <variant> 21 #include <vector> 22 #include <map> 23 #include <string> 24 #include <utility> 25 #include <unordered_map> 26 #include "mpl_logging.h" 27 28 /* 29 LMIR API exported. 30 31 LMIR, the low-level MIR, will serve as the canonical input for LiteCG. 32 33 Currently, it only contains the minimum set of features enough to 34 support eCompiler scenarioes. Later it will grow to be a complete core 35 set, but still with "just enough" features for general cases. 36 37 Additional features, will be defined with x-extension strategy. 38 39 The motivation of LMIR, is to hide the whole complexity of MIR interfaces, 40 and this should make integration of maple components easier. 41 */ 42 namespace maple { 43 44 /* import types for MIR: this is basically a simplification 45 we just need declaration, not headers. 46 */ 47 class MIRBuilder; // currently we just delegate MIRBuilder 48 class MIRModule; 49 class MIRFunction; 50 class MIRType; 51 class MIRStructType; 52 class MIRArrayType; 53 class MIRFuncType; 54 class MIRConst; 55 class MIRAggConst; 56 class MIRSymbol; 57 class StmtNode; 58 class BaseNode; 59 class BlockNode; 60 class MIRPreg; 61 62 namespace litecg { 63 64 // Our type abstraction. currently delegate to MIR 65 66 using String = std::string; 67 68 using Module = MIRModule; 69 using Function = MIRFunction; 70 71 // Note: Type is base class of all other Types 72 using Type = MIRType; // base class of all Types 73 using StructType = MIRStructType; // |__ StructType 74 using ArrayType = MIRArrayType; 75 using Const = MIRConst; 76 using StructConst = MIRAggConst; 77 using ArrayConst = MIRAggConst; 78 using Var = MIRSymbol; 79 using Stmt = StmtNode; 80 using BB = BlockNode; // A temporary faked BB 81 82 using Param = std::pair<const String, Type *>; 83 using Params = std::vector<Param>; 84 using FieldOffset = std::pair<int32_t, int32_t>; // (byteoffset, bitoffset) 85 using PregIdx = int32_t; 86 87 // enumerations 88 enum class MIRIntrinsic { 89 #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) INTRN_##STR, 90 #include "intrinsics.def" 91 #undef DEF_MIR_INTRINSIC 92 }; 93 using IntrinsicId = MIRIntrinsic; 94 /* available intrinsic should be list here. like: 95 INTRN_memcpy, INTRN_memset, etc. 96 */ 97 class Expr { 98 public: Expr(BaseNode * baseNode,Type * nodeType)99 Expr(BaseNode *baseNode, Type *nodeType) : node(baseNode), type(nodeType) {} 100 Expr()101 Expr() : node(nullptr), type(nullptr) {} 102 103 ~Expr() = default; 104 GetNode()105 BaseNode *GetNode() 106 { 107 return node; 108 } 109 GetNode()110 BaseNode *GetNode() const 111 { 112 return node; 113 } 114 GetType()115 Type *GetType() 116 { 117 return type; 118 } 119 GetType()120 Type *GetType() const 121 { 122 return type; 123 } 124 125 bool IsDread() const; 126 bool IsRegread() const; 127 bool IsConstValue() const; 128 129 private: 130 BaseNode *node; 131 Type *type; 132 }; 133 134 enum LiteCGValueKind { 135 kPregKind, 136 kSymbolKind, 137 kConstKind, 138 kGlueAdd, 139 }; 140 141 struct LiteCGValue { 142 LiteCGValueKind kind; 143 std::variant<PregIdx, MIRSymbol*, MIRConst*> data; 144 }; 145 146 using Args = std::vector<Expr>; 147 148 enum FuncAttr { // visibility of the defined function 149 FUNC_global, // function has global visibility 150 FUNC_weak, // weak function defined in this module 151 FUNC_internal, // function defined and only used in this module 152 }; 153 154 enum GlobalRegister { 155 kSregSp = -1, 156 kSregFp = -2, 157 }; 158 159 enum ConvAttr { 160 CCall, 161 Web_Kit_JS_Call, 162 GHC_Call, 163 }; 164 165 enum GlobalVarAttr { 166 VAR_external, // global variable declaration (no definition) 167 VAR_weak, // weak function defined in this module 168 VAR_internal, // variable defined and only used in this module 169 VAR_global, // exported variable defined in this module 170 VAR_readonly, // this is additional flag, default is R/W 171 }; 172 173 enum IntCmpCondition { 174 kEQ, 175 kNE, 176 kULT, 177 kULE, 178 kUGT, 179 kUGE, 180 kSLT, 181 kSLE, 182 kSGT, 183 kSGE, 184 }; 185 186 enum FloatCmpCondition { 187 kOLT, 188 kOLE, 189 kOGT, 190 kOGE, 191 kONE, 192 kOEQ, 193 }; 194 195 enum LiteCGTypeKind { 196 kLiteCGTypeInvalid, 197 kLiteCGTypeUnknown, 198 kLiteCGTypeScalar, 199 kLiteCGTypeBitField, 200 kLiteCGTypeArray, 201 kLiteCGTypeFArray, 202 kLiteCGTypeJArray, 203 kLiteCGTypeStruct, 204 kLiteCGTypeUnion, 205 kLiteCGTypeClass, 206 kLiteCGTypeInterface, 207 kLiteCGTypeStructIncomplete, 208 kLiteCGTypeClassIncomplete, 209 kLiteCGTypeConstString, 210 kLiteCGTypeInterfaceIncomplete, 211 kLiteCGTypePointer, 212 kLiteCGTypeFunction, 213 kLiteCGTypeVoid, 214 kLiteCGTypeByName, 215 kLiteCGTypeParam, 216 kLiteCGTypeInstantVector, 217 kLiteCGTypeGenericInstant, 218 }; 219 220 // FieldAttr: do we need to support volatile here? 221 // using FieldAttr = AttrKind 222 /* used attribute for field: 223 ATTR_volatile 224 */ 225 226 using FieldId = uint32_t; 227 /* Use FieldId from MIR directly: it's a uint32_t, but with special meaning 228 for FieldId == 0: refer to the "whole" of the type 229 To avoid conflict with MIR type define, here using type name "FieldId" 230 */ 231 232 Module *CreateModuleWithName(const std::string &name); 233 void ReleaseModule(Module *module); 234 235 /** 236 * a simplified, specialized MapleIR builder for LiteCG 237 * The basic IR set 238 * 239 * General rule for the interface: 240 * + if function returns value type, then returns type is value type 241 * + otherwise if the return value can be null, return type is pointer 242 * caller should check for null 243 * + otherwise the return type is reference. 244 * 245 * + for compound IR (need to be constructed with a sequence of calls, 246 * e.g., struct type/const, array const, function, switch), using 247 * specific builder class to do the "chained" construction. 248 * 249 */ 250 class LMIRBuilder { 251 public: 252 LMIRBuilder(Module &module); 253 ~LMIRBuilder() = default; 254 255 void DumpIRToFile(const std::string fileName); 256 257 LiteCGTypeKind LiteCGGetTypeKind(Type *type) const; 258 void SetCallStmtDeoptBundleInfo(Stmt &icallNode, const std::unordered_map<int, LiteCGValue> &deoptBundleInfo); 259 260 // Type creation (currently all in global scope) 261 /* 262 For primitive types, using LMIRBuilder's public member: 263 i8Type, u8Type, etc. 264 */ 265 266 // derived type creation 267 Type *CreatePtrType(Type *mirType); 268 Type *CreateRefType(Type *mirType); 269 270 bool IsHeapPointerType(Type *mirType) const; 271 272 // (multi-dim) array of fixed size array 273 ArrayType *CreateArrayType(Type *elemType, std::vector<uint32_t> &dimSize); 274 275 /* using StructTypeBuilder interface for StructType creation 276 auto structType = CreateStructType("mystruct") 277 .Field("field1", i32Type) 278 .Field("field2", i64Type) 279 .Done(); 280 */ 281 Type *GetStructType(const String &name); // query for existing struct type 282 283 // usage of this function has precondition, should be documented 284 FieldOffset GetFieldOffset(StructType *structType, FieldId fieldId); 285 286 // for function pointer 287 Type *CreateFuncType(std::vector<Type *> params, Type *retType, bool isVarg); 288 289 Type *LiteCGGetPointedType(Type *type); 290 291 std::vector<Type *> LiteCGGetFuncParamTypes(Type *type); 292 293 Type *LiteCGGetFuncReturnType(Type *type); 294 // still need interface for AddressOfFunction 295 296 // Function declaration and definition 297 /* using FunctionBuilder interface for Function creation: 298 // i32 myfunc(i32 param1, i64 param2) { } 299 auto structType = DefineFunction("myfunc") 300 .Param(i32Type, "param1") 301 .Param(i64Type, "param2") 302 .Ret(i32Type) // optional for void 303 .Done(); 304 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 CHECK_NULL_FATAL(var); 440 return Dread(*var); 441 } 442 443 Expr DreadWithField(Var &var, FieldId id); 444 Expr IntrinsicOp(IntrinsicId id, Type *type, Args &args_); 445 Expr Iread(Type *type, Expr addr, Type *baseType, FieldId fieldId = 0); 446 PregIdx CreatePreg(Type *mtype); 447 Stmt &Regassign(Expr src, PregIdx reg); 448 Expr Regread(PregIdx pregIdx); 449 Expr Addrof(Var &var); // do we need other forms? 450 Expr ConstVal(Const &constVal); // a const operand 451 452 Expr Lnot(Type *type, Expr src); 453 Expr Bnot(Type *type, Expr src); 454 Expr Sqrt(Type *type, Expr src); 455 Expr Ceil(Type *type, Expr src); 456 Expr Abs(Type *type, Expr src); 457 458 Expr Add(Type *type, Expr src1, Expr src2); 459 Expr Sub(Type *type, Expr src1, Expr src2); 460 Expr Mul(Type *type, Expr src1, Expr src2); 461 Expr UDiv(Type *type, Expr src1, Expr src2); // unsigned 462 Expr SDiv(Type *type, Expr src1, Expr src2); // signed 463 Expr URem(Type *type, Expr src1, Expr src2); // unsigned 464 Expr SRem(Type *type, Expr src1, Expr src2); // signed 465 Expr Shl(Type *type, Expr src1, Expr src2); 466 Expr LShr(Type *type, Expr src1, Expr src2); 467 Expr AShr(Type *type, Expr src1, Expr src2); 468 Expr And(Type *type, Expr src1, Expr src2); 469 Expr Or(Type *type, Expr src1, Expr src2); 470 Expr Xor(Type *type, Expr src1, Expr src2); 471 Expr Max(Type *type, Expr src1, Expr src2); 472 Expr Min(Type *type, Expr src1, Expr src2); 473 474 Expr ICmpEQ(Type *type, Expr src1, Expr src2); 475 Expr ICmpNE(Type *type, Expr src1, Expr src2); 476 // unsigned compare 477 Expr ICmpULT(Type *type, Expr src1, Expr src2); 478 Expr ICmpULE(Type *type, Expr src1, Expr src2); 479 Expr ICmpUGT(Type *type, Expr src1, Expr src2); 480 Expr ICmpUGE(Type *type, Expr src1, Expr src2); 481 // signed compare 482 Expr ICmpSLT(Type *type, Expr src1, Expr src2); 483 Expr ICmpSLE(Type *type, Expr src1, Expr src2); 484 Expr ICmpSGT(Type *type, Expr src1, Expr src2); 485 Expr ICmpSGE(Type *type, Expr src1, Expr src2); 486 Expr ICmp(Type *type, Expr src1, Expr src2, IntCmpCondition cond); 487 Expr FCmp(Type *type, Expr src1, Expr src2, FloatCmpCondition cond); 488 489 // Type conversion 490 // Type of opnd should be consistent with fromType: no implicient conversion 491 Expr Trunc(Type *fromType, Type *toType, Expr opnd); 492 Expr ZExt(Type *fromType, Type *toType, Expr opnd); 493 Expr SExt(Type *fromType, Type *toType, Expr opnd); 494 Expr BitCast(Type *fromType, Type *toType, Expr opnd); 495 Expr Cvt(Type *fromType, Type *toType, Expr opnd); 496 Expr Floor(Type *fromType, Type *toType, Expr opnd); 497 Expr Ceil(Type *fromType, Type *toType, Expr opnd); 498 499 Expr Select(Type *type, Expr cond, Expr ifTrue, Expr ifFalse); 500 501 void SetFuncFrameResverdSlot(int slot); 502 void SetFuncFramePointer(const String &val); 503 void SetCurrentDebugComment(const std::string& comment); 504 void ClearCurrentDebugComment(); 505 506 public: 507 // helper classes for compound IR entity building 508 class SwitchBuilder { 509 public: SwitchBuilder(LMIRBuilder & builder_,Type * type_,Expr cond_,BB & defaultBB_)510 SwitchBuilder(LMIRBuilder &builder_, Type *type_, Expr cond_, BB &defaultBB_) 511 : builder(builder_), type(type_), cond(cond_), defaultBB(defaultBB_) 512 { 513 } 514 Case(int64_t value,BB & bb)515 SwitchBuilder &Case(int64_t value, BB &bb) 516 { 517 cases.push_back(std::make_pair(value, &bb)); 518 return *this; 519 } 520 Done()521 Stmt &Done() 522 { 523 return builder.CreateSwitchInternal(type, cond, defaultBB, cases); 524 } 525 526 private: 527 LMIRBuilder &builder; 528 Type *type; 529 Expr cond; 530 BB &defaultBB; 531 std::vector<std::pair<int64_t, BB *>> cases; 532 }; 533 Switch(Type * type,Expr cond,BB & defaultBB)534 SwitchBuilder Switch(Type *type, Expr cond, BB &defaultBB) 535 { 536 return SwitchBuilder(*this, type, cond, defaultBB); 537 } 538 539 class StructTypeBuilder { 540 public: StructTypeBuilder(LMIRBuilder & builder_,const String & name_)541 StructTypeBuilder(LMIRBuilder &builder_, const String &name_) : builder(builder_), name(name_) {} 542 Field(std::string_view fieldName,Type * fieldType)543 StructTypeBuilder &Field(std::string_view fieldName, Type *fieldType) 544 { 545 // field type attribute? 546 fields.push_back(std::make_pair(fieldName, fieldType)); 547 return *this; 548 } 549 Done()550 Type *Done() 551 { 552 return builder.CreateStructTypeInternal(name, fields); 553 } 554 555 private: 556 LMIRBuilder &builder; 557 const String &name; 558 std::vector<std::pair<std::string_view, Type *>> fields; 559 }; 560 CreateStructType(const String & name)561 StructTypeBuilder CreateStructType(const String &name) 562 { 563 return StructTypeBuilder(*this, name); 564 } 565 566 class StructConstBuilder { 567 public: StructConstBuilder(LMIRBuilder & builder_,StructType * type_)568 StructConstBuilder(LMIRBuilder &builder_, StructType *type_) : builder(builder_) 569 { 570 structConst = &builder_.CreateStructConstInternal(type_); 571 } 572 Field(FieldId fieldId,Const & field)573 StructConstBuilder &Field(FieldId fieldId, Const &field) 574 { 575 builder.AddConstItemInternal(*structConst, fieldId, field); 576 return *this; 577 } 578 Done()579 StructConst &Done() 580 { 581 return *structConst; 582 } 583 584 private: 585 LMIRBuilder &builder; 586 StructConst *structConst; 587 }; 588 CreateStructConst(StructType * type)589 StructConstBuilder CreateStructConst(StructType *type) 590 { 591 return StructConstBuilder(*this, type); 592 } 593 594 class ArrayConstBuilder { 595 public: ArrayConstBuilder(LMIRBuilder & builder_,ArrayType * type_)596 ArrayConstBuilder(LMIRBuilder &builder_, ArrayType *type_) : builder(builder_) 597 { 598 arrayConst = &builder.CreateArrayConstInternal(type_); 599 } 600 Element(Const & element)601 ArrayConstBuilder &Element(Const &element) 602 { 603 builder.AddConstItemInternal(*arrayConst, element); 604 return *this; 605 } 606 607 template <class T> Dim(const std::vector<T> init)608 ArrayConstBuilder &Dim(const std::vector<T> init) 609 { 610 for (const auto &value : init) { 611 // fix the element type. 612 Const &element = builder.CreateIntConst(builder.i32Type, static_cast<int64_t>(value)); 613 Element(element); 614 } 615 return *this; 616 } 617 618 template <class T> Dim(std::initializer_list<T> literal)619 ArrayConstBuilder &Dim(std::initializer_list<T> literal) 620 { 621 return Dim(std::vector<T>(literal)); 622 } 623 Done()624 ArrayConst &Done() 625 { 626 return *arrayConst; 627 } 628 629 private: 630 LMIRBuilder &builder; 631 ArrayConst *arrayConst; 632 }; 633 CreateArrayConst(ArrayType * type)634 ArrayConstBuilder CreateArrayConst(ArrayType *type) 635 { 636 return ArrayConstBuilder(*this, type); 637 } 638 639 class FunctionBuilder { 640 public: FunctionBuilder(LMIRBuilder & builder_,const String & name_,bool needBody_)641 FunctionBuilder(LMIRBuilder &builder_, const String &name_, bool needBody_) 642 : builder(builder_), name(name_), needBody(needBody_) 643 { 644 attr = FUNC_internal; 645 convAttr = CCall; 646 isVargs = false; 647 } 648 649 // optional: indicate the function has variable args Vargs()650 FunctionBuilder &Vargs() 651 { 652 isVargs = true; 653 return *this; 654 } 655 Param(Type * type,const String paramName)656 FunctionBuilder &Param(Type *type, const String paramName) 657 { 658 params.push_back(std::make_pair(paramName, type)); 659 return *this; 660 } 661 662 // optional: if not called, return nothing (return void) Return(Type * type)663 FunctionBuilder &Return(Type *type) 664 { 665 retType = type; 666 return *this; 667 } 668 669 // optional: if not called, default to FUNC_local Attribute(FuncAttr attr_)670 FunctionBuilder &Attribute(FuncAttr attr_) 671 { 672 attr = attr_; 673 return *this; 674 } 675 676 // optional: if not called, default to Func_CCall CallConvAttribute(ConvAttr convAttr_)677 FunctionBuilder &CallConvAttribute(ConvAttr convAttr_) 678 { 679 convAttr = convAttr_; 680 return *this; 681 } 682 Done()683 Function &Done() 684 { 685 return builder.CreateFunctionInternal(name, retType, params, isVargs, needBody, attr, convAttr); 686 } 687 688 private: 689 LMIRBuilder &builder; 690 const String &name; 691 Type *retType; 692 FuncAttr attr; 693 ConvAttr convAttr; 694 bool isVargs; 695 bool needBody; // indicate whether is a declaration or definition. 696 Params params; 697 }; 698 699 // only declare the function in current module (means it's an external function) DeclareFunction(const String & name)700 FunctionBuilder DeclareFunction(const String &name) 701 { 702 return FunctionBuilder(*this, name, false); 703 } 704 705 // define the function in current module DefineFunction(const String & name)706 FunctionBuilder DefineFunction(const String &name) 707 { 708 return FunctionBuilder(*this, name, true); 709 } 710 711 public: 712 // builtin types: primitive types (all MIR primitive types except PTY_ptr) 713 Type *i8Type; 714 Type *i16Type; 715 Type *i32Type; 716 Type *i64Type; 717 Type *i128Type; 718 Type *u1Type; 719 Type *u8Type; 720 Type *u16Type; 721 Type *u32Type; 722 Type *u64Type; 723 Type *u128Type; 724 Type *voidType; 725 Type *f32Type; 726 Type *f64Type; 727 728 // builtin types: commonly used derived types 729 Type *strType; 730 Type *i64PtrType; 731 Type *i64RefType; 732 Type *i64RefRefType; 733 734 private: 735 Stmt &CreateSwitchInternal(Type *type, Expr cond, BB &defaultBB, std::vector<std::pair<int64_t, BB *>> &cases); 736 Type *CreateStructTypeInternal(const String &name, std::vector<std::pair<std::string_view, Type *>> &fields); 737 StructConst &CreateStructConstInternal(StructType *type); 738 void AddConstItemInternal(StructConst &structConst, FieldId fieldId, Const &field); 739 void AddConstItemInternal(ArrayConst &structConst, Const &element); 740 ArrayConst &CreateArrayConstInternal(ArrayType *type); 741 Function &CreateFunctionInternal(const String &name, Type *retType, Params ¶ms, bool isVargs, bool needBody, 742 FuncAttr attr, ConvAttr convAttr); 743 744 private: 745 MIRBuilder &mirBuilder; // The real IR-builder: current implementation 746 Module &module; // and the module to process 747 }; 748 749 } // namespace litecg 750 } // namespace maple 751 #endif // MAPLE_LITECG_LMIR_BUILDER_H 752