github.com/llir/llvm@v0.3.6/ir/inst_other.go (about) 1 package ir 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/llir/llvm/ir/enum" 8 "github.com/llir/llvm/ir/types" 9 "github.com/llir/llvm/ir/value" 10 ) 11 12 // --- [ Other instructions ] -------------------------------------------------- 13 14 // ~~~ [ icmp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 16 // InstICmp is an LLVM IR icmp instruction. 17 type InstICmp struct { 18 // Name of local variable associated with the result. 19 LocalIdent 20 // Integer comparison predicate. 21 Pred enum.IPred 22 // Integer scalar or vector operands. 23 X, Y value.Value // integer scalar, pointer, integer vector or pointer vector. 24 25 // extra. 26 27 // Type of result produced by the instruction. 28 Typ types.Type // boolean or boolean vector 29 // (optional) Metadata. 30 Metadata 31 } 32 33 // NewICmp returns a new icmp instruction based on the given integer comparison 34 // predicate and integer scalar or vector operands. 35 func NewICmp(pred enum.IPred, x, y value.Value) *InstICmp { 36 inst := &InstICmp{Pred: pred, X: x, Y: y} 37 // Compute type. 38 inst.Type() 39 return inst 40 } 41 42 // String returns the LLVM syntax representation of the instruction as a 43 // type-value pair. 44 func (inst *InstICmp) String() string { 45 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 46 } 47 48 // Type returns the type of the instruction. The result type is either boolean 49 // type or vector of booleans type. 50 func (inst *InstICmp) Type() types.Type { 51 // Cache type if not present. 52 if inst.Typ == nil { 53 switch xType := inst.X.Type().(type) { 54 case *types.IntType, *types.PointerType: 55 inst.Typ = types.I1 56 case *types.VectorType: 57 inst.Typ = types.NewVector(xType.Len, types.I1) 58 default: 59 panic(fmt.Errorf("invalid icmp operand type; expected *types.IntType, *types.PointerType or *types.VectorType, got %T", xType)) 60 } 61 } 62 return inst.Typ 63 } 64 65 // LLString returns the LLVM syntax representation of the instruction. 66 // 67 // 'icmp' Pred=IPred X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+? 68 func (inst *InstICmp) LLString() string { 69 buf := &strings.Builder{} 70 fmt.Fprintf(buf, "%s = ", inst.Ident()) 71 fmt.Fprintf(buf, "icmp %s %s, %s", inst.Pred, inst.X, inst.Y.Ident()) 72 for _, md := range inst.Metadata { 73 fmt.Fprintf(buf, ", %s", md) 74 } 75 return buf.String() 76 } 77 78 // Operands returns a mutable list of operands of the given instruction. 79 func (inst *InstICmp) Operands() []*value.Value { 80 return []*value.Value{&inst.X, &inst.Y} 81 } 82 83 // ~~~ [ fcmp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 85 // InstFCmp is an LLVM IR fcmp instruction. 86 type InstFCmp struct { 87 // Name of local variable associated with the result. 88 LocalIdent 89 // Floating-point comparison predicate. 90 Pred enum.FPred 91 // Floating-point scalar or vector operands. 92 X, Y value.Value // floating-point scalar or floating-point vector 93 94 // extra. 95 96 // Type of result produced by the instruction. 97 Typ types.Type // boolean or boolean vector 98 // (optional) Fast math flags. 99 FastMathFlags []enum.FastMathFlag 100 // (optional) Metadata. 101 Metadata 102 } 103 104 // NewFCmp returns a new fcmp instruction based on the given floating-point 105 // comparison predicate and floating-point scalar or vector operands. 106 func NewFCmp(pred enum.FPred, x, y value.Value) *InstFCmp { 107 inst := &InstFCmp{Pred: pred, X: x, Y: y} 108 // Compute type. 109 inst.Type() 110 return inst 111 } 112 113 // String returns the LLVM syntax representation of the instruction as a 114 // type-value pair. 115 func (inst *InstFCmp) String() string { 116 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 117 } 118 119 // Type returns the type of the instruction. The result type is either boolean 120 // type or vector of booleans type. 121 func (inst *InstFCmp) Type() types.Type { 122 // Cache type if not present. 123 if inst.Typ == nil { 124 switch xType := inst.X.Type().(type) { 125 case *types.FloatType: 126 inst.Typ = types.I1 127 case *types.VectorType: 128 inst.Typ = types.NewVector(xType.Len, types.I1) 129 default: 130 panic(fmt.Errorf("invalid fcmp operand type; expected *types.FloatType or *types.VectorType, got %T", xType)) 131 } 132 } 133 return inst.Typ 134 } 135 136 // LLString returns the LLVM syntax representation of the instruction. 137 // 138 // 'fcmp' FastMathFlags=FastMathFlag* Pred=FPred X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+? 139 func (inst *InstFCmp) LLString() string { 140 buf := &strings.Builder{} 141 fmt.Fprintf(buf, "%s = ", inst.Ident()) 142 buf.WriteString("fcmp") 143 for _, flag := range inst.FastMathFlags { 144 fmt.Fprintf(buf, " %s", flag) 145 } 146 fmt.Fprintf(buf, " %s %s, %s", inst.Pred, inst.X, inst.Y.Ident()) 147 for _, md := range inst.Metadata { 148 fmt.Fprintf(buf, ", %s", md) 149 } 150 return buf.String() 151 } 152 153 // Operands returns a mutable list of operands of the given instruction. 154 func (inst *InstFCmp) Operands() []*value.Value { 155 return []*value.Value{&inst.X, &inst.Y} 156 } 157 158 // ~~~ [ phi ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159 160 // InstPhi is an LLVM IR phi instruction. 161 type InstPhi struct { 162 // Name of local variable associated with the result. 163 LocalIdent 164 // Incoming values. 165 Incs []*Incoming 166 167 // extra. 168 169 // Type of result produced by the instruction. 170 Typ types.Type // type of incoming value 171 // (optional) Fast math flags. 172 FastMathFlags []enum.FastMathFlag 173 // (optional) Metadata. 174 Metadata 175 } 176 177 // NewPhi returns a new phi instruction based on the given incoming values. 178 func NewPhi(incs ...*Incoming) *InstPhi { 179 inst := &InstPhi{Incs: incs} 180 // Compute type. 181 inst.Type() 182 return inst 183 } 184 185 // String returns the LLVM syntax representation of the instruction as a 186 // type-value pair. 187 func (inst *InstPhi) String() string { 188 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 189 } 190 191 // Type returns the type of the instruction. The result type is the type of the 192 // incoming value. 193 func (inst *InstPhi) Type() types.Type { 194 // Cache type if not present. 195 if inst.Typ == nil { 196 inst.Typ = inst.Incs[0].X.Type() 197 } 198 return inst.Typ 199 } 200 201 // LLString returns the LLVM syntax representation of the instruction. 202 // 203 // 'phi' Typ=Type Incs=(Inc separator ',')+ Metadata=(',' MetadataAttachment)+? 204 func (inst *InstPhi) LLString() string { 205 buf := &strings.Builder{} 206 fmt.Fprintf(buf, "%s = ", inst.Ident()) 207 buf.WriteString("phi ") 208 for _, flag := range inst.FastMathFlags { 209 buf.WriteString(flag.String()) 210 buf.WriteString(" ") 211 } 212 buf.WriteString(inst.Typ.String()) 213 buf.WriteString(" ") 214 for i, inc := range inst.Incs { 215 if i != 0 { 216 buf.WriteString(", ") 217 } 218 buf.WriteString(inc.String()) 219 } 220 for _, md := range inst.Metadata { 221 fmt.Fprintf(buf, ", %s", md) 222 } 223 return buf.String() 224 } 225 226 // Operands returns a mutable list of operands of the given instruction. 227 func (inst *InstPhi) Operands() []*value.Value { 228 ops := make([]*value.Value, 0, 2*len(inst.Incs)) 229 for i := range inst.Incs { 230 ops = append(ops, &inst.Incs[i].X) 231 ops = append(ops, &inst.Incs[i].Pred) 232 } 233 return ops 234 } 235 236 // ___ [ Incoming value ] ______________________________________________________ 237 238 // Incoming is an incoming value of a phi instruction. 239 type Incoming struct { 240 // Incoming value. 241 X value.Value 242 // Predecessor basic block of the incoming value. 243 Pred value.Value // *ir.Block 244 } 245 246 // NewIncoming returns a new incoming value based on the given value and 247 // predecessor basic block. 248 func NewIncoming(x value.Value, pred *Block) *Incoming { 249 return &Incoming{X: x, Pred: pred} 250 } 251 252 // String returns the string representation of the incoming value. 253 func (inc *Incoming) String() string { 254 // '[' X=Value ',' Pred=LocalIdent ']' 255 return fmt.Sprintf("[ %s, %s ]", inc.X.Ident(), inc.Pred.Ident()) 256 } 257 258 // ~~~ [ select ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 259 260 // InstSelect is an LLVM IR select instruction. 261 type InstSelect struct { 262 // Name of local variable associated with the result. 263 LocalIdent 264 // Selection condition. 265 Cond value.Value // boolean or boolean vector 266 // True condition value. 267 ValueTrue value.Value 268 // False condition value. 269 ValueFalse value.Value 270 271 // extra. 272 273 // Type of result produced by the instruction. 274 Typ types.Type 275 // (optional) Fast math flags. 276 FastMathFlags []enum.FastMathFlag 277 // (optional) Metadata. 278 Metadata 279 } 280 281 // NewSelect returns a new select instruction based on the given selection 282 // condition and true and false condition values. 283 func NewSelect(cond, valueTrue, valueFalse value.Value) *InstSelect { 284 inst := &InstSelect{Cond: cond, ValueTrue: valueTrue, ValueFalse: valueFalse} 285 // Compute type. 286 inst.Type() 287 return inst 288 } 289 290 // String returns the LLVM syntax representation of the instruction as a 291 // type-value pair. 292 func (inst *InstSelect) String() string { 293 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 294 } 295 296 // Type returns the type of the instruction. 297 func (inst *InstSelect) Type() types.Type { 298 // Cache type if not present. 299 if inst.Typ == nil { 300 inst.Typ = inst.ValueTrue.Type() 301 } 302 return inst.Typ 303 } 304 305 // LLString returns the LLVM syntax representation of the instruction. 306 // 307 // 'select' FastMathFlags=FastMathFlag* Cond=TypeValue ',' ValueTrue=TypeValue ',' ValueFalse=TypeValue Metadata=(',' MetadataAttachment)+? 308 func (inst *InstSelect) LLString() string { 309 buf := &strings.Builder{} 310 fmt.Fprintf(buf, "%s = ", inst.Ident()) 311 buf.WriteString("select") 312 for _, flag := range inst.FastMathFlags { 313 fmt.Fprintf(buf, " %s", flag) 314 } 315 fmt.Fprintf(buf, " %s, %s, %s", inst.Cond, inst.ValueTrue, inst.ValueFalse) 316 for _, md := range inst.Metadata { 317 fmt.Fprintf(buf, ", %s", md) 318 } 319 return buf.String() 320 } 321 322 // Operands returns a mutable list of operands of the given instruction. 323 func (inst *InstSelect) Operands() []*value.Value { 324 return []*value.Value{&inst.Cond, &inst.ValueTrue, &inst.ValueFalse} 325 } 326 327 // ~~~ [ freeze ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 328 329 // InstFreeze is an LLVM IR freeze instruction. 330 type InstFreeze struct { 331 // Name of local variable associated with the result. 332 LocalIdent 333 // Operand. 334 X value.Value 335 // extra. 336 337 // Type of result produced by the instruction. 338 Typ types.Type 339 // (optional) Metadata. 340 Metadata 341 } 342 343 // NewInstFreeze returns a new freeze instruction based on the given 344 // operand. 345 func NewInstFreeze(x value.Value) *InstFreeze { 346 inst := &InstFreeze{X: x} 347 // Compute type. 348 inst.Type() 349 return inst 350 } 351 352 // String returns the LLVM syntax representation of the instruction as a 353 // type-value pair. 354 func (inst *InstFreeze) String() string { 355 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 356 } 357 358 // Type returns the type of the instruction. 359 func (inst *InstFreeze) Type() types.Type { 360 // Cache type if not present. 361 if inst.Typ == nil { 362 inst.Typ = inst.X.Type() 363 } 364 return inst.Typ 365 } 366 367 // LLString returns the LLVM syntax representation of the instruction. 368 // 369 // 'freeze' Type Value 370 func (inst *InstFreeze) LLString() string { 371 buf := &strings.Builder{} 372 fmt.Fprintf(buf, "%s = ", inst.Ident()) 373 fmt.Fprintf(buf, "freeze %s", inst.X) 374 for _, md := range inst.Metadata { 375 fmt.Fprintf(buf, ", %s", md) 376 } 377 return buf.String() 378 } 379 380 // Operands returns a mutable list of operands of the given instruction. 381 func (inst *InstFreeze) Operands() []*value.Value { 382 return []*value.Value{&inst.X} 383 } 384 385 // ~~~ [ call ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 386 387 // InstCall is an LLVM IR call instruction. 388 type InstCall struct { 389 // Name of local variable associated with the result. 390 LocalIdent 391 // Callee. 392 // TODO: specify the set of underlying types of Callee. 393 Callee value.Value 394 // Function arguments. 395 // 396 // Arg has one of the following underlying types: 397 // value.Value 398 // *ir.Arg 399 // TODO: add metadata value? 400 Args []value.Value 401 402 // extra. 403 404 // Type of result produced by the instruction. 405 Typ types.Type 406 // (optional) Tail; zero if not present. 407 Tail enum.Tail 408 // (optional) Fast math flags. 409 FastMathFlags []enum.FastMathFlag 410 // (optional) Calling convention; zero if not present. 411 CallingConv enum.CallingConv 412 // (optional) Return attributes. 413 ReturnAttrs []ReturnAttribute 414 // (optional) Address space; zero if not present. 415 AddrSpace types.AddrSpace 416 // (optional) Function attributes. 417 FuncAttrs []FuncAttribute 418 // (optional) Operand bundles. 419 OperandBundles []*OperandBundle 420 // (optional) Metadata. 421 Metadata 422 } 423 424 // NewCall returns a new call instruction based on the given callee and function 425 // arguments. 426 // 427 // TODO: specify the set of underlying types of callee. 428 func NewCall(callee value.Value, args ...value.Value) *InstCall { 429 inst := &InstCall{Callee: callee, Args: args} 430 // Compute type. 431 inst.Type() 432 return inst 433 } 434 435 // String returns the LLVM syntax representation of the instruction as a 436 // type-value pair. 437 func (inst *InstCall) String() string { 438 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 439 } 440 441 // Type returns the type of the instruction. 442 func (inst *InstCall) Type() types.Type { 443 // Cache type if not present. 444 if inst.Typ == nil { 445 sig := inst.Sig() 446 inst.Typ = sig.RetType 447 } 448 return inst.Typ 449 } 450 451 // LLString returns the LLVM syntax representation of the instruction. 452 // 453 // Tailopt 'call' FastMathFlags=FastMathFlag* CallingConvopt ReturnAttrs=ReturnAttribute* AddrSpaceopt Typ=Type Callee=Value '(' Args ')' FuncAttrs=FuncAttribute* OperandBundles=('[' (OperandBundle separator ',')+ ']')? Metadata=(',' MetadataAttachment)+? 454 func (inst *InstCall) LLString() string { 455 buf := &strings.Builder{} 456 if !inst.Type().Equal(types.Void) { 457 fmt.Fprintf(buf, "%s = ", inst.Ident()) 458 } 459 if inst.Tail != enum.TailNone { 460 fmt.Fprintf(buf, "%s ", inst.Tail) 461 } 462 buf.WriteString("call") 463 for _, flag := range inst.FastMathFlags { 464 fmt.Fprintf(buf, " %s", flag) 465 } 466 if inst.CallingConv != enum.CallingConvNone { 467 fmt.Fprintf(buf, " %s", callingConvString(inst.CallingConv)) 468 } 469 for _, attr := range inst.ReturnAttrs { 470 fmt.Fprintf(buf, " %s", attr) 471 } 472 // (optional) Address space. 473 if inst.AddrSpace != 0 { 474 fmt.Fprintf(buf, " %s", inst.AddrSpace) 475 } 476 // Use function signature instead of return type for variadic functions. 477 calleeType := inst.Type() 478 if sig := inst.Sig(); sig.Variadic { 479 calleeType = sig 480 } 481 fmt.Fprintf(buf, " %s %s(", calleeType, inst.Callee.Ident()) 482 for i, arg := range inst.Args { 483 if i != 0 { 484 buf.WriteString(", ") 485 } 486 buf.WriteString(arg.String()) 487 } 488 buf.WriteString(")") 489 for _, attr := range inst.FuncAttrs { 490 fmt.Fprintf(buf, " %s", attr) 491 } 492 if len(inst.OperandBundles) > 0 { 493 buf.WriteString(" [ ") 494 for i, operandBundle := range inst.OperandBundles { 495 if i != 0 { 496 buf.WriteString(", ") 497 } 498 buf.WriteString(operandBundle.String()) 499 } 500 buf.WriteString(" ]") 501 } 502 for _, md := range inst.Metadata { 503 fmt.Fprintf(buf, ", %s", md) 504 } 505 return buf.String() 506 } 507 508 // Operands returns a mutable list of operands of the given instruction. 509 func (inst *InstCall) Operands() []*value.Value { 510 ops := make([]*value.Value, 0, 1+len(inst.Args)) 511 ops = append(ops, &inst.Callee) 512 for i := range inst.Args { 513 ops = append(ops, &inst.Args[i]) 514 } 515 return ops 516 } 517 518 // Sig returns the function signature of the callee. 519 func (inst *InstCall) Sig() *types.FuncType { 520 t, ok := inst.Callee.Type().(*types.PointerType) 521 if !ok { 522 panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", inst.Callee.Type())) 523 } 524 sig, ok := t.ElemType.(*types.FuncType) 525 if !ok { 526 panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType)) 527 } 528 return sig 529 } 530 531 // ~~~ [ va_arg ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 532 533 // InstVAArg is an LLVM IR va_arg instruction. 534 type InstVAArg struct { 535 // Name of local variable associated with the result. 536 LocalIdent 537 // Variable argument list. 538 ArgList value.Value 539 // Argument type. 540 ArgType types.Type 541 542 // extra. 543 544 // (optional) Metadata. 545 Metadata 546 } 547 548 // NewVAArg returns a new va_arg instruction based on the given variable 549 // argument list and argument type. 550 func NewVAArg(argList value.Value, argType types.Type) *InstVAArg { 551 return &InstVAArg{ArgList: argList, ArgType: argType} 552 } 553 554 // String returns the LLVM syntax representation of the instruction as a 555 // type-value pair. 556 func (inst *InstVAArg) String() string { 557 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 558 } 559 560 // Type returns the type of the instruction. 561 func (inst *InstVAArg) Type() types.Type { 562 return inst.ArgType 563 } 564 565 // LLString returns the LLVM syntax representation of the instruction. 566 // 567 // 'va_arg' ArgList=TypeValue ',' ArgType=Type Metadata=(',' MetadataAttachment)+? 568 func (inst *InstVAArg) LLString() string { 569 buf := &strings.Builder{} 570 fmt.Fprintf(buf, "%s = ", inst.Ident()) 571 fmt.Fprintf(buf, "va_arg %s, %s", inst.ArgList, inst.ArgType) 572 for _, md := range inst.Metadata { 573 fmt.Fprintf(buf, ", %s", md) 574 } 575 return buf.String() 576 } 577 578 // Operands returns a mutable list of operands of the given instruction. 579 func (inst *InstVAArg) Operands() []*value.Value { 580 return []*value.Value{&inst.ArgList} 581 } 582 583 // ~~~ [ landingpad ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 584 585 // InstLandingPad is an LLVM IR landingpad instruction. 586 type InstLandingPad struct { 587 // Name of local variable associated with the result. 588 LocalIdent 589 // Result type. 590 ResultType types.Type 591 // (optional) Cleanup landing pad. 592 Cleanup bool 593 // Filter and catch clauses; zero or more if Cleanup is true, otherwise one 594 // or more. 595 Clauses []*Clause 596 597 // extra. 598 599 // (optional) Metadata. 600 Metadata 601 } 602 603 // NewLandingPad returns a new landingpad instruction based on the given result 604 // type and filter/catch clauses. 605 func NewLandingPad(resultType types.Type, clauses ...*Clause) *InstLandingPad { 606 return &InstLandingPad{ResultType: resultType, Clauses: clauses} 607 } 608 609 // String returns the LLVM syntax representation of the instruction as a 610 // type-value pair. 611 func (inst *InstLandingPad) String() string { 612 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 613 } 614 615 // Type returns the type of the instruction. 616 func (inst *InstLandingPad) Type() types.Type { 617 return inst.ResultType 618 } 619 620 // LLString returns the LLVM syntax representation of the instruction. 621 // 622 // 'landingpad' ResultType=Type Cleanupopt Clauses=Clause* Metadata=(',' MetadataAttachment)+? 623 func (inst *InstLandingPad) LLString() string { 624 buf := &strings.Builder{} 625 fmt.Fprintf(buf, "%s = ", inst.Ident()) 626 fmt.Fprintf(buf, "landingpad %s", inst.ResultType) 627 if inst.Cleanup { 628 buf.WriteString("\n\t\tcleanup") 629 } 630 for _, clause := range inst.Clauses { 631 fmt.Fprintf(buf, "\n\t\t%s", clause) 632 } 633 for _, md := range inst.Metadata { 634 fmt.Fprintf(buf, ", %s", md) 635 } 636 return buf.String() 637 } 638 639 // Operands returns a mutable list of operands of the given instruction. 640 func (inst *InstLandingPad) Operands() []*value.Value { 641 ops := make([]*value.Value, 0, len(inst.Clauses)) 642 for i := range inst.Clauses { 643 ops = append(ops, &inst.Clauses[i].X) 644 } 645 return ops 646 } 647 648 // ___ [ Landingpad clause ] ___________________________________________________ 649 650 // Clause is a landingpad catch or filter clause. 651 type Clause struct { 652 // Clause type (catch or filter). 653 Type enum.ClauseType 654 // Operand. 655 X value.Value 656 } 657 658 // NewClause returns a new landingpad clause based on the given clause type and 659 // operand. 660 func NewClause(clauseType enum.ClauseType, x value.Value) *Clause { 661 return &Clause{Type: clauseType, X: x} 662 } 663 664 // String returns the string representation of the landingpad clause. 665 func (clause *Clause) String() string { 666 return fmt.Sprintf("%s %s", clause.Type, clause.X) 667 } 668 669 // ~~~ [ catchpad ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 670 671 // InstCatchPad is an LLVM IR catchpad instruction. 672 type InstCatchPad struct { 673 // Name of local variable associated with the result. 674 LocalIdent 675 // Parent catchswitch terminator. 676 CatchSwitch value.Value // *ir.TermCatchSwitch 677 // Exception arguments. 678 // 679 // Arg has one of the following underlying types: 680 // value.Value 681 // TODO: add metadata value? 682 Args []value.Value 683 684 // extra. 685 686 // (optional) Metadata. 687 Metadata 688 } 689 690 // NewCatchPad returns a new catchpad instruction based on the given parent 691 // catchswitch terminator and exception arguments. 692 func NewCatchPad(catchSwitch *TermCatchSwitch, args ...value.Value) *InstCatchPad { 693 return &InstCatchPad{CatchSwitch: catchSwitch, Args: args} 694 } 695 696 // String returns the LLVM syntax representation of the instruction as a 697 // type-value pair. 698 func (inst *InstCatchPad) String() string { 699 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 700 } 701 702 // Type returns the type of the instruction. 703 func (inst *InstCatchPad) Type() types.Type { 704 return types.Token 705 } 706 707 // LLString returns the LLVM syntax representation of the instruction. 708 // 709 // 'catchpad' 'within' CatchSwitch=LocalIdent '[' Args=(ExceptionArg separator ',')* ']' Metadata=(',' MetadataAttachment)+? 710 func (inst *InstCatchPad) LLString() string { 711 buf := &strings.Builder{} 712 fmt.Fprintf(buf, "%s = ", inst.Ident()) 713 fmt.Fprintf(buf, "catchpad within %s [", inst.CatchSwitch.Ident()) 714 for i, arg := range inst.Args { 715 if i != 0 { 716 buf.WriteString(", ") 717 } 718 buf.WriteString(arg.String()) 719 } 720 buf.WriteString("]") 721 for _, md := range inst.Metadata { 722 fmt.Fprintf(buf, ", %s", md) 723 } 724 return buf.String() 725 } 726 727 // Operands returns a mutable list of operands of the given instruction. 728 func (inst *InstCatchPad) Operands() []*value.Value { 729 ops := make([]*value.Value, 0, 1+len(inst.Args)) 730 ops = append(ops, &inst.CatchSwitch) 731 for i := range inst.Args { 732 ops = append(ops, &inst.Args[i]) 733 } 734 return ops 735 } 736 737 // ~~~ [ cleanuppad ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 738 739 // InstCleanupPad is an LLVM IR cleanuppad instruction. 740 type InstCleanupPad struct { 741 // Name of local variable associated with the result. 742 LocalIdent 743 // Parent exception pad. 744 ParentPad value.Value // ir.ExceptionPad 745 // Exception arguments. 746 // 747 // Arg has one of the following underlying types: 748 // value.Value 749 // TODO: add metadata value? 750 Args []value.Value 751 752 // extra. 753 754 // (optional) Metadata. 755 Metadata 756 } 757 758 // NewCleanupPad returns a new cleanuppad instruction based on the given 759 // parent exception pad and exception arguments. 760 func NewCleanupPad(parentPad ExceptionPad, args ...value.Value) *InstCleanupPad { 761 return &InstCleanupPad{ParentPad: parentPad, Args: args} 762 } 763 764 // String returns the LLVM syntax representation of the instruction as a 765 // type-value pair. 766 func (inst *InstCleanupPad) String() string { 767 return fmt.Sprintf("%s %s", inst.Type(), inst.Ident()) 768 } 769 770 // Type returns the type of the instruction. 771 func (inst *InstCleanupPad) Type() types.Type { 772 return types.Token 773 } 774 775 // LLString returns the LLVM syntax representation of the instruction. 776 // 777 // 'cleanuppad' 'within' ParentPad=ExceptionPad '[' Args=(ExceptionArg separator ',')* ']' Metadata=(',' MetadataAttachment)+? 778 func (inst *InstCleanupPad) LLString() string { 779 buf := &strings.Builder{} 780 fmt.Fprintf(buf, "%s = ", inst.Ident()) 781 fmt.Fprintf(buf, "cleanuppad within %s [", inst.ParentPad.Ident()) 782 for i, arg := range inst.Args { 783 if i != 0 { 784 buf.WriteString(", ") 785 } 786 buf.WriteString(arg.String()) 787 } 788 buf.WriteString("]") 789 for _, md := range inst.Metadata { 790 fmt.Fprintf(buf, ", %s", md) 791 } 792 return buf.String() 793 } 794 795 // Operands returns a mutable list of operands of the given instruction. 796 func (inst *InstCleanupPad) Operands() []*value.Value { 797 ops := make([]*value.Value, 0, 1+len(inst.Args)) 798 ops = append(ops, &inst.ParentPad) 799 for i := range inst.Args { 800 ops = append(ops, &inst.Args[i]) 801 } 802 return ops 803 }