github.com/llir/llvm@v0.3.6/ir/alias.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 // === [ Aliases ] ============================================================= 13 14 // Alias is an alias of a global identifier or constant expression. 15 type Alias struct { 16 // Alias name (without '@' prefix). 17 GlobalIdent 18 // Aliasee. 19 Aliasee constant.Constant 20 21 // Pointer type of aliasee. 22 Typ *types.PointerType 23 // (optional) Linkage; zero value if not present. 24 Linkage enum.Linkage 25 // (optional) Preemption; zero value if not present. 26 Preemption enum.Preemption 27 // (optional) Visibility; zero value if not present. 28 Visibility enum.Visibility 29 // (optional) DLL storage class; zero value if not present. 30 DLLStorageClass enum.DLLStorageClass 31 // (optional) Thread local storage model; zero value if not present. 32 TLSModel enum.TLSModel 33 // (optional) Unnamed address; zero value if not present. 34 UnnamedAddr enum.UnnamedAddr 35 // (optional) Partition name; empty if not present. 36 Partition string 37 } 38 39 // NewAlias returns a new alias based on the given alias name and aliasee. 40 func NewAlias(name string, aliasee constant.Constant) *Alias { 41 alias := &Alias{Aliasee: aliasee} 42 alias.SetName(name) 43 // Compute type. 44 alias.Type() 45 return alias 46 } 47 48 // String returns the LLVM syntax representation of the alias as a type-value 49 // pair. 50 func (a *Alias) String() string { 51 return fmt.Sprintf("%s %s", a.Type(), a.Ident()) 52 } 53 54 // Type returns the type of the alias. 55 func (a *Alias) Type() types.Type { 56 // Cache type if not present. 57 if a.Typ == nil { 58 typ, ok := a.Aliasee.Type().(*types.PointerType) 59 if !ok { 60 panic(fmt.Errorf("invalid aliasee type of %q; expected *types.PointerType, got %T", a.Ident(), a.Aliasee.Type())) 61 } 62 a.Typ = typ 63 } 64 return a.Typ 65 } 66 67 // LLString returns the LLVM syntax representation of the alias definition. 68 // 69 // Name=GlobalIdent '=' (ExternLinkage | Linkageopt) Preemptionopt Visibilityopt DLLStorageClassopt ThreadLocalopt UnnamedAddropt IndirectSymbolKind ContentType=Type ',' IndirectSymbol Partitions=(',' Partition)* 70 func (a *Alias) LLString() string { 71 buf := &strings.Builder{} 72 fmt.Fprintf(buf, "%s =", a.Ident()) 73 if a.Linkage != enum.LinkageNone { 74 fmt.Fprintf(buf, " %s", a.Linkage) 75 } 76 if a.Preemption != enum.PreemptionNone { 77 fmt.Fprintf(buf, " %s", a.Preemption) 78 } 79 if a.Visibility != enum.VisibilityNone { 80 fmt.Fprintf(buf, " %s", a.Visibility) 81 } 82 if a.DLLStorageClass != enum.DLLStorageClassNone { 83 fmt.Fprintf(buf, " %s", a.DLLStorageClass) 84 } 85 if a.TLSModel != enum.TLSModelNone { 86 fmt.Fprintf(buf, " %s", tlsModelString(a.TLSModel)) 87 } 88 if a.UnnamedAddr != enum.UnnamedAddrNone { 89 fmt.Fprintf(buf, " %s", a.UnnamedAddr) 90 } 91 buf.WriteString(" alias") 92 fmt.Fprintf(buf, " %s, ", a.Typ.ElemType) 93 if expr, ok := a.Aliasee.(constant.Expression); ok { 94 buf.WriteString(expr.Ident()) 95 } else { 96 buf.WriteString(a.Aliasee.String()) 97 } 98 if len(a.Partition) > 0 { 99 fmt.Fprintf(buf, ", partition %s", quote(a.Partition)) 100 } 101 return buf.String() 102 }