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

     1  // Package metadata provides access to LLVM IR metadata.
     2  package metadata
     3  
     4  import (
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/llir/llvm/internal/enc"
    10  	"github.com/llir/llvm/ir/types"
    11  	"github.com/llir/llvm/ir/value"
    12  )
    13  
    14  // TODO: remove Null if possible.
    15  
    16  // Convenience literals.
    17  var (
    18  	// Null metadata literal.
    19  	Null = &NullLit{}
    20  )
    21  
    22  // ~~~ [ Named metadata definition ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    23  
    24  // NamedDef is a named metadata definition.
    25  type NamedDef struct {
    26  	// Metadata definition name (without '!' prefix).
    27  	Name string
    28  	// Metadata definition nodes.
    29  	Nodes []Node
    30  }
    31  
    32  // Ident returns the identifier associated with the named metadata definition.
    33  func (md *NamedDef) Ident() string {
    34  	return enc.MetadataName(md.Name)
    35  }
    36  
    37  // LLString returns the LLVM syntax representation of the named metadata
    38  // definition.
    39  //
    40  // Name=MetadataName '=' '!' '{' MDNodes=(MetadataNode separator ',')* '}'
    41  func (md *NamedDef) LLString() string {
    42  	buf := &strings.Builder{}
    43  	buf.WriteString("!{")
    44  	for i, node := range md.Nodes {
    45  		if i != 0 {
    46  			buf.WriteString(", ")
    47  		}
    48  		buf.WriteString(node.Ident())
    49  	}
    50  	buf.WriteString("}")
    51  	return buf.String()
    52  }
    53  
    54  // === [ Metadata nodes and metadata strings ] =================================
    55  
    56  // --- [ Metadata tuple ] ------------------------------------------------------
    57  
    58  // Tuple is a metadata node tuple.
    59  type Tuple struct {
    60  	// Metadata ID associated with the metadata tuple; -1 if not present.
    61  	MetadataID
    62  	// (optional) Distinct.
    63  	Distinct bool
    64  
    65  	// Metadata tuple fields.
    66  	Fields []Field
    67  }
    68  
    69  // String returns the LLVM syntax representation of the metadata tuple.
    70  func (md *Tuple) String() string {
    71  	return md.Ident()
    72  }
    73  
    74  // Ident returns the identifier associated with the metadata tuple.
    75  func (md *Tuple) Ident() string {
    76  	if md == nil {
    77  		return "null"
    78  	}
    79  	if md.MetadataID != -1 {
    80  		return md.MetadataID.Ident()
    81  	}
    82  	return md.LLString()
    83  }
    84  
    85  // LLString returns the LLVM syntax representation of the metadata tuple.
    86  //
    87  // '!' MDFields
    88  func (md *Tuple) LLString() string {
    89  	buf := &strings.Builder{}
    90  	if md.Distinct {
    91  		buf.WriteString("distinct ")
    92  	}
    93  	buf.WriteString("!{")
    94  	for i, field := range md.Fields {
    95  		if i != 0 {
    96  			buf.WriteString(", ")
    97  		}
    98  		buf.WriteString(field.String())
    99  	}
   100  	buf.WriteString("}")
   101  	return buf.String()
   102  }
   103  
   104  // SetDistinct specifies whether the metadata definition is dinstict.
   105  func (md *Tuple) SetDistinct(distinct bool) {
   106  	md.Distinct = distinct
   107  }
   108  
   109  // --- [ Metadata value ] ------------------------------------------------------
   110  
   111  // A Value is a metadata value.
   112  type Value struct {
   113  	// Metadata value.
   114  	Value Metadata
   115  }
   116  
   117  // String returns the LLVM syntax representation of the metadata value as a
   118  // type-value pair.
   119  func (md *Value) String() string {
   120  	return fmt.Sprintf("%s %s", md.Type(), md.Ident())
   121  }
   122  
   123  // Type returns the type of the metadata value.
   124  func (md *Value) Type() types.Type {
   125  	return types.Metadata
   126  }
   127  
   128  // Ident returns the identifier associated with the metadata value.
   129  func (md *Value) Ident() string {
   130  	return md.Value.String()
   131  }
   132  
   133  // --- [ Metadata string ] -----------------------------------------------------
   134  
   135  // String is a metadata string.
   136  type String struct {
   137  	// Metadata string value.
   138  	Value string
   139  }
   140  
   141  // String returns the LLVM syntax representation of the metadata string.
   142  func (md *String) String() string {
   143  	// '!' Val=StringLit
   144  	return fmt.Sprintf("!%s", quote(md.Value))
   145  }
   146  
   147  // --- [ Metadata attachment ] -------------------------------------------------
   148  
   149  // Attachment is a metadata attachment.
   150  type Attachment struct {
   151  	// Metadata attachment name (without '!' prefix); e.g. !dbg.
   152  	Name string
   153  	// Metadata attachment node.
   154  	Node MDNode
   155  }
   156  
   157  // String returns the string representation of the metadata attachment.
   158  func (m *Attachment) String() string {
   159  	// Name=MetadataName MDNode
   160  	return fmt.Sprintf("%s %s", enc.MetadataName(m.Name), m.Node.Ident())
   161  }
   162  
   163  // --- [ Integer literals ] -----------------------------------------------------
   164  
   165  // IntLit is an integer literal.
   166  type IntLit int64
   167  
   168  // String returns the LLVM syntax representation of the integer literal.
   169  func (i IntLit) String() string {
   170  	return strconv.FormatInt(int64(i), 10)
   171  }
   172  
   173  // UintLit is an unsigned integer literal.
   174  type UintLit uint64
   175  
   176  // String returns the LLVM syntax representation of the unsigned integer literal.
   177  func (i UintLit) String() string {
   178  	return strconv.FormatUint(uint64(i), 10)
   179  }
   180  
   181  // --- [ Null literal ] --------------------------------------------------------
   182  
   183  // TODO: remove NullLit if possible.
   184  
   185  // NullLit is a metadata null literal.
   186  type NullLit struct{}
   187  
   188  // String returns the LLVM syntax representation of the null literal.
   189  func (i *NullLit) String() string {
   190  	return "null"
   191  }
   192  
   193  // --- [ Metadata identifiers ] ------------------------------------------------
   194  
   195  // ~~~ [ Metadata ID ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   196  
   197  // MetadataID is a metadata ID, as used by metadata definitions.
   198  type MetadataID int64
   199  
   200  // Ident returns the identifier associated with the metadata ID.
   201  func (i MetadataID) Ident() string {
   202  	return enc.MetadataID(int64(i))
   203  }
   204  
   205  // ID returns the ID of the metadata ID.
   206  func (i MetadataID) ID() int64 {
   207  	return int64(i)
   208  }
   209  
   210  // SetID sets the ID of the metadata ID.
   211  func (i *MetadataID) SetID(id int64) {
   212  	*i = MetadataID(id)
   213  }
   214  
   215  // --- [ DIArgList ] -----------------------------------------------------------
   216  
   217  // DIArgList is a metadata node containing a list of function local values.
   218  type DIArgList struct {
   219  	Fields []value.Value
   220  }
   221  
   222  // String returns the LLVM syntax representation of the DIArgList metadata
   223  // node.
   224  func (md *DIArgList) String() string {
   225  	return md.LLString()
   226  }
   227  
   228  // LLString returns the LLVM syntax representation of the DIArgList metadata
   229  // node.
   230  //
   231  // '!DIArgList' '(' Fields=(DIArgListField separator ',')* ')'
   232  func (md *DIArgList) LLString() string {
   233  	buf := &strings.Builder{}
   234  	buf.WriteString("!DIArgList(")
   235  	for i, field := range md.Fields {
   236  		if i != 0 {
   237  			buf.WriteString(", ")
   238  		}
   239  		buf.WriteString(field.String())
   240  	}
   241  	buf.WriteString(")")
   242  	return buf.String()
   243  }