Skip to content

Commit

Permalink
Deprecate old void! @benchmark and @test functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Jan 9, 2025
1 parent c22b7d4 commit b941f93
Show file tree
Hide file tree
Showing 73 changed files with 994 additions and 866 deletions.
2 changes: 1 addition & 1 deletion benchmarks/stdlib/sort/quicksort.c3
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn void init() @init
set_benchmark_max_iterations(10_000);
}

fn void! quicksort_bench() @benchmark
fn void quicksort_bench() @benchmark
{
// test set: 500 numbers between 0 and 99;
int[] data = {
Expand Down
110 changes: 106 additions & 4 deletions lib/std/core/runtime.c3
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ struct SliceRaw
usz len;
}

def BenchmarkFn = fn void!();
def BenchmarkFn = fn void!() @if($$OLD_TEST);
def BenchmarkFn = fn void() @if(!$$OLD_TEST);

struct BenchmarkUnit
{
Expand Down Expand Up @@ -59,7 +60,7 @@ fn void set_benchmark_max_iterations(uint value) @builtin
benchmark_max_iterations = value;
}

fn bool run_benchmarks(BenchmarkUnit[] benchmarks)
fn bool run_benchmarks(BenchmarkUnit[] benchmarks) @if($$OLD_TEST)
{
int benchmarks_passed = 0;
int benchmark_count = benchmarks.len;
Expand Down Expand Up @@ -132,6 +133,62 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks)
return benchmark_count == benchmarks_passed;
}

fn bool run_benchmarks(BenchmarkUnit[] benchmarks) @if(!$$OLD_TEST)
{
usz max_name;

foreach (&unit : benchmarks)
{
if (max_name < unit.name.len) max_name = unit.name.len;
}

usz len = max_name + 9;

DString name = dstring::temp_with_capacity(64);
name.append_repeat('-', len / 2);
name.append(" BENCHMARKS ");
name.append_repeat('-', len - len / 2);

io::printn(name);

name.clear();

long sys_clock_started;
long sys_clock_finished;
long sys_clocks;
Clock clock;

foreach(unit : benchmarks)
{
defer name.clear();
name.appendf("Benchmarking %s ", unit.name);
name.append_repeat('.', max_name - unit.name.len + 2);
io::printf("%s ", name.str_view());

for (uint i = 0; i < benchmark_warmup_iterations; i++)
{
unit.func() @inline;
}

clock = std::time::clock::now();
sys_clock_started = $$sysclock();

for (uint i = 0; i < benchmark_max_iterations; i++)
{
unit.func() @inline;
}

sys_clock_finished = $$sysclock();
NanoDuration nano_seconds = clock.mark();
sys_clocks = sys_clock_finished - sys_clock_started;

io::printfn("[COMPLETE] %.2f ns, %.2f CPU's clocks", (float)nano_seconds / benchmark_max_iterations, (float)sys_clocks / benchmark_max_iterations);
}

io::printfn("\n%d benchmark%s run.\n", benchmarks.len, benchmarks.len > 1 ? "s" : "");
return true;
}

fn bool default_benchmark_runner()
{
@pool()
Expand All @@ -140,7 +197,8 @@ fn bool default_benchmark_runner()
};
}

def TestFn = fn void!();
def TestFn = fn void!() @if($$OLD_TEST);
def TestFn = fn void() @if(!$$OLD_TEST);

struct TestUnit
{
Expand Down Expand Up @@ -191,7 +249,7 @@ fn void test_panic(String message, String file, String function, uint line)
libc::longjmp(&test_context.buf, 1);
}

fn bool run_tests(TestUnit[] tests)
fn bool run_tests(TestUnit[] tests) @if($$OLD_TEST)
{
usz max_name;
foreach (&unit : tests)
Expand Down Expand Up @@ -239,6 +297,50 @@ fn bool run_tests(TestUnit[] tests)
return test_count == tests_passed;
}

fn bool run_tests(TestUnit[] tests) @if(!$$OLD_TEST)
{
usz max_name;
foreach (&unit : tests)
{
if (max_name < unit.name.len) max_name = unit.name.len;
}
quicksort(tests, &cmp_test_unit);

TestContext context;
test_context = &context;

PanicFn old_panic = builtin::panic;
defer builtin::panic = old_panic;
builtin::panic = &test_panic;
int tests_passed = 0;
int test_count = tests.len;
DString name = dstring::temp_with_capacity(64);
usz len = max_name + 9;
name.append_repeat('-', len / 2);
name.append(" TESTS ");
name.append_repeat('-', len - len / 2);
io::printn(name);
name.clear();
foreach(unit : tests)
{
defer name.clear();
name.appendf("Testing %s ", unit.name);
name.append_repeat('.', max_name - unit.name.len + 2);
io::printf("%s ", name.str_view());
(void)io::stdout().flush();
if (libc::setjmp(&context.buf) == 0)
{
unit.func();
io::printn("[ok]");
tests_passed++;
}
}
io::printfn("\n%d test%s run.\n", test_count, test_count > 1 ? "s" : "");
io::printfn("Test Result: %s. %d passed, %d failed.",
tests_passed < test_count ? "FAILED" : "ok", tests_passed, test_count - tests_passed);
return test_count == tests_passed;
}

fn bool default_test_runner()
{
@pool()
Expand Down
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- Improved `#foo` resolution inside of the compiler.
- Deprecated '&' macro arguments.
- Deprecate `fn void! main() type main functions.
- Deprecate old `void!` @benchmark and @test functions.

### Fixes
- Fix case trying to initialize a `char[*]*` from a String.
Expand Down
14 changes: 7 additions & 7 deletions resources/examples/benchmarks.c3
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import std::thread;

fn void! bench1() @benchmark
fn void bench1() @benchmark
{
return std::thread::sleep_ms(1);
std::thread::sleep_ms(1)!!;
}

fn void! bench123456789() @benchmark
fn void bench123456789() @benchmark
{
return std::thread::sleep_ms(2);
std::thread::sleep_ms(2)!!;
}

fn void! long_name_bench() @benchmark
fn void long_name_bench() @benchmark
{
return std::thread::sleep_ms(3);
std::thread::sleep_ms(3)!!;
}

fn void! very_long_name_bench() @benchmark
fn void very_long_name_bench() @benchmark
{
return std::thread::sleep_ms(10);
}
Expand Down
10 changes: 10 additions & 0 deletions src/build/build.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ typedef enum
SHOW_BACKTRACE_ON = 1
} ShowBacktrace;

typedef enum
{
OLD_TEST_NOT_SET = -1,
OLD_TEST_OFF = 0,
OLD_TEST_ON = 1
} OldTest;

typedef enum
{
SIZE_OPTIMIZATION_NOT_SET = -1,
Expand Down Expand Up @@ -471,6 +478,7 @@ typedef struct BuildOptions_
OptimizationSetting optsetting;
DebugInfo debug_info_override;
ShowBacktrace show_backtrace;
OldTest old_test;
ArchOsTarget arch_os_target_override;
SafetyLevel safety_level;
PanicLevel panic_level;
Expand Down Expand Up @@ -624,6 +632,7 @@ typedef struct
EmitStdlib emit_stdlib;
LinkLibc link_libc;
ShowBacktrace show_backtrace;
OldTest old_test;
StripUnused strip_unused;
DebugInfo debug_info;
MergeFunctions merge_functions;
Expand Down Expand Up @@ -705,6 +714,7 @@ static BuildTarget default_build_target = {
.arch_os_target = ARCH_OS_TARGET_DEFAULT,
.debug_info = DEBUG_INFO_NOT_SET,
.show_backtrace = SHOW_BACKTRACE_NOT_SET,
.old_test = OLD_TEST_NOT_SET,
.use_stdlib = USE_STDLIB_NOT_SET,
.link_libc = LINK_LIBC_NOT_SET,
.emit_stdlib = EMIT_STDLIB_NOT_SET,
Expand Down
7 changes: 7 additions & 0 deletions src/build/build_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ static void usage(bool full)
PRINTF(" --optsize=<option> - Code size optimization: none, small, tiny.");
PRINTF(" --single-module=<yes|no> - Compile all modules together, enables more inlining.");
PRINTF(" --show-backtrace=<yes|no> - Show detailed backtrace on segfaults.");
PRINTF(" --old-test-bench=<yes|no> - Allow benchmarks and tests to use the deprecated 'void!' returns.");
}
PRINTF("");
PRINTF(" -g - Emit debug info.");
Expand Down Expand Up @@ -691,6 +692,11 @@ static void parse_option(BuildOptions *options)
options->safety_level = (SafetyLevel)parse_multi_option(argopt, 2, on_off);
return;
}
if ((argopt = match_argopt("old-test-bench")))
{
options->old_test = (OldTest) parse_multi_option(argopt, 2, on_off);
return;
}
if ((argopt = match_argopt("show-backtrace")))
{
options->show_backtrace = (ShowBacktrace) parse_multi_option(argopt, 2, on_off);
Expand Down Expand Up @@ -1149,6 +1155,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
.safety_level = SAFETY_NOT_SET,
.panic_level = PANIC_NOT_SET,
.show_backtrace = SHOW_BACKTRACE_NOT_SET,
.old_test = OLD_TEST_NOT_SET,
.optlevel = OPTIMIZATION_NOT_SET,
.optsize = SIZE_OPTIMIZATION_NOT_SET,
.build_threads = cpus(),
Expand Down
1 change: 1 addition & 0 deletions src/build/builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
if (options->memory_environment != MEMORY_ENV_NOT_SET) target->memory_environment = options->memory_environment;
if (options->debug_info_override != DEBUG_INFO_NOT_SET) target->debug_info = options->debug_info_override;
if (options->show_backtrace != SHOW_BACKTRACE_NOT_SET) target->show_backtrace = options->show_backtrace;
if (options->old_test != OLD_TEST_NOT_SET) target->old_test = options->old_test;
if (options->arch_os_target_override != ARCH_OS_TARGET_DEFAULT) target->arch_os_target = options->arch_os_target_override;
if (options->reloc_model != RELOC_DEFAULT) target->reloc_model = options->reloc_model;
if (options->symtab_size) target->symtab_size = options->symtab_size;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,7 @@ void compile()
setup_bool_define("COMPILER_SAFE_MODE", safe_mode_enabled());
setup_bool_define("DEBUG_SYMBOLS", compiler.build.debug_info == DEBUG_INFO_FULL);
setup_bool_define("BACKTRACE", compiler.build.show_backtrace != SHOW_BACKTRACE_OFF);

setup_bool_define("OLD_TEST", compiler.build.old_test == OLD_TEST_ON);
#if LLVM_AVAILABLE
setup_int_define("LLVM_VERSION", llvm_version_major, type_int);
#else
Expand Down
29 changes: 18 additions & 11 deletions src/compiler/sema_decls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3509,34 +3509,41 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *era
if (is_test || is_benchmark || is_init_finalizer)
{
ASSERT0(!is_interface_method);
if (vec_size(sig->params))
unsigned params = vec_size(sig->params);
if (params)
{
RETURN_SEMA_ERROR(sig->params[0], "%s functions may not take any parameters.",
is_init_finalizer ? "'@init' and '@finalizer'" : "'@test' and '@benchmark'");
is_init_finalizer ? "'@init' and '@finalizer'" : "'@test' and '@benchmark'");
}
TypeInfo *rtype_info = type_infoptr(sig->rtype);
if (!sema_resolve_type_info(context, rtype_info, RESOLVE_TYPE_DEFAULT)) return false;
Type *rtype = rtype_info->type;
if (is_init_finalizer)
{
if (rtype->canonical != type_void)
if (!type_is_void(rtype))
{
RETURN_SEMA_ERROR(rtype_info, "'@init' and '@finalizer' functions may only return 'void'.");
}
goto CHECK_DONE;
}
else
if (compiler.build.old_test != OLD_TEST_ON)
{
if (type_no_optional(rtype) != type_void)
if (!type_is_void(rtype))
{
RETURN_SEMA_ERROR(rtype_info, "'@test' and '@benchmark' functions may only return 'void' or 'void!'.");
}
if (type_is_void(rtype))
{
rtype_info->type = type_get_optional(rtype);
RETURN_SEMA_ERROR(rtype_info, "'@test' and '@benchmark' function may only return 'void' you can allow 'void!' by passing in '--old-test-bench=yes'.");
}
goto CHECK_DONE;
}
if (!type_is_void(type_no_optional(rtype)))
{
RETURN_SEMA_ERROR(rtype_info, "'@test' and '@benchmark' function may only return 'void' or 'void!'.");
}
if (!type_is_optional(rtype))
{
rtype_info->type = type_get_optional(rtype);
}
}

CHECK_DONE:
decl->type = type_new_func(decl, sig);
if (!sema_analyse_function_signature(context, decl, type_infoptrzero(decl->func_decl.type_parent), sig->abi, sig)) return decl_poison(decl);
TypeInfo *rtype_info = type_infoptr(sig->rtype);
Expand Down
2 changes: 1 addition & 1 deletion test/unit/regression/bitstruct_ops.c3
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bitstruct Bar : char[13]
bool gh : 25;
}

fn void! test_bitops() @test
fn void test_bitops() @test
{
Foo f1 = { true, true };
Foo f2 = { true, false };
Expand Down
4 changes: 2 additions & 2 deletions test/unit/regression/bitstruct_ops2.c3
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bitstruct Bar : char[13]
bool gh;
}

fn void! test_bitops() @test
fn void test_bitops() @test
{
Foo f1 = { true, true };
Foo f2 = { true, false };
Expand Down Expand Up @@ -42,7 +42,7 @@ fn void! test_bitops() @test
assert(b3.z == true && b3.w == false && b3.gh == true);
}

fn void! test_bitops_const() @test
fn void test_bitops_const() @test
{
const Foo F1 = { true, true };
const Foo F2 = { true, false };
Expand Down
4 changes: 2 additions & 2 deletions test/unit/regression/ct_slice.c3
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module ct_slice @test;

fn void! slice_bytes()
fn void slice_bytes()
{
char[4] $a = x'aabbccdd';
var $b = $a[1..2];
Expand All @@ -9,7 +9,7 @@ fn void! slice_bytes()
assert(y == char[2] { 187, 204 });
}

fn void! slice_string()
fn void slice_string()
{
String $a = "abcd";
assert($a == "abcd");
Expand Down
Loading

0 comments on commit b941f93

Please sign in to comment.