Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / exp / ssa / util.go
1 package ssa
2
3 // This file defines a number of miscellaneous utility functions.
4
5 import (
6         "fmt"
7         "go/ast"
8         "go/types"
9 )
10
11 func unreachable() {
12         panic("unreachable")
13 }
14
15 //// AST utilities
16
17 // noparens returns e with any enclosing parentheses stripped.
18 func noparens(e ast.Expr) ast.Expr {
19         for {
20                 p, ok := e.(*ast.ParenExpr)
21                 if !ok {
22                         break
23                 }
24                 e = p.X
25         }
26         return e
27 }
28
29 // isBlankIdent returns true iff e is an Ident with name "_".
30 // They have no associated types.Object, and thus no type.
31 //
32 // TODO(gri): consider making typechecker not treat them differently.
33 // It's one less thing for clients like us to worry about.
34 //
35 func isBlankIdent(e ast.Expr) bool {
36         id, ok := e.(*ast.Ident)
37         return ok && id.Name == "_"
38 }
39
40 //// Type utilities.  Some of these belong in go/types.
41
42 // underlyingType returns the underlying type of typ.
43 // TODO(gri): this is a copy of go/types.underlying; export that function.
44 //
45 func underlyingType(typ types.Type) types.Type {
46         if typ, ok := typ.(*types.NamedType); ok {
47                 return typ.Underlying // underlying types are never NamedTypes
48         }
49         if typ == nil {
50                 panic("underlyingType(nil)")
51         }
52         return typ
53 }
54
55 // isPointer returns true for types whose underlying type is a pointer.
56 func isPointer(typ types.Type) bool {
57         if nt, ok := typ.(*types.NamedType); ok {
58                 typ = nt.Underlying
59         }
60         _, ok := typ.(*types.Pointer)
61         return ok
62 }
63
64 // pointer(typ) returns the type that is a pointer to typ.
65 func pointer(typ types.Type) *types.Pointer {
66         return &types.Pointer{Base: typ}
67 }
68
69 // indirect(typ) assumes that typ is a pointer type,
70 // or named alias thereof, and returns its base type.
71 // Panic ensures if it is not a pointer.
72 //
73 func indirectType(ptr types.Type) types.Type {
74         if v, ok := underlyingType(ptr).(*types.Pointer); ok {
75                 return v.Base
76         }
77         // When debugging it is convenient to comment out this line
78         // and let it continue to print the (illegal) SSA form.
79         panic("indirect() of non-pointer type: " + ptr.String())
80         return nil
81 }
82
83 // deref returns a pointer's base type; otherwise it returns typ.
84 func deref(typ types.Type) types.Type {
85         if typ, ok := underlyingType(typ).(*types.Pointer); ok {
86                 return typ.Base
87         }
88         return typ
89 }
90
91 // methodIndex returns the method (and its index) named id within the
92 // method table methods of named or interface type typ.  If not found,
93 // panic ensues.
94 //
95 func methodIndex(typ types.Type, methods []*types.Method, id Id) (i int, m *types.Method) {
96         for i, m = range methods {
97                 if IdFromQualifiedName(m.QualifiedName) == id {
98                         return
99                 }
100         }
101         panic(fmt.Sprint("method not found: ", id, " in interface ", typ))
102 }
103
104 // objKind returns the syntactic category of the named entity denoted by obj.
105 func objKind(obj types.Object) ast.ObjKind {
106         switch obj.(type) {
107         case *types.Package:
108                 return ast.Pkg
109         case *types.TypeName:
110                 return ast.Typ
111         case *types.Const:
112                 return ast.Con
113         case *types.Var:
114                 return ast.Var
115         case *types.Func:
116                 return ast.Fun
117         }
118         panic(fmt.Sprintf("unexpected Object type: %T", obj))
119 }
120
121 // DefaultType returns the default "typed" type for an "untyped" type;
122 // it returns the incoming type for all other types. If there is no
123 // corresponding untyped type, the result is types.Typ[types.Invalid].
124 //
125 // Exported to exp/ssa/interp.
126 //
127 // TODO(gri): this is a copy of go/types.defaultType; export that function.
128 //
129 func DefaultType(typ types.Type) types.Type {
130         if t, ok := typ.(*types.Basic); ok {
131                 k := types.Invalid
132                 switch t.Kind {
133                 // case UntypedNil:
134                 //      There is no default type for nil. For a good error message,
135                 //      catch this case before calling this function.
136                 case types.UntypedBool:
137                         k = types.Bool
138                 case types.UntypedInt:
139                         k = types.Int
140                 case types.UntypedRune:
141                         k = types.Rune
142                 case types.UntypedFloat:
143                         k = types.Float64
144                 case types.UntypedComplex:
145                         k = types.Complex128
146                 case types.UntypedString:
147                         k = types.String
148                 }
149                 typ = types.Typ[k]
150         }
151         return typ
152 }
153
154 // makeId returns the Id (name, pkg) if the name is exported or
155 // (name, nil) otherwise.
156 //
157 func makeId(name string, pkg *types.Package) (id Id) {
158         id.Name = name
159         if !ast.IsExported(name) {
160                 id.Pkg = pkg
161         }
162         return
163 }
164
165 // IdFromQualifiedName returns the Id (qn.Name, qn.Pkg) if qn is an
166 // exported name or (qn.Name, nil) otherwise.
167 //
168 // Exported to exp/ssa/interp.
169 //
170 func IdFromQualifiedName(qn types.QualifiedName) Id {
171         return makeId(qn.Name, qn.Pkg)
172 }