Update starch to upstream commit f76162205fa082d4c9a75b89eb4295e03f5f68fd

This commit is contained in:
Oliver Jowett 2021-02-09 14:05:05 +08:00
parent 270c629515
commit fa80e7c917
8 changed files with 76 additions and 51 deletions

View File

@ -425,15 +425,15 @@ static void starch_benchmark_usage(const char *argv0)
" (default: benchmark all functions)\n" " (default: benchmark all functions)\n"
"\n" "\n"
"Supported flavors: " "Supported flavors: "
#ifdef STARCH_FLAVOR_GENERIC
"generic "
#endif
#ifdef STARCH_FLAVOR_ARMV7A_VFPV3 #ifdef STARCH_FLAVOR_ARMV7A_VFPV3
"armv7a_vfpv3 " "armv7a_vfpv3 "
#endif #endif
#ifdef STARCH_FLAVOR_ARMV7A_VFPV4 #ifdef STARCH_FLAVOR_ARMV7A_VFPV4
"armv7a_vfpv4 " "armv7a_vfpv4 "
#endif #endif
#ifdef STARCH_FLAVOR_GENERIC
"generic "
#endif
#ifdef STARCH_FLAVOR_X86_64_AVX #ifdef STARCH_FLAVOR_X86_64_AVX
"x86_64_avx " "x86_64_avx "
#endif #endif

View File

@ -73,12 +73,6 @@ void starch_subtract_n_set_wisdom (const char * const * received_wisdom)
starch_subtract_n_regentry starch_subtract_n_registry[] = { starch_subtract_n_regentry starch_subtract_n_registry[] = {
#ifdef STARCH_MIX_GENERIC
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_GENERIC */
#ifdef STARCH_MIX_ARM #ifdef STARCH_MIX_ARM
{ 0, "neon_intrinsics_armv7a_vfpv4", "armv7a_vfpv4", starch_subtract_n_neon_intrinsics_armv7a_vfpv4, supports_neon_vfpv4 }, { 0, "neon_intrinsics_armv7a_vfpv4", "armv7a_vfpv4", starch_subtract_n_neon_intrinsics_armv7a_vfpv4, supports_neon_vfpv4 },
{ 1, "neon_intrinsics_armv7a_vfpv3", "armv7a_vfpv3", starch_subtract_n_neon_intrinsics_armv7a_vfpv3, supports_neon_vfpv3 }, { 1, "neon_intrinsics_armv7a_vfpv3", "armv7a_vfpv3", starch_subtract_n_neon_intrinsics_armv7a_vfpv3, supports_neon_vfpv3 },
@ -93,6 +87,12 @@ starch_subtract_n_regentry starch_subtract_n_registry[] = {
{ 10, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL }, { 10, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_ARM */ #endif /* STARCH_MIX_ARM */
#ifdef STARCH_MIX_GENERIC
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_GENERIC */
#ifdef STARCH_MIX_X86_64 #ifdef STARCH_MIX_X86_64
{ 0, "generic_x86_64_avx2", "x86_64_avx2", starch_subtract_n_generic_x86_64_avx2, supports_x86_avx2 }, { 0, "generic_x86_64_avx2", "x86_64_avx2", starch_subtract_n_generic_x86_64_avx2, supports_x86_avx2 },
{ 1, "generic_x86_64_avx", "x86_64_avx", starch_subtract_n_generic_x86_64_avx, supports_x86_avx }, { 1, "generic_x86_64_avx", "x86_64_avx", starch_subtract_n_generic_x86_64_avx, supports_x86_avx },
@ -161,12 +161,6 @@ void starch_subtract_n_aligned_set_wisdom (const char * const * received_wisdom)
starch_subtract_n_aligned_regentry starch_subtract_n_aligned_registry[] = { starch_subtract_n_aligned_regentry starch_subtract_n_aligned_registry[] = {
#ifdef STARCH_MIX_GENERIC
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_GENERIC */
#ifdef STARCH_MIX_ARM #ifdef STARCH_MIX_ARM
{ 0, "generic_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_generic_armv7a_vfpv4, supports_neon_vfpv4 }, { 0, "generic_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_generic_armv7a_vfpv4, supports_neon_vfpv4 },
{ 1, "unroll_4_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_unroll_4_armv7a_vfpv4, supports_neon_vfpv4 }, { 1, "unroll_4_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_unroll_4_armv7a_vfpv4, supports_neon_vfpv4 },
@ -189,6 +183,12 @@ starch_subtract_n_aligned_regentry starch_subtract_n_aligned_registry[] = {
{ 18, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL }, { 18, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_ARM */ #endif /* STARCH_MIX_ARM */
#ifdef STARCH_MIX_GENERIC
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
#endif /* STARCH_MIX_GENERIC */
#ifdef STARCH_MIX_X86_64 #ifdef STARCH_MIX_X86_64
{ 0, "generic_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_generic_x86_64_avx2, supports_x86_avx2 }, { 0, "generic_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_generic_x86_64_avx2, supports_x86_avx2 },
{ 1, "unroll_4_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_unroll_4_x86_64_avx2, supports_x86_avx2 }, { 1, "unroll_4_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_unroll_4_x86_64_avx2, supports_x86_avx2 },

View File

@ -5,12 +5,6 @@
/* mixes */ /* mixes */
/* Generic build, compiler defaults only */
#ifdef STARCH_MIX_GENERIC
#define STARCH_FLAVOR_GENERIC
#define STARCH_MIX_ALIGNMENT 1
#endif /* STARCH_MIX_GENERIC */
/* ARM */ /* ARM */
#ifdef STARCH_MIX_ARM #ifdef STARCH_MIX_ARM
#define STARCH_FLAVOR_ARMV7A_VFPV4 #define STARCH_FLAVOR_ARMV7A_VFPV4
@ -19,6 +13,12 @@
#define STARCH_MIX_ALIGNMENT 16 #define STARCH_MIX_ALIGNMENT 16
#endif /* STARCH_MIX_ARM */ #endif /* STARCH_MIX_ARM */
/* Generic build, compiler defaults only */
#ifdef STARCH_MIX_GENERIC
#define STARCH_FLAVOR_GENERIC
#define STARCH_MIX_ALIGNMENT 1
#endif /* STARCH_MIX_GENERIC */
/* x64-64 */ /* x64-64 */
#ifdef STARCH_MIX_X86_64 #ifdef STARCH_MIX_X86_64
#define STARCH_FLAVOR_X86_64_AVX2 #define STARCH_FLAVOR_X86_64_AVX2
@ -71,14 +71,6 @@ void starch_subtract_n_aligned_set_wisdom( const char * const * received_wisdom
/* flavors and prototypes */ /* flavors and prototypes */
#ifdef STARCH_FLAVOR_GENERIC
void starch_subtract_n_generic_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
void starch_subtract_n_unroll_4_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
void starch_subtract_n_bad_implementation_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
#endif /* STARCH_FLAVOR_GENERIC */
int starch_read_wisdom (const char * path);
#ifdef STARCH_FLAVOR_ARMV7A_VFPV3 #ifdef STARCH_FLAVOR_ARMV7A_VFPV3
int supports_neon_vfpv3 (void); int supports_neon_vfpv3 (void);
void starch_subtract_n_generic_armv7a_vfpv3 ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 ); void starch_subtract_n_generic_armv7a_vfpv3 ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
@ -107,6 +99,14 @@ void starch_subtract_n_aligned_neon_intrinsics_armv7a_vfpv4 ( const uint16_t * a
int starch_read_wisdom (const char * path); int starch_read_wisdom (const char * path);
#ifdef STARCH_FLAVOR_GENERIC
void starch_subtract_n_generic_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
void starch_subtract_n_unroll_4_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
void starch_subtract_n_bad_implementation_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
#endif /* STARCH_FLAVOR_GENERIC */
int starch_read_wisdom (const char * path);
#ifdef STARCH_FLAVOR_X86_64_AVX #ifdef STARCH_FLAVOR_X86_64_AVX
int supports_x86_avx (void); int supports_x86_avx (void);
void starch_subtract_n_generic_x86_64_avx ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 ); void starch_subtract_n_generic_x86_64_avx ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );

View File

@ -8,8 +8,9 @@ import sys
import re import re
import os import os
import mako.lookup import mako.lookup
from functools import total_ordering
from typing import Optional, Union, Iterable, Sequence, MutableSequence, Mapping, MutableMapping, FrozenSet from typing import Optional, Union, Iterable, Sequence, MutableSequence, Mapping, MutableMapping, FrozenSet, Dict, List
class Feature(object): class Feature(object):
"""Feature represents a type of code that can only be built with """Feature represents a type of code that can only be built with
@ -35,7 +36,7 @@ themselves using the STARCH_IMPL_REQUIRES macro."""
def macro(self) -> str: def macro(self) -> str:
return 'STARCH_FEATURE_' + self.name.upper() return 'STARCH_FEATURE_' + self.name.upper()
@total_ordering
class BuildFlavor(object): class BuildFlavor(object):
"""BuildFlavor models code built with specific compiler flags. """BuildFlavor models code built with specific compiler flags.
Shared implementation code will be built multiple times, once per flavor. Shared implementation code will be built multiple times, once per flavor.
@ -89,7 +90,13 @@ intrinsics)"""
def cflags(self) -> str: def cflags(self) -> str:
return ' '.join(self.compile_flags) return ' '.join(self.compile_flags)
def __lt__(self, other: object) -> bool:
if not isinstance(other, BuildFlavor):
return NotImplemented
return self.name < other.name
@total_ordering
class Function(object): class Function(object):
"""A user-callable function that will be dispatched to """A user-callable function that will be dispatched to
one of the many possible implementations based on runtime feature one of the many possible implementations based on runtime feature
@ -175,6 +182,11 @@ support."""
def benchmark_verify_symbol(self) -> str: def benchmark_verify_symbol(self) -> str:
return self.gen.sym(self.name + '_benchmark_verify') return self.gen.sym(self.name + '_benchmark_verify')
def __lt__(self, other: object) -> bool:
if not isinstance(other, Function):
return NotImplemented
return self.name < other.name
class FunctionImpl(object): class FunctionImpl(object):
"""A possible implementation of a function, not built in any particular way yet.""" """A possible implementation of a function, not built in any particular way yet."""
@ -210,6 +222,7 @@ class FunctionImpl(object):
return self.gen.sym(self.function.name + '_' + self.name + '_' + flavor.name) return self.gen.sym(self.function.name + '_' + self.name + '_' + flavor.name)
@total_ordering
class SourceFile(object): class SourceFile(object):
"""A scanned source file that contains implementation code.""" """A scanned source file that contains implementation code."""
@ -220,7 +233,13 @@ class SourceFile(object):
self.path = path self.path = path
self.impls = [] self.impls = []
def __lt__(self, other: object) -> bool:
if not isinstance(other, SourceFile):
return NotImplemented
return self.path < other.path
@total_ordering
class BuildMix(object): class BuildMix(object):
"""A combination of build flavors that make up one possible way of building all """A combination of build flavors that make up one possible way of building all
the code. The output of a mix is a library that dispatches functions within the the code. The output of a mix is a library that dispatches functions within the
@ -254,6 +273,12 @@ specified first."""
def function_wisdom(self, function) -> Sequence[str]: def function_wisdom(self, function) -> Sequence[str]:
return self.wisdom.get(function, []) return self.wisdom.get(function, [])
def __lt__(self, other: object) -> bool:
if not isinstance(other, BuildMix):
return NotImplemented
return self.name < other.name
class Generator(object): class Generator(object):
functions: MutableMapping[str, Function] functions: MutableMapping[str, Function]
features: MutableMapping[str, Feature] features: MutableMapping[str, Feature]
@ -380,8 +405,8 @@ class Generator(object):
return key return key
return self.flavors[key] return self.flavors[key]
def load_wisdom(self, path: str) -> Mapping[str,Sequence[str]]: def load_wisdom(self, path: str) -> Mapping[Function,Sequence[str]]:
results: Mapping[Function,Sequence[str]] = {} results: Dict[Function,List[str]] = {}
try: try:
f = open(path, 'r') f = open(path, 'r')
@ -420,7 +445,7 @@ class Generator(object):
if wisdom_file: if wisdom_file:
resolved_wisdom = self.load_wisdom(wisdom_file) resolved_wisdom = self.load_wisdom(wisdom_file)
else: else:
resolved_wisdom = dict( (self.get_function(name), values) for name,values in wisdom.items() ) resolved_wisdom = dict( (self.get_function(name), list(values)) for name,values in wisdom.items() )
self.mixes[name] = BuildMix(name, description, resolved_flavors, resolved_wisdom) self.mixes[name] = BuildMix(name, description, resolved_flavors, resolved_wisdom)
def sym(self, symbol: str) -> str: def sym(self, symbol: str) -> str:

View File

@ -115,7 +115,7 @@ static bool starch_benchmark_flavor_in_list(const char *flavor, const starch_ben
} }
<% functions_to_benchmark = [f for f in gen.functions.values() if f.benchmark] %> <% functions_to_benchmark = [f for f in gen.functions.values() if f.benchmark] %>
% for function in functions_to_benchmark: % for function in sorted(functions_to_benchmark):
/* prototypes for benchmark helpers provided by user code */ /* prototypes for benchmark helpers provided by user code */
void ${function.benchmark_symbol} (void); void ${function.benchmark_symbol} (void);
% if function.benchmark_verify: % if function.benchmark_verify:
@ -252,7 +252,7 @@ static void starch_benchmark_run_${function.name}( ${function.declaration_arglis
#define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(1, alignof(_type), (_count) * sizeof(_type))) #define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(1, alignof(_type), (_count) * sizeof(_type)))
#define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr) #define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr)
% for source in gen.benchmark_files: % for source in sorted(gen.benchmark_files):
#include "${os.path.relpath(source.path, current_dir)}" #include "${os.path.relpath(source.path, current_dir)}"
% endfor % endfor
@ -278,13 +278,13 @@ static void starch_benchmark_run_${function.name}( ${function.declaration_arglis
#define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(STARCH_MIX_ALIGNMENT, alignof(_type), (_count) * sizeof(_type))) #define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(STARCH_MIX_ALIGNMENT, alignof(_type), (_count) * sizeof(_type)))
#define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr) #define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr)
% for source in gen.benchmark_files: % for source in sorted(gen.benchmark_files):
% if any( (function.aligned and function.benchmark == source) for function in gen.functions.values() ): % if any( (function.aligned and function.benchmark == source) for function in gen.functions.values() ):
#include "${os.path.relpath(source.path, current_dir)}" #include "${os.path.relpath(source.path, current_dir)}"
% endif % endif
% endfor % endfor
% for function in functions_to_benchmark: % for function in sorted(functions_to_benchmark):
static void starch_benchmark_all_${function.name}(void) static void starch_benchmark_all_${function.name}(void)
{ {
fprintf(stderr, "==== ${function.name} ===\n"); fprintf(stderr, "==== ${function.name} ===\n");
@ -330,14 +330,14 @@ static void starch_benchmark_usage(const char *argv0)
" (default: benchmark all functions)\n" " (default: benchmark all functions)\n"
"\n" "\n"
"Supported flavors: " "Supported flavors: "
% for flavor in gen.flavors.values(): % for flavor in sorted(gen.flavors.values()):
#ifdef ${flavor.macro} #ifdef ${flavor.macro}
"${flavor.name} " "${flavor.name} "
#endif #endif
% endfor % endfor
"\n" "\n"
"Supported functions: " "Supported functions: "
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
"${function.name} " "${function.name} "
% endfor % endfor
"\n", argv0); "\n", argv0);
@ -425,7 +425,7 @@ int main(int argc, char **argv)
} }
for (int i = optind; i < argc; ++i) { for (int i = optind; i < argc; ++i) {
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
if (!strcmp(argv[i], "${function.name}")) { if (!strcmp(argv[i], "${function.name}")) {
specific = 1; specific = 1;
% if function.benchmark: % if function.benchmark:
@ -443,7 +443,7 @@ int main(int argc, char **argv)
} }
if (!specific) { if (!specific) {
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
% if function.benchmark: % if function.benchmark:
starch_benchmark_all_${function.name}(); starch_benchmark_all_${function.name}();
% else: % else:

View File

@ -22,7 +22,7 @@ static int starch_regentry_rank_compare (const void *l, const void *r)
return left->rank - right->rank; return left->rank - right->rank;
} }
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
/* dispatcher / registry for ${function.name} */ /* dispatcher / registry for ${function.name} */
${function.regentry_type} * ${function.select_symbol}() { ${function.regentry_type} * ${function.select_symbol}() {
@ -80,7 +80,7 @@ void ${function.set_wisdom_symbol} (const char * const * received_wisdom)
} }
${function.regentry_type} ${function.registry_symbol}[] = { ${function.regentry_type} ${function.registry_symbol}[] = {
% for mix in gen.mixes.values(): % for mix in sorted(gen.mixes.values()):
<% <%
# gather all implementations for this mix, sort by wisdom # gather all implementations for this mix, sort by wisdom
def rank_key(value, wisdom=mix.function_wisdom(function)): def rank_key(value, wisdom=mix.function_wisdom(function)):
@ -128,7 +128,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
return -1; return -1;
/* reset all ranks to identify entries not listed in the wisdom file; we'll assign ranks at the end to produce a stable sort */ /* reset all ranks to identify entries not listed in the wisdom file; we'll assign ranks at the end to produce a stable sort */
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
int rank_${function.name} = 0; int rank_${function.name} = 0;
for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) { for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) {
entry->rank = 0; entry->rank = 0;
@ -167,7 +167,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
*end = 0; *end = 0;
/* try to find a matching registry entry */ /* try to find a matching registry entry */
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
if (!strcmp(name, "${function.name}")) { if (!strcmp(name, "${function.name}")) {
for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) { for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) {
if (!strcmp(impl, entry->name)) { if (!strcmp(impl, entry->name)) {
@ -188,7 +188,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
fclose(fp); fclose(fp);
/* assign ranks to unmatched items to (stable) sort them last; re-sort everything */ /* assign ranks to unmatched items to (stable) sort them last; re-sort everything */
% for function in gen.functions.values(): % for function in sorted(gen.functions.values()):
{ {
${function.regentry_type} *entry; ${function.regentry_type} *entry;
for (entry = ${function.registry_symbol}; entry->name; ++entry) { for (entry = ${function.registry_symbol}; entry->name; ++entry) {

View File

@ -19,7 +19,7 @@
#define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _ ## _impl ## _ ## ${flavor.name} #define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _ ## _impl ## _ ## ${flavor.name}
#define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl) #define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl)
% for source in gen.impl_files: % for source in sorted(gen.impl_files):
% if any( ((impl.feature is None or impl.feature in flavor.features) and not impl.function.aligned) for impl in source.impls): % if any( ((impl.feature is None or impl.feature in flavor.features) and not impl.function.aligned) for impl in source.impls):
#include "${os.path.relpath(source.path, current_dir)}" #include "${os.path.relpath(source.path, current_dir)}"
% endif % endif
@ -39,7 +39,7 @@
#define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _aligned_ ## _impl ## _ ## ${flavor.name} #define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _aligned_ ## _impl ## _ ## ${flavor.name}
#define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl) #define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl)
% for source in gen.impl_files: % for source in sorted(gen.impl_files):
% if any( ((impl.feature is None or impl.feature in flavor.features) and impl.function.aligned) for impl in source.impls): % if any( ((impl.feature is None or impl.feature in flavor.features) and impl.function.aligned) for impl in source.impls):
#include "${os.path.relpath(source.path, current_dir)}" #include "${os.path.relpath(source.path, current_dir)}"
% endif % endif

View File

@ -10,7 +10,7 @@
/* mixes */ /* mixes */
% for mix in gen.mixes.values(): % for mix in sorted(gen.mixes.values()):
/* ${mix.description} */ /* ${mix.description} */
#ifdef ${mix.macro} #ifdef ${mix.macro}
% for flavor in mix.flavors: % for flavor in mix.flavors:
@ -51,7 +51,7 @@ void ${function.set_wisdom_symbol}( const char * const * received_wisdom );
% endfor % endfor
/* flavors and prototypes */ /* flavors and prototypes */
% for flavor in gen.flavors.values(): % for flavor in sorted(gen.flavors.values()):
#ifdef ${flavor.macro} #ifdef ${flavor.macro}
% if flavor.test_function is not None: % if flavor.test_function is not None:
int ${flavor.test_function} (void); int ${flavor.test_function} (void);