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