0

I am developing an interpreter that converts an Intermediate Representation (IR) into an Assembly. However, I have a doubt that it is necessary to convert each instruction individually to Assembly, as shown in the example below. Additionally, I would like to receive recommendations and optimization suggestions based on the code provided. Any guidance or insight on how to improve the Assembly conversion process and make it more efficient.

#include <stdio.h>
#include <stdlib.h>

typedef enum {
    OP_ADD,
    OP_SUB,
    OP_DIV,
    OP_MUL,
    NUM_OPCODES

} bytecode_opcode;

void convert_add() { printf("add rax, rbx\n"); }
void convert_sub() { printf("sub rax, rbx\n"); }
void convert_div() { printf("div rbx\n"); }
void convert_mul() { printf("mul rbx\n"); }

typedef void (*conversion_func)();

conversion_func conversion_table[NUM_OPCODES] = {
    convert_add,
    convert_sub,
    convert_div,
    convert_mul
};

void convert_to_x64(bytecode_opcode instr) {
    if (instr >= 0 && instr < NUM_OPCODES) {
        conversion_func func = conversion_table[instr];
        func();
    } else {
        printf("Opcode inválido\n");
    }
}

int main() {
    convert_to_x64(OP_ADD);
    convert_to_x64(OP_MUL);
    convert_to_x64(10); 

    return 0;
}

1 Answer 1

3

Interpreters don't necessarily need to concern themselves with machine code or assembly language — they simply have to get done what the input language says to do.  In the case of addition, for example, an interpreter needs to add, such as return a+b; — not necessarily to generate machine code then run it.

Generating machine code (or assembly code) would be part of a JIT (just in time) compiler, an interpreter of a very different form.

A JIT is an in-memory compiler along with a runtime that manages compiled code for reuse.  A JIT can have varying degrees of optimization.  It could translate the input language instructions one-for-one into assembly — while an optimizing JIT will consider larger portions of the input language and translate them much like a real compiler backend, in steps with chunks of input, using intermediate forms that favor optimization.

For an optimizing JIT, should probably include register allocation and some other common compiler backend transformations, to get closer to compiled code quality.

Sign up to request clarification or add additional context in comments.

3 Comments

The idea is to create a JIT compiler that translates into assembly. So does this mean that I will have to translate one by one as I showed in the example?
You can and that will work but will have lower code quality / performance than an optimizing approach; still,, maybe that's a good place to start.
Thanks, I will add optimization in the future

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.