@@ -2271,6 +2271,244 @@ def add_analyze_checks(
2271
2271
)
2272
2272
2273
2273
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
+
2274
2512
def build_global_values_dictionary (glob_val_dict , raw_tool_output , prefixes , ginfo ):
2275
2513
for nameless_value in ginfo .get_nameless_values ():
2276
2514
if nameless_value .global_ir_rhs_regexp is None :
0 commit comments