Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/buildcommit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,12 @@ jobs:
- name: test
if: ${{ matrix.native == 'yes' }}
timeout-minutes: 1
run: vs2022\${{matrix.folder}}\Debug\test.exe
shell: cmd
run: |
vs2022\${{matrix.folder}}\Debug\test.exe
set RC=%ERRORLEVEL%
echo test.exe exit %RC%
exit /b %RC%
- name: Upload build artifacts
uses: actions/upload-artifact@v7.0.0
with:
Expand Down
28 changes: 26 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.3.0] - 2026-10-15

### Added
- FreeBSD, OpenBSD and NetBSD (amd64, `sysv_amd64` ABI) are built and tested on every commit by a new `build and test bsd` workflow.
- `armhf`, a 32-bit ARM hard-float ABI (AAPCS-VFP). `__ARM_PCS_VFP` selects it. Soft-float stays `arm32`. CI and the release archive include `lib/armhf`.
- `docs/platform-abi.md`, the current contract for switching and register spills. `docs/abi-register-audit.md` remains the historical record of that audit.
- `test_09` checks that the caller's rounding mode survives `stackman_switch`, including a switch onto a saved stack. Soft-float `arm32` does not spill `FPSCR`, and the test expects the callback's mode to remain.
- FreeBSD, OpenBSD and NetBSD (amd64, `sysv_amd64` ABI) are built and tested on every commit by a `build and test bsd` workflow.

### Changed
- `stackman_switch` spills floating-point control and status state and reloads it after the restore callback. `stackman_call` does not touch those registers.
- `armhf` spills the whole `FPSCR`.
- `aarch64` and `darwin_arm64` spill `FPCR` and `FPSR`.
- `win_arm64` spills `FPSR` as well as `FPCR`.
- `riscv64` spills the whole `fcsr`.
- `sysv_i386` spills the x87 control word. `win_x64` spills `MXCSR`.
- `win_x86` spills the x87 control word and `MXCSR`, so older compilers that emit x87 and current MSVC, which emits SSE2, each keep their rounding mode.
- Softfp (`-mfloat-abi=softfp`) is not a supported platform. That build selects `arm32` and does not preserve `FPSCR`.
- CI test steps stop after one minute.

### Fixed
- `test_04` allocates 8KB for the `stackman_call` stack. Two MSVC Debug (`/ZI`) frames of the recursive callback overflowed a 1KB block into the heap header, so the x64 test failed intermittently.
- RISC-V `stackman_call` leaves a null stack unchanged and passes the previous stack pointer to the callback.
- Windows ARM64 no longer uses the live TEB register `x18` as a scratch in `stackman_switch` or `stackman_call`.
- AArch64 `stackman_switch` keeps the frame pointer attached across a stack switch, and the unwind info covers the `FPCR` slot.
- ABI detection now works on the BSDs: `tools/abiname.sh` used a `mktemp` template with three `X`s, which BSD `mktemp(1)` rejects.

### Removed
- Leftover Windows ARM32 sources, Visual Studio configurations, and `lib/win_arm`. Version 1.0.0 had already dropped that platform.

## [1.2.5] - 2026-06-23

### Changed
Expand Down Expand Up @@ -142,7 +165,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- GitHub Actions CI for automated building and testing
- Visual Studio project files (VS2017, VS2019, VS2022)

[Unreleased]: https://github.com/stackless-dev/stackman/compare/v1.2.5...HEAD
[Unreleased]: https://github.com/stackless-dev/stackman/compare/v1.3.0...HEAD
[1.3.0]: https://github.com/stackless-dev/stackman/releases/tag/v1.3.0
[1.2.5]: https://github.com/stackless-dev/stackman/releases/tag/v1.2.5
[1.2.4]: https://github.com/stackless-dev/stackman/releases/tag/v1.2.4
[1.2.3]: https://github.com/stackless-dev/stackman/releases/tag/v1.2.3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
║ ║
║ Do you have a stack? Stackman is here to help. ║
║ ║
║ v1.2.5 • 11 platforms • Stack switching simplified ║
║ v1.3.0 • 11 platforms • Stack switching simplified ║
║ ║
╚══════════════════════════════════════════════════════════════╝
```
Expand Down
6 changes: 3 additions & 3 deletions stackman/stackman.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

/* Version information */
#define STACKMAN_VERSION_MAJOR 1
#define STACKMAN_VERSION_MINOR 2
#define STACKMAN_VERSION_PATCH 5
#define STACKMAN_VERSION_MINOR 3
#define STACKMAN_VERSION_PATCH 0

/* Version as a string */
#define STACKMAN_VERSION "1.2.5"
#define STACKMAN_VERSION "1.3.0"

/* Version as a single number for comparisons (MMmmpp: Major, minor, patch) */
#define STACKMAN_VERSION_NUMBER ((STACKMAN_VERSION_MAJOR * 10000) + \
Expand Down
56 changes: 56 additions & 0 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,51 @@
#include <stdlib.h>
#include <stdint.h>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* Name of the test currently running, so a fault names itself.
* stdout from a crashed process is lost when it is fully buffered. */
static const char *current_test;

static LONG WINAPI test_crash(EXCEPTION_POINTERS *info)
{
EXCEPTION_RECORD *rec = info->ExceptionRecord;

fprintf(stderr, "exception 0x%08lx at %p during %s",
rec->ExceptionCode, rec->ExceptionAddress,
current_test ? current_test : "startup");
if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
rec->NumberParameters >= 2) {
fprintf(stderr, " %s %p",
rec->ExceptionInformation[0] ? "write" : "read",
(void *)rec->ExceptionInformation[1]);
}
fprintf(stderr, "\n");
fflush(stderr);
return EXCEPTION_CONTINUE_SEARCH;
}
#endif

static void test_startup(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#ifdef _WIN32
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
AddVectoredExceptionHandler(1, test_crash);
#endif
}

static void test_enter(const char *name)
{
#ifdef _WIN32
current_test = name;
#endif
printf("%s\n", name);
}

/* Soft-float arm32 does not spill FPSCR. Softfp selects that assembly. */
#if defined(__arm__) && !defined(__aarch64__) && !defined(__ARM_PCS_VFP)
#define STACKMAN_ROUND_ISOLATED 0
Expand Down Expand Up @@ -567,25 +612,36 @@ void test_09(void *stack_marker)
int main(int argc, char*argv[])
{
int stack_marker = 0;

test_startup();
test_enter("test_01");
test_01();
printf("test_01 ok\n");
test_enter("test_02");
test_02((void*)&stack_marker);
printf("test_02 ok\n");

test_enter("test_03");
test_03((void*)&stack_marker);
printf("test_03 ok\n");
#ifdef TEST_04
test_enter("test_04");
test_04();
printf("test_04 ok\n");
test_enter("test_05");
test_05();
printf("test_05 ok\n");
#endif
test_enter("test_06");
test_06();
printf("test_06 ok\n");
test_enter("test_07");
test_07();
printf("test_07 ok\n");
test_enter("test_08");
test_08();
printf("test_08 ok\n");
test_enter("test_09");
test_09((void*)&stack_marker);
printf("test_09 ok\n");
return 0;
Expand Down
Loading