1 // Do not edit. Bootstrap copy of /usr/local/google/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/gc/fmt.go 2 3 //line /usr/local/google/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/gc/fmt.go:1 4 // Copyright 2011 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package gc 9 10 import ( 11 "bytes" 12 "bootstrap/internal/obj" 13 "fmt" 14 "strconv" 15 "strings" 16 "unicode/utf8" 17 ) 18 19 // 20 // Format conversions 21 // %L int Line numbers 22 // 23 // %E int etype values (aka 'Kind') 24 // 25 // %O int Node Opcodes 26 // Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg) 27 // 28 // %J Node* Node details 29 // Flags: "%hJ" suppresses things not relevant until walk. 30 // 31 // %V Val* Constant values 32 // 33 // %S Sym* Symbols 34 // Flags: +,- #: mode (see below) 35 // "%hS" unqualified identifier in any mode 36 // "%hhS" in export mode: unqualified identifier if exported, qualified if not 37 // 38 // %T Type* Types 39 // Flags: +,- #: mode (see below) 40 // 'l' definition instead of name. 41 // 'h' omit "func" and receiver in function types 42 // 'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix. 43 // 44 // %N Node* Nodes 45 // Flags: +,- #: mode (see below) 46 // 'h' (only in +/debug mode) suppress recursion 47 // 'l' (only in Error mode) print "foo (type Bar)" 48 // 49 // %H NodeList* NodeLists 50 // Flags: those of %N 51 // ',' separate items with ',' instead of ';' 52 // 53 // In mparith1.c: 54 // %B Mpint* Big integers 55 // %F Mpflt* Big floats 56 // 57 // %S, %T and %N obey use the following flags to set the format mode: 58 const ( 59 FErr = iota 60 FDbg 61 FExp 62 FTypeId 63 ) 64 65 var fmtmode int = FErr 66 67 var fmtpkgpfx int // %uT stickyness 68 69 // 70 // E.g. for %S: %+S %#S %-S print an identifier properly qualified for debug/export/internal mode. 71 // 72 // The mode flags +, - and # are sticky, meaning they persist through 73 // recursions of %N, %T and %S, but not the h and l flags. The u flag is 74 // sticky only on %T recursions and only used in %-/Sym mode. 75 76 // 77 // Useful format combinations: 78 // 79 // %+N %+H multiline recursive debug dump of node/nodelist 80 // %+hN %+hH non recursive debug dump 81 // 82 // %#N %#T export format 83 // %#lT type definition instead of name 84 // %#hT omit"func" and receiver in function signature 85 // 86 // %lN "foo (type Bar)" for error messages 87 // 88 // %-T type identifiers 89 // %-hT type identifiers without "func" and arg names in type signatures (methodsym) 90 // %-uT type identifiers with package name instead of prefix (typesym, dcommontype, typehash) 91 // 92 93 func setfmode(flags *int) int { 94 fm := fmtmode 95 if *flags&obj.FmtSign != 0 { 96 fmtmode = FDbg 97 } else if *flags&obj.FmtSharp != 0 { 98 fmtmode = FExp 99 } else if *flags&obj.FmtLeft != 0 { 100 fmtmode = FTypeId 101 } 102 103 *flags &^= (obj.FmtSharp | obj.FmtLeft | obj.FmtSign) 104 return fm 105 } 106 107 // Fmt "%L": Linenumbers 108 109 var goopnames = []string{ 110 OADDR: "&", 111 OADD: "+", 112 OADDSTR: "+", 113 OANDAND: "&&", 114 OANDNOT: "&^", 115 OAND: "&", 116 OAPPEND: "append", 117 OAS: "=", 118 OAS2: "=", 119 OBREAK: "break", 120 OCALL: "function call", // not actual syntax 121 OCAP: "cap", 122 OCASE: "case", 123 OCLOSE: "close", 124 OCOMPLEX: "complex", 125 OCOM: "^", 126 OCONTINUE: "continue", 127 OCOPY: "copy", 128 ODEC: "--", 129 ODELETE: "delete", 130 ODEFER: "defer", 131 ODIV: "/", 132 OEQ: "==", 133 OFALL: "fallthrough", 134 OFOR: "for", 135 OGE: ">=", 136 OGOTO: "goto", 137 OGT: ">", 138 OIF: "if", 139 OIMAG: "imag", 140 OINC: "++", 141 OIND: "*", 142 OLEN: "len", 143 OLE: "<=", 144 OLSH: "<<", 145 OLT: "<", 146 OMAKE: "make", 147 OMINUS: "-", 148 OMOD: "%", 149 OMUL: "*", 150 ONEW: "new", 151 ONE: "!=", 152 ONOT: "!", 153 OOROR: "||", 154 OOR: "|", 155 OPANIC: "panic", 156 OPLUS: "+", 157 OPRINTN: "println", 158 OPRINT: "print", 159 ORANGE: "range", 160 OREAL: "real", 161 ORECV: "<-", 162 ORECOVER: "recover", 163 ORETURN: "return", 164 ORSH: ">>", 165 OSELECT: "select", 166 OSEND: "<-", 167 OSUB: "-", 168 OSWITCH: "switch", 169 OXOR: "^", 170 } 171 172 // Fmt "%O": Node opcodes 173 func Oconv(o int, flag int) string { 174 if (flag&obj.FmtSharp != 0) || fmtmode != FDbg { 175 if o >= 0 && o < len(goopnames) && goopnames[o] != "" { 176 return goopnames[o] 177 } 178 } 179 180 if o >= 0 && o < len(opnames) && opnames[o] != "" { 181 return opnames[o] 182 } 183 184 return fmt.Sprintf("O-%d", o) 185 } 186 187 var classnames = []string{ 188 "Pxxx", 189 "PEXTERN", 190 "PAUTO", 191 "PPARAM", 192 "PPARAMOUT", 193 "PPARAMREF", 194 "PFUNC", 195 } 196 197 // Fmt "%J": Node details. 198 func Jconv(n *Node, flag int) string { 199 var buf bytes.Buffer 200 201 c := flag & obj.FmtShort 202 203 if c == 0 && n.Ullman != 0 { 204 fmt.Fprintf(&buf, " u(%d)", n.Ullman) 205 } 206 207 if c == 0 && n.Addable { 208 fmt.Fprintf(&buf, " a(%v)", n.Addable) 209 } 210 211 if c == 0 && n.Name != nil && n.Name.Vargen != 0 { 212 fmt.Fprintf(&buf, " g(%d)", n.Name.Vargen) 213 } 214 215 if n.Lineno != 0 { 216 fmt.Fprintf(&buf, " l(%d)", n.Lineno) 217 } 218 219 if c == 0 && n.Xoffset != BADWIDTH { 220 fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, stkdelta[n]) 221 } 222 223 if n.Class != 0 { 224 s := "" 225 if n.Class&PHEAP != 0 { 226 s = ",heap" 227 } 228 if int(n.Class&^PHEAP) < len(classnames) { 229 fmt.Fprintf(&buf, " class(%s%s)", classnames[n.Class&^PHEAP], s) 230 } else { 231 fmt.Fprintf(&buf, " class(%d?%s)", n.Class&^PHEAP, s) 232 } 233 } 234 235 if n.Colas { 236 fmt.Fprintf(&buf, " colas(%v)", n.Colas) 237 } 238 239 if n.Name != nil && n.Name.Funcdepth != 0 { 240 fmt.Fprintf(&buf, " f(%d)", n.Name.Funcdepth) 241 } 242 if n.Func != nil && n.Func.Depth != 0 { 243 fmt.Fprintf(&buf, " ff(%d)", n.Func.Depth) 244 } 245 246 switch n.Esc { 247 case EscUnknown: 248 break 249 250 case EscHeap: 251 buf.WriteString(" esc(h)") 252 253 case EscScope: 254 buf.WriteString(" esc(s)") 255 256 case EscNone: 257 buf.WriteString(" esc(no)") 258 259 case EscNever: 260 if c == 0 { 261 buf.WriteString(" esc(N)") 262 } 263 264 default: 265 fmt.Fprintf(&buf, " esc(%d)", n.Esc) 266 } 267 268 if e, ok := n.Opt().(*NodeEscState); ok && e.Escloopdepth != 0 { 269 fmt.Fprintf(&buf, " ld(%d)", e.Escloopdepth) 270 } 271 272 if c == 0 && n.Typecheck != 0 { 273 fmt.Fprintf(&buf, " tc(%d)", n.Typecheck) 274 } 275 276 if c == 0 && n.Dodata != 0 { 277 fmt.Fprintf(&buf, " dd(%d)", n.Dodata) 278 } 279 280 if n.Isddd { 281 fmt.Fprintf(&buf, " isddd(%v)", n.Isddd) 282 } 283 284 if n.Implicit { 285 fmt.Fprintf(&buf, " implicit(%v)", n.Implicit) 286 } 287 288 if n.Embedded != 0 { 289 fmt.Fprintf(&buf, " embedded(%d)", n.Embedded) 290 } 291 292 if n.Addrtaken { 293 buf.WriteString(" addrtaken") 294 } 295 296 if n.Assigned { 297 buf.WriteString(" assigned") 298 } 299 300 if c == 0 && n.Used { 301 fmt.Fprintf(&buf, " used(%v)", n.Used) 302 } 303 return buf.String() 304 } 305 306 // Fmt "%V": Values 307 func Vconv(v Val, flag int) string { 308 switch v.Ctype() { 309 case CTINT: 310 if (flag&obj.FmtSharp != 0) || fmtmode == FExp { 311 return Bconv(v.U.(*Mpint), obj.FmtSharp) 312 } 313 return Bconv(v.U.(*Mpint), 0) 314 315 case CTRUNE: 316 x := Mpgetfix(v.U.(*Mpint)) 317 if ' ' <= x && x < 0x80 && x != '\\' && x != '\'' { 318 return fmt.Sprintf("'%c'", int(x)) 319 } 320 if 0 <= x && x < 1<<16 { 321 return fmt.Sprintf("'\\u%04x'", uint(int(x))) 322 } 323 if 0 <= x && x <= utf8.MaxRune { 324 return fmt.Sprintf("'\\U%08x'", uint64(x)) 325 } 326 return fmt.Sprintf("('\\x00' + %v)", v.U.(*Mpint)) 327 328 case CTFLT: 329 if (flag&obj.FmtSharp != 0) || fmtmode == FExp { 330 return Fconv(v.U.(*Mpflt), 0) 331 } 332 return Fconv(v.U.(*Mpflt), obj.FmtSharp) 333 334 case CTCPLX: 335 if (flag&obj.FmtSharp != 0) || fmtmode == FExp { 336 return fmt.Sprintf("(%v+%vi)", &v.U.(*Mpcplx).Real, &v.U.(*Mpcplx).Imag) 337 } 338 if mpcmpfltc(&v.U.(*Mpcplx).Real, 0) == 0 { 339 return fmt.Sprintf("%vi", Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp)) 340 } 341 if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) == 0 { 342 return Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp) 343 } 344 if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) < 0 { 345 return fmt.Sprintf("(%v%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp)) 346 } 347 return fmt.Sprintf("(%v+%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp)) 348 349 case CTSTR: 350 return strconv.Quote(v.U.(string)) 351 352 case CTBOOL: 353 if v.U.(bool) { 354 return "true" 355 } 356 return "false" 357 358 case CTNIL: 359 return "nil" 360 } 361 362 return fmt.Sprintf("<ctype=%d>", v.Ctype) 363 } 364 365 /* 366 s%,%,\n%g 367 s%\n+%\n%g 368 s%^[ ]*T%%g 369 s%,.*%%g 370 s%.+% [T&] = "&",%g 371 s%^ ........*\]%&~%g 372 s%~ %%g 373 */ 374 var etnames = []string{ 375 TINT: "INT", 376 TUINT: "UINT", 377 TINT8: "INT8", 378 TUINT8: "UINT8", 379 TINT16: "INT16", 380 TUINT16: "UINT16", 381 TINT32: "INT32", 382 TUINT32: "UINT32", 383 TINT64: "INT64", 384 TUINT64: "UINT64", 385 TUINTPTR: "UINTPTR", 386 TFLOAT32: "FLOAT32", 387 TFLOAT64: "FLOAT64", 388 TCOMPLEX64: "COMPLEX64", 389 TCOMPLEX128: "COMPLEX128", 390 TBOOL: "BOOL", 391 TPTR32: "PTR32", 392 TPTR64: "PTR64", 393 TFUNC: "FUNC", 394 TARRAY: "ARRAY", 395 TSTRUCT: "STRUCT", 396 TCHAN: "CHAN", 397 TMAP: "MAP", 398 TINTER: "INTER", 399 TFORW: "FORW", 400 TFIELD: "FIELD", 401 TSTRING: "STRING", 402 TANY: "ANY", 403 } 404 405 // Fmt "%E": etype 406 func Econv(et int, flag int) string { 407 if et >= 0 && et < len(etnames) && etnames[et] != "" { 408 return etnames[et] 409 } 410 return fmt.Sprintf("E-%d", et) 411 } 412 413 // Fmt "%S": syms 414 func symfmt(s *Sym, flag int) string { 415 if s.Pkg != nil && flag&obj.FmtShort == 0 { 416 switch fmtmode { 417 case FErr: // This is for the user 418 if s.Pkg == localpkg { 419 return s.Name 420 } 421 422 // If the name was used by multiple packages, display the full path, 423 if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 { 424 return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name) 425 } 426 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name) 427 428 case FDbg: 429 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name) 430 431 case FTypeId: 432 if flag&obj.FmtUnsigned != 0 { 433 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name) // dcommontype, typehash 434 } 435 return fmt.Sprintf("%s.%s", s.Pkg.Prefix, s.Name) // (methodsym), typesym, weaksym 436 437 case FExp: 438 if s.Name != "" && s.Name[0] == '.' { 439 Fatal("exporting synthetic symbol %s", s.Name) 440 } 441 if s.Pkg != builtinpkg { 442 return fmt.Sprintf("@%q.%s", s.Pkg.Path, s.Name) 443 } 444 } 445 } 446 447 if flag&obj.FmtByte != 0 { 448 // FmtByte (hh) implies FmtShort (h) 449 // skip leading "type." in method name 450 p := s.Name 451 if i := strings.LastIndex(s.Name, "."); i >= 0 { 452 p = s.Name[i+1:] 453 } 454 455 // exportname needs to see the name without the prefix too. 456 if (fmtmode == FExp && !exportname(p)) || fmtmode == FDbg { 457 return fmt.Sprintf("@%q.%s", s.Pkg.Path, p) 458 } 459 460 return p 461 } 462 463 return s.Name 464 } 465 466 var basicnames = []string{ 467 TINT: "int", 468 TUINT: "uint", 469 TINT8: "int8", 470 TUINT8: "uint8", 471 TINT16: "int16", 472 TUINT16: "uint16", 473 TINT32: "int32", 474 TUINT32: "uint32", 475 TINT64: "int64", 476 TUINT64: "uint64", 477 TUINTPTR: "uintptr", 478 TFLOAT32: "float32", 479 TFLOAT64: "float64", 480 TCOMPLEX64: "complex64", 481 TCOMPLEX128: "complex128", 482 TBOOL: "bool", 483 TANY: "any", 484 TSTRING: "string", 485 TNIL: "nil", 486 TIDEAL: "untyped number", 487 TBLANK: "blank", 488 } 489 490 func typefmt(t *Type, flag int) string { 491 if t == nil { 492 return "<T>" 493 } 494 495 if t == bytetype || t == runetype { 496 // in %-T mode collapse rune and byte with their originals. 497 if fmtmode != FTypeId { 498 return Sconv(t.Sym, obj.FmtShort) 499 } 500 t = Types[t.Etype] 501 } 502 503 if t == errortype { 504 return "error" 505 } 506 507 // Unless the 'l' flag was specified, if the type has a name, just print that name. 508 if flag&obj.FmtLong == 0 && t.Sym != nil && t.Etype != TFIELD && t != Types[t.Etype] { 509 switch fmtmode { 510 case FTypeId: 511 if flag&obj.FmtShort != 0 { 512 if t.Vargen != 0 { 513 return fmt.Sprintf("%v%d", Sconv(t.Sym, obj.FmtShort), t.Vargen) 514 } 515 return Sconv(t.Sym, obj.FmtShort) 516 } 517 518 if flag&obj.FmtUnsigned != 0 { 519 return Sconv(t.Sym, obj.FmtUnsigned) 520 } 521 fallthrough 522 523 case FExp: 524 if t.Sym.Pkg == localpkg && t.Vargen != 0 { 525 return fmt.Sprintf("%v%d", t.Sym, t.Vargen) 526 } 527 } 528 529 return Sconv(t.Sym, 0) 530 } 531 532 if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" { 533 prefix := "" 534 if fmtmode == FErr && (t == idealbool || t == idealstring) { 535 prefix = "untyped " 536 } 537 return prefix + basicnames[t.Etype] 538 } 539 540 if fmtmode == FDbg { 541 fmtmode = 0 542 str := Econv(int(t.Etype), 0) + "-" + typefmt(t, flag) 543 fmtmode = FDbg 544 return str 545 } 546 547 switch t.Etype { 548 case TPTR32, TPTR64: 549 if fmtmode == FTypeId && (flag&obj.FmtShort != 0) { 550 return fmt.Sprintf("*%v", Tconv(t.Type, obj.FmtShort)) 551 } 552 return fmt.Sprintf("*%v", t.Type) 553 554 case TARRAY: 555 if t.Bound >= 0 { 556 return fmt.Sprintf("[%d]%v", t.Bound, t.Type) 557 } 558 if t.Bound == -100 { 559 return fmt.Sprintf("[...]%v", t.Type) 560 } 561 return fmt.Sprintf("[]%v", t.Type) 562 563 case TCHAN: 564 switch t.Chan { 565 case Crecv: 566 return fmt.Sprintf("<-chan %v", t.Type) 567 568 case Csend: 569 return fmt.Sprintf("chan<- %v", t.Type) 570 } 571 572 if t.Type != nil && t.Type.Etype == TCHAN && t.Type.Sym == nil && t.Type.Chan == Crecv { 573 return fmt.Sprintf("chan (%v)", t.Type) 574 } 575 return fmt.Sprintf("chan %v", t.Type) 576 577 case TMAP: 578 return fmt.Sprintf("map[%v]%v", t.Down, t.Type) 579 580 case TINTER: 581 var buf bytes.Buffer 582 buf.WriteString("interface {") 583 for t1 := t.Type; t1 != nil; t1 = t1.Down { 584 buf.WriteString(" ") 585 if exportname(t1.Sym.Name) { 586 buf.WriteString(Sconv(t1.Sym, obj.FmtShort)) 587 } else { 588 buf.WriteString(Sconv(t1.Sym, obj.FmtUnsigned)) 589 } 590 buf.WriteString(Tconv(t1.Type, obj.FmtShort)) 591 if t1.Down != nil { 592 buf.WriteString(";") 593 } 594 } 595 if t.Type != nil { 596 buf.WriteString(" ") 597 } 598 buf.WriteString("}") 599 return buf.String() 600 601 case TFUNC: 602 var buf bytes.Buffer 603 if flag&obj.FmtShort != 0 { 604 // no leading func 605 } else { 606 if t.Thistuple != 0 { 607 buf.WriteString("method") 608 buf.WriteString(Tconv(getthisx(t), 0)) 609 buf.WriteString(" ") 610 } 611 buf.WriteString("func") 612 } 613 buf.WriteString(Tconv(getinargx(t), 0)) 614 615 switch t.Outtuple { 616 case 0: 617 break 618 619 case 1: 620 if fmtmode != FExp { 621 buf.WriteString(" ") 622 buf.WriteString(Tconv(getoutargx(t).Type.Type, 0)) // struct->field->field's type 623 break 624 } 625 fallthrough 626 627 default: 628 buf.WriteString(" ") 629 buf.WriteString(Tconv(getoutargx(t), 0)) 630 } 631 return buf.String() 632 633 case TSTRUCT: 634 if t.Map != nil { 635 // Format the bucket struct for map[x]y as map.bucket[x]y. 636 // This avoids a recursive print that generates very long names. 637 if t.Map.Bucket == t { 638 return fmt.Sprintf("map.bucket[%v]%v", t.Map.Down, t.Map.Type) 639 } 640 641 if t.Map.Hmap == t { 642 return fmt.Sprintf("map.hdr[%v]%v", t.Map.Down, t.Map.Type) 643 } 644 645 if t.Map.Hiter == t { 646 return fmt.Sprintf("map.iter[%v]%v", t.Map.Down, t.Map.Type) 647 } 648 649 Yyerror("unknown internal map type") 650 } 651 652 var buf bytes.Buffer 653 if t.Funarg != 0 { 654 buf.WriteString("(") 655 if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags 656 for t1 := t.Type; t1 != nil; t1 = t1.Down { 657 buf.WriteString(Tconv(t1, obj.FmtShort)) 658 if t1.Down != nil { 659 buf.WriteString(", ") 660 } 661 } 662 } else { 663 for t1 := t.Type; t1 != nil; t1 = t1.Down { 664 buf.WriteString(Tconv(t1, 0)) 665 if t1.Down != nil { 666 buf.WriteString(", ") 667 } 668 } 669 } 670 buf.WriteString(")") 671 } else { 672 buf.WriteString("struct {") 673 for t1 := t.Type; t1 != nil; t1 = t1.Down { 674 buf.WriteString(" ") 675 buf.WriteString(Tconv(t1, obj.FmtLong)) 676 if t1.Down != nil { 677 buf.WriteString(";") 678 } 679 } 680 if t.Type != nil { 681 buf.WriteString(" ") 682 } 683 buf.WriteString("}") 684 } 685 return buf.String() 686 687 case TFIELD: 688 var name string 689 if flag&obj.FmtShort == 0 { 690 s := t.Sym 691 692 // Take the name from the original, lest we substituted it with ~r%d or ~b%d. 693 // ~r%d is a (formerly) unnamed result. 694 if (fmtmode == FErr || fmtmode == FExp) && t.Nname != nil { 695 if t.Nname.Orig != nil { 696 s = t.Nname.Orig.Sym 697 if s != nil && s.Name[0] == '~' { 698 if s.Name[1] == 'r' { // originally an unnamed result 699 s = nil 700 } else if s.Name[1] == 'b' { // originally the blank identifier _ 701 s = Lookup("_") 702 } 703 } 704 } else { 705 s = nil 706 } 707 } 708 709 if s != nil && t.Embedded == 0 { 710 if t.Funarg != 0 { 711 name = Nconv(t.Nname, 0) 712 } else if flag&obj.FmtLong != 0 { 713 name = Sconv(s, obj.FmtShort|obj.FmtByte) // qualify non-exported names (used on structs, not on funarg) 714 } else { 715 name = Sconv(s, 0) 716 } 717 } else if fmtmode == FExp { 718 // TODO(rsc) this breaks on the eliding of unused arguments in the backend 719 // when this is fixed, the special case in dcl.c checkarglist can go. 720 //if(t->funarg) 721 // fmtstrcpy(fp, "_ "); 722 //else 723 if t.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 { 724 name = fmt.Sprintf("@%q.?", s.Pkg.Path) 725 } else { 726 name = "?" 727 } 728 } 729 } 730 731 var typ string 732 if t.Isddd { 733 typ = "..." + Tconv(t.Type.Type, 0) 734 } else { 735 typ = Tconv(t.Type, 0) 736 } 737 738 str := typ 739 if name != "" { 740 str = name + " " + typ 741 } 742 if flag&obj.FmtShort == 0 && t.Note != nil { 743 str += " " + strconv.Quote(*t.Note) 744 } 745 return str 746 747 case TFORW: 748 if t.Sym != nil { 749 return fmt.Sprintf("undefined %v", t.Sym) 750 } 751 return "undefined" 752 753 case TUNSAFEPTR: 754 if fmtmode == FExp { 755 return "@\"unsafe\".Pointer" 756 } 757 return "unsafe.Pointer" 758 } 759 760 if fmtmode == FExp { 761 Fatal("missing %v case during export", Econv(int(t.Etype), 0)) 762 } 763 764 // Don't know how to handle - fall back to detailed prints. 765 return fmt.Sprintf("%v <%v> %v", Econv(int(t.Etype), 0), t.Sym, t.Type) 766 } 767 768 // Statements which may be rendered with a simplestmt as init. 769 func stmtwithinit(op int) bool { 770 switch op { 771 case OIF, OFOR, OSWITCH: 772 return true 773 } 774 775 return false 776 } 777 778 func stmtfmt(n *Node) string { 779 var f string 780 781 // some statements allow for an init, but at most one, 782 // but we may have an arbitrary number added, eg by typecheck 783 // and inlining. If it doesn't fit the syntax, emit an enclosing 784 // block starting with the init statements. 785 786 // if we can just say "for" n->ninit; ... then do so 787 simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(int(n.Op)) 788 789 // otherwise, print the inits as separate statements 790 complexinit := n.Ninit != nil && !simpleinit && (fmtmode != FErr) 791 792 // but if it was for if/for/switch, put in an extra surrounding block to limit the scope 793 extrablock := complexinit && stmtwithinit(int(n.Op)) 794 795 if extrablock { 796 f += "{" 797 } 798 799 if complexinit { 800 f += fmt.Sprintf(" %v; ", n.Ninit) 801 } 802 803 switch n.Op { 804 case ODCL: 805 if fmtmode == FExp { 806 switch n.Left.Class &^ PHEAP { 807 case PPARAM, PPARAMOUT, PAUTO: 808 f += fmt.Sprintf("var %v %v", n.Left, n.Left.Type) 809 goto ret 810 } 811 } 812 813 f += fmt.Sprintf("var %v %v", n.Left.Sym, n.Left.Type) 814 815 case ODCLFIELD: 816 if n.Left != nil { 817 f += fmt.Sprintf("%v %v", n.Left, n.Right) 818 } else { 819 f += Nconv(n.Right, 0) 820 } 821 822 // Don't export "v = <N>" initializing statements, hope they're always 823 // preceded by the DCL which will be re-parsed and typecheck to reproduce 824 // the "v = <N>" again. 825 case OAS, OASWB: 826 if fmtmode == FExp && n.Right == nil { 827 break 828 } 829 830 if n.Colas && !complexinit { 831 f += fmt.Sprintf("%v := %v", n.Left, n.Right) 832 } else { 833 f += fmt.Sprintf("%v = %v", n.Left, n.Right) 834 } 835 836 case OASOP: 837 if n.Implicit { 838 if n.Etype == OADD { 839 f += fmt.Sprintf("%v++", n.Left) 840 } else { 841 f += fmt.Sprintf("%v--", n.Left) 842 } 843 break 844 } 845 846 f += fmt.Sprintf("%v %v= %v", n.Left, Oconv(int(n.Etype), obj.FmtSharp), n.Right) 847 848 case OAS2: 849 if n.Colas && !complexinit { 850 f += fmt.Sprintf("%v := %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma)) 851 break 852 } 853 fallthrough 854 855 case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 856 f += fmt.Sprintf("%v = %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma)) 857 858 case ORETURN: 859 f += fmt.Sprintf("return %v", Hconv(n.List, obj.FmtComma)) 860 861 case ORETJMP: 862 f += fmt.Sprintf("retjmp %v", n.Sym) 863 864 case OPROC: 865 f += fmt.Sprintf("go %v", n.Left) 866 867 case ODEFER: 868 f += fmt.Sprintf("defer %v", n.Left) 869 870 case OIF: 871 if simpleinit { 872 f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Left, n.Nbody) 873 } else { 874 f += fmt.Sprintf("if %v { %v }", n.Left, n.Nbody) 875 } 876 if n.Rlist != nil { 877 f += fmt.Sprintf(" else { %v }", n.Rlist) 878 } 879 880 case OFOR: 881 if fmtmode == FErr { // TODO maybe only if FmtShort, same below 882 f += "for loop" 883 break 884 } 885 886 f += "for" 887 if simpleinit { 888 f += fmt.Sprintf(" %v;", n.Ninit.N) 889 } else if n.Right != nil { 890 f += " ;" 891 } 892 893 if n.Left != nil { 894 f += fmt.Sprintf(" %v", n.Left) 895 } 896 897 if n.Right != nil { 898 f += fmt.Sprintf("; %v", n.Right) 899 } else if simpleinit { 900 f += ";" 901 } 902 903 f += fmt.Sprintf(" { %v }", n.Nbody) 904 905 case ORANGE: 906 if fmtmode == FErr { 907 f += "for loop" 908 break 909 } 910 911 if n.List == nil { 912 f += fmt.Sprintf("for range %v { %v }", n.Right, n.Nbody) 913 break 914 } 915 916 f += fmt.Sprintf("for %v = range %v { %v }", Hconv(n.List, obj.FmtComma), n.Right, n.Nbody) 917 918 case OSELECT, OSWITCH: 919 if fmtmode == FErr { 920 f += fmt.Sprintf("%v statement", Oconv(int(n.Op), 0)) 921 break 922 } 923 924 f += Oconv(int(n.Op), obj.FmtSharp) 925 if simpleinit { 926 f += fmt.Sprintf(" %v;", n.Ninit.N) 927 } 928 if n.Left != nil { 929 f += Nconv(n.Left, 0) 930 } 931 932 f += fmt.Sprintf(" { %v }", n.List) 933 934 case OCASE, OXCASE: 935 if n.List != nil { 936 f += fmt.Sprintf("case %v: %v", Hconv(n.List, obj.FmtComma), n.Nbody) 937 } else { 938 f += fmt.Sprintf("default: %v", n.Nbody) 939 } 940 941 case OBREAK, 942 OCONTINUE, 943 OGOTO, 944 OFALL, 945 OXFALL: 946 if n.Left != nil { 947 f += fmt.Sprintf("%v %v", Oconv(int(n.Op), obj.FmtSharp), n.Left) 948 } else { 949 f += Oconv(int(n.Op), obj.FmtSharp) 950 } 951 952 case OEMPTY: 953 break 954 955 case OLABEL: 956 f += fmt.Sprintf("%v: ", n.Left) 957 } 958 959 ret: 960 if extrablock { 961 f += "}" 962 } 963 964 return f 965 } 966 967 var opprec = []int{ 968 OAPPEND: 8, 969 OARRAYBYTESTR: 8, 970 OARRAYLIT: 8, 971 OARRAYRUNESTR: 8, 972 OCALLFUNC: 8, 973 OCALLINTER: 8, 974 OCALLMETH: 8, 975 OCALL: 8, 976 OCAP: 8, 977 OCLOSE: 8, 978 OCONVIFACE: 8, 979 OCONVNOP: 8, 980 OCONV: 8, 981 OCOPY: 8, 982 ODELETE: 8, 983 OGETG: 8, 984 OLEN: 8, 985 OLITERAL: 8, 986 OMAKESLICE: 8, 987 OMAKE: 8, 988 OMAPLIT: 8, 989 ONAME: 8, 990 ONEW: 8, 991 ONONAME: 8, 992 OPACK: 8, 993 OPANIC: 8, 994 OPAREN: 8, 995 OPRINTN: 8, 996 OPRINT: 8, 997 ORUNESTR: 8, 998 OSTRARRAYBYTE: 8, 999 OSTRARRAYRUNE: 8, 1000 OSTRUCTLIT: 8, 1001 OTARRAY: 8, 1002 OTCHAN: 8, 1003 OTFUNC: 8, 1004 OTINTER: 8, 1005 OTMAP: 8, 1006 OTSTRUCT: 8, 1007 OINDEXMAP: 8, 1008 OINDEX: 8, 1009 OSLICE: 8, 1010 OSLICESTR: 8, 1011 OSLICEARR: 8, 1012 OSLICE3: 8, 1013 OSLICE3ARR: 8, 1014 ODOTINTER: 8, 1015 ODOTMETH: 8, 1016 ODOTPTR: 8, 1017 ODOTTYPE2: 8, 1018 ODOTTYPE: 8, 1019 ODOT: 8, 1020 OXDOT: 8, 1021 OCALLPART: 8, 1022 OPLUS: 7, 1023 ONOT: 7, 1024 OCOM: 7, 1025 OMINUS: 7, 1026 OADDR: 7, 1027 OIND: 7, 1028 ORECV: 7, 1029 OMUL: 6, 1030 ODIV: 6, 1031 OMOD: 6, 1032 OLSH: 6, 1033 ORSH: 6, 1034 OAND: 6, 1035 OANDNOT: 6, 1036 OADD: 5, 1037 OSUB: 5, 1038 OOR: 5, 1039 OXOR: 5, 1040 OEQ: 4, 1041 OLT: 4, 1042 OLE: 4, 1043 OGE: 4, 1044 OGT: 4, 1045 ONE: 4, 1046 OCMPSTR: 4, 1047 OCMPIFACE: 4, 1048 OSEND: 3, 1049 OANDAND: 2, 1050 OOROR: 1, 1051 // Statements handled by stmtfmt 1052 OAS: -1, 1053 OAS2: -1, 1054 OAS2DOTTYPE: -1, 1055 OAS2FUNC: -1, 1056 OAS2MAPR: -1, 1057 OAS2RECV: -1, 1058 OASOP: -1, 1059 OBREAK: -1, 1060 OCASE: -1, 1061 OCONTINUE: -1, 1062 ODCL: -1, 1063 ODCLFIELD: -1, 1064 ODEFER: -1, 1065 OEMPTY: -1, 1066 OFALL: -1, 1067 OFOR: -1, 1068 OGOTO: -1, 1069 OIF: -1, 1070 OLABEL: -1, 1071 OPROC: -1, 1072 ORANGE: -1, 1073 ORETURN: -1, 1074 OSELECT: -1, 1075 OSWITCH: -1, 1076 OXCASE: -1, 1077 OXFALL: -1, 1078 OEND: 0, 1079 } 1080 1081 func exprfmt(n *Node, prec int) string { 1082 for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) { 1083 n = n.Left 1084 } 1085 1086 if n == nil { 1087 return "<N>" 1088 } 1089 1090 nprec := opprec[n.Op] 1091 if n.Op == OTYPE && n.Sym != nil { 1092 nprec = 8 1093 } 1094 1095 if prec > nprec { 1096 return fmt.Sprintf("(%v)", n) 1097 } 1098 1099 switch n.Op { 1100 case OPAREN: 1101 return fmt.Sprintf("(%v)", n.Left) 1102 1103 case ODDDARG: 1104 return "... argument" 1105 1106 case OREGISTER: 1107 return obj.Rconv(int(n.Reg)) 1108 1109 case OLITERAL: // this is a bit of a mess 1110 if fmtmode == FErr { 1111 if n.Orig != nil && n.Orig != n { 1112 return exprfmt(n.Orig, prec) 1113 } 1114 if n.Sym != nil { 1115 return Sconv(n.Sym, 0) 1116 } 1117 } 1118 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { 1119 return exprfmt(n.Orig, prec) 1120 } 1121 if n.Type != nil && n.Type != Types[n.Type.Etype] && n.Type != idealbool && n.Type != idealstring { 1122 // Need parens when type begins with what might 1123 // be misinterpreted as a unary operator: * or <-. 1124 if Isptr[n.Type.Etype] || (n.Type.Etype == TCHAN && n.Type.Chan == Crecv) { 1125 return fmt.Sprintf("(%v)(%v)", n.Type, Vconv(n.Val(), 0)) 1126 } else { 1127 return fmt.Sprintf("%v(%v)", n.Type, Vconv(n.Val(), 0)) 1128 } 1129 } 1130 1131 return Vconv(n.Val(), 0) 1132 1133 // Special case: name used as local variable in export. 1134 // _ becomes ~b%d internally; print as _ for export 1135 case ONAME: 1136 if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' { 1137 return "_" 1138 } 1139 if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 { 1140 return fmt.Sprintf("%v%d", n.Sym, n.Name.Vargen) 1141 } 1142 1143 // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method, 1144 // but for export, this should be rendered as (*pkg.T).meth. 1145 // These nodes have the special property that they are names with a left OTYPE and a right ONAME. 1146 if fmtmode == FExp && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME { 1147 if Isptr[n.Left.Type.Etype] { 1148 return fmt.Sprintf("(%v).%v", n.Left.Type, Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte)) 1149 } else { 1150 return fmt.Sprintf("%v.%v", n.Left.Type, Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte)) 1151 } 1152 } 1153 fallthrough 1154 1155 //fallthrough 1156 case OPACK, ONONAME: 1157 return Sconv(n.Sym, 0) 1158 1159 case OTYPE: 1160 if n.Type == nil && n.Sym != nil { 1161 return Sconv(n.Sym, 0) 1162 } 1163 return Tconv(n.Type, 0) 1164 1165 case OTARRAY: 1166 if n.Left != nil { 1167 return fmt.Sprintf("[]%v", n.Left) 1168 } 1169 var f string 1170 f += fmt.Sprintf("[]%v", n.Right) 1171 return f // happens before typecheck 1172 1173 case OTMAP: 1174 return fmt.Sprintf("map[%v]%v", n.Left, n.Right) 1175 1176 case OTCHAN: 1177 switch n.Etype { 1178 case Crecv: 1179 return fmt.Sprintf("<-chan %v", n.Left) 1180 1181 case Csend: 1182 return fmt.Sprintf("chan<- %v", n.Left) 1183 1184 default: 1185 if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.Etype == Crecv { 1186 return fmt.Sprintf("chan (%v)", n.Left) 1187 } else { 1188 return fmt.Sprintf("chan %v", n.Left) 1189 } 1190 } 1191 1192 case OTSTRUCT: 1193 return "<struct>" 1194 1195 case OTINTER: 1196 return "<inter>" 1197 1198 case OTFUNC: 1199 return "<func>" 1200 1201 case OCLOSURE: 1202 if fmtmode == FErr { 1203 return "func literal" 1204 } 1205 if n.Nbody != nil { 1206 return fmt.Sprintf("%v { %v }", n.Type, n.Nbody) 1207 } 1208 return fmt.Sprintf("%v { %v }", n.Type, n.Name.Param.Closure.Nbody) 1209 1210 case OCOMPLIT: 1211 ptrlit := n.Right != nil && n.Right.Implicit && n.Right.Type != nil && Isptr[n.Right.Type.Etype] 1212 if fmtmode == FErr { 1213 if n.Right != nil && n.Right.Type != nil && !n.Implicit { 1214 if ptrlit { 1215 return fmt.Sprintf("&%v literal", n.Right.Type.Type) 1216 } else { 1217 return fmt.Sprintf("%v literal", n.Right.Type) 1218 } 1219 } 1220 1221 return "composite literal" 1222 } 1223 1224 if fmtmode == FExp && ptrlit { 1225 // typecheck has overwritten OIND by OTYPE with pointer type. 1226 return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Type, Hconv(n.List, obj.FmtComma)) 1227 } 1228 1229 return fmt.Sprintf("(%v{ %v })", n.Right, Hconv(n.List, obj.FmtComma)) 1230 1231 case OPTRLIT: 1232 if fmtmode == FExp && n.Left.Implicit { 1233 return Nconv(n.Left, 0) 1234 } 1235 return fmt.Sprintf("&%v", n.Left) 1236 1237 case OSTRUCTLIT: 1238 if fmtmode == FExp { // requires special handling of field names 1239 var f string 1240 if n.Implicit { 1241 f += "{" 1242 } else { 1243 f += fmt.Sprintf("(%v{", n.Type) 1244 } 1245 for l := n.List; l != nil; l = l.Next { 1246 f += fmt.Sprintf(" %v:%v", Sconv(l.N.Left.Sym, obj.FmtShort|obj.FmtByte), l.N.Right) 1247 1248 if l.Next != nil { 1249 f += "," 1250 } else { 1251 f += " " 1252 } 1253 } 1254 1255 if !n.Implicit { 1256 f += "})" 1257 return f 1258 } 1259 f += "}" 1260 return f 1261 } 1262 fallthrough 1263 1264 case OARRAYLIT, OMAPLIT: 1265 if fmtmode == FErr { 1266 return fmt.Sprintf("%v literal", n.Type) 1267 } 1268 if fmtmode == FExp && n.Implicit { 1269 return fmt.Sprintf("{ %v }", Hconv(n.List, obj.FmtComma)) 1270 } 1271 return fmt.Sprintf("(%v{ %v })", n.Type, Hconv(n.List, obj.FmtComma)) 1272 1273 case OKEY: 1274 if n.Left != nil && n.Right != nil { 1275 if fmtmode == FExp && n.Left.Type != nil && n.Left.Type.Etype == TFIELD { 1276 // requires special handling of field names 1277 return fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, obj.FmtShort|obj.FmtByte), n.Right) 1278 } else { 1279 return fmt.Sprintf("%v:%v", n.Left, n.Right) 1280 } 1281 } 1282 1283 if n.Left == nil && n.Right != nil { 1284 return fmt.Sprintf(":%v", n.Right) 1285 } 1286 if n.Left != nil && n.Right == nil { 1287 return fmt.Sprintf("%v:", n.Left) 1288 } 1289 return ":" 1290 1291 case OXDOT, 1292 ODOT, 1293 ODOTPTR, 1294 ODOTINTER, 1295 ODOTMETH, 1296 OCALLPART: 1297 var f string 1298 f += exprfmt(n.Left, nprec) 1299 if n.Right == nil || n.Right.Sym == nil { 1300 f += ".<nil>" 1301 return f 1302 } 1303 f += fmt.Sprintf(".%v", Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte)) 1304 return f 1305 1306 case ODOTTYPE, ODOTTYPE2: 1307 var f string 1308 f += exprfmt(n.Left, nprec) 1309 if n.Right != nil { 1310 f += fmt.Sprintf(".(%v)", n.Right) 1311 return f 1312 } 1313 f += fmt.Sprintf(".(%v)", n.Type) 1314 return f 1315 1316 case OINDEX, 1317 OINDEXMAP, 1318 OSLICE, 1319 OSLICESTR, 1320 OSLICEARR, 1321 OSLICE3, 1322 OSLICE3ARR: 1323 var f string 1324 f += exprfmt(n.Left, nprec) 1325 f += fmt.Sprintf("[%v]", n.Right) 1326 return f 1327 1328 case OCOPY, OCOMPLEX: 1329 return fmt.Sprintf("%v(%v, %v)", Oconv(int(n.Op), obj.FmtSharp), n.Left, n.Right) 1330 1331 case OCONV, 1332 OCONVIFACE, 1333 OCONVNOP, 1334 OARRAYBYTESTR, 1335 OARRAYRUNESTR, 1336 OSTRARRAYBYTE, 1337 OSTRARRAYRUNE, 1338 ORUNESTR: 1339 if n.Type == nil || n.Type.Sym == nil { 1340 return fmt.Sprintf("(%v)(%v)", n.Type, n.Left) 1341 } 1342 if n.Left != nil { 1343 return fmt.Sprintf("%v(%v)", n.Type, n.Left) 1344 } 1345 return fmt.Sprintf("%v(%v)", n.Type, Hconv(n.List, obj.FmtComma)) 1346 1347 case OREAL, 1348 OIMAG, 1349 OAPPEND, 1350 OCAP, 1351 OCLOSE, 1352 ODELETE, 1353 OLEN, 1354 OMAKE, 1355 ONEW, 1356 OPANIC, 1357 ORECOVER, 1358 OPRINT, 1359 OPRINTN: 1360 if n.Left != nil { 1361 return fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), n.Left) 1362 } 1363 if n.Isddd { 1364 return fmt.Sprintf("%v(%v...)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma)) 1365 } 1366 return fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma)) 1367 1368 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: 1369 var f string 1370 f += exprfmt(n.Left, nprec) 1371 if n.Isddd { 1372 f += fmt.Sprintf("(%v...)", Hconv(n.List, obj.FmtComma)) 1373 return f 1374 } 1375 f += fmt.Sprintf("(%v)", Hconv(n.List, obj.FmtComma)) 1376 return f 1377 1378 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 1379 if n.List != nil { // pre-typecheck 1380 return fmt.Sprintf("make(%v, %v)", n.Type, Hconv(n.List, obj.FmtComma)) 1381 } 1382 if n.Right != nil { 1383 return fmt.Sprintf("make(%v, %v, %v)", n.Type, n.Left, n.Right) 1384 } 1385 if n.Left != nil && (n.Op == OMAKESLICE || !isideal(n.Left.Type)) { 1386 return fmt.Sprintf("make(%v, %v)", n.Type, n.Left) 1387 } 1388 return fmt.Sprintf("make(%v)", n.Type) 1389 1390 // Unary 1391 case OPLUS, 1392 OMINUS, 1393 OADDR, 1394 OCOM, 1395 OIND, 1396 ONOT, 1397 ORECV: 1398 var f string 1399 if n.Left.Op == n.Op { 1400 f += fmt.Sprintf("%v ", Oconv(int(n.Op), obj.FmtSharp)) 1401 } else { 1402 f += Oconv(int(n.Op), obj.FmtSharp) 1403 } 1404 f += exprfmt(n.Left, nprec+1) 1405 return f 1406 1407 // Binary 1408 case OADD, 1409 OAND, 1410 OANDAND, 1411 OANDNOT, 1412 ODIV, 1413 OEQ, 1414 OGE, 1415 OGT, 1416 OLE, 1417 OLT, 1418 OLSH, 1419 OMOD, 1420 OMUL, 1421 ONE, 1422 OOR, 1423 OOROR, 1424 ORSH, 1425 OSEND, 1426 OSUB, 1427 OXOR: 1428 var f string 1429 f += exprfmt(n.Left, nprec) 1430 1431 f += fmt.Sprintf(" %v ", Oconv(int(n.Op), obj.FmtSharp)) 1432 f += exprfmt(n.Right, nprec+1) 1433 return f 1434 1435 case OADDSTR: 1436 var f string 1437 for l := n.List; l != nil; l = l.Next { 1438 if l != n.List { 1439 f += " + " 1440 } 1441 f += exprfmt(l.N, nprec) 1442 } 1443 1444 return f 1445 1446 case OCMPSTR, OCMPIFACE: 1447 var f string 1448 f += exprfmt(n.Left, nprec) 1449 f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp)) 1450 f += exprfmt(n.Right, nprec+1) 1451 return f 1452 } 1453 1454 return fmt.Sprintf("<node %v>", Oconv(int(n.Op), 0)) 1455 } 1456 1457 func nodefmt(n *Node, flag int) string { 1458 t := n.Type 1459 1460 // we almost always want the original, except in export mode for literals 1461 // this saves the importer some work, and avoids us having to redo some 1462 // special casing for package unsafe 1463 if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil { 1464 n = n.Orig 1465 } 1466 1467 if flag&obj.FmtLong != 0 && t != nil { 1468 if t.Etype == TNIL { 1469 return "nil" 1470 } else { 1471 return fmt.Sprintf("%v (type %v)", n, t) 1472 } 1473 } 1474 1475 // TODO inlining produces expressions with ninits. we can't print these yet. 1476 1477 if opprec[n.Op] < 0 { 1478 return stmtfmt(n) 1479 } 1480 1481 return exprfmt(n, 0) 1482 } 1483 1484 var dumpdepth int 1485 1486 func indent(buf *bytes.Buffer) { 1487 buf.WriteString("\n") 1488 for i := 0; i < dumpdepth; i++ { 1489 buf.WriteString(". ") 1490 } 1491 } 1492 1493 func nodedump(n *Node, flag int) string { 1494 if n == nil { 1495 return "" 1496 } 1497 1498 recur := flag&obj.FmtShort == 0 1499 1500 var buf bytes.Buffer 1501 if recur { 1502 indent(&buf) 1503 if dumpdepth > 10 { 1504 buf.WriteString("...") 1505 return buf.String() 1506 } 1507 1508 if n.Ninit != nil { 1509 fmt.Fprintf(&buf, "%v-init%v", Oconv(int(n.Op), 0), n.Ninit) 1510 indent(&buf) 1511 } 1512 } 1513 1514 switch n.Op { 1515 default: 1516 fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0)) 1517 1518 case OREGISTER, OINDREG: 1519 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), obj.Rconv(int(n.Reg)), Jconv(n, 0)) 1520 1521 case OLITERAL: 1522 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), Vconv(n.Val(), 0), Jconv(n, 0)) 1523 1524 case ONAME, ONONAME: 1525 if n.Sym != nil { 1526 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), n.Sym, Jconv(n, 0)) 1527 } else { 1528 fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0)) 1529 } 1530 if recur && n.Type == nil && n.Name.Param.Ntype != nil { 1531 indent(&buf) 1532 fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Name.Param.Ntype) 1533 } 1534 1535 case OASOP: 1536 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), Oconv(int(n.Etype), 0), Jconv(n, 0)) 1537 1538 case OTYPE: 1539 fmt.Fprintf(&buf, "%v %v%v type=%v", Oconv(int(n.Op), 0), n.Sym, Jconv(n, 0), n.Type) 1540 if recur && n.Type == nil && n.Name.Param.Ntype != nil { 1541 indent(&buf) 1542 fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Name.Param.Ntype) 1543 } 1544 } 1545 1546 if n.Sym != nil && n.Op != ONAME { 1547 fmt.Fprintf(&buf, " %v", n.Sym) 1548 } 1549 1550 if n.Type != nil { 1551 fmt.Fprintf(&buf, " %v", n.Type) 1552 } 1553 1554 if recur { 1555 if n.Left != nil { 1556 buf.WriteString(Nconv(n.Left, 0)) 1557 } 1558 if n.Right != nil { 1559 buf.WriteString(Nconv(n.Right, 0)) 1560 } 1561 if n.List != nil { 1562 indent(&buf) 1563 fmt.Fprintf(&buf, "%v-list%v", Oconv(int(n.Op), 0), n.List) 1564 } 1565 1566 if n.Rlist != nil { 1567 indent(&buf) 1568 fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist) 1569 } 1570 1571 if n.Nbody != nil { 1572 indent(&buf) 1573 fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody) 1574 } 1575 } 1576 1577 return buf.String() 1578 } 1579 1580 func (s *Sym) String() string { 1581 return Sconv(s, 0) 1582 } 1583 1584 // Fmt "%S": syms 1585 // Flags: "%hS" suppresses qualifying with package 1586 func Sconv(s *Sym, flag int) string { 1587 if flag&obj.FmtLong != 0 { 1588 panic("linksymfmt") 1589 } 1590 1591 if s == nil { 1592 return "<S>" 1593 } 1594 1595 if s.Name == "_" { 1596 return "_" 1597 } 1598 1599 sf := flag 1600 sm := setfmode(&flag) 1601 var r int 1602 _ = r 1603 str := symfmt(s, flag) 1604 flag = sf 1605 fmtmode = sm 1606 return str 1607 } 1608 1609 func (t *Type) String() string { 1610 return Tconv(t, 0) 1611 } 1612 1613 // Fmt "%T": types. 1614 // Flags: 'l' print definition, not name 1615 // 'h' omit 'func' and receiver from function types, short type names 1616 // 'u' package name, not prefix (FTypeId mode, sticky) 1617 func Tconv(t *Type, flag int) string { 1618 if t == nil { 1619 return "<T>" 1620 } 1621 1622 if t.Trecur > 4 { 1623 return "<...>" 1624 } 1625 1626 t.Trecur++ 1627 sf := flag 1628 sm := setfmode(&flag) 1629 1630 if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) { 1631 fmtpkgpfx++ 1632 } 1633 if fmtpkgpfx != 0 { 1634 flag |= obj.FmtUnsigned 1635 } 1636 1637 var r int 1638 _ = r 1639 str := typefmt(t, flag) 1640 1641 if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) { 1642 fmtpkgpfx-- 1643 } 1644 1645 flag = sf 1646 fmtmode = sm 1647 t.Trecur-- 1648 return str 1649 } 1650 1651 func (n *Node) String() string { 1652 return Nconv(n, 0) 1653 } 1654 1655 // Fmt '%N': Nodes. 1656 // Flags: 'l' suffix with "(type %T)" where possible 1657 // '+h' in debug mode, don't recurse, no multiline output 1658 func Nconv(n *Node, flag int) string { 1659 if n == nil { 1660 return "<N>" 1661 } 1662 sf := flag 1663 sm := setfmode(&flag) 1664 1665 var r int 1666 _ = r 1667 var str string 1668 switch fmtmode { 1669 case FErr, FExp: 1670 str = nodefmt(n, flag) 1671 1672 case FDbg: 1673 dumpdepth++ 1674 str = nodedump(n, flag) 1675 dumpdepth-- 1676 1677 default: 1678 Fatal("unhandled %%N mode") 1679 } 1680 1681 flag = sf 1682 fmtmode = sm 1683 return str 1684 } 1685 1686 func (l *NodeList) String() string { 1687 return Hconv(l, 0) 1688 } 1689 1690 // Fmt '%H': NodeList. 1691 // Flags: all those of %N plus ',': separate with comma's instead of semicolons. 1692 func Hconv(l *NodeList, flag int) string { 1693 if l == nil && fmtmode == FDbg { 1694 return "<nil>" 1695 } 1696 1697 sf := flag 1698 sm := setfmode(&flag) 1699 var r int 1700 _ = r 1701 sep := "; " 1702 if fmtmode == FDbg { 1703 sep = "\n" 1704 } else if flag&obj.FmtComma != 0 { 1705 sep = ", " 1706 } 1707 1708 var buf bytes.Buffer 1709 for ; l != nil; l = l.Next { 1710 buf.WriteString(Nconv(l.N, 0)) 1711 if l.Next != nil { 1712 buf.WriteString(sep) 1713 } 1714 } 1715 1716 flag = sf 1717 fmtmode = sm 1718 return buf.String() 1719 } 1720 1721 func dumplist(s string, l *NodeList) { 1722 fmt.Printf("%s%v\n", s, Hconv(l, obj.FmtSign)) 1723 } 1724 1725 func Dump(s string, n *Node) { 1726 fmt.Printf("%s [%p]%v\n", s, n, Nconv(n, obj.FmtSign)) 1727 } 1728