Хорошо, сначала возьмите все фрагменты кода и переформатируйте их в свои собственные функции. Таким образом, ваш код идет по адресу:
void addOpcode(uint32_t *result, uint32_t L, uint32_t R) {
*result = L + R;
}
switch (opcode) {
case ADD:
addOpcode(&result, L, R);
break;
....
Хорошо, поэтому после этого ваш переводчик должен все еще работать. Теперь возьмите все новые функции и поместите их в свой собственный файл. Теперь скомпилируйте этот файл с помощью llvm-gcc или clang и вместо того, чтобы генерировать собственный код, скомпилируйте его с помощью "cpp" backend (-march -cpp). Это создаст код C++, который создает код байта для блока компиляции. Вы можете указать параметры, чтобы ограничить его конкретными функциями и т. Д. Возможно, вы захотите использовать «-cppgen module».
Теперь вернемся к тому, что ваш цикл интерпретатора соединяет вызовы сгенерированного кода на C++ вместо прямого выполнения исходного кода, а затем передает его некоторым оптимизаторам и родному кодегенератору. Gratz на JIT ;-) Вы можете увидеть пример этого в нескольких проектах LLVM, таких как vm_ops в llvm-lua.
Замечательно! Я думал, что это будет что-то вроде этого, с LLVM, в котором будут вложены все функции. – joeforker
Как это соотносится с интерпретатором с перекрестными ссылками, где вы только JIT серии инструкций CALL для каждой реализации байт-кода, встраиваете реализацию только нескольких опкодов, скорее всего, коды BRANCH, и каждая реализация кода операции заканчивается с помощью RET? – joeforker
Я не совсем понимаю это. Вы хотите передать все функции opcode в LLVM, и когда вы вернете его обратно на C, у него автоматически будет встроенный JIT? – Unknown