From 2018fa277c794bfb2dbb10e3fb7c203e8949b189 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Thu, 10 Oct 2024 17:30:16 -0700 Subject: [PATCH] Use a trampoline if musttail not available For the previous approach to work, we would have had to lock in the generated code for every function that needs to make tail calls in assembly. --- ConflictSet.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 8b153b7..4c418c0 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -3260,35 +3260,28 @@ struct CheckContext { ConflictSet::Result *results; int64_t started; ReadContext *tls; +#if !__has_attribute(musttail) + CheckJob *job; + bool done; +#endif }; -#if __has_attribute(musttail) FLATTEN PRESERVE_NONE void keepGoing(CheckJob *job, CheckContext *context) { +#if __has_attribute(musttail) job = job->next; MUSTTAIL return job->continuation(job, context); +#else + context->job = job->next; + return; +#endif } -#else -static_assert(offsetof(CheckJob, next) == 0x38); -static_assert(offsetof(CheckJob, continuation) == 0x28); -extern "C" void keepGoing(CheckJob *, CheckContext *); - -#if defined(__x86_64__) -asm("keepGoing:\n" - " mov 0x38(%rdi),%rdi\n" - " jmp *0x28(%rdi)\n"); -#elif defined(__aarch64__) -asm("keepGoing:\n" - " ldr x0, [x0, #0x38]\n" - " ldr x16, [x0, #0x28]\n" - " br x16\n"); -#else -#error "Only x64 and aarch64 are supported" -#endif -#endif FLATTEN PRESERVE_NONE void complete(CheckJob *job, CheckContext *context) { if (context->started == context->count) { if (job->prev == job) { +#if !__has_attribute(musttail) + context->done = true; +#endif return; } job->prev->next = job->next; @@ -3495,9 +3488,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { inProgress[0].prev = inProgress + started - 1; inProgress[started - 1].next = inProgress; +#if __has_attribute(musttail) // Kick off the sequence of tail calls that finally returns once all jobs // are done inProgress->continuation(inProgress, &context); +#else + context.job = inProgress; + context.done = false; + while (!context.done) { + context.job->continuation(context.job, &context); + } +#endif for (int i = 0; i < count; ++i) { assert(reads[i].readVersion >= 0);