opt.rb 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # Copyright (C) 2011 Apple Inc. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions
  5. # are met:
  6. # 1. Redistributions of source code must retain the above copyright
  7. # notice, this list of conditions and the following disclaimer.
  8. # 2. Redistributions in binary form must reproduce the above copyright
  9. # notice, this list of conditions and the following disclaimer in the
  10. # documentation and/or other materials provided with the distribution.
  11. #
  12. # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  13. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  14. # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  15. # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  16. # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  17. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  18. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  19. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  20. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  22. # THE POSSIBILITY OF SUCH DAMAGE.
  23. require "config"
  24. require "ast"
  25. #
  26. # "Optimization" passes. These are used to lower the representation for
  27. # backends that cannot handle some of our higher-level instructions.
  28. #
  29. #
  30. # A temporary - a variable that will be allocated to a register after we're
  31. # done.
  32. #
  33. class Node
  34. def replaceTemporariesWithRegisters(kind)
  35. mapChildren {
  36. | node |
  37. node.replaceTemporariesWithRegisters(kind)
  38. }
  39. end
  40. end
  41. class Tmp < NoChildren
  42. attr_reader :firstMention, :lastMention
  43. attr_reader :kind
  44. attr_accessor :register
  45. def initialize(codeOrigin, kind)
  46. super(codeOrigin)
  47. @kind = kind
  48. end
  49. def dump
  50. "$tmp#{object_id}"
  51. end
  52. def mention!(position)
  53. if not @firstMention or position < @firstMention
  54. @firstMention = position
  55. end
  56. if not @lastMention or position > @lastMention
  57. @lastMention = position
  58. end
  59. end
  60. def replaceTemporariesWithRegisters(kind)
  61. if @kind == kind
  62. raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
  63. @register
  64. else
  65. self
  66. end
  67. end
  68. def address?
  69. false
  70. end
  71. def label?
  72. false
  73. end
  74. def immediate?
  75. false
  76. end
  77. def register?
  78. true
  79. end
  80. end
  81. # Assign registers to temporaries, by finding which temporaries interfere
  82. # with each other. Note that this relies on temporary live ranges not crossing
  83. # basic block boundaries.
  84. def assignRegistersToTemporaries(list, kind, registers)
  85. list.each_with_index {
  86. | node, index |
  87. node.filter(Tmp).uniq.each {
  88. | tmp |
  89. if tmp.kind == kind
  90. tmp.mention! index
  91. end
  92. }
  93. }
  94. freeRegisters = registers.dup
  95. list.each_with_index {
  96. | node, index |
  97. tmpList = node.filter(Tmp).uniq
  98. tmpList.each {
  99. | tmp |
  100. if tmp.kind == kind and tmp.firstMention == index
  101. raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
  102. tmp.register = freeRegisters.pop
  103. end
  104. }
  105. tmpList.each {
  106. | tmp |
  107. if tmp.kind == kind and tmp.lastMention == index
  108. freeRegisters.push tmp.register
  109. raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
  110. end
  111. }
  112. }
  113. list.map {
  114. | node |
  115. node.replaceTemporariesWithRegisters(kind)
  116. }
  117. end