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

     1  package ir
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/llir/llvm/ir/constant"
     8  	"github.com/llir/llvm/ir/enum"
     9  	"github.com/llir/llvm/ir/types"
    10  )
    11  
    12  // === [ Global variables ] ====================================================
    13  
    14  // Global is a global variable declaration or definition.
    15  type Global struct {
    16  	// Global variable name (without '@' prefix).
    17  	GlobalIdent
    18  	// Immutability of global variable (constant or global).
    19  	Immutable bool
    20  	// Content type.
    21  	ContentType types.Type
    22  	// Initial value; or nil if declaration.
    23  	Init constant.Constant
    24  
    25  	// extra.
    26  
    27  	// Pointer type to global variable, including an optional address space. If
    28  	// Typ is nil, the first invocation of Type stores a pointer type with
    29  	// ContentType as element.
    30  	Typ *types.PointerType
    31  	// (optional) Linkage; zero value if not present.
    32  	Linkage enum.Linkage
    33  	// (optional) Preemption; zero value if not present.
    34  	Preemption enum.Preemption
    35  	// (optional) Visibility; zero value if not present.
    36  	Visibility enum.Visibility
    37  	// (optional) DLL storage class; zero value if not present.
    38  	DLLStorageClass enum.DLLStorageClass
    39  	// (optional) Thread local storage model; zero value if not present.
    40  	TLSModel enum.TLSModel
    41  	// (optional) Unnamed address; zero value if not present.
    42  	UnnamedAddr enum.UnnamedAddr
    43  	// (optional) Address space; zero if not present.
    44  	AddrSpace types.AddrSpace
    45  	// (optional) Externally initialized; false if not present.
    46  	ExternallyInitialized bool
    47  	// (optional) Section name; empty if not present.
    48  	Section string
    49  	// (optional) Partition name; empty if not present.
    50  	Partition string
    51  	// (optional) Comdat; nil if not present.
    52  	Comdat *ComdatDef
    53  	// (optional) Alignment; zero if not present.
    54  	Align Align
    55  	// (optional) Function attributes.
    56  	FuncAttrs []FuncAttribute
    57  	// (optional) Metadata.
    58  	Metadata
    59  }
    60  
    61  // NewGlobal returns a new global variable declaration based on the given global
    62  // variable name and content type.
    63  func NewGlobal(name string, contentType types.Type) *Global {
    64  	global := &Global{ContentType: contentType}
    65  	global.SetName(name)
    66  	// Compute type.
    67  	global.Type()
    68  	return global
    69  }
    70  
    71  // NewGlobalDef returns a new global variable definition based on the given
    72  // global variable name and initial value.
    73  func NewGlobalDef(name string, init constant.Constant) *Global {
    74  	global := &Global{ContentType: init.Type(), Init: init}
    75  	global.SetName(name)
    76  	// Compute type.
    77  	global.Type()
    78  	return global
    79  }
    80  
    81  // String returns the LLVM syntax representation of the global variable as a
    82  // type-value pair.
    83  func (g *Global) String() string {
    84  	return fmt.Sprintf("%s %s", g.Type(), g.Ident())
    85  }
    86  
    87  // Type returns the type of the global variable.
    88  func (g *Global) Type() types.Type {
    89  	// Cache type if not present.
    90  	if g.Typ == nil {
    91  		g.Typ = types.NewPointer(g.ContentType)
    92  		g.Typ.AddrSpace = g.AddrSpace
    93  	}
    94  	return g.Typ
    95  }
    96  
    97  // LLString returns the LLVM syntax representation of the global variable
    98  // definition or declaration.
    99  //
   100  // Global declaration.
   101  //
   102  //    Name=GlobalIdent '=' Linkage=ExternLinkage Preemptionopt Visibilityopt DLLStorageClassopt ThreadLocalopt UnnamedAddropt AddrSpaceopt ExternallyInitializedopt Immutable ContentType=Type (',' Section)? (',' Partition)? (',' Comdat)? (',' Align)? Metadata=(',' MetadataAttachment)+? FuncAttrs=FuncAttribute+?
   103  //
   104  // Global definition.
   105  //
   106  //    Name=GlobalIdent '=' Linkage=Linkageopt Preemptionopt Visibilityopt DLLStorageClassopt ThreadLocalopt UnnamedAddropt AddrSpaceopt ExternallyInitializedopt Immutable ContentType=Type Init=Constant (',' Section)? (',' Partition)? (',' Comdat)? (',' Align)? Metadata=(',' MetadataAttachment)+? FuncAttrs=FuncAttribute+?
   107  func (g *Global) LLString() string {
   108  	buf := &strings.Builder{}
   109  	fmt.Fprintf(buf, "%s =", g.Ident())
   110  	if g.Linkage != enum.LinkageNone {
   111  		fmt.Fprintf(buf, " %s", g.Linkage)
   112  	}
   113  	if g.Preemption != enum.PreemptionNone {
   114  		fmt.Fprintf(buf, " %s", g.Preemption)
   115  	}
   116  	if g.Visibility != enum.VisibilityNone {
   117  		fmt.Fprintf(buf, " %s", g.Visibility)
   118  	}
   119  	if g.DLLStorageClass != enum.DLLStorageClassNone {
   120  		fmt.Fprintf(buf, " %s", g.DLLStorageClass)
   121  	}
   122  	if g.TLSModel != enum.TLSModelNone {
   123  		fmt.Fprintf(buf, " %s", tlsModelString(g.TLSModel))
   124  	}
   125  	if g.UnnamedAddr != enum.UnnamedAddrNone {
   126  		fmt.Fprintf(buf, " %s", g.UnnamedAddr)
   127  	}
   128  	if g.AddrSpace != 0 {
   129  		fmt.Fprintf(buf, " %s", g.AddrSpace)
   130  	}
   131  	if g.ExternallyInitialized {
   132  		buf.WriteString(" externally_initialized")
   133  	}
   134  	if g.Immutable {
   135  		buf.WriteString(" constant")
   136  	} else {
   137  		buf.WriteString(" global")
   138  	}
   139  	fmt.Fprintf(buf, " %s", g.ContentType)
   140  	if g.Init != nil {
   141  		// Global definition.
   142  		fmt.Fprintf(buf, " %s", g.Init.Ident())
   143  	}
   144  	if g.Section != "" {
   145  		fmt.Fprintf(buf, ", section %s", quote(g.Section))
   146  	}
   147  	if g.Partition != "" {
   148  		fmt.Fprintf(buf, ", partition %s", quote(g.Partition))
   149  	}
   150  	if g.Comdat != nil {
   151  		if g.Comdat.Name == g.Name() {
   152  			buf.WriteString(", comdat")
   153  		} else {
   154  			fmt.Fprintf(buf, ", %s", g.Comdat)
   155  		}
   156  	}
   157  	if g.Align != 0 {
   158  		fmt.Fprintf(buf, ", %s", g.Align)
   159  	}
   160  	for _, md := range g.Metadata {
   161  		fmt.Fprintf(buf, ", %s", md)
   162  	}
   163  	for _, attr := range g.FuncAttrs {
   164  		fmt.Fprintf(buf, " %s", attr)
   165  	}
   166  	return buf.String()
   167  }