Moved intermediate representation into functions and files and load program into RAM. Benchmarks shows an increase of aproximately 256 times in execution speed !

This commit is contained in:
Ulysse Cura 2026-10-11 21:24:40 +02:00
parent 9bfa557615
commit 4cbc8b8262
4 changed files with 388 additions and 388 deletions

View File

@ -1,5 +1,6 @@
SOURCES += \ SOURCES += \
main.c main.c \
ir.c
INCLUDES += INCLUDES +=

283
src/ir.c Normal file
View File

@ -0,0 +1,283 @@
#include "ir.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
operation_t char_to_operation(int c)
{
switch(c)
{
case '>':
return MEM_POINTER_ADD;
case '<':
return MEM_POINTER_SUB;
case '+':
return MEM_ADD;
case '-':
return MEM_SUB;
case '[':
return JUMP_IF_0;
case ']':
return JUMP_IF_NOT_0;
case '.':
return PRINT_CHAR;
case ',':
return GET_CHAR;
default:
return NONE;
}
}
int process_operation_into_ir_file(FILE *ir_file, operation_t operation, operation_t *last_operation)
{
if(operation == NONE)
{
return EXIT_SUCCESS;
}
switch(operation)
{
case MEM_POINTER_ADD:
case MEM_POINTER_SUB:
case MEM_ADD:
case MEM_SUB:
if(operation == *last_operation)
{
operation++; // Go to advanced version of operation
if(fseek(ir_file, -1, SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
if(fwrite(&operation, sizeof(operation_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
operand_t nb = 2;
if(fwrite(&nb, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
}
else if(operation + 1 == *last_operation)
{
operation++;
operand_t nb;
if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
if(fread(&nb, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error reading file: %d\n", errno);
return EXIT_FAILURE;
}
nb++;
if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
if(fwrite(&nb, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
}
else
{
if(fwrite(&operation, sizeof(operation_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
}
break;
case JUMP_IF_0:
case JUMP_IF_NOT_0:
if(fwrite(&operation, sizeof(operation), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
operand_t jump_pos = 0;
if(fwrite(&jump_pos, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
break;
case PRINT_CHAR:
case GET_CHAR:
if(fwrite(&operation, sizeof(operation), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
break;
default:
fprintf(stderr, "Error: invalid operation nb.\n");
return EXIT_FAILURE;
}
*last_operation = operation;
return EXIT_SUCCESS;
}
int calculate_jump_operands(FILE *ir_file)
{
while(true)
{
operation_t operation;
if(fread(&operation, sizeof(operation_t), 1, ir_file) != 1)
{
if(feof(ir_file))
{
break;
}
else
{
fprintf(stderr, "Error reading file: %d\n", ferror(ir_file));
return EXIT_FAILURE;
}
}
if(operation == JUMP_IF_0)
{
long bracket_pos = ftell(ir_file);
if(bracket_pos == -1)
{
fprintf(stderr, "Error getting file pointer: %d\n", errno);
return EXIT_FAILURE;
}
// Find corresponding closing bracket index
for(size_t bracket_index = 1; bracket_index;)
{
operation_t operation_search;
if(fread(&operation_search, sizeof(operation_t), 1, ir_file) != 1)
{
if(feof(ir_file))
{
fprintf(stderr, "Reached end of file before finding closing bracket.\n");
}
else
{
fprintf(stderr, "Error reading file: %d\n", ferror(ir_file));
}
return EXIT_FAILURE;
}
switch(operation_search)
{
case MEM_POINTER_ADD_NB:
case MEM_POINTER_SUB_NB:
case MEM_ADD_NB:
case MEM_SUB_NB:
case JUMP_IF_NOT_0:
if(fseek(ir_file, sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
break;
default:
break;
}
if(operation_search == JUMP_IF_0)
{
bracket_index++;
}
else if(operation_search == JUMP_IF_NOT_0)
{
bracket_index--;
}
}
long corresponding_bracket_pos = ftell(ir_file);
if(corresponding_bracket_pos == -1)
{
fprintf(stderr, "Error getting file pointer: %d\n", errno);
return EXIT_FAILURE;
}
if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
operand_t bracket_pos_operand = (operand_t)bracket_pos + sizeof(operand_t);
if(fwrite(&bracket_pos_operand, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
if(fseek(ir_file, bracket_pos, SEEK_SET))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
operand_t corresponding_bracket_pos_operand = (operand_t)corresponding_bracket_pos;
if(fwrite(&corresponding_bracket_pos_operand, sizeof(operand_t), 1, ir_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
return EXIT_FAILURE;
}
}
switch(operation)
{
case MEM_POINTER_ADD_NB:
case MEM_POINTER_SUB_NB:
case MEM_ADD_NB:
case MEM_SUB_NB:
case JUMP_IF_NOT_0:
if(fseek(ir_file, sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
return EXIT_FAILURE;
}
break;
default:
break;
}
}
return EXIT_SUCCESS;
}

34
src/ir.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _IR_H
#define _IR_H
#include <stdint.h>
#include <stdio.h>
// The advanced version of operations always have value = simple version + 1
enum operations_t {
NONE,
MEM_POINTER_ADD,
MEM_POINTER_ADD_NB,
MEM_POINTER_SUB,
MEM_POINTER_SUB_NB,
MEM_ADD,
MEM_ADD_NB,
MEM_SUB,
MEM_SUB_NB,
JUMP_IF_0,
JUMP_IF_NOT_0,
PRINT_CHAR,
GET_CHAR
};
typedef uint8_t operation_t;
typedef uint32_t operand_t;
operation_t char_to_operation(int c);
int process_operation_into_ir_file(FILE *ir_file, operation_t operation, operation_t *last_operation);
int calculate_jump_operands(FILE *ir_file);
#endif // _IR_H

View File

@ -3,32 +3,12 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <errno.h> #include <errno.h>
#include "ir.h"
#include <time.h> #include <time.h>
#define BRACKETS_NB_MAX 1024
#define DATA_SIZE_MAX 65536 #define DATA_SIZE_MAX 65536
#define PROGRAM_SIZE_MAX 65536
// The advanced version of operations should always have value = simple version + 1
enum operations_t {
NONE,
MEM_POINTER_ADD,
MEM_POINTER_ADD_NB,
MEM_POINTER_SUB,
MEM_POINTER_SUB_NB,
MEM_ADD,
MEM_ADD_NB,
MEM_SUB,
MEM_SUB_NB,
JUMP_IF_0,
JUMP_IF_NOT_0,
PRINT_CHAR,
GET_CHAR
};
typedef uint8_t operation_t;
typedef int operand_t;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -41,7 +21,7 @@ int main(int argc, char *argv[])
} }
FILE *program_file = NULL; FILE *program_file = NULL;
FILE *intermediate_representation_file = NULL; FILE *ir_file = NULL;
program_file = fopen(argv[1], "r"); program_file = fopen(argv[1], "r");
if(program_file == NULL) if(program_file == NULL)
@ -50,14 +30,14 @@ int main(int argc, char *argv[])
goto end; goto end;
} }
intermediate_representation_file = tmpfile(); ir_file = tmpfile();
if(intermediate_representation_file == NULL) if(ir_file == NULL)
{ {
fprintf(stderr, "Error creating tmp file: %d\n", errno); fprintf(stderr, "Error creating tmp file: %d\n", errno);
goto end; goto end;
} }
// Strip program file // Convert into intermediate representation
while(true) while(true)
{ {
int c = fgetc(program_file); int c = fgetc(program_file);
@ -75,326 +55,83 @@ int main(int argc, char *argv[])
break; break;
} }
operation_t operation = NONE;
static operation_t last_operation = NONE; static operation_t last_operation = NONE;
operation_t operation = char_to_operation(c);
switch(c) if(process_operation_into_ir_file(ir_file, operation, &last_operation))
{ {
case '>': goto end;
operation = MEM_POINTER_ADD;
break;
case '<':
operation = MEM_POINTER_SUB;
break;
case '+':
operation = MEM_ADD;
break;
case '-':
operation = MEM_SUB;
break;
case '[':
operation = JUMP_IF_0;
break;
case ']':
operation = JUMP_IF_NOT_0;
break;
case '.':
operation = PRINT_CHAR;
break;
case ',':
operation = GET_CHAR;
break;
default:
break;
} }
if(operation == NONE)
{
continue;
}
switch(operation)
{
case MEM_POINTER_ADD:
case MEM_POINTER_SUB:
case MEM_ADD:
case MEM_SUB:
if(operation == last_operation)
{
operation++; // Go to advanced version of operation
if(fseek(intermediate_representation_file, -1, SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
if(fwrite(&operation, sizeof(operation_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
operand_t nb = 2;
if(fwrite(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
}
else if(operation + 1 == last_operation)
{
operation++;
operand_t nb;
if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
if(fread(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error reading file: %d\n", errno);
goto end;
}
nb++;
if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
if(fwrite(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
}
else
{
if(fwrite(&operation, sizeof(operation_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
}
break;
case JUMP_IF_0:
case JUMP_IF_NOT_0:
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
operand_t jump_pos = 0;
if(fwrite(&jump_pos, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
break;
case PRINT_CHAR:
case GET_CHAR:
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
break;
default:
break;
}
last_operation = operation;
} }
if(fclose(program_file) == EOF) if(fclose(program_file) == EOF)
{ {
program_file = NULL; program_file = NULL;
fprintf(stderr, "Error closing program file: %d\n", errno); fprintf(stderr, "Error closing program file: %d\n", errno);
goto end; goto end;
} }
program_file = NULL; program_file = NULL;
// Parse brackets if(fseek(ir_file, 0, SEEK_END))
rewind(intermediate_representation_file);
while(true)
{ {
operation_t operation; fprintf(stderr, "Error seeking file: %d\n", errno);
size_t nb_read = fread(&operation, sizeof(operation_t), 1, intermediate_representation_file); goto end;
if(nb_read != 1)
{
if(feof(intermediate_representation_file))
{
break;
}
else
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
}
if(operation == JUMP_IF_0)
{
long bracket_pos = ftell(intermediate_representation_file);
if(bracket_pos == -1)
{
fprintf(stderr, "Error getting file pointer: %d\n", errno);
goto end;
}
// Find corresponding closing bracket index
for(size_t bracket_index = 1; bracket_index;)
{
operation_t operation_search;
nb_read = fread(&operation_search, sizeof(operation_t), 1, intermediate_representation_file);
if(nb_read != 1)
{
if(feof(intermediate_representation_file))
{
fprintf(stderr, "Reached end of file before finding closing bracket.\n");
}
else
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
}
goto end;
}
switch(operation_search)
{
case MEM_POINTER_ADD_NB:
case MEM_POINTER_SUB_NB:
case MEM_ADD_NB:
case MEM_SUB_NB:
case JUMP_IF_NOT_0:
if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
break;
default:
break;
}
if(operation_search == JUMP_IF_0)
{
bracket_index++;
}
else if(operation_search == JUMP_IF_NOT_0)
{
bracket_index--;
}
}
long corresponding_bracket_pos = ftell(intermediate_representation_file);
if(corresponding_bracket_pos == -1)
{
fprintf(stderr, "Error getting file pointer: %d\n", errno);
goto end;
}
if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
operand_t bracket_pos_operand = (operand_t)bracket_pos + sizeof(operand_t);
if(fwrite(&bracket_pos_operand, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
if(fseek(intermediate_representation_file, bracket_pos, SEEK_SET))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
operand_t corresponding_bracket_pos_operand = (operand_t)corresponding_bracket_pos;
if(fwrite(&corresponding_bracket_pos_operand, sizeof(operand_t), 1, intermediate_representation_file) != 1)
{
fprintf(stderr, "Error writing file: %d\n", errno);
goto end;
}
}
switch(operation)
{
case MEM_POINTER_ADD_NB:
case MEM_POINTER_SUB_NB:
case MEM_ADD_NB:
case MEM_SUB_NB:
case JUMP_IF_NOT_0:
fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR);
break;
default:
break;
}
} }
rewind(intermediate_representation_file); long program_size = ftell(ir_file);
if(program_size == -1)
{
fprintf(stderr, "Error getting file pointer: %d\n", errno);
return EXIT_FAILURE;
}
if(program_size > PROGRAM_SIZE_MAX)
{
fputs("Program too big.\n", stderr);
goto end;
}
rewind(ir_file);
if(calculate_jump_operands(ir_file))
{
goto end;
}
rewind(ir_file);
uint8_t program[PROGRAM_SIZE_MAX];
if(fread(program, sizeof(uint8_t), program_size, ir_file) != program_size)
{
fprintf(stderr, "Error reading file: %d\n", errno);
goto end;
}
if(fclose(ir_file))
{
ir_file = NULL;
fprintf(stderr, "Error closing ir file: %d\n", errno);
goto end;
}
ir_file = NULL;
// Program memory
uint8_t mem[DATA_SIZE_MAX] = {0}; uint8_t mem[DATA_SIZE_MAX] = {0};
size_t mem_pointer = 0; size_t mem_pointer = 0;
uint8_t nb_read;
operand_t operand; operand_t operand;
size_t program_pointer = 0;
while(true) while(true)
{ {
operation_t operation; operation_t operation = program[program_pointer];
nb_read = fread(&operation, sizeof(operation_t), 1, intermediate_representation_file); program_pointer++;
if(nb_read != 1) if(program_pointer > program_size)
{ {
if(feof(intermediate_representation_file)) break;
{
break;
}
else
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
} }
switch(operation) switch(operation)
@ -404,12 +141,8 @@ int main(int argc, char *argv[])
break; break;
case MEM_POINTER_ADD_NB: case MEM_POINTER_ADD_NB:
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); operand = *(operand_t *)&program[program_pointer];
if(nb_read != 1) program_pointer += sizeof(operand_t);
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
mem_pointer += operand; mem_pointer += operand;
break; break;
@ -418,12 +151,8 @@ int main(int argc, char *argv[])
break; break;
case MEM_POINTER_SUB_NB: case MEM_POINTER_SUB_NB:
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); operand = *(operand_t *)&program[program_pointer];
if(nb_read != 1) program_pointer += sizeof(operand_t);
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
mem_pointer -= operand; mem_pointer -= operand;
break; break;
@ -432,12 +161,8 @@ int main(int argc, char *argv[])
break; break;
case MEM_ADD_NB: case MEM_ADD_NB:
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); operand = *(operand_t *)&program[program_pointer];
if(nb_read != 1) program_pointer += sizeof(operand_t);
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
mem[mem_pointer] += operand; mem[mem_pointer] += operand;
break; break;
@ -446,64 +171,21 @@ int main(int argc, char *argv[])
break; break;
case MEM_SUB_NB: case MEM_SUB_NB:
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); operand = *(operand_t *)&program[program_pointer];
if(nb_read != 1) program_pointer += sizeof(operand_t);
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
mem[mem_pointer] -= operand; mem[mem_pointer] -= operand;
break; break;
case JUMP_IF_0: case JUMP_IF_0:
if(mem[mem_pointer] == 0)
{
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file);
if(nb_read != 1)
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
if(fseek(intermediate_representation_file, operand, SEEK_SET))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
}
else
{
if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
}
break;
case JUMP_IF_NOT_0: case JUMP_IF_NOT_0:
if(mem[mem_pointer]) if(operation == JUMP_IF_0 ? mem[mem_pointer] == 0 : mem[mem_pointer] != 0)
{ {
nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); operand = *(operand_t *)&program[program_pointer];
if(nb_read != 1) program_pointer = operand;
{
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
goto end;
}
if(fseek(intermediate_representation_file, operand, SEEK_SET))
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
} }
else else
{ {
if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR)) program_pointer += sizeof(operand_t);
{
fprintf(stderr, "Error seeking file: %d\n", errno);
goto end;
}
} }
break; break;
@ -524,9 +206,9 @@ int main(int argc, char *argv[])
status = EXIT_SUCCESS; status = EXIT_SUCCESS;
end: end:
if(intermediate_representation_file != NULL) if(ir_file != NULL)
{ {
if(fclose(intermediate_representation_file)) if(fclose(ir_file))
{ {
fprintf(stderr, "Error closing tmp file: %d\n", errno); fprintf(stderr, "Error closing tmp file: %d\n", errno);
} }