Beispiel #1
0
    def gen_test_case_with_const(self):
        """generate tests calling function with const"""
        cnt = 0
        cases = '\n\n;; Const vs const'
        for op in self.BINARY_OPS:
            for param_1, param_2 in self.get_test_data_with_const:
                result = []
                for idx in range(0, len(param_1)):
                    result.append(
                        IntOp.binary_op(op, param_1[idx], param_2[idx],
                                        self.lane_width))
                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op}_with_const_{cnt}'.format(
                            lane_type=self.LANE_TYPE, op=op, cnt=cnt), [],
                        SIMD.v128_const(result, self.LANE_TYPE)))
                cnt += 1

        cases += '\n\n;; Param vs const'
        for op in self.BINARY_OPS:
            for param_1, param_2 in self.get_test_data_with_const:
                result = []
                for idx in range(0, len(param_1)):
                    result.append(
                        IntOp.binary_op(op, param_1[idx], param_2[idx],
                                        self.lane_width))
                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op}_with_const_{cnt}'.format(
                            lane_type=self.LANE_TYPE, op=op, cnt=cnt),
                        [SIMD.v128_const(param_2, self.LANE_TYPE)],
                        SIMD.v128_const(result, self.LANE_TYPE)))
                cnt += 1

        return cases
Beispiel #2
0
    def get_combine_cases(self):
        combine_cases = [';; combination\n(module']
        ternary_func_template = '  (func (export "{func}") (param v128 v128 v128) (result v128)\n' \
                              '    ({lane}.{op1} ({lane}.{op2} (local.get 0) (local.get 1))'\
                              '(local.get 2)))'
        for func in sorted(self.combine_ternary_arith_test_data):
            func_parts = func.split('-')
            op1 = func_parts[1].replace('_', '_saturate_')
            op2 = func_parts[2].replace('_', '_saturate_')
            combine_cases.append(ternary_func_template.format(func=func,
                                                            lane=self.LANE_TYPE,
                                                            op1=op1,
                                                            op2=op2))
        binary_func_template = '  (func (export "{func}") (param v128 v128) (result v128)\n'\
                             '    ({lane}.{op1} ({lane}.{op2} (local.get 0)) (local.get 1)))'
        for func in sorted(self.combine_binary_arith_test_data):
            func_parts = func.split('-')
            op1 = func_parts[1].replace('_', '_saturate_')
            combine_cases.append(binary_func_template.format(func=func,
                                                           lane=self.LANE_TYPE,
                                                           op1=op1,
                                                           op2=func_parts[2]))
        combine_cases.append(')\n')

        for func, test in sorted(self.combine_ternary_arith_test_data.items()):
            combine_cases.append(str(AssertReturn(func,
                                 [SIMD.v128_const(elem, self.LANE_TYPE) for elem in test[:-1]],
                                 SIMD.v128_const(test[-1], self.LANE_TYPE))))

        for func, test in sorted(self.combine_binary_arith_test_data.items()):
            combine_cases.append(str(AssertReturn(func,
                                 [SIMD.v128_const(elem, self.LANE_TYPE) for elem in test[:-1]],
                                 SIMD.v128_const(test[-1], self.LANE_TYPE))))

        return '\n'.join(combine_cases)
Beispiel #3
0
    def get_normal_case(self):
        s = SIMD()
        cases = []

        # store using arg
        for (addr, ret) in self.get_case_data():
            i32_addr = s.const(addr, "i32")
            v128_val = s.v128_const(list_stringify(ret), self.LANE_TYPE)
            result = s.const(ret[addr], "i64")
            instr = "v128.store{lane_len}_lane_{idx}".format(
                lane_len=self.LANE_LEN, idx=addr)
            cases.append(str(AssertReturn(instr, [i32_addr, v128_val],
                                          result)))

        # store using offset
        for (addr, ret) in self.get_case_data():
            v128_val = s.v128_const(list_stringify(ret), self.LANE_TYPE)
            result = s.const(ret[addr], "i64")
            instr = "v128.store{lane_len}_lane_{idx}_offset_{idx}".format(
                lane_len=self.LANE_LEN, idx=addr)
            cases.append(str(AssertReturn(instr, [v128_val], result)))

        # store using offset with alignment
        for (addr, ret) in self.get_case_data():
            for align in self.valid_alignments():
                i32_addr = s.const(addr, "i32")
                v128_val = s.v128_const(list_stringify(ret), self.LANE_TYPE)
                result = s.const(ret[addr], "i64")
                instr = "v128.store{lane_len}_lane_{idx}_align_{align}".format(
                    lane_len=self.LANE_LEN, idx=addr, align=align)
                cases.append(
                    str(AssertReturn(instr, [i32_addr, v128_val], result)))

        return '\n'.join(cases)
Beispiel #4
0
    def get_normal_case(self):

        s = SIMD()

        case_data = self.get_case_data()

        cases = []

        for item in case_data:
            # Recognize '#' as a commentary
            if item[0] == '#':
                cases.append('\n;; {}'.format(item[1]))
                continue
            """
            Generate assert_return
            Params: instruction: instruction name;
                    param: param for instruction;
                    ret: excepted result;
                    lane_type: lane type
            """
            instruction, param, ret, lane_type = item
            cases.append(
                str(
                    AssertReturn(instruction, [
                        s.v128_const(param[0], lane_type[0]),
                        s.v128_const(param[1], lane_type[1])
                    ], s.v128_const(ret, lane_type[2]))))

        return '\n'.join(cases)
Beispiel #5
0
    def gen_test_case_combination(self):
        """generate combination test cases"""

        cases = '\n'

        binary_ops = list(self.BINARY_OPS)
        binary_ops.reverse()
        for op1 in self.BINARY_OPS:
            for op2 in binary_ops:

                result = []
                ret = IntOp.binary_op(op2, '0', '1', self.lane_width)
                ret = IntOp.binary_op(op1, ret, '2', self.lane_width)
                result.append(ret)

                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op1}-{lane_type}.{op2}'.format(
                            lane_type=self.LANE_TYPE, op1=op1, op2=op2), [
                                SIMD.v128_const('0', self.LANE_TYPE),
                                SIMD.v128_const('1', self.LANE_TYPE),
                                SIMD.v128_const('2', self.LANE_TYPE)
                            ], SIMD.v128_const(result, self.LANE_TYPE)))
        cases += '\n'
        return cases
    def get_normal_case(self):
        cases = []

        for op in self.UNARY_OPS:
            src_lane_type = self.src_lane_type(op)
            src_value = self.LANE_VALUE[src_lane_type]
            operands = self.get_test_cases(src_value)

            for (low, high) in operands:
                result = low if "low" in op else high

                if self.is_unsigned(op):
                    # Unsign-extend, mask top bits.
                    result = result & src_value.mask

                cases.append(
                    str(
                        AssertReturn(
                            op,
                            [SIMD.v128_const([str(low), str(high)], src_lane_type)],
                            SIMD.v128_const(str(result), self.dst_lane_type(op)),
                        )
                    )
                )

            cases.append("")

        return "\n".join(cases)
Beispiel #7
0
 def gen(case_data):
     cases = ''
     for op in self.BINARY_OPS:
         for param_1, param_2 in case_data:
             result = []
             for idx in range(0, len(param_1)):
                 result.append(IntOp.binary_op(op, param_1[idx], param_2[idx], self.lane_width))
             cases += '\n' + str(AssertReturn('{lane_type}.{op}'.format(lane_type=self.LANE_TYPE, op=op),
                                              [SIMD.v128_const(param_1, self.LANE_TYPE), SIMD.v128_const(param_2, self.LANE_TYPE)],
                                              SIMD.v128_const(result, self.LANE_TYPE)))
     return cases
Beispiel #8
0
 def gen_unary(case_data):
     cases = ''
     for op in self.UNARY_OPS:
         o = ArithmeticOp(op)
         for param in case_data:
             result = []
             for idx in range(0, len(param)):
                 result.append(o.unary_op(param[idx], self.LANE_VALUE))
             cases += '\n' + str(
                 AssertReturn(
                     '{lane_type}.{op}'.format(lane_type=self.LANE_TYPE,
                                               op=op),
                     [SIMD.v128_const(param, self.LANE_TYPE)],
                     SIMD.v128_const(result, self.LANE_TYPE)))
     return cases
Beispiel #9
0
    def get_normal_case(self):
        """
        Generate normal case with test data
        """

        lst_i_p_r = self.init_case_data(self.get_case_data())

        cases = []
        for ipr in lst_i_p_r:

            if ipr[0] == '#':
                cases.append(ipr[1])
                continue

            cases.append(str(AssertReturn(ipr[0], ipr[1], ipr[2])))

        return '\n'.join(cases)
Beispiel #10
0
    def get_normal_case(self):
        s = SIMD()
        case_data = self.get_case_data()
        cases = []

        for item in case_data:
            # Recognize '#' as a commentary
            if item[0] == '#':
                cases.append('\n;; {}'.format(item[1]))
                continue

            instruction, param, ret, lane_type = item
            v128_result = s.v128_const(ret, lane_type[-1])
            v128_params = []
            for i, p in enumerate(param):
                v128_params.append(s.v128_const(p, lane_type[i]))
            cases.append(
                str(AssertReturn(instruction, v128_params, v128_result)))

        return '\n'.join(cases)
Beispiel #11
0
    def get_normal_case(self):
        """Normal test cases from WebAssembly core tests
        """
        cases = []
        binary_test_data = []
        unary_test_data = []

        for op in self.BINARY_OPS:
            op_name = self.full_op_name(op)
            for p1 in self.FLOAT_NUMBERS:
                for p2 in self.FLOAT_NUMBERS:
                    result = self.floatOp.binary_op(op, p1, p2)
                    if 'nan' not in result:
                        # Normal floating point numbers as the results
                        binary_test_data.append(
                            ['assert_return', op_name, p1, p2, result])
                    else:
                        # Since the results contain the 'nan' string, the result literals would be
                        # nan:canonical
                        binary_test_data.append([
                            'assert_return', op_name, p1, p2, 'nan:canonical'
                        ])

            for p1 in self.NAN_NUMBERS:
                for p2 in self.FLOAT_NUMBERS:
                    if 'nan:' in p1 or 'nan:' in p2:
                        # When the arguments contain 'nan:', the result literal is nan:arithmetic
                        binary_test_data.append([
                            'assert_return', op_name, p1, p2, 'nan:arithmetic'
                        ])
                    else:
                        # No 'nan' string found, then the result literal is nan:canonical
                        binary_test_data.append([
                            'assert_return', op_name, p1, p2, 'nan:canonical'
                        ])
                for p2 in self.NAN_NUMBERS:
                    if 'nan:' in p1 or 'nan:' in p2:
                        binary_test_data.append([
                            'assert_return', op_name, p1, p2, 'nan:arithmetic'
                        ])
                    else:
                        binary_test_data.append([
                            'assert_return', op_name, p1, p2, 'nan:canonical'
                        ])

            for p1 in self.LITERAL_NUMBERS:
                for p2 in self.LITERAL_NUMBERS:
                    result = self.floatOp.binary_op(op, p1, p2, hex_form=False)
                    binary_test_data.append(
                        ['assert_return', op_name, p1, p2, result])

        for case in binary_test_data:
            cases.append(self.single_binary_test(case))

        # Test opposite signs of zero
        lst_oppo_signs_0 = [
            '\n;; Test opposite signs of zero',
            [
                'f64x2.min', [['0', '0'], ['+0', '-0']], [['0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.min', [['-0', '+0'], ['+0', '-0']], [['-0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.min', [['-0', '-0'], ['+0', '+0']], [['-0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['0', '0'], ['+0', '-0']], [['0', '0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['-0', '+0'], ['+0', '-0']], [['0', '0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['-0', '-0'], ['+0', '+0']], [['+0', '+0']],
                ['f64x2', 'f64x2', 'f64x2']
            ], '\n'
        ]

        # Generate test case for opposite signs of zero
        for case_data in lst_oppo_signs_0:

            if isinstance(case_data, str):
                cases.append(case_data)
                continue

            cases.append(
                str(
                    AssertReturn(
                        case_data[0], [
                            self.v128_const(case_data[3][0], case_data[1][0]),
                            self.v128_const(case_data[3][1], case_data[1][1])
                        ], self.v128_const(case_data[3][2], case_data[2][0]))))

        for p in self.FLOAT_NUMBERS + self.LITERAL_NUMBERS:
            op_name = self.full_op_name('abs')
            hex_literal = True
            if p in self.LITERAL_NUMBERS:
                hex_literal = False
            result = self.floatOp.unary_op('abs', p, hex_form=hex_literal)
            # Abs operation is valid for all the floating point numbers
            unary_test_data.append(['assert_return', op_name, p, result])

        for case in unary_test_data:
            cases.append(self.single_unary_test(case))

        return '\n'.join(cases)
Beispiel #12
0
    def gen_test_func_template(self):

        # Get function code
        template = Simdf32x4ArithmeticCase.gen_test_func_template(self)

        # Function template
        tpl_func = '  (func (export "{func}"){params} (result v128) ({op} {operand_1}{operand_2}))'

        # Raw data list specific for "const vs const" and "param vs const" tests"
        const_test_raw_data = [[[['0', '1'], ['0', '2']],
                                [['0', '1'], ['0', '2']]],
                               [[['2', '-3'], ['1', '3']],
                                [['1', '-3'], ['2', '3']]],
                               [[['0', '1'], ['0', '1']],
                                [['0', '1'], ['0', '1']]],
                               [[['2', '3'], ['2', '3']],
                                [['2', '3'], ['2', '3']]],
                               [[['0x00', '0x01'], ['0x00', '0x02']],
                                [['0x00', '0x01'], ['0x00', '0x02']]],
                               [[['0x02', '0x80000000'],
                                 ['0x01', '2147483648']],
                                [['0x01', '0x80000000'],
                                 ['0x02', '2147483648']]],
                               [[['0x00', '0x01'], ['0x00', '0x01']],
                                [['0x00', '0x01'], ['0x00', '0x01']]],
                               [[['0x02', '0x80000000'],
                                 ['0x02', '0x80000000']],
                                [['0x02', '0x80000000'],
                                 ['0x02', '0x80000000']]]]

        # Test data list combined with `const_test_raw_data` and corresponding ops and function names
        # specific for "const vs const" and "param vs const" tests
        const_test_data = {}

        # Generate func and assert
        for op in self.BINARY_OPS:

            op_name = self.full_op_name(op)

            # Add comment for the case script "  ;; [f64x2.min, f64x2.max] const vs const"
            template.insert(
                len(template) - 1, '  ;; {} const vs const'.format(op_name))

            # Add const vs const cases
            for case_data in const_test_raw_data:

                func = "{op}_with_const_{index}".format(op=op_name,
                                                        index=len(template) -
                                                        7)
                template.insert(
                    len(template) - 1,
                    tpl_func.format(func=func,
                                    params='',
                                    op=op_name,
                                    operand_1=self.v128_const(
                                        'f64x2', case_data[0][0]),
                                    operand_2=' ' +
                                    self.v128_const('f64x2', case_data[0][1])))

                ret_idx = 0 if op == 'min' else 1

                if op not in const_test_data:
                    const_test_data[op] = []

                const_test_data[op].append([func, case_data[1][ret_idx]])

            # Add comment for the case script "  ;; [f64x2.min, f64x2.max] param vs const"
            template.insert(
                len(template) - 1, '  ;; {} param vs const'.format(op_name))

            case_cnt = 0

            # Add param vs const cases
            for case_data in const_test_raw_data:

                func = "{op}_with_const_{index}".format(op=op_name,
                                                        index=len(template) -
                                                        7)

                # Cross parameters and constants
                if case_cnt in (0, 3):
                    operand_1 = '(local.get 0)'
                    operand_2 = self.v128_const('f64x2', case_data[0][0])
                else:
                    operand_1 = self.v128_const('f64x2', case_data[0][0])
                    operand_2 = '(local.get 0)'

                template.insert(
                    len(template) - 1,
                    tpl_func.format(func=func,
                                    params=' (param v128)',
                                    op=op_name,
                                    operand_1=operand_1,
                                    operand_2=' ' + operand_2))

                ret_idx = 0 if op == 'min' else 1

                if op not in const_test_data:
                    const_test_data[op] = []

                const_test_data[op].append(
                    [func, case_data[0][1], case_data[1][ret_idx]])

                case_cnt += 1

        # Generate func for abs
        op_name = self.full_op_name('abs')
        template.insert(len(template) - 1, '')
        func = "{op}_with_const_{index}".format(op=op_name, index=35)
        template.insert(
            len(template) - 1,
            tpl_func.format(func=func,
                            params='',
                            op=op_name,
                            operand_1=self.v128_const('f64x2', ['-0', '-1']),
                            operand_2=''))
        func = "{op}_with_const_{index}".format(op=op_name, index=36)
        template.insert(
            len(template) - 1,
            tpl_func.format(func=func,
                            params='',
                            op=op_name,
                            operand_1=self.v128_const('f64x2', ['-2', '-3']),
                            operand_2=''))

        # Test different lanes go through different if-then clauses
        lst_diff_lane_vs_clause = [[
            'f64x2.min', [['nan', '0'], ['0', '1']], [['nan', '0']],
            ['f64x2', 'f64x2', 'f64x2']
        ],
                                   [
                                       'f64x2.min', [['0', '1'], ['-nan',
                                                                  '0']],
                                       [['-nan', '0']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.min', [['0', '1'], ['-nan',
                                                                  '1']],
                                       [['nan:canonical', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['nan', '0'], ['0', '1']],
                                       [['nan:canonical', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['0', '1'], ['-nan',
                                                                  '0']],
                                       [['nan:canonical', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['0', '1'], ['-nan',
                                                                  '1']],
                                       [['nan:canonical', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ]]

        # Template for assert
        tpl_assert = '(assert_return\n' \
                     '  (invoke "{func}"\n' \
                     '    {operand_1}\n' \
                     '    {operand_2}\n' \
                     '  )\n' \
                     '  {expected_result}\n' \
                     ')'

        lst_diff_lane_vs_clause_assert = []

        # Add comment in wast script
        lst_diff_lane_vs_clause_assert.append('')
        lst_diff_lane_vs_clause_assert.append(
            ';; Test different lanes go through different if-then clauses')

        for case_data in lst_diff_lane_vs_clause:

            lst_diff_lane_vs_clause_assert.append(
                ';; {lane_type}'.format(lane_type=case_data[0]))

            lst_diff_lane_vs_clause_assert.append(
                tpl_assert.format(
                    func=case_data[0],
                    operand_1=self.v128_const(case_data[3][0],
                                              case_data[1][0]),
                    operand_2=self.v128_const(case_data[3][1],
                                              case_data[1][1]),
                    expected_result=self.v128_const(case_data[3][2],
                                                    case_data[2][0])))

        lst_diff_lane_vs_clause_assert.append('')

        # Add test for operations with constant operands
        for key in const_test_data:
            op_name = self.full_op_name(key)
            case_cnt = 0
            for case_data in const_test_data[key]:

                # Add comment for the param combination
                if case_cnt == 0:
                    template.append(';; {} const vs const'.format(op_name))
                if case_cnt == 4:
                    template.append(';; {} param vs const'.format(op_name))

                # Cross parameters and constants
                if case_cnt < 8:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0], [],
                                self.v128_const('f64x2', case_data[1]))))
                else:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0],
                                [self.v128_const('f64x2', case_data[1])],
                                self.v128_const('f64x2', case_data[2]))))
                case_cnt += 1

        # Generate and append f64x2.abs assert
        op_name = self.full_op_name('abs')
        template.append('')
        func = "{op}_with_const_{index}".format(op=op_name, index=35)
        template.append(
            str(AssertReturn(func, [], self.v128_const('f64x2', ['0', '1']))))
        func = "{op}_with_const_{index}".format(op=op_name, index=36)
        template.append(
            str(AssertReturn(func, [], self.v128_const('f64x2', ['2', '3']))))

        template.extend(lst_diff_lane_vs_clause_assert)

        return template
Beispiel #13
0
    def get_normal_case(self):
        """Normal test cases from WebAssembly core tests, 4 assert statements:
            assert_return
            assert_return_canonical_nan
            assert_return_arithmetic_nan
            assert_malformed
        """
        cases = []
        binary_test_data = []
        unary_test_data = []

        for op in self.BINARY_OPS:
            op_name = self.full_op_name(op)
            for p1 in self.FLOAT_NUMBERS:
                for p2 in self.FLOAT_NUMBERS:
                    result = self.floatOp.binary_op(op, p1, p2)
                    if 'nan' not in result:
                        # Normal floating point numbers as the results
                        binary_test_data.append(
                            ['assert_return', op_name, p1, p2, result])
                    else:
                        # Since the results contain the 'nan' string, it should be in the
                        # assert_return_canonical_nan statements
                        binary_test_data.append([
                            'assert_return_canonical_nan_f64x2', op_name, p1,
                            p2
                        ])

            # assert_return_canonical_nan and assert_return_arithmetic_nan cases
            for p1 in self.NAN_NUMBERS:
                for p2 in self.FLOAT_NUMBERS:
                    if 'nan:' in p1 or 'nan:' in p2:
                        # When the arguments contain 'nan:', always use assert_return_arithmetic_nan
                        # statements for the cases. Since there 2 parameters for binary operation and
                        # the order of the parameters matter. Different order makes different cases.
                        binary_test_data.append([
                            'assert_return_arithmetic_nan_f64x2', op_name, p1,
                            p2
                        ])
                        binary_test_data.append([
                            'assert_return_arithmetic_nan_f64x2', op_name, p2,
                            p1
                        ])
                    else:
                        # No 'nan' string found, then it should be assert_return_canonical_nan.
                        binary_test_data.append([
                            'assert_return_canonical_nan_f64x2', op_name, p1,
                            p2
                        ])
                        binary_test_data.append([
                            'assert_return_canonical_nan_f64x2', op_name, p2,
                            p1
                        ])
                for p2 in self.NAN_NUMBERS:
                    # Both parameters contain 'nan', then there must be no assert_return.
                    if 'nan:' in p1 or 'nan:' in p2:
                        binary_test_data.append([
                            'assert_return_arithmetic_nan_f64x2', op_name, p1,
                            p2
                        ])
                    else:
                        binary_test_data.append([
                            'assert_return_canonical_nan_f64x2', op_name, p1,
                            p2
                        ])

        for case in binary_test_data:
            cases.append(self.single_binary_test(case))

        # Test opposite signs of zero
        lst_oppo_signs_0 = [
            '\n;; Test opposite signs of zero',
            [
                'f64x2.min', [['0', '0'], ['+0', '-0']], [['0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.min', [['-0', '+0'], ['+0', '-0']], [['-0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.min', [['-0', '-0'], ['+0', '+0']], [['-0', '-0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['0', '0'], ['+0', '-0']], [['0', '0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['-0', '+0'], ['+0', '-0']], [['0', '0']],
                ['f64x2', 'f64x2', 'f64x2']
            ],
            [
                'f64x2.max', [['-0', '-0'], ['+0', '+0']], [['+0', '+0']],
                ['f64x2', 'f64x2', 'f64x2']
            ], '\n'
        ]

        # Generate test case for opposite signs of zero
        for case_data in lst_oppo_signs_0:

            if isinstance(case_data, str):
                cases.append(case_data)
                continue

            cases.append(
                str(
                    AssertReturn(
                        case_data[0], [
                            self.v128_const(case_data[3][0], case_data[1][0]),
                            self.v128_const(case_data[3][1], case_data[1][1])
                        ], self.v128_const(case_data[3][2], case_data[2][0]))))

        for p in self.FLOAT_NUMBERS:
            op_name = self.full_op_name('abs')
            result = self.floatOp.unary_op('abs', p)
            # Abs operation is valid for all the floating point numbers
            unary_test_data.append(['assert_return', op_name, p, result])

        for case in unary_test_data:
            cases.append(self.single_unary_test(case))

        return '\n'.join(cases)
Beispiel #14
0
    def gen_test_fn_template(self):

        # Get function code
        template = Simdf32x4ArithmeticCase.gen_test_fn_template(self)

        # Function template
        tpl_func = '  (func (export "{}"){} (result v128) ({} {}{}))'

        # Raw data list specific for "const vs const" and "param vs const" tests
        const_test_raw_data = [[[['0', '1'], ['0', '2']],
                                [['0', '1'], ['0', '2']]],
                               [[['2', '-3'], ['1', '3']],
                                [['1', '-3'], ['2', '3']]],
                               [[['0', '1'], ['0', '1']],
                                [['0', '1'], ['0', '1']]],
                               [[['2', '3'], ['2', '3']],
                                [['2', '3'], ['2', '3']]],
                               [[['0x00', '0x01'], ['0x00', '0x02']],
                                [['0x00', '0x01'], ['0x00', '0x02']]],
                               [[['0x02', '0x80000000'],
                                 ['0x01', '2147483648']],
                                [['0x01', '0x80000000'],
                                 ['0x02', '2147483648']]],
                               [[['0x00', '0x01'], ['0x00', '0x01']],
                                [['0x00', '0x01'], ['0x00', '0x01']]],
                               [[['0x02', '0x80000000'],
                                 ['0x02', '0x80000000']],
                                [['0x02', '0x80000000'],
                                 ['0x02', '0x80000000']]]]

        # Test data list combined with `const_test_raw_data` and corresponding ops and function names
        # specific for "const vs const" and "param vs const" tests
        const_test_data = {}

        # Generate func and assert
        for op in self.BINARY_OPS:

            op_name = self.full_op_name(op)

            # Add comment for the case script "  ;; [f64x2.min, f64x2.max] const vs const"
            template.insert(
                len(template) - 1, '  ;; {} const vs const'.format(op_name))

            # Add const vs const cases
            for case_data in const_test_raw_data:

                func_name = "{}_with_const_{}".format(op_name,
                                                      len(template) - 7)
                template.insert(
                    len(template) - 1,
                    tpl_func.format(
                        func_name, '', op_name,
                        self.v128_const('f64x2', case_data[0][0]),
                        ' ' + self.v128_const('f64x2', case_data[0][1])))

                ret_idx = 0 if op == 'min' else 1

                if op not in const_test_data:
                    const_test_data[op] = []

                const_test_data[op].append([func_name, case_data[1][ret_idx]])

            # Add comment for the case script "  ;; [f64x2.min, f64x2.max] param vs const"
            template.insert(
                len(template) - 1, '  ;; {} param vs const'.format(op_name))

            case_cnt = 0

            # Add param vs const cases
            for case_data in const_test_raw_data:

                func_name = "{}_with_const_{}".format(op_name,
                                                      len(template) - 7)

                # Cross parameters and constants
                if case_cnt in (0, 3):
                    func_param_0 = '(local.get 0)'
                    func_param_1 = self.v128_const('f64x2', case_data[0][0])
                else:
                    func_param_0 = self.v128_const('f64x2', case_data[0][0])
                    func_param_1 = '(local.get 0)'

                template.insert(
                    len(template) - 1,
                    tpl_func.format(func_name, ' (param v128)', op_name,
                                    func_param_0, ' ' + func_param_1))

                ret_idx = 0 if op == 'min' else 1

                if op not in const_test_data:
                    const_test_data[op] = []

                const_test_data[op].append(
                    [func_name, case_data[0][1], case_data[1][ret_idx]])

                case_cnt += 1

        # Generate func for abs
        op_name = self.full_op_name('abs')
        template.insert(len(template) - 1, '')
        func_name = "{}_with_const_{}".format(op_name, 35)
        template.insert(
            len(template) - 1,
            tpl_func.format(func_name, '', op_name,
                            self.v128_const('f64x2', ['-0', '-1']), ''))
        func_name = "{}_with_const_{}".format(op_name, 36)
        template.insert(
            len(template) - 1,
            tpl_func.format(func_name, '', op_name,
                            self.v128_const('f64x2', ['-2', '-3']), ''))

        # Test different lanes go through different if-then clauses
        lst_diff_lane_vs_clause = [[
            'f64x2.min', [['nan', '0'], ['0', '1']], [['nan', '0']],
            ['f64x2', 'f64x2', 'f64x2']
        ],
                                   [
                                       'f64x2.min', [['0', '1'], ['-nan',
                                                                  '0']],
                                       [['-nan', '0']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.min', [['0', '1'], ['-nan',
                                                                  '1']],
                                       [['-nan', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['nan', '0'], ['0', '1']],
                                       [['nan', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['0', '1'], ['-nan',
                                                                  '0']],
                                       [['-nan', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ],
                                   [
                                       'f64x2.max', [['0', '1'], ['-nan',
                                                                  '1']],
                                       [['-nan', '1']],
                                       ['f64x2', 'f64x2', 'f64x2']
                                   ]]

        # Case number
        case_cnt = 0

        # Template for func name to extract a lane
        tpl_func_name_by_lane = 'call_indirect_vv_v_f64x2_extract_lane_{}'

        # Template for assert
        tpl_assert = '({}\n' \
                     '  (invoke "{}"\n' \
                     '    {}\n' \
                     '    {}\n' \
                     '    {}\n' \
                     '  )\n' \
                     '{}' \
                     ')'

        lst_diff_lane_vs_clause_assert = []

        # Add comment in wast script
        lst_diff_lane_vs_clause_assert.append('')
        lst_diff_lane_vs_clause_assert.append(
            ';; Test different lanes go through different if-then clauses')

        template.insert(len(template) - 1, '')
        template.insert(
            len(template) - 1,
            '  ;;  Test different lanes go through different if-then clauses')

        # Add test case for test different lanes go through different if-then clauses
        template.insert(
            len(template) - 1,
            '  (type $vv_v (func (param v128 v128) (result v128)))\n'
            '  (table funcref (elem $f64x2_min $f64x2_max))\n'
            '\n'
            '  (func $f64x2_min (type $vv_v)\n'
            '    (f64x2.min (local.get 0) (local.get 1))\n'
            '  )\n'
            '\n'
            '  (func $f64x2_max (type $vv_v)\n'
            '    (f64x2.max (local.get 0) (local.get 1))\n'
            '  )\n'
            '\n'
            '  (func (export "call_indirect_vv_v_f64x2_extract_lane_0")\n'
            '    (param v128 v128 i32) (result f64)\n'
            '    (f64x2.extract_lane 0\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )\n'
            '  (func (export "call_indirect_vv_v_f64x2_extract_lane_1")\n'
            '    (param v128 v128 i32) (result f64)\n'
            '    (f64x2.extract_lane 1\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )')

        for case_data in lst_diff_lane_vs_clause:

            lst_diff_lane_vs_clause_assert.append(';; {} {}'.format(
                case_data[0], case_cnt))

            # generate assert for every data lane
            for lane_idx in range(0, len(case_data[2][0])):

                # get the result by lane
                ret = case_data[2][0][lane_idx]

                idx_func = '0' if 'min' in case_data[0] else '1'

                # append assert
                if 'nan' in ret:

                    lst_diff_lane_vs_clause_assert.append(
                        tpl_assert.format(
                            'assert_return_canonical_nan',
                            tpl_func_name_by_lane.format(lane_idx),
                            self.v128_const('f64x2', case_data[1][0]),
                            self.v128_const('f64x2', case_data[1][1]),
                            self.v128_const('i32', idx_func), ''))
                else:

                    lst_diff_lane_vs_clause_assert.append(
                        tpl_assert.format(
                            'assert_return',
                            tpl_func_name_by_lane.format(lane_idx),
                            self.v128_const('f64x2', case_data[1][0]),
                            self.v128_const('f64x2', case_data[1][1]),
                            self.v128_const('i32', idx_func),
                            '  ' + self.v128_const('f64', ret) + '\n'))

            case_cnt += 1
            if case_cnt == 2:
                case_cnt = 0

        lst_diff_lane_vs_clause_assert.append('')

        # Add test for operations with constant operands
        for key in const_test_data:

            case_cnt = 0
            for case_data in const_test_data[key]:

                # Add comment for the param combination
                if case_cnt == 0:
                    template.append(';; {} const vs const'.format(op_name))
                if case_cnt == 4:
                    template.append(';; {} param vs const'.format(op_name))

                # Cross parameters and constants
                if case_cnt < 8:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0], [],
                                self.v128_const('f64x2', case_data[1]))))
                else:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0],
                                [self.v128_const('f64x2', case_data[1])],
                                self.v128_const('f64x2', case_data[2]))))
                case_cnt += 1

        # Generate and append f64x2.abs assert
        op_name = self.full_op_name('abs')
        template.append('')
        func_name = "{}_with_const_{}".format(op_name, 35)
        template.append(
            str(
                AssertReturn(func_name, [],
                             self.v128_const('f64x2', ['0', '1']))))
        func_name = "{}_with_const_{}".format(op_name, 36)
        template.append(
            str(
                AssertReturn(func_name, [],
                             self.v128_const('f64x2', ['2', '3']))))

        template.extend(lst_diff_lane_vs_clause_assert)

        return template
Beispiel #15
0
    def gen_test_case_combination(self):
        """generate combination test cases"""

        cases = '\n'

        binary_ops = list(self.BINARY_OPS)
        binary_ops.reverse()
        unary_ops = list(self.UNARY_OPS)
        unary_ops.reverse()
        for op1 in self.BINARY_OPS:
            """binary vs binary"""
            o1 = ArithmeticOp(op1)
            for op2 in binary_ops:
                o2 = ArithmeticOp(op2)
                result = []
                ret = o2.binary_op('0', '1', self.LANE_VALUE)
                ret = o1.binary_op(ret, '2', self.LANE_VALUE)
                result.append(ret)

                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op1}-{lane_type}.{op2}'.format(
                            lane_type=self.LANE_TYPE, op1=op1, op2=op2), [
                                SIMD.v128_const('0', self.LANE_TYPE),
                                SIMD.v128_const('1', self.LANE_TYPE),
                                SIMD.v128_const('2', self.LANE_TYPE)
                            ], SIMD.v128_const(result, self.LANE_TYPE)))
            for op2 in self.UNARY_OPS:
                """binary vs unary"""
                o2 = ArithmeticOp(op2)
                result1 = []
                ret1 = o2.unary_op('-1', self.LANE_VALUE)
                ret1 = o1.binary_op(ret1, '0', self.LANE_VALUE)
                result1.append(ret1)
                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op1}-{lane_type}.{op2}'.format(
                            lane_type=self.LANE_TYPE, op1=op1, op2=op2), [
                                SIMD.v128_const('-1', self.LANE_TYPE),
                                SIMD.v128_const('0', self.LANE_TYPE)
                            ], SIMD.v128_const(result1, self.LANE_TYPE)))
                """unary vs binary"""
                result2 = []
                ret2 = o1.binary_op('0', '-1', self.LANE_VALUE)
                ret2 = o2.unary_op(ret2, self.LANE_VALUE)
                result2.append(ret2)
                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op1}-{lane_type}.{op2}'.format(
                            lane_type=self.LANE_TYPE, op1=op2, op2=op1), [
                                SIMD.v128_const('0', self.LANE_TYPE),
                                SIMD.v128_const('-1', self.LANE_TYPE)
                            ], SIMD.v128_const(result2, self.LANE_TYPE)))
        for op1 in self.UNARY_OPS:
            """unary vs unary"""
            o1 = ArithmeticOp(op1)
            for op2 in unary_ops:
                o2 = ArithmeticOp(op2)
                result3 = []
                ret3 = o2.unary_op('-1', self.LANE_VALUE)
                ret3 = o1.unary_op(ret3, self.LANE_VALUE)
                result3.append(ret3)
                cases += '\n' + str(
                    AssertReturn(
                        '{lane_type}.{op1}-{lane_type}.{op2}'.format(
                            lane_type=self.LANE_TYPE, op1=op1, op2=op2),
                        [SIMD.v128_const('-1', self.LANE_TYPE)],
                        SIMD.v128_const(result3, self.LANE_TYPE)))

        cases += '\n'
        return cases
Beispiel #16
0
    def gen_test_func_template(self):

        # Get function code
        template = Simdf32x4ArithmeticCase.gen_test_func_template(self)

        # Function template
        tpl_func = '  (func (export "{func}"){params} (result v128) ({op} {operand_1}{operand_2}))'

        # Const data for min and max
        lst_instr_with_const = [[[['0', '1', '2', '-3'], ['0', '2', '1', '3']],
                                 [['0', '1', '1', '-3'], ['0', '2', '2',
                                                          '3']]],
                                [[['0', '1', '2', '3'], ['0', '1', '2', '3']],
                                 [['0', '1', '2', '3'], ['0', '1', '2', '3']]],
                                [[['0x00', '0x01', '0x02', '0x80000000'],
                                  ['0x00', '0x02', '0x01', '2147483648']],
                                 [['0x00', '0x01', '0x01', '0x80000000'],
                                  ['0x00', '0x02', '0x02', '2147483648']]],
                                [[['0x00', '0x01', '0x02', '0x80000000'],
                                  ['0x00', '0x01', '0x02', '0x80000000']],
                                 [['0x00', '0x01', '0x02', '0x80000000'],
                                  ['0x00', '0x01', '0x02', '0x80000000']]]]

        # Assert data
        lst_oprt_with_const_assert = {}

        # Generate func and assert
        for op in self.BINARY_OPS:

            op_name = self.full_op_name(op)

            # Add comment for the case script "  ;; [f32x4.min, f32x4.max] const vs const"
            template.insert(
                len(template) - 1, '  ;; {} const vs const'.format(op_name))

            # Add const vs const cases
            for case_data in lst_instr_with_const:

                func = "{op}_with_const_{index}".format(op=op_name,
                                                        index=len(template) -
                                                        7)
                template.insert(
                    len(template) - 1,
                    tpl_func.format(func=func,
                                    params='',
                                    op=op_name,
                                    operand_1=self.v128_const(
                                        'f32x4', case_data[0][0]),
                                    operand_2=' ' +
                                    self.v128_const('f32x4', case_data[0][1])))

                ret_idx = 0 if op == 'min' else 1

                if op not in lst_oprt_with_const_assert:
                    lst_oprt_with_const_assert[op] = []

                lst_oprt_with_const_assert[op].append(
                    [func, case_data[1][ret_idx]])

            # Add comment for the case script "  ;; [f32x4.min, f32x4.max] param vs const"
            template.insert(
                len(template) - 1, '  ;; {} param vs const'.format(op_name))

            case_cnt = 0

            # Add param vs const cases
            for case_data in lst_instr_with_const:

                func = "{}_with_const_{}".format(op_name, len(template) - 7)

                # Cross parameters and constants
                if case_cnt in (0, 3):
                    operand_1 = '(local.get 0)'
                    operand_2 = self.v128_const('f32x4', case_data[0][0])
                else:
                    operand_1 = self.v128_const('f32x4', case_data[0][0])
                    operand_2 = '(local.get 0)'

                template.insert(
                    len(template) - 1,
                    tpl_func.format(func=func,
                                    params='(param v128)',
                                    op=op_name,
                                    operand_1=operand_1,
                                    operand_2=' ' + operand_2))

                ret_idx = 0 if op == 'min' else 1

                if op not in lst_oprt_with_const_assert:
                    lst_oprt_with_const_assert[op] = []

                lst_oprt_with_const_assert[op].append(
                    [func, case_data[0][1], case_data[1][ret_idx]])

                case_cnt += 1

        # Generate func for abs
        op_name = self.full_op_name('abs')
        func = "{}_with_const".format(op_name)
        template.insert(len(template) - 1, '')
        template.insert(
            len(template) - 1,
            tpl_func.format(func=func,
                            params='',
                            op=op_name,
                            operand_1=self.v128_const(
                                'f32x4', ['-0', '-1', '-2', '-3']),
                            operand_2=''))

        # Test different lanes go through different if-then clauses
        lst_diff_lane_vs_clause = [[
            'f32x4.min', [['nan', '0', '0', '1'], ['0', '-nan', '1', '0']],
            [['nan', '-nan', '0', '0']], ['f32x4', 'f32x4', 'f32x4']
        ],
                                   [
                                       'f32x4.min',
                                       [['nan', '0', '0', '0'],
                                        ['0', '-nan', '1', '0']],
                                       [['nan', '-nan', '0', '0']],
                                       ['f32x4', 'f32x4', 'f32x4']
                                   ],
                                   [
                                       'f32x4.max',
                                       [['nan', '0', '0', '1'],
                                        ['0', '-nan', '1', '0']],
                                       [['nan', '-nan', '1', '1']],
                                       ['f32x4', 'f32x4', 'f32x4']
                                   ],
                                   [
                                       'f32x4.max',
                                       [['nan', '0', '0', '0'],
                                        ['0', '-nan', '1', '0']],
                                       [['nan', '-nan', '1', '0']],
                                       ['f32x4', 'f32x4', 'f32x4']
                                   ]]

        # Case number
        case_cnt = 0

        # Template for func name to extract a lane
        tpl_func_by_lane = 'call_indirect_vv_v_f32x4_extract_lane_{}'

        # Template for assert
        tpl_assert = '({assert_type}\n' \
                     '  (invoke "{func}"\n' \
                     '    {operand_1}\n' \
                     '    {operand_2}\n' \
                     '    {operand_3}\n' \
                     '  )\n' \
                     '{expected_result}' \
                     ')'

        lst_diff_lane_vs_clause_assert = []

        # Add comment in wast script
        lst_diff_lane_vs_clause_assert.append('')
        lst_diff_lane_vs_clause_assert.append(
            ';; Test different lanes go through different if-then clauses')

        template.insert(len(template) - 1, '')
        template.insert(
            len(template) - 1,
            '  ;;  Test different lanes go through different if-then clauses')

        # Add test case for test different lanes go through different if-then clauses
        template.insert(
            len(template) - 1,
            '  (type $vv_v (func (param v128 v128) (result v128)))\n'
            '  (table funcref (elem $f32x4_min $f32x4_max))\n'
            '\n'
            '  (func $f32x4_min (type $vv_v)\n'
            '    (f32x4.min (local.get 0) (local.get 1))\n'
            '  )\n'
            '\n'
            '  (func $f32x4_max (type $vv_v)\n'
            '    (f32x4.max (local.get 0) (local.get 1))\n'
            '  )\n'
            '\n'
            '  (func (export "call_indirect_vv_v_f32x4_extract_lane_0")\n'
            '    (param v128 v128 i32) (result f32)\n'
            '    (f32x4.extract_lane 0\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )\n'
            '  (func (export "call_indirect_vv_v_f32x4_extract_lane_1")\n'
            '    (param v128 v128 i32) (result f32)\n'
            '    (f32x4.extract_lane 1\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )\n'
            '  (func (export "call_indirect_vv_v_f32x4_extract_lane_2")\n'
            '    (param v128 v128 i32) (result f32)\n'
            '    (f32x4.extract_lane 2\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )\n'
            '  (func (export "call_indirect_vv_v_f32x4_extract_lane_3")\n'
            '    (param v128 v128 i32) (result f32)\n'
            '    (f32x4.extract_lane 3\n'
            '      (call_indirect (type $vv_v) (local.get 0) (local.get 1) (local.get 2))\n'
            '    )\n'
            '  )')

        for case_data in lst_diff_lane_vs_clause:

            lst_diff_lane_vs_clause_assert.append(
                ';; {lane_type} {index}'.format(lane_type=case_data[0],
                                                index=case_cnt))

            # generate assert for every data lane
            for lane_idx in range(0, len(case_data[2][0])):

                # get the result by lane
                ret = case_data[2][0][lane_idx]

                idx_func = '0' if 'min' in case_data[0] else '1'

                # append assert
                if 'nan' in ret:

                    lst_diff_lane_vs_clause_assert.append(
                        tpl_assert.format(
                            assert_type='assert_return_canonical_nan',
                            func=tpl_func_by_lane.format(lane_idx),
                            operand_1=self.v128_const('f32x4',
                                                      case_data[1][0]),
                            operand_2=self.v128_const('f32x4',
                                                      case_data[1][1]),
                            operand_3=self.v128_const('i32', idx_func),
                            expected_result=''))
                else:

                    lst_diff_lane_vs_clause_assert.append(
                        tpl_assert.format(
                            assert_type='assert_return',
                            func=tpl_func_by_lane.format(lane_idx),
                            operand_1=self.v128_const('f32x4',
                                                      case_data[1][0]),
                            operand_2=self.v128_const('f32x4',
                                                      case_data[1][1]),
                            operand_3=self.v128_const('i32', idx_func),
                            expected_result='  ' +
                            self.v128_const('f32', ret) + '\n'))

            case_cnt += 1
            if case_cnt == 2:
                case_cnt = 0

        lst_diff_lane_vs_clause_assert.append('')

        # Add test for operations with constant operands
        for key in lst_oprt_with_const_assert:

            case_cnt = 0
            for case_data in lst_oprt_with_const_assert[key]:

                # Add comment for the param combination
                if case_cnt == 0:
                    template.append(';; {} const vs const'.format(op_name))
                if case_cnt == 4:
                    template.append(';; {} param vs const'.format(op_name))

                # Cross parameters and constants
                if case_cnt < 4:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0], [],
                                self.v128_const('f32x4', case_data[1]))))
                else:
                    template.append(
                        str(
                            AssertReturn(
                                case_data[0],
                                [self.v128_const('f32x4', case_data[1])],
                                self.v128_const('f32x4', case_data[2]))))
                case_cnt += 1

        # Generate and append f32x4.abs assert
        op_name = self.full_op_name('abs')
        func = "{}_with_const".format(op_name)
        template.append('')
        template.append(
            str(
                AssertReturn(func, [],
                             self.v128_const('f32x4', ['0', '1', '2', '3']))))

        template.extend(lst_diff_lane_vs_clause_assert)

        return template