]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - offlineasm/asm.rb
JavaScriptCore-7600.1.4.13.1.tar.gz
[apple/javascriptcore.git] / offlineasm / asm.rb
index 12bade022b26cdc8e98acf44beb16cc9b12d5a3c..88c7d7abb6d97a594634da5352f9d0d236f85561 100644 (file)
@@ -25,6 +25,7 @@
 
 $: << File.dirname(__FILE__)
 
+require "config"
 require "backends"
 require "digest/sha1"
 require "offsets"
@@ -39,16 +40,25 @@ class Assembler
         @state = :cpp
         @commentState = :none
         @comment = nil
+        @internalComment = nil
+        @annotation = nil
+        @codeOrigin = nil
+        @numLocalLabels = 0
+        @numGlobalLabels = 0
+
+        @newlineSpacerState = :none
+        @lastlabel = ""
     end
-    
+
     def enterAsm
-        @outp.puts "asm ("
+        @outp.puts "OFFLINE_ASM_BEGIN" if !$emitWinAsm
         @state = :asm
     end
     
     def leaveAsm
+        putsProcEndIfNeeded if $emitWinAsm
         putsLastComment
-        @outp.puts ");"
+        @outp.puts "OFFLINE_ASM_END" if !$emitWinAsm
         @state = :cpp
     end
     
@@ -58,17 +68,68 @@ class Assembler
         leaveAsm
     end
     
+    # Concatenates all the various components of the comment to dump.
     def lastComment
-        if @comment
-            result = "// #{@comment}"
-        else
-            result = ""
+        separator = " "
+        result = ""
+        result = "#{@comment}" if @comment
+        if @annotation and $enableInstrAnnotations
+            result += separator if result != ""
+            result += "#{@annotation}"
         end
+        if @internalComment
+            result += separator if result != ""
+            result += "#{@internalComment}"
+        end
+        if @codeOrigin and $enableCodeOriginComments
+            result += separator if result != ""
+            result += "#{@codeOrigin}"
+        end
+        if result != ""
+            result = $commentPrefix + " " + result
+        end
+
+        # Reset all the components that we've just sent to be dumped.
         @commentState = :none
         @comment = nil
+        @annotation = nil
+        @codeOrigin = nil
+        @internalComment = nil
         result
     end
     
+    # Puts a C Statement in the output stream.
+    def putc(*line)
+        raise unless @state == :asm
+        @outp.puts(formatDump("    " + line.join(''), lastComment))
+    end
+    
+    def formatDump(dumpStr, comment, commentColumns=$preferredCommentStartColumn)
+        if comment.length > 0
+            "%-#{commentColumns}s %s" % [dumpStr, comment]
+        else
+            dumpStr
+        end
+    end
+
+    # private method for internal use only.
+    def putAnnotation(text)
+        raise unless @state == :asm
+        if $enableInstrAnnotations
+            @outp.puts text
+            @annotation = nil
+        end
+    end
+
+    def putLocalAnnotation()
+        putAnnotation "    // #{@annotation}" if @annotation
+    end
+
+    def putGlobalAnnotation()
+        putsNewlineSpacerIfAppropriate(:annotation)
+        putAnnotation "// #{@annotation}" if @annotation
+    end
+
     def putsLastComment
         comment = lastComment
         unless comment.empty?
@@ -78,7 +139,11 @@ class Assembler
     
     def puts(*line)
         raise unless @state == :asm
-        @outp.puts("\"\\t" + line.join('') + "\\n\" #{lastComment}")
+        if !$emitWinAsm
+            @outp.puts(formatDump("    \"\\t" + line.join('') + "\\n\"", lastComment))
+        else
+            @outp.puts(formatDump("    " + line.join(''), lastComment))
+        end
     end
     
     def print(line)
@@ -86,42 +151,133 @@ class Assembler
         @outp.print("\"" + line + "\"")
     end
     
-    def putsLabel(labelName)
+    def putsNewlineSpacerIfAppropriate(state)
+        if @newlineSpacerState != state
+            @outp.puts("\n")
+            @newlineSpacerState = state
+        end
+    end
+
+    def putsProc(label, comment)
+        raise unless $emitWinAsm
+        @outp.puts(formatDump("#{label} PROC PUBLIC", comment))
+        @lastlabel = label
+    end
+
+    def putsProcEndIfNeeded
+        raise unless $emitWinAsm
+        if @lastlabel != ""
+            @outp.puts("#{@lastlabel} ENDP")
+        end
+        @lastlabel = ""
+    end
+
+    def putsLabel(labelName, isGlobal)
         raise unless @state == :asm
-        @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName}) #{lastComment}")
+        @numGlobalLabels += 1
+        putsProcEndIfNeeded if $emitWinAsm and isGlobal
+        putsNewlineSpacerIfAppropriate(:global)
+        @internalComment = $enableLabelCountComments ? "Global Label #{@numGlobalLabels}" : nil
+        if isGlobal
+            if !$emitWinAsm
+                @outp.puts(formatDump("OFFLINE_ASM_GLOBAL_LABEL(#{labelName})", lastComment))
+            else
+                putsProc(labelName, lastComment)
+            end            
+        elsif /\Allint_op_/.match(labelName)
+            if !$emitWinAsm
+                @outp.puts(formatDump("OFFLINE_ASM_OPCODE_LABEL(op_#{$~.post_match})", lastComment))
+            else
+                label = "llint_" + "op_#{$~.post_match}"
+                @outp.puts(formatDump("  _#{label}:", lastComment))
+            end            
+        else
+            if !$emitWinAsm
+                @outp.puts(formatDump("OFFLINE_ASM_GLUE_LABEL(#{labelName})", lastComment))
+            else
+                @outp.puts(formatDump("  _#{labelName}:", lastComment))
+            end
+        end
+        @newlineSpacerState = :none # After a global label, we can use another spacer.
     end
     
     def putsLocalLabel(labelName)
         raise unless @state == :asm
-        @outp.puts("LOCAL_LABEL_STRING(#{labelName}) \":\\n\" #{lastComment}")
+        @numLocalLabels += 1
+        @outp.puts("\n")
+        @internalComment = $enableLabelCountComments ? "Local Label #{@numLocalLabels}" : nil
+        if !$emitWinAsm
+            @outp.puts(formatDump("  OFFLINE_ASM_LOCAL_LABEL(#{labelName})", lastComment))
+        else
+            @outp.puts(formatDump("  #{labelName}:", lastComment))
+        end
     end
-    
+
+    def self.externLabelReference(labelName)
+        if !$emitWinAsm
+            "\" LOCAL_REFERENCE(#{labelName}) \""
+        else
+            "#{labelName}"
+        end
+    end
+
     def self.labelReference(labelName)
-        "\" SYMBOL_STRING(#{labelName}) \""
+        if !$emitWinAsm
+            "\" LOCAL_LABEL_STRING(#{labelName}) \""
+        else
+            "_#{labelName}"
+        end
     end
     
     def self.localLabelReference(labelName)
-        "\" LOCAL_LABEL_STRING(#{labelName}) \""
+        if !$emitWinAsm
+            "\" LOCAL_LABEL_STRING(#{labelName}) \""
+        else
+            "#{labelName}"
+        end
     end
     
-    def comment(text)
+    def self.cLabelReference(labelName)
+        if /\Allint_op_/.match(labelName)
+            "op_#{$~.post_match}"  # strip opcodes of their llint_ prefix.
+        else
+            "#{labelName}"
+        end
+    end
+    
+    def self.cLocalLabelReference(labelName)
+        "#{labelName}"
+    end
+    
+    def codeOrigin(text)
         case @commentState
         when :none
-            @comment = text
+            @codeOrigin = text
             @commentState = :one
         when :one
-            @outp.puts "// #{@comment}"
-            @outp.puts "// #{text}"
-            @comment = nil
+            if $enableCodeOriginComments
+                @outp.puts "    " + $commentPrefix + " #{@codeOrigin}"
+                @outp.puts "    " + $commentPrefix + " #{text}"
+            end
+            @codeOrigin = nil
             @commentState = :many
         when :many
-            @outp.puts "// #{text}"
+            @outp.puts $commentPrefix + " #{text}" if $enableCodeOriginComments
         else
             raise
         end
     end
+
+    def comment(text)
+        @comment = text
+    end
+    def annotation(text)
+        @annotation = text
+    end
 end
 
+IncludeFile.processIncludeOptions()
+
 asmFile = ARGV.shift
 offsetsFile = ARGV.shift
 outputFlnm = ARGV.shift
@@ -131,12 +287,15 @@ $stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating ass
 begin
     configurationList = offsetsAndConfigurationIndex(offsetsFile)
 rescue MissingMagicValuesException
-    $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation assuming the classic interpreter is enabled."
+    $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation."
     exit 0
 end
 
+$emitWinAsm = isMSVC ? outputFlnm.index(".asm") != nil : false
+$commentPrefix = $emitWinAsm ? ";" : "//"
+
 inputHash =
-    "// offlineasm input hash: " + parseHash(asmFile) +
+    $commentPrefix + " offlineasm input hash: " + parseHash(asmFile) +
     " " + Digest::SHA1.hexdigest(configurationList.map{|v| (v[0] + [v[1]]).join(' ')}.join(' ')) +
     " " + selfHash
 
@@ -155,11 +314,11 @@ File.open(outputFlnm, "w") {
     | outp |
     $output = outp
     $output.puts inputHash
-    
+
     $asm = Assembler.new($output)
     
     ast = parse(asmFile)
-    
+
     configurationList.each {
         | configuration |
         offsetsList = configuration[0]