3 # Copyright (C) 2011 Apple Inc. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
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.
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.
26 $
: << File
.dirname(__FILE__
)
37 IncludeFile
.processIncludeOptions()
39 inputFlnm
= ARGV.shift
40 outputFlnm
= ARGV.shift
42 validBackends
= ARGV.shift
44 $stderr.puts
"Only dealing with backends: #{validBackends}"
45 includeOnlyBackends(validBackends
.split(","))
48 $stderr.puts
"offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}."
51 OFFSET_MAGIC_NUMBERS
.each
{
53 $output.puts
"unsigned(#{number}),"
57 inputHash
= "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}"
59 if FileTest
.exist
? outputFlnm
60 File
.open(outputFlnm
, "r") {
63 if firstLine
and firstLine
.chomp
== inputHash
64 $stderr.puts
"offlineasm: Nothing changed."
70 originalAST
= parse(inputFlnm
)
73 # Optimize the AST to make configuration extraction faster. This reduces the AST to a form
74 # that only contains the things that matter for our purposes: offsets, sizes, and if
79 def offsetsPruneTo(sequence
)
82 child
.offsetsPruneTo(sequence
)
87 result
= Sequence
.new(codeOrigin
, [])
88 offsetsPruneTo(result
)
94 def offsetsPruneTo(sequence
)
95 ifThenElse
= IfThenElse
.new(codeOrigin
, predicate
, thenCase
.offsetsPrune
)
96 ifThenElse
.elseCase
= elseCase
.offsetsPrune
97 sequence
.list
<< ifThenElse
102 def offsetsPruneTo(sequence
)
103 sequence
.list
<< self
108 def offsetsPruneTo(sequence
)
109 sequence
.list
<< self
113 prunedAST
= originalAST
.offsetsPrune
115 File
.open(outputFlnm
, "w") {
120 emitCodeInAllConfigurations(prunedAST
) {
121 | settings
, ast
, backend
, index
|
122 offsetsList
= ast
.filter(StructOffset
).uniq
.sort
123 sizesList
= ast
.filter(Sizeof
).uniq
.sort
124 length +
= OFFSET_HEADER_MAGIC_NUMBERS
.size +
(OFFSET_MAGIC_NUMBERS
.size +
1) * (1 + offsetsList
.size + sizesList
.size
)
126 outp
.puts
"static const unsigned extractorTable[#{length}] = {"
127 emitCodeInAllConfigurations(prunedAST
) {
128 | settings
, ast
, backend
, index
|
129 OFFSET_HEADER_MAGIC_NUMBERS
.each
{
131 $output.puts
"unsigned(#{number}),"
134 offsetsList
= ast
.filter(StructOffset
).uniq
.sort
135 sizesList
= ast
.filter(Sizeof
).uniq
.sort
138 outp
.puts
"#{index},"
142 outp
.puts
"OFFLINE_ASM_OFFSETOF(#{offset.struct}, #{offset.field}),"
147 outp
.puts
"sizeof(#{offset.struct}),"
153 $stderr.puts
"offlineasm: offset extractor #{outputFlnm} successfully generated."