@@ -2271,6 +2271,244 @@ def add_analyze_checks(
22712271 )
22722272
22732273
2274+ IR_FUNC_NAME_RE = re .compile (
2275+ r"^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[A-Za-z0-9_.]+)\s*\("
2276+ )
2277+ IR_PREFIX_DATA_RE = re .compile (r"^ *(;|$)" )
2278+ MIR_FUNC_NAME_RE = re .compile (r" *name: *(?P<func>[A-Za-z0-9_.-]+)" )
2279+ MIR_BODY_BEGIN_RE = re .compile (r" *body: *\|" )
2280+ MIR_BASIC_BLOCK_RE = re .compile (r" *bb\.[0-9]+.*:$" )
2281+ MIR_PREFIX_DATA_RE = re .compile (r"^ *(;|bb.[0-9].*: *$|[a-z]+:( |$)|$)" )
2282+
2283+
2284+ def find_mir_functions_with_one_bb (lines , verbose = False ):
2285+ result = []
2286+ cur_func = None
2287+ bbs = 0
2288+ for line in lines :
2289+ m = MIR_FUNC_NAME_RE .match (line )
2290+ if m :
2291+ if bbs == 1 :
2292+ result .append (cur_func )
2293+ cur_func = m .group ("func" )
2294+ bbs = 0
2295+ m = MIR_BASIC_BLOCK_RE .match (line )
2296+ if m :
2297+ bbs += 1
2298+ if bbs == 1 :
2299+ result .append (cur_func )
2300+ return result
2301+
2302+
2303+ def add_mir_checks_for_function (
2304+ test ,
2305+ output_lines ,
2306+ run_list ,
2307+ func_dict ,
2308+ func_name ,
2309+ single_bb ,
2310+ print_fixed_stack ,
2311+ first_check_is_next ,
2312+ at_the_function_name ,
2313+ ):
2314+ printed_prefixes = set ()
2315+ for run in run_list :
2316+ for prefix in run [0 ]:
2317+ if prefix in printed_prefixes :
2318+ break
2319+ if not func_dict [prefix ][func_name ]:
2320+ continue
2321+ if printed_prefixes :
2322+ # Add some space between different check prefixes.
2323+ indent = len (output_lines [- 1 ]) - len (output_lines [- 1 ].lstrip (" " ))
2324+ output_lines .append (" " * indent + ";" )
2325+ printed_prefixes .add (prefix )
2326+ add_mir_check_lines (
2327+ test ,
2328+ output_lines ,
2329+ prefix ,
2330+ ("@" if at_the_function_name else "" ) + func_name ,
2331+ single_bb ,
2332+ func_dict [prefix ][func_name ],
2333+ print_fixed_stack ,
2334+ first_check_is_next ,
2335+ )
2336+ break
2337+ else :
2338+ warn (
2339+ "Found conflicting asm for function: {}" .format (func_name ),
2340+ test_file = test ,
2341+ )
2342+ return output_lines
2343+
2344+
2345+ def add_mir_check_lines (
2346+ test ,
2347+ output_lines ,
2348+ prefix ,
2349+ func_name ,
2350+ single_bb ,
2351+ func_info ,
2352+ print_fixed_stack ,
2353+ first_check_is_next ,
2354+ ):
2355+ func_body = str (func_info ).splitlines ()
2356+ if single_bb :
2357+ # Don't bother checking the basic block label for a single BB
2358+ func_body .pop (0 )
2359+
2360+ if not func_body :
2361+ warn (
2362+ "Function has no instructions to check: {}" .format (func_name ),
2363+ test_file = test ,
2364+ )
2365+ return
2366+
2367+ first_line = func_body [0 ]
2368+ indent = len (first_line ) - len (first_line .lstrip (" " ))
2369+ # A check comment, indented the appropriate amount
2370+ check = "{:>{}}; {}" .format ("" , indent , prefix )
2371+
2372+ output_lines .append ("{}-LABEL: name: {}" .format (check , func_name ))
2373+
2374+ if print_fixed_stack :
2375+ output_lines .append ("{}: fixedStack:" .format (check ))
2376+ for stack_line in func_info .extrascrub .splitlines ():
2377+ filecheck_directive = check + "-NEXT"
2378+ output_lines .append ("{}: {}" .format (filecheck_directive , stack_line ))
2379+
2380+ first_check = not first_check_is_next
2381+ for func_line in func_body :
2382+ if not func_line .strip ():
2383+ # The mir printer prints leading whitespace so we can't use CHECK-EMPTY:
2384+ output_lines .append (check + "-NEXT: {{" + func_line + "$}}" )
2385+ continue
2386+ filecheck_directive = check if first_check else check + "-NEXT"
2387+ first_check = False
2388+ check_line = "{}: {}" .format (filecheck_directive , func_line [indent :]).rstrip ()
2389+ output_lines .append (check_line )
2390+
2391+
2392+ def should_add_mir_line_to_output (input_line , prefix_set ):
2393+ # Skip any check lines that we're handling as well as comments
2394+ m = CHECK_RE .match (input_line )
2395+ if (m and m .group (1 ) in prefix_set ) or input_line .strip () == ";" :
2396+ return False
2397+ return True
2398+
2399+
2400+ def add_mir_checks (
2401+ input_lines ,
2402+ prefix_set ,
2403+ autogenerated_note ,
2404+ test ,
2405+ run_list ,
2406+ func_dict ,
2407+ print_fixed_stack ,
2408+ first_check_is_next ,
2409+ at_the_function_name ,
2410+ ):
2411+ simple_functions = find_mir_functions_with_one_bb (input_lines )
2412+
2413+ output_lines = []
2414+ output_lines .append (autogenerated_note )
2415+
2416+ func_name = None
2417+ state = "toplevel"
2418+ for input_line in input_lines :
2419+ if input_line == autogenerated_note :
2420+ continue
2421+
2422+ if state == "toplevel" :
2423+ m = IR_FUNC_NAME_RE .match (input_line )
2424+ if m :
2425+ state = "ir function prefix"
2426+ func_name = m .group ("func" )
2427+ if input_line .rstrip ("| \r \n " ) == "---" :
2428+ state = "document"
2429+ output_lines .append (input_line )
2430+ elif state == "document" :
2431+ m = MIR_FUNC_NAME_RE .match (input_line )
2432+ if m :
2433+ state = "mir function metadata"
2434+ func_name = m .group ("func" )
2435+ if input_line .strip () == "..." :
2436+ state = "toplevel"
2437+ func_name = None
2438+ if should_add_mir_line_to_output (input_line , prefix_set ):
2439+ output_lines .append (input_line )
2440+ elif state == "mir function metadata" :
2441+ if should_add_mir_line_to_output (input_line , prefix_set ):
2442+ output_lines .append (input_line )
2443+ m = MIR_BODY_BEGIN_RE .match (input_line )
2444+ if m :
2445+ if func_name in simple_functions :
2446+ # If there's only one block, put the checks inside it
2447+ state = "mir function prefix"
2448+ continue
2449+ state = "mir function body"
2450+ add_mir_checks_for_function (
2451+ test ,
2452+ output_lines ,
2453+ run_list ,
2454+ func_dict ,
2455+ func_name ,
2456+ single_bb = False ,
2457+ print_fixed_stack = print_fixed_stack ,
2458+ first_check_is_next = first_check_is_next ,
2459+ at_the_function_name = at_the_function_name ,
2460+ )
2461+ elif state == "mir function prefix" :
2462+ m = MIR_PREFIX_DATA_RE .match (input_line )
2463+ if not m :
2464+ state = "mir function body"
2465+ add_mir_checks_for_function (
2466+ test ,
2467+ output_lines ,
2468+ run_list ,
2469+ func_dict ,
2470+ func_name ,
2471+ single_bb = True ,
2472+ print_fixed_stack = print_fixed_stack ,
2473+ first_check_is_next = first_check_is_next ,
2474+ at_the_function_name = at_the_function_name ,
2475+ )
2476+
2477+ if should_add_mir_line_to_output (input_line , prefix_set ):
2478+ output_lines .append (input_line )
2479+ elif state == "mir function body" :
2480+ if input_line .strip () == "..." :
2481+ state = "toplevel"
2482+ func_name = None
2483+ if should_add_mir_line_to_output (input_line , prefix_set ):
2484+ output_lines .append (input_line )
2485+ elif state == "ir function prefix" :
2486+ m = IR_PREFIX_DATA_RE .match (input_line )
2487+ if not m :
2488+ state = "ir function body"
2489+ add_mir_checks_for_function (
2490+ test ,
2491+ output_lines ,
2492+ run_list ,
2493+ func_dict ,
2494+ func_name ,
2495+ single_bb = False ,
2496+ print_fixed_stack = print_fixed_stack ,
2497+ first_check_is_next = first_check_is_next ,
2498+ at_the_function_name = at_the_function_name ,
2499+ )
2500+
2501+ if should_add_mir_line_to_output (input_line , prefix_set ):
2502+ output_lines .append (input_line )
2503+ elif state == "ir function body" :
2504+ if input_line .strip () == "}" :
2505+ state = "toplevel"
2506+ func_name = None
2507+ if should_add_mir_line_to_output (input_line , prefix_set ):
2508+ output_lines .append (input_line )
2509+ return output_lines
2510+
2511+
22742512def build_global_values_dictionary (glob_val_dict , raw_tool_output , prefixes , ginfo ):
22752513 for nameless_value in ginfo .get_nameless_values ():
22762514 if nameless_value .global_ir_rhs_regexp is None :
0 commit comments