Provide binary and unary TAC operations

This commit is contained in:
2025-10-30 23:29:00 +01:00
parent 788cb4253f
commit 61e6b85528

View File

@@ -155,9 +155,27 @@ type
ElnaGeneratorKind = ( ElnaGeneratorKind = (
load_immediate, load_immediate,
load_address, load_address,
add add,
add_immediate,
load_word,
store_word,
call,
move,
sub,
div,
rem,
mul,
_xor,
_or,
and,
seqz,
snez,
slt,
xor_immediate,
neg,
not
); );
ElnaGeneratorOperand = (register, immediate, symbol); ElnaGeneratorOperand = (register, immediate, symbol, offset);
ElnaGeneratorRegister = ( ElnaGeneratorRegister = (
zero, zero,
ra, ra,
@@ -615,7 +633,7 @@ begin
this^ := operand_length this^ := operand_length
end; end;
proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word); proc _elna_generator_instruction_create(kind: Word);
var var
result: Word; result: Word;
instruction_size: Word; instruction_size: Word;
@@ -623,8 +641,18 @@ begin
instruction_size := _elna_generator_instruction_size(); instruction_size := _elna_generator_instruction_size();
result := _allocate(instruction_size); result := _allocate(instruction_size);
_elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_immediate); _elna_generator_instruction_set_kind(result, kind);
_elna_generator_instruction_set_next(result, 0); _elna_generator_instruction_set_next(result, 0);
return result
end;
proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.load_immediate);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.immediate, source_immediate, immediate_length); _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.immediate, source_immediate, immediate_length);
@@ -634,19 +662,253 @@ end;
proc _elna_generator_load_address(target_register: Word, source_symbol: Word, symbol_length: Word); proc _elna_generator_load_address(target_register: Word, source_symbol: Word, symbol_length: Word);
var var
result: Word; result: Word;
instruction_size: Word;
begin begin
instruction_size := _elna_generator_instruction_size(); result := _elna_generator_instruction_create(ElnaGeneratorKind.load_address);
result := _allocate(instruction_size);
_elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_address);
_elna_generator_instruction_set_next(result, 0);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length); _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length);
return result return result
end; end;
proc _elna_generator_add(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.add);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_mul(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.mul);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_sub(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.sub);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_div(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.div);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_rem(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.rem);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_xor(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind._xor);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_xor_immediate(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind._xor);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0);
return result
end;
proc _elna_generator_or(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind._or);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_and(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.and);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_add_immediate(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.add_immediate);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0);
return result
end;
proc _elna_generator_slt(destination: Word, lhs: Word, rhs: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.slt);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0);
_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0);
return result
end;
proc _elna_generator_call(symbol: Word, length: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.call);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.symbol, symbol, length);
return result
end;
proc _elna_generator_load_word(target: Word, register: Word, offset: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.load_word);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset);
return result
end;
proc _elna_generator_store_word(target: Word, register: Word, offset: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.store_word);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset);
return result
end;
proc _elna_generator_move(destination: Word, source: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.move);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0);
return result
end;
proc _elna_generator_seqz(destination: Word, source: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.seqz);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0);
return result
end;
proc _elna_generator_snez(destination: Word, source: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.snez);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0);
return result
end;
proc _elna_generator_neg(destination: Word, source: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.neg);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0);
return result
end;
proc _elna_generator_not(destination: Word, source: Word);
var
result: Word;
begin
result := _elna_generator_instruction_create(ElnaGeneratorKind.not);
_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0);
_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0);
return result
end;
proc _elna_writer_instruction_name(instruction_kind: Word); proc _elna_writer_instruction_name(instruction_kind: Word);
var var
argument_count: Word; argument_count: Word;
@@ -660,6 +922,60 @@ begin
elsif instruction_kind = ElnaGeneratorKind.add then elsif instruction_kind = ElnaGeneratorKind.add then
argument_count := 3; argument_count := 3;
_write_s("\tadd", 4) _write_s("\tadd", 4)
elsif instruction_kind = ElnaGeneratorKind.add_immediate then
argument_count := 3;
_write_s("\taddi", 5)
elsif instruction_kind = ElnaGeneratorKind.load_word then
argument_count := 2;
_write_s("\tlw", 3)
elsif instruction_kind = ElnaGeneratorKind.store_word then
argument_count := 2;
_write_s("\tsw", 3)
elsif instruction_kind = ElnaGeneratorKind.call then
argument_count := 1;
_write_s("\tcall", 5)
elsif instruction_kind = ElnaGeneratorKind.move then
argument_count := 2;
_write_s("\tmv", 3)
elsif instruction_kind = ElnaGeneratorKind.sub then
argument_count := 3;
_write_s("\tsub", 4)
elsif instruction_kind = ElnaGeneratorKind.mul then
argument_count := 3;
_write_s("\tmul", 4)
elsif instruction_kind = ElnaGeneratorKind.div then
argument_count := 3;
_write_s("\tdiv", 4)
elsif instruction_kind = ElnaGeneratorKind.rem then
argument_count := 3;
_write_s("\trem", 4)
elsif instruction_kind = ElnaGeneratorKind._xor then
argument_count := 3;
_write_s("\txor", 4)
elsif instruction_kind = ElnaGeneratorKind.xor_immediate then
argument_count := 3;
_write_s("\txori", 5)
elsif instruction_kind = ElnaGeneratorKind._or then
argument_count := 3;
_write_s("\tor", 3)
elsif instruction_kind = ElnaGeneratorKind.and then
argument_count := 3;
_write_s("\tand", 4)
elsif instruction_kind = ElnaGeneratorKind.seqz then
argument_count := 2;
_write_s("\tseqz", 5)
elsif instruction_kind = ElnaGeneratorKind.snez then
argument_count := 2;
_write_s("\tsnez", 5)
elsif instruction_kind = ElnaGeneratorKind.slt then
argument_count := 3;
_write_s("\tslt", 4)
elsif instruction_kind = ElnaGeneratorKind.neg then
argument_count := 2;
_write_s("\tneg", 4)
elsif instruction_kind = ElnaGeneratorKind.not then
argument_count := 2;
_write_s("\tnot", 4)
end; end;
return argument_count return argument_count
end; end;
@@ -686,6 +1002,11 @@ begin
_write_c(' '); _write_c(' ');
if operand_type = ElnaGeneratorOperand.register then if operand_type = ElnaGeneratorOperand.register then
_elna_writer_register(operand_value) _elna_writer_register(operand_value)
elsif operand_type = ElnaGeneratorOperand.offset then
_write_i(operand_length);
_write_c('(');
_elna_writer_register(operand_value);
_write_c(')')
elsif operand_length = 0 then elsif operand_length = 0 then
_write_i(operand_value) _write_i(operand_value)
else else
@@ -696,13 +1017,22 @@ end;
proc _elna_writer_instruction(instruction: Word); proc _elna_writer_instruction(instruction: Word);
var var
instruction_kind: Word; instruction_kind: Word;
argument_count: Word;
current_argument: Word;
begin begin
instruction_kind := _elna_generator_instruction_get_kind(instruction); instruction_kind := _elna_generator_instruction_get_kind(instruction);
_elna_writer_instruction_name(instruction_kind); argument_count := _elna_writer_instruction_name(instruction_kind);
current_argument := 1;
_elna_writer_operand(instruction, 1); .elna_writer_instruction_loop;
_write_c(','); if current_argument <= argument_count then
_elna_writer_operand(instruction, 2); _elna_writer_operand(instruction, current_argument);
current_argument := current_argument + 1
end;
if current_argument <= argument_count then
_write_c(',');
goto elna_writer_instruction_loop
end;
_write_c('\n') _write_c('\n')
end; end;
@@ -776,13 +1106,11 @@ var
integer_token: Word; integer_token: Word;
integer_length: Word; integer_length: Word;
token_kind: Word; token_kind: Word;
instruction: Word;
begin begin
integer_token := _integer_literal_node_get_value(integer_literal_node); integer_token := _integer_literal_node_get_value(integer_literal_node);
integer_length := _integer_literal_node_get_length(integer_literal_node); integer_length := _integer_literal_node_get_length(integer_literal_node);
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length); return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length)
_elna_writer_instructions(instruction)
end; end;
proc _character_literal_node_size(); proc _character_literal_node_size();
@@ -839,13 +1167,11 @@ proc _compile_character_literal(character_literal_node: Word);
var var
character: Word; character: Word;
character_length: Word; character_length: Word;
instruction: Word;
begin begin
character := _character_literal_node_get_value(character_literal_node); character := _character_literal_node_get_value(character_literal_node);
character_length := _character_literal_node_get_length(character_literal_node); character_length := _character_literal_node_get_length(character_literal_node);
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length); return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length)
_elna_writer_instructions(instruction)
end; end;
proc _variable_expression_size(); proc _variable_expression_size();
@@ -912,16 +1238,18 @@ var
name: Word; name: Word;
name_token: Word; name_token: Word;
lookup_result: Word; lookup_result: Word;
instruction: Word;
begin begin
name := _variable_expression_get_name(variable_expression); name := _variable_expression_get_name(variable_expression);
name_token := _variable_expression_get_length(variable_expression); name_token := _variable_expression_get_length(variable_expression);
lookup_result := _symbol_table_lookup(symbol_table, name, name_token); lookup_result := _symbol_table_lookup(symbol_table, name, name_token);
if lookup_result <> 0 then if lookup_result <> 0 then
_compile_local_designator(lookup_result) instruction := _compile_local_designator(lookup_result)
else else
_compile_global_designator(variable_expression) instruction := _compile_global_designator(variable_expression)
end end;
return instruction
end; end;
proc _string_literal_node_size(); proc _string_literal_node_size();
@@ -980,6 +1308,7 @@ var
offset: Word; offset: Word;
instruction: Word; instruction: Word;
first_instruction: Word; first_instruction: Word;
next_instruction: Word;
begin begin
token_start := _string_literal_node_get_value(string_literal_node); token_start := _string_literal_node_get_value(string_literal_node);
length := _string_literal_node_get_length(string_literal_node); length := _string_literal_node_get_length(string_literal_node);
@@ -988,10 +1317,10 @@ begin
first_instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, "strings", 7); first_instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, "strings", 7);
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0); instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0);
_elna_generator_instruction_set_next(first_instruction, instruction); _elna_generator_instruction_set_next(first_instruction, instruction);
next_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
_elna_generator_instruction_set_next(instruction, next_instruction);
_elna_writer_instructions(first_instruction); return first_instruction
_write_z("\tadd t0, t0, t1\n\0")
end; end;
proc _parse_simple_expression(); proc _parse_simple_expression();
@@ -1065,25 +1394,26 @@ begin
return simple_expression return simple_expression
end; end;
proc _compile_simple_expression(parser_node: Word, symbol_table: Word); proc _compile_simple_expression(parser_node: Word, symbol_table: Word, is_address: Word);
var var
is_address: Word; is_address: Word;
node_kind: Word; node_kind: Word;
instruction: Word;
begin begin
is_address := 0; is_address^ := 0;
node_kind := _node_get_kind(parser_node); node_kind := _node_get_kind(parser_node);
if node_kind = NodeKind.character_literal then if node_kind = NodeKind.character_literal then
_compile_character_literal(parser_node) instruction := _compile_character_literal(parser_node)
elsif node_kind = NodeKind.string_literal then elsif node_kind = NodeKind.string_literal then
_compile_string_literal(parser_node) instruction := _compile_string_literal(parser_node)
elsif node_kind = NodeKind.integer_literal then elsif node_kind = NodeKind.integer_literal then
_compile_integer_literal(parser_node) instruction := _compile_integer_literal(parser_node)
else else
_compile_variable_expression(parser_node, symbol_table); instruction := _compile_variable_expression(parser_node, symbol_table);
is_address := 1 is_address^ := 1
end; end;
return is_address _elna_writer_instructions(instruction)
end; end;
proc _unary_expression_size(); proc _unary_expression_size();
@@ -1157,6 +1487,8 @@ var
expression_kind: Word; expression_kind: Word;
operator: Word; operator: Word;
operand: Word; operand: Word;
is_address: Word;
instruction: Word;
begin begin
operator := 0; operator := 0;
operand := 0; operand := 0;
@@ -1171,14 +1503,20 @@ begin
end; end;
if operator = '@' then if operator = '@' then
_compile_designator(operand, symbol_table) _compile_designator(operand, symbol_table, @is_address)
elsif _compile_designator(operand, symbol_table) then else
_write_z("\tlw t0, (t0) # Designator is an address.\n\0") _compile_designator(operand, symbol_table, @is_address);
if is_address then
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
_elna_writer_instruction(instruction)
end
end; end;
if operator = '-' then if operator = '-' then
_write_z("\tneg t0, t0\n\0") instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
_elna_writer_instruction(instruction)
elsif operator = '~' then elsif operator = '~' then
_write_z("\tnot t0, t0\n\0") instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
_elna_writer_instruction(instruction)
end end
end; end;
@@ -1296,6 +1634,8 @@ var
token_kind: Word; token_kind: Word;
expression_kind: Word; expression_kind: Word;
operand_node: Word; operand_node: Word;
first_instruction: Word;
instruction: Word;
begin begin
expression_kind := _node_get_kind(parser_node); expression_kind := _node_get_kind(parser_node);
@@ -1307,42 +1647,53 @@ begin
operand_node := _binary_expression_get_lhs(parser_node); operand_node := _binary_expression_get_lhs(parser_node);
_compile_unary_expression(operand_node, symbol_table); _compile_unary_expression(operand_node, symbol_table);
(* Save the value of the left expression on the stack. *) (* Save the value of the left expression on the stack. *)
_write_z("\tsw t0, 64(sp)\n\0"); instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 64);
_elna_writer_instruction(instruction);
operand_node := _binary_expression_get_rhs(parser_node); operand_node := _binary_expression_get_rhs(parser_node);
_compile_unary_expression(operand_node, symbol_table); _compile_unary_expression(operand_node, symbol_table);
(* Load the left expression from the stack; *) (* Load the left expression from the stack; *)
_write_z("\tlw t1, 64(sp)\n\0"); instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 64);
_elna_writer_instruction(instruction);
if token_kind = LexerTokenKind.plus then if token_kind = LexerTokenKind.plus then
_write_z("\tadd t0, t0, t1\n\0") first_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind.minus then elsif token_kind = LexerTokenKind.minus then
_write_z("\tsub t0, t1, t0\n\0"); first_instruction := _elna_generator_sub(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
elsif token_kind = LexerTokenKind.multiplication then elsif token_kind = LexerTokenKind.multiplication then
_write_z("\tmul t0, t0, t1\n\0") first_instruction := _elna_generator_mul(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind.and then elsif token_kind = LexerTokenKind.and then
_write_z("\tand t0, t0, t1\n\0") first_instruction := _elna_generator_and(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind._or then elsif token_kind = LexerTokenKind._or then
_write_z("\tor t0, t0, t1\n\0") first_instruction := _elna_generator_or(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind._xor then elsif token_kind = LexerTokenKind._xor then
_write_z("\txor t0, t0, t1\n\0") first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind.equals then elsif token_kind = LexerTokenKind.equals then
_write_z("\txor t0, t0, t1\n\tseqz t0, t0\n\0") first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
instruction := _elna_generator_seqz(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
_elna_generator_instruction_set_next(first_instruction, instruction)
elsif token_kind = LexerTokenKind.remainder then elsif token_kind = LexerTokenKind.remainder then
_write_z("\trem t0, t1, t0\n\0") first_instruction := _elna_generator_rem(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
elsif token_kind = LexerTokenKind.division then elsif token_kind = LexerTokenKind.division then
_write_z("\tdiv t0, t1, t0\n\0") first_instruction := _elna_generator_div(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
elsif token_kind = LexerTokenKind.less_than then elsif token_kind = LexerTokenKind.less_than then
_write_z("\tslt t0, t1, t0\n\0") first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
elsif token_kind = LexerTokenKind.greater_than then elsif token_kind = LexerTokenKind.greater_than then
_write_z("\tslt t0, t0, t1\n\0") first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
elsif token_kind = LexerTokenKind.less_equal then elsif token_kind = LexerTokenKind.less_equal then
_write_z("\tslt t0, t0, t1\n\txori t0, t0, 1\n\0") first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1);
_elna_generator_instruction_set_next(first_instruction, instruction)
elsif token_kind = LexerTokenKind.not_equal then elsif token_kind = LexerTokenKind.not_equal then
_write_z("\txor t0, t0, t1\n\tsnez t0, t0\n\0") first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
instruction := _elna_generator_snez(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
_elna_generator_instruction_set_next(first_instruction, instruction)
elsif token_kind = LexerTokenKind.greater_equal then elsif token_kind = LexerTokenKind.greater_equal then
_write_z("\tslt t0, t1, t0\n\txori t0, t0, 1\n\0") first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
end instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1);
_elna_generator_instruction_set_next(first_instruction, instruction)
end;
_elna_writer_instructions(first_instruction)
end end
end; end;
@@ -1429,11 +1780,15 @@ var
argument_count: Word; argument_count: Word;
stack_offset: Word; stack_offset: Word;
parsed_expression: Word; parsed_expression: Word;
instruction: Word;
first_instruction: Word;
current_instruction: Word;
begin begin
parsed_expression := _call_get_name(parsed_call); parsed_expression := _call_get_name(parsed_call);
name := _variable_expression_get_name(parsed_expression); name := _variable_expression_get_name(parsed_expression);
name_length := _variable_expression_get_length(parsed_expression); name_length := _variable_expression_get_length(parsed_expression);
argument_count := 0; argument_count := 0;
first_instruction := 0;
.compile_call_loop; .compile_call_loop;
@@ -1444,11 +1799,11 @@ begin
_compile_binary_expression(parsed_expression, symbol_table); _compile_binary_expression(parsed_expression, symbol_table);
(* Save the argument on the stack. *) (* Save the argument on the stack. *)
_write_z("\tsw t0, \0");
stack_offset := argument_count * 4; stack_offset := argument_count * 4;
_write_i(116 - stack_offset);
_write_z("(sp)\n\0"); instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0,
ElnaGeneratorRegister.sp, 116 - stack_offset);
_elna_writer_instruction(instruction);
argument_count := argument_count + 1; argument_count := argument_count + 1;
goto compile_call_loop goto compile_call_loop
@@ -1460,24 +1815,27 @@ begin
if argument_count <> 0 then if argument_count <> 0 then
(* Decrement the argument counter. *) (* Decrement the argument counter. *)
argument_count := argument_count - 1; argument_count := argument_count - 1;
stack_offset := argument_count * 4;
_write_z("\tlw a\0");
_write_i(argument_count);
_write_z(", \0");
(* Calculate the stack offset: 116 - (4 * argument_counter) *) (* Calculate the stack offset: 116 - (4 * argument_counter) *)
stack_offset := argument_count * 4; instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count,
_write_i(116 - stack_offset); ElnaGeneratorRegister.sp, 116 - stack_offset);
if first_instruction = 0 then
_write_z("(sp)\n\0"); first_instruction := instruction
else
_elna_generator_instruction_set_next(current_instruction, instruction)
end;
current_instruction := instruction;
goto compile_call_finalize goto compile_call_finalize
end; end;
instruction := _elna_generator_call(name, name_length);
_write_z("\tcall \0"); if first_instruction = 0 then
_write_s(name, name_length); first_instruction := instruction
_write_c('\n') else
_elna_generator_instruction_set_next(current_instruction, instruction)
end;
_elna_writer_instructions(first_instruction)
end; end;
(** (**
@@ -1633,25 +1991,24 @@ end;
proc _compile_local_designator(symbol: Word); proc _compile_local_designator(symbol: Word);
var var
variable_offset: Word; variable_offset: Word;
instruction: Word;
begin begin
_write_z("\taddi t0, sp, \0");
variable_offset := _parameter_info_get_offset(symbol); variable_offset := _parameter_info_get_offset(symbol);
_write_i(variable_offset); instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, variable_offset);
_write_c('\n') return instruction
end; end;
proc _compile_global_designator(variable_expression: Word); proc _compile_global_designator(variable_expression: Word);
var var
name: Word; name: Word;
token_length: Word; token_length: Word;
instruction: Word;
begin begin
_write_z("\tla t0, \0");
name := _variable_expression_get_name(variable_expression); name := _variable_expression_get_name(variable_expression);
token_length := _variable_expression_get_length(variable_expression); token_length := _variable_expression_get_length(variable_expression);
instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, name, token_length);
_write_s(name, token_length); return instruction
_write_c('\n')
end; end;
proc _field_access_expression_size(); proc _field_access_expression_size();
@@ -1706,6 +2063,7 @@ var
member_length: Word; member_length: Word;
counter: Word; counter: Word;
symbol: Word; symbol: Word;
instruction: Word;
begin begin
symbol := _field_access_expression_get_aggregate(field_access_expression); symbol := _field_access_expression_get_aggregate(field_access_expression);
value_name := _variable_expression_get_name(symbol); value_name := _variable_expression_get_name(symbol);
@@ -1736,9 +2094,8 @@ begin
counter := counter + 1; counter := counter + 1;
goto compile_enumeration_value_members goto compile_enumeration_value_members
end; end;
_write_z("\tli t0, \0"); instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0);
_write_i(counter); _elna_writer_instructions(instruction)
_write_c('\n')
end end
end; end;
@@ -1769,31 +2126,32 @@ begin
return result return result
end; end;
proc _compile_designator(parser_node: Word, symbol_table: Word); proc _compile_designator(parser_node: Word, symbol_table: Word, is_address: Word);
var var
name_token: Word; name_token: Word;
lookup_result: Word; lookup_result: Word;
token_kind: Word; token_kind: Word;
parser_node: Word; parser_node: Word;
is_address: Word;
node_kind: Word; node_kind: Word;
instruction: Word;
begin begin
is_address := 1;
node_kind := _node_get_kind(parser_node); node_kind := _node_get_kind(parser_node);
if node_kind = NodeKind.dereference_expression then if node_kind = NodeKind.dereference_expression then
parser_node := _dereference_expression_get_pointer(parser_node); parser_node := _dereference_expression_get_pointer(parser_node);
_compile_simple_expression(parser_node, symbol_table); _compile_simple_expression(parser_node, symbol_table, is_address);
_write_z("\tlw t0, (t0)\n\0") instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
_elna_writer_instructions(instruction)
elsif node_kind = NodeKind.field_access_expression then elsif node_kind = NodeKind.field_access_expression then
_compile_enumeration_value(parser_node); _compile_enumeration_value(parser_node);
is_address := 0 is_address^ := 0
elsif node_kind = NodeKind.call then elsif node_kind = NodeKind.call then
_compile_call(parser_node, symbol_table); _compile_call(parser_node, symbol_table);
_write_z("\tmv t0, a0\n\0"); instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0);
is_address := 0 _elna_writer_instructions(instruction);
is_address^ := 0
else else
is_address := _compile_simple_expression(parser_node, symbol_table) _compile_simple_expression(parser_node, symbol_table, is_address)
end; end;
return is_address return is_address
end; end;
@@ -1853,18 +2211,25 @@ end;
proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word); proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word);
var var
current_expression: Word; current_expression: Word;
is_address: Word;
first_instruction: Word;
instruction: Word;
begin begin
current_expression := _assignment_statement_get_assignee(parser_tree); current_expression := _assignment_statement_get_assignee(parser_tree);
_compile_designator(current_expression, symbol_table); _compile_designator(current_expression, symbol_table, @is_address);
(* Save the assignee address on the stack. *) (* Save the assignee address on the stack. *)
_write_z("\tsw t0, 60(sp)\n\0"); instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60);
_elna_writer_instructions(instruction);
(* Compile the assignment. *) (* Compile the assignment. *)
current_expression := _assignment_statement_get_assignment(parser_tree); current_expression := _assignment_statement_get_assignment(parser_tree);
_compile_binary_expression(current_expression, symbol_table); _compile_binary_expression(current_expression, symbol_table);
_write_z("\tlw t1, 60(sp)\n\tsw t0, (t1)\n\0") first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 60);
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, 0);
_elna_generator_instruction_set_next(first_instruction, instruction);
_elna_writer_instructions(first_instruction)
end; end;
proc _return_statement_size(); proc _return_statement_size();
@@ -1910,10 +2275,12 @@ end;
proc _compile_return_statement(parser_node: Word, symbol_table: Word); proc _compile_return_statement(parser_node: Word, symbol_table: Word);
var var
return_expression: Word; return_expression: Word;
instruction: Word;
begin begin
return_expression := _return_statement_get_returned(parser_node); return_expression := _return_statement_get_returned(parser_node);
_compile_binary_expression(return_expression, symbol_table); _compile_binary_expression(return_expression, symbol_table);
_write_z("\tmv a0, t0\n\0") instruction := _elna_generator_move(ElnaGeneratorRegister.a0, ElnaGeneratorRegister.t0);
_elna_writer_instructions(instruction)
end; end;
(** (**
@@ -1959,6 +2326,7 @@ proc _compile_conditional_statements(parser_node: Word, after_end_label: Word, s
var var
condition_label: Word; condition_label: Word;
current_node: Word; current_node: Word;
instruction: Word;
begin begin
(* Compile condition. *) (* Compile condition. *)
current_node := _conditional_statements_get_condition(parser_node); current_node := _conditional_statements_get_condition(parser_node);
@@ -2821,6 +3189,9 @@ var
current_parameter: Word; current_parameter: Word;
new_symbol_table: Word; new_symbol_table: Word;
symbol_info: Word; symbol_info: Word;
instruction: Word;
first_instruction: Word;
current_instruction: Word;
begin begin
name_pointer := _declaration_get_name(parser_node); name_pointer := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node); name_length := _declaration_get_length(parser_node);
@@ -2843,6 +3214,7 @@ begin
current_parameter := _procedure_declaration_get_parameters(parser_node); current_parameter := _procedure_declaration_get_parameters(parser_node);
parameter_counter := 0; parameter_counter := 0;
first_instruction := 0;
.compile_procedure_declaration_parameters; .compile_procedure_declaration_parameters;
if current_parameter <> 0 then if current_parameter <> 0 then
name_pointer := _declaration_get_name(current_parameter); name_pointer := _declaration_get_name(current_parameter);
@@ -2851,12 +3223,14 @@ begin
symbol_info := _parameter_info_get_offset(symbol_info); symbol_info := _parameter_info_get_offset(symbol_info);
_write_z("\tsw a\0"); instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter,
_write_i(parameter_counter); ElnaGeneratorRegister.sp, symbol_info);
_write_z(", \0"); if first_instruction = 0 then
_write_i(symbol_info); first_instruction := instruction
else
_write_z("(sp)\n\0"); _elna_generator_instruction_set_next(current_instruction, instruction)
end;
current_instruction := instruction;
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *) (* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
parameter_counter := parameter_counter + 1; parameter_counter := parameter_counter + 1;
@@ -2864,6 +3238,7 @@ begin
current_parameter := _declaration_get_next(current_parameter); current_parameter := _declaration_get_next(current_parameter);
goto compile_procedure_declaration_parameters goto compile_procedure_declaration_parameters
end; end;
_elna_writer_instructions(first_instruction);
current_parameter := _procedure_declaration_get_body(parser_node); current_parameter := _procedure_declaration_get_body(parser_node);
_compile_statements(current_parameter, new_symbol_table); _compile_statements(current_parameter, new_symbol_table);
@@ -4255,7 +4630,7 @@ end;
proc _initialize_global_state(); proc _initialize_global_state();
begin begin
compiler_strings_position := @compiler_strings; compiler_strings_position := @compiler_strings;
memory_free_pointer := _mmap(495616); memory_free_pointer := _mmap(1048576);
source_code := _mmap(495616); source_code := _mmap(495616);
symbol_table_store := _mmap(495616) symbol_table_store := _mmap(495616)
end; end;