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__
)
43 @internalComment = nil
49 @newlineSpacerState = :none
53 @outp.puts
"OFFLINE_ASM_BEGIN"
59 @outp.puts
"OFFLINE_ASM_END"
69 # Concatenates all the various components of the comment to dump.
73 result
= "#{@comment}" if @comment
74 if @annotation and $enableInstrAnnotations
75 result +
= separator
if result !
= ""
76 result +
= "#{@annotation}"
79 result +
= separator
if result !
= ""
80 result +
= "#{@internalComment}"
82 if @codeOrigin and $enableCodeOriginComments
83 result +
= separator
if result !
= ""
84 result +
= "#{@codeOrigin}"
87 result
= "// " + result
90 # Reset all the components that we've just sent to be dumped.
95 @internalComment = nil
99 # Puts a C Statement in the output stream.
101 raise unless @state == :asm
102 @outp.puts(formatDump(" " + line
.join(''), lastComment
))
105 def formatDump(dumpStr
, comment
, commentColumns
=$preferredCommentStartColumn)
106 if comment
.length
> 0
107 "%-#{commentColumns}s %s" % [dumpStr
, comment
]
113 # private method for internal use only.
114 def putAnnotation(text
)
115 raise unless @state == :asm
116 if $enableInstrAnnotations
122 def putLocalAnnotation()
123 putAnnotation
" // #{@annotation}" if @annotation
126 def putGlobalAnnotation()
127 putsNewlineSpacerIfAppropriate(:annotation)
128 putAnnotation
"// #{@annotation}" if @annotation
132 comment
= lastComment
133 unless comment
.empty
?
139 raise unless @state == :asm
140 @outp.puts(formatDump(" \"\\t" + line
.join('') +
"\\n\"", lastComment
))
144 raise unless @state == :asm
145 @outp.print("\"" + line +
"\"")
148 def putsNewlineSpacerIfAppropriate(state
)
149 if @newlineSpacerState !
= state
151 @newlineSpacerState = state
155 def putsLabel(labelName
)
156 raise unless @state == :asm
157 @numGlobalLabels +
= 1
158 putsNewlineSpacerIfAppropriate(:global)
159 @internalComment = $enableLabelCountComments ? "Global Label #{@numGlobalLabels}" : nil
160 if /\Allint_op_/.match(labelName
)
161 @outp.puts(formatDump("OFFLINE_ASM_OPCODE_LABEL(op_#{$~.post_match})", lastComment
))
163 @outp.puts(formatDump("OFFLINE_ASM_GLUE_LABEL(#{labelName})", lastComment
))
165 @newlineSpacerState = :none # After a global label, we can use another spacer.
168 def putsLocalLabel(labelName
)
169 raise unless @state == :asm
172 @internalComment = $enableLabelCountComments ? "Local Label #{@numLocalLabels}" : nil
173 @outp.puts(formatDump(" OFFLINE_ASM_LOCAL_LABEL(#{labelName})", lastComment
))
176 def self.labelReference(labelName
)
177 "\" LOCAL_REFERENCE(#{labelName}) \""
180 def self.localLabelReference(labelName
)
181 "\" LOCAL_LABEL_STRING(#{labelName}) \""
184 def self.cLabelReference(labelName
)
185 if /\Allint_op_/.match(labelName
)
186 "op_#{$~.post_match}" # strip opcodes of their llint_ prefix.
192 def self.cLocalLabelReference(labelName
)
202 if $enableCodeOriginComments
203 @outp.puts
" // #{@codeOrigin}"
204 @outp.puts
" // #{text}"
207 @commentState = :many
209 @outp.puts
"// #{text}" if $enableCodeOriginComments
224 offsetsFile
= ARGV.shift
225 outputFlnm
= ARGV.shift
227 $stderr.puts
"offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}."
230 configurationList
= offsetsAndConfigurationIndex(offsetsFile
)
231 rescue MissingMagicValuesException
232 $stderr.puts
"offlineasm: No magic values found. Skipping assembly file generation."
237 "// offlineasm input hash: " +
parseHash(asmFile
) +
238 " " + Digest
::SHA1.hexdigest(configurationList
.map
{|v
| (v
[0] +
[v
[1]]).join(' ')}.join(' ')) +
241 if FileTest
.exist
? outputFlnm
242 File
.open(outputFlnm
, "r") {
245 if firstLine
and firstLine
.chomp
== inputHash
246 $stderr.puts
"offlineasm: Nothing changed."
252 File
.open(outputFlnm
, "w") {
255 $output.puts inputHash
257 $asm = Assembler
.new($output)
261 configurationList
.each
{
263 offsetsList
= configuration
[0]
264 configIndex
= configuration
[1]
265 forSettings(computeSettingsCombinations(ast
)[configIndex
], ast
) {
266 | concreteSettings
, lowLevelAST
, backend
|
267 lowLevelAST
= lowLevelAST
.resolve(*buildOffsetsMap(lowLevelAST
, offsetsList
))
269 emitCodeInConfiguration(concreteSettings
, lowLevelAST
, backend
) {
271 lowLevelAST
.lower(backend
)
278 $stderr.puts
"offlineasm: Assembly file #{outputFlnm} successfully generated."