]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
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 | ||
93a37866 | 28 | require "config" |
6fe7ccc8 A |
29 | require "backends" |
30 | require "digest/sha1" | |
31 | require "offsets" | |
32 | require "parser" | |
33 | require "self_hash" | |
34 | require "settings" | |
35 | require "transform" | |
36 | ||
37 | inputFlnm = ARGV.shift | |
38 | outputFlnm = ARGV.shift | |
39 | ||
40 | $stderr.puts "offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}." | |
41 | ||
42 | def emitMagicNumber | |
43 | OFFSET_MAGIC_NUMBERS.each { | |
44 | | number | | |
93a37866 | 45 | $output.puts "unsigned(#{number})," |
6fe7ccc8 A |
46 | } |
47 | end | |
48 | ||
49 | inputHash = "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}" | |
50 | ||
51 | if 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 | } | |
60 | end | |
61 | ||
62 | originalAST = 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 | ||
70 | class 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 | |
83 | end | |
84 | ||
85 | class IfThenElse | |
86 | def offsetsPruneTo(sequence) | |
87 | ifThenElse = IfThenElse.new(codeOrigin, predicate, thenCase.offsetsPrune) | |
88 | ifThenElse.elseCase = elseCase.offsetsPrune | |
89 | sequence.list << ifThenElse | |
90 | end | |
91 | end | |
92 | ||
93 | class StructOffset | |
94 | def offsetsPruneTo(sequence) | |
95 | sequence.list << self | |
96 | end | |
97 | end | |
98 | ||
99 | class Sizeof | |
100 | def offsetsPruneTo(sequence) | |
101 | sequence.list << self | |
102 | end | |
103 | end | |
104 | ||
105 | prunedAST = originalAST.offsetsPrune | |
106 | ||
107 | File.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 | | |
93a37866 | 123 | $output.puts "unsigned(#{number})," |
6fe7ccc8 A |
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 |