Я сомневаюсь, что кто-то может помочь с этим вопросом из-за следующего в документации по компиляции Эрланга :
Обратите внимание, что формат файлов ассемблера не задокументирован, и может изменяться междуReleases - эта опция предназначена в основном для внутренней отладки.
... но на всякий случай здесь идет трассировка стека истории:
- compile: file / 2 with['S'], чтобы сгенерировать ассемблерный код
- Считать файл .S и создать структуру данных ключ-значение, где ключом является кортеж 'function' в файле .S, а значением является тело функции, т.е.инструкции по сборке, которые реализуют функцию.
- Измените структуру данных, добавив сборку для выполнения внешнего вызова функции в определенных функциях.
- crash ...
К сожалению, я просто быстро просмотрел файлы .S, сгенерированные при компиляции модуля, содержащего следующую функцию, с закомментированным первым выражением в функции и без него:
spawn_worker(Which) ->
%syner:sync_pt(),
case Which of
?NAIVE -> spawn(err1, naive_worker_loop, [])
end.
Когда я это сделал, я подумал, что единственное, что изменилось, это кортеж:
{call_ext, 0, {extfunc, syner, sync_pt, 0}}.
... поэтому я предположил, что единственное, что необходимо для внедрения вызова функции в сборку, это добавить этот кортеж ... но теперь, когда я действительно должен внедрить кортеж ... я вижучто в сгенерированной сборке есть несколько дополнительных инструкций:
Без syner: sync_pt () :
{function, spawn_worker, 1, 4}.
{label,3}.
{func_info,{atom,err1},{atom,spawn_worker},1}.
{label,4}.
{test,is_eq_exact,{f,5},[{x,0},{atom,naive}]}.
{move,{atom,naive_worker_loop},{x,1}}.
{move,nil,{x,2}}.
{move,{atom,err1},{x,0}}.
{call_ext_only,3,{extfunc,erlang,spawn,3}}.
{label,5}.
{case_end,{x,0}}.
С syner: sync_pt () :
{function, spawn_worker, 1, 4}.
{label,3}.
{func_info,{atom,err1},{atom,spawn_worker},1}.
{label,4}.
{allocate,1,1}.
{move,{x,0},{y,0}}.
{call_ext,0,{extfunc,syner,sync_pt,0}}.
{test,is_eq_exact,{f,5},[{y,0},{atom,naive}]}.
{move,{atom,naive_worker_loop},{x,1}}.
{move,nil,{x,2}}.
{move,{atom,err1},{x,0}}.
{call_ext_last,3,{extfunc,erlang,spawn,3},1}.
{label,5}.
{case_end,{y,0}}.
Я не могу просто заключить, что добавление чего-то вроде:
{allocate,1,1}.
{move,{x,0},{y,0}}.
{call_ext,0,{extfunc,syner,sync_pt,0}}.
к каждой функции, в которую я хочу внедрить вызов внешней функции, сделает свое дело.
- , потому что я не уверен, применим ли этот ассемблерный код ко всем функциям, в которые я хочу вставить (например, {allocate, 1,1} всегда в порядке)
- потому что, если вы присмотритесь к остальной части сборки, она немного изменится (например, {call_ext_only, 3, {extfunc, erlang, spawn, 3}}. изменится на {call_ext_last, 3, {extfunc, erlang, spawn, 3}, 1}. ).
Итак, вопрос в том, есть ли какой-нибудь ресурс, который я могу использовать, чтобы понять иманипулировать сборкой, сгенерированной компиляцией Эрланга: file / 2?
Я задаю этот вопрос на всякий случай.Я сомневаюсь, что для этого есть ресурс, так как в документации четко сказано, что его нет, но мне нечего терять.Даже если бы и было, кажется, что манипулирование ассемблерным кодом будет сложнее, чем хотелось бы.Использование parse_transform / 2 определенно проще, и мне удалось получить что-то похожее для работы с ним ... просто пробовал разные варианты.
Спасибо за ваше время.