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  }