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

     1  package constant
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/llir/llvm/ir/types"
     8  )
     9  
    10  // --- [ Struct constants ] ----------------------------------------------------
    11  
    12  // Struct is an LLVM IR struct constant.
    13  type Struct struct {
    14  	// Struct type.
    15  	Typ *types.StructType
    16  	// Struct fields.
    17  	Fields []Constant
    18  }
    19  
    20  // NewStruct returns a new struct constant based on the given struct type and
    21  // fields. The struct type is infered from the type of the fields if t is nil.
    22  func NewStruct(t *types.StructType, fields ...Constant) *Struct {
    23  	c := &Struct{
    24  		Fields: fields,
    25  		Typ:    t,
    26  	}
    27  	// Compute type.
    28  	c.Type()
    29  	return c
    30  }
    31  
    32  // String returns the LLVM syntax representation of the constant as a type-value
    33  // pair.
    34  func (c *Struct) String() string {
    35  	return fmt.Sprintf("%s %s", c.Type(), c.Ident())
    36  }
    37  
    38  // Type returns the type of the constant.
    39  func (c *Struct) Type() types.Type {
    40  	// Cache type if not present.
    41  	if c.Typ == nil {
    42  		var fieldTypes []types.Type
    43  		for _, field := range c.Fields {
    44  			fieldTypes = append(fieldTypes, field.Type())
    45  		}
    46  		c.Typ = types.NewStruct(fieldTypes...)
    47  	}
    48  	return c.Typ
    49  }
    50  
    51  // Ident returns the identifier associated with the constant.
    52  func (c *Struct) Ident() string {
    53  	// Struct constant.
    54  	//
    55  	//    '{' Fields=(TypeConst separator ',')+? '}'
    56  	//
    57  	// Packed struct constant.
    58  	//
    59  	//    '<' '{' Fields=(TypeConst separator ',')+? '}' '>'
    60  	if len(c.Fields) == 0 {
    61  		if c.Typ.Packed {
    62  			return "<{}>"
    63  		}
    64  		return "{}"
    65  	}
    66  	buf := &strings.Builder{}
    67  	if c.Typ.Packed {
    68  		buf.WriteString("<")
    69  	}
    70  	buf.WriteString("{ ")
    71  	for i, field := range c.Fields {
    72  		if i != 0 {
    73  			buf.WriteString(", ")
    74  		}
    75  		buf.WriteString(field.String())
    76  	}
    77  	buf.WriteString(" }")
    78  	if c.Typ.Packed {
    79  		buf.WriteString(">")
    80  	}
    81  	return buf.String()
    82  }