diff --git a/loopy/__init__.py b/loopy/__init__.py index d69a57bf1a5435adfb067df5cfb2080633cac765..a1c97d2f402656affabb97d1484dc34572240f39 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -142,7 +142,7 @@ from loopy.frontend.fortran import (c_preprocess, parse_transformed_fortran, parse_fortran) from loopy.target import TargetBase, ASTBuilderBase -from loopy.target.c import CTarget, ExecutableCTarget, generate_header +from loopy.target.c import CFamilyTarget, CTarget, ExecutableCTarget, generate_header from loopy.target.cuda import CudaTarget from loopy.target.opencl import OpenCLTarget from loopy.target.pyopencl import PyOpenCLTarget @@ -271,7 +271,7 @@ __all__ = [ "LoopyError", "LoopyWarning", "TargetBase", - "CTarget", "ExecutableCTarget", "generate_header", + "CFamilyTarget", "CTarget", "ExecutableCTarget", "generate_header", "CudaTarget", "OpenCLTarget", "PyOpenCLTarget", "ISPCTarget", "NumbaTarget", "NumbaCudaTarget", diff --git a/loopy/kernel/array.py b/loopy/kernel/array.py index 3588f38af13479b127208c25735f1046eaa82706..84b0a4a74bdc0e4dc32b5823c50a4a9c0a8d9f25 100644 --- a/loopy/kernel/array.py +++ b/loopy/kernel/array.py @@ -619,7 +619,7 @@ class ArrayBase(ImmutableRecord): If an integer N is given, the array would be declared with ``__attribute__((aligned(N)))`` in code generation for - :class:`loopy.CTarget`. + :class:`loopy.CFamilyTarget`. .. versionadded:: 2018.1 diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index 2658b8cd743d335323dab7dd9aebd82ef5830652..53d05a28e7245e381be769af12d6066ffb486541 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -448,8 +448,8 @@ def parse_reduction_op(name): def reduction_function_mangler(kernel, func_id, arg_dtypes): if isinstance(func_id, ArgExtOp): - from loopy.target.opencl import CTarget - if not isinstance(kernel.target, CTarget): + from loopy.target.opencl import CFamilyTarget + if not isinstance(kernel.target, CFamilyTarget): raise LoopyError("%s: only C-like targets supported for now" % func_id) op = func_id.reduction_op @@ -470,8 +470,8 @@ def reduction_function_mangler(kernel, func_id, arg_dtypes): ) elif isinstance(func_id, SegmentedOp): - from loopy.target.opencl import CTarget - if not isinstance(kernel.target, CTarget): + from loopy.target.opencl import CFamilyTarget + if not isinstance(kernel.target, CFamilyTarget): raise LoopyError("%s: only C-like targets supported for now" % func_id) op = func_id.reduction_op diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index a81354e2fd7b52ba514af936441c7a2d980c77b5..73d2a6328af87cb51fb90d43efcde34d39aa8299 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -31,6 +31,7 @@ __doc__ = """ .. autoclass:: TargetBase .. autoclass:: ASTBuilderBase +.. autoclass:: CFamilyTarget .. autoclass:: CTarget .. autoclass:: ExecutableCTarget .. autoclass:: CudaTarget diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index 25b190809fdc38341c811ede15a8baae693a3116..6e3602eda11d5f65e8a6af2977966e946c72a718 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -77,6 +77,11 @@ class DTypeRegistryWrapper(object): # {{{ preamble generator +def c99_preamble_generator(preamble_info): + if any(dtype.is_integral() for dtype in preamble_info.seen_dtypes): + yield("10_stdint", "#include ") + + def _preamble_generator(preamble_info): integer_type_names = ["int8", "int16", "int32", "int64"] @@ -314,8 +319,10 @@ class CExpression(object): # }}} -class CTarget(TargetBase): - """A target for plain "C", without any parallel extensions. +class CFamilyTarget(TargetBase): + """A target for "least-common denominator C", without any parallel + extensions, and without use of any C99 specifics. Intended to be + usable as a common base for C99, C++, OpenCL, CUDA, and the like. """ hash_fields = TargetBase.hash_fields + ("fortran_abi",) @@ -323,7 +330,7 @@ class CTarget(TargetBase): def __init__(self, fortran_abi=False): self.fortran_abi = fortran_abi - super(CTarget, self).__init__() + super(CFamilyTarget, self).__init__() def split_kernel_at_global_barriers(self): return False @@ -332,7 +339,7 @@ class CTarget(TargetBase): return DummyHostASTBuilder(self) def get_device_ast_builder(self): - return CASTBuilder(self) + return CFamilyASTBuilder(self) # {{{ types @@ -368,29 +375,6 @@ class CTarget(TargetBase): # }}} -# {{{ executable c target - -class ExecutableCTarget(CTarget): - """ - An executable CTarget that uses (by default) JIT compilation of C-code - """ - - def __init__(self, compiler=None, fortran_abi=False): - super(ExecutableCTarget, self).__init__(fortran_abi=fortran_abi) - from loopy.target.c.c_execution import CCompiler - self.compiler = compiler or CCompiler() - - def get_kernel_executor(self, knl, *args, **kwargs): - from loopy.target.c.c_execution import CKernelExecutor - return CKernelExecutor(knl, compiler=self.compiler) - - def get_host_ast_builder(self): - # enable host code generation - return CASTBuilder(self) - -# }}} - - class _ConstRestrictPointer(Pointer): def get_decl_pair(self): sub_tp, sub_decl = self.subdecl.get_decl_pair() @@ -484,24 +468,24 @@ def c_math_mangler(target, name, arg_dtypes, modify_name=True): # }}} -class CASTBuilder(ASTBuilderBase): +class CFamilyASTBuilder(ASTBuilderBase): # {{{ library def function_manglers(self): return ( - super(CASTBuilder, self).function_manglers() + [ + super(CFamilyASTBuilder, self).function_manglers() + [ c_math_mangler ]) def symbol_manglers(self): return ( - super(CASTBuilder, self).symbol_manglers() + [ + super(CFamilyASTBuilder, self).symbol_manglers() + [ c_symbol_mangler ]) def preamble_generators(self): return ( - super(CASTBuilder, self).preamble_generators() + [ + super(CFamilyASTBuilder, self).preamble_generators() + [ _preamble_generator, ]) @@ -1064,7 +1048,7 @@ def generate_header(kernel, codegen_result=None): functions. """ - if not isinstance(kernel.target, CTarget): + if not isinstance(kernel.target, CFamilyTarget): raise LoopyError( 'Header generation for non C-based languages are not implemented') @@ -1080,4 +1064,57 @@ def generate_header(kernel, codegen_result=None): # }}} + +# {{{ C99 target + +class CTarget(CFamilyTarget): + """This target may emit code using all features of C99. + For a target base supporting "least-common-denominator" C, + see :class:`CFamilyTarget`. + """ + + def get_device_ast_builder(self): + return CASTBuilder(self) + + @memoize_method + def get_dtype_registry(self): + from loopy.target.c.compyte.dtypes import ( + DTypeRegistry, fill_registry_with_c99_stdint_types) + result = DTypeRegistry() + fill_registry_with_c99_stdint_types(result) + return DTypeRegistryWrapper(result) + + +class CASTBuilder(CFamilyASTBuilder): + def preamble_generators(self): + return ( + super(CASTBuilder, self).preamble_generators() + [ + c99_preamble_generator, + ]) + +# }}} + + +# {{{ executable c target + +class ExecutableCTarget(CTarget): + """ + An executable CFamilyTarget that uses (by default) JIT compilation of C-code + """ + + def __init__(self, compiler=None, fortran_abi=False): + super(ExecutableCTarget, self).__init__(fortran_abi=fortran_abi) + from loopy.target.c.c_execution import CCompiler + self.compiler = compiler or CCompiler() + + def get_kernel_executor(self, knl, *args, **kwargs): + from loopy.target.c.c_execution import CKernelExecutor + return CKernelExecutor(knl, compiler=self.compiler) + + def get_host_ast_builder(self): + # enable host code generation + return CFamilyASTBuilder(self) + +# }}} + # vim: foldmethod=marker diff --git a/loopy/target/c/c_execution.py b/loopy/target/c/c_execution.py index 60947c7f77d09582868304ded121386bbb3aab68..698507978f7c20d6d594fd3e03626e7b12012a94 100644 --- a/loopy/target/c/c_execution.py +++ b/loopy/target/c/c_execution.py @@ -306,7 +306,8 @@ class IDIToCDLL(object): """ def __init__(self, target): self.target = target - self.registry = target.get_dtype_registry().wrapped_registry + from loopy.target.c import CFamilyTarget + self.registry = CFamilyTarget().get_dtype_registry().wrapped_registry def __call__(self, knl, idi): # next loop through the implemented data info to get the arg data diff --git a/loopy/target/c/compyte b/loopy/target/c/compyte index 11dc00352423cddd71f09e809d0a22ab1c3ea7a5..25ee8b48fd0c7d9f0bd987c6862cdb1884fb1372 160000 --- a/loopy/target/c/compyte +++ b/loopy/target/c/compyte @@ -1 +1 @@ -Subproject commit 11dc00352423cddd71f09e809d0a22ab1c3ea7a5 +Subproject commit 25ee8b48fd0c7d9f0bd987c6862cdb1884fb1372 diff --git a/loopy/target/cuda.py b/loopy/target/cuda.py index 8f14738c307ce7f2d98a47ef0dc086b4c69f7910..50fd1026f7bd15ce72915d0d5d5e60f6da4e264c 100644 --- a/loopy/target/cuda.py +++ b/loopy/target/cuda.py @@ -28,7 +28,7 @@ import numpy as np from pytools import memoize_method -from loopy.target.c import CTarget, CASTBuilder +from loopy.target.c import CFamilyTarget, CFamilyASTBuilder from loopy.target.c.codegen.expression import ExpressionToCExpressionMapper from loopy.diagnostic import LoopyError from loopy.types import NumpyType @@ -169,7 +169,7 @@ class ExpressionToCudaCExpressionMapper(ExpressionToCExpressionMapper): # {{{ target -class CudaTarget(CTarget): +class CudaTarget(CFamilyTarget): """A target for Nvidia's CUDA GPU programming language.""" def __init__(self, extern_c=True): @@ -216,7 +216,7 @@ class CudaTarget(CTarget): # {{{ ast builder -class CUDACASTBuilder(CASTBuilder): +class CUDACASTBuilder(CFamilyASTBuilder): # {{{ library def function_manglers(self): diff --git a/loopy/target/ispc.py b/loopy/target/ispc.py index cccee2301e44b16e2454bda5e98af7db7893c003..eb0157bf86d478901fb5a07bbac28aa7a11bcec9 100644 --- a/loopy/target/ispc.py +++ b/loopy/target/ispc.py @@ -26,7 +26,7 @@ THE SOFTWARE. import numpy as np # noqa -from loopy.target.c import CTarget, CASTBuilder +from loopy.target.c import CFamilyTarget, CFamilyASTBuilder from loopy.target.c.codegen.expression import ExpressionToCExpressionMapper from loopy.diagnostic import LoopyError from loopy.symbolic import Literal @@ -154,7 +154,7 @@ def fill_registry_with_ispc_types(reg, respect_windows, include_bool=True): # }}} -class ISPCTarget(CTarget): +class ISPCTarget(CFamilyTarget): """A code generation target for Intel's `ISPC `_ SPMD programming language, to target Intel's Knight's hardware and modern Intel CPUs with wide vector units. @@ -200,7 +200,7 @@ class ISPCTarget(CTarget): # }}} -class ISPCASTBuilder(CASTBuilder): +class ISPCASTBuilder(CFamilyASTBuilder): def _arg_names_and_decls(self, codegen_state): implemented_data_info = codegen_state.implemented_data_info arg_names = [iai.name for iai in implemented_data_info] diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 8a6e5284258d864d19d7f1353ec9dfaaa7d72a9b..04d436043daed74362ebabd96e18bf1d4d6d4a6c 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -26,7 +26,7 @@ THE SOFTWARE. import numpy as np -from loopy.target.c import CTarget, CASTBuilder +from loopy.target.c import CFamilyTarget, CFamilyASTBuilder from loopy.target.c.codegen.expression import ExpressionToCExpressionMapper from pytools import memoize_method from loopy.diagnostic import LoopyError @@ -304,7 +304,7 @@ class ExpressionToOpenCLCExpressionMapper(ExpressionToCExpressionMapper): # {{{ target -class OpenCLTarget(CTarget): +class OpenCLTarget(CFamilyTarget): """A target for the OpenCL C heterogeneous compute programming language. """ @@ -362,7 +362,7 @@ class OpenCLTarget(CTarget): # {{{ ast builder -class OpenCLCASTBuilder(CASTBuilder): +class OpenCLCASTBuilder(CFamilyASTBuilder): # {{{ library def function_manglers(self):