Generate pseudo variables where possible
This commit is contained in:
@@ -563,6 +563,7 @@ var
|
||||
label_counter: Word;
|
||||
symbol_table_store: Word;
|
||||
temporary_variable_counter: Word;
|
||||
pseudo_counter: Word;
|
||||
|
||||
(**
|
||||
* Calculates and returns the string token length between quotes, including the
|
||||
@@ -694,6 +695,26 @@ proc _is_alnum(character: Word);
|
||||
return _is_alpha(character) or isdigit(character)
|
||||
end;
|
||||
|
||||
proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word);
|
||||
var
|
||||
buffer: Word;
|
||||
begin
|
||||
(* TODO: 100 pseudo registers should be enough to save temporary state,
|
||||
but this should not be the final solution. *)
|
||||
if pseudo_counter > 100 then
|
||||
pseudo_counter := 1
|
||||
else
|
||||
pseudo_counter := pseudo_counter + 1
|
||||
end;
|
||||
buffer := malloc(6);
|
||||
|
||||
sprintf(buffer, "$%i\0", pseudo_counter);
|
||||
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := buffer;
|
||||
operand_length^ := strlen(buffer);
|
||||
end;
|
||||
|
||||
proc elna_instruction_list_concatenate(this: ^ElnaInstructionList, value: Word);
|
||||
var
|
||||
start: Word;
|
||||
@@ -1858,20 +1879,18 @@ var
|
||||
begin
|
||||
offset := _add_string(string_literal_node^.value);
|
||||
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
first_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(first_instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(first_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(first_instruction, 2, ElnaTacKind.symbol, "strings", 7);
|
||||
|
||||
(* Add offset to the string block pointer. *)
|
||||
next_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(next_instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(next_instruction, 2, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(next_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(next_instruction, 2, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacKind.immediate, offset, 0);
|
||||
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := "$unary";
|
||||
operand_length^ := 6;
|
||||
|
||||
return elna_instruction_list_concatenate(first_instruction, next_instruction)
|
||||
end;
|
||||
|
||||
@@ -2047,6 +2066,9 @@ var
|
||||
is_address: Word;
|
||||
first_instruction: Word;
|
||||
instruction: Word;
|
||||
base_type: Word;
|
||||
base_value: Word;
|
||||
base_length: Word;
|
||||
begin
|
||||
instruction := nil;
|
||||
if parser_node^.kind = ElnaTreeKind.unary_expression then
|
||||
@@ -2056,39 +2078,37 @@ begin
|
||||
operator := 0;
|
||||
operand := parser_node
|
||||
end;
|
||||
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
|
||||
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, @base_type, @base_value, @base_length);
|
||||
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
if operator = '@' then
|
||||
if is_address then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length)
|
||||
else
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length)
|
||||
end
|
||||
elsif operator = '-' then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length)
|
||||
elsif operator = '~' then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length)
|
||||
elsif is_address then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.load);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.pseudo, "$unary", 6)
|
||||
elna_tac_instruction_set_operand(instruction, 1, base_type, base_value, base_length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
else
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^)
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length)
|
||||
end;
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := "$unary";
|
||||
operand_length^ := 6;
|
||||
|
||||
return elna_instruction_list_concatenate(first_instruction, instruction)
|
||||
end;
|
||||
|
||||
@@ -2168,13 +2188,13 @@ var
|
||||
lhs_type: Word;
|
||||
lhs_value: Word;
|
||||
lhs_length: Word;
|
||||
rhs_type: Word;
|
||||
rhs_value: Word;
|
||||
rhs_length: Word;
|
||||
begin
|
||||
if parser_node^.kind <> ElnaTreeKind.binary_expression then
|
||||
first_instruction := elna_tac_unary_expression(parser_node, symbol_table, operand_type, operand_value, operand_length)
|
||||
else
|
||||
lhs_type := 0;
|
||||
lhs_value := 0;
|
||||
lhs_length := 0;
|
||||
first_instruction := elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
|
||||
|
||||
(* Save the value of the left expression on the stack. *)
|
||||
@@ -2182,17 +2202,18 @@ begin
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(instruction, 2, lhs_type, lhs_value, lhs_length);
|
||||
|
||||
if first_instruction = 0 then
|
||||
lhs_type := ElnaTacKind.pseudo;
|
||||
lhs_value := "$lhs";
|
||||
lhs_length := 4;
|
||||
|
||||
if first_instruction = nil then
|
||||
first_instruction := instruction
|
||||
else
|
||||
elna_instruction_list_concatenate(first_instruction, instruction)
|
||||
end;
|
||||
current_instruction := instruction;
|
||||
|
||||
lhs_type := 0;
|
||||
lhs_value := 0;
|
||||
lhs_length := 0;
|
||||
instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
|
||||
instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @rhs_type, @rhs_value, @rhs_length);
|
||||
current_instruction := elna_instruction_list_concatenate(current_instruction, instruction);
|
||||
|
||||
if parser_node^.operator = ElnaLexerKind.plus then
|
||||
@@ -2224,13 +2245,11 @@ begin
|
||||
elsif parser_node^.operator = ElnaLexerKind.not_equal then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.not_equal)
|
||||
end;
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, "$binary", 7);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(instruction, 3, lhs_type, lhs_value, lhs_length);
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := "$binary";
|
||||
operand_length^ := 7;
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(instruction, 2, lhs_type, lhs_value, lhs_length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, rhs_type, rhs_value, rhs_length);
|
||||
|
||||
elna_instruction_list_concatenate(current_instruction, instruction)
|
||||
end;
|
||||
@@ -2299,30 +2318,22 @@ var
|
||||
arguments_operand: ^ElnaTacOperand;
|
||||
call_instruction: Word;
|
||||
argument_entry: ^ElnaTreeExpressionList;
|
||||
name_buffer: Word;
|
||||
argument_count: Word;
|
||||
begin
|
||||
parsed_expression := parsed_call^.callee;
|
||||
first_instruction := nil;
|
||||
arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand));
|
||||
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
|
||||
elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.symbol, parsed_expression^.name, parsed_expression^.length);
|
||||
elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, parsed_call^.count);
|
||||
elna_tac_instruction_set_operand(call_instruction, 3, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(call_instruction, 3, operand_type^, operand_value^, operand_length^);
|
||||
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := "$unary";
|
||||
operand_length^ := 6;
|
||||
|
||||
argument_count := 0;
|
||||
argument_entry := parsed_call^.arguments;
|
||||
.elna_tac_call_loop;
|
||||
|
||||
if argument_entry <> nil then
|
||||
argument_type := 0;
|
||||
argument_value := 0;
|
||||
argument_length := 0;
|
||||
instruction := elna_tac_binary_expression(argument_entry^.expression, symbol_table,
|
||||
@argument_type, @argument_value, @argument_length);
|
||||
if first_instruction = nil then
|
||||
@@ -2333,27 +2344,12 @@ begin
|
||||
if instruction <> nil then
|
||||
current_instruction := instruction
|
||||
end;
|
||||
|
||||
(* Save the argument on the stack. *)
|
||||
name_buffer := malloc(4);
|
||||
sprintf(name_buffer, "$ar%i\0", argument_count);
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.pseudo, name_buffer, 4);
|
||||
elna_tac_instruction_set_operand(instruction, 2, argument_type, argument_value, argument_length);
|
||||
if first_instruction = 0 then
|
||||
first_instruction := instruction
|
||||
else
|
||||
elna_instruction_list_concatenate(current_instruction, instruction)
|
||||
end;
|
||||
current_instruction := instruction;
|
||||
|
||||
arguments_operand^.kind := ElnaTacKind.pseudo;
|
||||
arguments_operand^.value := name_buffer;
|
||||
arguments_operand^.length := 4;
|
||||
arguments_operand^.kind := argument_type;
|
||||
arguments_operand^.value := argument_value;
|
||||
arguments_operand^.length := argument_length;
|
||||
arguments_operand := arguments_operand + #size(ElnaTacOperand);
|
||||
|
||||
argument_entry := argument_entry^.next;
|
||||
argument_count := argument_count + 1;
|
||||
goto elna_tac_call_loop
|
||||
end;
|
||||
if first_instruction = nil then
|
||||
@@ -2573,11 +2569,14 @@ var
|
||||
current_field: ^ElnaTypeField;
|
||||
field_offset: Word;
|
||||
is_address: Word;
|
||||
base_type: Word;
|
||||
base_value: Word;
|
||||
base_length: Word;
|
||||
begin
|
||||
designator_base := field_access_expression^.aggregate;
|
||||
aggregate_type := designator_base^.type_decoration;
|
||||
|
||||
first_instruction := elna_tac_designator(designator_base, symbol_table, @is_address, operand_type, operand_value, operand_length);
|
||||
first_instruction := elna_tac_designator(designator_base, symbol_table, @is_address, @base_type, @base_value, @base_length);
|
||||
|
||||
field_count := aggregate_type^.length;
|
||||
current_field := aggregate_type^.members;
|
||||
@@ -2592,14 +2591,12 @@ begin
|
||||
field_offset := field_offset + field_type^.size;
|
||||
goto elna_tac_field_access_expression_field
|
||||
end;
|
||||
last_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacKind.pseudo, "$unary", 6);
|
||||
elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacKind.immediate, field_offset, 0);
|
||||
elna_tac_instruction_set_operand(last_instruction, 3, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
operand_type^ := ElnaTacKind.pseudo;
|
||||
operand_value^ := "$unary";
|
||||
operand_length^ := 6;
|
||||
last_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(last_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacKind.immediate, field_offset, 0);
|
||||
elna_tac_instruction_set_operand(last_instruction, 3, base_type, base_value, base_length);
|
||||
|
||||
return elna_instruction_list_concatenate(first_instruction, last_instruction)
|
||||
end;
|
||||
@@ -2611,9 +2608,9 @@ var
|
||||
offset_instruction: Word;
|
||||
add_instruction: Word;
|
||||
is_address: Word;
|
||||
offset_type: Word;
|
||||
offset_value: Word;
|
||||
offset_length: Word;
|
||||
inter_type: Word;
|
||||
inter_value: Word;
|
||||
inter_length: Word;
|
||||
aggregate_type: ^ElnaTypeArray;
|
||||
designator_base: ^ElnaTreeExpression;
|
||||
element_type: ^ElnaType;
|
||||
@@ -2622,27 +2619,28 @@ begin
|
||||
aggregate_type := designator_base^.type_decoration;
|
||||
element_type := aggregate_type^.base;
|
||||
|
||||
index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, operand_type, operand_value, operand_length);
|
||||
index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, @inter_type, @inter_value, @inter_length);
|
||||
elna_tac_generate_pseudo(operand_type, operand_value, operand_length);
|
||||
|
||||
add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
|
||||
elna_tac_instruction_set_operand(add_instruction, 1, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(add_instruction, 2, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(add_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(add_instruction, 2, inter_type, inter_value, inter_length);
|
||||
elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacKind.immediate, 1, 0);
|
||||
|
||||
offset_instruction := elna_tac_instruction_create(ElnaTacOperator.multiply);
|
||||
elna_tac_instruction_set_operand(offset_instruction, 1, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(offset_instruction, 2, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(offset_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(offset_instruction, 2, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(offset_instruction, 3, ElnaTacKind.immediate, element_type^.size, 0);
|
||||
|
||||
elna_instruction_list_concatenate(add_instruction, offset_instruction);
|
||||
index_instructions := elna_instruction_list_concatenate(index_instructions, add_instruction);
|
||||
|
||||
array_instructions := elna_tac_designator(array_access_expression^.array, symbol_table, @is_address, operand_type, operand_value, operand_length);
|
||||
array_instructions := elna_tac_designator(array_access_expression^.array, symbol_table, @is_address, @inter_type, @inter_value, @inter_length);
|
||||
|
||||
add_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(add_instruction, 1, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(add_instruction, 2, operand_type^, operand_value^, operand_length^);
|
||||
elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacKind.pseudo, "$lhs", 4);
|
||||
elna_tac_instruction_set_operand(add_instruction, 2, inter_type, inter_value, inter_length);
|
||||
elna_tac_instruction_set_operand(add_instruction, 3, operand_type^, operand_value^, operand_length^);
|
||||
|
||||
elna_instruction_list_concatenate(offset_instruction, array_instructions);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user