diff --git a/VERSION b/VERSION index 09a3acf..bcaffe1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0 \ No newline at end of file +0.7.0 \ No newline at end of file diff --git a/append_badges.py b/append_badges.py deleted file mode 100644 index 40f1e8b..0000000 --- a/append_badges.py +++ /dev/null @@ -1,67 +0,0 @@ -import yaml - -with open('.github/workflows/ci.yml', 'r') as f: - data = yaml.safe_load(f) - -jobs = data.get('jobs', {}) -job_names = [k for k in jobs.keys() if k != 'generate-badges'] - -steps = [ - {"uses": "actions/checkout@v4", "with": {"ref": "badges"}}, - {"name": "Set up directory", "run": "mkdir -p status"} -] - -for j in job_names: - run_script = f"""if [ "${{{{ needs.{j}.result }}}}" == "success" ]; then - COLOR="brightgreen" - TEXT="passing" -else - COLOR="red" - TEXT="failing" -fi -cat > status/{j}.svg << 'SVGEOF' - - - - - - - - - - - - - - - {j} - ${{TEXT}} - - -SVGEOF -""" - steps.append({ - "name": f"Generate badge for {j}", - "run": run_script - }) - -steps.append({ - "name": "Commit and push badges", - "run": 'git config user.name "GitHub Actions"\ngit config user.email "actions@github.com"\ngit add status/*.svg\ngit diff --quiet && git diff --staged --quiet || (git commit -m "Update build status badges [skip ci]" && git push origin badges)' -}) - -badge_job = { - 'needs': list(job_names), - 'if': 'always()', - 'runs-on': 'ubuntu-latest', - 'steps': steps -} - -data['jobs']['generate-badges'] = badge_job - -class MyDumper(yaml.Dumper): - def increase_indent(self, flow=False, indentless=False): - return super(MyDumper, self).increase_indent(flow, False) - -with open('.github/workflows/ci.yml', 'w') as f: - yaml.dump(data, f, Dumper=MyDumper, sort_keys=False, default_flow_style=False) diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index b3ed978..0000000 --- a/codecov.yml +++ /dev/null @@ -1,2 +0,0 @@ -ignore: - - "tests" \ No newline at end of file diff --git a/consolidate.py b/consolidate.py deleted file mode 100644 index 780b2d4..0000000 --- a/consolidate.py +++ /dev/null @@ -1,80 +0,0 @@ -import glob, yaml, os - -def get_workflows(): - workflows = glob.glob('.github/workflows/*.yml') - ignores = ['coverage.yml', 'release.yml', 'update-version-readme.yml', 'ci.yml'] - return [w for w in workflows if os.path.basename(w) not in ignores] - -def process_workflow(filepath): - with open(filepath, 'r') as f: - data = yaml.safe_load(f) - - target_name = data.get('name') - jobs = data.get('jobs', {}) - - combined_steps = [] - ordered_job_keys = [] - for prefix in ['setup', 'build', 'test']: - for k in list(jobs.keys()): - if k.startswith(prefix) and k not in ordered_job_keys: - ordered_job_keys.append(k) - for k in list(jobs.keys()): - if k not in ordered_job_keys: - ordered_job_keys.append(k) - - runs_on = None - - for k in ordered_job_keys: - job = jobs[k] - if not runs_on: - runs_on = job.get('runs-on') - - steps = job.get('steps', []) - for step in steps: - if 'uses' in step: - uses = step['uses'] - if 'actions/upload-artifact' in uses: continue - if 'actions/download-artifact' in uses: continue - if 'actions/checkout' in uses: - if any('actions/checkout' in s.get('uses', '') for s in combined_steps): - continue - combined_steps.append(step) - - combined_job = { - 'runs-on': runs_on, - 'steps': combined_steps - } - - for k in ordered_job_keys: - for extra_key in ['container', 'services', 'env']: - if extra_key in jobs[k] and extra_key not in combined_job: - combined_job[extra_key] = jobs[k][extra_key] - - return target_name, combined_job - -all_combined_jobs = {} -workflows_to_delete = get_workflows() - -for w in workflows_to_delete: - tname, cjob = process_workflow(w) - # the job_key should be a valid github actions job ID - job_key = os.path.basename(w).replace('.yml', '') - all_combined_jobs[job_key] = cjob - -ci_data = { - 'name': 'CI', - 'on': { - 'push': None, - 'pull_request': None - }, - 'jobs': all_combined_jobs -} - -class MyDumper(yaml.Dumper): - def increase_indent(self, flow=False, indentless=False): - return super(MyDumper, self).increase_indent(flow, False) - -with open('.github/workflows/ci.yml', 'w') as f: - yaml.dump(ci_data, f, Dumper=MyDumper, sort_keys=False, default_flow_style=False) - -print("Wrote ci.yml. Processed", len(workflows_to_delete), "workflows.") diff --git a/docs/streamline-plan.md b/docs/streamline-plan.md deleted file mode 100644 index ec875d1..0000000 --- a/docs/streamline-plan.md +++ /dev/null @@ -1,96 +0,0 @@ -# Streamlining Summary - -## Summary - -The coroutine-layer streamlining work is implemented across the C runtime, assembly backends, and toolchain selection files. YAFL now uses `yafl_switch(yafl_t *save, yafl_t target, void *data)` and `yafl_make_context()` internally, which removes `transfer_t`, removes `pending_arg`, and keeps the hot path at a save/restore plus direct data handoff. - -The public API in `include/yafl.h` stays unchanged. All of the streamlining work remains below that surface. - -## Status - -- `src/yafl.c` now uses direct `void *` handoff through `yafl_switch`. -- Assembly sources and exported symbols are renamed to `switch_*` / `make_context_*` and `yafl_switch` / `yafl_make_context`. -- Toolchain `ASM_FILES` lists point at the renamed files. -- The host arm64 build and test suite pass after the refactor. - -## Implemented Design - -### Low-level switch primitive - -The internal switch ABI is now: - -`void *yafl_switch(yafl_t *save, yafl_t target, void *data)` - -- `*save` receives the current suspended context. -- `target` is the context to resume. -- `data` is delivered directly both as the resumed return value and as the first-entry argument. - -This removes the synthetic transport struct and the Windows-specific hidden struct-return plumbing that existed in the old backend model. - -### Initial context creation - -The initial saved context is created by: - -`yafl_t yafl_make_context(void *sp, size_t size, yafl_entry_t fn)` - -Each backend-specific `make_context_*` file prepares the initial stack/register image for a new fiber and installs the `finish:` fallback path that terminates the process if a fiber entry function unexpectedly returns through the raw frame. - -### C runtime changes - -- `yafl_transfer_t` is removed. -- `pending_arg` is removed from `struct yafl_fiber`. -- `fiber_entry_trampoline()` now receives the first resume argument directly and discovers the active fiber through TLS. -- `yafl_fiber_resume()` and `yafl_fiber_suspend()` use direct `void *` handoff through `yafl_switch()`. -- Fiber stack cleanup and watermark reinitialization are both routed through helpers so failure paths stay linear. - -### Assembly and naming changes - -- All internal switch-family files are renamed from `jump_*` to `switch_*`. -- All initial-context files are renamed from `make_*` to `make_context_*`. -- Exported assembly symbols are renamed from `jump_fcontext` / `make_fcontext` to `yafl_switch` / `yafl_make_context`. -- Toolchain `ASM_FILES` lists in `toolchains/*.cmake` point at the renamed files. - -### Backend scope - -The direct-data `yafl_switch` model is implemented across the maintained backends in the tree, including x86_64, arm64, i386, arm, riscv64, loongarch64, mips32, mips64, ppc32, ppc64, s390x, and sparc64. - -The guiding backend rule is unchanged across architectures: save-via-pointer, restore-target-from-second-argument, and pass `data` directly. - -## Validation - -- Host arm64 library build succeeds. -- Host tests pass: `test_yafl_basic`, `test_yafl_suspend_resume`, `test_yafl_guard`, `test_yafl_many`, and `test_yafl_watermark`. -- Maintained sources no longer carry live `transfer_t`, `pending_arg`, `jump_fcontext`, or `make_fcontext` implementation references. -- Non-host assembly validation is opportunistic and depends on the locally available target assemblers. - -## Remaining Follow-up - -- Keep generated coverage artifacts in sync with the source tree when coverage is regenerated. -- Expand cross-target validation when additional target toolchains are available. - -## Decisions - -1. **Do not move the C trampoline into assembly** - - That would hardcode `struct yafl_fiber` offsets into every backend. - - The resulting code would be harder to audit and not meaningfully faster. - -2. **Do not collapse the initial-context primitive and the switch primitive into one assembly entry point** - - `yafl_switch` is the hot path. - - `yafl_make_context` runs only during fiber creation. - - Combining them would trade a tiny amount of source reduction for a branchier and less legible hot path. - -3. **Do not merge ELF and Mach-O assembly files even when they currently match** - - OS-level context requirements may diverge later, including support for wider architectural state such as AVX or other OS-managed register state. - - Keep separate per-OS source files so those changes can land without re-splitting shared assembly later. - -4. **Do not introduce runtime architecture dispatch to reduce file count** - - The current per-target selection in the toolchain files keeps the build explicit and predictable. - - Runtime selection would increase complexity without helping performance. - -## Relevant Files - -- `src/yafl.c` — current C runtime implementation of the streamlined switch semantics. -- `include/yafl.h` — no public API changes are required. -- `src/asm/*/switch_*` — backend switch-family sources implementing `yafl_switch`. -- `src/asm/*/make_context_*` — backend entry-context sources implementing `yafl_make_context`. -- `toolchains/*.cmake` — backend selection for the renamed assembly sources. diff --git a/fix_ci.py b/fix_ci.py deleted file mode 100644 index 21daea6..0000000 --- a/fix_ci.py +++ /dev/null @@ -1,34 +0,0 @@ -import yaml - -with open('.github/workflows/ci.yml', 'r') as f: - data = yaml.safe_load(f) - -for job_name, job_info in data['jobs'].items(): - if job_name == 'generate-badges': continue - - seen_step_names = set() - new_steps = [] - - for step in job_info.get('steps', []): - if 'name' in step: - name = step['name'] - - # Skip redundant executable permission restore - if name == 'Restore execute permissions': continue - if step.get('run') and 'chmod +x build/bin' in str(step.get('run', '')): continue - - # Skip duplicated setup/install steps - if name in seen_step_names: continue - - seen_step_names.add(name) - - new_steps.append(step) - - job_info['steps'] = new_steps - -class MyDumper(yaml.Dumper): - def increase_indent(self, flow=False, indentless=False): - return super(MyDumper, self).increase_indent(flow, False) - -with open('.github/workflows/ci.yml', 'w') as f: - yaml.dump(data, f, Dumper=MyDumper, sort_keys=False, default_flow_style=False) diff --git a/parse_workflows.py b/parse_workflows.py deleted file mode 100644 index 999512c..0000000 --- a/parse_workflows.py +++ /dev/null @@ -1,7 +0,0 @@ -import os, glob, yaml - -workflows = glob.glob('.github/workflows/*.yml') -workflows = [w for w in workflows if 'coverage' not in w and 'update-version' not in w and 'release' not in w] - -# We will collect the matrix entries -print("Parsing workflows...") diff --git a/tests/test_yafl_watermark.c b/tests/test_yafl_watermark.c index 286da27..4b2a7ad 100644 --- a/tests/test_yafl_watermark.c +++ b/tests/test_yafl_watermark.c @@ -128,4 +128,4 @@ int main(void) { printf("\nAll watermark tests passed!\n"); return 0; -} \ No newline at end of file +} diff --git a/tmp.yml b/tmp.yml deleted file mode 100644 index e69de29..0000000 diff --git a/workflows.tar.gz b/workflows.tar.gz deleted file mode 100644 index b9f922e..0000000 Binary files a/workflows.tar.gz and /dev/null differ