1# 2# Copyright (C) 2016 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17 18class ArcSummary(object): 19 """Summarizes an arc from a .gcno file. 20 21 Attributes: 22 src_block_index: integer index of the source basic block. 23 dstBlockIndex: integer index of the destination basic block. 24 on_tree: True iff arc has flag GCOV_ARC_ON_TREE. 25 fake: True iff arc has flag GCOV_ARC_FAKE. 26 fallthrough: True iff arc has flag GCOV_ARC_FALLTHROUGH. 27 resolved: True iff the arc's count has been resolved. 28 count: Integer number of times the arc was covered. 29 """ 30 31 GCOV_ARC_ON_TREE = 1 32 GCOV_ARC_FAKE = 1 << 1 33 GCOV_ARC_FALLTHROUGH = 1 << 2 34 35 def __init__(self, src_block, dst_block, flag): 36 """Inits the arc summary with provided values. 37 38 Stores the source and destination block indices and parses 39 the arc flag. 40 41 Args: 42 src_block: BlockSummary of source block. 43 dst_block: BlockSummary of destination block. 44 flag: integer flag for the given arc. 45 """ 46 47 self.src_block = src_block 48 self.dst_block = dst_block 49 self.on_tree = bool(flag & self.GCOV_ARC_ON_TREE) 50 self.fake = bool(flag & self.GCOV_ARC_FAKE) 51 self.fallthrough = bool(flag & self.GCOV_ARC_FALLTHROUGH) 52 self.resolved = False 53 self.count = 0 54 55 def Resolve(self): 56 """Resolves the arc count and returns True if successful. 57 58 Uses the property that the sum of counts of arcs entering a 59 node is equal to the sum of counts of arcs leaving a node. The 60 exception to this rule is fake non-fallthrough nodes, which have 61 no exit edges. In this case, remove the arc as an exit arc from 62 the source so that the source can be resolved. 63 64 Returns: 65 True if the arc could be resolved and False otherwise. 66 """ 67 if self.fake and not self.fallthrough: 68 try: 69 self.src_block.exit_arcs.remove(self) 70 except ValueError: 71 pass 72 elif (len(self.src_block.entry_arcs) > 0 and 73 all(a.resolved for a in self.src_block.entry_arcs) and 74 all(a.resolved for a in self.src_block.exit_arcs if a != self)): 75 in_flow = sum(a.count for a in self.src_block.entry_arcs) 76 out_flow = sum(a.count for a in self.src_block.exit_arcs 77 if a != self) 78 self.count = in_flow - out_flow 79 self.resolved = True 80 elif (len(self.dst_block.exit_arcs) > 0 and 81 all(a.resolved for a in self.dst_block.exit_arcs) and 82 all(a.resolved for a in self.dst_block.entry_arcs if a != self)): 83 out_flow = sum(a.count for a in self.dst_block.exit_arcs) 84 in_flow = sum(a.count for a in self.dst_block.entry_arcs 85 if a != self) 86 self.count = out_flow - in_flow 87 self.resolved = True 88 else: 89 return False 90 return True 91