flang компилятор доказывает, что программа не зациклится 0.7.24 GitHub English

Кеш приговоров ядра

Ядро доказательств выносит приговор каждому обязательству программы заново на каждый flang check, flang emit и на каждую перепечатку компилятора. Кеш приговоров складывает эти приговоры в файл и при следующем прогоне отдаёт их оттуда, не переспрашивая ядро.

Кешируется приговор целиком, включая отказы. Обязательство, которое ядро закрыть не смогло, стоит тех же шагов, что и доказанное, и переспрашивается каждым проходом; кеш только «доказанного» сберёг бы меньшую часть работы.

Где живёт

Механизм разнесён по двум слоям, и граница между ними — правило доверия.

Файл кеша — JSON: записи разложены по корзинам («Номер корзины» в proofterm.flang), каждая запись несёт ключ под k и приговор под v.

Как звать

FLANG_KESH_PRIGOVOROV=/путь/к/кешу.json flang check программа.flang
FLANG_KESH_PRIGOVOROV=/путь/к/кешу.json flang emit программа.flang --target c
FLANG_KESH_PRIGOVOROV=/путь/к/кешу.json sh scripts/bootstrap-reprint.sh

Переменная не задана — кеш выключен, и ядро идёт прежней дорогой. Двоичный не смог прочитать сам себя (отпечатка проверяльщика нет) — кеш тоже выключен: ключ без отпечатка раздавал бы чужие приговоры молча.

Пока кеш включён, каждый прогон называет его работу одной строкой в stderr:

кеш приговоров: спросов 1, попаданий 1, промахов 0, доля попаданий 100.0 %

Попадания считает ядро («Спросить кеш»), рантайм только печатает посчитанное. Для замера времени по стадиям есть FLANG_VITKI=1: печатает в stderr число шагов вычислителя на каждый вызов ядра (витки: <имя вызова> <число>).

Кеша нет на дороге --proof: отчёт о доказательствах строится отдельно от суда ядра, и приговоры там считаются заново. Сравнивать прогон с кешем и без надо печатью (flang emit) или flang check без --proof.

Что в ключе

«Вердикт без теоремы» в ядре — чистая функция трёх доводов: обязательства, программы и уже оплаченных фактов. Ключ покрывает ровно их и код, который их читает. Общая часть для всей программы («Основа кеша»):

ЧтоОткуда
отпечаток проверяльщикаsha256 самого двоичного компилятора
версия формата термов ядра«Версия ядра»
все функции программы — тела, постусловия, предусловияполе functions
объявления типовполе types
объявления законовполя monoids, monads, isomorphisms, intersections, embeddings
список неоплаченных требует«Оплаченное».«неоплаченные»

Часть на каждое обязательство («Ключ кеша»): узел обязательства и множество уже доказанных фактов («Оплаченное».«доказанные»). Из узлов перед печатью снимаются места («Значение без мест рекурсивно»): сдвиг строк в файле кеш не промахивает.

Все части печатаются строкой и сворачиваются sha256. Прежний многочленный отпечаток заменён: он линеен по кодам знаков, и два разных обязательства с одним ключом строятся намеренно, а кеш с таким ключом отдаёт «доказано» тому, что ядро без кеша отвергает.

Два решения в ключе названы вместе с их ценой:

Приборы

Всё лежит в docs/benchmarks/verdict-cache/:

sh docs/benchmarks/verdict-cache/probes.sh <двоичный> [<второй двоичный>]
sh docs/benchmarks/verdict-cache/second-kernel.sh [<куда собрать>]
sh docs/benchmarks/verdict-cache/three-prints.sh [<рабочий каталог>]

Соседний каталог

benchmarks/кеш-доказанного/ (снят 11 сентября 2026; последнее состояние — git show b5fcb2ae4:benchmarks/кеш-доказанного/) — более ранняя работа о том же явлении: прибор прибор.c считает ключ и даёт пробам, чем его опровергать, но ничего не хранит; его ключ уже (тела вызванных берутся замыканием графа вызовов). Кеш, который читает и пишет файл и подставляет приговор вместо повторного суда, — только здесь.