Я пытаюсь внедрить Hoopl в некоторый компилятор и столкнулся с некоторой проблемой: создание графика для Hoopl заставляет узлы появляться в порядке введенных меток.
Например:
(define (test) (if (eq? (random) 1 ) 2 (if (eq? (random) 2 ) 3 0) ) )
"компилирует" в
L25: call-direct random -> _tmp7_6
branch L27
L26: return RETVAL
L27: iconst 1 _tmp8_7
branch L28
L28: call-direct eq? _tmp7_6, _tmp8_7 -> _tmp4_8
branch L29
L29: cond-branch _tmp4_8 L30 L31
L30: iconst 2 RETVAL
branch L26
L31: call-direct random -> _tmp12_10
branch L32
L32: iconst 2 _tmp13_11
branch L33
L33: call-direct eq? _tmp12_10, _tmp13_11 -> _tmp9_12
branch L34
L34: cond-branch _tmp9_12 L36 L37
L35: assign RETVAL _tmp6_15
branch L26
L36: iconst 3 _tmp6_15
branch L35
L37: iconst 0 _tmp6_15
branch L35
Порядок инструкций (в порядке showGraph) странный из-за порядка построения рекурсивного графа из AST.Чтобы сгенерировать код, мне нужно изменить порядок блоков более естественным образом, скажем, поместите return RETVAL в конец функции, объедините блоки, подобные этому
branch Lx:
Lx: ...
, в один блок и так далее.Кажется, мне нужно что-то вроде:
block1 = get block
Ln = get_last jump
block2 = find block Ln
if (some conditions)
remove block2
replace blick1 (merge block1 block2)
Я совершенно запутался, как это сделать с помощью Hoopl.Конечно, я могу сбросить все узлы, а затем выполнить преобразования вне рамок Hoopl, но я считаю, что это плохая идея.
Может кто-нибудь дать мне какой-нибудь клей?Я не нашел никаких полезных примеров.Нечто подобное выполняется в проекте Lambdachine, но кажется слишком сложным.
Есть и другой вопрос.Есть ли смысл делать все инструкции Call нелокальными?Какой смысл в этом, учитывая, что реализация Call не изменяет какие-либо локальные переменные и всегда передает управление следующей инструкции блока?Если инструкции Call определены как
data Insn e x where
Call :: [Expr] -> Expr -> Label :: Insn O C -- last instruction of the block
, это заставляет график выглядеть еще более странным.Поэтому я использую
-- what the difference with any other primitive, like "add a b -> c"
Call :: [Expr] -> Expr -> Label :: Insn O O
Может быть, я не прав с этим?