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.

1975 lines
54 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 pointer
  5. // This file implements the generation and resolution rules for
  6. // constraints arising from the use of reflection in the target
  7. // program. See doc.go for explanation of the representation.
  8. //
  9. // For consistency, the names of all parameters match those of the
  10. // actual functions in the "reflect" package.
  11. //
  12. // To avoid proliferation of equivalent labels, intrinsics should
  13. // memoize as much as possible, like TypeOf and Zero do for their
  14. // tagged objects.
  15. //
  16. // TODO(adonovan): this file is rather subtle. Explain how we derive
  17. // the implementation of each reflect operator from its spec,
  18. // including the subtleties of reflect.flag{Addr,RO,Indir}.
  19. // [Hint: our implementation is as if reflect.flagIndir was always
  20. // true, i.e. reflect.Values are pointers to tagged objects, there is
  21. // no inline allocation optimization; and indirect tagged objects (not
  22. // yet implemented) correspond to reflect.Values with
  23. // reflect.flagAddr.]
  24. // A picture would help too.
  25. //
  26. // TODO(adonovan): try factoring up the common parts of the majority of
  27. // these constraints that are single input, single output.
  28. import (
  29. "fmt"
  30. exact "go/constant"
  31. "go/types"
  32. "reflect"
  33. "golang.org/x/tools/go/ssa"
  34. )
  35. func init() {
  36. for name, fn := range map[string]intrinsic{
  37. // reflect.Value methods.
  38. "(reflect.Value).Addr": ext۰reflect۰Value۰Addr,
  39. "(reflect.Value).Bool": ext۰NoEffect,
  40. "(reflect.Value).Bytes": ext۰reflect۰Value۰Bytes,
  41. "(reflect.Value).Call": ext۰reflect۰Value۰Call,
  42. "(reflect.Value).CallSlice": ext۰reflect۰Value۰CallSlice,
  43. "(reflect.Value).CanAddr": ext۰NoEffect,
  44. "(reflect.Value).CanInterface": ext۰NoEffect,
  45. "(reflect.Value).CanSet": ext۰NoEffect,
  46. "(reflect.Value).Cap": ext۰NoEffect,
  47. "(reflect.Value).Close": ext۰NoEffect,
  48. "(reflect.Value).Complex": ext۰NoEffect,
  49. "(reflect.Value).Convert": ext۰reflect۰Value۰Convert,
  50. "(reflect.Value).Elem": ext۰reflect۰Value۰Elem,
  51. "(reflect.Value).Field": ext۰reflect۰Value۰Field,
  52. "(reflect.Value).FieldByIndex": ext۰reflect۰Value۰FieldByIndex,
  53. "(reflect.Value).FieldByName": ext۰reflect۰Value۰FieldByName,
  54. "(reflect.Value).FieldByNameFunc": ext۰reflect۰Value۰FieldByNameFunc,
  55. "(reflect.Value).Float": ext۰NoEffect,
  56. "(reflect.Value).Index": ext۰reflect۰Value۰Index,
  57. "(reflect.Value).Int": ext۰NoEffect,
  58. "(reflect.Value).Interface": ext۰reflect۰Value۰Interface,
  59. "(reflect.Value).InterfaceData": ext۰NoEffect,
  60. "(reflect.Value).IsNil": ext۰NoEffect,
  61. "(reflect.Value).IsValid": ext۰NoEffect,
  62. "(reflect.Value).Kind": ext۰NoEffect,
  63. "(reflect.Value).Len": ext۰NoEffect,
  64. "(reflect.Value).MapIndex": ext۰reflect۰Value۰MapIndex,
  65. "(reflect.Value).MapKeys": ext۰reflect۰Value۰MapKeys,
  66. "(reflect.Value).Method": ext۰reflect۰Value۰Method,
  67. "(reflect.Value).MethodByName": ext۰reflect۰Value۰MethodByName,
  68. "(reflect.Value).NumField": ext۰NoEffect,
  69. "(reflect.Value).NumMethod": ext۰NoEffect,
  70. "(reflect.Value).OverflowComplex": ext۰NoEffect,
  71. "(reflect.Value).OverflowFloat": ext۰NoEffect,
  72. "(reflect.Value).OverflowInt": ext۰NoEffect,
  73. "(reflect.Value).OverflowUint": ext۰NoEffect,
  74. "(reflect.Value).Pointer": ext۰NoEffect,
  75. "(reflect.Value).Recv": ext۰reflect۰Value۰Recv,
  76. "(reflect.Value).Send": ext۰reflect۰Value۰Send,
  77. "(reflect.Value).Set": ext۰reflect۰Value۰Set,
  78. "(reflect.Value).SetBool": ext۰NoEffect,
  79. "(reflect.Value).SetBytes": ext۰reflect۰Value۰SetBytes,
  80. "(reflect.Value).SetComplex": ext۰NoEffect,
  81. "(reflect.Value).SetFloat": ext۰NoEffect,
  82. "(reflect.Value).SetInt": ext۰NoEffect,
  83. "(reflect.Value).SetLen": ext۰NoEffect,
  84. "(reflect.Value).SetMapIndex": ext۰reflect۰Value۰SetMapIndex,
  85. "(reflect.Value).SetPointer": ext۰reflect۰Value۰SetPointer,
  86. "(reflect.Value).SetString": ext۰NoEffect,
  87. "(reflect.Value).SetUint": ext۰NoEffect,
  88. "(reflect.Value).Slice": ext۰reflect۰Value۰Slice,
  89. "(reflect.Value).String": ext۰NoEffect,
  90. "(reflect.Value).TryRecv": ext۰reflect۰Value۰Recv,
  91. "(reflect.Value).TrySend": ext۰reflect۰Value۰Send,
  92. "(reflect.Value).Type": ext۰NoEffect,
  93. "(reflect.Value).Uint": ext۰NoEffect,
  94. "(reflect.Value).UnsafeAddr": ext۰NoEffect,
  95. // Standalone reflect.* functions.
  96. "reflect.Append": ext۰reflect۰Append,
  97. "reflect.AppendSlice": ext۰reflect۰AppendSlice,
  98. "reflect.Copy": ext۰reflect۰Copy,
  99. "reflect.ChanOf": ext۰reflect۰ChanOf,
  100. "reflect.DeepEqual": ext۰NoEffect,
  101. "reflect.Indirect": ext۰reflect۰Indirect,
  102. "reflect.MakeChan": ext۰reflect۰MakeChan,
  103. "reflect.MakeFunc": ext۰reflect۰MakeFunc,
  104. "reflect.MakeMap": ext۰reflect۰MakeMap,
  105. "reflect.MakeSlice": ext۰reflect۰MakeSlice,
  106. "reflect.MapOf": ext۰reflect۰MapOf,
  107. "reflect.New": ext۰reflect۰New,
  108. "reflect.NewAt": ext۰reflect۰NewAt,
  109. "reflect.PtrTo": ext۰reflect۰PtrTo,
  110. "reflect.Select": ext۰reflect۰Select,
  111. "reflect.SliceOf": ext۰reflect۰SliceOf,
  112. "reflect.TypeOf": ext۰reflect۰TypeOf,
  113. "reflect.ValueOf": ext۰reflect۰ValueOf,
  114. "reflect.Zero": ext۰reflect۰Zero,
  115. "reflect.init": ext۰NoEffect,
  116. // *reflect.rtype methods
  117. "(*reflect.rtype).Align": ext۰NoEffect,
  118. "(*reflect.rtype).AssignableTo": ext۰NoEffect,
  119. "(*reflect.rtype).Bits": ext۰NoEffect,
  120. "(*reflect.rtype).ChanDir": ext۰NoEffect,
  121. "(*reflect.rtype).ConvertibleTo": ext۰NoEffect,
  122. "(*reflect.rtype).Elem": ext۰reflect۰rtype۰Elem,
  123. "(*reflect.rtype).Field": ext۰reflect۰rtype۰Field,
  124. "(*reflect.rtype).FieldAlign": ext۰NoEffect,
  125. "(*reflect.rtype).FieldByIndex": ext۰reflect۰rtype۰FieldByIndex,
  126. "(*reflect.rtype).FieldByName": ext۰reflect۰rtype۰FieldByName,
  127. "(*reflect.rtype).FieldByNameFunc": ext۰reflect۰rtype۰FieldByNameFunc,
  128. "(*reflect.rtype).Implements": ext۰NoEffect,
  129. "(*reflect.rtype).In": ext۰reflect۰rtype۰In,
  130. "(*reflect.rtype).IsVariadic": ext۰NoEffect,
  131. "(*reflect.rtype).Key": ext۰reflect۰rtype۰Key,
  132. "(*reflect.rtype).Kind": ext۰NoEffect,
  133. "(*reflect.rtype).Len": ext۰NoEffect,
  134. "(*reflect.rtype).Method": ext۰reflect۰rtype۰Method,
  135. "(*reflect.rtype).MethodByName": ext۰reflect۰rtype۰MethodByName,
  136. "(*reflect.rtype).Name": ext۰NoEffect,
  137. "(*reflect.rtype).NumField": ext۰NoEffect,
  138. "(*reflect.rtype).NumIn": ext۰NoEffect,
  139. "(*reflect.rtype).NumMethod": ext۰NoEffect,
  140. "(*reflect.rtype).NumOut": ext۰NoEffect,
  141. "(*reflect.rtype).Out": ext۰reflect۰rtype۰Out,
  142. "(*reflect.rtype).PkgPath": ext۰NoEffect,
  143. "(*reflect.rtype).Size": ext۰NoEffect,
  144. "(*reflect.rtype).String": ext۰NoEffect,
  145. } {
  146. intrinsicsByName[name] = fn
  147. }
  148. }
  149. // -------------------- (reflect.Value) --------------------
  150. func ext۰reflect۰Value۰Addr(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  151. // ---------- func (Value).Bytes() Value ----------
  152. // result = v.Bytes()
  153. type rVBytesConstraint struct {
  154. v nodeid // (ptr)
  155. result nodeid // (indirect)
  156. }
  157. func (c *rVBytesConstraint) ptr() nodeid { return c.v }
  158. func (c *rVBytesConstraint) presolve(h *hvn) {
  159. h.markIndirect(onodeid(c.result), "rVBytes.result")
  160. }
  161. func (c *rVBytesConstraint) renumber(mapping []nodeid) {
  162. c.v = mapping[c.v]
  163. c.result = mapping[c.result]
  164. }
  165. func (c *rVBytesConstraint) String() string {
  166. return fmt.Sprintf("n%d = reflect n%d.Bytes()", c.result, c.v)
  167. }
  168. func (c *rVBytesConstraint) solve(a *analysis, delta *nodeset) {
  169. changed := false
  170. for _, x := range delta.AppendTo(a.deltaSpace) {
  171. vObj := nodeid(x)
  172. tDyn, slice, indirect := a.taggedValue(vObj)
  173. if indirect {
  174. // TODO(adonovan): we'll need to implement this
  175. // when we start creating indirect tagged objects.
  176. panic("indirect tagged object")
  177. }
  178. tSlice, ok := tDyn.Underlying().(*types.Slice)
  179. if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
  180. if a.onlineCopy(c.result, slice) {
  181. changed = true
  182. }
  183. }
  184. }
  185. if changed {
  186. a.addWork(c.result)
  187. }
  188. }
  189. func ext۰reflect۰Value۰Bytes(a *analysis, cgn *cgnode) {
  190. a.addConstraint(&rVBytesConstraint{
  191. v: a.funcParams(cgn.obj),
  192. result: a.funcResults(cgn.obj),
  193. })
  194. }
  195. // ---------- func (Value).Call(in []Value) []Value ----------
  196. // result = v.Call(in)
  197. type rVCallConstraint struct {
  198. cgn *cgnode
  199. targets nodeid // (indirect)
  200. v nodeid // (ptr)
  201. arg nodeid // = in[*]
  202. result nodeid // (indirect)
  203. dotdotdot bool // interpret last arg as a "..." slice
  204. }
  205. func (c *rVCallConstraint) ptr() nodeid { return c.v }
  206. func (c *rVCallConstraint) presolve(h *hvn) {
  207. h.markIndirect(onodeid(c.targets), "rVCall.targets")
  208. h.markIndirect(onodeid(c.result), "rVCall.result")
  209. }
  210. func (c *rVCallConstraint) renumber(mapping []nodeid) {
  211. c.targets = mapping[c.targets]
  212. c.v = mapping[c.v]
  213. c.arg = mapping[c.arg]
  214. c.result = mapping[c.result]
  215. }
  216. func (c *rVCallConstraint) String() string {
  217. return fmt.Sprintf("n%d = reflect n%d.Call(n%d)", c.result, c.v, c.arg)
  218. }
  219. func (c *rVCallConstraint) solve(a *analysis, delta *nodeset) {
  220. if c.targets == 0 {
  221. panic("no targets")
  222. }
  223. changed := false
  224. for _, x := range delta.AppendTo(a.deltaSpace) {
  225. vObj := nodeid(x)
  226. tDyn, fn, indirect := a.taggedValue(vObj)
  227. if indirect {
  228. // TODO(adonovan): we'll need to implement this
  229. // when we start creating indirect tagged objects.
  230. panic("indirect tagged object")
  231. }
  232. tSig, ok := tDyn.Underlying().(*types.Signature)
  233. if !ok {
  234. continue // not a function
  235. }
  236. if tSig.Recv() != nil {
  237. panic(tSig) // TODO(adonovan): rethink when we implement Method()
  238. }
  239. // Add dynamic call target.
  240. if a.onlineCopy(c.targets, fn) {
  241. a.addWork(c.targets)
  242. // TODO(adonovan): is 'else continue' a sound optimisation here?
  243. }
  244. // Allocate a P/R block.
  245. tParams := tSig.Params()
  246. tResults := tSig.Results()
  247. params := a.addNodes(tParams, "rVCall.params")
  248. results := a.addNodes(tResults, "rVCall.results")
  249. // Make a dynamic call to 'fn'.
  250. a.store(fn, params, 1, a.sizeof(tParams))
  251. a.load(results, fn, 1+a.sizeof(tParams), a.sizeof(tResults))
  252. // Populate P by type-asserting each actual arg (all merged in c.arg).
  253. for i, n := 0, tParams.Len(); i < n; i++ {
  254. T := tParams.At(i).Type()
  255. a.typeAssert(T, params, c.arg, false)
  256. params += nodeid(a.sizeof(T))
  257. }
  258. // Use R by tagging and copying each actual result to c.result.
  259. for i, n := 0, tResults.Len(); i < n; i++ {
  260. T := tResults.At(i).Type()
  261. // Convert from an arbitrary type to a reflect.Value
  262. // (like MakeInterface followed by reflect.ValueOf).
  263. if isInterface(T) {
  264. // (don't tag)
  265. if a.onlineCopy(c.result, results) {
  266. changed = true
  267. }
  268. } else {
  269. obj := a.makeTagged(T, c.cgn, nil)
  270. a.onlineCopyN(obj+1, results, a.sizeof(T))
  271. if a.addLabel(c.result, obj) { // (true)
  272. changed = true
  273. }
  274. }
  275. results += nodeid(a.sizeof(T))
  276. }
  277. }
  278. if changed {
  279. a.addWork(c.result)
  280. }
  281. }
  282. // Common code for direct (inlined) and indirect calls to (reflect.Value).Call.
  283. func reflectCallImpl(a *analysis, cgn *cgnode, site *callsite, recv, arg nodeid, dotdotdot bool) nodeid {
  284. // Allocate []reflect.Value array for the result.
  285. ret := a.nextNode()
  286. a.addNodes(types.NewArray(a.reflectValueObj.Type(), 1), "rVCall.ret")
  287. a.endObject(ret, cgn, nil)
  288. // pts(targets) will be the set of possible call targets.
  289. site.targets = a.addOneNode(tInvalid, "rvCall.targets", nil)
  290. // All arguments are merged since they arrive in a slice.
  291. argelts := a.addOneNode(a.reflectValueObj.Type(), "rVCall.args", nil)
  292. a.load(argelts, arg, 1, 1) // slice elements
  293. a.addConstraint(&rVCallConstraint{
  294. cgn: cgn,
  295. targets: site.targets,
  296. v: recv,
  297. arg: argelts,
  298. result: ret + 1, // results go into elements of ret
  299. dotdotdot: dotdotdot,
  300. })
  301. return ret
  302. }
  303. func reflectCall(a *analysis, cgn *cgnode, dotdotdot bool) {
  304. // This is the shared contour implementation of (reflect.Value).Call
  305. // and CallSlice, as used by indirect calls (rare).
  306. // Direct calls are inlined in gen.go, eliding the
  307. // intermediate cgnode for Call.
  308. site := new(callsite)
  309. cgn.sites = append(cgn.sites, site)
  310. recv := a.funcParams(cgn.obj)
  311. arg := recv + 1
  312. ret := reflectCallImpl(a, cgn, site, recv, arg, dotdotdot)
  313. a.addressOf(cgn.fn.Signature.Results().At(0).Type(), a.funcResults(cgn.obj), ret)
  314. }
  315. func ext۰reflect۰Value۰Call(a *analysis, cgn *cgnode) {
  316. reflectCall(a, cgn, false)
  317. }
  318. func ext۰reflect۰Value۰CallSlice(a *analysis, cgn *cgnode) {
  319. // TODO(adonovan): implement. Also, inline direct calls in gen.go too.
  320. if false {
  321. reflectCall(a, cgn, true)
  322. }
  323. }
  324. func ext۰reflect۰Value۰Convert(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  325. // ---------- func (Value).Elem() Value ----------
  326. // result = v.Elem()
  327. type rVElemConstraint struct {
  328. cgn *cgnode
  329. v nodeid // (ptr)
  330. result nodeid // (indirect)
  331. }
  332. func (c *rVElemConstraint) ptr() nodeid { return c.v }
  333. func (c *rVElemConstraint) presolve(h *hvn) {
  334. h.markIndirect(onodeid(c.result), "rVElem.result")
  335. }
  336. func (c *rVElemConstraint) renumber(mapping []nodeid) {
  337. c.v = mapping[c.v]
  338. c.result = mapping[c.result]
  339. }
  340. func (c *rVElemConstraint) String() string {
  341. return fmt.Sprintf("n%d = reflect n%d.Elem()", c.result, c.v)
  342. }
  343. func (c *rVElemConstraint) solve(a *analysis, delta *nodeset) {
  344. changed := false
  345. for _, x := range delta.AppendTo(a.deltaSpace) {
  346. vObj := nodeid(x)
  347. tDyn, payload, indirect := a.taggedValue(vObj)
  348. if indirect {
  349. // TODO(adonovan): we'll need to implement this
  350. // when we start creating indirect tagged objects.
  351. panic("indirect tagged object")
  352. }
  353. switch t := tDyn.Underlying().(type) {
  354. case *types.Interface:
  355. if a.onlineCopy(c.result, payload) {
  356. changed = true
  357. }
  358. case *types.Pointer:
  359. obj := a.makeTagged(t.Elem(), c.cgn, nil)
  360. a.load(obj+1, payload, 0, a.sizeof(t.Elem()))
  361. if a.addLabel(c.result, obj) {
  362. changed = true
  363. }
  364. }
  365. }
  366. if changed {
  367. a.addWork(c.result)
  368. }
  369. }
  370. func ext۰reflect۰Value۰Elem(a *analysis, cgn *cgnode) {
  371. a.addConstraint(&rVElemConstraint{
  372. cgn: cgn,
  373. v: a.funcParams(cgn.obj),
  374. result: a.funcResults(cgn.obj),
  375. })
  376. }
  377. func ext۰reflect۰Value۰Field(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  378. func ext۰reflect۰Value۰FieldByIndex(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  379. func ext۰reflect۰Value۰FieldByName(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  380. func ext۰reflect۰Value۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  381. // ---------- func (Value).Index() Value ----------
  382. // result = v.Index()
  383. type rVIndexConstraint struct {
  384. cgn *cgnode
  385. v nodeid // (ptr)
  386. result nodeid // (indirect)
  387. }
  388. func (c *rVIndexConstraint) ptr() nodeid { return c.v }
  389. func (c *rVIndexConstraint) presolve(h *hvn) {
  390. h.markIndirect(onodeid(c.result), "rVIndex.result")
  391. }
  392. func (c *rVIndexConstraint) renumber(mapping []nodeid) {
  393. c.v = mapping[c.v]
  394. c.result = mapping[c.result]
  395. }
  396. func (c *rVIndexConstraint) String() string {
  397. return fmt.Sprintf("n%d = reflect n%d.Index()", c.result, c.v)
  398. }
  399. func (c *rVIndexConstraint) solve(a *analysis, delta *nodeset) {
  400. changed := false
  401. for _, x := range delta.AppendTo(a.deltaSpace) {
  402. vObj := nodeid(x)
  403. tDyn, payload, indirect := a.taggedValue(vObj)
  404. if indirect {
  405. // TODO(adonovan): we'll need to implement this
  406. // when we start creating indirect tagged objects.
  407. panic("indirect tagged object")
  408. }
  409. var res nodeid
  410. switch t := tDyn.Underlying().(type) {
  411. case *types.Array:
  412. res = a.makeTagged(t.Elem(), c.cgn, nil)
  413. a.onlineCopyN(res+1, payload+1, a.sizeof(t.Elem()))
  414. case *types.Slice:
  415. res = a.makeTagged(t.Elem(), c.cgn, nil)
  416. a.load(res+1, payload, 1, a.sizeof(t.Elem()))
  417. case *types.Basic:
  418. if t.Kind() == types.String {
  419. res = a.makeTagged(types.Typ[types.Rune], c.cgn, nil)
  420. }
  421. }
  422. if res != 0 && a.addLabel(c.result, res) {
  423. changed = true
  424. }
  425. }
  426. if changed {
  427. a.addWork(c.result)
  428. }
  429. }
  430. func ext۰reflect۰Value۰Index(a *analysis, cgn *cgnode) {
  431. a.addConstraint(&rVIndexConstraint{
  432. cgn: cgn,
  433. v: a.funcParams(cgn.obj),
  434. result: a.funcResults(cgn.obj),
  435. })
  436. }
  437. // ---------- func (Value).Interface() Value ----------
  438. // result = v.Interface()
  439. type rVInterfaceConstraint struct {
  440. v nodeid // (ptr)
  441. result nodeid // (indirect)
  442. }
  443. func (c *rVInterfaceConstraint) ptr() nodeid { return c.v }
  444. func (c *rVInterfaceConstraint) presolve(h *hvn) {
  445. h.markIndirect(onodeid(c.result), "rVInterface.result")
  446. }
  447. func (c *rVInterfaceConstraint) renumber(mapping []nodeid) {
  448. c.v = mapping[c.v]
  449. c.result = mapping[c.result]
  450. }
  451. func (c *rVInterfaceConstraint) String() string {
  452. return fmt.Sprintf("n%d = reflect n%d.Interface()", c.result, c.v)
  453. }
  454. func (c *rVInterfaceConstraint) solve(a *analysis, delta *nodeset) {
  455. changed := false
  456. for _, x := range delta.AppendTo(a.deltaSpace) {
  457. vObj := nodeid(x)
  458. tDyn, payload, indirect := a.taggedValue(vObj)
  459. if indirect {
  460. // TODO(adonovan): we'll need to implement this
  461. // when we start creating indirect tagged objects.
  462. panic("indirect tagged object")
  463. }
  464. if isInterface(tDyn) {
  465. if a.onlineCopy(c.result, payload) {
  466. a.addWork(c.result)
  467. }
  468. } else {
  469. if a.addLabel(c.result, vObj) {
  470. changed = true
  471. }
  472. }
  473. }
  474. if changed {
  475. a.addWork(c.result)
  476. }
  477. }
  478. func ext۰reflect۰Value۰Interface(a *analysis, cgn *cgnode) {
  479. a.addConstraint(&rVInterfaceConstraint{
  480. v: a.funcParams(cgn.obj),
  481. result: a.funcResults(cgn.obj),
  482. })
  483. }
  484. // ---------- func (Value).MapIndex(Value) Value ----------
  485. // result = v.MapIndex(_)
  486. type rVMapIndexConstraint struct {
  487. cgn *cgnode
  488. v nodeid // (ptr)
  489. result nodeid // (indirect)
  490. }
  491. func (c *rVMapIndexConstraint) ptr() nodeid { return c.v }
  492. func (c *rVMapIndexConstraint) presolve(h *hvn) {
  493. h.markIndirect(onodeid(c.result), "rVMapIndex.result")
  494. }
  495. func (c *rVMapIndexConstraint) renumber(mapping []nodeid) {
  496. c.v = mapping[c.v]
  497. c.result = mapping[c.result]
  498. }
  499. func (c *rVMapIndexConstraint) String() string {
  500. return fmt.Sprintf("n%d = reflect n%d.MapIndex(_)", c.result, c.v)
  501. }
  502. func (c *rVMapIndexConstraint) solve(a *analysis, delta *nodeset) {
  503. changed := false
  504. for _, x := range delta.AppendTo(a.deltaSpace) {
  505. vObj := nodeid(x)
  506. tDyn, m, indirect := a.taggedValue(vObj)
  507. tMap, _ := tDyn.Underlying().(*types.Map)
  508. if tMap == nil {
  509. continue // not a map
  510. }
  511. if indirect {
  512. // TODO(adonovan): we'll need to implement this
  513. // when we start creating indirect tagged objects.
  514. panic("indirect tagged object")
  515. }
  516. obj := a.makeTagged(tMap.Elem(), c.cgn, nil)
  517. a.load(obj+1, m, a.sizeof(tMap.Key()), a.sizeof(tMap.Elem()))
  518. if a.addLabel(c.result, obj) {
  519. changed = true
  520. }
  521. }
  522. if changed {
  523. a.addWork(c.result)
  524. }
  525. }
  526. func ext۰reflect۰Value۰MapIndex(a *analysis, cgn *cgnode) {
  527. a.addConstraint(&rVMapIndexConstraint{
  528. cgn: cgn,
  529. v: a.funcParams(cgn.obj),
  530. result: a.funcResults(cgn.obj),
  531. })
  532. }
  533. // ---------- func (Value).MapKeys() []Value ----------
  534. // result = v.MapKeys()
  535. type rVMapKeysConstraint struct {
  536. cgn *cgnode
  537. v nodeid // (ptr)
  538. result nodeid // (indirect)
  539. }
  540. func (c *rVMapKeysConstraint) ptr() nodeid { return c.v }
  541. func (c *rVMapKeysConstraint) presolve(h *hvn) {
  542. h.markIndirect(onodeid(c.result), "rVMapKeys.result")
  543. }
  544. func (c *rVMapKeysConstraint) renumber(mapping []nodeid) {
  545. c.v = mapping[c.v]
  546. c.result = mapping[c.result]
  547. }
  548. func (c *rVMapKeysConstraint) String() string {
  549. return fmt.Sprintf("n%d = reflect n%d.MapKeys()", c.result, c.v)
  550. }
  551. func (c *rVMapKeysConstraint) solve(a *analysis, delta *nodeset) {
  552. changed := false
  553. for _, x := range delta.AppendTo(a.deltaSpace) {
  554. vObj := nodeid(x)
  555. tDyn, m, indirect := a.taggedValue(vObj)
  556. tMap, _ := tDyn.Underlying().(*types.Map)
  557. if tMap == nil {
  558. continue // not a map
  559. }
  560. if indirect {
  561. // TODO(adonovan): we'll need to implement this
  562. // when we start creating indirect tagged objects.
  563. panic("indirect tagged object")
  564. }
  565. kObj := a.makeTagged(tMap.Key(), c.cgn, nil)
  566. a.load(kObj+1, m, 0, a.sizeof(tMap.Key()))
  567. if a.addLabel(c.result, kObj) {
  568. changed = true
  569. }
  570. }
  571. if changed {
  572. a.addWork(c.result)
  573. }
  574. }
  575. func ext۰reflect۰Value۰MapKeys(a *analysis, cgn *cgnode) {
  576. // Allocate an array for the result.
  577. obj := a.nextNode()
  578. T := types.NewSlice(a.reflectValueObj.Type())
  579. a.addNodes(sliceToArray(T), "reflect.MapKeys result")
  580. a.endObject(obj, cgn, nil)
  581. a.addressOf(T, a.funcResults(cgn.obj), obj)
  582. a.addConstraint(&rVMapKeysConstraint{
  583. cgn: cgn,
  584. v: a.funcParams(cgn.obj),
  585. result: obj + 1, // result is stored in array elems
  586. })
  587. }
  588. func ext۰reflect۰Value۰Method(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  589. func ext۰reflect۰Value۰MethodByName(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  590. // ---------- func (Value).Recv(Value) Value ----------
  591. // result, _ = v.Recv()
  592. type rVRecvConstraint struct {
  593. cgn *cgnode
  594. v nodeid // (ptr)
  595. result nodeid // (indirect)
  596. }
  597. func (c *rVRecvConstraint) ptr() nodeid { return c.v }
  598. func (c *rVRecvConstraint) presolve(h *hvn) {
  599. h.markIndirect(onodeid(c.result), "rVRecv.result")
  600. }
  601. func (c *rVRecvConstraint) renumber(mapping []nodeid) {
  602. c.v = mapping[c.v]
  603. c.result = mapping[c.result]
  604. }
  605. func (c *rVRecvConstraint) String() string {
  606. return fmt.Sprintf("n%d = reflect n%d.Recv()", c.result, c.v)
  607. }
  608. func (c *rVRecvConstraint) solve(a *analysis, delta *nodeset) {
  609. changed := false
  610. for _, x := range delta.AppendTo(a.deltaSpace) {
  611. vObj := nodeid(x)
  612. tDyn, ch, indirect := a.taggedValue(vObj)
  613. tChan, _ := tDyn.Underlying().(*types.Chan)
  614. if tChan == nil {
  615. continue // not a channel
  616. }
  617. if indirect {
  618. // TODO(adonovan): we'll need to implement this
  619. // when we start creating indirect tagged objects.
  620. panic("indirect tagged object")
  621. }
  622. tElem := tChan.Elem()
  623. elemObj := a.makeTagged(tElem, c.cgn, nil)
  624. a.load(elemObj+1, ch, 0, a.sizeof(tElem))
  625. if a.addLabel(c.result, elemObj) {
  626. changed = true
  627. }
  628. }
  629. if changed {
  630. a.addWork(c.result)
  631. }
  632. }
  633. func ext۰reflect۰Value۰Recv(a *analysis, cgn *cgnode) {
  634. a.addConstraint(&rVRecvConstraint{
  635. cgn: cgn,
  636. v: a.funcParams(cgn.obj),
  637. result: a.funcResults(cgn.obj),
  638. })
  639. }
  640. // ---------- func (Value).Send(Value) ----------
  641. // v.Send(x)
  642. type rVSendConstraint struct {
  643. cgn *cgnode
  644. v nodeid // (ptr)
  645. x nodeid
  646. }
  647. func (c *rVSendConstraint) ptr() nodeid { return c.v }
  648. func (c *rVSendConstraint) presolve(*hvn) {}
  649. func (c *rVSendConstraint) renumber(mapping []nodeid) {
  650. c.v = mapping[c.v]
  651. c.x = mapping[c.x]
  652. }
  653. func (c *rVSendConstraint) String() string {
  654. return fmt.Sprintf("reflect n%d.Send(n%d)", c.v, c.x)
  655. }
  656. func (c *rVSendConstraint) solve(a *analysis, delta *nodeset) {
  657. for _, x := range delta.AppendTo(a.deltaSpace) {
  658. vObj := nodeid(x)
  659. tDyn, ch, indirect := a.taggedValue(vObj)
  660. tChan, _ := tDyn.Underlying().(*types.Chan)
  661. if tChan == nil {
  662. continue // not a channel
  663. }
  664. if indirect {
  665. // TODO(adonovan): we'll need to implement this
  666. // when we start creating indirect tagged objects.
  667. panic("indirect tagged object")
  668. }
  669. // Extract x's payload to xtmp, then store to channel.
  670. tElem := tChan.Elem()
  671. xtmp := a.addNodes(tElem, "Send.xtmp")
  672. a.typeAssert(tElem, xtmp, c.x, false)
  673. a.store(ch, xtmp, 0, a.sizeof(tElem))
  674. }
  675. }
  676. func ext۰reflect۰Value۰Send(a *analysis, cgn *cgnode) {
  677. params := a.funcParams(cgn.obj)
  678. a.addConstraint(&rVSendConstraint{
  679. cgn: cgn,
  680. v: params,
  681. x: params + 1,
  682. })
  683. }
  684. func ext۰reflect۰Value۰Set(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  685. // ---------- func (Value).SetBytes(x []byte) ----------
  686. // v.SetBytes(x)
  687. type rVSetBytesConstraint struct {
  688. cgn *cgnode
  689. v nodeid // (ptr)
  690. x nodeid
  691. }
  692. func (c *rVSetBytesConstraint) ptr() nodeid { return c.v }
  693. func (c *rVSetBytesConstraint) presolve(*hvn) {}
  694. func (c *rVSetBytesConstraint) renumber(mapping []nodeid) {
  695. c.v = mapping[c.v]
  696. c.x = mapping[c.x]
  697. }
  698. func (c *rVSetBytesConstraint) String() string {
  699. return fmt.Sprintf("reflect n%d.SetBytes(n%d)", c.v, c.x)
  700. }
  701. func (c *rVSetBytesConstraint) solve(a *analysis, delta *nodeset) {
  702. for _, x := range delta.AppendTo(a.deltaSpace) {
  703. vObj := nodeid(x)
  704. tDyn, slice, indirect := a.taggedValue(vObj)
  705. if indirect {
  706. // TODO(adonovan): we'll need to implement this
  707. // when we start creating indirect tagged objects.
  708. panic("indirect tagged object")
  709. }
  710. tSlice, ok := tDyn.Underlying().(*types.Slice)
  711. if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
  712. if a.onlineCopy(slice, c.x) {
  713. a.addWork(slice)
  714. }
  715. }
  716. }
  717. }
  718. func ext۰reflect۰Value۰SetBytes(a *analysis, cgn *cgnode) {
  719. params := a.funcParams(cgn.obj)
  720. a.addConstraint(&rVSetBytesConstraint{
  721. cgn: cgn,
  722. v: params,
  723. x: params + 1,
  724. })
  725. }
  726. // ---------- func (Value).SetMapIndex(k Value, v Value) ----------
  727. // v.SetMapIndex(key, val)
  728. type rVSetMapIndexConstraint struct {
  729. cgn *cgnode
  730. v nodeid // (ptr)
  731. key nodeid
  732. val nodeid
  733. }
  734. func (c *rVSetMapIndexConstraint) ptr() nodeid { return c.v }
  735. func (c *rVSetMapIndexConstraint) presolve(*hvn) {}
  736. func (c *rVSetMapIndexConstraint) renumber(mapping []nodeid) {
  737. c.v = mapping[c.v]
  738. c.key = mapping[c.key]
  739. c.val = mapping[c.val]
  740. }
  741. func (c *rVSetMapIndexConstraint) String() string {
  742. return fmt.Sprintf("reflect n%d.SetMapIndex(n%d, n%d)", c.v, c.key, c.val)
  743. }
  744. func (c *rVSetMapIndexConstraint) solve(a *analysis, delta *nodeset) {
  745. for _, x := range delta.AppendTo(a.deltaSpace) {
  746. vObj := nodeid(x)
  747. tDyn, m, indirect := a.taggedValue(vObj)
  748. tMap, _ := tDyn.Underlying().(*types.Map)
  749. if tMap == nil {
  750. continue // not a map
  751. }
  752. if indirect {
  753. // TODO(adonovan): we'll need to implement this
  754. // when we start creating indirect tagged objects.
  755. panic("indirect tagged object")
  756. }
  757. keysize := a.sizeof(tMap.Key())
  758. // Extract key's payload to keytmp, then store to map key.
  759. keytmp := a.addNodes(tMap.Key(), "SetMapIndex.keytmp")
  760. a.typeAssert(tMap.Key(), keytmp, c.key, false)
  761. a.store(m, keytmp, 0, keysize)
  762. // Extract val's payload to vtmp, then store to map value.
  763. valtmp := a.addNodes(tMap.Elem(), "SetMapIndex.valtmp")
  764. a.typeAssert(tMap.Elem(), valtmp, c.val, false)
  765. a.store(m, valtmp, keysize, a.sizeof(tMap.Elem()))
  766. }
  767. }
  768. func ext۰reflect۰Value۰SetMapIndex(a *analysis, cgn *cgnode) {
  769. params := a.funcParams(cgn.obj)
  770. a.addConstraint(&rVSetMapIndexConstraint{
  771. cgn: cgn,
  772. v: params,
  773. key: params + 1,
  774. val: params + 2,
  775. })
  776. }
  777. func ext۰reflect۰Value۰SetPointer(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  778. // ---------- func (Value).Slice(v Value, i, j int) Value ----------
  779. // result = v.Slice(_, _)
  780. type rVSliceConstraint struct {
  781. cgn *cgnode
  782. v nodeid // (ptr)
  783. result nodeid // (indirect)
  784. }
  785. func (c *rVSliceConstraint) ptr() nodeid { return c.v }
  786. func (c *rVSliceConstraint) presolve(h *hvn) {
  787. h.markIndirect(onodeid(c.result), "rVSlice.result")
  788. }
  789. func (c *rVSliceConstraint) renumber(mapping []nodeid) {
  790. c.v = mapping[c.v]
  791. c.result = mapping[c.result]
  792. }
  793. func (c *rVSliceConstraint) String() string {
  794. return fmt.Sprintf("n%d = reflect n%d.Slice(_, _)", c.result, c.v)
  795. }
  796. func (c *rVSliceConstraint) solve(a *analysis, delta *nodeset) {
  797. changed := false
  798. for _, x := range delta.AppendTo(a.deltaSpace) {
  799. vObj := nodeid(x)
  800. tDyn, payload, indirect := a.taggedValue(vObj)
  801. if indirect {
  802. // TODO(adonovan): we'll need to implement this
  803. // when we start creating indirect tagged objects.
  804. panic("indirect tagged object")
  805. }
  806. var res nodeid
  807. switch t := tDyn.Underlying().(type) {
  808. case *types.Pointer:
  809. if tArr, ok := t.Elem().Underlying().(*types.Array); ok {
  810. // pointer to array
  811. res = a.makeTagged(types.NewSlice(tArr.Elem()), c.cgn, nil)
  812. if a.onlineCopy(res+1, payload) {
  813. a.addWork(res + 1)
  814. }
  815. }
  816. case *types.Array:
  817. // TODO(adonovan): implement addressable
  818. // arrays when we do indirect tagged objects.
  819. case *types.Slice:
  820. res = vObj
  821. case *types.Basic:
  822. if t == types.Typ[types.String] {
  823. res = vObj
  824. }
  825. }
  826. if res != 0 && a.addLabel(c.result, res) {
  827. changed = true
  828. }
  829. }
  830. if changed {
  831. a.addWork(c.result)
  832. }
  833. }
  834. func ext۰reflect۰Value۰Slice(a *analysis, cgn *cgnode) {
  835. a.addConstraint(&rVSliceConstraint{
  836. cgn: cgn,
  837. v: a.funcParams(cgn.obj),
  838. result: a.funcResults(cgn.obj),
  839. })
  840. }
  841. // -------------------- Standalone reflect functions --------------------
  842. func ext۰reflect۰Append(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  843. func ext۰reflect۰AppendSlice(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  844. func ext۰reflect۰Copy(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  845. // ---------- func ChanOf(ChanDir, Type) Type ----------
  846. // result = ChanOf(dir, t)
  847. type reflectChanOfConstraint struct {
  848. cgn *cgnode
  849. t nodeid // (ptr)
  850. result nodeid // (indirect)
  851. dirs []types.ChanDir
  852. }
  853. func (c *reflectChanOfConstraint) ptr() nodeid { return c.t }
  854. func (c *reflectChanOfConstraint) presolve(h *hvn) {
  855. h.markIndirect(onodeid(c.result), "reflectChanOf.result")
  856. }
  857. func (c *reflectChanOfConstraint) renumber(mapping []nodeid) {
  858. c.t = mapping[c.t]
  859. c.result = mapping[c.result]
  860. }
  861. func (c *reflectChanOfConstraint) String() string {
  862. return fmt.Sprintf("n%d = reflect.ChanOf(n%d)", c.result, c.t)
  863. }
  864. func (c *reflectChanOfConstraint) solve(a *analysis, delta *nodeset) {
  865. changed := false
  866. for _, x := range delta.AppendTo(a.deltaSpace) {
  867. tObj := nodeid(x)
  868. T := a.rtypeTaggedValue(tObj)
  869. if typeTooHigh(T) {
  870. continue
  871. }
  872. for _, dir := range c.dirs {
  873. if a.addLabel(c.result, a.makeRtype(types.NewChan(dir, T))) {
  874. changed = true
  875. }
  876. }
  877. }
  878. if changed {
  879. a.addWork(c.result)
  880. }
  881. }
  882. // dirMap maps reflect.ChanDir to the set of channel types generated by ChanOf.
  883. var dirMap = [...][]types.ChanDir{
  884. 0: {types.SendOnly, types.RecvOnly, types.SendRecv}, // unknown
  885. reflect.RecvDir: {types.RecvOnly},
  886. reflect.SendDir: {types.SendOnly},
  887. reflect.BothDir: {types.SendRecv},
  888. }
  889. func ext۰reflect۰ChanOf(a *analysis, cgn *cgnode) {
  890. // If we have access to the callsite,
  891. // and the channel argument is a constant (as is usual),
  892. // only generate the requested direction.
  893. var dir reflect.ChanDir // unknown
  894. if site := cgn.callersite; site != nil {
  895. if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
  896. v, _ := exact.Int64Val(c.Value)
  897. if 0 <= v && v <= int64(reflect.BothDir) {
  898. dir = reflect.ChanDir(v)
  899. }
  900. }
  901. }
  902. params := a.funcParams(cgn.obj)
  903. a.addConstraint(&reflectChanOfConstraint{
  904. cgn: cgn,
  905. t: params + 1,
  906. result: a.funcResults(cgn.obj),
  907. dirs: dirMap[dir],
  908. })
  909. }
  910. // ---------- func Indirect(v Value) Value ----------
  911. // result = Indirect(v)
  912. type reflectIndirectConstraint struct {
  913. cgn *cgnode
  914. v nodeid // (ptr)
  915. result nodeid // (indirect)
  916. }
  917. func (c *reflectIndirectConstraint) ptr() nodeid { return c.v }
  918. func (c *reflectIndirectConstraint) presolve(h *hvn) {
  919. h.markIndirect(onodeid(c.result), "reflectIndirect.result")
  920. }
  921. func (c *reflectIndirectConstraint) renumber(mapping []nodeid) {
  922. c.v = mapping[c.v]
  923. c.result = mapping[c.result]
  924. }
  925. func (c *reflectIndirectConstraint) String() string {
  926. return fmt.Sprintf("n%d = reflect.Indirect(n%d)", c.result, c.v)
  927. }
  928. func (c *reflectIndirectConstraint) solve(a *analysis, delta *nodeset) {
  929. changed := false
  930. for _, x := range delta.AppendTo(a.deltaSpace) {
  931. vObj := nodeid(x)
  932. tDyn, _, _ := a.taggedValue(vObj)
  933. var res nodeid
  934. if tPtr, ok := tDyn.Underlying().(*types.Pointer); ok {
  935. // load the payload of the pointer's tagged object
  936. // into a new tagged object
  937. res = a.makeTagged(tPtr.Elem(), c.cgn, nil)
  938. a.load(res+1, vObj+1, 0, a.sizeof(tPtr.Elem()))
  939. } else {
  940. res = vObj
  941. }
  942. if a.addLabel(c.result, res) {
  943. changed = true
  944. }
  945. }
  946. if changed {
  947. a.addWork(c.result)
  948. }
  949. }
  950. func ext۰reflect۰Indirect(a *analysis, cgn *cgnode) {
  951. a.addConstraint(&reflectIndirectConstraint{
  952. cgn: cgn,
  953. v: a.funcParams(cgn.obj),
  954. result: a.funcResults(cgn.obj),
  955. })
  956. }
  957. // ---------- func MakeChan(Type) Value ----------
  958. // result = MakeChan(typ)
  959. type reflectMakeChanConstraint struct {
  960. cgn *cgnode
  961. typ nodeid // (ptr)
  962. result nodeid // (indirect)
  963. }
  964. func (c *reflectMakeChanConstraint) ptr() nodeid { return c.typ }
  965. func (c *reflectMakeChanConstraint) presolve(h *hvn) {
  966. h.markIndirect(onodeid(c.result), "reflectMakeChan.result")
  967. }
  968. func (c *reflectMakeChanConstraint) renumber(mapping []nodeid) {
  969. c.typ = mapping[c.typ]
  970. c.result = mapping[c.result]
  971. }
  972. func (c *reflectMakeChanConstraint) String() string {
  973. return fmt.Sprintf("n%d = reflect.MakeChan(n%d)", c.result, c.typ)
  974. }
  975. func (c *reflectMakeChanConstraint) solve(a *analysis, delta *nodeset) {
  976. changed := false
  977. for _, x := range delta.AppendTo(a.deltaSpace) {
  978. typObj := nodeid(x)
  979. T := a.rtypeTaggedValue(typObj)
  980. tChan, ok := T.Underlying().(*types.Chan)
  981. if !ok || tChan.Dir() != types.SendRecv {
  982. continue // not a bidirectional channel type
  983. }
  984. obj := a.nextNode()
  985. a.addNodes(tChan.Elem(), "reflect.MakeChan.value")
  986. a.endObject(obj, c.cgn, nil)
  987. // put its address in a new T-tagged object
  988. id := a.makeTagged(T, c.cgn, nil)
  989. a.addLabel(id+1, obj)
  990. // flow the T-tagged object to the result
  991. if a.addLabel(c.result, id) {
  992. changed = true
  993. }
  994. }
  995. if changed {
  996. a.addWork(c.result)
  997. }
  998. }
  999. func ext۰reflect۰MakeChan(a *analysis, cgn *cgnode) {
  1000. a.addConstraint(&reflectMakeChanConstraint{
  1001. cgn: cgn,
  1002. typ: a.funcParams(cgn.obj),
  1003. result: a.funcResults(cgn.obj),
  1004. })
  1005. }
  1006. func ext۰reflect۰MakeFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  1007. // ---------- func MakeMap(Type) Value ----------
  1008. // result = MakeMap(typ)
  1009. type reflectMakeMapConstraint struct {
  1010. cgn *cgnode
  1011. typ nodeid // (ptr)
  1012. result nodeid // (indirect)
  1013. }
  1014. func (c *reflectMakeMapConstraint) ptr() nodeid { return c.typ }
  1015. func (c *reflectMakeMapConstraint) presolve(h *hvn) {
  1016. h.markIndirect(onodeid(c.result), "reflectMakeMap.result")
  1017. }
  1018. func (c *reflectMakeMapConstraint) renumber(mapping []nodeid) {
  1019. c.typ = mapping[c.typ]
  1020. c.result = mapping[c.result]
  1021. }
  1022. func (c *reflectMakeMapConstraint) String() string {
  1023. return fmt.Sprintf("n%d = reflect.MakeMap(n%d)", c.result, c.typ)
  1024. }
  1025. func (c *reflectMakeMapConstraint) solve(a *analysis, delta *nodeset) {
  1026. changed := false
  1027. for _, x := range delta.AppendTo(a.deltaSpace) {
  1028. typObj := nodeid(x)
  1029. T := a.rtypeTaggedValue(typObj)
  1030. tMap, ok := T.Underlying().(*types.Map)
  1031. if !ok {
  1032. continue // not a map type
  1033. }
  1034. mapObj := a.nextNode()
  1035. a.addNodes(tMap.Key(), "reflect.MakeMap.key")
  1036. a.addNodes(tMap.Elem(), "reflect.MakeMap.value")
  1037. a.endObject(mapObj, c.cgn, nil)
  1038. // put its address in a new T-tagged object
  1039. id := a.makeTagged(T, c.cgn, nil)
  1040. a.addLabel(id+1, mapObj)
  1041. // flow the T-tagged object to the result
  1042. if a.addLabel(c.result, id) {
  1043. changed = true
  1044. }
  1045. }
  1046. if changed {
  1047. a.addWork(c.result)
  1048. }
  1049. }
  1050. func ext۰reflect۰MakeMap(a *analysis, cgn *cgnode) {
  1051. a.addConstraint(&reflectMakeMapConstraint{
  1052. cgn: cgn,
  1053. typ: a.funcParams(cgn.obj),
  1054. result: a.funcResults(cgn.obj),
  1055. })
  1056. }
  1057. // ---------- func MakeSlice(Type) Value ----------
  1058. // result = MakeSlice(typ)
  1059. type reflectMakeSliceConstraint struct {
  1060. cgn *cgnode
  1061. typ nodeid // (ptr)
  1062. result nodeid // (indirect)
  1063. }
  1064. func (c *reflectMakeSliceConstraint) ptr() nodeid { return c.typ }
  1065. func (c *reflectMakeSliceConstraint) presolve(h *hvn) {
  1066. h.markIndirect(onodeid(c.result), "reflectMakeSlice.result")
  1067. }
  1068. func (c *reflectMakeSliceConstraint) renumber(mapping []nodeid) {
  1069. c.typ = mapping[c.typ]
  1070. c.result = mapping[c.result]
  1071. }
  1072. func (c *reflectMakeSliceConstraint) String() string {
  1073. return fmt.Sprintf("n%d = reflect.MakeSlice(n%d)", c.result, c.typ)
  1074. }
  1075. func (c *reflectMakeSliceConstraint) solve(a *analysis, delta *nodeset) {
  1076. changed := false
  1077. for _, x := range delta.AppendTo(a.deltaSpace) {
  1078. typObj := nodeid(x)
  1079. T := a.rtypeTaggedValue(typObj)
  1080. if _, ok := T.Underlying().(*types.Slice); !ok {
  1081. continue // not a slice type
  1082. }
  1083. obj := a.nextNode()
  1084. a.addNodes(sliceToArray(T), "reflect.MakeSlice")
  1085. a.endObject(obj, c.cgn, nil)
  1086. // put its address in a new T-tagged object
  1087. id := a.makeTagged(T, c.cgn, nil)
  1088. a.addLabel(id+1, obj)
  1089. // flow the T-tagged object to the result
  1090. if a.addLabel(c.result, id) {
  1091. changed = true
  1092. }
  1093. }
  1094. if changed {
  1095. a.addWork(c.result)
  1096. }
  1097. }
  1098. func ext۰reflect۰MakeSlice(a *analysis, cgn *cgnode) {
  1099. a.addConstraint(&reflectMakeSliceConstraint{
  1100. cgn: cgn,
  1101. typ: a.funcParams(cgn.obj),
  1102. result: a.funcResults(cgn.obj),
  1103. })
  1104. }
  1105. func ext۰reflect۰MapOf(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  1106. // ---------- func New(Type) Value ----------
  1107. // result = New(typ)
  1108. type reflectNewConstraint struct {
  1109. cgn *cgnode
  1110. typ nodeid // (ptr)
  1111. result nodeid // (indirect)
  1112. }
  1113. func (c *reflectNewConstraint) ptr() nodeid { return c.typ }
  1114. func (c *reflectNewConstraint) presolve(h *hvn) {
  1115. h.markIndirect(onodeid(c.result), "reflectNew.result")
  1116. }
  1117. func (c *reflectNewConstraint) renumber(mapping []nodeid) {
  1118. c.typ = mapping[c.typ]
  1119. c.result = mapping[c.result]
  1120. }
  1121. func (c *reflectNewConstraint) String() string {
  1122. return fmt.Sprintf("n%d = reflect.New(n%d)", c.result, c.typ)
  1123. }
  1124. func (c *reflectNewConstraint) solve(a *analysis, delta *nodeset) {
  1125. changed := false
  1126. for _, x := range delta.AppendTo(a.deltaSpace) {
  1127. typObj := nodeid(x)
  1128. T := a.rtypeTaggedValue(typObj)
  1129. // allocate new T object
  1130. newObj := a.nextNode()
  1131. a.addNodes(T, "reflect.New")
  1132. a.endObject(newObj, c.cgn, nil)
  1133. // put its address in a new *T-tagged object
  1134. id := a.makeTagged(types.NewPointer(T), c.cgn, nil)
  1135. a.addLabel(id+1, newObj)
  1136. // flow the pointer to the result
  1137. if a.addLabel(c.result, id) {
  1138. changed = true
  1139. }
  1140. }
  1141. if changed {
  1142. a.addWork(c.result)
  1143. }
  1144. }
  1145. func ext۰reflect۰New(a *analysis, cgn *cgnode) {
  1146. a.addConstraint(&reflectNewConstraint{
  1147. cgn: cgn,
  1148. typ: a.funcParams(cgn.obj),
  1149. result: a.funcResults(cgn.obj),
  1150. })
  1151. }
  1152. func ext۰reflect۰NewAt(a *analysis, cgn *cgnode) {
  1153. ext۰reflect۰New(a, cgn)
  1154. // TODO(adonovan): also report dynamic calls to unsound intrinsics.
  1155. if site := cgn.callersite; site != nil {
  1156. a.warnf(site.pos(), "unsound: %s contains a reflect.NewAt() call", site.instr.Parent())
  1157. }
  1158. }
  1159. // ---------- func PtrTo(Type) Type ----------
  1160. // result = PtrTo(t)
  1161. type reflectPtrToConstraint struct {
  1162. cgn *cgnode
  1163. t nodeid // (ptr)
  1164. result nodeid // (indirect)
  1165. }
  1166. func (c *reflectPtrToConstraint) ptr() nodeid { return c.t }
  1167. func (c *reflectPtrToConstraint) presolve(h *hvn) {
  1168. h.markIndirect(onodeid(c.result), "reflectPtrTo.result")
  1169. }
  1170. func (c *reflectPtrToConstraint) renumber(mapping []nodeid) {
  1171. c.t = mapping[c.t]
  1172. c.result = mapping[c.result]
  1173. }
  1174. func (c *reflectPtrToConstraint) String() string {
  1175. return fmt.Sprintf("n%d = reflect.PtrTo(n%d)", c.result, c.t)
  1176. }
  1177. func (c *reflectPtrToConstraint) solve(a *analysis, delta *nodeset) {
  1178. changed := false
  1179. for _, x := range delta.AppendTo(a.deltaSpace) {
  1180. tObj := nodeid(x)
  1181. T := a.rtypeTaggedValue(tObj)
  1182. if typeTooHigh(T) {
  1183. continue
  1184. }
  1185. if a.addLabel(c.result, a.makeRtype(types.NewPointer(T))) {
  1186. changed = true
  1187. }
  1188. }
  1189. if changed {
  1190. a.addWork(c.result)
  1191. }
  1192. }
  1193. func ext۰reflect۰PtrTo(a *analysis, cgn *cgnode) {
  1194. a.addConstraint(&reflectPtrToConstraint{
  1195. cgn: cgn,
  1196. t: a.funcParams(cgn.obj),
  1197. result: a.funcResults(cgn.obj),
  1198. })
  1199. }
  1200. func ext۰reflect۰Select(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  1201. // ---------- func SliceOf(Type) Type ----------
  1202. // result = SliceOf(t)
  1203. type reflectSliceOfConstraint struct {
  1204. cgn *cgnode
  1205. t nodeid // (ptr)
  1206. result nodeid // (indirect)
  1207. }
  1208. func (c *reflectSliceOfConstraint) ptr() nodeid { return c.t }
  1209. func (c *reflectSliceOfConstraint) presolve(h *hvn) {
  1210. h.markIndirect(onodeid(c.result), "reflectSliceOf.result")
  1211. }
  1212. func (c *reflectSliceOfConstraint) renumber(mapping []nodeid) {
  1213. c.t = mapping[c.t]
  1214. c.result = mapping[c.result]
  1215. }
  1216. func (c *reflectSliceOfConstraint) String() string {
  1217. return fmt.Sprintf("n%d = reflect.SliceOf(n%d)", c.result, c.t)
  1218. }
  1219. func (c *reflectSliceOfConstraint) solve(a *analysis, delta *nodeset) {
  1220. changed := false
  1221. for _, x := range delta.AppendTo(a.deltaSpace) {
  1222. tObj := nodeid(x)
  1223. T := a.rtypeTaggedValue(tObj)
  1224. if typeTooHigh(T) {
  1225. continue
  1226. }
  1227. if a.addLabel(c.result, a.makeRtype(types.NewSlice(T))) {
  1228. changed = true
  1229. }
  1230. }
  1231. if changed {
  1232. a.addWork(c.result)
  1233. }
  1234. }
  1235. func ext۰reflect۰SliceOf(a *analysis, cgn *cgnode) {
  1236. a.addConstraint(&reflectSliceOfConstraint{
  1237. cgn: cgn,
  1238. t: a.funcParams(cgn.obj),
  1239. result: a.funcResults(cgn.obj),
  1240. })
  1241. }
  1242. // ---------- func TypeOf(v Value) Type ----------
  1243. // result = TypeOf(i)
  1244. type reflectTypeOfConstraint struct {
  1245. cgn *cgnode
  1246. i nodeid // (ptr)
  1247. result nodeid // (indirect)
  1248. }
  1249. func (c *reflectTypeOfConstraint) ptr() nodeid { return c.i }
  1250. func (c *reflectTypeOfConstraint) presolve(h *hvn) {
  1251. h.markIndirect(onodeid(c.result), "reflectTypeOf.result")
  1252. }
  1253. func (c *reflectTypeOfConstraint) renumber(mapping []nodeid) {
  1254. c.i = mapping[c.i]
  1255. c.result = mapping[c.result]
  1256. }
  1257. func (c *reflectTypeOfConstraint) String() string {
  1258. return fmt.Sprintf("n%d = reflect.TypeOf(n%d)", c.result, c.i)
  1259. }
  1260. func (c *reflectTypeOfConstraint) solve(a *analysis, delta *nodeset) {
  1261. changed := false
  1262. for _, x := range delta.AppendTo(a.deltaSpace) {
  1263. iObj := nodeid(x)
  1264. tDyn, _, _ := a.taggedValue(iObj)
  1265. if a.addLabel(c.result, a.makeRtype(tDyn)) {
  1266. changed = true
  1267. }
  1268. }
  1269. if changed {
  1270. a.addWork(c.result)
  1271. }
  1272. }
  1273. func ext۰reflect۰TypeOf(a *analysis, cgn *cgnode) {
  1274. a.addConstraint(&reflectTypeOfConstraint{
  1275. cgn: cgn,
  1276. i: a.funcParams(cgn.obj),
  1277. result: a.funcResults(cgn.obj),
  1278. })
  1279. }
  1280. // ---------- func ValueOf(interface{}) Value ----------
  1281. func ext۰reflect۰ValueOf(a *analysis, cgn *cgnode) {
  1282. // TODO(adonovan): when we start creating indirect tagged
  1283. // objects, we'll need to handle them specially here since
  1284. // they must never appear in the PTS of an interface{}.
  1285. a.copy(a.funcResults(cgn.obj), a.funcParams(cgn.obj), 1)
  1286. }
  1287. // ---------- func Zero(Type) Value ----------
  1288. // result = Zero(typ)
  1289. type reflectZeroConstraint struct {
  1290. cgn *cgnode
  1291. typ nodeid // (ptr)
  1292. result nodeid // (indirect)
  1293. }
  1294. func (c *reflectZeroConstraint) ptr() nodeid { return c.typ }
  1295. func (c *reflectZeroConstraint) presolve(h *hvn) {
  1296. h.markIndirect(onodeid(c.result), "reflectZero.result")
  1297. }
  1298. func (c *reflectZeroConstraint) renumber(mapping []nodeid) {
  1299. c.typ = mapping[c.typ]
  1300. c.result = mapping[c.result]
  1301. }
  1302. func (c *reflectZeroConstraint) String() string {
  1303. return fmt.Sprintf("n%d = reflect.Zero(n%d)", c.result, c.typ)
  1304. }
  1305. func (c *reflectZeroConstraint) solve(a *analysis, delta *nodeset) {
  1306. changed := false
  1307. for _, x := range delta.AppendTo(a.deltaSpace) {
  1308. typObj := nodeid(x)
  1309. T := a.rtypeTaggedValue(typObj)
  1310. // TODO(adonovan): if T is an interface type, we need
  1311. // to create an indirect tagged object containing
  1312. // new(T). To avoid updates of such shared values,
  1313. // we'll need another flag on indirect tagged objects
  1314. // that marks whether they are addressable or
  1315. // readonly, just like the reflect package does.
  1316. // memoize using a.reflectZeros[T]
  1317. var id nodeid
  1318. if z := a.reflectZeros.At(T); false && z != nil {
  1319. id = z.(nodeid)
  1320. } else {
  1321. id = a.makeTagged(T, c.cgn, nil)
  1322. a.reflectZeros.Set(T, id)
  1323. }
  1324. if a.addLabel(c.result, id) {
  1325. changed = true
  1326. }
  1327. }
  1328. if changed {
  1329. a.addWork(c.result)
  1330. }
  1331. }
  1332. func ext۰reflect۰Zero(a *analysis, cgn *cgnode) {
  1333. a.addConstraint(&reflectZeroConstraint{
  1334. cgn: cgn,
  1335. typ: a.funcParams(cgn.obj),
  1336. result: a.funcResults(cgn.obj),
  1337. })
  1338. }
  1339. // -------------------- (*reflect.rtype) methods --------------------
  1340. // ---------- func (*rtype) Elem() Type ----------
  1341. // result = Elem(t)
  1342. type rtypeElemConstraint struct {
  1343. cgn *cgnode
  1344. t nodeid // (ptr)
  1345. result nodeid // (indirect)
  1346. }
  1347. func (c *rtypeElemConstraint) ptr() nodeid { return c.t }
  1348. func (c *rtypeElemConstraint) presolve(h *hvn) {
  1349. h.markIndirect(onodeid(c.result), "rtypeElem.result")
  1350. }
  1351. func (c *rtypeElemConstraint) renumber(mapping []nodeid) {
  1352. c.t = mapping[c.t]
  1353. c.result = mapping[c.result]
  1354. }
  1355. func (c *rtypeElemConstraint) String() string {
  1356. return fmt.Sprintf("n%d = (*reflect.rtype).Elem(n%d)", c.result, c.t)
  1357. }
  1358. func (c *rtypeElemConstraint) solve(a *analysis, delta *nodeset) {
  1359. // Implemented by *types.{Map,Chan,Array,Slice,Pointer}.
  1360. type hasElem interface {
  1361. Elem() types.Type
  1362. }
  1363. changed := false
  1364. for _, x := range delta.AppendTo(a.deltaSpace) {
  1365. tObj := nodeid(x)
  1366. T := a.nodes[tObj].obj.data.(types.Type)
  1367. if tHasElem, ok := T.Underlying().(hasElem); ok {
  1368. if a.addLabel(c.result, a.makeRtype(tHasElem.Elem())) {
  1369. changed = true
  1370. }
  1371. }
  1372. }
  1373. if changed {
  1374. a.addWork(c.result)
  1375. }
  1376. }
  1377. func ext۰reflect۰rtype۰Elem(a *analysis, cgn *cgnode) {
  1378. a.addConstraint(&rtypeElemConstraint{
  1379. cgn: cgn,
  1380. t: a.funcParams(cgn.obj),
  1381. result: a.funcResults(cgn.obj),
  1382. })
  1383. }
  1384. // ---------- func (*rtype) Field(int) StructField ----------
  1385. // ---------- func (*rtype) FieldByName(string) (StructField, bool) ----------
  1386. // result = FieldByName(t, name)
  1387. // result = Field(t, _)
  1388. type rtypeFieldByNameConstraint struct {
  1389. cgn *cgnode
  1390. name string // name of field; "" for unknown
  1391. t nodeid // (ptr)
  1392. result nodeid // (indirect)
  1393. }
  1394. func (c *rtypeFieldByNameConstraint) ptr() nodeid { return c.t }
  1395. func (c *rtypeFieldByNameConstraint) presolve(h *hvn) {
  1396. h.markIndirect(onodeid(c.result+3), "rtypeFieldByName.result.Type")
  1397. }
  1398. func (c *rtypeFieldByNameConstraint) renumber(mapping []nodeid) {
  1399. c.t = mapping[c.t]
  1400. c.result = mapping[c.result]
  1401. }
  1402. func (c *rtypeFieldByNameConstraint) String() string {
  1403. return fmt.Sprintf("n%d = (*reflect.rtype).FieldByName(n%d, %q)", c.result, c.t, c.name)
  1404. }
  1405. func (c *rtypeFieldByNameConstraint) solve(a *analysis, delta *nodeset) {
  1406. // type StructField struct {
  1407. // 0 __identity__
  1408. // 1 Name string
  1409. // 2 PkgPath string
  1410. // 3 Type Type
  1411. // 4 Tag StructTag
  1412. // 5 Offset uintptr
  1413. // 6 Index []int
  1414. // 7 Anonymous bool
  1415. // }
  1416. for _, x := range delta.AppendTo(a.deltaSpace) {
  1417. tObj := nodeid(x)
  1418. T := a.nodes[tObj].obj.data.(types.Type)
  1419. tStruct, ok := T.Underlying().(*types.Struct)
  1420. if !ok {
  1421. continue // not a struct type
  1422. }
  1423. n := tStruct.NumFields()
  1424. for i := 0; i < n; i++ {
  1425. f := tStruct.Field(i)
  1426. if c.name == "" || c.name == f.Name() {
  1427. // a.offsetOf(Type) is 3.
  1428. if id := c.result + 3; a.addLabel(id, a.makeRtype(f.Type())) {
  1429. a.addWork(id)
  1430. }
  1431. // TODO(adonovan): StructField.Index should be non-nil.
  1432. }
  1433. }
  1434. }
  1435. }
  1436. func ext۰reflect۰rtype۰FieldByName(a *analysis, cgn *cgnode) {
  1437. // If we have access to the callsite,
  1438. // and the argument is a string constant,
  1439. // return only that field.
  1440. var name string
  1441. if site := cgn.callersite; site != nil {
  1442. if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
  1443. name = exact.StringVal(c.Value)
  1444. }
  1445. }
  1446. a.addConstraint(&rtypeFieldByNameConstraint{
  1447. cgn: cgn,
  1448. name: name,
  1449. t: a.funcParams(cgn.obj),
  1450. result: a.funcResults(cgn.obj),
  1451. })
  1452. }
  1453. func ext۰reflect۰rtype۰Field(a *analysis, cgn *cgnode) {
  1454. // No-one ever calls Field with a constant argument,
  1455. // so we don't specialize that case.
  1456. a.addConstraint(&rtypeFieldByNameConstraint{
  1457. cgn: cgn,
  1458. t: a.funcParams(cgn.obj),
  1459. result: a.funcResults(cgn.obj),
  1460. })
  1461. }
  1462. func ext۰reflect۰rtype۰FieldByIndex(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  1463. func ext۰reflect۰rtype۰FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
  1464. // ---------- func (*rtype) In/Out(i int) Type ----------
  1465. // result = In/Out(t, i)
  1466. type rtypeInOutConstraint struct {
  1467. cgn *cgnode
  1468. t nodeid // (ptr)
  1469. result nodeid // (indirect)
  1470. out bool
  1471. i int // -ve if not a constant
  1472. }
  1473. func (c *rtypeInOutConstraint) ptr() nodeid { return c.t }
  1474. func (c *rtypeInOutConstraint) presolve(h *hvn) {
  1475. h.markIndirect(onodeid(c.result), "rtypeInOut.result")
  1476. }
  1477. func (c *rtypeInOutConstraint) renumber(mapping []nodeid) {
  1478. c.t = mapping[c.t]
  1479. c.result = mapping[c.result]
  1480. }
  1481. func (c *rtypeInOutConstraint) String() string {
  1482. return fmt.Sprintf("n%d = (*reflect.rtype).InOut(n%d, %d)", c.result, c.t, c.i)
  1483. }
  1484. func (c *rtypeInOutConstraint) solve(a *analysis, delta *nodeset) {
  1485. changed := false
  1486. for _, x := range delta.AppendTo(a.deltaSpace) {
  1487. tObj := nodeid(x)
  1488. T := a.nodes[tObj].obj.data.(types.Type)
  1489. sig, ok := T.Underlying().(*types.Signature)
  1490. if !ok {
  1491. continue // not a func type
  1492. }
  1493. tuple := sig.Params()
  1494. if c.out {
  1495. tuple = sig.Results()
  1496. }
  1497. for i, n := 0, tuple.Len(); i < n; i++ {
  1498. if c.i < 0 || c.i == i {
  1499. if a.addLabel(c.result, a.makeRtype(tuple.At(i).Type())) {
  1500. changed = true
  1501. }
  1502. }
  1503. }
  1504. }
  1505. if changed {
  1506. a.addWork(c.result)
  1507. }
  1508. }
  1509. func ext۰reflect۰rtype۰InOut(a *analysis, cgn *cgnode, out bool) {
  1510. // If we have access to the callsite,
  1511. // and the argument is an int constant,
  1512. // return only that parameter.
  1513. index := -1
  1514. if site := cgn.callersite; site != nil {
  1515. if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
  1516. v, _ := exact.Int64Val(c.Value)
  1517. index = int(v)
  1518. }
  1519. }
  1520. a.addConstraint(&rtypeInOutConstraint{
  1521. cgn: cgn,
  1522. t: a.funcParams(cgn.obj),
  1523. result: a.funcResults(cgn.obj),
  1524. out: out,
  1525. i: index,
  1526. })
  1527. }
  1528. func ext۰reflect۰rtype۰In(a *analysis, cgn *cgnode) {
  1529. ext۰reflect۰rtype۰InOut(a, cgn, false)
  1530. }
  1531. func ext۰reflect۰rtype۰Out(a *analysis, cgn *cgnode) {
  1532. ext۰reflect۰rtype۰InOut(a, cgn, true)
  1533. }
  1534. // ---------- func (*rtype) Key() Type ----------
  1535. // result = Key(t)
  1536. type rtypeKeyConstraint struct {
  1537. cgn *cgnode
  1538. t nodeid // (ptr)
  1539. result nodeid // (indirect)
  1540. }
  1541. func (c *rtypeKeyConstraint) ptr() nodeid { return c.t }
  1542. func (c *rtypeKeyConstraint) presolve(h *hvn) {
  1543. h.markIndirect(onodeid(c.result), "rtypeKey.result")
  1544. }
  1545. func (c *rtypeKeyConstraint) renumber(mapping []nodeid) {
  1546. c.t = mapping[c.t]
  1547. c.result = mapping[c.result]
  1548. }
  1549. func (c *rtypeKeyConstraint) String() string {
  1550. return fmt.Sprintf("n%d = (*reflect.rtype).Key(n%d)", c.result, c.t)
  1551. }
  1552. func (c *rtypeKeyConstraint) solve(a *analysis, delta *nodeset) {
  1553. changed := false
  1554. for _, x := range delta.AppendTo(a.deltaSpace) {
  1555. tObj := nodeid(x)
  1556. T := a.nodes[tObj].obj.data.(types.Type)
  1557. if tMap, ok := T.Underlying().(*types.Map); ok {
  1558. if a.addLabel(c.result, a.makeRtype(tMap.Key())) {
  1559. changed = true
  1560. }
  1561. }
  1562. }
  1563. if changed {
  1564. a.addWork(c.result)
  1565. }
  1566. }
  1567. func ext۰reflect۰rtype۰Key(a *analysis, cgn *cgnode) {
  1568. a.addConstraint(&rtypeKeyConstraint{
  1569. cgn: cgn,
  1570. t: a.funcParams(cgn.obj),
  1571. result: a.funcResults(cgn.obj),
  1572. })
  1573. }
  1574. // ---------- func (*rtype) Method(int) (Method, bool) ----------
  1575. // ---------- func (*rtype) MethodByName(string) (Method, bool) ----------
  1576. // result = MethodByName(t, name)
  1577. // result = Method(t, _)
  1578. type rtypeMethodByNameConstraint struct {
  1579. cgn *cgnode
  1580. name string // name of method; "" for unknown
  1581. t nodeid // (ptr)
  1582. result nodeid // (indirect)
  1583. }
  1584. func (c *rtypeMethodByNameConstraint) ptr() nodeid { return c.t }
  1585. func (c *rtypeMethodByNameConstraint) presolve(h *hvn) {
  1586. h.markIndirect(onodeid(c.result+3), "rtypeMethodByName.result.Type")
  1587. h.markIndirect(onodeid(c.result+4), "rtypeMethodByName.result.Func")
  1588. }
  1589. func (c *rtypeMethodByNameConstraint) renumber(mapping []nodeid) {
  1590. c.t = mapping[c.t]
  1591. c.result = mapping[c.result]
  1592. }
  1593. func (c *rtypeMethodByNameConstraint) String() string {
  1594. return fmt.Sprintf("n%d = (*reflect.rtype).MethodByName(n%d, %q)", c.result, c.t, c.name)
  1595. }
  1596. // changeRecv returns sig with Recv prepended to Params().
  1597. func changeRecv(sig *types.Signature) *types.Signature {
  1598. params := sig.Params()
  1599. n := params.Len()
  1600. p2 := make([]*types.Var, n+1)
  1601. p2[0] = sig.Recv()
  1602. for i := 0; i < n; i++ {
  1603. p2[i+1] = params.At(i)
  1604. }
  1605. return types.NewSignature(nil, types.NewTuple(p2...), sig.Results(), sig.Variadic())
  1606. }
  1607. func (c *rtypeMethodByNameConstraint) solve(a *analysis, delta *nodeset) {
  1608. for _, x := range delta.AppendTo(a.deltaSpace) {
  1609. tObj := nodeid(x)
  1610. T := a.nodes[tObj].obj.data.(types.Type)
  1611. isIface := isInterface(T)
  1612. // We don't use Lookup(c.name) when c.name != "" to avoid
  1613. // ambiguity: >1 unexported methods could match.
  1614. mset := a.prog.MethodSets.MethodSet(T)
  1615. for i, n := 0, mset.Len(); i < n; i++ {
  1616. sel := mset.At(i)
  1617. if c.name == "" || c.name == sel.Obj().Name() {
  1618. // type Method struct {
  1619. // 0 __identity__
  1620. // 1 Name string
  1621. // 2 PkgPath string
  1622. // 3 Type Type
  1623. // 4 Func Value
  1624. // 5 Index int
  1625. // }
  1626. var sig *types.Signature
  1627. var fn *ssa.Function
  1628. if isIface {
  1629. sig = sel.Type().(*types.Signature)
  1630. } else {
  1631. fn = a.prog.MethodValue(sel)
  1632. // move receiver to params[0]
  1633. sig = changeRecv(fn.Signature)
  1634. }
  1635. // a.offsetOf(Type) is 3.
  1636. if id := c.result + 3; a.addLabel(id, a.makeRtype(sig)) {
  1637. a.addWork(id)
  1638. }
  1639. if fn != nil {
  1640. // a.offsetOf(Func) is 4.
  1641. if id := c.result + 4; a.addLabel(id, a.objectNode(nil, fn)) {
  1642. a.addWork(id)
  1643. }
  1644. }
  1645. }
  1646. }
  1647. }
  1648. }
  1649. func ext۰reflect۰rtype۰MethodByName(a *analysis, cgn *cgnode) {
  1650. // If we have access to the callsite,
  1651. // and the argument is a string constant,
  1652. // return only that method.
  1653. var name string
  1654. if site := cgn.callersite; site != nil {
  1655. if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
  1656. name = exact.StringVal(c.Value)
  1657. }
  1658. }
  1659. a.addConstraint(&rtypeMethodByNameConstraint{
  1660. cgn: cgn,
  1661. name: name,
  1662. t: a.funcParams(cgn.obj),
  1663. result: a.funcResults(cgn.obj),
  1664. })
  1665. }
  1666. func ext۰reflect۰rtype۰Method(a *analysis, cgn *cgnode) {
  1667. // No-one ever calls Method with a constant argument,
  1668. // so we don't specialize that case.
  1669. a.addConstraint(&rtypeMethodByNameConstraint{
  1670. cgn: cgn,
  1671. t: a.funcParams(cgn.obj),
  1672. result: a.funcResults(cgn.obj),
  1673. })
  1674. }
  1675. // typeHeight returns the "height" of the type, which is roughly
  1676. // speaking the number of chan, map, pointer and slice type constructors
  1677. // at the root of T; these are the four type kinds that can be created
  1678. // via reflection. Chan and map constructors are counted as double the
  1679. // height of slice and pointer constructors since they are less often
  1680. // deeply nested.
  1681. //
  1682. // The solver rules for type constructors must somehow bound the set of
  1683. // types they create to ensure termination of the algorithm in cases
  1684. // where the output of a type constructor flows to its input, e.g.
  1685. //
  1686. // func f(t reflect.Type) {
  1687. // f(reflect.PtrTo(t))
  1688. // }
  1689. //
  1690. // It does this by limiting the type height to k, but this still leaves
  1691. // a potentially exponential (4^k) number of of types that may be
  1692. // enumerated in pathological cases.
  1693. //
  1694. func typeHeight(T types.Type) int {
  1695. switch T := T.(type) {
  1696. case *types.Chan:
  1697. return 2 + typeHeight(T.Elem())
  1698. case *types.Map:
  1699. k := typeHeight(T.Key())
  1700. v := typeHeight(T.Elem())
  1701. if v > k {
  1702. k = v // max(k, v)
  1703. }
  1704. return 2 + k
  1705. case *types.Slice:
  1706. return 1 + typeHeight(T.Elem())
  1707. case *types.Pointer:
  1708. return 1 + typeHeight(T.Elem())
  1709. }
  1710. return 0
  1711. }
  1712. func typeTooHigh(T types.Type) bool {
  1713. return typeHeight(T) > 3
  1714. }