Home | History | Annotate | Download | only in c1visualizer
      1 # Copyright (C) 2014 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #   http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 from common.logger                   import Logger
     16 from file_format.common              import SplitStream
     17 from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
     18 
     19 import re
     20 
     21 class C1ParserState:
     22   OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
     23 
     24   def __init__(self):
     25     self.currentState = C1ParserState.OutsideBlock
     26     self.lastMethodName = None
     27 
     28 def __parseC1Line(line, lineNo, state, fileName):
     29   """ This function is invoked on each line of the output file and returns
     30       a triplet which instructs the parser how the line should be handled. If the
     31       line is to be included in the current group, it is returned in the first
     32       value. If the line starts a new output group, the name of the group is
     33       returned in the second value. The third value is only here to make the
     34       function prototype compatible with `SplitStream` and is always set to
     35       `None` here.
     36   """
     37   if state.currentState == C1ParserState.StartingCfgBlock:
     38     # Previous line started a new 'cfg' block which means that this one must
     39     # contain the name of the pass (this is enforced by C1visualizer).
     40     if re.match("name\s+\"[^\"]+\"", line):
     41       # Extract the pass name, prepend it with the name of the method and
     42       # return as the beginning of a new group.
     43       state.currentState = C1ParserState.InsideCfgBlock
     44       return (None, state.lastMethodName + " " + line.split("\"")[1], None)
     45     else:
     46       Logger.fail("Expected output group name", fileName, lineNo)
     47 
     48   elif state.currentState == C1ParserState.InsideCfgBlock:
     49     if line == "end_cfg":
     50       state.currentState = C1ParserState.OutsideBlock
     51       return (None, None, None)
     52     else:
     53       return (line, None, None)
     54 
     55   elif state.currentState == C1ParserState.InsideCompilationBlock:
     56     # Search for the method's name. Format: method "<name>"
     57     if re.match("method\s+\"[^\"]*\"", line):
     58       methodName = line.split("\"")[1].strip()
     59       if not methodName:
     60         Logger.fail("Empty method name in output", fileName, lineNo)
     61       state.lastMethodName = methodName
     62     elif line == "end_compilation":
     63       state.currentState = C1ParserState.OutsideBlock
     64     return (None, None, None)
     65 
     66   else:
     67     assert state.currentState == C1ParserState.OutsideBlock
     68     if line == "begin_cfg":
     69       # The line starts a new group but we'll wait until the next line from
     70       # which we can extract the name of the pass.
     71       if state.lastMethodName is None:
     72         Logger.fail("Expected method header", fileName, lineNo)
     73       state.currentState = C1ParserState.StartingCfgBlock
     74       return (None, None, None)
     75     elif line == "begin_compilation":
     76       state.currentState = C1ParserState.InsideCompilationBlock
     77       return (None, None, None)
     78     else:
     79       Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
     80 
     81 def ParseC1visualizerStream(fileName, stream):
     82   c1File = C1visualizerFile(fileName)
     83   state = C1ParserState()
     84   fnProcessLine = lambda line, lineNo: __parseC1Line(line, lineNo, state, fileName)
     85   fnLineOutsideChunk = lambda line, lineNo: \
     86       Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
     87   for passName, passLines, startLineNo, testArch in \
     88       SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
     89     C1visualizerPass(c1File, passName, passLines, startLineNo + 1)
     90   return c1File
     91