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 }