1# Copyright 2017 The Meson development team
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6
7#     http://www.apache.org/licenses/LICENSE-2.0
8
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from .. import mesonlib, compilers, mlog
16
17from . import ExtensionModule
18
19from ..interpreterbase import FeatureNew
20
21class SimdModule(ExtensionModule):
22
23    @FeatureNew('SIMD module', '0.42.0')
24    def __init__(self, interpreter):
25        super().__init__(interpreter)
26        # FIXME add Altivec and AVX512.
27        self.isets = ('mmx',
28                      'sse',
29                      'sse2',
30                      'sse3',
31                      'ssse3',
32                      'sse41',
33                      'sse42',
34                      'avx',
35                      'avx2',
36                      'neon',
37                      )
38        self.methods.update({
39            'check': self.check,
40        })
41
42    def check(self, state, args, kwargs):
43        result = []
44        if len(args) != 1:
45            raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.')
46        prefix = args[0]
47        if not isinstance(prefix, str):
48            raise mesonlib.MesonException('Argument must be a string.')
49        if 'compiler' not in kwargs:
50            raise mesonlib.MesonException('Must specify compiler keyword')
51        if 'sources' in kwargs:
52            raise mesonlib.MesonException('SIMD module does not support the "sources" keyword')
53        basic_kwargs = {}
54        for key, value in kwargs.items():
55            if key not in self.isets and key != 'compiler':
56                basic_kwargs[key] = value
57        compiler = kwargs['compiler']
58        if not isinstance(compiler, compilers.compilers.Compiler):
59            raise mesonlib.MesonException('Compiler argument must be a compiler object.')
60        cdata = self.interpreter.func_configuration_data(None, [], {})
61        conf = cdata.conf_data
62        for iset in self.isets:
63            if iset not in kwargs:
64                continue
65            iset_fname = kwargs[iset] # Might also be an array or Files. static_library will validate.
66            args = compiler.get_instruction_set_args(iset)
67            if args is None:
68                mlog.log('Compiler supports %s:' % iset, mlog.red('NO'))
69                continue
70            if args:
71                if not compiler.has_multi_arguments(args, state.environment)[0]:
72                    mlog.log('Compiler supports %s:' % iset, mlog.red('NO'))
73                    continue
74            mlog.log('Compiler supports %s:' % iset, mlog.green('YES'))
75            conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset)
76            libname = prefix + '_' + iset
77            lib_kwargs = {'sources': iset_fname,
78                          }
79            lib_kwargs.update(basic_kwargs)
80            langarg_key = compiler.get_language() + '_args'
81            old_lang_args = mesonlib.extract_as_list(lib_kwargs, langarg_key)
82            all_lang_args = old_lang_args + args
83            lib_kwargs[langarg_key] = all_lang_args
84            result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs))
85        return [result, cdata]
86
87def initialize(*args, **kwargs):
88    return SimdModule(*args, **kwargs)
89