Use operand record in TAC expression visitor

This commit is contained in:
2026-02-22 00:11:41 +01:00
parent 8142680fb7
commit b987dd741a
4 changed files with 5372 additions and 49 deletions

View File

@@ -38,11 +38,20 @@ desc 'Convert previous stage language into the current stage language'
task :convert do task :convert do
File.open('boot/stage20/cl.elna', 'w') do |current_stage| File.open('boot/stage20/cl.elna', 'w') do |current_stage|
File.readlines('boot/stage19/cl.elna').each do |line| File.readlines('boot/stage19/cl.elna').each do |line|
if line.include? "_assign_at(@classification, 1, ElnaLexerClass.eof)" current_stage << line
current_stage << "\tclassification[1] := ElnaLexerClass.eof;\n"
else
current_stage << line
end
end end
current_stage << <<~FUN
proc f(m: ElnaInstructionModule);
begin
end;
proc g();
var
x: ElnaInstructionModule;
begin
f(x)
end;
FUN
end end
end end

View File

@@ -252,7 +252,8 @@ type
length: Word; length: Word;
body: Word; body: Word;
temporaries: Word; temporaries: Word;
parameters: Word parameters: Word;
return_type: ^ElnaTreeNode
end; end;
ElnaTreeTypeDeclaration = record ElnaTreeTypeDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
@@ -528,7 +529,7 @@ type
allocate_stack, allocate_stack,
ret ret
); );
ElnaRtlKind = (register, immediate, symbol, pseudo, offset, pseudo_mem); ElnaRtlKind = (register, immediate, symbol, pseudo, offset);
ElnaRtlOperand = record ElnaRtlOperand = record
kind: ElnaRtlKind; kind: ElnaRtlKind;
value: Word; value: Word;
@@ -1008,17 +1009,15 @@ begin
return result return result
end; end;
proc elna_rtl_call(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction); proc elna_rtl_call(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var var
argument_count: Word; argument_count: Word;
current_argument: ^ElnaTacOperand; current_argument: ^ElnaTacOperand;
argument_type: Word;
argument_value: Word;
argument_length: Word;
argument_move: ^ElnaRtlInstruction; argument_move: ^ElnaRtlInstruction;
current_register: Word; current_register: Word;
first_instruction: Word; first_instruction: Word;
current_instruction: Word; current_instruction: Word;
variable_info: ^ElnaRtlInfo;
begin begin
current_register := 0; current_register := 0;
first_instruction := nil; first_instruction := nil;
@@ -1031,15 +1030,12 @@ begin
if argument_count > 0 then if argument_count > 0 then
argument_count := argument_count - 1; argument_count := argument_count - 1;
argument_type := current_argument^.kind; if current_argument^.kind = ElnaTacKind.pseudo then
argument_value := current_argument^.value; argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
argument_length := current_argument^.length; elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
current_argument := current_argument + #size(ElnaTacOperand); elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.pseudo,
current_argument^.value, current_argument^.length)
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move); end;
elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, argument_type, argument_value, argument_length);
if first_instruction = nil then if first_instruction = nil then
first_instruction := argument_move first_instruction := argument_move
else else
@@ -1047,6 +1043,7 @@ begin
end; end;
current_instruction := argument_move; current_instruction := argument_move;
current_argument := current_argument + #size(ElnaTacOperand);
current_register := current_register + 1; current_register := current_register + 1;
goto elna_rtl_call_loop goto elna_rtl_call_loop
@@ -1119,7 +1116,7 @@ begin
return result return result
end; end;
proc elna_rtl_instruction(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction); proc elna_rtl_instruction(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var var
result: ^ElnaRtlInstruction; result: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction; operands: ^ElnaRtlInstruction;
@@ -1140,7 +1137,7 @@ begin
elsif tac_instruction^.operator = ElnaTacOperator.store then elsif tac_instruction^.operator = ElnaTacOperator.store then
result := elna_rtl_store(tac_instruction, next_instruction) result := elna_rtl_store(tac_instruction, next_instruction)
elsif tac_instruction^.operator = ElnaTacOperator.proc_call then elsif tac_instruction^.operator = ElnaTacOperator.proc_call then
result := elna_rtl_call(tac_instruction, next_instruction) result := elna_rtl_call(tac_instruction, next_instruction, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.subtract then elsif tac_instruction^.operator = ElnaTacOperator.subtract then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.sub) result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.sub)
elsif tac_instruction^.operator = ElnaTacOperator.multiply then elsif tac_instruction^.operator = ElnaTacOperator.multiply then
@@ -1591,7 +1588,7 @@ begin
_write_c('\n') _write_c('\n')
end; end;
proc elna_rtl_instructions(instruction: ^ElnaTacInstruction); proc elna_rtl_instructions(instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var var
last_copy: ^ElnaRtlInstruction; last_copy: ^ElnaRtlInstruction;
current_copy: ^ElnaRtlInstruction; current_copy: ^ElnaRtlInstruction;
@@ -1599,7 +1596,7 @@ var
first_copy: ^ElnaRtlInstruction; first_copy: ^ElnaRtlInstruction;
begin begin
if instruction <> nil then if instruction <> nil then
first_copy := elna_rtl_instruction(instruction, @current_copy); first_copy := elna_rtl_instruction(instruction, @current_copy, variable_map);
instruction := instruction^.next instruction := instruction^.next
else else
first_copy := nil; first_copy := nil;
@@ -1608,7 +1605,7 @@ begin
.elna_rtl_instructions_start; .elna_rtl_instructions_start;
if instruction <> nil then if instruction <> nil then
next_copy := elna_rtl_instruction(instruction, @last_copy); next_copy := elna_rtl_instruction(instruction, @last_copy, variable_map);
instruction := instruction^.next; instruction := instruction^.next;
current_copy^.next := next_copy; current_copy^.next := next_copy;
@@ -2874,10 +2871,10 @@ begin
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacKind.symbol, condition_label, 0); elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacKind.symbol, condition_label, 0);
elna_instruction_list_concatenate(first_instruction, current_instruction); first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
instruction := elna_tac_statements(parser_node^.statements, symbol_table); instruction := elna_tac_statements(parser_node^.statements, symbol_table);
if instruction <> 0 then if instruction <> nil then
elna_instruction_list_concatenate(current_instruction, instruction); elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction current_instruction := instruction
end; end;
@@ -3563,10 +3560,16 @@ begin
_elna_lexer_skip_token(); _elna_lexer_skip_token();
result^.parameters := parameter_head; result^.parameters := parameter_head;
(* Skip semicolon and newline. *) (* Skip semicolon or arrow. *)
_elna_lexer_read_token(@token_kind); _elna_lexer_read_token(@token_kind);
_elna_lexer_skip_token(); _elna_lexer_skip_token();
if token_kind = ElnaLexerKind.arrow then
result^.return_type := elna_parser_type_expression()
else
result^.return_type := nil
end;
parameter_head := elna_parser_var_part(); parameter_head := elna_parser_var_part();
result^.temporaries := parameter_head; result^.temporaries := parameter_head;
@@ -3713,17 +3716,17 @@ begin
pseudo_symbol^.allocated := false; pseudo_symbol^.allocated := false;
if elna_type_is_aggregate(variable_info^.variable_type) then 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 := malloc(#size(ElnaRtlTypeByteArray));
byte_array^.kind := ElnaRtlTypeKind.byte_array; byte_array^.kind := ElnaRtlTypeKind.byte_array;
byte_array^.size := variable_info^.variable_type^.size; byte_array^.size := variable_info^.variable_type^.size;
pseudo_symbol^.rtl_type = byte_array pseudo_symbol^.rtl_type := byte_array
else
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
end; end;
elna_symbol_table_enter(variable_map, current_entry^.name, current_entry^.length, pseudo_symbol); elna_symbol_table_enter(variable_map, current_entry^.name, current_entry^.length, pseudo_symbol);
@@ -3749,9 +3752,9 @@ begin
result^.length := tac_declaration^.length; result^.length := tac_declaration^.length;
parameters = elna_rtl_parameters(tac_declaration^.parameters, tac_declaration^.count); 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); result^.variable_map := elna_rtl_symbol_table(tac_declaration^.symbol_table);
body := elna_rtl_instructions(tac_declaration^.body, result^.variable_map);
result^.body := elna_instruction_list_concatenate(parameters, body);
return result return result
end; end;
@@ -5039,7 +5042,7 @@ begin
return result return result
end; end;
proc _elna_lexer_classify_keyword(position_start: Word, position_end: Word); proc elna_lexer_classify_keyword(position_start: Word, position_end: Word);
var var
result: Word; result: Word;
token_length: Word; token_length: Word;
@@ -5095,7 +5098,7 @@ begin
return result return result
end; end;
proc _elna_lexer_classify_finalize(start_position: Word); proc elna_lexer_classify_finalize(start_position: Word);
var var
character: Word; character: Word;
result: Word; result: Word;
@@ -5119,7 +5122,7 @@ begin
return result return result
end; end;
proc _elna_lexer_classify_single(start_position: Word); proc elna_lexer_classify_single(start_position: Word);
var var
character: Word; character: Word;
result: Word; result: Word;
@@ -5161,7 +5164,7 @@ begin
return result return result
end; end;
proc _elna_lexer_classify_composite(start_position: Word, one_before_last: Word); proc elna_lexer_classify_composite(start_position: Word, one_before_last: Word);
var var
first_character: Word; first_character: Word;
last_character: Word; last_character: Word;
@@ -5182,12 +5185,14 @@ begin
if last_character = '=' then if last_character = '=' then
result := ElnaLexerKind.greater_equal result := ElnaLexerKind.greater_equal
end end
elsif first_character = '-' then
result := ElnaLexerKind.arrow
end; end;
return result return result
end; end;
proc _elna_lexer_classify_delimited(start_position: Word, end_position: Word); proc elna_lexer_classify_delimited(start_position: Word, end_position: Word);
var var
token_length: Word; token_length: Word;
delimiter: Word; delimiter: Word;
@@ -5206,7 +5211,7 @@ begin
return result return result
end; end;
proc _elna_lexer_classify_integer(start_position: Word, end_position: Word); proc elna_lexer_classify_integer(start_position: Word, end_position: Word);
return ElnaLexerKind.integer return ElnaLexerKind.integer
end; end;
@@ -5223,29 +5228,29 @@ begin
elsif action_to_perform = ElnaLexerAction.single then elsif action_to_perform = ElnaLexerAction.single then
lexer_state.finish := lexer_state.finish + 1; lexer_state.finish := lexer_state.finish + 1;
intermediate := _elna_lexer_classify_single(lexer_state.start); intermediate := elna_lexer_classify_single(lexer_state.start);
kind^ := intermediate kind^ := intermediate
elsif action_to_perform = ElnaLexerAction.eof then elsif action_to_perform = ElnaLexerAction.eof then
intermediate := ElnaLexerKind.eof; intermediate := ElnaLexerKind.eof;
kind^ := intermediate kind^ := intermediate
elsif action_to_perform = ElnaLexerAction.finalize then elsif action_to_perform = ElnaLexerAction.finalize then
intermediate := _elna_lexer_classify_finalize(lexer_state.start); intermediate := elna_lexer_classify_finalize(lexer_state.start);
kind^ := intermediate kind^ := intermediate
elsif action_to_perform = ElnaLexerAction.composite then elsif action_to_perform = ElnaLexerAction.composite then
intermediate := _elna_lexer_classify_composite(lexer_state.start, lexer_state.finish); intermediate := elna_lexer_classify_composite(lexer_state.start, lexer_state.finish);
kind^ := intermediate; kind^ := intermediate;
lexer_state.finish := lexer_state.finish + 1 lexer_state.finish := lexer_state.finish + 1
elsif action_to_perform = ElnaLexerAction.key_id then elsif action_to_perform = ElnaLexerAction.key_id then
intermediate := _elna_lexer_classify_keyword(lexer_state.start, lexer_state.finish); intermediate := elna_lexer_classify_keyword(lexer_state.start, lexer_state.finish);
kind^ := intermediate kind^ := intermediate
elsif action_to_perform = ElnaLexerAction.integer then elsif action_to_perform = ElnaLexerAction.integer then
intermediate := _elna_lexer_classify_integer(lexer_state.start, lexer_state.finish); intermediate := elna_lexer_classify_integer(lexer_state.start, lexer_state.finish);
kind^ := intermediate kind^ := intermediate
elsif action_to_perform = ElnaLexerAction.delimited then elsif action_to_perform = ElnaLexerAction.delimited then
lexer_state.finish := lexer_state.finish + 1; lexer_state.finish := lexer_state.finish + 1;
intermediate := _elna_lexer_classify_delimited(lexer_state.start, lexer_state.finish); intermediate := elna_lexer_classify_delimited(lexer_state.start, lexer_state.finish);
kind^ := intermediate kind^ := intermediate
end end
end; end;

5309
boot/stage20/cl.elna Normal file

File diff suppressed because it is too large Load Diff

0
boot/stage20/linker.arg Normal file
View File