summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-02-17 19:14:49 +0100
committerEugen Wissner <belka@caraus.de>2026-02-17 19:59:15 +0100
commit8142680fb7d8e91061a8aa6bf25150c0a890d865 (patch)
tree9fa975843d16f104f2ba11f40ec67e7b8ab7c842
parent512a57cccae2e304ee99c29334d34a7b905db1e9 (diff)
downloadelna-8142680fb7d8e91061a8aa6bf25150c0a890d865.tar.gz
Allow compound types on the stack
-rw-r--r--boot/stage19/cl.elna251
1 files changed, 161 insertions, 90 deletions
diff --git a/boot/stage19/cl.elna b/boot/stage19/cl.elna
index 881bf88..2fd12a0 100644
--- a/boot/stage19/cl.elna
+++ b/boot/stage19/cl.elna
@@ -7,6 +7,8 @@ program;
(* Stage 19 compiler. *)
+(* - Aggregates can be allocated on the stack. *)
+
type
(**
* List of intermediate representation items.
@@ -18,14 +20,6 @@ type
data: Word;
code: Word
end;
- ElnaInstructionDeclaration = record
- next: Word;
- name: Word;
- length: Word;
- body: Word;
- parameters: Word;
- count: Word
- end;
(* Type representation. *)
ElnaTypeKind = (primitive, enumeration, _record, pointer, array);
@@ -540,6 +534,19 @@ type
value: Word;
length: Word
end;
+ ElnaRtlStaticVariable = record
+ next: Word;
+ name: Word;
+ length: Word;
+ body: Word
+ end;
+ ElnaRtlProcedure = record
+ next: Word;
+ name: Word;
+ length: Word;
+ body: Word;
+ variable_map: ^ElnaSymbolTable
+ end;
ElnaRtlInstruction = record
next: Word;
operator: ElnaRtlOperator;
@@ -579,13 +586,27 @@ type
t5,
t6
);
+ ElnaRtlTypeKind = (long_word, byte_array);
+ ElnaRtlType = record
+ kind: ElnaRtlTypeKind;
+ size: Word
+ end;
+ ElnaRtlTypeWord = record
+ kind: ElnaRtlTypeKind;
+ size: Word
+ end;
+ ElnaRtlTypeByteArray = record
+ kind: ElnaRtlTypeKind;
+ size: Word
+ end;
ElnaRtlInfo = record
- counter: Word
+ counter: Word;
+ rtl_type: ^ElnaRtlType;
+ allocated: Word
end;
var
symbol_table_global: [1024]Word;
- variable_map: [1024]Word;
compiler_strings: [1024]Word;
classification: [256]Word;
@@ -1232,18 +1253,6 @@ begin
return result
end;
-proc elna_instruction_module_create(data: Word, code: Word);
-var
- result: ^ElnaInstructionModule;
-begin
- result := malloc(#size(ElnaInstructionModule));
-
- result^.data := data;
- result^.code := code;
-
- return result
-end;
-
proc elna_tac_label(counter: Word, length: Word);
var
result: Word;
@@ -1368,17 +1377,16 @@ begin
end
end;
-proc elna_alloc_variable(operand_value: Word, operand_length: Word);
+proc elna_alloc_variable(operand_value: Word, operand_length: Word, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
begin
- pseudo_symbol := elna_symbol_table_lookup(@variable_map, operand_value, operand_length);
- if pseudo_symbol = nil then
- pseudo_symbol := malloc(#size(ElnaRtlInfo));
+ pseudo_symbol := elna_symbol_table_lookup(variable_map, operand_value, operand_length);
+ if pseudo_symbol^.allocated = false then
+ pseudo_symbol^.allocated := true;
pseudo_symbol^.counter := temporary_variable_counter;
- elna_symbol_table_enter(@variable_map, operand_value, operand_length, pseudo_symbol);
- temporary_variable_counter := temporary_variable_counter + 4
+ temporary_variable_counter := temporary_variable_counter + pseudo_symbol^.rtl_type^.size
end;
return pseudo_symbol
end;
@@ -1388,7 +1396,7 @@ end;
* to be a register, but is not a register, then this procedure rewrites it
* to a temporary register and preserves its value in the following instruction.
*)
-proc elna_alloc_operation_target(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_operation_target(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
store_instruction: ^ElnaRtlInstruction;
@@ -1397,7 +1405,8 @@ begin
store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
store_instruction^.next := instruction^.next;
- pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
+ variable_map);
elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
@@ -1406,23 +1415,24 @@ begin
end
end;
-proc elna_alloc_load_address(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_load_address(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
begin
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
- pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
+ variable_map);
instruction^.operator := ElnaRtlOperator.addi;
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.sp, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol^.counter, 0)
end;
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
end
end;
-proc elna_alloc_store(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_store(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
old_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
@@ -1431,7 +1441,8 @@ begin
old_instruction := malloc(#size(ElnaRtlInstruction));
memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
- pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
+ variable_map);
instruction^.operator := ElnaRtlOperator.lw;
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
@@ -1442,7 +1453,7 @@ begin
end
end;
-proc elna_alloc_load(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_load(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
old_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
@@ -1451,7 +1462,8 @@ begin
old_instruction := malloc(#size(ElnaRtlInstruction));
memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
- pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
+ variable_map);
old_instruction^.operator := ElnaRtlOperator.sw;
elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
@@ -1462,14 +1474,15 @@ begin
end
end;
-proc elna_alloc_instruction(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_instruction(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
old_instruction: ^ElnaRtlInstruction;
begin
if instruction^.operator = ElnaRtlOperator.move then
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
+ variable_map);
instruction^.operator = ElnaRtlOperator.sw;
instruction^.operands[1].kind := instruction^.operands[2].kind;
@@ -1480,40 +1493,42 @@ begin
goto elna_alloc_instruction_end
end;
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
- pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
+ variable_map);
instruction^.operator = ElnaRtlOperator.lw;
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
goto elna_alloc_instruction_end
end
elsif instruction^.operator = ElnaRtlOperator.la then
- elna_alloc_load_address(instruction)
+ elna_alloc_load_address(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.lw then
- elna_alloc_load(instruction)
+ elna_alloc_load(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sw then
- elna_alloc_store(instruction)
+ elna_alloc_store(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._or then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.and then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.mul then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sub then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.add then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._xor then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.rem then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.slt then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.beqz then
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
old_instruction := malloc(#size(ElnaRtlInstruction));
memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
- pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length);
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
+ variable_map);
instruction^.operator := ElnaRtlOperator.lw;
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
@@ -1525,11 +1540,11 @@ begin
goto elna_alloc_instruction_end
end
elsif instruction^.operator = ElnaRtlOperator.seqz then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.snez then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.xori then
- elna_alloc_operation_target(instruction)
+ elna_alloc_operation_target(instruction, variable_map)
end;
.elna_alloc_instruction_end;
end;
@@ -1604,12 +1619,12 @@ begin
return first_copy
end;
-proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction);
+proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
begin
.elna_alloc_instructions_start;
if instruction <> nil then
- elna_alloc_instruction(instruction);
+ elna_alloc_instruction(instruction, variable_map);
instruction := instruction^.next;
goto elna_alloc_instructions_start
end
@@ -1625,15 +1640,14 @@ begin
end
end;
-proc elna_alloc_procedure(rtl_declaration: ^ElnaInstructionDeclaration);
+proc elna_alloc_procedure(rtl_declaration: ^ElnaRtlProcedure);
var
stack_instruction: ^ElnaRtlInstruction;
begin
.elna_alloc_procedure_loop;
temporary_variable_counter := 0;
- variable_map := 0;
- elna_alloc_instructions(rtl_declaration^.body);
+ elna_alloc_instructions(rtl_declaration^.body, rtl_declaration^.variable_map);
stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack);
stack_instruction^.next := rtl_declaration^.body;
@@ -1651,7 +1665,7 @@ begin
end
end;
-proc elna_riscv_procedure(procedure: ^ElnaInstructionDeclaration);
+proc elna_riscv_procedure(procedure: ^ElnaRtlProcedure);
begin
.elna_riscv_procedure_loop;
@@ -1670,7 +1684,7 @@ begin
end
end;
-proc elna_riscv_variable(variable: ^ElnaInstructionDeclaration);
+proc elna_riscv_variable(variable: ^ElnaRtlStaticVariable);
begin
.elna_riscv_variable_loop;
if variable <> 0 then
@@ -1685,13 +1699,13 @@ end;
proc elna_rtl_module_declaration(tac_module: ^ElnaInstructionModule);
var
- code_part: ^ElnaInstructionDeclaration;
- data_part: ^ElnaInstructionDeclaration;
+ result: ^ElnaInstructionModule;
begin
- data_part := elna_rtl_globals(tac_module^.data);
- code_part := elna_rtl_procedures(tac_module^.code);
+ result := malloc(#size(ElnaInstructionModule));
+ result^.data := elna_rtl_globals(tac_module^.data);
+ result^.code := elna_rtl_procedures(tac_module^.code);
- return elna_instruction_module_create(data_part, code_part)
+ return result
end;
proc elna_alloc_module(pair: ^ElnaInstructionModule);
@@ -3614,9 +3628,9 @@ end;
proc elna_rtl_global_declaration(tac_declaration: ^ElnaTacStaticVariable);
var
- result: ^ElnaInstructionDeclaration;
+ result: ^ElnaRtlStaticVariable;
begin
- result := malloc(#size(ElnaInstructionDeclaration));
+ result := malloc(#size(ElnaRtlStaticVariable));
result^.next := nil;
result^.name := tac_declaration^.name;
@@ -3663,13 +3677,72 @@ begin
return result
end;
-proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaInstructionDeclaration);
+(* Returns whether the provided type is array or record. *)
+proc elna_type_is_aggregate(_type: ^ElnaType);
+var
+ lhs: Word;
+ rhs: Word;
+begin
+ lhs := _type^.kind = ElnaTypeKind._record;
+ rhs := _type^.kind = ElnaTypeKind.array;
+
+ return lhs or rhs
+end;
+
+proc elna_rtl_symbol_table(symbol_table: ^ElnaSymbolTable);
+var
+ variable_map: ^ElnaSymbolTable;
+ count: Word;
+ current_entry: ^ElnaSymbolEntry;
+ pseudo_symbol: ^ElnaRtlInfo;
+ variable_info: ^ElnaSymbolTemporaryInfo;
+ byte_array: ^ElnaRtlTypeByteArray;
+ long_word: ^ElnaRtlTypeWord;
+begin
+ variable_map := malloc(16384);
+ variable_map^.count := 0;
+
+ count := symbol_table^.count;
+ current_entry := symbol_table + 4;
+
+ .elna_rtl_symbol_table_loop;
+ if count > 0 then
+ variable_info := current_entry^.symbol_info;
+
+ pseudo_symbol := malloc(#size(ElnaRtlInfo));
+ pseudo_symbol^.allocated := false;
+
+ if elna_type_is_aggregate(variable_info^.variable_type) then
+ long_word := malloc(#size(ElnaRtlTypeWord));
+ long_word^.kind := ElnaRtlTypeKind.long_word;
+ long_word^.size := variable_info^.variable_type^.size;
+
+ pseudo_symbol^.rtl_type = long_word
+ else
+ byte_array := malloc(#size(ElnaRtlTypeByteArray));
+ byte_array^.kind := ElnaRtlTypeKind.byte_array;
+ byte_array^.size := variable_info^.variable_type^.size;
+
+ pseudo_symbol^.rtl_type = byte_array
+ end;
+ elna_symbol_table_enter(variable_map, current_entry^.name, current_entry^.length, pseudo_symbol);
+
+ count := count - 1;
+ current_entry := current_entry + #size(ElnaSymbolEntry);
+
+ goto elna_rtl_symbol_table_loop
+ end;
+
+ return variable_map;
+end;
+
+proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaTacProcedure);
var
- result: ^ElnaInstructionDeclaration;
+ result: ^ElnaRtlProcedure;
body: ^ElnaRtlInstruction;
parameters: ^ElnaRtlInstruction;
begin
- result := malloc(#size(ElnaInstructionDeclaration));
+ result := malloc(#size(ElnaRtlProcedure));
result^.next := nil;
result^.name := tac_declaration^.name;
@@ -3678,6 +3751,7 @@ begin
parameters = elna_rtl_parameters(tac_declaration^.parameters, tac_declaration^.count);
body := elna_rtl_instructions(tac_declaration^.body);
result^.body := elna_instruction_list_concatenate(parameters, body);
+ result^.variable_map := elna_rtl_symbol_table(tac_declaration^.symbol_table);
return result
end;
@@ -3738,9 +3812,9 @@ end;
proc elna_rtl_globals(tac_procedure: ^ElnaTacStaticVariable);
var
- current_copy: ^ElnaInstructionDeclaration;
- next_copy: ^ElnaInstructionDeclaration;
- first_copy: ^ElnaInstructionDeclaration;
+ current_copy: ^ElnaRtlStaticVariable;
+ next_copy: ^ElnaRtlStaticVariable;
+ first_copy: ^ElnaRtlStaticVariable;
begin
if tac_procedure <> nil then
first_copy := elna_rtl_global_declaration(tac_procedure);
@@ -3764,11 +3838,11 @@ begin
return first_copy
end;
-proc elna_rtl_procedures(tac_procedure: ^ElnaInstructionDeclaration);
+proc elna_rtl_procedures(tac_procedure: ^ElnaTacProcedure);
var
- current_copy: ^ElnaInstructionDeclaration;
- next_copy: ^ElnaInstructionDeclaration;
- first_copy: ^ElnaInstructionDeclaration;
+ current_copy: ^ElnaRtlProcedure;
+ next_copy: ^ElnaRtlProcedure;
+ first_copy: ^ElnaRtlProcedure;
begin
if tac_procedure <> nil then
first_copy := elna_rtl_procedure_declaration(tac_procedure);
@@ -3794,9 +3868,9 @@ end;
proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration);
var
- result: ^ElnaInstructionDeclaration;
- current_procedure: ^ElnaInstructionDeclaration;
- first_procedure: ^ElnaInstructionDeclaration;
+ result: ^ElnaTacProcedure;
+ current_procedure: ^ElnaTacProcedure;
+ first_procedure: ^ElnaTacProcedure;
begin
first_procedure := nil;
@@ -4068,18 +4142,15 @@ begin
return result
end;
-(**
- * Process the source code and print the generated code.
- *)
proc elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration);
var
- data_part: ^ElnaTacStaticVariable;
- code_part: Word;
+ result: ^ElnaInstructionModule;
begin
- data_part := elna_tac_var_part(parser_node^.globals);
- code_part := elna_tac_procedures(parser_node^.procedures);
+ result := malloc(#size(ElnaInstructionModule));
+ result^.data := elna_tac_var_part(parser_node^.globals);
+ result^.code := elna_tac_procedures(parser_node^.procedures);
- return elna_instruction_module_create(data_part, code_part)
+ return result
end;
proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration);