diff --git a/10.-%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2-%D0%BD%D0%B0-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%28%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA%29.md b/10.-%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2-%D0%BD%D0%B0-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%28%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA%29.md index 6192989..9df0c68 100644 --- a/10.-%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2-%D0%BD%D0%B0-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%28%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA%29.md +++ b/10.-%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2-%D0%BD%D0%B0-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%28%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA%29.md @@ -29,16 +29,16 @@ Начинается всё с того, что каждой вершине приписывается два счётчика: `cnt_in = cnt_out = 0`. Данные блока `A` более свежие чем данные блока `B`, если `A->cnt_out > B->cnt_in`. `A->doStep()` перебирает все блоки `B` такие, что блок `B` имеет более свежие данные чем `A`, то есть `B->cnt_out > A->cnt_in`. Для каждого такого блока `B` он обновляет множество `A->IN` данными из `B->OUT` через `A->addIn(B->getOut())`. И для тех данных, которые действительно обновили `A->IN` он вызывает `A->forwardData()`. (На самом деле берётся не вся коллекция `B->getOut()` сразу целиком, а каждый её элемент сначала попадает в `addIn`, а затем, если `addIn` возвращает `true`, попадает в `forwardData`). При этом в `cnt_in` (`cnt_out`) попадает максимальное значение счётчика `cnt_out` среди блоков, которые добавили в множество `IN` (при помощи `addIn`) хоть один новый элемент (соответственно добавили в `OUT` при помощи `forwardData` хоть один новый элемент). Если данная вершина вызывает `doStep` впервые, то в конце [к `cnt_in` и `cnt_out` прибавляем по 1][**TODO: это не правильно, нужно потом исправить в коде и здесь**] чтобы обозначить, что в `OUT` этой вершины есть данные, которые появляются изначально при создании вершины и которые нужно распространить в остальные вершины. -Теперь осталось только решить задачу с заполнением `nodes`. Эту задачу берёт на себя метод `fit()`. Реализация этого метода отличается в случаях, когда рассматривается задача прямого и обратного анализа потока данных. До этого повествование шло, будто мы рассматриваем задачу прямого обхода. Поэтому в случае прямого обхода nodes заполняется естественно в топологическом порядке, то есть так, чтобы выполнялось соотношение, что для любых `i < j` дуги из `nodes[i]` в `nodes[j]` либо нет, либо это обратная дуга графа потока управления (см функцию `sortCfgNodes`). Для каждой созданной вершины `node` нужно заполнить +Теперь осталось только решить задачу с заполнением `nodes`. Эту задачу берёт на себя метод `fit()`. Реализация этого метода отличается в случаях, когда рассматривается задача прямого и обратного анализа потока данных. До этого повествование шло так, будто мы рассматриваем задачу прямого обхода. Поэтому в случае прямого обхода nodes заполняется естественно в топологическом порядке, то есть так, чтобы выполнялось соотношение, что для любых `i < j` дуги из `nodes[i]` в `nodes[j]` либо нет, либо это обратная дуга графа потока управления (см функцию `sortCfgNodes`). Для каждой созданной вершины `node` нужно заполнить * `rollback` - множество `i` таких что есть обратная дуга `node -> nodes[i]` * `prev_blocks` - множество всех вершин, из которых в node могут попасть данные (для задачи прямого обхода - это `nodes[i]` такие что есть дуга `nodes[i] -> nodes`; для задачи обратного прохода - это `nodes[i]`: есть дуга `node -> nodes[i]`). * `bb` - соответствующий базовый блок. -На самом деле реальизация `fit` для задач прямого и обратного обхода почти одинаковая, потому что обратная задача отличается только тем, что массив `nodes` развёрнут и `prev_blocks` другой. При этом `IN` `DataFlowAnalysisNode` соотвествует `OUT` для базового блока и наоборот `OUT` `DataFlowAnalysisNode` соотвествует `IN` базового блока. +На самом деле реализация `fit` для задач прямого и обратного обхода почти одинаковая, потому что обратная задача отличается только тем, что массив `nodes` развёрнут и `prev_blocks` другой. При этом `IN` `DataFlowAnalysisNode` соответствует `OUT` для базового блока и наоборот `OUT` `DataFlowAnalysisNode` соответствует `IN` базового блока. Поэтому для `DataFlowAnalysis` определены классы `BackwardDataFlowAnalysis` и `ForwardDataFlowAnalysis` (**TODO: ForwardDataFlowAnalysis ещё не определён**). -На практике требуется при создании экземпляра наследника `DataFlowAnalysisNode` передавать в конструктор какие-то аргументы кроме базового блока, поэтому в `fit` при создании объекта наследника `DataFlowAnalysisNode` используется виртуальная функция `createNode`, которая должна быть реализована в конечном наследнике и выполнять создание объекта типа `NodeType`. Чаще всего это просто вызов конструктора `NodeType` с аргументамы `BasicBlock*` и аргументами-полями класса. +На практике требуется при создании экземпляра наследника `DataFlowAnalysisNode` передавать в конструктор какие-то аргументы кроме базового блока, поэтому в `fit` при создании объекта наследника `DataFlowAnalysisNode` используется виртуальная функция `createNode`, которая должна быть реализована в конечном наследнике и выполнять создание объекта типа `NodeType`. Чаще всего это просто вызов конструктора `NodeType` с аргументами `BasicBlock*` и аргументами-полями класса. Итак, если подвести итог, то для создания анализа достаточно: