scripts: test.py/bench.py: Allowed expressions in ifdefs/ifndefs

This extends our ifdef/ifndef test attributes to support more
complicated logic expressions.

So far we haven't really needed this (ifdef/ifndef accepts an implicitly
anded list, which has covered everything so far), but I realized there's
a simple trick to make this work.

For example, in test.toml:

  ifdef = 'A && !(B || C)'

Generated ifdef:

  #if (defined(A) && !(defined(B) || defined(C)))

This doesn't require complex parsing or anything, just a simple regex:

  s/[a-zA-Z_0-9]\+/defined(&)/g

Is using #if defined(A) everywhere instead of #ifdef A more expensive
for the compiler? Not sure. But it seems like we're heavily dominated by
the single-threaded link time, so I'm not sure we care.
This commit is contained in:
Christopher Haster
2026-01-03 01:03:00 -06:00
parent 35a1ac93fa
commit 0c6e455961
2 changed files with 60 additions and 20 deletions
+30 -10
View File
@@ -402,9 +402,13 @@ def compile(bench_paths, **args):
# write any ifdef prologues # write any ifdef prologues
if case.ifdef or case.ifndef: if case.ifdef or case.ifndef:
for ifdef in case.ifdef: for ifdef in case.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in case.ifndef: for ifndef in case.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# create case define functions # create case define functions
@@ -474,9 +478,13 @@ def compile(bench_paths, **args):
# write any ifdef prologues # write any ifdef prologues
if suite.ifdef or suite.ifndef: if suite.ifdef or suite.ifndef:
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# write any suite defines # write any suite defines
@@ -534,9 +542,13 @@ def compile(bench_paths, **args):
'BENCH_INTERNAL' if suite.internal else None])) 'BENCH_INTERNAL' if suite.internal else None]))
or 0)) or 0))
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln(4*' '+'#ifdef %s' % ifdef) f.writeln(4*' '+'#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln(4*' '+'#ifndef %s' % ifndef) f.writeln(4*' '+'#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
# create suite defines # create suite defines
if suite.defines: if suite.defines:
f.writeln(4*' '+'.defines = (const bench_define_t[]){') f.writeln(4*' '+'.defines = (const bench_define_t[]){')
@@ -562,9 +574,13 @@ def compile(bench_paths, **args):
else None])) else None]))
or 0)) or 0))
for ifdef in it.chain(suite.ifdef, case.ifdef): for ifdef in it.chain(suite.ifdef, case.ifdef):
f.writeln(12*' '+'#ifdef %s' % ifdef) f.writeln(12*' '+'#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in it.chain(suite.ifndef, case.ifndef): for ifndef in it.chain(suite.ifndef, case.ifndef):
f.writeln(12*' '+'#ifndef %s' % ifndef) f.writeln(12*' '+'#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
# create case defines # create case defines
if case.defines: if case.defines:
f.writeln(12*' '+'.defines' f.writeln(12*' '+'.defines'
@@ -633,9 +649,13 @@ def compile(bench_paths, **args):
# any ifdef prologues # any ifdef prologues
if suite.ifdef or suite.ifndef: if suite.ifdef or suite.ifndef:
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# any suite code # any suite code
+30 -10
View File
@@ -414,9 +414,13 @@ def compile(test_paths, **args):
# write any ifdef prologues # write any ifdef prologues
if case.ifdef or case.ifndef: if case.ifdef or case.ifndef:
for ifdef in case.ifdef: for ifdef in case.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in case.ifndef: for ifndef in case.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# create case define functions # create case define functions
@@ -486,9 +490,13 @@ def compile(test_paths, **args):
# write any ifdef prologues # write any ifdef prologues
if suite.ifdef or suite.ifndef: if suite.ifdef or suite.ifndef:
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# write any suite defines # write any suite defines
@@ -548,9 +556,13 @@ def compile(test_paths, **args):
'TEST_FUZZ' if suite.fuzz else None])) 'TEST_FUZZ' if suite.fuzz else None]))
or 0)) or 0))
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln(4*' '+'#ifdef %s' % ifdef) f.writeln(4*' '+'#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln(4*' '+'#ifndef %s' % ifndef) f.writeln(4*' '+'#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
# create suite defines # create suite defines
if suite.defines: if suite.defines:
f.writeln(4*' '+'.defines = (const test_define_t[]){') f.writeln(4*' '+'.defines = (const test_define_t[]){')
@@ -580,9 +592,13 @@ def compile(test_paths, **args):
else None])) else None]))
or 0)) or 0))
for ifdef in it.chain(suite.ifdef, case.ifdef): for ifdef in it.chain(suite.ifdef, case.ifdef):
f.writeln(12*' '+'#ifdef %s' % ifdef) f.writeln(12*' '+'#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in it.chain(suite.ifndef, case.ifndef): for ifndef in it.chain(suite.ifndef, case.ifndef):
f.writeln(12*' '+'#ifndef %s' % ifndef) f.writeln(12*' '+'#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
# create case defines # create case defines
if case.defines: if case.defines:
f.writeln(12*' '+'.defines' f.writeln(12*' '+'.defines'
@@ -651,9 +667,13 @@ def compile(test_paths, **args):
# any ifdef prologues # any ifdef prologues
if suite.ifdef or suite.ifndef: if suite.ifdef or suite.ifndef:
for ifdef in suite.ifdef: for ifdef in suite.ifdef:
f.writeln('#ifdef %s' % ifdef) f.writeln('#if (%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifdef))
for ifndef in suite.ifndef: for ifndef in suite.ifndef:
f.writeln('#ifndef %s' % ifndef) f.writeln('#if !(%s)' % re.sub(
'[a-zA-Z_0-9]+', 'defined(\g<0>)',
ifndef))
f.writeln() f.writeln()
# any suite code # any suite code