blob: 7402e17e2a81aa10d04a687cf823ce7b78cf77f6 [file] [log] [blame]
Russ Cox8c195bd2015-02-13 14:40:36 -05001// Copyright 2009 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
5package gc
6
7import (
8 "bytes"
9 "cmd/internal/obj"
Matthew Dempsky392434e2015-02-27 16:05:30 +090010 "crypto/md5"
11 "encoding/binary"
Russ Cox8c195bd2015-02-13 14:40:36 -050012 "fmt"
13 "os"
14 "sort"
15 "strings"
16 "unicode"
17 "unicode/utf8"
18)
19
20type Error struct {
21 lineno int
22 seq int
23 msg string
24}
25
26var errors []Error
27
Russ Cox8c195bd2015-02-13 14:40:36 -050028func errorexit() {
29 Flusherrors()
30 if outfile != "" {
31 os.Remove(outfile)
32 }
33 os.Exit(2)
34}
35
36func parserline() int {
Russ Cox9c8c0e72015-02-23 14:02:27 -050037 if parsing && theparser.Lookahead() > 0 {
38 // parser has one symbol lookahead
Russ Cox8c195bd2015-02-13 14:40:36 -050039 return int(prevlineno)
40 }
41 return int(lineno)
42}
43
44func adderrorname(n *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -050045 if n.Op != ODOT {
46 return
47 }
Russ Cox17228f42015-04-17 12:03:22 -040048 old := fmt.Sprintf("%v: undefined: %v\n", n.Line(), n.Left)
Russ Cox8c195bd2015-02-13 14:40:36 -050049 if len(errors) > 0 && int32(errors[len(errors)-1].lineno) == n.Lineno && errors[len(errors)-1].msg == old {
Russ Cox17228f42015-04-17 12:03:22 -040050 errors[len(errors)-1].msg = fmt.Sprintf("%v: undefined: %v in %v\n", n.Line(), n.Left, n)
Russ Cox8c195bd2015-02-13 14:40:36 -050051 }
52}
53
Matthew Dempsky4f2a7302015-04-02 17:01:14 -070054func adderr(line int, format string, args ...interface{}) {
Russ Cox8c195bd2015-02-13 14:40:36 -050055 errors = append(errors, Error{
56 seq: len(errors),
57 lineno: line,
58 msg: fmt.Sprintf("%v: %s\n", Ctxt.Line(line), fmt.Sprintf(format, args...)),
59 })
60}
61
62type errcmp []Error
63
64func (x errcmp) Len() int {
65 return len(x)
66}
67
68func (x errcmp) Swap(i, j int) {
69 x[i], x[j] = x[j], x[i]
70}
71
72func (x errcmp) Less(i, j int) bool {
Russ Cox382b44e2015-02-23 16:07:24 -050073 a := &x[i]
74 b := &x[j]
Russ Cox8c195bd2015-02-13 14:40:36 -050075 if a.lineno != b.lineno {
76 return a.lineno-b.lineno < 0
77 }
78 if a.seq != b.seq {
79 return a.seq-b.seq < 0
80 }
81 return stringsCompare(a.msg, b.msg) < 0
82}
83
84func Flusherrors() {
Dave Cheneye9ab3432015-05-01 11:51:47 +100085 bstdout.Flush()
Russ Cox8c195bd2015-02-13 14:40:36 -050086 if len(errors) == 0 {
87 return
88 }
89 sort.Sort(errcmp(errors[:len(errors)]))
Russ Cox382b44e2015-02-23 16:07:24 -050090 for i := 0; i < len(errors); i++ {
Russ Cox8c195bd2015-02-13 14:40:36 -050091 if i == 0 || errors[i].msg != errors[i-1].msg {
92 fmt.Printf("%s", errors[i].msg)
93 }
94 }
95 errors = errors[:0]
96}
97
98func hcrash() {
99 if Debug['h'] != 0 {
100 Flusherrors()
101 if outfile != "" {
102 os.Remove(outfile)
103 }
104 var x *int
105 *x = 0
106 }
107}
108
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700109func yyerrorl(line int, format string, args ...interface{}) {
110 adderr(line, format, args...)
Russ Cox8c195bd2015-02-13 14:40:36 -0500111
112 hcrash()
113 nerrors++
Russ Coxdc7b54b2015-02-17 22:13:49 -0500114 if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500115 Flusherrors()
116 fmt.Printf("%v: too many errors\n", Ctxt.Line(line))
117 errorexit()
118 }
119}
120
Russ Cox8c195bd2015-02-13 14:40:36 -0500121var yyerror_lastsyntax int
122
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700123func Yyerror(format string, args ...interface{}) {
124 msg := fmt.Sprintf(format, args...)
125 if strings.HasPrefix(msg, "syntax error") {
Russ Cox8c195bd2015-02-13 14:40:36 -0500126 nsyntaxerrors++
127
Russ Cox8c195bd2015-02-13 14:40:36 -0500128 // An unexpected EOF caused a syntax error. Use the previous
129 // line number since getc generated a fake newline character.
130 if curio.eofnl != 0 {
131 lexlineno = prevlineno
132 }
133
134 // only one syntax error per line
135 if int32(yyerror_lastsyntax) == lexlineno {
136 return
137 }
138 yyerror_lastsyntax = int(lexlineno)
139
Russ Cox8c195bd2015-02-13 14:40:36 -0500140 // plain "syntax error" gets "near foo" added
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700141 if msg == "syntax error" {
Russ Cox8c195bd2015-02-13 14:40:36 -0500142 yyerrorl(int(lexlineno), "syntax error near %s", lexbuf.String())
143 return
144 }
145
Matthew Dempskye7d9f812015-04-02 21:51:46 -0700146 // The grammar has { and LBRACE but both show up as {.
147 // Rewrite syntax error referring to "{ or {" to say just "{".
148 // The grammar has ? and @ but only for reading imports.
149 // Silence them in ordinary errors.
150 msg = strings.Replace(msg, "{ or {", "{", -1)
151 msg = strings.Replace(msg, " or ?", "", -1)
152 msg = strings.Replace(msg, " or @", "", -1)
Russ Cox8c195bd2015-02-13 14:40:36 -0500153
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700154 msg = strings.Replace(msg, "LLITERAL", litbuf, -1)
155
156 yyerrorl(int(lexlineno), "%s", msg)
Russ Cox8c195bd2015-02-13 14:40:36 -0500157 return
158 }
159
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700160 adderr(parserline(), "%s", msg)
Russ Cox8c195bd2015-02-13 14:40:36 -0500161
162 hcrash()
163 nerrors++
Russ Coxdc7b54b2015-02-17 22:13:49 -0500164 if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500165 Flusherrors()
166 fmt.Printf("%v: too many errors\n", Ctxt.Line(parserline()))
167 errorexit()
168 }
169}
170
171func Warn(fmt_ string, args ...interface{}) {
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700172 adderr(parserline(), fmt_, args...)
Russ Cox8c195bd2015-02-13 14:40:36 -0500173
174 hcrash()
175}
176
177func Warnl(line int, fmt_ string, args ...interface{}) {
Matthew Dempsky4f2a7302015-04-02 17:01:14 -0700178 adderr(line, fmt_, args...)
Russ Cox8c195bd2015-02-13 14:40:36 -0500179 if Debug['m'] != 0 {
180 Flusherrors()
181 }
182}
183
184func Fatal(fmt_ string, args ...interface{}) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500185 Flusherrors()
186
187 fmt.Printf("%v: internal compiler error: ", Ctxt.Line(int(lineno)))
188 fmt.Printf(fmt_, args...)
189 fmt.Printf("\n")
190
191 // If this is a released compiler version, ask for a bug report.
192 if strings.HasPrefix(obj.Getgoversion(), "release") {
193 fmt.Printf("\n")
194 fmt.Printf("Please file a bug report including a short program that triggers the error.\n")
195 fmt.Printf("https://golang.org/issue/new\n")
196 }
197
198 hcrash()
199 errorexit()
200}
201
Matthew Dempsky14677762015-04-20 13:32:40 -0700202func linehistpragma(file string) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500203 if Debug['i'] != 0 {
Matthew Dempsky14677762015-04-20 13:32:40 -0700204 fmt.Printf("pragma %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
Russ Cox8c195bd2015-02-13 14:40:36 -0500205 }
Matthew Dempsky14677762015-04-20 13:32:40 -0700206 Ctxt.AddImport(file)
207}
Russ Cox8c195bd2015-02-13 14:40:36 -0500208
Matthew Dempsky14677762015-04-20 13:32:40 -0700209func linehistpush(file string) {
210 if Debug['i'] != 0 {
211 fmt.Printf("import %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
Russ Cox8c195bd2015-02-13 14:40:36 -0500212 }
Matthew Dempsky14677762015-04-20 13:32:40 -0700213 Ctxt.LineHist.Push(int(lexlineno), file)
214}
215
216func linehistpop() {
217 if Debug['i'] != 0 {
218 fmt.Printf("end of import at line %v\n", Ctxt.Line(int(lexlineno)))
219 }
220 Ctxt.LineHist.Pop(int(lexlineno))
221}
222
223func linehistupdate(file string, off int) {
224 if Debug['i'] != 0 {
225 fmt.Printf("line %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
226 }
227 Ctxt.LineHist.Update(int(lexlineno), file, off)
Russ Cox8c195bd2015-02-13 14:40:36 -0500228}
229
230func setlineno(n *Node) int32 {
Russ Cox382b44e2015-02-23 16:07:24 -0500231 lno := lineno
Russ Cox8c195bd2015-02-13 14:40:36 -0500232 if n != nil {
233 switch n.Op {
Russ Cox55203c72015-06-28 23:12:21 -0400234 case ONAME, OTYPE, OPACK:
Russ Cox8c195bd2015-02-13 14:40:36 -0500235 break
236
Russ Cox55203c72015-06-28 23:12:21 -0400237 case OLITERAL:
238 if n.Sym != nil {
239 break
240 }
241 fallthrough
242
Russ Cox8c195bd2015-02-13 14:40:36 -0500243 default:
244 lineno = n.Lineno
245 if lineno == 0 {
246 if Debug['K'] != 0 {
247 Warn("setlineno: line 0")
248 }
249 lineno = lno
250 }
251 }
252 }
253
254 return lno
255}
256
Russ Coxd0b59de2015-03-02 16:21:15 -0500257func Lookup(name string) *Sym {
258 return localpkg.Lookup(name)
Russ Cox8c195bd2015-02-13 14:40:36 -0500259}
260
Matthew Dempsky8b3670f2015-03-06 12:02:24 -0800261func Lookupf(format string, a ...interface{}) *Sym {
262 return Lookup(fmt.Sprintf(format, a...))
263}
264
Russ Coxd0b59de2015-03-02 16:21:15 -0500265func LookupBytes(name []byte) *Sym {
266 return localpkg.LookupBytes(name)
267}
268
269var initSyms []*Sym
270
Russ Coxc8198342015-03-12 18:45:30 -0400271var nopkg = &Pkg{
272 Syms: make(map[string]*Sym),
273}
Russ Coxd0b59de2015-03-02 16:21:15 -0500274
275func (pkg *Pkg) Lookup(name string) *Sym {
276 if pkg == nil {
277 pkg = nopkg
278 }
279 if s := pkg.Syms[name]; s != nil {
280 return s
281 }
282
283 s := &Sym{
284 Name: name,
285 Pkg: pkg,
286 Lexical: LNAME,
287 }
Russ Coxc8198342015-03-12 18:45:30 -0400288 if name == "init" {
Russ Coxd0b59de2015-03-02 16:21:15 -0500289 initSyms = append(initSyms, s)
290 }
Russ Coxd0b59de2015-03-02 16:21:15 -0500291 pkg.Syms[name] = s
292 return s
293}
294
295func (pkg *Pkg) LookupBytes(name []byte) *Sym {
296 if pkg == nil {
297 pkg = nopkg
298 }
299 if s := pkg.Syms[string(name)]; s != nil {
300 return s
301 }
302 str := internString(name)
303 return pkg.Lookup(str)
Russ Cox8c195bd2015-02-13 14:40:36 -0500304}
305
306func Pkglookup(name string, pkg *Pkg) *Sym {
Russ Coxd0b59de2015-03-02 16:21:15 -0500307 return pkg.Lookup(name)
Russ Cox8c195bd2015-02-13 14:40:36 -0500308}
309
310func restrictlookup(name string, pkg *Pkg) *Sym {
311 if !exportname(name) && pkg != localpkg {
312 Yyerror("cannot refer to unexported name %s.%s", pkg.Name, name)
313 }
314 return Pkglookup(name, pkg)
315}
316
317// find all the exported symbols in package opkg
318// and make them available in the current package
319func importdot(opkg *Pkg, pack *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500320 var s1 *Sym
Russ Cox8c195bd2015-02-13 14:40:36 -0500321 var pkgerror string
322
Russ Cox382b44e2015-02-23 16:07:24 -0500323 n := 0
Russ Coxd0b59de2015-03-02 16:21:15 -0500324 for _, s := range opkg.Syms {
325 if s.Def == nil {
326 continue
Russ Cox8c195bd2015-02-13 14:40:36 -0500327 }
Russ Coxd0b59de2015-03-02 16:21:15 -0500328 if !exportname(s.Name) || strings.ContainsRune(s.Name, 0xb7) { // 0xb7 = center dot
329 continue
330 }
331 s1 = Lookup(s.Name)
332 if s1.Def != nil {
333 pkgerror = fmt.Sprintf("during import %q", opkg.Path)
334 redeclare(s1, pkgerror)
335 continue
336 }
337
338 s1.Def = s.Def
339 s1.Block = s.Block
Russ Cox140ef3c2015-05-26 23:08:39 -0400340 if s1.Def.Name == nil {
341 Dump("s1def", s1.Def)
Russ Coxa53710f2015-06-03 14:16:01 -0400342 Fatal("missing Name")
Russ Cox140ef3c2015-05-26 23:08:39 -0400343 }
344 s1.Def.Name.Pack = pack
Russ Coxd0b59de2015-03-02 16:21:15 -0500345 s1.Origpkg = opkg
346 n++
Russ Cox8c195bd2015-02-13 14:40:36 -0500347 }
348
349 if n == 0 {
350 // can't possibly be used - there were no symbols
Russ Coxbed1f902015-03-02 16:03:26 -0500351 yyerrorl(int(pack.Lineno), "imported and not used: %q", opkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500352 }
353}
354
Russ Coxdc7b54b2015-02-17 22:13:49 -0500355func gethunk() {
Russ Cox382b44e2015-02-23 16:07:24 -0500356 nh := int32(NHUNK)
Russ Coxdc7b54b2015-02-17 22:13:49 -0500357 if thunk >= 10*NHUNK {
358 nh = 10 * NHUNK
359 }
Russ Cox382b44e2015-02-23 16:07:24 -0500360 h := string(make([]byte, nh))
Russ Coxdc7b54b2015-02-17 22:13:49 -0500361 if h == "" {
362 Flusherrors()
363 Yyerror("out of memory")
364 errorexit()
365 }
366
367 hunk = h
368 nhunk = nh
369 thunk += nh
370}
371
Russ Cox8c195bd2015-02-13 14:40:36 -0500372func Nod(op int, nleft *Node, nright *Node) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -0500373 n := new(Node)
Russ Cox8c195bd2015-02-13 14:40:36 -0500374 n.Op = uint8(op)
375 n.Left = nleft
376 n.Right = nright
377 n.Lineno = int32(parserline())
378 n.Xoffset = BADWIDTH
379 n.Orig = n
Josh Bleecher Snyder57279ba2015-03-10 21:37:13 -0700380 switch op {
381 case OCLOSURE, ODCLFUNC:
382 n.Func = new(Func)
Russ Coxfd2154f2015-05-27 07:31:56 -0400383 n.Func.FCurfn = Curfn
Josh Bleecher Snyder76ec0ee2015-04-03 17:43:38 -0700384 case ONAME:
385 n.Name = new(Name)
Russ Cox3c3019a2015-05-27 00:44:05 -0400386 n.Name.Param = new(Param)
Russ Coxac2bda12015-05-26 23:18:27 -0400387 case OLABEL, OPACK:
Russ Cox4fdd5362015-05-26 22:19:27 -0400388 n.Name = new(Name)
Josh Bleecher Snyderf4ab8202015-05-18 10:27:59 -0700389 case ODCLFIELD:
Russ Cox3c3019a2015-05-27 00:44:05 -0400390 if nleft != nil {
391 n.Name = nleft.Name
392 } else {
393 n.Name = new(Name)
394 n.Name.Param = new(Param)
395 }
Josh Bleecher Snyder57279ba2015-03-10 21:37:13 -0700396 }
Russ Coxfd2154f2015-05-27 07:31:56 -0400397 if n.Name != nil {
398 n.Name.Curfn = Curfn
399 }
Russ Cox8c195bd2015-02-13 14:40:36 -0500400 return n
401}
402
403func saveorignode(n *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500404 if n.Orig != nil {
405 return
406 }
Russ Cox382b44e2015-02-23 16:07:24 -0500407 norig := Nod(int(n.Op), nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500408 *norig = *n
409 n.Orig = norig
410}
411
412// ispaddedfield reports whether the given field
413// is followed by padding. For the case where t is
414// the last field, total gives the size of the enclosing struct.
Russ Coxdc7b54b2015-02-17 22:13:49 -0500415func ispaddedfield(t *Type, total int64) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500416 if t.Etype != TFIELD {
Russ Cox17228f42015-04-17 12:03:22 -0400417 Fatal("ispaddedfield called non-field %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500418 }
419 if t.Down == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500420 return t.Width+t.Type.Width != total
Russ Cox8c195bd2015-02-13 14:40:36 -0500421 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500422 return t.Width+t.Type.Width != t.Down.Width
Russ Cox8c195bd2015-02-13 14:40:36 -0500423}
424
425func algtype1(t *Type, bad **Type) int {
Russ Cox8c195bd2015-02-13 14:40:36 -0500426 if bad != nil {
427 *bad = nil
428 }
429 if t.Broke != 0 {
430 return AMEM
431 }
432 if t.Noalg != 0 {
433 return ANOEQ
434 }
435
436 switch t.Etype {
437 // will be defined later.
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700438 case TANY, TFORW:
Russ Cox8c195bd2015-02-13 14:40:36 -0500439 *bad = t
440
441 return -1
442
443 case TINT8,
444 TUINT8,
445 TINT16,
446 TUINT16,
447 TINT32,
448 TUINT32,
449 TINT64,
450 TUINT64,
451 TINT,
452 TUINT,
453 TUINTPTR,
454 TBOOL,
455 TPTR32,
456 TPTR64,
457 TCHAN,
458 TUNSAFEPTR:
459 return AMEM
460
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700461 case TFUNC, TMAP:
Russ Cox8c195bd2015-02-13 14:40:36 -0500462 if bad != nil {
463 *bad = t
464 }
465 return ANOEQ
466
467 case TFLOAT32:
468 return AFLOAT32
469
470 case TFLOAT64:
471 return AFLOAT64
472
473 case TCOMPLEX64:
474 return ACPLX64
475
476 case TCOMPLEX128:
477 return ACPLX128
478
479 case TSTRING:
480 return ASTRING
481
482 case TINTER:
Russ Coxdc7b54b2015-02-17 22:13:49 -0500483 if isnilinter(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500484 return ANILINTER
485 }
486 return AINTER
487
488 case TARRAY:
Russ Coxdc7b54b2015-02-17 22:13:49 -0500489 if Isslice(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500490 if bad != nil {
491 *bad = t
492 }
493 return ANOEQ
494 }
495
Russ Cox382b44e2015-02-23 16:07:24 -0500496 a := algtype1(t.Type, bad)
Russ Cox8c195bd2015-02-13 14:40:36 -0500497 if a == ANOEQ || a == AMEM {
498 if a == ANOEQ && bad != nil {
499 *bad = t
500 }
501 return a
502 }
503
504 return -1 // needs special compare
505
506 case TSTRUCT:
507 if t.Type != nil && t.Type.Down == nil && !isblanksym(t.Type.Sym) {
508 // One-field struct is same as that one field alone.
509 return algtype1(t.Type.Type, bad)
510 }
511
Russ Cox382b44e2015-02-23 16:07:24 -0500512 ret := AMEM
513 var a int
514 for t1 := t.Type; t1 != nil; t1 = t1.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -0500515 // All fields must be comparable.
516 a = algtype1(t1.Type, bad)
517
518 if a == ANOEQ {
519 return ANOEQ
520 }
521
522 // Blank fields, padded fields, fields with non-memory
523 // equality need special compare.
Russ Coxdc7b54b2015-02-17 22:13:49 -0500524 if a != AMEM || isblanksym(t1.Sym) || ispaddedfield(t1, t.Width) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500525 ret = -1
526 continue
527 }
528 }
529
530 return ret
531 }
532
Russ Cox17228f42015-04-17 12:03:22 -0400533 Fatal("algtype1: unexpected type %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500534 return 0
535}
536
537func algtype(t *Type) int {
Russ Cox382b44e2015-02-23 16:07:24 -0500538 a := algtype1(t, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500539 if a == AMEM || a == ANOEQ {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500540 if Isslice(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500541 return ASLICE
542 }
543 switch t.Width {
544 case 0:
545 return a + AMEM0 - AMEM
546
547 case 1:
548 return a + AMEM8 - AMEM
549
550 case 2:
551 return a + AMEM16 - AMEM
552
553 case 4:
554 return a + AMEM32 - AMEM
555
556 case 8:
557 return a + AMEM64 - AMEM
558
559 case 16:
560 return a + AMEM128 - AMEM
561 }
562 }
563
564 return a
565}
566
567func maptype(key *Type, val *Type) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -0500568 if key != nil {
Russ Cox382b44e2015-02-23 16:07:24 -0500569 var bad *Type
570 atype := algtype1(key, &bad)
571 var mtype int
Russ Cox8c195bd2015-02-13 14:40:36 -0500572 if bad == nil {
573 mtype = int(key.Etype)
574 } else {
575 mtype = int(bad.Etype)
576 }
577 switch mtype {
578 default:
579 if atype == ANOEQ {
Russ Cox17228f42015-04-17 12:03:22 -0400580 Yyerror("invalid map key type %v", key)
Russ Cox8c195bd2015-02-13 14:40:36 -0500581 }
582
583 // will be resolved later.
584 case TANY:
585 break
586
587 // map[key] used during definition of key.
588 // postpone check until key is fully defined.
589 // if there are multiple uses of map[key]
590 // before key is fully defined, the error
591 // will only be printed for the first one.
592 // good enough.
593 case TFORW:
594 if key.Maplineno == 0 {
595 key.Maplineno = lineno
596 }
597 }
598 }
599
Russ Cox382b44e2015-02-23 16:07:24 -0500600 t := typ(TMAP)
Russ Cox8c195bd2015-02-13 14:40:36 -0500601 t.Down = key
602 t.Type = val
603 return t
604}
605
606func typ(et int) *Type {
Russ Cox382b44e2015-02-23 16:07:24 -0500607 t := new(Type)
Russ Cox8c195bd2015-02-13 14:40:36 -0500608 t.Etype = uint8(et)
609 t.Width = BADWIDTH
610 t.Lineno = int(lineno)
611 t.Orig = t
612 return t
613}
614
615type methcmp []*Type
616
617func (x methcmp) Len() int {
618 return len(x)
619}
620
621func (x methcmp) Swap(i, j int) {
622 x[i], x[j] = x[j], x[i]
623}
624
625func (x methcmp) Less(i, j int) bool {
Russ Cox382b44e2015-02-23 16:07:24 -0500626 a := x[i]
627 b := x[j]
Russ Cox8c195bd2015-02-13 14:40:36 -0500628 if a.Sym == nil && b.Sym == nil {
629 return false
630 }
631 if a.Sym == nil {
632 return true
633 }
634 if b.Sym == nil {
635 return 1 < 0
636 }
Russ Cox382b44e2015-02-23 16:07:24 -0500637 k := stringsCompare(a.Sym.Name, b.Sym.Name)
Russ Cox8c195bd2015-02-13 14:40:36 -0500638 if k != 0 {
639 return k < 0
640 }
641 if !exportname(a.Sym.Name) {
Russ Coxbed1f902015-03-02 16:03:26 -0500642 k := stringsCompare(a.Sym.Pkg.Path, b.Sym.Pkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500643 if k != 0 {
644 return k < 0
645 }
646 }
647
648 return false
649}
650
651func sortinter(t *Type) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -0500652 if t.Type == nil || t.Type.Down == nil {
653 return t
654 }
655
Russ Cox382b44e2015-02-23 16:07:24 -0500656 i := 0
657 for f := t.Type; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -0500658 i++
659 }
Russ Cox382b44e2015-02-23 16:07:24 -0500660 a := make([]*Type, i)
Russ Cox8c195bd2015-02-13 14:40:36 -0500661 i = 0
Russ Cox382b44e2015-02-23 16:07:24 -0500662 var f *Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500663 for f = t.Type; f != nil; f = f.Down {
664 a[i] = f
665 i++
666 }
667 sort.Sort(methcmp(a[:i]))
668 for {
669 tmp11 := i
670 i--
Russ Coxdc7b54b2015-02-17 22:13:49 -0500671 if tmp11 <= 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500672 break
673 }
674 a[i].Down = f
675 f = a[i]
676 }
677
678 t.Type = f
679 return t
680}
681
682func Nodintconst(v int64) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -0500683 c := Nod(OLITERAL, nil, nil)
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -0700684 c.Addable = true
Russ Cox81d58102015-05-27 00:47:05 -0400685 c.SetVal(Val{new(Mpint)})
686 Mpmovecfix(c.Val().U.(*Mpint), v)
Russ Cox8c195bd2015-02-13 14:40:36 -0500687 c.Type = Types[TIDEAL]
688 ullmancalc(c)
689 return c
690}
691
692func nodfltconst(v *Mpflt) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -0500693 c := Nod(OLITERAL, nil, nil)
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -0700694 c.Addable = true
Russ Cox81d58102015-05-27 00:47:05 -0400695 c.SetVal(Val{newMpflt()})
696 mpmovefltflt(c.Val().U.(*Mpflt), v)
Russ Cox8c195bd2015-02-13 14:40:36 -0500697 c.Type = Types[TIDEAL]
698 ullmancalc(c)
699 return c
700}
701
702func Nodconst(n *Node, t *Type, v int64) {
703 *n = Node{}
704 n.Op = OLITERAL
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -0700705 n.Addable = true
Russ Cox8c195bd2015-02-13 14:40:36 -0500706 ullmancalc(n)
Russ Cox81d58102015-05-27 00:47:05 -0400707 n.SetVal(Val{new(Mpint)})
708 Mpmovecfix(n.Val().U.(*Mpint), v)
Russ Cox8c195bd2015-02-13 14:40:36 -0500709 n.Type = t
710
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000711 if Isfloat[t.Etype] {
Russ Cox17228f42015-04-17 12:03:22 -0400712 Fatal("nodconst: bad type %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500713 }
714}
715
716func nodnil() *Node {
Russ Cox382b44e2015-02-23 16:07:24 -0500717 c := Nodintconst(0)
Russ Cox81d58102015-05-27 00:47:05 -0400718 c.SetVal(Val{new(NilVal)})
Russ Cox8c195bd2015-02-13 14:40:36 -0500719 c.Type = Types[TNIL]
720 return c
721}
722
Russ Coxdc7b54b2015-02-17 22:13:49 -0500723func Nodbool(b bool) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -0500724 c := Nodintconst(0)
Russ Cox81d58102015-05-27 00:47:05 -0400725 c.SetVal(Val{b})
Russ Cox8c195bd2015-02-13 14:40:36 -0500726 c.Type = idealbool
727 return c
728}
729
730func aindex(b *Node, t *Type) *Type {
Russ Cox382b44e2015-02-23 16:07:24 -0500731 bound := int64(-1) // open bound
Russ Cox8c195bd2015-02-13 14:40:36 -0500732 typecheck(&b, Erv)
733 if b != nil {
734 switch consttype(b) {
735 default:
736 Yyerror("array bound must be an integer expression")
737
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700738 case CTINT, CTRUNE:
Russ Cox81d58102015-05-27 00:47:05 -0400739 bound = Mpgetfix(b.Val().U.(*Mpint))
Russ Cox8c195bd2015-02-13 14:40:36 -0500740 if bound < 0 {
741 Yyerror("array bound must be non negative")
742 }
743 }
744 }
745
746 // fixed array
Russ Cox382b44e2015-02-23 16:07:24 -0500747 r := typ(TARRAY)
Russ Cox8c195bd2015-02-13 14:40:36 -0500748
749 r.Type = t
750 r.Bound = bound
751 return r
752}
753
David Chase05d8f1d2015-05-22 22:01:01 -0400754// treecopy recursively copies n, with the exception of
755// ONAME, OLITERAL, OTYPE, and non-iota ONONAME leaves.
756// Copies of iota ONONAME nodes are assigned the current
757// value of iota_. If lineno != 0, it sets the line number
758// of newly allocated nodes to lineno.
759func treecopy(n *Node, lineno int32) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -0500760 if n == nil {
761 return nil
762 }
763
Russ Cox382b44e2015-02-23 16:07:24 -0500764 var m *Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500765 switch n.Op {
766 default:
767 m = Nod(OXXX, nil, nil)
768 *m = *n
769 m.Orig = m
David Chase05d8f1d2015-05-22 22:01:01 -0400770 m.Left = treecopy(n.Left, lineno)
771 m.Right = treecopy(n.Right, lineno)
772 m.List = listtreecopy(n.List, lineno)
David Chase7929a0d2015-06-29 16:30:19 -0400773 if lineno != 0 {
David Chase05d8f1d2015-05-22 22:01:01 -0400774 m.Lineno = lineno
775 }
Russ Cox3c3019a2015-05-27 00:44:05 -0400776 if m.Name != nil && n.Op != ODCLFIELD {
Russ Cox4fdd5362015-05-26 22:19:27 -0400777 Dump("treecopy", n)
778 Fatal("treecopy Name")
Russ Cox8c195bd2015-02-13 14:40:36 -0500779 }
780
781 case ONONAME:
782 if n.Sym == Lookup("iota") {
783 // Not sure yet whether this is the real iota,
784 // but make a copy of the Node* just in case,
785 // so that all the copies of this const definition
786 // don't have the same iota value.
787 m = Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500788 *m = *n
David Chase05d8f1d2015-05-22 22:01:01 -0400789 if lineno != 0 {
790 m.Lineno = lineno
791 }
Russ Cox11322d42015-05-26 23:56:14 -0400792 m.Name = new(Name)
793 *m.Name = *n.Name
794 m.Name.Iota = iota_
Russ Cox8c195bd2015-02-13 14:40:36 -0500795 break
796 }
797 fallthrough
798
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700799 case ONAME, OLITERAL, OTYPE:
Russ Cox8c195bd2015-02-13 14:40:36 -0500800 m = n
801 }
802
803 return m
804}
805
Russ Coxdc7b54b2015-02-17 22:13:49 -0500806func isnil(n *Node) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500807 if n == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500808 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500809 }
810 if n.Op != OLITERAL {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500811 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500812 }
Russ Cox81d58102015-05-27 00:47:05 -0400813 if n.Val().Ctype() != CTNIL {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500814 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500815 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500816 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500817}
818
Russ Coxdc7b54b2015-02-17 22:13:49 -0500819func isptrto(t *Type, et int) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500820 if t == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500821 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500822 }
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000823 if !Isptr[t.Etype] {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500824 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500825 }
826 t = t.Type
827 if t == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500828 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500829 }
830 if int(t.Etype) != et {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500831 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500832 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500833 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500834}
835
Russ Coxdc7b54b2015-02-17 22:13:49 -0500836func Istype(t *Type, et int) bool {
837 return t != nil && int(t.Etype) == et
Russ Cox8c195bd2015-02-13 14:40:36 -0500838}
839
Russ Coxdc7b54b2015-02-17 22:13:49 -0500840func Isfixedarray(t *Type) bool {
841 return t != nil && t.Etype == TARRAY && t.Bound >= 0
Russ Cox8c195bd2015-02-13 14:40:36 -0500842}
843
Russ Coxdc7b54b2015-02-17 22:13:49 -0500844func Isslice(t *Type) bool {
845 return t != nil && t.Etype == TARRAY && t.Bound < 0
Russ Cox8c195bd2015-02-13 14:40:36 -0500846}
847
848func isblank(n *Node) bool {
849 if n == nil {
850 return false
851 }
852 return isblanksym(n.Sym)
853}
854
855func isblanksym(s *Sym) bool {
856 return s != nil && s.Name == "_"
857}
858
Russ Coxdc7b54b2015-02-17 22:13:49 -0500859func Isinter(t *Type) bool {
860 return t != nil && t.Etype == TINTER
Russ Cox8c195bd2015-02-13 14:40:36 -0500861}
862
Russ Coxdc7b54b2015-02-17 22:13:49 -0500863func isnilinter(t *Type) bool {
864 if !Isinter(t) {
865 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500866 }
867 if t.Type != nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500868 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500869 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500870 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500871}
872
Russ Coxdc7b54b2015-02-17 22:13:49 -0500873func isideal(t *Type) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500874 if t == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500875 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500876 }
877 if t == idealstring || t == idealbool {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500878 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500879 }
880 switch t.Etype {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700881 case TNIL, TIDEAL:
Russ Coxdc7b54b2015-02-17 22:13:49 -0500882 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500883 }
884
Russ Coxdc7b54b2015-02-17 22:13:49 -0500885 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500886}
887
888/*
889 * given receiver of type t (t == r or t == *r)
890 * return type to hang methods off (r).
891 */
892func methtype(t *Type, mustname int) *Type {
893 if t == nil {
894 return nil
895 }
896
897 // strip away pointer if it's there
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000898 if Isptr[t.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500899 if t.Sym != nil {
900 return nil
901 }
902 t = t.Type
903 if t == nil {
904 return nil
905 }
906 }
907
908 // need a type name
909 if t.Sym == nil && (mustname != 0 || t.Etype != TSTRUCT) {
910 return nil
911 }
912
913 // check types
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000914 if !issimple[t.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500915 switch t.Etype {
916 default:
917 return nil
918
919 case TSTRUCT,
920 TARRAY,
921 TMAP,
922 TCHAN,
923 TSTRING,
924 TFUNC:
925 break
926 }
927 }
928
929 return t
930}
931
932func cplxsubtype(et int) int {
933 switch et {
934 case TCOMPLEX64:
935 return TFLOAT32
936
937 case TCOMPLEX128:
938 return TFLOAT64
939 }
940
941 Fatal("cplxsubtype: %v\n", Econv(int(et), 0))
942 return 0
943}
944
Russ Coxbed1f902015-03-02 16:03:26 -0500945func eqnote(a, b *string) bool {
946 return a == b || a != nil && b != nil && *a == *b
Russ Cox8c195bd2015-02-13 14:40:36 -0500947}
948
949type TypePairList struct {
950 t1 *Type
951 t2 *Type
952 next *TypePairList
953}
954
Russ Coxdc7b54b2015-02-17 22:13:49 -0500955func onlist(l *TypePairList, t1 *Type, t2 *Type) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500956 for ; l != nil; l = l.next {
957 if (l.t1 == t1 && l.t2 == t2) || (l.t1 == t2 && l.t2 == t1) {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500958 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500959 }
960 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500961 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500962}
963
964// Return 1 if t1 and t2 are identical, following the spec rules.
965//
966// Any cyclic type must go through a named type, and if one is
967// named, it is only identical to the other if they are the same
968// pointer (t1 == t2), so there's no chance of chasing cycles
969// ad infinitum, so no need for a depth counter.
970func Eqtype(t1 *Type, t2 *Type) bool {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500971 return eqtype1(t1, t2, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500972}
973
Russ Coxdc7b54b2015-02-17 22:13:49 -0500974func eqtype1(t1 *Type, t2 *Type, assumed_equal *TypePairList) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -0500975 if t1 == t2 {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500976 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500977 }
978 if t1 == nil || t2 == nil || t1.Etype != t2.Etype {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500979 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500980 }
981 if t1.Sym != nil || t2.Sym != nil {
982 // Special case: we keep byte and uint8 separate
983 // for error messages. Treat them as equal.
984 switch t1.Etype {
985 case TUINT8:
986 if (t1 == Types[TUINT8] || t1 == bytetype) && (t2 == Types[TUINT8] || t2 == bytetype) {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500987 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500988 }
989
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -0700990 case TINT, TINT32:
Russ Cox8c195bd2015-02-13 14:40:36 -0500991 if (t1 == Types[runetype.Etype] || t1 == runetype) && (t2 == Types[runetype.Etype] || t2 == runetype) {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500992 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500993 }
994 }
995
Russ Coxdc7b54b2015-02-17 22:13:49 -0500996 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500997 }
998
Russ Coxdc7b54b2015-02-17 22:13:49 -0500999 if onlist(assumed_equal, t1, t2) {
1000 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001001 }
Russ Cox382b44e2015-02-23 16:07:24 -05001002 var l TypePairList
Russ Cox8c195bd2015-02-13 14:40:36 -05001003 l.next = assumed_equal
1004 l.t1 = t1
1005 l.t2 = t2
1006
1007 switch t1.Etype {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001008 case TINTER, TSTRUCT:
Russ Cox8c195bd2015-02-13 14:40:36 -05001009 t1 = t1.Type
1010 t2 = t2.Type
Russ Coxd7f6d462015-03-09 00:31:13 -04001011 for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05001012 if t1.Etype != TFIELD || t2.Etype != TFIELD {
Russ Cox17228f42015-04-17 12:03:22 -04001013 Fatal("struct/interface missing field: %v %v", t1, t2)
Russ Cox8c195bd2015-02-13 14:40:36 -05001014 }
Russ Coxdc7b54b2015-02-17 22:13:49 -05001015 if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, &l) || !eqnote(t1.Note, t2.Note) {
Russ Cox79f727a2015-03-02 12:35:15 -05001016 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001017 }
1018 }
1019
1020 if t1 == nil && t2 == nil {
Russ Cox79f727a2015-03-02 12:35:15 -05001021 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001022 }
Russ Cox79f727a2015-03-02 12:35:15 -05001023 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001024
1025 // Loop over structs: receiver, in, out.
1026 case TFUNC:
1027 t1 = t1.Type
1028 t2 = t2.Type
Russ Coxd7f6d462015-03-09 00:31:13 -04001029 for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05001030 if t1.Etype != TSTRUCT || t2.Etype != TSTRUCT {
Russ Cox17228f42015-04-17 12:03:22 -04001031 Fatal("func missing struct: %v %v", t1, t2)
Russ Cox8c195bd2015-02-13 14:40:36 -05001032 }
1033
1034 // Loop over fields in structs, ignoring argument names.
Russ Coxc8198342015-03-12 18:45:30 -04001035 ta := t1.Type
1036 tb := t2.Type
Russ Coxd7f6d462015-03-09 00:31:13 -04001037 for ; ta != nil && tb != nil; ta, tb = ta.Down, tb.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05001038 if ta.Etype != TFIELD || tb.Etype != TFIELD {
Russ Cox17228f42015-04-17 12:03:22 -04001039 Fatal("func struct missing field: %v %v", ta, tb)
Russ Cox8c195bd2015-02-13 14:40:36 -05001040 }
Russ Coxdc7b54b2015-02-17 22:13:49 -05001041 if ta.Isddd != tb.Isddd || !eqtype1(ta.Type, tb.Type, &l) {
Russ Cox79f727a2015-03-02 12:35:15 -05001042 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001043 }
1044 }
1045
1046 if ta != nil || tb != nil {
Russ Cox79f727a2015-03-02 12:35:15 -05001047 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001048 }
1049 }
1050
1051 if t1 == nil && t2 == nil {
Russ Cox79f727a2015-03-02 12:35:15 -05001052 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001053 }
Russ Cox79f727a2015-03-02 12:35:15 -05001054 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001055
1056 case TARRAY:
1057 if t1.Bound != t2.Bound {
Russ Cox79f727a2015-03-02 12:35:15 -05001058 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001059 }
1060
1061 case TCHAN:
1062 if t1.Chan != t2.Chan {
Russ Cox79f727a2015-03-02 12:35:15 -05001063 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001064 }
1065 }
1066
Russ Coxdc7b54b2015-02-17 22:13:49 -05001067 if eqtype1(t1.Down, t2.Down, &l) && eqtype1(t1.Type, t2.Type, &l) {
Russ Cox79f727a2015-03-02 12:35:15 -05001068 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001069 }
Russ Coxdc7b54b2015-02-17 22:13:49 -05001070 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001071}
1072
1073// Are t1 and t2 equal struct types when field names are ignored?
1074// For deciding whether the result struct from g can be copied
1075// directly when compiling f(g()).
Russ Coxdc7b54b2015-02-17 22:13:49 -05001076func eqtypenoname(t1 *Type, t2 *Type) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05001077 if t1 == nil || t2 == nil || t1.Etype != TSTRUCT || t2.Etype != TSTRUCT {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001078 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001079 }
1080
1081 t1 = t1.Type
1082 t2 = t2.Type
1083 for {
1084 if !Eqtype(t1, t2) {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001085 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001086 }
1087 if t1 == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001088 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001089 }
1090 t1 = t1.Down
1091 t2 = t2.Down
1092 }
1093}
1094
1095// Is type src assignment compatible to type dst?
1096// If so, return op code to use in conversion.
1097// If not, return 0.
1098func assignop(src *Type, dst *Type, why *string) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05001099 if why != nil {
1100 *why = ""
1101 }
1102
1103 // TODO(rsc,lvd): This behaves poorly in the presence of inlining.
1104 // https://golang.org/issue/2795
1105 if safemode != 0 && importpkg == nil && src != nil && src.Etype == TUNSAFEPTR {
1106 Yyerror("cannot use unsafe.Pointer")
1107 errorexit()
1108 }
1109
1110 if src == dst {
1111 return OCONVNOP
1112 }
1113 if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil {
1114 return 0
1115 }
1116
1117 // 1. src type is identical to dst.
1118 if Eqtype(src, dst) {
1119 return OCONVNOP
1120 }
1121
1122 // 2. src and dst have identical underlying types
1123 // and either src or dst is not a named type or
1124 // both are empty interface types.
1125 // For assignable but different non-empty interface types,
1126 // we want to recompute the itab.
Russ Coxdc7b54b2015-02-17 22:13:49 -05001127 if Eqtype(src.Orig, dst.Orig) && (src.Sym == nil || dst.Sym == nil || isnilinter(src)) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001128 return OCONVNOP
1129 }
1130
1131 // 3. dst is an interface type and src implements dst.
1132 if dst.Etype == TINTER && src.Etype != TNIL {
Russ Cox382b44e2015-02-23 16:07:24 -05001133 var missing *Type
1134 var ptr int
1135 var have *Type
Russ Coxdc7b54b2015-02-17 22:13:49 -05001136 if implements(src, dst, &missing, &have, &ptr) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001137 return OCONVIFACE
1138 }
1139
1140 // we'll have complained about this method anyway, suppress spurious messages.
1141 if have != nil && have.Sym == missing.Sym && (have.Type.Broke != 0 || missing.Type.Broke != 0) {
1142 return OCONVIFACE
1143 }
1144
1145 if why != nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001146 if isptrto(src, TINTER) {
Russ Cox17228f42015-04-17 12:03:22 -04001147 *why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
Russ Coxdc7b54b2015-02-17 22:13:49 -05001148 } else if have != nil && have.Sym == missing.Sym && have.Nointerface {
Russ Cox17228f42015-04-17 12:03:22 -04001149 *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -05001150 } else if have != nil && have.Sym == missing.Sym {
Russ Cox17228f42015-04-17 12:03:22 -04001151 *why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", src, dst, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort|obj.FmtByte), missing.Sym, Tconv(missing.Type, obj.FmtShort|obj.FmtByte))
Russ Cox8c195bd2015-02-13 14:40:36 -05001152 } else if ptr != 0 {
Russ Cox17228f42015-04-17 12:03:22 -04001153 *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -05001154 } else if have != nil {
Russ Cox17228f42015-04-17 12:03:22 -04001155 *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", src, dst, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort|obj.FmtByte), missing.Sym, Tconv(missing.Type, obj.FmtShort|obj.FmtByte))
Russ Cox8c195bd2015-02-13 14:40:36 -05001156 } else {
Russ Cox17228f42015-04-17 12:03:22 -04001157 *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -05001158 }
1159 }
1160
1161 return 0
1162 }
1163
Russ Coxdc7b54b2015-02-17 22:13:49 -05001164 if isptrto(dst, TINTER) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001165 if why != nil {
Russ Cox17228f42015-04-17 12:03:22 -04001166 *why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
Russ Cox8c195bd2015-02-13 14:40:36 -05001167 }
1168 return 0
1169 }
1170
1171 if src.Etype == TINTER && dst.Etype != TBLANK {
Russ Cox382b44e2015-02-23 16:07:24 -05001172 var have *Type
1173 var ptr int
1174 var missing *Type
Russ Coxdc7b54b2015-02-17 22:13:49 -05001175 if why != nil && implements(dst, src, &missing, &have, &ptr) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001176 *why = ": need type assertion"
1177 }
1178 return 0
1179 }
1180
1181 // 4. src is a bidirectional channel value, dst is a channel type,
1182 // src and dst have identical element types, and
1183 // either src or dst is not a named type.
1184 if src.Etype == TCHAN && src.Chan == Cboth && dst.Etype == TCHAN {
1185 if Eqtype(src.Type, dst.Type) && (src.Sym == nil || dst.Sym == nil) {
1186 return OCONVNOP
1187 }
1188 }
1189
1190 // 5. src is the predeclared identifier nil and dst is a nillable type.
1191 if src.Etype == TNIL {
1192 switch dst.Etype {
1193 case TARRAY:
1194 if dst.Bound != -100 { // not slice
1195 break
1196 }
1197 fallthrough
1198
1199 case TPTR32,
1200 TPTR64,
1201 TFUNC,
1202 TMAP,
1203 TCHAN,
1204 TINTER:
1205 return OCONVNOP
1206 }
1207 }
1208
1209 // 6. rule about untyped constants - already converted by defaultlit.
1210
1211 // 7. Any typed value can be assigned to the blank identifier.
1212 if dst.Etype == TBLANK {
1213 return OCONVNOP
1214 }
1215
1216 return 0
1217}
1218
1219// Can we convert a value of type src to a value of type dst?
1220// If so, return op code to use in conversion (maybe OCONVNOP).
1221// If not, return 0.
1222func convertop(src *Type, dst *Type, why *string) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05001223 if why != nil {
1224 *why = ""
1225 }
1226
1227 if src == dst {
1228 return OCONVNOP
1229 }
1230 if src == nil || dst == nil {
1231 return 0
1232 }
1233
1234 // 1. src can be assigned to dst.
Russ Cox382b44e2015-02-23 16:07:24 -05001235 op := assignop(src, dst, why)
Russ Cox8c195bd2015-02-13 14:40:36 -05001236 if op != 0 {
1237 return op
1238 }
1239
1240 // The rules for interfaces are no different in conversions
1241 // than assignments. If interfaces are involved, stop now
1242 // with the good message from assignop.
1243 // Otherwise clear the error.
1244 if src.Etype == TINTER || dst.Etype == TINTER {
1245 return 0
1246 }
1247 if why != nil {
1248 *why = ""
1249 }
1250
1251 // 2. src and dst have identical underlying types.
1252 if Eqtype(src.Orig, dst.Orig) {
1253 return OCONVNOP
1254 }
1255
1256 // 3. src and dst are unnamed pointer types
1257 // and their base types have identical underlying types.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001258 if Isptr[src.Etype] && Isptr[dst.Etype] && src.Sym == nil && dst.Sym == nil {
Russ Cox8c195bd2015-02-13 14:40:36 -05001259 if Eqtype(src.Type.Orig, dst.Type.Orig) {
1260 return OCONVNOP
1261 }
1262 }
1263
1264 // 4. src and dst are both integer or floating point types.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001265 if (Isint[src.Etype] || Isfloat[src.Etype]) && (Isint[dst.Etype] || Isfloat[dst.Etype]) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001266 if Simtype[src.Etype] == Simtype[dst.Etype] {
1267 return OCONVNOP
1268 }
1269 return OCONV
1270 }
1271
1272 // 5. src and dst are both complex types.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001273 if Iscomplex[src.Etype] && Iscomplex[dst.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05001274 if Simtype[src.Etype] == Simtype[dst.Etype] {
1275 return OCONVNOP
1276 }
1277 return OCONV
1278 }
1279
1280 // 6. src is an integer or has type []byte or []rune
1281 // and dst is a string type.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001282 if Isint[src.Etype] && dst.Etype == TSTRING {
Russ Cox8c195bd2015-02-13 14:40:36 -05001283 return ORUNESTR
1284 }
1285
Russ Coxdc7b54b2015-02-17 22:13:49 -05001286 if Isslice(src) && dst.Etype == TSTRING {
Russ Cox8c195bd2015-02-13 14:40:36 -05001287 if src.Type.Etype == bytetype.Etype {
1288 return OARRAYBYTESTR
1289 }
1290 if src.Type.Etype == runetype.Etype {
1291 return OARRAYRUNESTR
1292 }
1293 }
1294
1295 // 7. src is a string and dst is []byte or []rune.
1296 // String to slice.
Russ Coxdc7b54b2015-02-17 22:13:49 -05001297 if src.Etype == TSTRING && Isslice(dst) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001298 if dst.Type.Etype == bytetype.Etype {
1299 return OSTRARRAYBYTE
1300 }
1301 if dst.Type.Etype == runetype.Etype {
1302 return OSTRARRAYRUNE
1303 }
1304 }
1305
1306 // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001307 if (Isptr[src.Etype] || src.Etype == TUINTPTR) && dst.Etype == TUNSAFEPTR {
Russ Cox8c195bd2015-02-13 14:40:36 -05001308 return OCONVNOP
1309 }
1310
1311 // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001312 if src.Etype == TUNSAFEPTR && (Isptr[dst.Etype] || dst.Etype == TUINTPTR) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001313 return OCONVNOP
1314 }
1315
1316 return 0
1317}
1318
Russ Cox8c195bd2015-02-13 14:40:36 -05001319func assignconv(n *Node, t *Type, context string) *Node {
Russ Coxc8198342015-03-12 18:45:30 -04001320 return assignconvfn(n, t, func() string { return context })
1321}
1322
1323// Convert node n for assignment to type t.
1324func assignconvfn(n *Node, t *Type, context func() string) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05001325 if n == nil || n.Type == nil || n.Type.Broke != 0 {
1326 return n
1327 }
1328
1329 if t.Etype == TBLANK && n.Type.Etype == TNIL {
1330 Yyerror("use of untyped nil")
1331 }
1332
Russ Cox382b44e2015-02-23 16:07:24 -05001333 old := n
Russ Cox8c195bd2015-02-13 14:40:36 -05001334 old.Diag++ // silence errors about n; we'll issue one below
1335 defaultlit(&n, t)
1336 old.Diag--
1337 if t.Etype == TBLANK {
1338 return n
1339 }
1340
1341 // Convert ideal bool from comparison to plain bool
1342 // if the next step is non-bool (like interface{}).
1343 if n.Type == idealbool && t.Etype != TBOOL {
1344 if n.Op == ONAME || n.Op == OLITERAL {
Russ Cox382b44e2015-02-23 16:07:24 -05001345 r := Nod(OCONVNOP, n, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001346 r.Type = Types[TBOOL]
1347 r.Typecheck = 1
Dave Cheney44e90312015-03-06 21:18:41 +11001348 r.Implicit = true
Russ Cox8c195bd2015-02-13 14:40:36 -05001349 n = r
1350 }
1351 }
1352
1353 if Eqtype(n.Type, t) {
1354 return n
1355 }
1356
Russ Cox382b44e2015-02-23 16:07:24 -05001357 var why string
1358 op := assignop(n.Type, t, &why)
Russ Cox8c195bd2015-02-13 14:40:36 -05001359 if op == 0 {
Russ Cox17228f42015-04-17 12:03:22 -04001360 Yyerror("cannot use %v as type %v in %s%s", Nconv(n, obj.FmtLong), t, context(), why)
Russ Cox8c195bd2015-02-13 14:40:36 -05001361 op = OCONV
1362 }
1363
Russ Cox382b44e2015-02-23 16:07:24 -05001364 r := Nod(op, n, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001365 r.Type = t
1366 r.Typecheck = 1
Dave Cheney44e90312015-03-06 21:18:41 +11001367 r.Implicit = true
Russ Cox8c195bd2015-02-13 14:40:36 -05001368 r.Orig = n.Orig
1369 return r
1370}
1371
Russ Cox13f9c8b2015-03-08 13:33:49 -04001372// substArgTypes substitutes the given list of types for
1373// successive occurrences of the "any" placeholder in the
1374// type syntax expression n.Type.
1375func substArgTypes(n *Node, types ...*Type) {
1376 for _, t := range types {
1377 dowidth(t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001378 }
Russ Cox13f9c8b2015-03-08 13:33:49 -04001379 substAny(&n.Type, &types)
1380 if len(types) > 0 {
1381 Fatal("substArgTypes: too many argument types")
Russ Cox8c195bd2015-02-13 14:40:36 -05001382 }
Russ Cox13f9c8b2015-03-08 13:33:49 -04001383}
Russ Cox8c195bd2015-02-13 14:40:36 -05001384
Russ Cox13f9c8b2015-03-08 13:33:49 -04001385// substAny walks *tp, replacing instances of "any" with successive
1386// elements removed from types.
1387func substAny(tp **Type, types *[]*Type) {
1388 for {
1389 t := *tp
1390 if t == nil {
1391 return
Russ Cox8c195bd2015-02-13 14:40:36 -05001392 }
Russ Cox13f9c8b2015-03-08 13:33:49 -04001393 if t.Etype == TANY && t.Copyany != 0 {
1394 if len(*types) == 0 {
1395 Fatal("substArgTypes: not enough argument types")
Russ Cox8c195bd2015-02-13 14:40:36 -05001396 }
Russ Cox13f9c8b2015-03-08 13:33:49 -04001397 *tp = (*types)[0]
1398 *types = (*types)[1:]
Russ Cox8c195bd2015-02-13 14:40:36 -05001399 }
1400
Russ Cox13f9c8b2015-03-08 13:33:49 -04001401 switch t.Etype {
1402 case TPTR32, TPTR64, TCHAN, TARRAY:
1403 tp = &t.Type
1404 continue
1405
1406 case TMAP:
1407 substAny(&t.Down, types)
1408 tp = &t.Type
1409 continue
1410
1411 case TFUNC:
1412 substAny(&t.Type, types)
1413 substAny(&t.Type.Down.Down, types)
1414 substAny(&t.Type.Down, types)
1415
1416 case TSTRUCT:
1417 for t = t.Type; t != nil; t = t.Down {
1418 substAny(&t.Type, types)
Russ Cox8c195bd2015-02-13 14:40:36 -05001419 }
1420 }
Russ Cox13f9c8b2015-03-08 13:33:49 -04001421 return
Russ Cox8c195bd2015-02-13 14:40:36 -05001422 }
Russ Cox8c195bd2015-02-13 14:40:36 -05001423}
1424
1425/*
1426 * Is this a 64-bit type?
1427 */
Russ Coxdc7b54b2015-02-17 22:13:49 -05001428func Is64(t *Type) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05001429 if t == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001430 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001431 }
1432 switch Simtype[t.Etype] {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001433 case TINT64, TUINT64, TPTR64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001434 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001435 }
1436
Russ Coxdc7b54b2015-02-17 22:13:49 -05001437 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001438}
1439
1440/*
1441 * Is a conversion between t1 and t2 a no-op?
1442 */
Russ Coxdc7b54b2015-02-17 22:13:49 -05001443func Noconv(t1 *Type, t2 *Type) bool {
Russ Cox382b44e2015-02-23 16:07:24 -05001444 e1 := int(Simtype[t1.Etype])
1445 e2 := int(Simtype[t2.Etype])
Russ Cox8c195bd2015-02-13 14:40:36 -05001446
1447 switch e1 {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001448 case TINT8, TUINT8:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001449 return e2 == TINT8 || e2 == TUINT8
Russ Cox8c195bd2015-02-13 14:40:36 -05001450
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001451 case TINT16, TUINT16:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001452 return e2 == TINT16 || e2 == TUINT16
Russ Cox8c195bd2015-02-13 14:40:36 -05001453
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001454 case TINT32, TUINT32, TPTR32:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001455 return e2 == TINT32 || e2 == TUINT32 || e2 == TPTR32
Russ Cox8c195bd2015-02-13 14:40:36 -05001456
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001457 case TINT64, TUINT64, TPTR64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001458 return e2 == TINT64 || e2 == TUINT64 || e2 == TPTR64
Russ Cox8c195bd2015-02-13 14:40:36 -05001459
1460 case TFLOAT32:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001461 return e2 == TFLOAT32
Russ Cox8c195bd2015-02-13 14:40:36 -05001462
1463 case TFLOAT64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001464 return e2 == TFLOAT64
Russ Cox8c195bd2015-02-13 14:40:36 -05001465 }
1466
Russ Coxdc7b54b2015-02-17 22:13:49 -05001467 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001468}
1469
Russ Cox8c195bd2015-02-13 14:40:36 -05001470func shallow(t *Type) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -05001471 if t == nil {
1472 return nil
1473 }
Russ Cox382b44e2015-02-23 16:07:24 -05001474 nt := typ(0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001475 *nt = *t
1476 if t.Orig == t {
1477 nt.Orig = nt
1478 }
1479 return nt
1480}
1481
1482func deep(t *Type) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -05001483 if t == nil {
1484 return nil
1485 }
1486
Russ Cox382b44e2015-02-23 16:07:24 -05001487 var nt *Type
Russ Cox8c195bd2015-02-13 14:40:36 -05001488 switch t.Etype {
1489 default:
1490 nt = t // share from here down
1491
1492 case TANY:
1493 nt = shallow(t)
1494 nt.Copyany = 1
1495
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001496 case TPTR32, TPTR64, TCHAN, TARRAY:
Russ Cox8c195bd2015-02-13 14:40:36 -05001497 nt = shallow(t)
1498 nt.Type = deep(t.Type)
1499
1500 case TMAP:
1501 nt = shallow(t)
1502 nt.Down = deep(t.Down)
1503 nt.Type = deep(t.Type)
1504
1505 case TFUNC:
1506 nt = shallow(t)
1507 nt.Type = deep(t.Type)
1508 nt.Type.Down = deep(t.Type.Down)
1509 nt.Type.Down.Down = deep(t.Type.Down.Down)
1510
1511 case TSTRUCT:
1512 nt = shallow(t)
1513 nt.Type = shallow(t.Type)
Russ Cox382b44e2015-02-23 16:07:24 -05001514 xt := nt.Type
Russ Cox8c195bd2015-02-13 14:40:36 -05001515
1516 for t = t.Type; t != nil; t = t.Down {
1517 xt.Type = deep(t.Type)
1518 xt.Down = shallow(t.Down)
1519 xt = xt.Down
1520 }
1521 }
1522
1523 return nt
1524}
1525
1526func syslook(name string, copy int) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -05001527 s := Pkglookup(name, Runtimepkg)
Russ Cox8c195bd2015-02-13 14:40:36 -05001528 if s == nil || s.Def == nil {
1529 Fatal("syslook: can't find runtime.%s", name)
1530 }
1531
Russ Coxdc7b54b2015-02-17 22:13:49 -05001532 if copy == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001533 return s.Def
1534 }
1535
Russ Cox382b44e2015-02-23 16:07:24 -05001536 n := Nod(0, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001537 *n = *s.Def
1538 n.Type = deep(s.Def.Type)
1539
1540 return n
1541}
1542
1543/*
1544 * compute a hash value for type t.
1545 * if t is a method type, ignore the receiver
1546 * so that the hash can be used in interface checks.
1547 * %T already contains
1548 * all the necessary logic to generate a representation
1549 * of the type that completely describes it.
1550 * using smprint here avoids duplicating that code.
1551 * using md5 here is overkill, but i got tired of
1552 * accidental collisions making the runtime think
1553 * two types are equal when they really aren't.
1554 */
1555func typehash(t *Type) uint32 {
1556 var p string
Russ Cox8c195bd2015-02-13 14:40:36 -05001557
1558 if t.Thistuple != 0 {
1559 // hide method receiver from Tpretty
1560 t.Thistuple = 0
1561
Russ Coxc8198342015-03-12 18:45:30 -04001562 p = Tconv(t, obj.FmtLeft|obj.FmtUnsigned)
Russ Cox8c195bd2015-02-13 14:40:36 -05001563 t.Thistuple = 1
1564 } else {
Russ Coxc8198342015-03-12 18:45:30 -04001565 p = Tconv(t, obj.FmtLeft|obj.FmtUnsigned)
Russ Cox8c195bd2015-02-13 14:40:36 -05001566 }
1567
1568 //print("typehash: %s\n", p);
Matthew Dempsky392434e2015-02-27 16:05:30 +09001569 h := md5.Sum([]byte(p))
1570 return binary.LittleEndian.Uint32(h[:4])
Russ Cox8c195bd2015-02-13 14:40:36 -05001571}
1572
Josh Bleecher Snydere64764c2015-04-28 17:08:28 -07001573var initPtrtoDone bool
1574
1575var (
1576 ptrToUint8 *Type
1577 ptrToAny *Type
1578 ptrToString *Type
1579 ptrToBool *Type
1580 ptrToInt32 *Type
1581)
1582
1583func initPtrto() {
1584 ptrToUint8 = ptrto1(Types[TUINT8])
1585 ptrToAny = ptrto1(Types[TANY])
1586 ptrToString = ptrto1(Types[TSTRING])
1587 ptrToBool = ptrto1(Types[TBOOL])
1588 ptrToInt32 = ptrto1(Types[TINT32])
1589}
1590
1591func ptrto1(t *Type) *Type {
Russ Cox382b44e2015-02-23 16:07:24 -05001592 t1 := typ(Tptr)
Russ Cox8c195bd2015-02-13 14:40:36 -05001593 t1.Type = t
1594 t1.Width = int64(Widthptr)
1595 t1.Align = uint8(Widthptr)
1596 return t1
1597}
1598
Josh Bleecher Snydere64764c2015-04-28 17:08:28 -07001599// Ptrto returns the Type *t.
1600// The returned struct must not be modified.
1601func Ptrto(t *Type) *Type {
1602 if Tptr == 0 {
1603 Fatal("ptrto: no tptr")
1604 }
1605 // Reduce allocations by pre-creating common cases.
1606 if !initPtrtoDone {
1607 initPtrto()
1608 initPtrtoDone = true
1609 }
1610 switch t {
1611 case Types[TUINT8]:
1612 return ptrToUint8
1613 case Types[TINT32]:
1614 return ptrToInt32
1615 case Types[TANY]:
1616 return ptrToAny
1617 case Types[TSTRING]:
1618 return ptrToString
1619 case Types[TBOOL]:
1620 return ptrToBool
1621 }
1622 return ptrto1(t)
1623}
1624
Russ Cox8c195bd2015-02-13 14:40:36 -05001625func frame(context int) {
1626 var l *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -05001627
1628 if context != 0 {
1629 fmt.Printf("--- external frame ---\n")
1630 l = externdcl
1631 } else if Curfn != nil {
Russ Coxbd4fff62015-05-27 10:42:55 -04001632 fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -07001633 l = Curfn.Func.Dcl
Russ Cox8c195bd2015-02-13 14:40:36 -05001634 } else {
1635 return
1636 }
1637
Russ Cox382b44e2015-02-23 16:07:24 -05001638 var n *Node
1639 var w int64
Russ Cox8c195bd2015-02-13 14:40:36 -05001640 for ; l != nil; l = l.Next {
1641 n = l.N
1642 w = -1
1643 if n.Type != nil {
1644 w = n.Type.Width
1645 }
1646 switch n.Op {
1647 case ONAME:
Russ Cox11322d42015-05-26 23:56:14 -04001648 fmt.Printf("%v %v G%d %v width=%d\n", Oconv(int(n.Op), 0), n.Sym, n.Name.Vargen, n.Type, w)
Russ Cox8c195bd2015-02-13 14:40:36 -05001649
1650 case OTYPE:
Russ Cox17228f42015-04-17 12:03:22 -04001651 fmt.Printf("%v %v width=%d\n", Oconv(int(n.Op), 0), n.Type, w)
Russ Cox8c195bd2015-02-13 14:40:36 -05001652 }
1653 }
1654}
1655
1656/*
1657 * calculate sethi/ullman number
1658 * roughly how many registers needed to
1659 * compile a node. used to compile the
1660 * hardest side first to minimize registers.
1661 */
1662func ullmancalc(n *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001663 if n == nil {
1664 return
1665 }
1666
Russ Cox382b44e2015-02-23 16:07:24 -05001667 var ul int
1668 var ur int
Russ Cox8c195bd2015-02-13 14:40:36 -05001669 if n.Ninit != nil {
1670 ul = UINF
1671 goto out
1672 }
1673
1674 switch n.Op {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001675 case OREGISTER, OLITERAL, ONAME:
Russ Cox8c195bd2015-02-13 14:40:36 -05001676 ul = 1
1677 if n.Class == PPARAMREF || (n.Class&PHEAP != 0) {
1678 ul++
1679 }
1680 goto out
1681
Russ Cox0ad4f8b2015-04-17 00:25:10 -04001682 case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OASWB:
Russ Cox8c195bd2015-02-13 14:40:36 -05001683 ul = UINF
1684 goto out
1685
1686 // hard with race detector
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001687 case OANDAND, OOROR:
Russ Cox8c195bd2015-02-13 14:40:36 -05001688 if flag_race != 0 {
1689 ul = UINF
1690 goto out
1691 }
1692 }
1693
1694 ul = 1
1695 if n.Left != nil {
1696 ul = int(n.Left.Ullman)
1697 }
1698 ur = 1
1699 if n.Right != nil {
1700 ur = int(n.Right.Ullman)
1701 }
1702 if ul == ur {
1703 ul += 1
1704 }
1705 if ur > ul {
1706 ul = ur
1707 }
1708
1709out:
1710 if ul > 200 {
1711 ul = 200 // clamp to uchar with room to grow
1712 }
1713 n.Ullman = uint8(ul)
1714}
1715
1716func badtype(o int, tl *Type, tr *Type) {
Russ Cox382b44e2015-02-23 16:07:24 -05001717 fmt_ := ""
Russ Cox8c195bd2015-02-13 14:40:36 -05001718 if tl != nil {
Russ Cox17228f42015-04-17 12:03:22 -04001719 fmt_ += fmt.Sprintf("\n\t%v", tl)
Russ Cox8c195bd2015-02-13 14:40:36 -05001720 }
1721 if tr != nil {
Russ Cox17228f42015-04-17 12:03:22 -04001722 fmt_ += fmt.Sprintf("\n\t%v", tr)
Russ Cox8c195bd2015-02-13 14:40:36 -05001723 }
1724
1725 // common mistake: *struct and *interface.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001726 if tl != nil && tr != nil && Isptr[tl.Etype] && Isptr[tr.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05001727 if tl.Type.Etype == TSTRUCT && tr.Type.Etype == TINTER {
Josh Bleecher Snyder05ca0f32015-02-28 20:31:32 +00001728 fmt_ += "\n\t(*struct vs *interface)"
Russ Cox8c195bd2015-02-13 14:40:36 -05001729 } else if tl.Type.Etype == TINTER && tr.Type.Etype == TSTRUCT {
Josh Bleecher Snyder05ca0f32015-02-28 20:31:32 +00001730 fmt_ += "\n\t(*interface vs *struct)"
Russ Cox8c195bd2015-02-13 14:40:36 -05001731 }
1732 }
1733
Russ Cox382b44e2015-02-23 16:07:24 -05001734 s := fmt_
Russ Cox8c195bd2015-02-13 14:40:36 -05001735 Yyerror("illegal types for operand: %v%s", Oconv(int(o), 0), s)
1736}
1737
1738/*
1739 * iterator to walk a structure declaration
1740 */
1741func Structfirst(s *Iter, nn **Type) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -05001742 var t *Type
1743
Russ Cox382b44e2015-02-23 16:07:24 -05001744 n := *nn
Russ Cox8c195bd2015-02-13 14:40:36 -05001745 if n == nil {
1746 goto bad
1747 }
1748
1749 switch n.Etype {
1750 default:
1751 goto bad
1752
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001753 case TSTRUCT, TINTER, TFUNC:
Russ Cox8c195bd2015-02-13 14:40:36 -05001754 break
1755 }
1756
1757 t = n.Type
1758 if t == nil {
Russ Cox79f727a2015-03-02 12:35:15 -05001759 return nil
Russ Cox8c195bd2015-02-13 14:40:36 -05001760 }
1761
1762 if t.Etype != TFIELD {
Russ Cox17228f42015-04-17 12:03:22 -04001763 Fatal("structfirst: not field %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001764 }
1765
1766 s.T = t
1767 return t
1768
1769bad:
Russ Cox17228f42015-04-17 12:03:22 -04001770 Fatal("structfirst: not struct %v", n)
Russ Cox8c195bd2015-02-13 14:40:36 -05001771
Russ Cox8c195bd2015-02-13 14:40:36 -05001772 return nil
1773}
1774
1775func structnext(s *Iter) *Type {
Russ Cox382b44e2015-02-23 16:07:24 -05001776 n := s.T
1777 t := n.Down
Russ Cox8c195bd2015-02-13 14:40:36 -05001778 if t == nil {
Russ Cox79f727a2015-03-02 12:35:15 -05001779 return nil
Russ Cox8c195bd2015-02-13 14:40:36 -05001780 }
1781
1782 if t.Etype != TFIELD {
Russ Cox17228f42015-04-17 12:03:22 -04001783 Fatal("structnext: not struct %v", n)
Russ Cox79f727a2015-03-02 12:35:15 -05001784
1785 return nil
Russ Cox8c195bd2015-02-13 14:40:36 -05001786 }
1787
1788 s.T = t
1789 return t
Russ Cox8c195bd2015-02-13 14:40:36 -05001790}
1791
1792/*
1793 * iterator to this and inargs in a function
1794 */
1795func funcfirst(s *Iter, t *Type) *Type {
1796 var fp *Type
1797
1798 if t == nil {
1799 goto bad
1800 }
1801
1802 if t.Etype != TFUNC {
1803 goto bad
1804 }
1805
1806 s.Tfunc = t
1807 s.Done = 0
1808 fp = Structfirst(s, getthis(t))
1809 if fp == nil {
1810 s.Done = 1
1811 fp = Structfirst(s, getinarg(t))
1812 }
1813
1814 return fp
1815
1816bad:
Russ Cox17228f42015-04-17 12:03:22 -04001817 Fatal("funcfirst: not func %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001818 return nil
1819}
1820
1821func funcnext(s *Iter) *Type {
Russ Cox382b44e2015-02-23 16:07:24 -05001822 fp := structnext(s)
Russ Coxdc7b54b2015-02-17 22:13:49 -05001823 if fp == nil && s.Done == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001824 s.Done = 1
1825 fp = Structfirst(s, getinarg(s.Tfunc))
1826 }
1827
1828 return fp
1829}
1830
1831func getthis(t *Type) **Type {
1832 if t.Etype != TFUNC {
Russ Cox17228f42015-04-17 12:03:22 -04001833 Fatal("getthis: not a func %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001834 }
1835 return &t.Type
1836}
1837
1838func Getoutarg(t *Type) **Type {
1839 if t.Etype != TFUNC {
Russ Cox17228f42015-04-17 12:03:22 -04001840 Fatal("getoutarg: not a func %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001841 }
1842 return &t.Type.Down
1843}
1844
1845func getinarg(t *Type) **Type {
1846 if t.Etype != TFUNC {
Russ Cox17228f42015-04-17 12:03:22 -04001847 Fatal("getinarg: not a func %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001848 }
1849 return &t.Type.Down.Down
1850}
1851
1852func getthisx(t *Type) *Type {
1853 return *getthis(t)
1854}
1855
1856func getoutargx(t *Type) *Type {
1857 return *Getoutarg(t)
1858}
1859
1860func getinargx(t *Type) *Type {
1861 return *getinarg(t)
1862}
1863
Josh Bleecher Snyder4a7e5bc2015-04-06 19:36:36 -07001864// Brcom returns !(op).
1865// For example, Brcom(==) is !=.
Russ Cox8c195bd2015-02-13 14:40:36 -05001866func Brcom(a int) int {
1867 switch a {
1868 case OEQ:
1869 return ONE
1870 case ONE:
1871 return OEQ
1872 case OLT:
1873 return OGE
1874 case OGT:
1875 return OLE
1876 case OLE:
1877 return OGT
1878 case OGE:
1879 return OLT
1880 }
Josh Bleecher Snyder4a7e5bc2015-04-06 19:36:36 -07001881 Fatal("brcom: no com for %v\n", Oconv(a, 0))
Russ Cox8c195bd2015-02-13 14:40:36 -05001882 return a
1883}
1884
Josh Bleecher Snyder4a7e5bc2015-04-06 19:36:36 -07001885// Brrev returns reverse(op).
1886// For example, Brrev(<) is >.
Russ Cox8c195bd2015-02-13 14:40:36 -05001887func Brrev(a int) int {
1888 switch a {
1889 case OEQ:
1890 return OEQ
1891 case ONE:
1892 return ONE
1893 case OLT:
1894 return OGT
1895 case OGT:
1896 return OLT
1897 case OLE:
1898 return OGE
1899 case OGE:
1900 return OLE
1901 }
Josh Bleecher Snyder4a7e5bc2015-04-06 19:36:36 -07001902 Fatal("brrev: no rev for %v\n", Oconv(a, 0))
Russ Cox8c195bd2015-02-13 14:40:36 -05001903 return a
1904}
1905
1906/*
1907 * return side effect-free n, appending side effects to init.
1908 * result is assignable if n is.
1909 */
1910func safeexpr(n *Node, init **NodeList) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05001911 if n == nil {
1912 return nil
1913 }
1914
1915 if n.Ninit != nil {
1916 walkstmtlist(n.Ninit)
1917 *init = concat(*init, n.Ninit)
1918 n.Ninit = nil
1919 }
1920
1921 switch n.Op {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001922 case ONAME, OLITERAL:
Russ Cox8c195bd2015-02-13 14:40:36 -05001923 return n
1924
Russ Coxd4472792015-05-06 12:35:53 -04001925 case ODOT, OLEN, OCAP:
Russ Cox382b44e2015-02-23 16:07:24 -05001926 l := safeexpr(n.Left, init)
Russ Cox8c195bd2015-02-13 14:40:36 -05001927 if l == n.Left {
1928 return n
1929 }
Russ Cox382b44e2015-02-23 16:07:24 -05001930 r := Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001931 *r = *n
1932 r.Left = l
1933 typecheck(&r, Erv)
1934 walkexpr(&r, init)
1935 return r
1936
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001937 case ODOTPTR, OIND:
Russ Cox382b44e2015-02-23 16:07:24 -05001938 l := safeexpr(n.Left, init)
Russ Cox8c195bd2015-02-13 14:40:36 -05001939 if l == n.Left {
1940 return n
1941 }
Russ Cox382b44e2015-02-23 16:07:24 -05001942 a := Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001943 *a = *n
1944 a.Left = l
1945 walkexpr(&a, init)
1946 return a
1947
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001948 case OINDEX, OINDEXMAP:
Russ Cox382b44e2015-02-23 16:07:24 -05001949 l := safeexpr(n.Left, init)
1950 r := safeexpr(n.Right, init)
Russ Cox8c195bd2015-02-13 14:40:36 -05001951 if l == n.Left && r == n.Right {
1952 return n
1953 }
Russ Cox382b44e2015-02-23 16:07:24 -05001954 a := Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001955 *a = *n
1956 a.Left = l
1957 a.Right = r
1958 walkexpr(&a, init)
1959 return a
1960 }
1961
1962 // make a copy; must not be used as an lvalue
Russ Coxdc7b54b2015-02-17 22:13:49 -05001963 if islvalue(n) {
Russ Cox17228f42015-04-17 12:03:22 -04001964 Fatal("missing lvalue case in safeexpr: %v", n)
Russ Cox8c195bd2015-02-13 14:40:36 -05001965 }
1966 return cheapexpr(n, init)
1967}
1968
1969func copyexpr(n *Node, t *Type, init **NodeList) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -05001970 l := temp(t)
1971 a := Nod(OAS, l, n)
Russ Cox8c195bd2015-02-13 14:40:36 -05001972 typecheck(&a, Etop)
1973 walkexpr(&a, init)
1974 *init = list(*init, a)
1975 return l
1976}
1977
1978/*
1979 * return side-effect free and cheap n, appending side effects to init.
1980 * result may not be assignable.
1981 */
1982func cheapexpr(n *Node, init **NodeList) *Node {
1983 switch n.Op {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07001984 case ONAME, OLITERAL:
Russ Cox8c195bd2015-02-13 14:40:36 -05001985 return n
1986 }
1987
1988 return copyexpr(n, n.Type, init)
1989}
1990
1991/*
1992 * return n in a local variable of type t if it is not already.
1993 * the value is guaranteed not to change except by direct
1994 * assignment to it.
1995 */
1996func localexpr(n *Node, t *Type, init **NodeList) *Node {
Dave Cheney7885de52015-03-05 18:20:54 +11001997 if n.Op == ONAME && (!n.Addrtaken || strings.HasPrefix(n.Sym.Name, "autotmp_")) && (n.Class == PAUTO || n.Class == PPARAM || n.Class == PPARAMOUT) && convertop(n.Type, t, nil) == OCONVNOP {
Russ Cox8c195bd2015-02-13 14:40:36 -05001998 return n
1999 }
2000
2001 return copyexpr(n, t, init)
2002}
2003
2004func Setmaxarg(t *Type, extra int32) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002005 dowidth(t)
Russ Cox382b44e2015-02-23 16:07:24 -05002006 w := t.Argwid
Russ Cox8c195bd2015-02-13 14:40:36 -05002007 if w >= Thearch.MAXWIDTH {
Russ Cox17228f42015-04-17 12:03:22 -04002008 Fatal("bad argwid %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002009 }
2010 w += int64(extra)
2011 if w >= Thearch.MAXWIDTH {
Russ Cox17228f42015-04-17 12:03:22 -04002012 Fatal("bad argwid %d + %v", extra, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002013 }
2014 if w > Maxarg {
2015 Maxarg = w
2016 }
2017}
2018
2019/*
2020 * unicode-aware case-insensitive strcmp
2021 */
2022
2023/*
2024 * code to resolve elided DOTs
2025 * in embedded types
2026 */
2027
2028// search depth 0 --
2029// return count of fields+methods
2030// found with a given name
2031func lookdot0(s *Sym, t *Type, save **Type, ignorecase int) int {
Russ Cox382b44e2015-02-23 16:07:24 -05002032 u := t
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002033 if Isptr[u.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002034 u = u.Type
2035 }
2036
Russ Cox382b44e2015-02-23 16:07:24 -05002037 c := 0
Russ Cox8c195bd2015-02-13 14:40:36 -05002038 if u.Etype == TSTRUCT || u.Etype == TINTER {
Russ Cox382b44e2015-02-23 16:07:24 -05002039 for f := u.Type; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002040 if f.Sym == s || (ignorecase != 0 && f.Type.Etype == TFUNC && f.Type.Thistuple > 0 && strings.EqualFold(f.Sym.Name, s.Name)) {
2041 if save != nil {
2042 *save = f
2043 }
2044 c++
2045 }
2046 }
2047 }
2048
2049 u = methtype(t, 0)
2050 if u != nil {
Russ Cox382b44e2015-02-23 16:07:24 -05002051 for f := u.Method; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002052 if f.Embedded == 0 && (f.Sym == s || (ignorecase != 0 && strings.EqualFold(f.Sym.Name, s.Name))) {
2053 if save != nil {
2054 *save = f
2055 }
2056 c++
2057 }
2058 }
2059 }
2060
2061 return c
2062}
2063
2064// search depth d for field/method s --
2065// return count of fields+methods
2066// found at search depth.
2067// answer is in dotlist array and
2068// count of number of ways is returned.
2069func adddot1(s *Sym, t *Type, d int, save **Type, ignorecase int) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05002070 if t.Trecur != 0 {
2071 return 0
2072 }
2073 t.Trecur = 1
2074
Russ Cox382b44e2015-02-23 16:07:24 -05002075 var c int
2076 var u *Type
2077 var a int
Russ Cox8c195bd2015-02-13 14:40:36 -05002078 if d == 0 {
2079 c = lookdot0(s, t, save, ignorecase)
2080 goto out
2081 }
2082
2083 c = 0
2084 u = t
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002085 if Isptr[u.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002086 u = u.Type
2087 }
2088 if u.Etype != TSTRUCT && u.Etype != TINTER {
2089 goto out
2090 }
2091
2092 d--
Russ Cox382b44e2015-02-23 16:07:24 -05002093 for f := u.Type; f != nil; f = f.Down {
Russ Coxdc7b54b2015-02-17 22:13:49 -05002094 if f.Embedded == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05002095 continue
2096 }
2097 if f.Sym == nil {
2098 continue
2099 }
2100 a = adddot1(s, f.Type, d, save, ignorecase)
2101 if a != 0 && c == 0 {
2102 dotlist[d].field = f
2103 }
2104 c += a
2105 }
2106
2107out:
2108 t.Trecur = 0
2109 return c
2110}
2111
2112// in T.field
2113// find missing fields that
2114// will give shortest unique addressing.
2115// modify the tree with missing type names.
2116func adddot(n *Node) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05002117 typecheck(&n.Left, Etype|Erv)
2118 n.Diag |= n.Left.Diag
Russ Cox382b44e2015-02-23 16:07:24 -05002119 t := n.Left.Type
Russ Cox8c195bd2015-02-13 14:40:36 -05002120 if t == nil {
Russ Cox8c195bd2015-02-13 14:40:36 -05002121 return n
2122 }
2123
Russ Cox79f727a2015-03-02 12:35:15 -05002124 if n.Left.Op == OTYPE {
2125 return n
Russ Cox8c195bd2015-02-13 14:40:36 -05002126 }
2127
Russ Cox79f727a2015-03-02 12:35:15 -05002128 if n.Right.Op != ONAME {
2129 return n
2130 }
2131 s := n.Right.Sym
2132 if s == nil {
2133 return n
2134 }
2135
2136 var c int
2137 for d := 0; d < len(dotlist); d++ {
2138 c = adddot1(s, t, d, nil, 0)
2139 if c > 0 {
2140 if c > 1 {
Russ Cox17228f42015-04-17 12:03:22 -04002141 Yyerror("ambiguous selector %v", n)
Russ Cox79f727a2015-03-02 12:35:15 -05002142 n.Left = nil
2143 return n
2144 }
2145
2146 // rebuild elided dots
2147 for c := d - 1; c >= 0; c-- {
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002148 if n.Left.Type != nil && Isptr[n.Left.Type.Etype] {
Dave Cheney44e90312015-03-06 21:18:41 +11002149 n.Left.Implicit = true
Russ Cox79f727a2015-03-02 12:35:15 -05002150 }
2151 n.Left = Nod(ODOT, n.Left, newname(dotlist[c].field.Sym))
2152 }
2153
2154 return n
2155 }
2156 }
2157
Russ Cox8c195bd2015-02-13 14:40:36 -05002158 return n
2159}
2160
2161/*
2162 * code to help generate trampoline
2163 * functions for methods on embedded
2164 * subtypes.
2165 * these are approx the same as
2166 * the corresponding adddot routines
2167 * except that they expect to be called
2168 * with unique tasks and they return
2169 * the actual methods.
2170 */
2171type Symlink struct {
2172 field *Type
2173 good uint8
2174 followptr uint8
2175 link *Symlink
2176}
2177
2178var slist *Symlink
2179
2180func expand0(t *Type, followptr int) {
Russ Cox382b44e2015-02-23 16:07:24 -05002181 u := t
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002182 if Isptr[u.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002183 followptr = 1
2184 u = u.Type
2185 }
2186
2187 if u.Etype == TINTER {
Russ Cox382b44e2015-02-23 16:07:24 -05002188 var sl *Symlink
2189 for f := u.Type; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002190 if f.Sym.Flags&SymUniq != 0 {
2191 continue
2192 }
2193 f.Sym.Flags |= SymUniq
2194 sl = new(Symlink)
2195 sl.field = f
2196 sl.link = slist
2197 sl.followptr = uint8(followptr)
2198 slist = sl
2199 }
2200
2201 return
2202 }
2203
2204 u = methtype(t, 0)
2205 if u != nil {
Russ Cox382b44e2015-02-23 16:07:24 -05002206 var sl *Symlink
2207 for f := u.Method; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002208 if f.Sym.Flags&SymUniq != 0 {
2209 continue
2210 }
2211 f.Sym.Flags |= SymUniq
2212 sl = new(Symlink)
2213 sl.field = f
2214 sl.link = slist
2215 sl.followptr = uint8(followptr)
2216 slist = sl
2217 }
2218 }
2219}
2220
2221func expand1(t *Type, d int, followptr int) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002222 if t.Trecur != 0 {
2223 return
2224 }
2225 if d == 0 {
2226 return
2227 }
2228 t.Trecur = 1
2229
2230 if d != len(dotlist)-1 {
2231 expand0(t, followptr)
2232 }
2233
Russ Cox382b44e2015-02-23 16:07:24 -05002234 u := t
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002235 if Isptr[u.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002236 followptr = 1
2237 u = u.Type
2238 }
2239
2240 if u.Etype != TSTRUCT && u.Etype != TINTER {
2241 goto out
2242 }
2243
Russ Cox382b44e2015-02-23 16:07:24 -05002244 for f := u.Type; f != nil; f = f.Down {
Russ Coxdc7b54b2015-02-17 22:13:49 -05002245 if f.Embedded == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05002246 continue
2247 }
2248 if f.Sym == nil {
2249 continue
2250 }
2251 expand1(f.Type, d-1, followptr)
2252 }
2253
2254out:
2255 t.Trecur = 0
2256}
2257
2258func expandmeth(t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002259 if t == nil || t.Xmethod != nil {
2260 return
2261 }
2262
2263 // mark top-level method symbols
2264 // so that expand1 doesn't consider them.
Russ Cox382b44e2015-02-23 16:07:24 -05002265 var f *Type
Russ Cox8c195bd2015-02-13 14:40:36 -05002266 for f = t.Method; f != nil; f = f.Down {
2267 f.Sym.Flags |= SymUniq
2268 }
2269
2270 // generate all reachable methods
2271 slist = nil
2272
2273 expand1(t, len(dotlist)-1, 0)
2274
2275 // check each method to be uniquely reachable
Russ Cox382b44e2015-02-23 16:07:24 -05002276 var c int
2277 var d int
2278 for sl := slist; sl != nil; sl = sl.link {
Russ Cox8c195bd2015-02-13 14:40:36 -05002279 sl.field.Sym.Flags &^= SymUniq
2280 for d = 0; d < len(dotlist); d++ {
2281 c = adddot1(sl.field.Sym, t, d, &f, 0)
2282 if c == 0 {
2283 continue
2284 }
2285 if c == 1 {
2286 // addot1 may have dug out arbitrary fields, we only want methods.
2287 if f.Type.Etype == TFUNC && f.Type.Thistuple > 0 {
2288 sl.good = 1
2289 sl.field = f
2290 }
2291 }
2292
2293 break
2294 }
2295 }
2296
2297 for f = t.Method; f != nil; f = f.Down {
2298 f.Sym.Flags &^= SymUniq
2299 }
2300
2301 t.Xmethod = t.Method
Russ Cox382b44e2015-02-23 16:07:24 -05002302 for sl := slist; sl != nil; sl = sl.link {
Russ Cox8c195bd2015-02-13 14:40:36 -05002303 if sl.good != 0 {
2304 // add it to the base type method list
2305 f = typ(TFIELD)
2306
2307 *f = *sl.field
2308 f.Embedded = 1 // needs a trampoline
2309 if sl.followptr != 0 {
2310 f.Embedded = 2
2311 }
2312 f.Down = t.Xmethod
2313 t.Xmethod = f
2314 }
2315 }
2316}
2317
2318/*
2319 * Given funarg struct list, return list of ODCLFIELD Node fn args.
2320 */
2321func structargs(tl **Type, mustname int) *NodeList {
2322 var savet Iter
2323 var a *Node
2324 var n *Node
Russ Cox8c195bd2015-02-13 14:40:36 -05002325 var buf string
Russ Cox8c195bd2015-02-13 14:40:36 -05002326
Russ Cox175929b2015-03-02 14:22:05 -05002327 var args *NodeList
Russ Cox382b44e2015-02-23 16:07:24 -05002328 gen := 0
2329 for t := Structfirst(&savet, tl); t != nil; t = structnext(&savet) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002330 n = nil
2331 if mustname != 0 && (t.Sym == nil || t.Sym.Name == "_") {
2332 // invent a name so that we can refer to it in the trampoline
2333 buf = fmt.Sprintf(".anon%d", gen)
2334 gen++
2335
2336 n = newname(Lookup(buf))
2337 } else if t.Sym != nil {
2338 n = newname(t.Sym)
2339 }
2340 a = Nod(ODCLFIELD, n, typenod(t.Type))
2341 a.Isddd = t.Isddd
2342 if n != nil {
2343 n.Isddd = t.Isddd
2344 }
2345 args = list(args, a)
2346 }
2347
2348 return args
2349}
2350
2351/*
2352 * Generate a wrapper function to convert from
2353 * a receiver of type T to a receiver of type U.
2354 * That is,
2355 *
2356 * func (t T) M() {
2357 * ...
2358 * }
2359 *
2360 * already exists; this function generates
2361 *
2362 * func (u U) M() {
2363 * u.M()
2364 * }
2365 *
2366 * where the types T and U are such that u.M() is valid
2367 * and calls the T.M method.
2368 * The resulting function is for use in method tables.
2369 *
2370 * rcvr - U
2371 * method - M func (t T)(), a TFIELD type struct
2372 * newnam - the eventual mangled name of this function
2373 */
2374
2375var genwrapper_linehistdone int = 0
2376
2377func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002378 if false && Debug['r'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -04002379 fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
Russ Cox8c195bd2015-02-13 14:40:36 -05002380 }
2381
2382 lexlineno++
2383 lineno = lexlineno
2384 if genwrapper_linehistdone == 0 {
2385 // All the wrappers can share the same linehist entry.
Matthew Dempsky14677762015-04-20 13:32:40 -07002386 linehistpush("<autogenerated>")
Russ Cox8c195bd2015-02-13 14:40:36 -05002387
2388 genwrapper_linehistdone = 1
2389 }
2390
2391 dclcontext = PEXTERN
2392 markdcl()
2393
Russ Cox382b44e2015-02-23 16:07:24 -05002394 this := Nod(ODCLFIELD, newname(Lookup(".this")), typenod(rcvr))
Russ Cox3c3019a2015-05-27 00:44:05 -04002395 this.Left.Name.Param.Ntype = this.Right
Russ Cox382b44e2015-02-23 16:07:24 -05002396 in := structargs(getinarg(method.Type), 1)
2397 out := structargs(Getoutarg(method.Type), 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05002398
Russ Cox382b44e2015-02-23 16:07:24 -05002399 t := Nod(OTFUNC, nil, nil)
2400 l := list1(this)
Russ Cox8c195bd2015-02-13 14:40:36 -05002401 if iface != 0 && rcvr.Width < Types[Tptr].Width {
2402 // Building method for interface table and receiver
2403 // is smaller than the single pointer-sized word
2404 // that the interface call will pass in.
2405 // Add a dummy padding argument after the
2406 // receiver to make up the difference.
Russ Cox382b44e2015-02-23 16:07:24 -05002407 tpad := typ(TARRAY)
Russ Cox8c195bd2015-02-13 14:40:36 -05002408
2409 tpad.Type = Types[TUINT8]
2410 tpad.Bound = Types[Tptr].Width - rcvr.Width
Russ Cox382b44e2015-02-23 16:07:24 -05002411 pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad))
Russ Cox8c195bd2015-02-13 14:40:36 -05002412 l = list(l, pad)
2413 }
2414
2415 t.List = concat(l, in)
2416 t.Rlist = out
2417
Russ Cox382b44e2015-02-23 16:07:24 -05002418 fn := Nod(ODCLFUNC, nil, nil)
Russ Coxbd4fff62015-05-27 10:42:55 -04002419 fn.Func.Nname = newname(newnam)
2420 fn.Func.Nname.Name.Defn = fn
2421 fn.Func.Nname.Name.Param.Ntype = t
2422 declare(fn.Func.Nname, PFUNC)
Russ Cox8c195bd2015-02-13 14:40:36 -05002423 funchdr(fn)
2424
2425 // arg list
Russ Cox175929b2015-03-02 14:22:05 -05002426 var args *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -05002427
Dave Cheneyd3287562015-03-09 16:24:07 +11002428 isddd := false
Russ Cox382b44e2015-02-23 16:07:24 -05002429 for l := in; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -05002430 args = list(args, l.N.Left)
Dave Cheneyd3287562015-03-09 16:24:07 +11002431 isddd = l.N.Left.Isddd
Russ Cox8c195bd2015-02-13 14:40:36 -05002432 }
2433
Russ Cox382b44e2015-02-23 16:07:24 -05002434 methodrcvr := getthisx(method.Type).Type.Type
Russ Cox8c195bd2015-02-13 14:40:36 -05002435
2436 // generate nil pointer check for better error
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002437 if Isptr[rcvr.Etype] && rcvr.Type == methodrcvr {
Russ Cox8c195bd2015-02-13 14:40:36 -05002438 // generating wrapper from *T to T.
Russ Cox382b44e2015-02-23 16:07:24 -05002439 n := Nod(OIF, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002440
Russ Cox66be1482015-05-26 21:30:20 -04002441 n.Left = Nod(OEQ, this.Left, nodnil())
Russ Cox8c195bd2015-02-13 14:40:36 -05002442
2443 // these strings are already in the reflect tables,
2444 // so no space cost to use them here.
Russ Cox175929b2015-03-02 14:22:05 -05002445 var l *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -05002446
Russ Cox382b44e2015-02-23 16:07:24 -05002447 var v Val
Josh Bleecher Snyder13485be2015-05-14 17:57:42 -07002448 v.U = rcvr.Type.Sym.Pkg.Name // package name
Russ Cox8c195bd2015-02-13 14:40:36 -05002449 l = list(l, nodlit(v))
Josh Bleecher Snyder13485be2015-05-14 17:57:42 -07002450 v.U = rcvr.Type.Sym.Name // type name
Russ Cox8c195bd2015-02-13 14:40:36 -05002451 l = list(l, nodlit(v))
Josh Bleecher Snyder13485be2015-05-14 17:57:42 -07002452 v.U = method.Sym.Name
Russ Cox8c195bd2015-02-13 14:40:36 -05002453 l = list(l, nodlit(v)) // method name
Russ Cox382b44e2015-02-23 16:07:24 -05002454 call := Nod(OCALL, syslook("panicwrap", 0), nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002455 call.List = l
2456 n.Nbody = list1(call)
2457 fn.Nbody = list(fn.Nbody, n)
2458 }
2459
Russ Cox382b44e2015-02-23 16:07:24 -05002460 dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym)))
Russ Cox8c195bd2015-02-13 14:40:36 -05002461
2462 // generate call
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002463 if flag_race == 0 && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002464 // generate tail call: adjust pointer receiver and jump to embedded method.
2465 dot = dot.Left // skip final .M
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002466 if !Isptr[dotlist[0].field.Type.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002467 dot = Nod(OADDR, dot, nil)
2468 }
Russ Cox382b44e2015-02-23 16:07:24 -05002469 as := Nod(OAS, this.Left, Nod(OCONVNOP, dot, nil))
Russ Cox8c195bd2015-02-13 14:40:36 -05002470 as.Right.Type = rcvr
2471 fn.Nbody = list(fn.Nbody, as)
Russ Cox382b44e2015-02-23 16:07:24 -05002472 n := Nod(ORETJMP, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002473 n.Left = newname(methodsym(method.Sym, methodrcvr, 0))
2474 fn.Nbody = list(fn.Nbody, n)
2475 } else {
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -07002476 fn.Func.Wrapper = true // ignore frame for panic+recover matching
Russ Cox382b44e2015-02-23 16:07:24 -05002477 call := Nod(OCALL, dot, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002478 call.List = args
Dave Cheneyd3287562015-03-09 16:24:07 +11002479 call.Isddd = isddd
Russ Cox8c195bd2015-02-13 14:40:36 -05002480 if method.Type.Outtuple > 0 {
Russ Cox382b44e2015-02-23 16:07:24 -05002481 n := Nod(ORETURN, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002482 n.List = list1(call)
2483 call = n
2484 }
2485
2486 fn.Nbody = list(fn.Nbody, call)
2487 }
2488
2489 if false && Debug['r'] != 0 {
2490 dumplist("genwrapper body", fn.Nbody)
2491 }
2492
2493 funcbody(fn)
2494 Curfn = fn
2495
2496 // wrappers where T is anonymous (struct or interface) can be duplicated.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002497 if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Type.Etype == TSTRUCT {
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -07002498 fn.Func.Dupok = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002499 }
2500 typecheck(&fn, Etop)
2501 typechecklist(fn.Nbody, Etop)
2502
Russ Cox8c195bd2015-02-13 14:40:36 -05002503 inlcalls(fn)
David Chase5be61b12015-06-16 18:28:01 -04002504 escAnalyze(list1(fn), false)
Russ Cox8c195bd2015-02-13 14:40:36 -05002505
2506 Curfn = nil
2507 funccompile(fn)
2508}
2509
2510func hashmem(t *Type) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -05002511 sym := Pkglookup("memhash", Runtimepkg)
Russ Cox8c195bd2015-02-13 14:40:36 -05002512
Russ Cox382b44e2015-02-23 16:07:24 -05002513 n := newname(sym)
Russ Cox8c195bd2015-02-13 14:40:36 -05002514 n.Class = PFUNC
Russ Cox382b44e2015-02-23 16:07:24 -05002515 tfn := Nod(OTFUNC, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002516 tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
2517 tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
2518 tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
2519 tfn.Rlist = list(tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
2520 typecheck(&tfn, Etype)
2521 n.Type = tfn.Type
2522 return n
2523}
2524
2525func hashfor(t *Type) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05002526 var sym *Sym
Russ Cox8c195bd2015-02-13 14:40:36 -05002527
Russ Cox382b44e2015-02-23 16:07:24 -05002528 a := algtype1(t, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002529 switch a {
2530 case AMEM:
2531 Fatal("hashfor with AMEM type")
Russ Cox8c195bd2015-02-13 14:40:36 -05002532
2533 case AINTER:
2534 sym = Pkglookup("interhash", Runtimepkg)
2535
2536 case ANILINTER:
2537 sym = Pkglookup("nilinterhash", Runtimepkg)
2538
2539 case ASTRING:
2540 sym = Pkglookup("strhash", Runtimepkg)
2541
2542 case AFLOAT32:
2543 sym = Pkglookup("f32hash", Runtimepkg)
2544
2545 case AFLOAT64:
2546 sym = Pkglookup("f64hash", Runtimepkg)
2547
2548 case ACPLX64:
2549 sym = Pkglookup("c64hash", Runtimepkg)
2550
2551 case ACPLX128:
2552 sym = Pkglookup("c128hash", Runtimepkg)
2553
2554 default:
2555 sym = typesymprefix(".hash", t)
2556 }
2557
Russ Cox382b44e2015-02-23 16:07:24 -05002558 n := newname(sym)
Russ Cox8c195bd2015-02-13 14:40:36 -05002559 n.Class = PFUNC
Russ Cox382b44e2015-02-23 16:07:24 -05002560 tfn := Nod(OTFUNC, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002561 tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
2562 tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
2563 tfn.Rlist = list(tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
2564 typecheck(&tfn, Etype)
2565 n.Type = tfn.Type
2566 return n
2567}
2568
2569/*
2570 * Generate a helper function to compute the hash of a value of type t.
2571 */
2572func genhash(sym *Sym, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002573 if Debug['r'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -04002574 fmt.Printf("genhash %v %v\n", sym, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002575 }
2576
2577 lineno = 1 // less confusing than end of input
2578 dclcontext = PEXTERN
2579 markdcl()
2580
2581 // func sym(p *T, h uintptr) uintptr
Russ Cox382b44e2015-02-23 16:07:24 -05002582 fn := Nod(ODCLFUNC, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002583
Russ Coxbd4fff62015-05-27 10:42:55 -04002584 fn.Func.Nname = newname(sym)
2585 fn.Func.Nname.Class = PFUNC
Russ Cox382b44e2015-02-23 16:07:24 -05002586 tfn := Nod(OTFUNC, nil, nil)
Russ Coxbd4fff62015-05-27 10:42:55 -04002587 fn.Func.Nname.Name.Param.Ntype = tfn
Russ Cox8c195bd2015-02-13 14:40:36 -05002588
Russ Cox382b44e2015-02-23 16:07:24 -05002589 n := Nod(ODCLFIELD, newname(Lookup("p")), typenod(Ptrto(t)))
Russ Cox8c195bd2015-02-13 14:40:36 -05002590 tfn.List = list(tfn.List, n)
Russ Cox382b44e2015-02-23 16:07:24 -05002591 np := n.Left
Russ Cox8c195bd2015-02-13 14:40:36 -05002592 n = Nod(ODCLFIELD, newname(Lookup("h")), typenod(Types[TUINTPTR]))
2593 tfn.List = list(tfn.List, n)
Russ Cox382b44e2015-02-23 16:07:24 -05002594 nh := n.Left
Russ Cox8c195bd2015-02-13 14:40:36 -05002595 n = Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])) // return value
2596 tfn.Rlist = list(tfn.Rlist, n)
2597
2598 funchdr(fn)
Russ Coxbd4fff62015-05-27 10:42:55 -04002599 typecheck(&fn.Func.Nname.Name.Param.Ntype, Etype)
Russ Cox8c195bd2015-02-13 14:40:36 -05002600
2601 // genhash is only called for types that have equality but
2602 // cannot be handled by the standard algorithms,
2603 // so t must be either an array or a struct.
2604 switch t.Etype {
2605 default:
Russ Cox17228f42015-04-17 12:03:22 -04002606 Fatal("genhash %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002607
2608 case TARRAY:
Russ Coxdc7b54b2015-02-17 22:13:49 -05002609 if Isslice(t) {
Russ Cox17228f42015-04-17 12:03:22 -04002610 Fatal("genhash %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002611 }
2612
2613 // An array of pure memory would be handled by the
2614 // standard algorithm, so the element type must not be
2615 // pure memory.
Russ Cox382b44e2015-02-23 16:07:24 -05002616 hashel := hashfor(t.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05002617
Russ Cox382b44e2015-02-23 16:07:24 -05002618 n := Nod(ORANGE, nil, Nod(OIND, np, nil))
2619 ni := newname(Lookup("i"))
Russ Cox8c195bd2015-02-13 14:40:36 -05002620 ni.Type = Types[TINT]
2621 n.List = list1(ni)
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -07002622 n.Colas = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002623 colasdefn(n.List, n)
2624 ni = n.List.N
2625
2626 // TODO: with aeshash we don't need these shift/mul parts
2627
2628 // h = h<<3 | h>>61
2629 n.Nbody = list(n.Nbody, Nod(OAS, nh, Nod(OOR, Nod(OLSH, nh, Nodintconst(3)), Nod(ORSH, nh, Nodintconst(int64(Widthptr)*8-3)))))
2630
2631 // h *= mul
2632 // Same multipliers as in runtime.memhash.
Russ Cox382b44e2015-02-23 16:07:24 -05002633 var mul int64
Russ Cox8c195bd2015-02-13 14:40:36 -05002634 if Widthptr == 4 {
2635 mul = 3267000013
2636 } else {
2637 mul = 23344194077549503
2638 }
2639 n.Nbody = list(n.Nbody, Nod(OAS, nh, Nod(OMUL, nh, Nodintconst(mul))))
2640
2641 // h = hashel(&p[i], h)
Russ Cox382b44e2015-02-23 16:07:24 -05002642 call := Nod(OCALL, hashel, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002643
Russ Cox382b44e2015-02-23 16:07:24 -05002644 nx := Nod(OINDEX, np, ni)
Russ Coxdc7b54b2015-02-17 22:13:49 -05002645 nx.Bounded = true
Russ Cox382b44e2015-02-23 16:07:24 -05002646 na := Nod(OADDR, nx, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002647 na.Etype = 1 // no escape to heap
2648 call.List = list(call.List, na)
2649 call.List = list(call.List, nh)
2650 n.Nbody = list(n.Nbody, Nod(OAS, nh, call))
2651
2652 fn.Nbody = list(fn.Nbody, n)
2653
2654 // Walk the struct using memhash for runs of AMEM
2655 // and calling specific hash functions for the others.
2656 case TSTRUCT:
Russ Cox175929b2015-03-02 14:22:05 -05002657 var first *Type
Russ Cox8c195bd2015-02-13 14:40:36 -05002658
Russ Cox382b44e2015-02-23 16:07:24 -05002659 offend := int64(0)
2660 var size int64
2661 var call *Node
2662 var nx *Node
2663 var na *Node
2664 var hashel *Node
2665 for t1 := t.Type; ; t1 = t1.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002666 if t1 != nil && algtype1(t1.Type, nil) == AMEM && !isblanksym(t1.Sym) {
2667 offend = t1.Width + t1.Type.Width
2668 if first == nil {
2669 first = t1
2670 }
2671
2672 // If it's a memory field but it's padded, stop here.
Russ Coxdc7b54b2015-02-17 22:13:49 -05002673 if ispaddedfield(t1, t.Width) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002674 t1 = t1.Down
2675 } else {
2676 continue
2677 }
2678 }
2679
2680 // Run memhash for fields up to this one.
2681 if first != nil {
2682 size = offend - first.Width // first->width is offset
2683 hashel = hashmem(first.Type)
2684
2685 // h = hashel(&p.first, size, h)
2686 call = Nod(OCALL, hashel, nil)
2687
2688 nx = Nod(OXDOT, np, newname(first.Sym)) // TODO: fields from other packages?
2689 na = Nod(OADDR, nx, nil)
2690 na.Etype = 1 // no escape to heap
2691 call.List = list(call.List, na)
2692 call.List = list(call.List, nh)
2693 call.List = list(call.List, Nodintconst(size))
2694 fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
2695
2696 first = nil
2697 }
2698
2699 if t1 == nil {
2700 break
2701 }
2702 if isblanksym(t1.Sym) {
2703 continue
2704 }
2705
2706 // Run hash for this field.
2707 if algtype1(t1.Type, nil) == AMEM {
2708 hashel = hashmem(t1.Type)
2709
2710 // h = memhash(&p.t1, h, size)
2711 call = Nod(OCALL, hashel, nil)
2712
2713 nx = Nod(OXDOT, np, newname(t1.Sym)) // TODO: fields from other packages?
2714 na = Nod(OADDR, nx, nil)
2715 na.Etype = 1 // no escape to heap
2716 call.List = list(call.List, na)
2717 call.List = list(call.List, nh)
2718 call.List = list(call.List, Nodintconst(t1.Type.Width))
2719 fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
2720 } else {
2721 hashel = hashfor(t1.Type)
2722
2723 // h = hashel(&p.t1, h)
2724 call = Nod(OCALL, hashel, nil)
2725
2726 nx = Nod(OXDOT, np, newname(t1.Sym)) // TODO: fields from other packages?
2727 na = Nod(OADDR, nx, nil)
2728 na.Etype = 1 // no escape to heap
2729 call.List = list(call.List, na)
2730 call.List = list(call.List, nh)
2731 fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
2732 }
2733 }
2734 }
2735
Russ Cox382b44e2015-02-23 16:07:24 -05002736 r := Nod(ORETURN, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002737 r.List = list(r.List, nh)
2738 fn.Nbody = list(fn.Nbody, r)
2739
2740 if Debug['r'] != 0 {
2741 dumplist("genhash body", fn.Nbody)
2742 }
2743
2744 funcbody(fn)
2745 Curfn = fn
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -07002746 fn.Func.Dupok = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002747 typecheck(&fn, Etop)
2748 typechecklist(fn.Nbody, Etop)
2749 Curfn = nil
2750
2751 // Disable safemode while compiling this code: the code we
2752 // generate internally can refer to unsafe.Pointer.
2753 // In this case it can happen if we need to generate an ==
2754 // for a struct containing a reflect.Value, which itself has
2755 // an unexported field of type unsafe.Pointer.
Russ Cox382b44e2015-02-23 16:07:24 -05002756 old_safemode := safemode
Russ Cox8c195bd2015-02-13 14:40:36 -05002757
2758 safemode = 0
2759 funccompile(fn)
2760 safemode = old_safemode
2761}
2762
2763// Return node for
2764// if p.field != q.field { return false }
2765func eqfield(p *Node, q *Node, field *Node) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -05002766 nx := Nod(OXDOT, p, field)
2767 ny := Nod(OXDOT, q, field)
2768 nif := Nod(OIF, nil, nil)
Russ Cox66be1482015-05-26 21:30:20 -04002769 nif.Left = Nod(ONE, nx, ny)
Russ Cox382b44e2015-02-23 16:07:24 -05002770 r := Nod(ORETURN, nil, nil)
Russ Coxdc7b54b2015-02-17 22:13:49 -05002771 r.List = list(r.List, Nodbool(false))
Russ Cox8c195bd2015-02-13 14:40:36 -05002772 nif.Nbody = list(nif.Nbody, r)
2773 return nif
2774}
2775
2776func eqmemfunc(size int64, type_ *Type, needsize *int) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05002777 var fn *Node
2778
2779 switch size {
2780 default:
2781 fn = syslook("memequal", 1)
2782 *needsize = 1
2783
Russ Cox13f9c8b2015-03-08 13:33:49 -04002784 case 1, 2, 4, 8, 16:
Russ Cox382b44e2015-02-23 16:07:24 -05002785 buf := fmt.Sprintf("memequal%d", int(size)*8)
Russ Cox8c195bd2015-02-13 14:40:36 -05002786 fn = syslook(buf, 1)
2787 *needsize = 0
2788 }
2789
Russ Cox13f9c8b2015-03-08 13:33:49 -04002790 substArgTypes(fn, type_, type_)
Russ Cox8c195bd2015-02-13 14:40:36 -05002791 return fn
2792}
2793
2794// Return node for
2795// if !memequal(&p.field, &q.field [, size]) { return false }
2796func eqmem(p *Node, q *Node, field *Node, size int64) *Node {
Russ Cox8c195bd2015-02-13 14:40:36 -05002797 var needsize int
2798
Russ Cox382b44e2015-02-23 16:07:24 -05002799 nx := Nod(OADDR, Nod(OXDOT, p, field), nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002800 nx.Etype = 1 // does not escape
Russ Cox382b44e2015-02-23 16:07:24 -05002801 ny := Nod(OADDR, Nod(OXDOT, q, field), nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002802 ny.Etype = 1 // does not escape
2803 typecheck(&nx, Erv)
2804 typecheck(&ny, Erv)
2805
Russ Cox382b44e2015-02-23 16:07:24 -05002806 call := Nod(OCALL, eqmemfunc(size, nx.Type.Type, &needsize), nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002807 call.List = list(call.List, nx)
2808 call.List = list(call.List, ny)
2809 if needsize != 0 {
2810 call.List = list(call.List, Nodintconst(size))
2811 }
2812
Russ Cox382b44e2015-02-23 16:07:24 -05002813 nif := Nod(OIF, nil, nil)
Russ Cox66be1482015-05-26 21:30:20 -04002814 nif.Left = Nod(ONOT, call, nil)
Russ Cox382b44e2015-02-23 16:07:24 -05002815 r := Nod(ORETURN, nil, nil)
Russ Coxdc7b54b2015-02-17 22:13:49 -05002816 r.List = list(r.List, Nodbool(false))
Russ Cox8c195bd2015-02-13 14:40:36 -05002817 nif.Nbody = list(nif.Nbody, r)
2818 return nif
2819}
2820
2821/*
2822 * Generate a helper function to check equality of two values of type t.
2823 */
2824func geneq(sym *Sym, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002825 if Debug['r'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -04002826 fmt.Printf("geneq %v %v\n", sym, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002827 }
2828
2829 lineno = 1 // less confusing than end of input
2830 dclcontext = PEXTERN
2831 markdcl()
2832
2833 // func sym(p, q *T) bool
Russ Cox382b44e2015-02-23 16:07:24 -05002834 fn := Nod(ODCLFUNC, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002835
Russ Coxbd4fff62015-05-27 10:42:55 -04002836 fn.Func.Nname = newname(sym)
2837 fn.Func.Nname.Class = PFUNC
Russ Cox382b44e2015-02-23 16:07:24 -05002838 tfn := Nod(OTFUNC, nil, nil)
Russ Coxbd4fff62015-05-27 10:42:55 -04002839 fn.Func.Nname.Name.Param.Ntype = tfn
Russ Cox8c195bd2015-02-13 14:40:36 -05002840
Russ Cox382b44e2015-02-23 16:07:24 -05002841 n := Nod(ODCLFIELD, newname(Lookup("p")), typenod(Ptrto(t)))
Russ Cox8c195bd2015-02-13 14:40:36 -05002842 tfn.List = list(tfn.List, n)
Russ Cox382b44e2015-02-23 16:07:24 -05002843 np := n.Left
Russ Cox8c195bd2015-02-13 14:40:36 -05002844 n = Nod(ODCLFIELD, newname(Lookup("q")), typenod(Ptrto(t)))
2845 tfn.List = list(tfn.List, n)
Russ Cox382b44e2015-02-23 16:07:24 -05002846 nq := n.Left
Russ Cox8c195bd2015-02-13 14:40:36 -05002847 n = Nod(ODCLFIELD, nil, typenod(Types[TBOOL]))
2848 tfn.Rlist = list(tfn.Rlist, n)
2849
2850 funchdr(fn)
2851
2852 // geneq is only called for types that have equality but
2853 // cannot be handled by the standard algorithms,
2854 // so t must be either an array or a struct.
2855 switch t.Etype {
2856 default:
Russ Cox17228f42015-04-17 12:03:22 -04002857 Fatal("geneq %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002858
2859 case TARRAY:
Russ Coxdc7b54b2015-02-17 22:13:49 -05002860 if Isslice(t) {
Russ Cox17228f42015-04-17 12:03:22 -04002861 Fatal("geneq %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05002862 }
2863
2864 // An array of pure memory would be handled by the
2865 // standard memequal, so the element type must not be
2866 // pure memory. Even if we unrolled the range loop,
2867 // each iteration would be a function call, so don't bother
2868 // unrolling.
Russ Cox382b44e2015-02-23 16:07:24 -05002869 nrange := Nod(ORANGE, nil, Nod(OIND, np, nil))
Russ Cox8c195bd2015-02-13 14:40:36 -05002870
Russ Cox382b44e2015-02-23 16:07:24 -05002871 ni := newname(Lookup("i"))
Russ Cox8c195bd2015-02-13 14:40:36 -05002872 ni.Type = Types[TINT]
2873 nrange.List = list1(ni)
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -07002874 nrange.Colas = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002875 colasdefn(nrange.List, nrange)
2876 ni = nrange.List.N
2877
2878 // if p[i] != q[i] { return false }
Russ Cox382b44e2015-02-23 16:07:24 -05002879 nx := Nod(OINDEX, np, ni)
Russ Cox8c195bd2015-02-13 14:40:36 -05002880
Russ Coxdc7b54b2015-02-17 22:13:49 -05002881 nx.Bounded = true
Russ Cox382b44e2015-02-23 16:07:24 -05002882 ny := Nod(OINDEX, nq, ni)
Russ Coxdc7b54b2015-02-17 22:13:49 -05002883 ny.Bounded = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002884
Russ Cox382b44e2015-02-23 16:07:24 -05002885 nif := Nod(OIF, nil, nil)
Russ Cox66be1482015-05-26 21:30:20 -04002886 nif.Left = Nod(ONE, nx, ny)
Russ Cox382b44e2015-02-23 16:07:24 -05002887 r := Nod(ORETURN, nil, nil)
Russ Coxdc7b54b2015-02-17 22:13:49 -05002888 r.List = list(r.List, Nodbool(false))
Russ Cox8c195bd2015-02-13 14:40:36 -05002889 nif.Nbody = list(nif.Nbody, r)
2890 nrange.Nbody = list(nrange.Nbody, nif)
2891 fn.Nbody = list(fn.Nbody, nrange)
2892
2893 // Walk the struct using memequal for runs of AMEM
2894 // and calling specific equality tests for the others.
2895 // Skip blank-named fields.
2896 case TSTRUCT:
Russ Cox175929b2015-03-02 14:22:05 -05002897 var first *Type
Russ Cox8c195bd2015-02-13 14:40:36 -05002898
Russ Cox382b44e2015-02-23 16:07:24 -05002899 offend := int64(0)
2900 var size int64
2901 for t1 := t.Type; ; t1 = t1.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05002902 if t1 != nil && algtype1(t1.Type, nil) == AMEM && !isblanksym(t1.Sym) {
2903 offend = t1.Width + t1.Type.Width
2904 if first == nil {
2905 first = t1
2906 }
2907
2908 // If it's a memory field but it's padded, stop here.
Russ Coxdc7b54b2015-02-17 22:13:49 -05002909 if ispaddedfield(t1, t.Width) {
Russ Cox8c195bd2015-02-13 14:40:36 -05002910 t1 = t1.Down
2911 } else {
2912 continue
2913 }
2914 }
2915
2916 // Run memequal for fields up to this one.
2917 // TODO(rsc): All the calls to newname are wrong for
2918 // cross-package unexported fields.
2919 if first != nil {
2920 if first.Down == t1 {
2921 fn.Nbody = list(fn.Nbody, eqfield(np, nq, newname(first.Sym)))
2922 } else if first.Down.Down == t1 {
2923 fn.Nbody = list(fn.Nbody, eqfield(np, nq, newname(first.Sym)))
2924 first = first.Down
2925 if !isblanksym(first.Sym) {
2926 fn.Nbody = list(fn.Nbody, eqfield(np, nq, newname(first.Sym)))
2927 }
2928 } else {
2929 // More than two fields: use memequal.
2930 size = offend - first.Width // first->width is offset
2931 fn.Nbody = list(fn.Nbody, eqmem(np, nq, newname(first.Sym), size))
2932 }
2933
2934 first = nil
2935 }
2936
2937 if t1 == nil {
2938 break
2939 }
2940 if isblanksym(t1.Sym) {
2941 continue
2942 }
2943
2944 // Check this field, which is not just memory.
2945 fn.Nbody = list(fn.Nbody, eqfield(np, nq, newname(t1.Sym)))
2946 }
2947 }
2948
2949 // return true
Russ Cox382b44e2015-02-23 16:07:24 -05002950 r := Nod(ORETURN, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05002951
Russ Coxdc7b54b2015-02-17 22:13:49 -05002952 r.List = list(r.List, Nodbool(true))
Russ Cox8c195bd2015-02-13 14:40:36 -05002953 fn.Nbody = list(fn.Nbody, r)
2954
2955 if Debug['r'] != 0 {
2956 dumplist("geneq body", fn.Nbody)
2957 }
2958
2959 funcbody(fn)
2960 Curfn = fn
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -07002961 fn.Func.Dupok = true
Russ Cox8c195bd2015-02-13 14:40:36 -05002962 typecheck(&fn, Etop)
2963 typechecklist(fn.Nbody, Etop)
2964 Curfn = nil
2965
2966 // Disable safemode while compiling this code: the code we
2967 // generate internally can refer to unsafe.Pointer.
2968 // In this case it can happen if we need to generate an ==
2969 // for a struct containing a reflect.Value, which itself has
2970 // an unexported field of type unsafe.Pointer.
Russ Cox382b44e2015-02-23 16:07:24 -05002971 old_safemode := safemode
Russ Cox8c195bd2015-02-13 14:40:36 -05002972
2973 safemode = 0
2974 funccompile(fn)
2975 safemode = old_safemode
2976}
2977
2978func ifacelookdot(s *Sym, t *Type, followptr *int, ignorecase int) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -05002979 *followptr = 0
2980
2981 if t == nil {
2982 return nil
2983 }
2984
Russ Cox382b44e2015-02-23 16:07:24 -05002985 var m *Type
2986 var i int
2987 var c int
2988 for d := 0; d < len(dotlist); d++ {
Russ Cox8c195bd2015-02-13 14:40:36 -05002989 c = adddot1(s, t, d, &m, ignorecase)
2990 if c > 1 {
Russ Cox17228f42015-04-17 12:03:22 -04002991 Yyerror("%v.%v is ambiguous", t, s)
Russ Cox8c195bd2015-02-13 14:40:36 -05002992 return nil
2993 }
2994
2995 if c == 1 {
2996 for i = 0; i < d; i++ {
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00002997 if Isptr[dotlist[i].field.Type.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -05002998 *followptr = 1
2999 break
3000 }
3001 }
3002
3003 if m.Type.Etype != TFUNC || m.Type.Thistuple == 0 {
Russ Cox17228f42015-04-17 12:03:22 -04003004 Yyerror("%v.%v is a field, not a method", t, s)
Russ Cox8c195bd2015-02-13 14:40:36 -05003005 return nil
3006 }
3007
3008 return m
3009 }
3010 }
3011
3012 return nil
3013}
3014
Russ Coxdc7b54b2015-02-17 22:13:49 -05003015func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool {
Russ Cox382b44e2015-02-23 16:07:24 -05003016 t0 := t
Russ Cox8c195bd2015-02-13 14:40:36 -05003017 if t == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -05003018 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003019 }
3020
3021 // if this is too slow,
3022 // could sort these first
3023 // and then do one loop.
3024
3025 if t.Etype == TINTER {
Russ Cox382b44e2015-02-23 16:07:24 -05003026 var tm *Type
3027 for im := iface.Type; im != nil; im = im.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05003028 for tm = t.Type; tm != nil; tm = tm.Down {
3029 if tm.Sym == im.Sym {
3030 if Eqtype(tm.Type, im.Type) {
3031 goto found
3032 }
3033 *m = im
3034 *samename = tm
3035 *ptr = 0
Russ Coxdc7b54b2015-02-17 22:13:49 -05003036 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003037 }
3038 }
3039
3040 *m = im
3041 *samename = nil
3042 *ptr = 0
Russ Coxdc7b54b2015-02-17 22:13:49 -05003043 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003044 found:
3045 }
3046
Russ Coxdc7b54b2015-02-17 22:13:49 -05003047 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05003048 }
3049
3050 t = methtype(t, 0)
3051 if t != nil {
3052 expandmeth(t)
3053 }
Russ Cox382b44e2015-02-23 16:07:24 -05003054 var tm *Type
3055 var imtype *Type
3056 var followptr int
3057 var rcvr *Type
3058 for im := iface.Type; im != nil; im = im.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -05003059 imtype = methodfunc(im.Type, nil)
3060 tm = ifacelookdot(im.Sym, t, &followptr, 0)
Russ Coxdc7b54b2015-02-17 22:13:49 -05003061 if tm == nil || tm.Nointerface || !Eqtype(methodfunc(tm.Type, nil), imtype) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003062 if tm == nil {
3063 tm = ifacelookdot(im.Sym, t, &followptr, 1)
3064 }
3065 *m = im
3066 *samename = tm
3067 *ptr = 0
Russ Coxdc7b54b2015-02-17 22:13:49 -05003068 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003069 }
3070
3071 // if pointer receiver in method,
3072 // the method does not exist for value types.
3073 rcvr = getthisx(tm.Type).Type.Type
3074
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00003075 if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && followptr == 0 && !isifacemethod(tm.Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003076 if false && Debug['r'] != 0 {
3077 Yyerror("interface pointer mismatch")
3078 }
3079
3080 *m = im
3081 *samename = nil
3082 *ptr = 1
Russ Coxdc7b54b2015-02-17 22:13:49 -05003083 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003084 }
3085 }
3086
Russ Coxdc7b54b2015-02-17 22:13:49 -05003087 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05003088}
3089
3090/*
3091 * even simpler simtype; get rid of ptr, bool.
3092 * assuming that the front end has rejected
3093 * all the invalid conversions (like ptr -> bool)
3094 */
3095func Simsimtype(t *Type) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05003096 if t == nil {
3097 return 0
3098 }
3099
Russ Cox382b44e2015-02-23 16:07:24 -05003100 et := int(Simtype[t.Etype])
Russ Cox8c195bd2015-02-13 14:40:36 -05003101 switch et {
3102 case TPTR32:
3103 et = TUINT32
3104
3105 case TPTR64:
3106 et = TUINT64
3107
3108 case TBOOL:
3109 et = TUINT8
3110 }
3111
3112 return et
3113}
3114
David Chase05d8f1d2015-05-22 22:01:01 -04003115func listtreecopy(l *NodeList, lineno int32) *NodeList {
Russ Cox175929b2015-03-02 14:22:05 -05003116 var out *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -05003117 for ; l != nil; l = l.Next {
David Chase05d8f1d2015-05-22 22:01:01 -04003118 out = list(out, treecopy(l.N, lineno))
Russ Cox8c195bd2015-02-13 14:40:36 -05003119 }
3120 return out
3121}
3122
3123func liststmt(l *NodeList) *Node {
Russ Cox382b44e2015-02-23 16:07:24 -05003124 n := Nod(OBLOCK, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05003125 n.List = l
3126 if l != nil {
3127 n.Lineno = l.N.Lineno
3128 }
3129 return n
3130}
3131
3132/*
3133 * return nelem of list
3134 */
Russ Cox8c195bd2015-02-13 14:40:36 -05003135func structcount(t *Type) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05003136 var s Iter
3137
Russ Cox382b44e2015-02-23 16:07:24 -05003138 v := 0
Russ Cox8c195bd2015-02-13 14:40:36 -05003139 for t = Structfirst(&s, &t); t != nil; t = structnext(&s) {
3140 v++
3141 }
3142 return v
3143}
3144
3145/*
3146 * return power of 2 of the constant
3147 * operand. -1 if it is not a power of 2.
3148 * 1000+ if it is a -(power of 2)
3149 */
3150func powtwo(n *Node) int {
Russ Cox8c195bd2015-02-13 14:40:36 -05003151 if n == nil || n.Op != OLITERAL || n.Type == nil {
Russ Cox79f727a2015-03-02 12:35:15 -05003152 return -1
Russ Cox8c195bd2015-02-13 14:40:36 -05003153 }
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00003154 if !Isint[n.Type.Etype] {
Russ Cox79f727a2015-03-02 12:35:15 -05003155 return -1
Russ Cox8c195bd2015-02-13 14:40:36 -05003156 }
3157
Russ Cox81d58102015-05-27 00:47:05 -04003158 v := uint64(Mpgetfix(n.Val().U.(*Mpint)))
Russ Cox79f727a2015-03-02 12:35:15 -05003159 b := uint64(1)
Russ Cox382b44e2015-02-23 16:07:24 -05003160 for i := 0; i < 64; i++ {
Russ Cox8c195bd2015-02-13 14:40:36 -05003161 if b == v {
3162 return i
3163 }
3164 b = b << 1
3165 }
3166
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00003167 if !Issigned[n.Type.Etype] {
Russ Cox79f727a2015-03-02 12:35:15 -05003168 return -1
Russ Cox8c195bd2015-02-13 14:40:36 -05003169 }
3170
3171 v = -v
3172 b = 1
Russ Cox382b44e2015-02-23 16:07:24 -05003173 for i := 0; i < 64; i++ {
Russ Cox8c195bd2015-02-13 14:40:36 -05003174 if b == v {
3175 return i + 1000
3176 }
3177 b = b << 1
3178 }
3179
Russ Cox8c195bd2015-02-13 14:40:36 -05003180 return -1
3181}
3182
3183/*
3184 * return the unsigned type for
3185 * a signed integer type.
3186 * returns T if input is not a
3187 * signed integer type.
3188 */
3189func tounsigned(t *Type) *Type {
3190 // this is types[et+1], but not sure
3191 // that this relation is immutable
3192 switch t.Etype {
3193 default:
Russ Cox17228f42015-04-17 12:03:22 -04003194 fmt.Printf("tounsigned: unknown type %v\n", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05003195 t = nil
3196
3197 case TINT:
3198 t = Types[TUINT]
3199
3200 case TINT8:
3201 t = Types[TUINT8]
3202
3203 case TINT16:
3204 t = Types[TUINT16]
3205
3206 case TINT32:
3207 t = Types[TUINT32]
3208
3209 case TINT64:
3210 t = Types[TUINT64]
3211 }
3212
3213 return t
3214}
3215
3216/*
3217 * magic number for signed division
3218 * see hacker's delight chapter 10
3219 */
3220func Smagic(m *Magic) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003221 var mask uint64
Russ Cox8c195bd2015-02-13 14:40:36 -05003222
3223 m.Bad = 0
3224 switch m.W {
3225 default:
3226 m.Bad = 1
3227 return
3228
3229 case 8:
3230 mask = 0xff
3231
3232 case 16:
3233 mask = 0xffff
3234
3235 case 32:
3236 mask = 0xffffffff
3237
3238 case 64:
3239 mask = 0xffffffffffffffff
3240 }
3241
Russ Cox382b44e2015-02-23 16:07:24 -05003242 two31 := mask ^ (mask >> 1)
Russ Cox8c195bd2015-02-13 14:40:36 -05003243
Russ Cox382b44e2015-02-23 16:07:24 -05003244 p := m.W - 1
3245 ad := uint64(m.Sd)
Russ Cox8c195bd2015-02-13 14:40:36 -05003246 if m.Sd < 0 {
3247 ad = -uint64(m.Sd)
3248 }
3249
3250 // bad denominators
3251 if ad == 0 || ad == 1 || ad == two31 {
3252 m.Bad = 1
3253 return
3254 }
3255
Russ Cox382b44e2015-02-23 16:07:24 -05003256 t := two31
Russ Cox8c195bd2015-02-13 14:40:36 -05003257 ad &= mask
3258
Russ Cox382b44e2015-02-23 16:07:24 -05003259 anc := t - 1 - t%ad
Russ Cox8c195bd2015-02-13 14:40:36 -05003260 anc &= mask
3261
Russ Cox382b44e2015-02-23 16:07:24 -05003262 q1 := two31 / anc
3263 r1 := two31 - q1*anc
Russ Cox8c195bd2015-02-13 14:40:36 -05003264 q1 &= mask
3265 r1 &= mask
3266
Russ Cox382b44e2015-02-23 16:07:24 -05003267 q2 := two31 / ad
3268 r2 := two31 - q2*ad
Russ Cox8c195bd2015-02-13 14:40:36 -05003269 q2 &= mask
3270 r2 &= mask
3271
Russ Cox382b44e2015-02-23 16:07:24 -05003272 var delta uint64
Russ Cox8c195bd2015-02-13 14:40:36 -05003273 for {
3274 p++
3275 q1 <<= 1
3276 r1 <<= 1
3277 q1 &= mask
3278 r1 &= mask
3279 if r1 >= anc {
3280 q1++
3281 r1 -= anc
3282 q1 &= mask
3283 r1 &= mask
3284 }
3285
3286 q2 <<= 1
3287 r2 <<= 1
3288 q2 &= mask
3289 r2 &= mask
3290 if r2 >= ad {
3291 q2++
3292 r2 -= ad
3293 q2 &= mask
3294 r2 &= mask
3295 }
3296
3297 delta = ad - r2
3298 delta &= mask
3299 if q1 < delta || (q1 == delta && r1 == 0) {
3300 continue
3301 }
3302
3303 break
3304 }
3305
3306 m.Sm = int64(q2 + 1)
3307 if uint64(m.Sm)&two31 != 0 {
3308 m.Sm |= ^int64(mask)
3309 }
3310 m.S = p - m.W
3311}
3312
3313/*
3314 * magic number for unsigned division
3315 * see hacker's delight chapter 10
3316 */
3317func Umagic(m *Magic) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003318 var mask uint64
Russ Cox8c195bd2015-02-13 14:40:36 -05003319
3320 m.Bad = 0
3321 m.Ua = 0
3322
3323 switch m.W {
3324 default:
3325 m.Bad = 1
3326 return
3327
3328 case 8:
3329 mask = 0xff
3330
3331 case 16:
3332 mask = 0xffff
3333
3334 case 32:
3335 mask = 0xffffffff
3336
3337 case 64:
3338 mask = 0xffffffffffffffff
3339 }
3340
Russ Cox382b44e2015-02-23 16:07:24 -05003341 two31 := mask ^ (mask >> 1)
Russ Cox8c195bd2015-02-13 14:40:36 -05003342
3343 m.Ud &= mask
3344 if m.Ud == 0 || m.Ud == two31 {
3345 m.Bad = 1
3346 return
3347 }
3348
Russ Cox382b44e2015-02-23 16:07:24 -05003349 nc := mask - (-m.Ud&mask)%m.Ud
3350 p := m.W - 1
Russ Cox8c195bd2015-02-13 14:40:36 -05003351
Russ Cox382b44e2015-02-23 16:07:24 -05003352 q1 := two31 / nc
3353 r1 := two31 - q1*nc
Russ Cox8c195bd2015-02-13 14:40:36 -05003354 q1 &= mask
3355 r1 &= mask
3356
Russ Cox382b44e2015-02-23 16:07:24 -05003357 q2 := (two31 - 1) / m.Ud
3358 r2 := (two31 - 1) - q2*m.Ud
Russ Cox8c195bd2015-02-13 14:40:36 -05003359 q2 &= mask
3360 r2 &= mask
3361
Russ Cox382b44e2015-02-23 16:07:24 -05003362 var delta uint64
Russ Cox8c195bd2015-02-13 14:40:36 -05003363 for {
3364 p++
3365 if r1 >= nc-r1 {
3366 q1 <<= 1
3367 q1++
3368 r1 <<= 1
3369 r1 -= nc
3370 } else {
3371 q1 <<= 1
3372 r1 <<= 1
3373 }
3374
3375 q1 &= mask
3376 r1 &= mask
3377 if r2+1 >= m.Ud-r2 {
3378 if q2 >= two31-1 {
3379 m.Ua = 1
3380 }
3381
3382 q2 <<= 1
3383 q2++
3384 r2 <<= 1
3385 r2++
3386 r2 -= m.Ud
3387 } else {
3388 if q2 >= two31 {
3389 m.Ua = 1
3390 }
3391
3392 q2 <<= 1
3393 r2 <<= 1
3394 r2++
3395 }
3396
3397 q2 &= mask
3398 r2 &= mask
3399
3400 delta = m.Ud - 1 - r2
3401 delta &= mask
3402
3403 if p < m.W+m.W {
3404 if q1 < delta || (q1 == delta && r1 == 0) {
3405 continue
3406 }
3407 }
3408
3409 break
3410 }
3411
3412 m.Um = q2 + 1
3413 m.S = p - m.W
3414}
3415
3416func ngotype(n *Node) *Sym {
3417 if n.Type != nil {
3418 return typenamesym(n.Type)
3419 }
3420 return nil
3421}
3422
3423/*
3424 * Convert raw string to the prefix that will be used in the symbol
3425 * table. All control characters, space, '%' and '"', as well as
3426 * non-7-bit clean bytes turn into %xx. The period needs escaping
3427 * only in the last segment of the path, and it makes for happier
3428 * users if we escape that as little as possible.
3429 *
3430 * If you edit this, edit ../ld/lib.c:/^pathtoprefix too.
3431 * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
3432 */
3433func pathtoprefix(s string) string {
3434 slash := strings.LastIndex(s, "/")
3435 for i := 0; i < len(s); i++ {
3436 c := s[i]
3437 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
Russ Cox79f727a2015-03-02 12:35:15 -05003438 var buf bytes.Buffer
3439 for i := 0; i < len(s); i++ {
3440 c := s[i]
3441 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
3442 fmt.Fprintf(&buf, "%%%02x", c)
3443 continue
3444 }
3445 buf.WriteByte(c)
3446 }
3447 return buf.String()
Russ Cox8c195bd2015-02-13 14:40:36 -05003448 }
3449 }
3450 return s
Russ Cox8c195bd2015-02-13 14:40:36 -05003451}
3452
Russ Coxd0b59de2015-03-02 16:21:15 -05003453var pkgMap = make(map[string]*Pkg)
3454var pkgs []*Pkg
3455
Russ Coxbed1f902015-03-02 16:03:26 -05003456func mkpkg(path string) *Pkg {
Russ Coxd0b59de2015-03-02 16:21:15 -05003457 if p := pkgMap[path]; p != nil {
3458 return p
Russ Cox8c195bd2015-02-13 14:40:36 -05003459 }
3460
Russ Cox382b44e2015-02-23 16:07:24 -05003461 p := new(Pkg)
Russ Coxbed1f902015-03-02 16:03:26 -05003462 p.Path = path
3463 p.Prefix = pathtoprefix(path)
Russ Coxc8198342015-03-12 18:45:30 -04003464 p.Syms = make(map[string]*Sym)
Russ Coxd0b59de2015-03-02 16:21:15 -05003465 pkgMap[path] = p
3466 pkgs = append(pkgs, p)
Russ Cox8c195bd2015-02-13 14:40:36 -05003467 return p
3468}
3469
Russ Cox8c195bd2015-02-13 14:40:36 -05003470func addinit(np **Node, init *NodeList) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003471 if init == nil {
3472 return
3473 }
3474
Russ Cox382b44e2015-02-23 16:07:24 -05003475 n := *np
Russ Cox8c195bd2015-02-13 14:40:36 -05003476 switch n.Op {
3477 // There may be multiple refs to this node;
3478 // introduce OCONVNOP to hold init list.
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -07003479 case ONAME, OLITERAL:
Russ Cox8c195bd2015-02-13 14:40:36 -05003480 n = Nod(OCONVNOP, n, nil)
3481
3482 n.Type = n.Left.Type
3483 n.Typecheck = 1
3484 *np = n
3485 }
3486
3487 n.Ninit = concat(init, n.Ninit)
3488 n.Ullman = UINF
3489}
3490
3491var reservedimports = []string{
3492 "go",
3493 "type",
3494}
3495
Russ Coxbed1f902015-03-02 16:03:26 -05003496func isbadimport(path string) bool {
3497 if strings.Contains(path, "\x00") {
Russ Cox8c195bd2015-02-13 14:40:36 -05003498 Yyerror("import path contains NUL")
3499 return true
3500 }
3501
Russ Cox382b44e2015-02-23 16:07:24 -05003502 for i := 0; i < len(reservedimports); i++ {
Russ Coxbed1f902015-03-02 16:03:26 -05003503 if path == reservedimports[i] {
3504 Yyerror("import path %q is reserved and cannot be used", path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003505 return true
3506 }
3507 }
3508
Russ Cox382b44e2015-02-23 16:07:24 -05003509 var s string
Russ Cox8c195bd2015-02-13 14:40:36 -05003510 _ = s
Russ Cox382b44e2015-02-23 16:07:24 -05003511 var r uint
Russ Cox8c195bd2015-02-13 14:40:36 -05003512 _ = r
Russ Coxbed1f902015-03-02 16:03:26 -05003513 for _, r := range path {
Russ Cox8c195bd2015-02-13 14:40:36 -05003514 if r == utf8.RuneError {
Russ Coxbed1f902015-03-02 16:03:26 -05003515 Yyerror("import path contains invalid UTF-8 sequence: %q", path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003516 return true
3517 }
3518
3519 if r < 0x20 || r == 0x7f {
Russ Coxbed1f902015-03-02 16:03:26 -05003520 Yyerror("import path contains control character: %q", path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003521 return true
3522 }
3523
3524 if r == '\\' {
Russ Coxbed1f902015-03-02 16:03:26 -05003525 Yyerror("import path contains backslash; use slash: %q", path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003526 return true
3527 }
3528
3529 if unicode.IsSpace(rune(r)) {
Russ Coxbed1f902015-03-02 16:03:26 -05003530 Yyerror("import path contains space character: %q", path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003531 return true
3532 }
3533
3534 if strings.ContainsRune("!\"#$%&'()*,:;<=>?[]^`{|}", r) {
Russ Coxbed1f902015-03-02 16:03:26 -05003535 Yyerror("import path contains invalid character '%c': %q", r, path)
Russ Cox8c195bd2015-02-13 14:40:36 -05003536 return true
3537 }
3538 }
3539
3540 return false
3541}
3542
3543func checknil(x *Node, init **NodeList) {
Russ Coxdc7b54b2015-02-17 22:13:49 -05003544 if Isinter(x.Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -05003545 x = Nod(OITAB, x, nil)
3546 typecheck(&x, Erv)
3547 }
3548
Russ Cox382b44e2015-02-23 16:07:24 -05003549 n := Nod(OCHECKNIL, x, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05003550 n.Typecheck = 1
3551 *init = list(*init, n)
3552}
3553
3554/*
3555 * Can this type be stored directly in an interface word?
3556 * Yes, if the representation is a single pointer.
3557 */
Russ Coxdc7b54b2015-02-17 22:13:49 -05003558func isdirectiface(t *Type) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05003559 switch t.Etype {
3560 case TPTR32,
3561 TPTR64,
3562 TCHAN,
3563 TMAP,
3564 TFUNC,
3565 TUNSAFEPTR:
Russ Coxdc7b54b2015-02-17 22:13:49 -05003566 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05003567
3568 // Array of 1 direct iface type can be direct.
3569 case TARRAY:
Russ Coxdc7b54b2015-02-17 22:13:49 -05003570 return t.Bound == 1 && isdirectiface(t.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05003571
3572 // Struct with 1 field of direct iface type can be direct.
3573 case TSTRUCT:
Russ Coxdc7b54b2015-02-17 22:13:49 -05003574 return t.Type != nil && t.Type.Down == nil && isdirectiface(t.Type.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05003575 }
3576
Russ Coxdc7b54b2015-02-17 22:13:49 -05003577 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05003578}
Josh Bleecher Snyder55b45162015-03-17 13:56:29 -07003579
Russ Cox01af7272015-03-19 23:38:24 +00003580// type2IET returns "T" if t is a concrete type,
3581// "I" if t is an interface type, and "E" if t is an empty interface type.
Josh Bleecher Snyder55b45162015-03-17 13:56:29 -07003582// It is used to build calls to the conv* and assert* runtime routines.
Russ Cox01af7272015-03-19 23:38:24 +00003583func type2IET(t *Type) string {
Josh Bleecher Snyder55b45162015-03-17 13:56:29 -07003584 if isnilinter(t) {
3585 return "E"
3586 }
3587 if Isinter(t) {
3588 return "I"
3589 }
3590 return "T"
3591}