# Show HN draft - asmdiff

**Mechanics:** submit the repo URL `https://github.com/rt-rtos/asmdiff` with the
title below, then immediately post the body as your first comment. Post on a
weekday morning US-time for best odds. If it doesn't catch the first time, a
single repost after a while is allowed - don't over-read a quiet first attempt.
Make sure the repo is push-current and PyPI 0.2.0 is live first; people click
Install within seconds.

## Title

Primary:

```
Show HN: asmdiff - diff a function's assembly across compilers, or from a shipped ELF
```

Alternates (lead with the payoff):

- `Show HN: asmdiff - spot when a C construct silently compiles to a library call`
- `Show HN: asmdiff - per-function assembly diffing across a compiler matrix or an ELF`

## First comment

I kept rewriting small C functions to shave hot-path cost and then not being
sure the compiler actually did what I hoped: did that `x * exp2f(-5)` fold to a
multiply, or is it still a libcall? Nothing in `-Wall -Wextra -Wconversion` tells
you. The assembly does, but eyeballing `-S` across a couple of compilers and
optimization levels gets old fast.

asmdiff compiles a C function across a matrix of compilers/flags and prints the
per-function assembly side by side, plus a summary with instruction counts, loop
spans, and - the part I actually use - a `calls` column. A `-` means it lowered
to inline instructions; a symbol means a hidden library call. That's the whole
pitch: it makes fold-vs-libcall visible at a glance.

Two things grew out of that:

- It borrows the real build's include/define flags from compile_commands.json, so
  you can run one project source across, say, esp32 / esp32s2 / esp32s3
  cross-toolchains in a single command with no separate build trees. The esp32-S2
  (no hardware FPU) visibly sprouts softfloat calls (__floatsisf, __floatunsisf)
  the others don't.
- It also reads shipped ELF binaries - disassembles through the toolchain's
  objdump to show post-LTO/link reality instead of idealized -S output, with a
  regex filter to sweep LTO-renamed functions.

I originally wrote it to hunt hot-path codegen in the shorepine/amy synth engine, and it paid off: a
2 kHz timer callback was carrying both a softfloat divide and a 64-bit __udivdi3,
which also turned out to hide a real clock-wrap bug.

It's a single stdlib-only Python file, no dependencies (`uvx asmdiff` to try it,
or `uv tool install` / `pipx install`). Honest scope: it counts instructions, not
cycles - it tells you what the compiler emitted, not what it costs at runtime;
measuring that is still your job.

Happy to hear where it breaks or what's missing.
