1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 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""" 17A tool to check atomic memory order format. 18""" 19 20import re 21import sys 22 23if len(sys.argv) < 2: 24 sys.exit("File name to be checked was not specified") 25FILE = sys.argv[1] 26 27MAX_OFFSET = 3 28EMPTY_MEMORY_ORDER = "empty" 29PARAMETERIZED_MEMORY_ORDER = "parameterized" 30IGNORED_PREFIXES = ["ATOMIC_STORE", "ATOMIC_LOAD", "ATOMIC_FETCH_ADD", 31 "ATOMIC_FETCH_SUB", "ATOMIC_CAS_WEAK"] 32 33 34def obtain_memory_order(parsed_line: str) -> []: 35 memory_orders = list() 36 while True: 37 parsed_res = re.search(r"memory_order_(\w+)", parsed_line) 38 if parsed_res: 39 memory_order = parsed_res.group(1) 40 memory_orders.append(memory_order) 41 parsed_line = parsed_line.replace(memory_order, "", 1) 42 else: 43 break 44 return memory_orders 45 46 47def parse_file() -> (): 48 atomic_comments = dict() 49 atomic_operations = dict() 50 cur_parser_label = 0 51 with open(FILE) as parsed_file: 52 for index, line in enumerate(parsed_file.readlines(), 1): 53 res = re.search(r"// Atomic with (\w+) order reason: (.+)", line) 54 if res: 55 memory_order = res.group(1) 56 atomic_comments[index] = memory_order 57 58 # TODO: Support compare_exchange_strong|compare_exchange_weak 59 res = re.search(r"(.*)(\.|->)(store|load|fetch_add|fetch_sub|" 60 r"fetch_or|fetch_xor|fetch_and)\((.+)", line) 61 if res: 62 prefix = res.group(1) 63 is_ignored = False 64 for ignored_prefix in IGNORED_PREFIXES: 65 if ignored_prefix in prefix: 66 is_ignored = True 67 continue 68 if is_ignored: 69 continue 70 if cur_parser_label: 71 atomic_operations[cur_parser_label] = [EMPTY_MEMORY_ORDER] 72 cur_parser_label = 0 73 rest_str = res.group(4) 74 memory_order = obtain_memory_order(rest_str) 75 if memory_order: 76 atomic_operations[index] = memory_order 77 else: 78 cur_parser_label = index 79 else: 80 if cur_parser_label: 81 memory_order = obtain_memory_order(line) 82 if memory_order: 83 atomic_operations[cur_parser_label] = memory_order 84 cur_parser_label = 0 85 else: 86 if index - cur_parser_label >= MAX_OFFSET: 87 atomic_operations[cur_parser_label] = \ 88 [EMPTY_MEMORY_ORDER] 89 cur_parser_label = 0 90 if cur_parser_label: 91 atomic_operations[cur_parser_label] = [EMPTY_MEMORY_ORDER] 92 return atomic_comments, atomic_operations 93 94 95def process_results(atomic_comments: dict, atomic_operations: dict) -> int: 96 exit_code = 0 97 for index, memory_orders in atomic_operations.items(): 98 for memory_order in memory_orders: 99 is_commented = False 100 for i in reversed(range(index - MAX_OFFSET, index)): 101 commented_memory_order = atomic_comments.get(i) 102 if memory_order == commented_memory_order or \ 103 memory_order == EMPTY_MEMORY_ORDER and \ 104 commented_memory_order == PARAMETERIZED_MEMORY_ORDER: 105 is_commented = True 106 if commented_memory_order == PARAMETERIZED_MEMORY_ORDER: 107 memory_order = PARAMETERIZED_MEMORY_ORDER 108 break 109 if not is_commented: 110 print("File {}:{}: reason for specific memory order was not " 111 "specified for atomic operation".format(FILE, index)) 112 exit_code = 1 113 else: 114 if memory_order == EMPTY_MEMORY_ORDER: 115 print("File {}:{}: memory order was not specified for " 116 "atomic operation".format(FILE, index)) 117 exit_code = 1 118 return exit_code 119 120 121if __name__ == "__main__": 122 COMMENTS, OPERATIONS = parse_file() 123 sys.exit(process_results(COMMENTS, OPERATIONS)) 124