Home | History | Annotate | Download | only in testgen
      1 
      2 #!/usr/bin/python
      3 
      4 # Auto-generates an exhaustive and repetitive test for correct bundle-locked
      5 # alignment on x86.
      6 # For every possible offset in an aligned bundle, a bundle-locked group of every
      7 # size in the inclusive range [1, bundle_size] is inserted. An appropriate CHECK
      8 # is added to verify that NOP padding occurred (or did not occur) as expected.
      9 # Run with --align-to-end to generate a similar test with align_to_end for each
     10 # .bundle_lock directive.
     11 
     12 # This script runs with Python 2.7 and 3.2+
     13 
     14 from __future__ import print_function
     15 import argparse
     16 
     17 BUNDLE_SIZE_POW2 = 4
     18 BUNDLE_SIZE = 2 ** BUNDLE_SIZE_POW2
     19 
     20 PREAMBLE = '''
     21 # RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \\
     22 # RUN:   | llvm-objdump -triple i386 -disassemble -no-show-raw-insn - | FileCheck %s
     23 
     24 # !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!!
     25 #     It tests that bundle-aligned grouping works correctly in MC. Read the
     26 #     source of the script for more details.
     27 
     28   .text
     29   .bundle_align_mode {0}
     30 '''.format(BUNDLE_SIZE_POW2).lstrip()
     31 
     32 ALIGNTO = '  .align {0}, 0x90'
     33 NOPFILL = '  .fill {0}, 1, 0x90'
     34 
     35 def print_bundle_locked_sequence(len, align_to_end=False):
     36   print('  .bundle_lock{0}'.format(' align_to_end' if align_to_end else ''))
     37   print('  .rept {0}'.format(len))
     38   print('  inc %eax')
     39   print('  .endr')
     40   print('  .bundle_unlock')
     41 
     42 def generate(align_to_end=False):
     43   print(PREAMBLE)
     44 
     45   ntest = 0
     46   for instlen in range(1, BUNDLE_SIZE + 1):
     47     for offset in range(0, BUNDLE_SIZE):
     48       # Spread out all the instructions to not worry about cross-bundle
     49       # interference.
     50       print(ALIGNTO.format(2 * BUNDLE_SIZE))
     51       print('INSTRLEN_{0}_OFFSET_{1}:'.format(instlen, offset))
     52       if offset > 0:
     53         print(NOPFILL.format(offset))
     54       print_bundle_locked_sequence(instlen, align_to_end)
     55 
     56       # Now generate an appropriate CHECK line
     57       base_offset = ntest * 2 * BUNDLE_SIZE
     58       inst_orig_offset = base_offset + offset  # had it not been padded...
     59 
     60       def print_check(adjusted_offset=None, nop_split_offset=None):
     61         if adjusted_offset is not None:
     62           print('# CHECK: {0:x}: nop'.format(inst_orig_offset))
     63           if nop_split_offset is not None:
     64             print('# CHECK: {0:x}: nop'.format(nop_split_offset))
     65           print('# CHECK: {0:x}: incl'.format(adjusted_offset))
     66         else:
     67           print('# CHECK: {0:x}: incl'.format(inst_orig_offset))
     68 
     69       if align_to_end:
     70         if offset + instlen == BUNDLE_SIZE:
     71           # No padding needed
     72           print_check()
     73         elif offset + instlen < BUNDLE_SIZE:
     74           # Pad to end at nearest bundle boundary
     75           offset_to_end = base_offset + (BUNDLE_SIZE - instlen)
     76           print_check(offset_to_end)
     77         else: # offset + instlen > BUNDLE_SIZE
     78           # Pad to end at next bundle boundary, splitting the nop sequence
     79           # at the nearest bundle boundary
     80           offset_to_nearest_bundle = base_offset + BUNDLE_SIZE
     81           offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen)
     82           if offset_to_nearest_bundle == offset_to_end:
     83             offset_to_nearest_bundle = None
     84           print_check(offset_to_end, offset_to_nearest_bundle)
     85       else:
     86         if offset + instlen > BUNDLE_SIZE:
     87           # Padding needed
     88           aligned_offset = (inst_orig_offset + instlen) & ~(BUNDLE_SIZE - 1)
     89           print_check(aligned_offset)
     90         else:
     91           # No padding needed
     92           print_check()
     93 
     94       print()
     95       ntest += 1
     96 
     97 if __name__ == '__main__':
     98   argparser = argparse.ArgumentParser()
     99   argparser.add_argument('--align-to-end',
    100                          action='store_true',
    101                          help='generate .bundle_lock with align_to_end option')
    102   args = argparser.parse_args()
    103   generate(align_to_end=args.align_to_end)
    104