~

$ ls til/ --graph

  1. lld and gnu ld can pull different archive members

    I assumed two linkers fed the same archives in the same order would produce the same binary. Debugging a build divergence, I found out they don’t — ld.lld (LLVM’s linker) pulled an object out of one archive, ld.bfd (the GNU linker, what most people mean by “GNU ld”) pulled a same-named object out of a different one. Same sources, same link line.

    Both archives defined the same symbol with different bodies — that’s the underlying bug. It only stayed hidden because each linker happened to pick a different one.

    • The classical archive rule both linkers follow: when an undefined symbol comes up, walk archives left-to-right and pull the first member whose symbol table provides it.
    • They don’t agree in every case. Weak/strong handling, COMDAT group selection, and lld’s --start-lib / --end-lib lazy loading all differ from gnu ld in ways that can change which member ends up linked.
    • For my link line, that was enough to flip which archive won. Neither result is wrong — the spec lets both win.

    Haven’t pinned down the exact rule that diverged in my case. For now: don’t ship same-name symbols with different bodies across archives and expect the linker to disambiguate them. Which one wins is an implementation detail, and switching linkers (or versions) can flip it silently.

  2. C++ `[[likely]]` and `[[unlikely]]` aren't always symmetric

    I assumed annotating one branch with [[likely]] would make the compiler infer [[unlikely]] on the other. After all, in a plain if/else the other branch is the inverse.

    if (ok) [[likely]] {
        fast_path();
    } else {
        slow_path();
    }

    vs.

    if (ok) [[likely]] {
        fast_path();
    } else [[unlikely]] {
        slow_path();
    }

    Building with arm-none-eabi-gcc, the second version sometimes produced less code and a smaller stack frame than the first. Same optimization level, same sources.

    • One hint tells the compiler one branch’s weight; it still has to pick a reasonable default for the other.
    • Two hints pin both weights, so block layout, register allocation, and spill decisions can skew harder toward the hot path.
    • The extra instructions I saw looked like the cold path getting treated as merely “less likely” instead of “cold,” so it stayed close enough to cost the fast path a few spills.

    Haven’t fully chased down why yet. For now: if you care enough to annotate one side, annotate both.

  3. 희지가 귀엽다!

    ❤️_❤️

  4. Using Ninja directly with `-t compdb`

    You can use Ninja’s built-in tool to generate the compile_commands.json.

    $ ninja -t compdb > compile_commands.json
    • -t compdb tells Ninja to output the compilation database.
    • Redirect the output to compile_commands.json.
$
↑↓ move ↵ open esc close
$
$ shortcuts
j /k
navigate
Enter
open / activate
-
parent directory
gg /G
first / last
o
toggle entry (til)
h /l
prev / next photo (moments)
[ /]
prev / next moment
P (shift+p)
preview focused page
⌘ K /Ctrl K
command palette
?
this help
esc
close dialog