Home | History | Annotate | Download | only in ssa
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package ssa
      6 
      7 // TODO: use go/types instead?
      8 
      9 // A type interface used to import cmd/internal/gc:Type
     10 // Type instances are not guaranteed to be canonical.
     11 type Type interface {
     12 	Size() int64 // return the size in bytes
     13 	Alignment() int64
     14 
     15 	IsBoolean() bool // is a named or unnamed boolean type
     16 	IsInteger() bool //  ... ditto for the others
     17 	IsSigned() bool
     18 	IsFloat() bool
     19 	IsComplex() bool
     20 	IsPtrShaped() bool
     21 	IsString() bool
     22 	IsSlice() bool
     23 	IsArray() bool
     24 	IsStruct() bool
     25 	IsInterface() bool
     26 
     27 	IsMemory() bool // special ssa-package-only types
     28 	IsFlags() bool
     29 	IsVoid() bool
     30 	IsTuple() bool
     31 
     32 	ElemType() Type // given []T or *T or [n]T, return T
     33 	PtrTo() Type    // given T, return *T
     34 
     35 	NumFields() int         // # of fields of a struct
     36 	FieldType(i int) Type   // type of ith field of the struct or ith part of a tuple
     37 	FieldOff(i int) int64   // offset of ith field of the struct
     38 	FieldName(i int) string // name of ith field of the struct
     39 
     40 	NumElem() int64 // # of elements of an array
     41 
     42 	String() string
     43 	SimpleString() string // a coarser generic description of T, e.g. T's underlying type
     44 	Compare(Type) Cmp     // compare types, returning one of CMPlt, CMPeq, CMPgt.
     45 }
     46 
     47 // Special compiler-only types.
     48 type CompilerType struct {
     49 	Name   string
     50 	size   int64
     51 	Memory bool
     52 	Flags  bool
     53 	Void   bool
     54 	Int128 bool
     55 }
     56 
     57 func (t *CompilerType) Size() int64            { return t.size } // Size in bytes
     58 func (t *CompilerType) Alignment() int64       { return 0 }
     59 func (t *CompilerType) IsBoolean() bool        { return false }
     60 func (t *CompilerType) IsInteger() bool        { return false }
     61 func (t *CompilerType) IsSigned() bool         { return false }
     62 func (t *CompilerType) IsFloat() bool          { return false }
     63 func (t *CompilerType) IsComplex() bool        { return false }
     64 func (t *CompilerType) IsPtrShaped() bool      { return false }
     65 func (t *CompilerType) IsString() bool         { return false }
     66 func (t *CompilerType) IsSlice() bool          { return false }
     67 func (t *CompilerType) IsArray() bool          { return false }
     68 func (t *CompilerType) IsStruct() bool         { return false }
     69 func (t *CompilerType) IsInterface() bool      { return false }
     70 func (t *CompilerType) IsMemory() bool         { return t.Memory }
     71 func (t *CompilerType) IsFlags() bool          { return t.Flags }
     72 func (t *CompilerType) IsVoid() bool           { return t.Void }
     73 func (t *CompilerType) IsTuple() bool          { return false }
     74 func (t *CompilerType) String() string         { return t.Name }
     75 func (t *CompilerType) SimpleString() string   { return t.Name }
     76 func (t *CompilerType) ElemType() Type         { panic("not implemented") }
     77 func (t *CompilerType) PtrTo() Type            { panic("not implemented") }
     78 func (t *CompilerType) NumFields() int         { panic("not implemented") }
     79 func (t *CompilerType) FieldType(i int) Type   { panic("not implemented") }
     80 func (t *CompilerType) FieldOff(i int) int64   { panic("not implemented") }
     81 func (t *CompilerType) FieldName(i int) string { panic("not implemented") }
     82 func (t *CompilerType) NumElem() int64         { panic("not implemented") }
     83 
     84 type TupleType struct {
     85 	first  Type
     86 	second Type
     87 	// Any tuple with a memory type must put that memory type second.
     88 }
     89 
     90 func (t *TupleType) Size() int64          { panic("not implemented") }
     91 func (t *TupleType) Alignment() int64     { panic("not implemented") }
     92 func (t *TupleType) IsBoolean() bool      { return false }
     93 func (t *TupleType) IsInteger() bool      { return false }
     94 func (t *TupleType) IsSigned() bool       { return false }
     95 func (t *TupleType) IsFloat() bool        { return false }
     96 func (t *TupleType) IsComplex() bool      { return false }
     97 func (t *TupleType) IsPtrShaped() bool    { return false }
     98 func (t *TupleType) IsString() bool       { return false }
     99 func (t *TupleType) IsSlice() bool        { return false }
    100 func (t *TupleType) IsArray() bool        { return false }
    101 func (t *TupleType) IsStruct() bool       { return false }
    102 func (t *TupleType) IsInterface() bool    { return false }
    103 func (t *TupleType) IsMemory() bool       { return false }
    104 func (t *TupleType) IsFlags() bool        { return false }
    105 func (t *TupleType) IsVoid() bool         { return false }
    106 func (t *TupleType) IsTuple() bool        { return true }
    107 func (t *TupleType) String() string       { return t.first.String() + "," + t.second.String() }
    108 func (t *TupleType) SimpleString() string { return "Tuple" }
    109 func (t *TupleType) ElemType() Type       { panic("not implemented") }
    110 func (t *TupleType) PtrTo() Type          { panic("not implemented") }
    111 func (t *TupleType) NumFields() int       { panic("not implemented") }
    112 func (t *TupleType) FieldType(i int) Type {
    113 	switch i {
    114 	case 0:
    115 		return t.first
    116 	case 1:
    117 		return t.second
    118 	default:
    119 		panic("bad tuple index")
    120 	}
    121 }
    122 func (t *TupleType) FieldOff(i int) int64   { panic("not implemented") }
    123 func (t *TupleType) FieldName(i int) string { panic("not implemented") }
    124 func (t *TupleType) NumElem() int64         { panic("not implemented") }
    125 
    126 // Cmp is a comparison between values a and b.
    127 // -1 if a < b
    128 //  0 if a == b
    129 //  1 if a > b
    130 type Cmp int8
    131 
    132 const (
    133 	CMPlt = Cmp(-1)
    134 	CMPeq = Cmp(0)
    135 	CMPgt = Cmp(1)
    136 )
    137 
    138 func (t *CompilerType) Compare(u Type) Cmp {
    139 	x, ok := u.(*CompilerType)
    140 	// ssa.CompilerType is smaller than any other type
    141 	if !ok {
    142 		return CMPlt
    143 	}
    144 	if t == x {
    145 		return CMPeq
    146 	}
    147 	// desire fast sorting, not pretty sorting.
    148 	if len(t.Name) == len(x.Name) {
    149 		if t.Name == x.Name {
    150 			return CMPeq
    151 		}
    152 		if t.Name < x.Name {
    153 			return CMPlt
    154 		}
    155 		return CMPgt
    156 	}
    157 	if len(t.Name) > len(x.Name) {
    158 		return CMPgt
    159 	}
    160 	return CMPlt
    161 }
    162 
    163 func (t *TupleType) Compare(u Type) Cmp {
    164 	// ssa.TupleType is greater than ssa.CompilerType
    165 	if _, ok := u.(*CompilerType); ok {
    166 		return CMPgt
    167 	}
    168 	// ssa.TupleType is smaller than any other type
    169 	x, ok := u.(*TupleType)
    170 	if !ok {
    171 		return CMPlt
    172 	}
    173 	if t == x {
    174 		return CMPeq
    175 	}
    176 	if c := t.first.Compare(x.first); c != CMPeq {
    177 		return c
    178 	}
    179 	return t.second.Compare(x.second)
    180 }
    181 
    182 var (
    183 	TypeInvalid = &CompilerType{Name: "invalid"}
    184 	TypeMem     = &CompilerType{Name: "mem", Memory: true}
    185 	TypeFlags   = &CompilerType{Name: "flags", Flags: true}
    186 	TypeVoid    = &CompilerType{Name: "void", Void: true}
    187 	TypeInt128  = &CompilerType{Name: "int128", size: 16, Int128: true}
    188 )
    189 
    190 func MakeTuple(t0, t1 Type) *TupleType {
    191 	return &TupleType{first: t0, second: t1}
    192 }
    193