Я работаю над игрушечным языком, который сейчас нуждается в компиляции. Пока у меня есть вызовы вложенных функций, и мне интересно, как будет выглядеть псевдокод сборки. Это включает:
- Пролог и эпилог функции.
- «Блоки» инструкций.
- Как функции повторно используются.
- Не настоящий ассемблерный код, просто псевдокод (хотя я вроде как с x86).
Структура «блока» x86, о которой я говорю, выглядит так:
my_function:
enter N, 0
; ... details
leave
ret
Чтобы сохранить ее простой (избегая asyn c и всего такого), мой код игрушки в основном выглядит так:
my_func_a(add(1, my_func_z(2, 3)), sub(my_func_r(4, 5, 6), 7), 8)
Или разложенный:
my_func_a(
add(
1,
my_func_z(2, 3)
),
sub(
my_func_r(
4,
5,
6
),
7
),
8
)
Когда я пытаюсь мысленно перевести это на какая-то соответствующая псевдосборка, я в итоге делаю это:
u = my_func_r(4, 5, 6)
v = sub(u, 7)
w = my_func_z(2, 3)
x = add(1, w)
y = my_func_a(x, v) ; final result
Я не уверен, правильно ли я получил порядок, но я думаю, что это близко. Но это недостаточно низкоуровневый, как x86, поэтому я пытаюсь снизить его дальше:
mov r1, 4
mov r2, 5
mov r3, 6
call my_func_r
; how to capture the "u = ..."?
mov r1, u?
mov r2, 7
call sub
; how about capturing "v"?
mov r1, 2
mov r2, 3
call my_func_z
; w = ... somehow
mov r1, 1
mov r2, w
call add
; x = ... somehow
mov r1, x
mov r2, v
call my_func_a
; y...
Я бы попытался использовать какой-то инструмент для компиляции некоторого грубого C -подобного язык в LLVM, например, но мне непросто заставить все это работать и работать на данном этапе.
Теперь предположим, что у нас есть реализации для некоторых из этих функций:
my_func_r(a,b,c):
enter ...
add a, b
sub b, c
leave
ret
my_func_z(a,b):
enter ...
; ...
leave
ret
my_func_a(a,b):
enter ...
; ...
leave
ret
В основном мне интересно, как должен быть записан последний псевдокод ? (учитывая, что я точно не указал здесь, как все работает, на данный момент я получил это примерно на уровне). Как бы это выглядело примерно? Я не вижу, как значения правильно размещаются и передаются в версии сборки самого низкого уровня.
- Где аргументы передаются в функции? В каком месте, перед вызовом функции или внутри функции / блока?
- Как вы захватываете выходные переменные вне функции?
Извините, если этот псевдокод подвержен ошибки, я только начинаю складывать части вместе, так что будьте осторожны.