You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

431 lines
10 KiB

  1. // Copyright 2013 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. package ssa
  5. // This file implements the String() methods for all Value and
  6. // Instruction types.
  7. import (
  8. "bytes"
  9. "fmt"
  10. "go/types"
  11. "io"
  12. "reflect"
  13. "sort"
  14. "golang.org/x/tools/go/types/typeutil"
  15. )
  16. // relName returns the name of v relative to i.
  17. // In most cases, this is identical to v.Name(), but references to
  18. // Functions (including methods) and Globals use RelString and
  19. // all types are displayed with relType, so that only cross-package
  20. // references are package-qualified.
  21. //
  22. func relName(v Value, i Instruction) string {
  23. var from *types.Package
  24. if i != nil {
  25. from = i.Parent().pkg()
  26. }
  27. switch v := v.(type) {
  28. case Member: // *Function or *Global
  29. return v.RelString(from)
  30. case *Const:
  31. return v.RelString(from)
  32. }
  33. return v.Name()
  34. }
  35. func relType(t types.Type, from *types.Package) string {
  36. return types.TypeString(t, types.RelativeTo(from))
  37. }
  38. func relString(m Member, from *types.Package) string {
  39. // NB: not all globals have an Object (e.g. init$guard),
  40. // so use Package().Object not Object.Package().
  41. if pkg := m.Package().Pkg; pkg != nil && pkg != from {
  42. return fmt.Sprintf("%s.%s", pkg.Path(), m.Name())
  43. }
  44. return m.Name()
  45. }
  46. // Value.String()
  47. //
  48. // This method is provided only for debugging.
  49. // It never appears in disassembly, which uses Value.Name().
  50. func (v *Parameter) String() string {
  51. from := v.Parent().pkg()
  52. return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
  53. }
  54. func (v *FreeVar) String() string {
  55. from := v.Parent().pkg()
  56. return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
  57. }
  58. func (v *Builtin) String() string {
  59. return fmt.Sprintf("builtin %s", v.Name())
  60. }
  61. // Instruction.String()
  62. func (v *Alloc) String() string {
  63. op := "local"
  64. if v.Heap {
  65. op = "new"
  66. }
  67. from := v.Parent().pkg()
  68. return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
  69. }
  70. func (v *Phi) String() string {
  71. var b bytes.Buffer
  72. b.WriteString("phi [")
  73. for i, edge := range v.Edges {
  74. if i > 0 {
  75. b.WriteString(", ")
  76. }
  77. // Be robust against malformed CFG.
  78. if v.block == nil {
  79. b.WriteString("??")
  80. continue
  81. }
  82. block := -1
  83. if i < len(v.block.Preds) {
  84. block = v.block.Preds[i].Index
  85. }
  86. fmt.Fprintf(&b, "%d: ", block)
  87. edgeVal := "<nil>" // be robust
  88. if edge != nil {
  89. edgeVal = relName(edge, v)
  90. }
  91. b.WriteString(edgeVal)
  92. }
  93. b.WriteString("]")
  94. if v.Comment != "" {
  95. b.WriteString(" #")
  96. b.WriteString(v.Comment)
  97. }
  98. return b.String()
  99. }
  100. func printCall(v *CallCommon, prefix string, instr Instruction) string {
  101. var b bytes.Buffer
  102. b.WriteString(prefix)
  103. if !v.IsInvoke() {
  104. b.WriteString(relName(v.Value, instr))
  105. } else {
  106. fmt.Fprintf(&b, "invoke %s.%s", relName(v.Value, instr), v.Method.Name())
  107. }
  108. b.WriteString("(")
  109. for i, arg := range v.Args {
  110. if i > 0 {
  111. b.WriteString(", ")
  112. }
  113. b.WriteString(relName(arg, instr))
  114. }
  115. if v.Signature().Variadic() {
  116. b.WriteString("...")
  117. }
  118. b.WriteString(")")
  119. return b.String()
  120. }
  121. func (c *CallCommon) String() string {
  122. return printCall(c, "", nil)
  123. }
  124. func (v *Call) String() string {
  125. return printCall(&v.Call, "", v)
  126. }
  127. func (v *BinOp) String() string {
  128. return fmt.Sprintf("%s %s %s", relName(v.X, v), v.Op.String(), relName(v.Y, v))
  129. }
  130. func (v *UnOp) String() string {
  131. return fmt.Sprintf("%s%s%s", v.Op, relName(v.X, v), commaOk(v.CommaOk))
  132. }
  133. func printConv(prefix string, v, x Value) string {
  134. from := v.Parent().pkg()
  135. return fmt.Sprintf("%s %s <- %s (%s)",
  136. prefix,
  137. relType(v.Type(), from),
  138. relType(x.Type(), from),
  139. relName(x, v.(Instruction)))
  140. }
  141. func (v *ChangeType) String() string { return printConv("changetype", v, v.X) }
  142. func (v *Convert) String() string { return printConv("convert", v, v.X) }
  143. func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) }
  144. func (v *MakeInterface) String() string { return printConv("make", v, v.X) }
  145. func (v *MakeClosure) String() string {
  146. var b bytes.Buffer
  147. fmt.Fprintf(&b, "make closure %s", relName(v.Fn, v))
  148. if v.Bindings != nil {
  149. b.WriteString(" [")
  150. for i, c := range v.Bindings {
  151. if i > 0 {
  152. b.WriteString(", ")
  153. }
  154. b.WriteString(relName(c, v))
  155. }
  156. b.WriteString("]")
  157. }
  158. return b.String()
  159. }
  160. func (v *MakeSlice) String() string {
  161. from := v.Parent().pkg()
  162. return fmt.Sprintf("make %s %s %s",
  163. relType(v.Type(), from),
  164. relName(v.Len, v),
  165. relName(v.Cap, v))
  166. }
  167. func (v *Slice) String() string {
  168. var b bytes.Buffer
  169. b.WriteString("slice ")
  170. b.WriteString(relName(v.X, v))
  171. b.WriteString("[")
  172. if v.Low != nil {
  173. b.WriteString(relName(v.Low, v))
  174. }
  175. b.WriteString(":")
  176. if v.High != nil {
  177. b.WriteString(relName(v.High, v))
  178. }
  179. if v.Max != nil {
  180. b.WriteString(":")
  181. b.WriteString(relName(v.Max, v))
  182. }
  183. b.WriteString("]")
  184. return b.String()
  185. }
  186. func (v *MakeMap) String() string {
  187. res := ""
  188. if v.Reserve != nil {
  189. res = relName(v.Reserve, v)
  190. }
  191. from := v.Parent().pkg()
  192. return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
  193. }
  194. func (v *MakeChan) String() string {
  195. from := v.Parent().pkg()
  196. return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
  197. }
  198. func (v *FieldAddr) String() string {
  199. st := deref(v.X.Type()).Underlying().(*types.Struct)
  200. // Be robust against a bad index.
  201. name := "?"
  202. if 0 <= v.Field && v.Field < st.NumFields() {
  203. name = st.Field(v.Field).Name()
  204. }
  205. return fmt.Sprintf("&%s.%s [#%d]", relName(v.X, v), name, v.Field)
  206. }
  207. func (v *Field) String() string {
  208. st := v.X.Type().Underlying().(*types.Struct)
  209. // Be robust against a bad index.
  210. name := "?"
  211. if 0 <= v.Field && v.Field < st.NumFields() {
  212. name = st.Field(v.Field).Name()
  213. }
  214. return fmt.Sprintf("%s.%s [#%d]", relName(v.X, v), name, v.Field)
  215. }
  216. func (v *IndexAddr) String() string {
  217. return fmt.Sprintf("&%s[%s]", relName(v.X, v), relName(v.Index, v))
  218. }
  219. func (v *Index) String() string {
  220. return fmt.Sprintf("%s[%s]", relName(v.X, v), relName(v.Index, v))
  221. }
  222. func (v *Lookup) String() string {
  223. return fmt.Sprintf("%s[%s]%s", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))
  224. }
  225. func (v *Range) String() string {
  226. return "range " + relName(v.X, v)
  227. }
  228. func (v *Next) String() string {
  229. return "next " + relName(v.Iter, v)
  230. }
  231. func (v *TypeAssert) String() string {
  232. from := v.Parent().pkg()
  233. return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
  234. }
  235. func (v *Extract) String() string {
  236. return fmt.Sprintf("extract %s #%d", relName(v.Tuple, v), v.Index)
  237. }
  238. func (s *Jump) String() string {
  239. // Be robust against malformed CFG.
  240. block := -1
  241. if s.block != nil && len(s.block.Succs) == 1 {
  242. block = s.block.Succs[0].Index
  243. }
  244. return fmt.Sprintf("jump %d", block)
  245. }
  246. func (s *If) String() string {
  247. // Be robust against malformed CFG.
  248. tblock, fblock := -1, -1
  249. if s.block != nil && len(s.block.Succs) == 2 {
  250. tblock = s.block.Succs[0].Index
  251. fblock = s.block.Succs[1].Index
  252. }
  253. return fmt.Sprintf("if %s goto %d else %d", relName(s.Cond, s), tblock, fblock)
  254. }
  255. func (s *Go) String() string {
  256. return printCall(&s.Call, "go ", s)
  257. }
  258. func (s *Panic) String() string {
  259. return "panic " + relName(s.X, s)
  260. }
  261. func (s *Return) String() string {
  262. var b bytes.Buffer
  263. b.WriteString("return")
  264. for i, r := range s.Results {
  265. if i == 0 {
  266. b.WriteString(" ")
  267. } else {
  268. b.WriteString(", ")
  269. }
  270. b.WriteString(relName(r, s))
  271. }
  272. return b.String()
  273. }
  274. func (*RunDefers) String() string {
  275. return "rundefers"
  276. }
  277. func (s *Send) String() string {
  278. return fmt.Sprintf("send %s <- %s", relName(s.Chan, s), relName(s.X, s))
  279. }
  280. func (s *Defer) String() string {
  281. return printCall(&s.Call, "defer ", s)
  282. }
  283. func (s *Select) String() string {
  284. var b bytes.Buffer
  285. for i, st := range s.States {
  286. if i > 0 {
  287. b.WriteString(", ")
  288. }
  289. if st.Dir == types.RecvOnly {
  290. b.WriteString("<-")
  291. b.WriteString(relName(st.Chan, s))
  292. } else {
  293. b.WriteString(relName(st.Chan, s))
  294. b.WriteString("<-")
  295. b.WriteString(relName(st.Send, s))
  296. }
  297. }
  298. non := ""
  299. if !s.Blocking {
  300. non = "non"
  301. }
  302. return fmt.Sprintf("select %sblocking [%s]", non, b.String())
  303. }
  304. func (s *Store) String() string {
  305. return fmt.Sprintf("*%s = %s", relName(s.Addr, s), relName(s.Val, s))
  306. }
  307. func (s *MapUpdate) String() string {
  308. return fmt.Sprintf("%s[%s] = %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
  309. }
  310. func (s *DebugRef) String() string {
  311. p := s.Parent().Prog.Fset.Position(s.Pos())
  312. var descr interface{}
  313. if s.object != nil {
  314. descr = s.object // e.g. "var x int"
  315. } else {
  316. descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
  317. }
  318. var addr string
  319. if s.IsAddr {
  320. addr = "address of "
  321. }
  322. return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
  323. }
  324. func (p *Package) String() string {
  325. return "package " + p.Pkg.Path()
  326. }
  327. var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
  328. func (p *Package) WriteTo(w io.Writer) (int64, error) {
  329. var buf bytes.Buffer
  330. WritePackage(&buf, p)
  331. n, err := w.Write(buf.Bytes())
  332. return int64(n), err
  333. }
  334. // WritePackage writes to buf a human-readable summary of p.
  335. func WritePackage(buf *bytes.Buffer, p *Package) {
  336. fmt.Fprintf(buf, "%s:\n", p)
  337. var names []string
  338. maxname := 0
  339. for name := range p.Members {
  340. if l := len(name); l > maxname {
  341. maxname = l
  342. }
  343. names = append(names, name)
  344. }
  345. from := p.Pkg
  346. sort.Strings(names)
  347. for _, name := range names {
  348. switch mem := p.Members[name].(type) {
  349. case *NamedConst:
  350. fmt.Fprintf(buf, " const %-*s %s = %s\n",
  351. maxname, name, mem.Name(), mem.Value.RelString(from))
  352. case *Function:
  353. fmt.Fprintf(buf, " func %-*s %s\n",
  354. maxname, name, relType(mem.Type(), from))
  355. case *Type:
  356. fmt.Fprintf(buf, " type %-*s %s\n",
  357. maxname, name, relType(mem.Type().Underlying(), from))
  358. for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
  359. fmt.Fprintf(buf, " %s\n", types.SelectionString(meth, types.RelativeTo(from)))
  360. }
  361. case *Global:
  362. fmt.Fprintf(buf, " var %-*s %s\n",
  363. maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
  364. }
  365. }
  366. fmt.Fprintf(buf, "\n")
  367. }
  368. func commaOk(x bool) string {
  369. if x {
  370. return ",ok"
  371. }
  372. return ""
  373. }