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 }