1#!/usr/bin/env ruby 2 3# Copyright (C) 2011 Apple Inc. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24# THE POSSIBILITY OF SUCH DAMAGE. 25 26$: << File.dirname(__FILE__) 27 28require "config" 29require "backends" 30require "digest/sha1" 31require "offsets" 32require "parser" 33require "self_hash" 34require "settings" 35require "transform" 36 37inputFlnm = ARGV.shift 38outputFlnm = ARGV.shift 39 40$stderr.puts "offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}." 41 42def emitMagicNumber 43 OFFSET_MAGIC_NUMBERS.each { 44 | number | 45 $output.puts "unsigned(#{number})," 46 } 47end 48 49inputHash = "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}" 50 51if FileTest.exist? outputFlnm 52 File.open(outputFlnm, "r") { 53 | inp | 54 firstLine = inp.gets 55 if firstLine and firstLine.chomp == inputHash 56 $stderr.puts "offlineasm: Nothing changed." 57 exit 0 58 end 59 } 60end 61 62originalAST = parse(inputFlnm) 63 64# 65# Optimize the AST to make configuration extraction faster. This reduces the AST to a form 66# that only contains the things that matter for our purposes: offsets, sizes, and if 67# statements. 68# 69 70class Node 71 def offsetsPruneTo(sequence) 72 children.each { 73 | child | 74 child.offsetsPruneTo(sequence) 75 } 76 end 77 78 def offsetsPrune 79 result = Sequence.new(codeOrigin, []) 80 offsetsPruneTo(result) 81 result 82 end 83end 84 85class IfThenElse 86 def offsetsPruneTo(sequence) 87 ifThenElse = IfThenElse.new(codeOrigin, predicate, thenCase.offsetsPrune) 88 ifThenElse.elseCase = elseCase.offsetsPrune 89 sequence.list << ifThenElse 90 end 91end 92 93class StructOffset 94 def offsetsPruneTo(sequence) 95 sequence.list << self 96 end 97end 98 99class Sizeof 100 def offsetsPruneTo(sequence) 101 sequence.list << self 102 end 103end 104 105prunedAST = originalAST.offsetsPrune 106 107File.open(outputFlnm, "w") { 108 | outp | 109 $output = outp 110 outp.puts inputHash 111 length = 0 112 emitCodeInAllConfigurations(prunedAST) { 113 | settings, ast, backend, index | 114 offsetsList = ast.filter(StructOffset).uniq.sort 115 sizesList = ast.filter(Sizeof).uniq.sort 116 length += OFFSET_HEADER_MAGIC_NUMBERS.size + (OFFSET_MAGIC_NUMBERS.size + 1) * (1 + offsetsList.size + sizesList.size) 117 } 118 outp.puts "static const unsigned extractorTable[#{length}] = {" 119 emitCodeInAllConfigurations(prunedAST) { 120 | settings, ast, backend, index | 121 OFFSET_HEADER_MAGIC_NUMBERS.each { 122 | number | 123 $output.puts "unsigned(#{number})," 124 } 125 126 offsetsList = ast.filter(StructOffset).uniq.sort 127 sizesList = ast.filter(Sizeof).uniq.sort 128 129 emitMagicNumber 130 outp.puts "#{index}," 131 offsetsList.each { 132 | offset | 133 emitMagicNumber 134 outp.puts "OFFLINE_ASM_OFFSETOF(#{offset.struct}, #{offset.field})," 135 } 136 sizesList.each { 137 | offset | 138 emitMagicNumber 139 outp.puts "sizeof(#{offset.struct})," 140 } 141 } 142 outp.puts "};" 143} 144 145$stderr.puts "offlineasm: offset extractor #{outputFlnm} successfully generated." 146 147