github.com/llir/llvm@v0.3.6/ir/inst_binary.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  // --- [ Binary instructions ] -------------------------------------------------
    13  
    14  // ~~~ [ add ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    15  
    16  // InstAdd is an LLVM IR add instruction.
    17  type InstAdd struct {
    18  	// Name of local variable associated with the result.
    19  	LocalIdent
    20  	// Operands.
    21  	X, Y value.Value // integer scalar or integer vector
    22  
    23  	// extra.
    24  
    25  	// Type of result produced by the instruction.
    26  	Typ types.Type
    27  	// (optional) Overflow flags.
    28  	OverflowFlags []enum.OverflowFlag
    29  	// (optional) Metadata.
    30  	Metadata
    31  }
    32  
    33  // NewAdd returns a new add instruction based on the given operands.
    34  func NewAdd(x, y value.Value) *InstAdd {
    35  	inst := &InstAdd{X: x, Y: y}
    36  	// Compute type.
    37  	inst.Type()
    38  	return inst
    39  }
    40  
    41  // String returns the LLVM syntax representation of the instruction as a
    42  // type-value pair.
    43  func (inst *InstAdd) String() string {
    44  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
    45  }
    46  
    47  // Type returns the type of the instruction.
    48  func (inst *InstAdd) Type() types.Type {
    49  	// Cache type if not present.
    50  	if inst.Typ == nil {
    51  		inst.Typ = inst.X.Type()
    52  	}
    53  	return inst.Typ
    54  }
    55  
    56  // LLString returns the LLVM syntax representation of the instruction.
    57  //
    58  // 'add' OverflowFlags=OverflowFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
    59  func (inst *InstAdd) LLString() string {
    60  	buf := &strings.Builder{}
    61  	fmt.Fprintf(buf, "%s = ", inst.Ident())
    62  	buf.WriteString("add")
    63  	for _, flag := range inst.OverflowFlags {
    64  		fmt.Fprintf(buf, " %s", flag)
    65  	}
    66  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
    67  	for _, md := range inst.Metadata {
    68  		fmt.Fprintf(buf, ", %s", md)
    69  	}
    70  	return buf.String()
    71  }
    72  
    73  // Operands returns a mutable list of operands of the given instruction.
    74  func (inst *InstAdd) Operands() []*value.Value {
    75  	return []*value.Value{&inst.X, &inst.Y}
    76  }
    77  
    78  // ~~~ [ fadd ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    79  
    80  // InstFAdd is an LLVM IR fadd instruction.
    81  type InstFAdd struct {
    82  	// Name of local variable associated with the result.
    83  	LocalIdent
    84  	// Operands.
    85  	X, Y value.Value // floating-point scalar or floating-point vector
    86  
    87  	// extra.
    88  
    89  	// Type of result produced by the instruction.
    90  	Typ types.Type
    91  	// (optional) Fast math flags.
    92  	FastMathFlags []enum.FastMathFlag
    93  	// (optional) Metadata.
    94  	Metadata
    95  }
    96  
    97  // NewFAdd returns a new fadd instruction based on the given operands.
    98  func NewFAdd(x, y value.Value) *InstFAdd {
    99  	inst := &InstFAdd{X: x, Y: y}
   100  	// Compute type.
   101  	inst.Type()
   102  	return inst
   103  }
   104  
   105  // String returns the LLVM syntax representation of the instruction as a
   106  // type-value pair.
   107  func (inst *InstFAdd) String() string {
   108  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   109  }
   110  
   111  // Type returns the type of the instruction.
   112  func (inst *InstFAdd) Type() types.Type {
   113  	// Cache type if not present.
   114  	if inst.Typ == nil {
   115  		inst.Typ = inst.X.Type()
   116  	}
   117  	return inst.Typ
   118  }
   119  
   120  // LLString returns the LLVM syntax representation of the instruction.
   121  //
   122  // 'fadd' FastMathFlags=FastMathFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   123  func (inst *InstFAdd) LLString() string {
   124  	buf := &strings.Builder{}
   125  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   126  	buf.WriteString("fadd")
   127  	for _, flag := range inst.FastMathFlags {
   128  		fmt.Fprintf(buf, " %s", flag)
   129  	}
   130  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   131  	for _, md := range inst.Metadata {
   132  		fmt.Fprintf(buf, ", %s", md)
   133  	}
   134  	return buf.String()
   135  }
   136  
   137  // Operands returns a mutable list of operands of the given instruction.
   138  func (inst *InstFAdd) Operands() []*value.Value {
   139  	return []*value.Value{&inst.X, &inst.Y}
   140  }
   141  
   142  // ~~~ [ sub ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   143  
   144  // InstSub is an LLVM IR sub instruction.
   145  type InstSub struct {
   146  	// Name of local variable associated with the result.
   147  	LocalIdent
   148  	// Operands.
   149  	X, Y value.Value // integer scalar or integer vector
   150  
   151  	// extra.
   152  
   153  	// Type of result produced by the instruction.
   154  	Typ types.Type
   155  	// (optional) Overflow flags.
   156  	OverflowFlags []enum.OverflowFlag
   157  	// (optional) Metadata.
   158  	Metadata
   159  }
   160  
   161  // NewSub returns a new sub instruction based on the given operands.
   162  func NewSub(x, y value.Value) *InstSub {
   163  	inst := &InstSub{X: x, Y: y}
   164  	// Compute type.
   165  	inst.Type()
   166  	return inst
   167  }
   168  
   169  // String returns the LLVM syntax representation of the instruction as a
   170  // type-value pair.
   171  func (inst *InstSub) String() string {
   172  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   173  }
   174  
   175  // Type returns the type of the instruction.
   176  func (inst *InstSub) Type() types.Type {
   177  	// Cache type if not present.
   178  	if inst.Typ == nil {
   179  		inst.Typ = inst.X.Type()
   180  	}
   181  	return inst.Typ
   182  }
   183  
   184  // LLString returns the LLVM syntax representation of the instruction.
   185  //
   186  // 'sub' OverflowFlags=OverflowFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   187  func (inst *InstSub) LLString() string {
   188  	buf := &strings.Builder{}
   189  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   190  	buf.WriteString("sub")
   191  	for _, flag := range inst.OverflowFlags {
   192  		fmt.Fprintf(buf, " %s", flag)
   193  	}
   194  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   195  	for _, md := range inst.Metadata {
   196  		fmt.Fprintf(buf, ", %s", md)
   197  	}
   198  	return buf.String()
   199  }
   200  
   201  // Operands returns a mutable list of operands of the given instruction.
   202  func (inst *InstSub) Operands() []*value.Value {
   203  	return []*value.Value{&inst.X, &inst.Y}
   204  }
   205  
   206  // ~~~ [ fsub ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   207  
   208  // InstFSub is an LLVM IR fsub instruction.
   209  type InstFSub struct {
   210  	// Name of local variable associated with the result.
   211  	LocalIdent
   212  	// Operands.
   213  	X, Y value.Value // floating-point scalar or floating-point vector
   214  
   215  	// extra.
   216  
   217  	// Type of result produced by the instruction.
   218  	Typ types.Type
   219  	// (optional) Fast math flags.
   220  	FastMathFlags []enum.FastMathFlag
   221  	// (optional) Metadata.
   222  	Metadata
   223  }
   224  
   225  // NewFSub returns a new fsub instruction based on the given operands.
   226  func NewFSub(x, y value.Value) *InstFSub {
   227  	inst := &InstFSub{X: x, Y: y}
   228  	// Compute type.
   229  	inst.Type()
   230  	return inst
   231  }
   232  
   233  // String returns the LLVM syntax representation of the instruction as a
   234  // type-value pair.
   235  func (inst *InstFSub) String() string {
   236  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   237  }
   238  
   239  // Type returns the type of the instruction.
   240  func (inst *InstFSub) Type() types.Type {
   241  	// Cache type if not present.
   242  	if inst.Typ == nil {
   243  		inst.Typ = inst.X.Type()
   244  	}
   245  	return inst.Typ
   246  }
   247  
   248  // LLString returns the LLVM syntax representation of the instruction.
   249  //
   250  // 'fsub' FastMathFlags=FastMathFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   251  func (inst *InstFSub) LLString() string {
   252  	buf := &strings.Builder{}
   253  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   254  	buf.WriteString("fsub")
   255  	for _, flag := range inst.FastMathFlags {
   256  		fmt.Fprintf(buf, " %s", flag)
   257  	}
   258  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   259  	for _, md := range inst.Metadata {
   260  		fmt.Fprintf(buf, ", %s", md)
   261  	}
   262  	return buf.String()
   263  }
   264  
   265  // Operands returns a mutable list of operands of the given instruction.
   266  func (inst *InstFSub) Operands() []*value.Value {
   267  	return []*value.Value{&inst.X, &inst.Y}
   268  }
   269  
   270  // ~~~ [ mul ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   271  
   272  // InstMul is an LLVM IR mul instruction.
   273  type InstMul struct {
   274  	// Name of local variable associated with the result.
   275  	LocalIdent
   276  	// Operands.
   277  	X, Y value.Value // integer scalar or integer vector
   278  
   279  	// extra.
   280  
   281  	// Type of result produced by the instruction.
   282  	Typ types.Type
   283  	// (optional) Overflow flags.
   284  	OverflowFlags []enum.OverflowFlag
   285  	// (optional) Metadata.
   286  	Metadata
   287  }
   288  
   289  // NewMul returns a new mul instruction based on the given operands.
   290  func NewMul(x, y value.Value) *InstMul {
   291  	inst := &InstMul{X: x, Y: y}
   292  	// Compute type.
   293  	inst.Type()
   294  	return inst
   295  }
   296  
   297  // String returns the LLVM syntax representation of the instruction as a
   298  // type-value pair.
   299  func (inst *InstMul) String() string {
   300  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   301  }
   302  
   303  // Type returns the type of the instruction.
   304  func (inst *InstMul) Type() types.Type {
   305  	// Cache type if not present.
   306  	if inst.Typ == nil {
   307  		inst.Typ = inst.X.Type()
   308  	}
   309  	return inst.Typ
   310  }
   311  
   312  // LLString returns the LLVM syntax representation of the instruction.
   313  //
   314  // 'mul' OverflowFlags=OverflowFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   315  func (inst *InstMul) LLString() string {
   316  	buf := &strings.Builder{}
   317  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   318  	buf.WriteString("mul")
   319  	for _, flag := range inst.OverflowFlags {
   320  		fmt.Fprintf(buf, " %s", flag)
   321  	}
   322  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   323  	for _, md := range inst.Metadata {
   324  		fmt.Fprintf(buf, ", %s", md)
   325  	}
   326  	return buf.String()
   327  }
   328  
   329  // Operands returns a mutable list of operands of the given instruction.
   330  func (inst *InstMul) Operands() []*value.Value {
   331  	return []*value.Value{&inst.X, &inst.Y}
   332  }
   333  
   334  // ~~~ [ fmul ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   335  
   336  // InstFMul is an LLVM IR fmul instruction.
   337  type InstFMul struct {
   338  	// Name of local variable associated with the result.
   339  	LocalIdent
   340  	// Operands.
   341  	X, Y value.Value // floating-point scalar or floating-point vector
   342  
   343  	// extra.
   344  
   345  	// Type of result produced by the instruction.
   346  	Typ types.Type
   347  	// (optional) Fast math flags.
   348  	FastMathFlags []enum.FastMathFlag
   349  	// (optional) Metadata.
   350  	Metadata
   351  }
   352  
   353  // NewFMul returns a new fmul instruction based on the given operands.
   354  func NewFMul(x, y value.Value) *InstFMul {
   355  	inst := &InstFMul{X: x, Y: y}
   356  	// Compute type.
   357  	inst.Type()
   358  	return inst
   359  }
   360  
   361  // String returns the LLVM syntax representation of the instruction as a
   362  // type-value pair.
   363  func (inst *InstFMul) String() string {
   364  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   365  }
   366  
   367  // Type returns the type of the instruction.
   368  func (inst *InstFMul) Type() types.Type {
   369  	// Cache type if not present.
   370  	if inst.Typ == nil {
   371  		inst.Typ = inst.X.Type()
   372  	}
   373  	return inst.Typ
   374  }
   375  
   376  // LLString returns the LLVM syntax representation of the instruction.
   377  //
   378  // 'fmul' FastMathFlags=FastMathFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   379  func (inst *InstFMul) LLString() string {
   380  	buf := &strings.Builder{}
   381  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   382  	buf.WriteString("fmul")
   383  	for _, flag := range inst.FastMathFlags {
   384  		fmt.Fprintf(buf, " %s", flag)
   385  	}
   386  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   387  	for _, md := range inst.Metadata {
   388  		fmt.Fprintf(buf, ", %s", md)
   389  	}
   390  	return buf.String()
   391  }
   392  
   393  // Operands returns a mutable list of operands of the given instruction.
   394  func (inst *InstFMul) Operands() []*value.Value {
   395  	return []*value.Value{&inst.X, &inst.Y}
   396  }
   397  
   398  // ~~~ [ udiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   399  
   400  // InstUDiv is an LLVM IR udiv instruction.
   401  type InstUDiv struct {
   402  	// Name of local variable associated with the result.
   403  	LocalIdent
   404  	// Operands.
   405  	X, Y value.Value // integer scalar or integer vector
   406  
   407  	// extra.
   408  
   409  	// Type of result produced by the instruction.
   410  	Typ types.Type
   411  	// (optional) Exact.
   412  	Exact bool
   413  	// (optional) Metadata.
   414  	Metadata
   415  }
   416  
   417  // NewUDiv returns a new udiv instruction based on the given operands.
   418  func NewUDiv(x, y value.Value) *InstUDiv {
   419  	inst := &InstUDiv{X: x, Y: y}
   420  	// Compute type.
   421  	inst.Type()
   422  	return inst
   423  }
   424  
   425  // String returns the LLVM syntax representation of the instruction as a
   426  // type-value pair.
   427  func (inst *InstUDiv) String() string {
   428  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   429  }
   430  
   431  // Type returns the type of the instruction.
   432  func (inst *InstUDiv) Type() types.Type {
   433  	// Cache type if not present.
   434  	if inst.Typ == nil {
   435  		inst.Typ = inst.X.Type()
   436  	}
   437  	return inst.Typ
   438  }
   439  
   440  // LLString returns the LLVM syntax representation of the instruction.
   441  //
   442  // 'udiv' Exactopt X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   443  func (inst *InstUDiv) LLString() string {
   444  	buf := &strings.Builder{}
   445  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   446  	buf.WriteString("udiv")
   447  	if inst.Exact {
   448  		buf.WriteString(" exact")
   449  	}
   450  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   451  	for _, md := range inst.Metadata {
   452  		fmt.Fprintf(buf, ", %s", md)
   453  	}
   454  	return buf.String()
   455  }
   456  
   457  // Operands returns a mutable list of operands of the given instruction.
   458  func (inst *InstUDiv) Operands() []*value.Value {
   459  	return []*value.Value{&inst.X, &inst.Y}
   460  }
   461  
   462  // ~~~ [ sdiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   463  
   464  // InstSDiv is an LLVM IR sdiv instruction.
   465  type InstSDiv struct {
   466  	// Name of local variable associated with the result.
   467  	LocalIdent
   468  	// Operands.
   469  	X, Y value.Value // integer scalar or integer vector
   470  
   471  	// extra.
   472  
   473  	// Type of result produced by the instruction.
   474  	Typ types.Type
   475  	// (optional) Exact.
   476  	Exact bool
   477  	// (optional) Metadata.
   478  	Metadata
   479  }
   480  
   481  // NewSDiv returns a new sdiv instruction based on the given operands.
   482  func NewSDiv(x, y value.Value) *InstSDiv {
   483  	inst := &InstSDiv{X: x, Y: y}
   484  	// Compute type.
   485  	inst.Type()
   486  	return inst
   487  }
   488  
   489  // String returns the LLVM syntax representation of the instruction as a
   490  // type-value pair.
   491  func (inst *InstSDiv) String() string {
   492  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   493  }
   494  
   495  // Type returns the type of the instruction.
   496  func (inst *InstSDiv) Type() types.Type {
   497  	// Cache type if not present.
   498  	if inst.Typ == nil {
   499  		inst.Typ = inst.X.Type()
   500  	}
   501  	return inst.Typ
   502  }
   503  
   504  // LLString returns the LLVM syntax representation of the instruction.
   505  //
   506  // 'sdiv' Exactopt X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   507  func (inst *InstSDiv) LLString() string {
   508  	buf := &strings.Builder{}
   509  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   510  	buf.WriteString("sdiv")
   511  	if inst.Exact {
   512  		buf.WriteString(" exact")
   513  	}
   514  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   515  	for _, md := range inst.Metadata {
   516  		fmt.Fprintf(buf, ", %s", md)
   517  	}
   518  	return buf.String()
   519  }
   520  
   521  // Operands returns a mutable list of operands of the given instruction.
   522  func (inst *InstSDiv) Operands() []*value.Value {
   523  	return []*value.Value{&inst.X, &inst.Y}
   524  }
   525  
   526  // ~~~ [ fdiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   527  
   528  // InstFDiv is an LLVM IR fdiv instruction.
   529  type InstFDiv struct {
   530  	// Name of local variable associated with the result.
   531  	LocalIdent
   532  	// Operands.
   533  	X, Y value.Value // floating-point scalar or floating-point vector
   534  
   535  	// extra.
   536  
   537  	// Type of result produced by the instruction.
   538  	Typ types.Type
   539  	// (optional) Fast math flags.
   540  	FastMathFlags []enum.FastMathFlag
   541  	// (optional) Metadata.
   542  	Metadata
   543  }
   544  
   545  // NewFDiv returns a new fdiv instruction based on the given operands.
   546  func NewFDiv(x, y value.Value) *InstFDiv {
   547  	inst := &InstFDiv{X: x, Y: y}
   548  	// Compute type.
   549  	inst.Type()
   550  	return inst
   551  }
   552  
   553  // String returns the LLVM syntax representation of the instruction as a
   554  // type-value pair.
   555  func (inst *InstFDiv) String() string {
   556  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   557  }
   558  
   559  // Type returns the type of the instruction.
   560  func (inst *InstFDiv) Type() types.Type {
   561  	// Cache type if not present.
   562  	if inst.Typ == nil {
   563  		inst.Typ = inst.X.Type()
   564  	}
   565  	return inst.Typ
   566  }
   567  
   568  // LLString returns the LLVM syntax representation of the instruction.
   569  //
   570  // 'fdiv' FastMathFlags=FastMathFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   571  func (inst *InstFDiv) LLString() string {
   572  	buf := &strings.Builder{}
   573  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   574  	buf.WriteString("fdiv")
   575  	for _, flag := range inst.FastMathFlags {
   576  		fmt.Fprintf(buf, " %s", flag)
   577  	}
   578  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   579  	for _, md := range inst.Metadata {
   580  		fmt.Fprintf(buf, ", %s", md)
   581  	}
   582  	return buf.String()
   583  }
   584  
   585  // Operands returns a mutable list of operands of the given instruction.
   586  func (inst *InstFDiv) Operands() []*value.Value {
   587  	return []*value.Value{&inst.X, &inst.Y}
   588  }
   589  
   590  // ~~~ [ urem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   591  
   592  // InstURem is an LLVM IR urem instruction.
   593  type InstURem struct {
   594  	// Name of local variable associated with the result.
   595  	LocalIdent
   596  	// Operands.
   597  	X, Y value.Value // integer scalar or integer vector
   598  
   599  	// extra.
   600  
   601  	// Type of result produced by the instruction.
   602  	Typ types.Type
   603  	// (optional) Metadata.
   604  	Metadata
   605  }
   606  
   607  // NewURem returns a new urem instruction based on the given operands.
   608  func NewURem(x, y value.Value) *InstURem {
   609  	inst := &InstURem{X: x, Y: y}
   610  	// Compute type.
   611  	inst.Type()
   612  	return inst
   613  }
   614  
   615  // String returns the LLVM syntax representation of the instruction as a
   616  // type-value pair.
   617  func (inst *InstURem) String() string {
   618  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   619  }
   620  
   621  // Type returns the type of the instruction.
   622  func (inst *InstURem) Type() types.Type {
   623  	// Cache type if not present.
   624  	if inst.Typ == nil {
   625  		inst.Typ = inst.X.Type()
   626  	}
   627  	return inst.Typ
   628  }
   629  
   630  // LLString returns the LLVM syntax representation of the instruction.
   631  //
   632  // 'urem' X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   633  func (inst *InstURem) LLString() string {
   634  	buf := &strings.Builder{}
   635  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   636  	fmt.Fprintf(buf, "urem %s, %s", inst.X, inst.Y.Ident())
   637  	for _, md := range inst.Metadata {
   638  		fmt.Fprintf(buf, ", %s", md)
   639  	}
   640  	return buf.String()
   641  }
   642  
   643  // Operands returns a mutable list of operands of the given instruction.
   644  func (inst *InstURem) Operands() []*value.Value {
   645  	return []*value.Value{&inst.X, &inst.Y}
   646  }
   647  
   648  // ~~~ [ srem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   649  
   650  // InstSRem is an LLVM IR srem instruction.
   651  type InstSRem struct {
   652  	// Name of local variable associated with the result.
   653  	LocalIdent
   654  	// Operands.
   655  	X, Y value.Value // integer scalar or integer vector
   656  
   657  	// extra.
   658  
   659  	// Type of result produced by the instruction.
   660  	Typ types.Type
   661  	// (optional) Metadata.
   662  	Metadata
   663  }
   664  
   665  // NewSRem returns a new srem instruction based on the given operands.
   666  func NewSRem(x, y value.Value) *InstSRem {
   667  	inst := &InstSRem{X: x, Y: y}
   668  	// Compute type.
   669  	inst.Type()
   670  	return inst
   671  }
   672  
   673  // String returns the LLVM syntax representation of the instruction as a
   674  // type-value pair.
   675  func (inst *InstSRem) String() string {
   676  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   677  }
   678  
   679  // Type returns the type of the instruction.
   680  func (inst *InstSRem) Type() types.Type {
   681  	// Cache type if not present.
   682  	if inst.Typ == nil {
   683  		inst.Typ = inst.X.Type()
   684  	}
   685  	return inst.Typ
   686  }
   687  
   688  // LLString returns the LLVM syntax representation of the instruction.
   689  //
   690  // 'srem' X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   691  func (inst *InstSRem) LLString() string {
   692  	buf := &strings.Builder{}
   693  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   694  	fmt.Fprintf(buf, "srem %s, %s", inst.X, inst.Y.Ident())
   695  	for _, md := range inst.Metadata {
   696  		fmt.Fprintf(buf, ", %s", md)
   697  	}
   698  	return buf.String()
   699  }
   700  
   701  // Operands returns a mutable list of operands of the given instruction.
   702  func (inst *InstSRem) Operands() []*value.Value {
   703  	return []*value.Value{&inst.X, &inst.Y}
   704  }
   705  
   706  // ~~~ [ frem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   707  
   708  // InstFRem is an LLVM IR frem instruction.
   709  type InstFRem struct {
   710  	// Name of local variable associated with the result.
   711  	LocalIdent
   712  	// Operands.
   713  	X, Y value.Value // floating-point scalar or floating-point vector
   714  
   715  	// extra.
   716  
   717  	// Type of result produced by the instruction.
   718  	Typ types.Type
   719  	// (optional) Fast math flags.
   720  	FastMathFlags []enum.FastMathFlag
   721  	// (optional) Metadata.
   722  	Metadata
   723  }
   724  
   725  // NewFRem returns a new frem instruction based on the given operands.
   726  func NewFRem(x, y value.Value) *InstFRem {
   727  	inst := &InstFRem{X: x, Y: y}
   728  	// Compute type.
   729  	inst.Type()
   730  	return inst
   731  }
   732  
   733  // String returns the LLVM syntax representation of the instruction as a
   734  // type-value pair.
   735  func (inst *InstFRem) String() string {
   736  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   737  }
   738  
   739  // Type returns the type of the instruction.
   740  func (inst *InstFRem) Type() types.Type {
   741  	// Cache type if not present.
   742  	if inst.Typ == nil {
   743  		inst.Typ = inst.X.Type()
   744  	}
   745  	return inst.Typ
   746  }
   747  
   748  // LLString returns the LLVM syntax representation of the instruction.
   749  //
   750  // 'frem' FastMathFlags=FastMathFlag* X=TypeValue ',' Y=Value Metadata=(',' MetadataAttachment)+?
   751  func (inst *InstFRem) LLString() string {
   752  	buf := &strings.Builder{}
   753  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   754  	buf.WriteString("frem")
   755  	for _, flag := range inst.FastMathFlags {
   756  		fmt.Fprintf(buf, " %s", flag)
   757  	}
   758  	fmt.Fprintf(buf, " %s, %s", inst.X, inst.Y.Ident())
   759  	for _, md := range inst.Metadata {
   760  		fmt.Fprintf(buf, ", %s", md)
   761  	}
   762  	return buf.String()
   763  }
   764  
   765  // Operands returns a mutable list of operands of the given instruction.
   766  func (inst *InstFRem) Operands() []*value.Value {
   767  	return []*value.Value{&inst.X, &inst.Y}
   768  }