#define _POSIX_C_SOURCE 200809L #include "ir.h" #include "../runtime/labeltable.h" #include #include #include RavaInstructionList_t* rava_instruction_list_create() { RavaInstructionList_t *list = calloc(1, sizeof(RavaInstructionList_t)); list->capacity = 16; list->instructions = malloc(sizeof(RavaInstruction_t) * list->capacity); list->count = 0; list->next_label_id = 1; return list; } void rava_instruction_list_destroy(RavaInstructionList_t *list) { if (!list) return; free(list->instructions); free(list); } void rava_instruction_list_add(RavaInstructionList_t *list, RavaInstruction_t instr) { if (list->count >= list->capacity) { list->capacity *= 2; list->instructions = realloc(list->instructions, sizeof(RavaInstruction_t) * list->capacity); } list->instructions[list->count++] = instr; } int rava_instruction_list_new_label(RavaInstructionList_t *list) { return list->next_label_id++; } RavaMethod_t* rava_method_create(const char *name, RavaType_t *return_type) { RavaMethod_t *method = calloc(1, sizeof(RavaMethod_t)); method->name = strdup(name); method->return_type = return_type; method->param_types = NULL; method->param_count = 0; method->local_count = 0; method->instructions = rava_instruction_list_create(); method->label_table = NULL; return method; } void rava_method_destroy(RavaMethod_t *method) { if (!method) return; free(method->name); free(method->param_types); rava_instruction_list_destroy(method->instructions); if (method->label_table) { rava_labeltable_destroy(method->label_table); } free(method); } RavaClass_t* rava_class_create(const char *name) { RavaClass_t *class = calloc(1, sizeof(RavaClass_t)); class->name = strdup(name); class->superclass = NULL; class->methods = NULL; class->method_count = 0; class->method_capacity = 0; return class; } void rava_class_destroy(RavaClass_t *class) { if (!class) return; free(class->name); free(class->superclass); for (size_t i = 0; i < class->method_count; i++) { rava_method_destroy(class->methods[i]); } free(class->methods); free(class); } void rava_class_add_method(RavaClass_t *class, RavaMethod_t *method) { if (class->method_count >= class->method_capacity) { size_t new_capacity = class->method_capacity == 0 ? 4 : class->method_capacity * 2; class->methods = realloc(class->methods, sizeof(RavaMethod_t*) * new_capacity); class->method_capacity = new_capacity; } class->methods[class->method_count++] = method; } RavaProgram_t* rava_program_create() { RavaProgram_t *program = calloc(1, sizeof(RavaProgram_t)); program->classes = NULL; program->class_count = 0; program->class_capacity = 0; return program; } void rava_program_destroy(RavaProgram_t *program) { if (!program) return; for (size_t i = 0; i < program->class_count; i++) { rava_class_destroy(program->classes[i]); } free(program->classes); free(program); } void rava_program_add_class(RavaProgram_t *program, RavaClass_t *class) { if (program->class_count >= program->class_capacity) { size_t new_capacity = program->class_capacity == 0 ? 4 : program->class_capacity * 2; program->classes = realloc(program->classes, sizeof(RavaClass_t*) * new_capacity); program->class_capacity = new_capacity; } program->classes[program->class_count++] = class; } static const char* _rava_opcode_name(RavaOpCode_e opcode) { switch (opcode) { case RAVA_OP_NOP: return "NOP"; case RAVA_OP_LOAD_CONST: return "LOAD_CONST"; case RAVA_OP_LOAD_LOCAL: return "LOAD_LOCAL"; case RAVA_OP_STORE_LOCAL: return "STORE_LOCAL"; case RAVA_OP_ADD: return "ADD"; case RAVA_OP_SUB: return "SUB"; case RAVA_OP_MUL: return "MUL"; case RAVA_OP_DIV: return "DIV"; case RAVA_OP_MOD: return "MOD"; case RAVA_OP_NEG: return "NEG"; case RAVA_OP_EQ: return "EQ"; case RAVA_OP_NE: return "NE"; case RAVA_OP_LT: return "LT"; case RAVA_OP_LE: return "LE"; case RAVA_OP_GT: return "GT"; case RAVA_OP_GE: return "GE"; case RAVA_OP_JUMP: return "JUMP"; case RAVA_OP_JUMP_IF_TRUE: return "JUMP_IF_TRUE"; case RAVA_OP_JUMP_IF_FALSE: return "JUMP_IF_FALSE"; case RAVA_OP_LABEL: return "LABEL"; case RAVA_OP_CALL: return "CALL"; case RAVA_OP_CALL_STATIC: return "CALL_STATIC"; case RAVA_OP_RETURN: return "RETURN"; case RAVA_OP_RETURN_VOID: return "RETURN_VOID"; case RAVA_OP_NEW: return "NEW"; case RAVA_OP_NEW_ARRAY: return "NEW_ARRAY"; case RAVA_OP_ARRAY_LENGTH: return "ARRAY_LENGTH"; case RAVA_OP_LOAD_ARRAY: return "LOAD_ARRAY"; case RAVA_OP_STORE_ARRAY: return "STORE_ARRAY"; case RAVA_OP_POP: return "POP"; case RAVA_OP_DUP: return "DUP"; case RAVA_OP_PRINT: return "PRINT"; case RAVA_OP_PRINTLN: return "PRINTLN"; default: return "UNKNOWN"; } } void rava_ir_print(RavaProgram_t *program) { if (!program) return; printf("IR Program (%zu classes)\n", program->class_count); printf("================================================================================\n\n"); for (size_t i = 0; i < program->class_count; i++) { RavaClass_t *class = program->classes[i]; printf("Class: %s\n", class->name); for (size_t j = 0; j < class->method_count; j++) { RavaMethod_t *method = class->methods[j]; printf(" Method: %s (locals: %d)\n", method->name, method->local_count); for (size_t k = 0; k < method->instructions->count; k++) { RavaInstruction_t *instr = &method->instructions->instructions[k]; printf(" %04zu %-15s", k, _rava_opcode_name(instr->opcode)); switch (instr->opcode) { case RAVA_OP_LOAD_CONST: printf(" %lld", (long long)instr->operand.int_value); break; case RAVA_OP_LOAD_LOCAL: case RAVA_OP_STORE_LOCAL: printf(" [%d]", instr->operand.var.index); break; case RAVA_OP_LABEL: case RAVA_OP_JUMP: case RAVA_OP_JUMP_IF_TRUE: case RAVA_OP_JUMP_IF_FALSE: printf(" L%d", instr->operand.label_id); break; case RAVA_OP_CALL_STATIC: printf(" %s.%s", instr->operand.call.class_name, instr->operand.call.method_name); break; default: break; } printf("\n"); } printf("\n"); } } }