github.com/llir/llvm@v0.3.6/ir/constant/expr_other.go (about)

     1  package constant
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/llir/llvm/ir/enum"
     7  	"github.com/llir/llvm/ir/types"
     8  )
     9  
    10  // --- [ Other expressions ] ---------------------------------------------------
    11  
    12  // ~~~ [ icmp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    13  
    14  // ExprICmp is an LLVM IR icmp expression.
    15  type ExprICmp struct {
    16  	// Integer comparison predicate.
    17  	Pred enum.IPred
    18  	// Integer scalar or vector operands.
    19  	X, Y Constant
    20  
    21  	// extra.
    22  
    23  	// Type of result produced by the constant expression.
    24  	Typ types.Type
    25  }
    26  
    27  // NewICmp returns a new icmp expression based on the given integer comparison
    28  // predicate and integer scalar or vector operands.
    29  func NewICmp(pred enum.IPred, x, y Constant) *ExprICmp {
    30  	e := &ExprICmp{Pred: pred, X: x, Y: y}
    31  	// Compute type.
    32  	e.Type()
    33  	return e
    34  }
    35  
    36  // String returns the LLVM syntax representation of the constant expression as a
    37  // type-value pair.
    38  func (e *ExprICmp) String() string {
    39  	return fmt.Sprintf("%s %s", e.Type(), e.Ident())
    40  }
    41  
    42  // Type returns the type of the constant expression.
    43  func (e *ExprICmp) Type() types.Type {
    44  	// Cache type if not present.
    45  	if e.Typ == nil {
    46  		switch xType := e.X.Type().(type) {
    47  		case *types.IntType, *types.PointerType:
    48  			e.Typ = types.I1
    49  		case *types.VectorType:
    50  			e.Typ = types.NewVector(xType.Len, types.I1)
    51  		default:
    52  			panic(fmt.Errorf("invalid icmp operand type; expected *types.IntType, *types.PointerType or *types.VectorType, got %T", xType))
    53  		}
    54  	}
    55  	return e.Typ
    56  }
    57  
    58  // Ident returns the identifier associated with the constant expression.
    59  func (e *ExprICmp) Ident() string {
    60  	// 'icmp' Pred=IPred '(' X=TypeConst ',' Y=TypeConst ')'
    61  	return fmt.Sprintf("icmp %s (%s, %s)", e.Pred, e.X, e.Y)
    62  }
    63  
    64  // ~~~ [ fcmp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    65  
    66  // ExprFCmp is an LLVM IR fcmp expression.
    67  type ExprFCmp struct {
    68  	// Floating-point comparison predicate.
    69  	Pred enum.FPred
    70  	// Floating-point scalar or vector operands.
    71  	X, Y Constant
    72  
    73  	// extra.
    74  
    75  	// Type of result produced by the constant expression.
    76  	Typ types.Type
    77  }
    78  
    79  // NewFCmp returns a new fcmp expression based on the given floating-point
    80  // comparison predicate and floating-point scalar or vector operands.
    81  func NewFCmp(pred enum.FPred, x, y Constant) *ExprFCmp {
    82  	e := &ExprFCmp{Pred: pred, X: x, Y: y}
    83  	// Compute type.
    84  	e.Type()
    85  	return e
    86  }
    87  
    88  // String returns the LLVM syntax representation of the constant expression as a
    89  // type-value pair.
    90  func (e *ExprFCmp) String() string {
    91  	return fmt.Sprintf("%s %s", e.Type(), e.Ident())
    92  }
    93  
    94  // Type returns the type of the constant expression.
    95  func (e *ExprFCmp) Type() types.Type {
    96  	// Cache type if not present.
    97  	if e.Typ == nil {
    98  		switch xType := e.X.Type().(type) {
    99  		case *types.FloatType:
   100  			e.Typ = types.I1
   101  		case *types.VectorType:
   102  			e.Typ = types.NewVector(xType.Len, types.I1)
   103  		default:
   104  			panic(fmt.Errorf("invalid fcmp operand type; expected *types.FloatType or *types.VectorType, got %T", xType))
   105  		}
   106  	}
   107  	return e.Typ
   108  }
   109  
   110  // Ident returns the identifier associated with the constant expression.
   111  func (e *ExprFCmp) Ident() string {
   112  	// 'fcmp' Pred=FPred '(' X=TypeConst ',' Y=TypeConst ')'
   113  	return fmt.Sprintf("fcmp %s (%s, %s)", e.Pred, e.X, e.Y)
   114  }
   115  
   116  // ~~~ [ select ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   117  
   118  // ExprSelect is an LLVM IR select expression.
   119  type ExprSelect struct {
   120  	// Selection condition.
   121  	Cond Constant
   122  	// Operands.
   123  	X, Y Constant
   124  
   125  	// extra.
   126  
   127  	// Type of result produced by the constant expression.
   128  	Typ types.Type
   129  }
   130  
   131  // NewSelect returns a new select expression based on the given selection
   132  // condition and operands.
   133  func NewSelect(cond, x, y Constant) *ExprSelect {
   134  	e := &ExprSelect{Cond: cond, X: x, Y: y}
   135  	// Compute type.
   136  	e.Type()
   137  	return e
   138  }
   139  
   140  // String returns the LLVM syntax representation of the constant expression as a
   141  // type-value pair.
   142  func (e *ExprSelect) String() string {
   143  	return fmt.Sprintf("%s %s", e.Type(), e.Ident())
   144  }
   145  
   146  // Type returns the type of the constant expression.
   147  func (e *ExprSelect) Type() types.Type {
   148  	// Cache type if not present.
   149  	if e.Typ == nil {
   150  		e.Typ = e.X.Type()
   151  	}
   152  	return e.Typ
   153  }
   154  
   155  // Ident returns the identifier associated with the constant expression.
   156  func (e *ExprSelect) Ident() string {
   157  	// 'select' '(' Cond=TypeConst ',' X=TypeConst ',' Y=TypeConst ')'
   158  	return fmt.Sprintf("select (%s, %s, %s)", e.Cond, e.X, e.Y)
   159  }