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  }