github.com/llir/llvm@v0.3.6/ir/ifunc.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 // === [ IFuncs ] ============================================================== 13 14 // IFunc is an indirect function (a special kind of function alias). 15 type IFunc struct { 16 // IFunc name (without '@' prefix). 17 GlobalIdent 18 // Resolver. 19 Resolver constant.Constant 20 21 // Pointer type of resolver. 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 // NewIFunc returns a new indirect function based on the given IFunc name and 40 // resolver. 41 func NewIFunc(name string, resolver constant.Constant) *IFunc { 42 ifunc := &IFunc{Resolver: resolver} 43 ifunc.SetName(name) 44 // Compute type. 45 ifunc.Type() 46 return ifunc 47 } 48 49 // String returns the LLVM syntax representation of the IFunc as a type-value 50 // pair. 51 func (i *IFunc) String() string { 52 return fmt.Sprintf("%s %s", i.Type(), i.Ident()) 53 } 54 55 // Type returns the type of the IFunc. 56 func (i *IFunc) Type() types.Type { 57 // Cache type if not present. 58 if i.Typ == nil { 59 typ, ok := i.Resolver.Type().(*types.PointerType) 60 if !ok { 61 panic(fmt.Errorf("invalid resolver type of %q; expected *types.PointerType, got %T", i.Ident(), i.Resolver.Type())) 62 } 63 i.Typ = typ 64 } 65 return i.Typ 66 } 67 68 // LLString returns the LLVM syntax representation of the IFunc definition. 69 // 70 // Name=GlobalIdent '=' (ExternLinkage | Linkageopt) Preemptionopt Visibilityopt DLLStorageClassopt ThreadLocalopt UnnamedAddropt IndirectSymbolKind ContentType=Type ',' IndirectSymbol Partitions=(',' Partition)* 71 func (i *IFunc) LLString() string { 72 buf := &strings.Builder{} 73 fmt.Fprintf(buf, "%s =", i.Ident()) 74 if i.Linkage != enum.LinkageNone { 75 fmt.Fprintf(buf, " %s", i.Linkage) 76 } 77 if i.Preemption != enum.PreemptionNone { 78 fmt.Fprintf(buf, " %s", i.Preemption) 79 } 80 if i.Visibility != enum.VisibilityNone { 81 fmt.Fprintf(buf, " %s", i.Visibility) 82 } 83 if i.DLLStorageClass != enum.DLLStorageClassNone { 84 fmt.Fprintf(buf, " %s", i.DLLStorageClass) 85 } 86 if i.TLSModel != enum.TLSModelNone { 87 fmt.Fprintf(buf, " %s", tlsModelString(i.TLSModel)) 88 } 89 if i.UnnamedAddr != enum.UnnamedAddrNone { 90 fmt.Fprintf(buf, " %s", i.UnnamedAddr) 91 } 92 buf.WriteString(" ifunc") 93 fmt.Fprintf(buf, " %s, %s", i.Typ.ElemType, i.Resolver) 94 if len(i.Partition) > 0 { 95 fmt.Fprintf(buf, ", partition %s", quote(i.Partition)) 96 } 97 return buf.String() 98 }