bugfixed x86 parser and tests for dep finder

This commit is contained in:
JanLJL
2019-06-24 17:28:45 +02:00
parent 75a405e33e
commit e923c67bdb
6 changed files with 146 additions and 2 deletions

View File

@@ -92,6 +92,8 @@ class ParserX86ATT(BaseParser):
+ pp.Optional(operand_rest.setResultsName('operand2'))
+ pp.Optional(pp.Suppress(pp.Literal(',')))
+ pp.Optional(operand_rest.setResultsName('operand3'))
+ pp.Optional(pp.Suppress(pp.Literal(',')))
+ pp.Optional(operand_rest.setResultsName('operand4'))
+ pp.Optional(self.comment)
)
@@ -179,9 +181,15 @@ class ParserX86ATT(BaseParser):
result = AttrDict.convert_dict(result)
operands = AttrDict({'source': [], 'destination': []})
# Check from right to left
# Check fourth operand
if 'operand4' in result:
operands['destination'].append(self.process_operand(result['operand4']))
# Check third operand
if 'operand3' in result:
operands['destination'].append(self.process_operand(result['operand3']))
if len(operands['destination']) != 0:
operands['source'].insert(0, self.process_operand(result['operand3']))
else:
operands['destination'].append(self.process_operand(result['operand3']))
# Check second operand
if 'operand2' in result:
if len(operands['destination']) != 0:

View File

@@ -8,7 +8,8 @@ suite = unittest.TestLoader().loadTestsFromNames(
[
'test_parser_x86att',
'test_parser_AArch64v81',
'test_marker_utils'
'test_marker_utils',
'test_dependency_finder'
]
)

99
tests/test_dependency_finder.py Executable file
View File

@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""
Unit tests for KernelDAG
"""
import os
import unittest
from osaca.dependency_finder import KernelDAG
from osaca.parser import AttrDict, ParserAArch64v81, ParserX86ATT
class TestDependencyFinder(unittest.TestCase):
def setUp(self):
self.parser_x86 = ParserX86ATT()
self.parser_AArch64 = ParserAArch64v81()
with open(self._find_file('kernel-x86.s')) as f:
code_x86 = f.read()
with open(self._find_file('kernel-AArch64.s')) as f:
code_AArch64 = f.read()
self.kernel_x86 = self.parser_x86.parse_file(code_x86)
self.kernel_AArch64 = self.parser_AArch64.parse_file(code_AArch64)
###########
# Tests
###########
def test_is_read_is_written_x86(self):
# independent form HW model
dag = KernelDAG(self.kernel_x86, self.parser_x86, None)
reg_rcx = AttrDict({'name': 'rcx'})
reg_ymm1 = AttrDict({'name': 'ymm1'})
instr_form_r_c = self.parser_x86.parse_line('vmovsd %xmm0, (%r15,%rcx,8)')
instr_form_non_r_c = self.parser_x86.parse_line('movl %xmm0, (%r15,%rax,8)')
instr_form_w_c = self.parser_x86.parse_line('movi $0x05ACA, %rcx')
instr_form_rw_ymm_1 = self.parser_x86.parse_line('vinsertf128 $0x1, %xmm1, %ymm0, %ymm1')
instr_form_rw_ymm_2 = self.parser_x86.parse_line('vinsertf128 $0x1, %xmm0, %ymm1, %ymm1')
instr_form_r_ymm = self.parser_x86.parse_line('vmovapd %ymm1, %ymm0')
self.assertTrue(dag.is_read(reg_rcx, instr_form_r_c))
self.assertFalse(dag.is_read(reg_rcx, instr_form_non_r_c))
self.assertFalse(dag.is_read(reg_rcx, instr_form_w_c))
self.assertTrue(dag.is_written(reg_rcx, instr_form_w_c))
self.assertFalse(dag.is_written(reg_rcx, instr_form_r_c))
self.assertTrue(dag.is_read(reg_ymm1, instr_form_rw_ymm_1))
self.assertTrue(dag.is_read(reg_ymm1, instr_form_rw_ymm_2))
self.assertTrue(dag.is_read(reg_ymm1, instr_form_r_ymm))
self.assertTrue(dag.is_written(reg_ymm1, instr_form_rw_ymm_1))
self.assertTrue(dag.is_written(reg_ymm1, instr_form_rw_ymm_2))
self.assertFalse(dag.is_written(reg_ymm1, instr_form_r_ymm))
def test_is_read_is_written_AArch64(self):
# independent form HW model
dag = KernelDAG(self.kernel_AArch64, self.parser_AArch64, None)
reg_x1 = AttrDict({'prefix': 'x', 'name': '1'})
reg_q1 = AttrDict({'prefix': 'q', 'name': '1'})
reg_v1 = AttrDict({'prefix': 'v', 'name': '1', 'lanes': '2', 'shape': 'd'})
regs = [reg_x1, reg_q1, reg_v1]
instr_form_r_1 = self.parser_AArch64.parse_line('stp q1, q3, [x12, #192]')
instr_form_r_2 = self.parser_AArch64.parse_line('fadd v2.2d, v1.2d, v0.2d')
instr_form_w_1 = self.parser_AArch64.parse_line('ldr x0, [x0, #:got_lo12:q2c]')
instr_form_rw_1 = self.parser_AArch64.parse_line('fmul v1.2d, v1.2d, v0.2d')
instr_form_rw_2 = self.parser_AArch64.parse_line('ldp q2, q4, [x1, #64]!')
instr_form_rw_3 = self.parser_AArch64.parse_line('str x4, [x1], #64')
instr_form_non_rw_1 = self.parser_AArch64.parse_line('adds x0, x11')
for reg in regs:
with self.subTest(reg=reg):
self.assertTrue(dag.is_read(reg, instr_form_r_1))
self.assertTrue(dag.is_read(reg, instr_form_r_2))
self.assertTrue(dag.is_read(reg, instr_form_rw_1))
self.assertTrue(dag.is_read(reg, instr_form_rw_2))
self.assertTrue(dag.is_read(reg, instr_form_rw_3))
self.assertFalse(dag.is_read(reg, instr_form_w_1))
self.assertTrue(dag.is_written(reg, instr_form_rw_1))
self.assertTrue(dag.is_written(reg, instr_form_rw_2))
self.assertTrue(dag.is_written(reg, instr_form_rw_3))
self.assertFalse(dag.is_written(reg, instr_form_non_rw_1))
self.assertFalse(dag.is_written(reg, instr_form_non_rw_1))
##################
# Helper functions
##################
@staticmethod
def _find_file(name):
testdir = os.path.dirname(__file__)
name = os.path.join(testdir, 'test_files', name)
assert os.path.exists(name)
return name
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestDependencyFinder)
unittest.TextTestRunner(verbosity=2).run(suite)

View File

@@ -0,0 +1,20 @@
.LBB0_32:
ldp q4, q5, [x9, #-32]
ldp q6, q7, [x9], #64
ldp q16, q17, [x11, #-32]
ldp q18, q19, [x11], #64
fmul v4.2d, v4.2d, v16.2d
fmul v5.2d, v5.2d, v17.2d
fmul v6.2d, v6.2d, v18.2d
fmul v7.2d, v7.2d, v19.2d
ldp q0, q1, [x8, #-32]
ldp q2, q3, [x8], #64
fadd v0.2d, v0.2d, v4.2d
fadd v1.2d, v1.2d, v5.2d
stp q0, q1, [x10, #-32]
fadd v2.2d, v2.2d, v6.2d
fadd v3.2d, v3.2d, v7.2d
stp q2, q3, [x10]
add x10, x10, #64 // =64
adds x12, x12, #1 // =1
b.ne .LBB0_32

View File

@@ -0,0 +1,9 @@
.L10:
vmovapd (%r15,%rax), %ymm0
vmovapd (%r12,%rax), %ymm3
addl $1, %ecx
vfmadd132pd 0(%r13,%rax), %ymm3, %ymm0
vmovapd %ymm0, (%r14,%rax)
addq $32, %rax
cmpl %ecx, %r10d
ja .L10

View File

@@ -75,6 +75,7 @@ class TestParserX86ATT(unittest.TestCase):
instr4 = 'vmovss %xmm4, -4(%rsp,%rax,8) #12.9'
instr5 = 'mov %ebx,var(,1)'
instr6 = 'lea (,%rax,8),%rbx'
instr7 = 'vinsertf128 $0x1, %xmm0, %ymm1, %ymm1'
parsed_1 = self.parser.parse_instruction(instr1)
parsed_2 = self.parser.parse_instruction(instr2)
@@ -82,6 +83,7 @@ class TestParserX86ATT(unittest.TestCase):
parsed_4 = self.parser.parse_instruction(instr4)
parsed_5 = self.parser.parse_instruction(instr5)
parsed_6 = self.parser.parse_instruction(instr6)
parsed_7 = self.parser.parse_instruction(instr7)
self.assertEqual(parsed_1.instruction, 'vcvtsi2ss')
self.assertEqual(parsed_1.operands.destination[0].register.name, 'xmm2')
@@ -120,6 +122,11 @@ class TestParserX86ATT(unittest.TestCase):
self.assertEqual(parsed_6.operands.source[0].memory.scale, '8')
self.assertEqual(parsed_6.operands.destination[0].register.name, 'rbx')
self.assertEqual(parsed_7.operands.source[0].immediate.value, '0x1')
self.assertEqual(parsed_7.operands.source[1].register.name, 'xmm0')
self.assertEqual(parsed_7.operands.source[2].register.name, 'ymm1')
self.assertEqual(parsed_7.operands.destination[0].register.name, 'ymm1')
def test_parse_line(self):
line_comment = '# -- Begin main'
line_label = '..B1.7: # Preds ..B1.6'