blob: 5e121e995bae73373c1336f6b45fd748828276c8 [file] [log] [blame]
#!/usr/bin/env ruby
# Copyright (C) 2013 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.
class Reference
attr_reader :kind, :number
def initialize(kind, number)
@kind = kind
@number = number
end
def resolve(hashTable, bangTable)
case @kind
when "#"
result = hashTable[@number]
when "!"
result = bangTable[@number]
else
raise
end
raise unless result
result
end
end
def parse(string)
result = []
until string.empty?
before, match, string = string.partition(/[!#]([0-9]+)/)
result << before
if match.empty?
result << string
break
end
result << Reference.new(match[0..0], match[1..-1].to_i)
end
result
end
class MetaData
attr_reader :index, :name, :parent, :val
def initialize(index, name, parent, val)
@index = index
@name = name
@parent = parent
@val = val
end
end
$definitions = []
$declarations = {}
$attributes = []
$metaData = {}
$attributesBackMap = {}
$count = 0
loop {
line = $stdin.readline
if line =~ /^; NOTE: THIS IS A COMBINED MODULE/
puts line
puts $stdin.read
exit 0
end
break if line =~ /^define/
}
puts "; NOTE: THIS IS A COMBINED MODULE"
# Loop over all definitions.
shouldContinue = true
while shouldContinue
# We're starting a new definition.
body = ""
loop {
line = $stdin.readline
break if line.chomp == "}"
body += line
}
body = parse(body)
declarations=[]
metaDataMap=[]
attributeMap = []
unresolvedMetaData = []
loop {
line = $stdin.gets
if not line
shouldContinue = false
break
elsif line =~ /^define/
break
elsif line =~ /^declare/
declarations << parse(line)
elsif line =~ /!([0-9]+) = metadata !{metadata !\"([a-zA-Z0-9_]+)\"}/
index = $1.to_i
name = $2
unless $metaData[name]
$metaData[name] = MetaData.new($metaData.size, name, nil, nil)
end
metaDataMap[index] = $metaData[$2].index
elsif line =~ /!([0-9]+) = metadata !{metadata !\"([a-zA-Z0-9_]+)\", metadata !([0-9]+)/
metaData = MetaData.new($1.to_i, $2, $3.to_i, nil)
unresolvedMetaData << metaData
elsif line =~ /!([0-9]+) = metadata !{metadata !\"branch_weights\"/
index = $1.to_i
arr1 = line.split(',');
arr1.shift
arr2 = Array.new
name = "branch_weights"
arr1.each { |a|
a =~ /i32 ([0-9]+)/
name.concat($1)
arr2.push($1)
}
unless $metaData[name]
$metaData[name] = MetaData.new($metaData.size, "branch_weights", nil, arr2)
end
metaDataMap[index] = $metaData[name].index
elsif line =~ /!([0-9]+) = metadata !{i32 ([-+0-9]+), i32 ([-+0-9]+)}/
index = $1.to_i
name = "#$2#$3"
unless $metaData[name]
$metaData[name] = MetaData.new($metaData.size, nil, nil, [$2, $3])
end
metaDataMap[index] = $metaData[name].index
elsif line =~ /attributes #([0-9]+) = /
attributeNumber = $1.to_i
attributeBody = $~.post_match
if $attributesBackMap[attributeBody]
attributeMap[attributeNumber] = $attributesBackMap[attributeBody]
else
attributeMap[attributeNumber] = $attributes.size
$attributesBackMap[attributeBody] = $attributes.size
$attributes << attributeBody
end
end
}
# Iteratively resolve meta-data references
until unresolvedMetaData.empty?
index = 0
while index < unresolvedMetaData.size
metaData = unresolvedMetaData[index]
if $metaData[metaData.name]
metaDataMap[metaData.index] = $metaData[metaData.name].index
unresolvedMetaData[index] = unresolvedMetaData[-1]
unresolvedMetaData.pop
elsif metaDataMap[metaData.parent]
metaDataMap[metaData.index] = $metaData.size
$metaData[metaData.name] = MetaData.new($metaData.size, metaData.name, metaDataMap[metaData.parent], nil)
unresolvedMetaData[index] = unresolvedMetaData[-1]
unresolvedMetaData.pop
else
index += 1
end
end
end
# Output the body with all of the things remapped.
puts "define i64 @jsBody_#{$count += 1}() {"
body.each {
| thing |
if thing.is_a? Reference
print(thing.kind + thing.resolve(attributeMap, metaDataMap).to_s)
else
print(thing)
end
}
puts "}"
# Figure out what to do with declarations.
declarations.each {
| declaration |
declaration = declaration.map {
| thing |
if thing.is_a? Reference
thing.kind + thing.resolve(attributeMap, metaDataMap).to_s
else
thing
end
}
declaration = declaration.join('')
next if $declarations[declaration]
$declarations[declaration] = true
}
end
$declarations.each_key {
| declaration |
puts declaration
}
$attributes.each_with_index {
| attribute, index |
puts "attributes ##{index} = #{attribute}"
}
$metaData.each_value {
| metaData |
print "!#{metaData.index} = metadata !{"
if metaData.name
print "metadata !\"#{metaData.name}\""
end
if metaData.parent
print ", metadata !#{metaData.parent}"
end
if (metaData.val)
index = 0
if metaData.name
index = 1
end
metaData.val.each { |a|
if (index == 0)
print "i32 #{a}"
else
print ", i32 #{a}"
end
index += 1
}
end
puts "}"
}