aliases.nim 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Simple alias analysis for the HLO and the code generators.
  10. import
  11. ast, astalgo, types, trees
  12. import std/intsets
  13. when defined(nimPreviewSlimSystem):
  14. import std/assertions
  15. type
  16. TAnalysisResult* = enum
  17. arNo, arMaybe, arYes
  18. proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult
  19. proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
  20. result = arNo
  21. case n.kind
  22. of nkRecList:
  23. for i in 0..<n.len:
  24. result = isPartOfAux(n[i], b, marker)
  25. if result == arYes: return
  26. of nkRecCase:
  27. assert(n[0].kind == nkSym)
  28. result = isPartOfAux(n[0], b, marker)
  29. if result == arYes: return
  30. for i in 1..<n.len:
  31. case n[i].kind
  32. of nkOfBranch, nkElse:
  33. result = isPartOfAux(lastSon(n[i]), b, marker)
  34. if result == arYes: return
  35. else: discard "isPartOfAux(record case branch)"
  36. of nkSym:
  37. result = isPartOfAux(n.sym.typ, b, marker)
  38. else: discard
  39. proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
  40. result = arNo
  41. if a == nil or b == nil: return
  42. if containsOrIncl(marker, a.id): return
  43. if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
  44. case a.kind
  45. of tyObject:
  46. if a.baseClass != nil:
  47. result = isPartOfAux(a.baseClass.skipTypes(skipPtrs), b, marker)
  48. if result == arNo: result = isPartOfAux(a.n, b, marker)
  49. of tyGenericInst, tyDistinct, tyAlias, tySink:
  50. result = isPartOfAux(skipModifier(a), b, marker)
  51. of tySet, tyArray:
  52. result = isPartOfAux(a.elementType, b, marker)
  53. of tyTuple:
  54. for aa in a.kids:
  55. result = isPartOfAux(aa, b, marker)
  56. if result == arYes: return
  57. else: discard
  58. proc isPartOf(a, b: PType): TAnalysisResult =
  59. ## checks iff 'a' can be part of 'b'. Iterates over VALUE types!
  60. var marker = initIntSet()
  61. # watch out: parameters reversed because I'm too lazy to change the code...
  62. result = isPartOfAux(b, a, marker)
  63. proc isPartOf*(a, b: PNode): TAnalysisResult =
  64. ## checks if location `a` can be part of location `b`. We treat seqs and
  65. ## strings as pointers because the code gen often just passes them as such.
  66. ##
  67. ## Note: `a` can only be part of `b`, if `a`'s type can be part of `b`'s
  68. ## type. Since however type analysis is more expensive, we perform it only
  69. ## if necessary.
  70. ##
  71. ## cases:
  72. ##
  73. ## YES-cases:
  74. ## ```
  75. ## x <| x # for general trees
  76. ## x[] <| x
  77. ## x[i] <| x
  78. ## x.f <| x
  79. ## ```
  80. ##
  81. ## NO-cases:
  82. ## ```
  83. ## x !<| y # depending on type and symbol kind
  84. ## x[constA] !<| x[constB]
  85. ## x.f !<| x.g
  86. ## x.f !<| y.f iff x !<= y
  87. ## ```
  88. ##
  89. ## MAYBE-cases:
  90. ##
  91. ## ```
  92. ## x[] ?<| y[] iff compatible type
  93. ##
  94. ##
  95. ## x[] ?<| y depending on type
  96. ## ```
  97. if a.kind == b.kind:
  98. case a.kind
  99. of nkSym:
  100. const varKinds = {skVar, skTemp, skProc, skFunc}
  101. # same symbol: aliasing:
  102. if a.sym.id == b.sym.id: result = arYes
  103. elif a.sym.kind in varKinds or b.sym.kind in varKinds:
  104. # actually, a param could alias a var but we know that cannot happen
  105. # here. XXX make this more generic
  106. result = arNo
  107. else:
  108. # use expensive type check:
  109. if isPartOf(a.sym.typ, b.sym.typ) != arNo:
  110. result = arMaybe
  111. else:
  112. result = arNo
  113. of nkBracketExpr:
  114. result = isPartOf(a[0], b[0])
  115. if a.len >= 2 and b.len >= 2:
  116. # array accesses:
  117. if result == arYes and isDeepConstExpr(a[1]) and isDeepConstExpr(b[1]):
  118. # we know it's the same array and we have 2 constant indexes;
  119. # if they are
  120. var x = if a[1].kind == nkHiddenStdConv: a[1][1] else: a[1]
  121. var y = if b[1].kind == nkHiddenStdConv: b[1][1] else: b[1]
  122. if sameValue(x, y): result = arYes
  123. else: result = arNo
  124. # else: maybe and no are accurate
  125. else:
  126. # pointer derefs:
  127. if result != arYes:
  128. if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
  129. of nkDotExpr:
  130. result = isPartOf(a[0], b[0])
  131. if result != arNo:
  132. # if the fields are different, it's not the same location
  133. if a[1].sym.id != b[1].sym.id:
  134. result = arNo
  135. of nkHiddenDeref, nkDerefExpr:
  136. result = isPartOf(a[0], b[0])
  137. # weaken because of indirection:
  138. if result != arYes:
  139. if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
  140. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  141. result = isPartOf(a[1], b[1])
  142. of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
  143. result = isPartOf(a[0], b[0])
  144. else: result = arNo
  145. # Calls return a new location, so a default of ``arNo`` is fine.
  146. else:
  147. # go down recursively; this is quite demanding:
  148. const
  149. Ix0Kinds = {nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
  150. nkCheckedFieldExpr, nkHiddenAddr}
  151. Ix1Kinds = {nkHiddenStdConv, nkHiddenSubConv, nkConv}
  152. DerefKinds = {nkHiddenDeref, nkDerefExpr}
  153. case b.kind
  154. of Ix0Kinds:
  155. # a* !<| b.f iff a* !<| b
  156. result = isPartOf(a, b[0])
  157. of DerefKinds:
  158. # a* !<| b[] iff
  159. result = arNo
  160. if isPartOf(a.typ, b.typ) != arNo:
  161. result = isPartOf(a, b[0])
  162. if result == arNo: result = arMaybe
  163. of Ix1Kinds:
  164. # a* !<| T(b) iff a* !<| b
  165. result = isPartOf(a, b[1])
  166. of nkSym:
  167. # b is an atom, so we have to check a:
  168. case a.kind
  169. of Ix0Kinds:
  170. # a.f !<| b* iff a.f !<| b*
  171. result = isPartOf(a[0], b)
  172. of Ix1Kinds:
  173. result = isPartOf(a[1], b)
  174. of DerefKinds:
  175. if isPartOf(a.typ, b.typ) != arNo:
  176. result = isPartOf(a[0], b)
  177. if result == arNo: result = arMaybe
  178. else:
  179. result = arNo
  180. else: result = arNo
  181. of nkObjConstr:
  182. result = arNo
  183. for i in 1..<b.len:
  184. let res = isPartOf(a, b[i][1])
  185. if res != arNo:
  186. result = res
  187. if res == arYes: break
  188. of nkCallKinds:
  189. result = arNo
  190. for i in 1..<b.len:
  191. let res = isPartOf(a, b[i])
  192. if res != arNo:
  193. result = res
  194. if res == arYes: break
  195. of nkBracket:
  196. if b.len > 0:
  197. result = isPartOf(a, b[0])
  198. else:
  199. result = arNo
  200. else: result = arNo