252 lines
7.3 KiB
Ruby
Executable File
252 lines
7.3 KiB
Ruby
Executable File
#!/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 "}"
|
|
}
|
|
|