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

     1  package ir
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/llir/llvm/ir/types"
     8  	"github.com/llir/llvm/ir/value"
     9  )
    10  
    11  // --- [ Vector instructions ] -------------------------------------------------
    12  
    13  // ~~~ [ extractelement ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    14  
    15  // InstExtractElement is an LLVM IR extractelement instruction.
    16  type InstExtractElement struct {
    17  	// Name of local variable associated with the result.
    18  	LocalIdent
    19  	// Vector.
    20  	X value.Value
    21  	// Element index.
    22  	Index value.Value
    23  
    24  	// extra.
    25  
    26  	// Type of result produced by the instruction.
    27  	Typ types.Type
    28  	// (optional) Metadata.
    29  	Metadata
    30  }
    31  
    32  // NewExtractElement returns a new extractelement instruction based on the given
    33  // vector and element index.
    34  func NewExtractElement(x, index value.Value) *InstExtractElement {
    35  	inst := &InstExtractElement{X: x, Index: index}
    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 *InstExtractElement) 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 *InstExtractElement) Type() types.Type {
    49  	// Cache type if not present.
    50  	if inst.Typ == nil {
    51  		t, ok := inst.X.Type().(*types.VectorType)
    52  		if !ok {
    53  			panic(fmt.Errorf("invalid vector type; expected *types.VectorType, got %T", inst.X.Type()))
    54  		}
    55  		inst.Typ = t.ElemType
    56  	}
    57  	return inst.Typ
    58  }
    59  
    60  // LLString returns the LLVM syntax representation of the instruction.
    61  //
    62  // 'extractelement' X=TypeValue ',' Index=TypeValue Metadata=(',' MetadataAttachment)+?
    63  func (inst *InstExtractElement) LLString() string {
    64  	buf := &strings.Builder{}
    65  	fmt.Fprintf(buf, "%s = ", inst.Ident())
    66  	fmt.Fprintf(buf, "extractelement %s, %s", inst.X, inst.Index)
    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 *InstExtractElement) Operands() []*value.Value {
    75  	return []*value.Value{&inst.X, &inst.Index}
    76  }
    77  
    78  // ~~~ [ insertelement ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    79  
    80  // InstInsertElement is an LLVM IR insertelement instruction.
    81  type InstInsertElement struct {
    82  	// Name of local variable associated with the result.
    83  	LocalIdent
    84  	// Vector.
    85  	X value.Value
    86  	// Element to insert.
    87  	Elem value.Value
    88  	// Element index.
    89  	Index value.Value
    90  
    91  	// extra.
    92  
    93  	// Type of result produced by the instruction.
    94  	Typ *types.VectorType
    95  	// (optional) Metadata.
    96  	Metadata
    97  }
    98  
    99  // NewInsertElement returns a new insertelement instruction based on the given
   100  // vector, element and element index.
   101  func NewInsertElement(x, elem, index value.Value) *InstInsertElement {
   102  	inst := &InstInsertElement{X: x, Elem: elem, Index: index}
   103  	// Compute type.
   104  	inst.Type()
   105  	return inst
   106  }
   107  
   108  // String returns the LLVM syntax representation of the instruction as a
   109  // type-value pair.
   110  func (inst *InstInsertElement) String() string {
   111  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   112  }
   113  
   114  // Type returns the type of the instruction.
   115  func (inst *InstInsertElement) Type() types.Type {
   116  	// Cache type if not present.
   117  	if inst.Typ == nil {
   118  		t, ok := inst.X.Type().(*types.VectorType)
   119  		if !ok {
   120  			panic(fmt.Errorf("invalid vector type; expected *types.VectorType, got %T", inst.X.Type()))
   121  		}
   122  		inst.Typ = t
   123  	}
   124  	return inst.Typ
   125  }
   126  
   127  // LLString returns the LLVM syntax representation of the instruction.
   128  //
   129  // 'insertelement' X=TypeValue ',' Elem=TypeValue ',' Index=TypeValue
   130  // Metadata=(',' MetadataAttachment)+?
   131  func (inst *InstInsertElement) LLString() string {
   132  	buf := &strings.Builder{}
   133  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   134  	fmt.Fprintf(buf, "insertelement %s, %s, %s", inst.X, inst.Elem, inst.Index)
   135  	for _, md := range inst.Metadata {
   136  		fmt.Fprintf(buf, ", %s", md)
   137  	}
   138  	return buf.String()
   139  }
   140  
   141  // Operands returns a mutable list of operands of the given instruction.
   142  func (inst *InstInsertElement) Operands() []*value.Value {
   143  	return []*value.Value{&inst.X, &inst.Elem, &inst.Index}
   144  }
   145  
   146  // ~~~ [ shufflevector ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   147  
   148  // InstShuffleVector is an LLVM IR shufflevector instruction.
   149  type InstShuffleVector struct {
   150  	// Name of local variable associated with the result.
   151  	LocalIdent
   152  	// Vectors.
   153  	X, Y value.Value
   154  	// Shuffle mask.
   155  	Mask value.Value
   156  
   157  	// extra.
   158  
   159  	// Type of result produced by the instruction.
   160  	Typ *types.VectorType
   161  	// (optional) Metadata.
   162  	Metadata
   163  }
   164  
   165  // NewShuffleVector returns a new shufflevector instruction based on the given
   166  // vectors and shuffle mask.
   167  func NewShuffleVector(x, y, mask value.Value) *InstShuffleVector {
   168  	inst := &InstShuffleVector{X: x, Y: y, Mask: mask}
   169  	// Compute type.
   170  	inst.Type()
   171  	return inst
   172  }
   173  
   174  // String returns the LLVM syntax representation of the instruction as a
   175  // type-value pair.
   176  func (inst *InstShuffleVector) String() string {
   177  	return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
   178  }
   179  
   180  // Type returns the type of the instruction.
   181  func (inst *InstShuffleVector) Type() types.Type {
   182  	// Cache type if not present.
   183  	if inst.Typ == nil {
   184  		xType, ok := inst.X.Type().(*types.VectorType)
   185  		if !ok {
   186  			panic(fmt.Errorf("invalid vector type; expected *types.VectorType, got %T", inst.X.Type()))
   187  		}
   188  		maskType, ok := inst.Mask.Type().(*types.VectorType)
   189  		if !ok {
   190  			panic(fmt.Errorf("invalid vector type; expected *types.VectorType, got %T", inst.Mask.Type()))
   191  		}
   192  		inst.Typ = types.NewVector(maskType.Len, xType.ElemType)
   193  	}
   194  	return inst.Typ
   195  }
   196  
   197  // LLString returns the LLVM syntax representation of the instruction.
   198  //
   199  // 'shufflevector' X=TypeValue ',' Y=TypeValue ',' Mask=TypeValue
   200  // Metadata=(',' MetadataAttachment)+?
   201  func (inst *InstShuffleVector) LLString() string {
   202  	buf := &strings.Builder{}
   203  	fmt.Fprintf(buf, "%s = ", inst.Ident())
   204  	fmt.Fprintf(buf, "shufflevector %s, %s, %s", inst.X, inst.Y, inst.Mask)
   205  	for _, md := range inst.Metadata {
   206  		fmt.Fprintf(buf, ", %s", md)
   207  	}
   208  	return buf.String()
   209  }
   210  
   211  // Operands returns a mutable list of operands of the given instruction.
   212  func (inst *InstShuffleVector) Operands() []*value.Value {
   213  	return []*value.Value{&inst.X, &inst.Y, &inst.Mask}
   214  }