Provide binary and unary TAC operations
This commit is contained in:
@@ -155,9 +155,27 @@ type
|
||||
ElnaGeneratorKind = (
|
||||
load_immediate,
|
||||
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 = (
|
||||
zero,
|
||||
ra,
|
||||
@@ -615,7 +633,7 @@ begin
|
||||
this^ := operand_length
|
||||
end;
|
||||
|
||||
proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word);
|
||||
proc _elna_generator_instruction_create(kind: Word);
|
||||
var
|
||||
result: Word;
|
||||
instruction_size: Word;
|
||||
@@ -623,8 +641,18 @@ begin
|
||||
instruction_size := _elna_generator_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);
|
||||
|
||||
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, 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);
|
||||
var
|
||||
result: Word;
|
||||
instruction_size: Word;
|
||||
begin
|
||||
instruction_size := _elna_generator_instruction_size();
|
||||
result := _allocate(instruction_size);
|
||||
result := _elna_generator_instruction_create(ElnaGeneratorKind.load_address);
|
||||
|
||||
_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, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length);
|
||||
|
||||
return result
|
||||
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);
|
||||
var
|
||||
argument_count: Word;
|
||||
@@ -660,6 +922,60 @@ begin
|
||||
elsif instruction_kind = ElnaGeneratorKind.add then
|
||||
argument_count := 3;
|
||||
_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;
|
||||
return argument_count
|
||||
end;
|
||||
@@ -686,6 +1002,11 @@ begin
|
||||
_write_c(' ');
|
||||
if operand_type = ElnaGeneratorOperand.register then
|
||||
_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
|
||||
_write_i(operand_value)
|
||||
else
|
||||
@@ -696,13 +1017,22 @@ end;
|
||||
proc _elna_writer_instruction(instruction: Word);
|
||||
var
|
||||
instruction_kind: Word;
|
||||
argument_count: Word;
|
||||
current_argument: Word;
|
||||
begin
|
||||
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;
|
||||
if current_argument <= argument_count then
|
||||
_elna_writer_operand(instruction, current_argument);
|
||||
current_argument := current_argument + 1
|
||||
end;
|
||||
if current_argument <= argument_count then
|
||||
_write_c(',');
|
||||
_elna_writer_operand(instruction, 2);
|
||||
goto elna_writer_instruction_loop
|
||||
end;
|
||||
|
||||
_write_c('\n')
|
||||
end;
|
||||
@@ -776,13 +1106,11 @@ var
|
||||
integer_token: Word;
|
||||
integer_length: Word;
|
||||
token_kind: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
integer_token := _integer_literal_node_get_value(integer_literal_node);
|
||||
integer_length := _integer_literal_node_get_length(integer_literal_node);
|
||||
|
||||
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length);
|
||||
_elna_writer_instructions(instruction)
|
||||
return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length)
|
||||
end;
|
||||
|
||||
proc _character_literal_node_size();
|
||||
@@ -839,13 +1167,11 @@ proc _compile_character_literal(character_literal_node: Word);
|
||||
var
|
||||
character: Word;
|
||||
character_length: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
character := _character_literal_node_get_value(character_literal_node);
|
||||
character_length := _character_literal_node_get_length(character_literal_node);
|
||||
|
||||
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length);
|
||||
_elna_writer_instructions(instruction)
|
||||
return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length)
|
||||
end;
|
||||
|
||||
proc _variable_expression_size();
|
||||
@@ -912,16 +1238,18 @@ var
|
||||
name: Word;
|
||||
name_token: Word;
|
||||
lookup_result: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
name := _variable_expression_get_name(variable_expression);
|
||||
name_token := _variable_expression_get_length(variable_expression);
|
||||
|
||||
lookup_result := _symbol_table_lookup(symbol_table, name, name_token);
|
||||
if lookup_result <> 0 then
|
||||
_compile_local_designator(lookup_result)
|
||||
instruction := _compile_local_designator(lookup_result)
|
||||
else
|
||||
_compile_global_designator(variable_expression)
|
||||
end
|
||||
instruction := _compile_global_designator(variable_expression)
|
||||
end;
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc _string_literal_node_size();
|
||||
@@ -980,6 +1308,7 @@ var
|
||||
offset: Word;
|
||||
instruction: Word;
|
||||
first_instruction: Word;
|
||||
next_instruction: Word;
|
||||
begin
|
||||
token_start := _string_literal_node_get_value(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);
|
||||
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0);
|
||||
_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);
|
||||
|
||||
_write_z("\tadd t0, t0, t1\n\0")
|
||||
return first_instruction
|
||||
end;
|
||||
|
||||
proc _parse_simple_expression();
|
||||
@@ -1065,25 +1394,26 @@ begin
|
||||
return simple_expression
|
||||
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
|
||||
is_address: Word;
|
||||
node_kind: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
is_address := 0;
|
||||
is_address^ := 0;
|
||||
node_kind := _node_get_kind(parser_node);
|
||||
|
||||
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
|
||||
_compile_string_literal(parser_node)
|
||||
instruction := _compile_string_literal(parser_node)
|
||||
elsif node_kind = NodeKind.integer_literal then
|
||||
_compile_integer_literal(parser_node)
|
||||
instruction := _compile_integer_literal(parser_node)
|
||||
else
|
||||
_compile_variable_expression(parser_node, symbol_table);
|
||||
is_address := 1
|
||||
instruction := _compile_variable_expression(parser_node, symbol_table);
|
||||
is_address^ := 1
|
||||
end;
|
||||
return is_address
|
||||
_elna_writer_instructions(instruction)
|
||||
end;
|
||||
|
||||
proc _unary_expression_size();
|
||||
@@ -1157,6 +1487,8 @@ var
|
||||
expression_kind: Word;
|
||||
operator: Word;
|
||||
operand: Word;
|
||||
is_address: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
operator := 0;
|
||||
operand := 0;
|
||||
@@ -1171,14 +1503,20 @@ begin
|
||||
end;
|
||||
|
||||
if operator = '@' then
|
||||
_compile_designator(operand, symbol_table)
|
||||
elsif _compile_designator(operand, symbol_table) then
|
||||
_write_z("\tlw t0, (t0) # Designator is an address.\n\0")
|
||||
_compile_designator(operand, symbol_table, @is_address)
|
||||
else
|
||||
_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;
|
||||
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
|
||||
_write_z("\tnot t0, t0\n\0")
|
||||
instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
|
||||
_elna_writer_instruction(instruction)
|
||||
end
|
||||
end;
|
||||
|
||||
@@ -1296,6 +1634,8 @@ var
|
||||
token_kind: Word;
|
||||
expression_kind: Word;
|
||||
operand_node: Word;
|
||||
first_instruction: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
expression_kind := _node_get_kind(parser_node);
|
||||
|
||||
@@ -1307,42 +1647,53 @@ begin
|
||||
operand_node := _binary_expression_get_lhs(parser_node);
|
||||
_compile_unary_expression(operand_node, symbol_table);
|
||||
(* 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);
|
||||
_compile_unary_expression(operand_node, symbol_table);
|
||||
(* 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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_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
|
||||
_write_z("\tslt t0, t1, t0\n\txori t0, t0, 1\n\0")
|
||||
end
|
||||
first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
|
||||
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;
|
||||
|
||||
@@ -1429,11 +1780,15 @@ var
|
||||
argument_count: Word;
|
||||
stack_offset: Word;
|
||||
parsed_expression: Word;
|
||||
instruction: Word;
|
||||
first_instruction: Word;
|
||||
current_instruction: Word;
|
||||
begin
|
||||
parsed_expression := _call_get_name(parsed_call);
|
||||
name := _variable_expression_get_name(parsed_expression);
|
||||
name_length := _variable_expression_get_length(parsed_expression);
|
||||
argument_count := 0;
|
||||
first_instruction := 0;
|
||||
|
||||
.compile_call_loop;
|
||||
|
||||
@@ -1444,11 +1799,11 @@ begin
|
||||
_compile_binary_expression(parsed_expression, symbol_table);
|
||||
|
||||
(* Save the argument on the stack. *)
|
||||
_write_z("\tsw t0, \0");
|
||||
|
||||
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;
|
||||
goto compile_call_loop
|
||||
@@ -1460,24 +1815,27 @@ begin
|
||||
if argument_count <> 0 then
|
||||
(* Decrement the argument counter. *)
|
||||
argument_count := argument_count - 1;
|
||||
|
||||
_write_z("\tlw a\0");
|
||||
_write_i(argument_count);
|
||||
|
||||
_write_z(", \0");
|
||||
stack_offset := argument_count * 4;
|
||||
|
||||
(* Calculate the stack offset: 116 - (4 * argument_counter) *)
|
||||
stack_offset := argument_count * 4;
|
||||
_write_i(116 - stack_offset);
|
||||
|
||||
_write_z("(sp)\n\0");
|
||||
instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count,
|
||||
ElnaGeneratorRegister.sp, 116 - stack_offset);
|
||||
if first_instruction = 0 then
|
||||
first_instruction := instruction
|
||||
else
|
||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
||||
end;
|
||||
current_instruction := instruction;
|
||||
|
||||
goto compile_call_finalize
|
||||
end;
|
||||
|
||||
_write_z("\tcall \0");
|
||||
_write_s(name, name_length);
|
||||
_write_c('\n')
|
||||
instruction := _elna_generator_call(name, name_length);
|
||||
if first_instruction = 0 then
|
||||
first_instruction := instruction
|
||||
else
|
||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
||||
end;
|
||||
_elna_writer_instructions(first_instruction)
|
||||
end;
|
||||
|
||||
(**
|
||||
@@ -1633,25 +1991,24 @@ end;
|
||||
proc _compile_local_designator(symbol: Word);
|
||||
var
|
||||
variable_offset: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
_write_z("\taddi t0, sp, \0");
|
||||
variable_offset := _parameter_info_get_offset(symbol);
|
||||
_write_i(variable_offset);
|
||||
_write_c('\n')
|
||||
instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, variable_offset);
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc _compile_global_designator(variable_expression: Word);
|
||||
var
|
||||
name: Word;
|
||||
token_length: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
_write_z("\tla t0, \0");
|
||||
|
||||
name := _variable_expression_get_name(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);
|
||||
_write_c('\n')
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc _field_access_expression_size();
|
||||
@@ -1706,6 +2063,7 @@ var
|
||||
member_length: Word;
|
||||
counter: Word;
|
||||
symbol: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
symbol := _field_access_expression_get_aggregate(field_access_expression);
|
||||
value_name := _variable_expression_get_name(symbol);
|
||||
@@ -1736,9 +2094,8 @@ begin
|
||||
counter := counter + 1;
|
||||
goto compile_enumeration_value_members
|
||||
end;
|
||||
_write_z("\tli t0, \0");
|
||||
_write_i(counter);
|
||||
_write_c('\n')
|
||||
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0);
|
||||
_elna_writer_instructions(instruction)
|
||||
end
|
||||
end;
|
||||
|
||||
@@ -1769,31 +2126,32 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc _compile_designator(parser_node: Word, symbol_table: Word);
|
||||
proc _compile_designator(parser_node: Word, symbol_table: Word, is_address: Word);
|
||||
var
|
||||
name_token: Word;
|
||||
lookup_result: Word;
|
||||
token_kind: Word;
|
||||
parser_node: Word;
|
||||
is_address: Word;
|
||||
node_kind: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
is_address := 1;
|
||||
node_kind := _node_get_kind(parser_node);
|
||||
|
||||
if node_kind = NodeKind.dereference_expression then
|
||||
parser_node := _dereference_expression_get_pointer(parser_node);
|
||||
_compile_simple_expression(parser_node, symbol_table);
|
||||
_write_z("\tlw t0, (t0)\n\0")
|
||||
_compile_simple_expression(parser_node, symbol_table, is_address);
|
||||
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
|
||||
_elna_writer_instructions(instruction)
|
||||
elsif node_kind = NodeKind.field_access_expression then
|
||||
_compile_enumeration_value(parser_node);
|
||||
is_address := 0
|
||||
is_address^ := 0
|
||||
elsif node_kind = NodeKind.call then
|
||||
_compile_call(parser_node, symbol_table);
|
||||
_write_z("\tmv t0, a0\n\0");
|
||||
is_address := 0
|
||||
instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0);
|
||||
_elna_writer_instructions(instruction);
|
||||
is_address^ := 0
|
||||
else
|
||||
is_address := _compile_simple_expression(parser_node, symbol_table)
|
||||
_compile_simple_expression(parser_node, symbol_table, is_address)
|
||||
end;
|
||||
return is_address
|
||||
end;
|
||||
@@ -1853,18 +2211,25 @@ end;
|
||||
proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word);
|
||||
var
|
||||
current_expression: Word;
|
||||
is_address: Word;
|
||||
first_instruction: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
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. *)
|
||||
_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. *)
|
||||
current_expression := _assignment_statement_get_assignment(parser_tree);
|
||||
_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;
|
||||
|
||||
proc _return_statement_size();
|
||||
@@ -1910,10 +2275,12 @@ end;
|
||||
proc _compile_return_statement(parser_node: Word, symbol_table: Word);
|
||||
var
|
||||
return_expression: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
return_expression := _return_statement_get_returned(parser_node);
|
||||
_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;
|
||||
|
||||
(**
|
||||
@@ -1959,6 +2326,7 @@ proc _compile_conditional_statements(parser_node: Word, after_end_label: Word, s
|
||||
var
|
||||
condition_label: Word;
|
||||
current_node: Word;
|
||||
instruction: Word;
|
||||
begin
|
||||
(* Compile condition. *)
|
||||
current_node := _conditional_statements_get_condition(parser_node);
|
||||
@@ -2821,6 +3189,9 @@ var
|
||||
current_parameter: Word;
|
||||
new_symbol_table: Word;
|
||||
symbol_info: Word;
|
||||
instruction: Word;
|
||||
first_instruction: Word;
|
||||
current_instruction: Word;
|
||||
begin
|
||||
name_pointer := _declaration_get_name(parser_node);
|
||||
name_length := _declaration_get_length(parser_node);
|
||||
@@ -2843,6 +3214,7 @@ begin
|
||||
|
||||
current_parameter := _procedure_declaration_get_parameters(parser_node);
|
||||
parameter_counter := 0;
|
||||
first_instruction := 0;
|
||||
.compile_procedure_declaration_parameters;
|
||||
if current_parameter <> 0 then
|
||||
name_pointer := _declaration_get_name(current_parameter);
|
||||
@@ -2851,12 +3223,14 @@ begin
|
||||
|
||||
symbol_info := _parameter_info_get_offset(symbol_info);
|
||||
|
||||
_write_z("\tsw a\0");
|
||||
_write_i(parameter_counter);
|
||||
_write_z(", \0");
|
||||
_write_i(symbol_info);
|
||||
|
||||
_write_z("(sp)\n\0");
|
||||
instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter,
|
||||
ElnaGeneratorRegister.sp, symbol_info);
|
||||
if first_instruction = 0 then
|
||||
first_instruction := instruction
|
||||
else
|
||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
||||
end;
|
||||
current_instruction := instruction;
|
||||
|
||||
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
|
||||
parameter_counter := parameter_counter + 1;
|
||||
@@ -2864,6 +3238,7 @@ begin
|
||||
current_parameter := _declaration_get_next(current_parameter);
|
||||
goto compile_procedure_declaration_parameters
|
||||
end;
|
||||
_elna_writer_instructions(first_instruction);
|
||||
current_parameter := _procedure_declaration_get_body(parser_node);
|
||||
_compile_statements(current_parameter, new_symbol_table);
|
||||
|
||||
@@ -4255,7 +4630,7 @@ end;
|
||||
proc _initialize_global_state();
|
||||
begin
|
||||
compiler_strings_position := @compiler_strings;
|
||||
memory_free_pointer := _mmap(495616);
|
||||
memory_free_pointer := _mmap(1048576);
|
||||
source_code := _mmap(495616);
|
||||
symbol_table_store := _mmap(495616)
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user