123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- # Copyright (C) 2011 Apple Inc. All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions
- # are met:
- # 1. Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # 2. Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- # THE POSSIBILITY OF SUCH DAMAGE.
- require "config"
- require "ast"
- #
- # "Optimization" passes. These are used to lower the representation for
- # backends that cannot handle some of our higher-level instructions.
- #
- #
- # A temporary - a variable that will be allocated to a register after we're
- # done.
- #
- class Node
- def replaceTemporariesWithRegisters(kind)
- mapChildren {
- | node |
- node.replaceTemporariesWithRegisters(kind)
- }
- end
- end
- class Tmp < NoChildren
- attr_reader :firstMention, :lastMention
- attr_reader :kind
- attr_accessor :register
- def initialize(codeOrigin, kind)
- super(codeOrigin)
- @kind = kind
- end
-
- def dump
- "$tmp#{object_id}"
- end
-
- def mention!(position)
- if not @firstMention or position < @firstMention
- @firstMention = position
- end
- if not @lastMention or position > @lastMention
- @lastMention = position
- end
- end
-
- def replaceTemporariesWithRegisters(kind)
- if @kind == kind
- raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
- @register
- else
- self
- end
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
- end
- # Assign registers to temporaries, by finding which temporaries interfere
- # with each other. Note that this relies on temporary live ranges not crossing
- # basic block boundaries.
- def assignRegistersToTemporaries(list, kind, registers)
- list.each_with_index {
- | node, index |
- node.filter(Tmp).uniq.each {
- | tmp |
- if tmp.kind == kind
- tmp.mention! index
- end
- }
- }
-
- freeRegisters = registers.dup
- list.each_with_index {
- | node, index |
- tmpList = node.filter(Tmp).uniq
- tmpList.each {
- | tmp |
- if tmp.kind == kind and tmp.firstMention == index
- raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
- tmp.register = freeRegisters.pop
- end
- }
- tmpList.each {
- | tmp |
- if tmp.kind == kind and tmp.lastMention == index
- freeRegisters.push tmp.register
- raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
- end
- }
- }
-
- list.map {
- | node |
- node.replaceTemporariesWithRegisters(kind)
- }
- end
|