Generate pseudo variables where possible
This commit is contained in:
@@ -464,7 +464,7 @@ type
|
||||
label,
|
||||
_return
|
||||
);
|
||||
ElnaTacKind = (list, immediate, symbol, pseudo);
|
||||
ElnaTacKind = (list, immediate, symbol, pseudo, pseudo_mem);
|
||||
ElnaTacOperand = record
|
||||
kind: ElnaTacKind;
|
||||
value: Word;
|
||||
@@ -550,6 +550,9 @@ type
|
||||
t5,
|
||||
t6
|
||||
);
|
||||
ElnaRtlInfo = record
|
||||
counter: Word
|
||||
end;
|
||||
|
||||
var
|
||||
symbol_table_global: Array;
|
||||
@@ -563,6 +566,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
|
||||
@@ -575,22 +579,22 @@ var
|
||||
*)
|
||||
proc _string_length(string: Word);
|
||||
var
|
||||
counter1: Word;
|
||||
current_byte1: Word;
|
||||
counter: Word;
|
||||
current_byte: Word;
|
||||
begin
|
||||
(* Reset the counter. *)
|
||||
counter1 := 0;
|
||||
counter := 0;
|
||||
|
||||
.string_length_loop;
|
||||
string := string + 1;
|
||||
|
||||
current_byte1 := _load_byte(string);
|
||||
if current_byte1 <> '"' then
|
||||
counter1 := counter1 + 1;
|
||||
current_byte := _load_byte(string);
|
||||
if current_byte <> '"' then
|
||||
counter := counter + 1;
|
||||
goto string_length_loop
|
||||
end;
|
||||
|
||||
return counter1
|
||||
return counter
|
||||
end;
|
||||
|
||||
(**
|
||||
@@ -603,27 +607,27 @@ end;
|
||||
*)
|
||||
proc _add_string(string: Word);
|
||||
var
|
||||
contents1: Word;
|
||||
result1: Word;
|
||||
current_byte1: Word;
|
||||
contents: Word;
|
||||
result: Word;
|
||||
current_byte: Word;
|
||||
begin
|
||||
contents1 := string + 1;
|
||||
result1 := compiler_strings_length;
|
||||
contents := string + 1;
|
||||
result := compiler_strings_length;
|
||||
|
||||
.add_string_loop;
|
||||
current_byte1 := _load_byte(contents1);
|
||||
if current_byte1 <> '"' then
|
||||
_store_byte(current_byte1, compiler_strings_position);
|
||||
current_byte := _load_byte(contents);
|
||||
if current_byte <> '"' then
|
||||
_store_byte(current_byte, compiler_strings_position);
|
||||
compiler_strings_position := compiler_strings_position + 1;
|
||||
contents1 := contents1 + 1;
|
||||
contents := contents + 1;
|
||||
|
||||
if current_byte1 <> '\\' then
|
||||
if current_byte <> '\\' then
|
||||
compiler_strings_length := compiler_strings_length + 1
|
||||
end;
|
||||
goto add_string_loop
|
||||
end;
|
||||
|
||||
return result1
|
||||
return result
|
||||
end;
|
||||
|
||||
(**
|
||||
@@ -694,6 +698,20 @@ 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
|
||||
pseudo_counter := pseudo_counter + 1;
|
||||
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;
|
||||
@@ -835,7 +853,7 @@ begin
|
||||
return lhs
|
||||
end;
|
||||
|
||||
proc elna_rtl_binary_arithmetic(tac_instruction: Word, next_instruction: ^^ElnaRtlInstruction, operation: Word);
|
||||
proc elna_rtl_binary_arithmetic(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, operation: Word);
|
||||
var
|
||||
lhs: Word;
|
||||
binary_result: ^ElnaRtlInstruction;
|
||||
@@ -894,7 +912,13 @@ begin
|
||||
operand_value := tac_instruction^.operands[number].value;
|
||||
operand_length := tac_instruction^.operands[number].length;
|
||||
|
||||
elna_rtl_instruction_set_operand(rtl_instruction, number, operand_type, operand_value, operand_length)
|
||||
if operand_type = ElnaTacKind.immediate then
|
||||
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.immediate, operand_value, operand_length)
|
||||
elsif operand_type = ElnaTacKind.symbol then
|
||||
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.symbol, operand_value, operand_length)
|
||||
elsif operand_type = ElnaTacKind.pseudo then
|
||||
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.pseudo, operand_value, operand_length)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_rtl_conditional_jump(tac_instruction: Word, condition: Word);
|
||||
@@ -924,7 +948,7 @@ end;
|
||||
proc elna_rtl_call(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction);
|
||||
var
|
||||
argument_count: Word;
|
||||
current_argument: Word;
|
||||
current_argument: ^ElnaTacOperand;
|
||||
argument_type: Word;
|
||||
argument_value: Word;
|
||||
argument_length: Word;
|
||||
@@ -944,12 +968,10 @@ begin
|
||||
if argument_count > 0 then
|
||||
argument_count := argument_count - 1;
|
||||
|
||||
argument_type := current_argument^;
|
||||
current_argument := current_argument + 4;
|
||||
argument_value := current_argument^;
|
||||
current_argument := current_argument + 4;
|
||||
argument_length := current_argument^;
|
||||
current_argument := current_argument + 4;
|
||||
argument_type := current_argument^.kind;
|
||||
argument_value := current_argument^.value;
|
||||
argument_length := current_argument^.length;
|
||||
current_argument := current_argument + #size(ElnaTacOperand);
|
||||
|
||||
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
|
||||
elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
|
||||
@@ -1182,13 +1204,13 @@ end;
|
||||
|
||||
proc elna_tac_label(counter: Word, length: Word);
|
||||
var
|
||||
result1: Word;
|
||||
result: Word;
|
||||
begin
|
||||
result1 := elna_tac_instruction_create(ElnaTacOperator.label);
|
||||
result := elna_tac_instruction_create(ElnaTacOperator.label);
|
||||
|
||||
elna_tac_instruction_set_operand(result1, 1, ElnaTacKind.symbol, counter, length);
|
||||
elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length);
|
||||
|
||||
return result1
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_riscv_instruction_name(instruction_kind: Word);
|
||||
@@ -1273,8 +1295,8 @@ end;
|
||||
|
||||
proc elna_riscv_register(register: Word);
|
||||
begin
|
||||
_write_c('x');
|
||||
_write_i(register - 1)
|
||||
printf("x%i\0", register - 1);
|
||||
fflush(nil)
|
||||
end;
|
||||
|
||||
proc elna_riscv_operand(instruction: ^ElnaRtlInstruction, n: Word);
|
||||
@@ -1306,12 +1328,14 @@ end;
|
||||
|
||||
proc elna_alloc_variable(operand_value: Word, operand_length: Word);
|
||||
var
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
begin
|
||||
pseudo_symbol := _symbol_table_lookup(@variable_map, operand_value, operand_length);
|
||||
if pseudo_symbol = nil then
|
||||
_symbol_table_enter(@variable_map, operand_value, operand_length, temporary_variable_counter);
|
||||
pseudo_symbol := temporary_variable_counter;
|
||||
pseudo_symbol := malloc(#size(ElnaRtlInfo));
|
||||
pseudo_symbol^.counter := temporary_variable_counter;
|
||||
|
||||
_symbol_table_enter(@variable_map, operand_value, operand_length, pseudo_symbol);
|
||||
temporary_variable_counter := temporary_variable_counter + 4
|
||||
end;
|
||||
return pseudo_symbol
|
||||
@@ -1324,7 +1348,7 @@ end;
|
||||
*)
|
||||
proc elna_alloc_operation_target(instruction: ^ElnaRtlInstruction);
|
||||
var
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
store_instruction: ^ElnaRtlInstruction;
|
||||
begin
|
||||
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
|
||||
@@ -1333,7 +1357,7 @@ begin
|
||||
|
||||
pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length);
|
||||
elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
|
||||
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
instruction^.next := store_instruction;
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0)
|
||||
@@ -1342,14 +1366,14 @@ end;
|
||||
|
||||
proc elna_alloc_load_address(instruction: ^ElnaRtlInstruction);
|
||||
var
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
begin
|
||||
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
|
||||
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length);
|
||||
instruction^.operator := ElnaRtlOperator.addi;
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.sp, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol, 0)
|
||||
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol^.counter, 0)
|
||||
end;
|
||||
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
|
||||
elna_alloc_operation_target(instruction)
|
||||
@@ -1359,7 +1383,7 @@ end;
|
||||
proc elna_alloc_store(instruction: ^ElnaRtlInstruction);
|
||||
var
|
||||
old_instruction: ^ElnaRtlInstruction;
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
begin
|
||||
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
|
||||
old_instruction := malloc(#size(ElnaRtlInstruction));
|
||||
@@ -1369,7 +1393,7 @@ begin
|
||||
instruction^.operator := ElnaRtlOperator.lw;
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
instruction^.next := old_instruction;
|
||||
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0)
|
||||
@@ -1379,7 +1403,7 @@ end;
|
||||
proc elna_alloc_load(instruction: ^ElnaRtlInstruction);
|
||||
var
|
||||
old_instruction: ^ElnaRtlInstruction;
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
begin
|
||||
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
|
||||
old_instruction := malloc(#size(ElnaRtlInstruction));
|
||||
@@ -1389,7 +1413,7 @@ begin
|
||||
old_instruction^.operator := ElnaRtlOperator.sw;
|
||||
|
||||
elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
|
||||
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
instruction^.next := old_instruction;
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0)
|
||||
@@ -1398,7 +1422,7 @@ end;
|
||||
|
||||
proc elna_alloc_instruction(instruction: ^ElnaRtlInstruction);
|
||||
var
|
||||
pseudo_symbol: Word;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
old_instruction: ^ElnaRtlInstruction;
|
||||
begin
|
||||
if instruction^.operator = ElnaRtlOperator.move then
|
||||
@@ -1409,14 +1433,14 @@ begin
|
||||
instruction^.operands[1].kind := instruction^.operands[2].kind;
|
||||
instruction^.operands[1].value := instruction^.operands[2].value;
|
||||
instruction^.operands[1].length := instruction^.operands[2].length;
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
goto elna_alloc_instruction_end
|
||||
end;
|
||||
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
|
||||
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length);
|
||||
instruction^.operator = ElnaRtlOperator.lw;
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
goto elna_alloc_instruction_end
|
||||
end
|
||||
@@ -1451,7 +1475,7 @@ begin
|
||||
instruction^.operator := ElnaRtlOperator.lw;
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
|
||||
|
||||
instruction^.next := old_instruction;
|
||||
elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
|
||||
@@ -1564,7 +1588,7 @@ var
|
||||
stack_instruction: ^ElnaRtlInstruction;
|
||||
begin
|
||||
.elna_alloc_procedure_loop;
|
||||
temporary_variable_counter := 4;
|
||||
temporary_variable_counter := 0;
|
||||
variable_map := 0;
|
||||
|
||||
elna_alloc_instructions(rtl_declaration^.body);
|
||||
@@ -1591,14 +1615,10 @@ begin
|
||||
.elna_riscv_procedure_loop;
|
||||
|
||||
(* Write .type _procedure_name, @function. *)
|
||||
_write_z(".type \0");
|
||||
|
||||
_write_s(procedure^.name, procedure^.length);
|
||||
_write_z(", @function\n\0");
|
||||
printf(".type %.*s, @function\n\0", procedure^.length, procedure^.name);
|
||||
|
||||
(* Write procedure label, _procedure_name: *)
|
||||
_write_s(procedure^.name, procedure^.length);
|
||||
_write_z(":\n\0");
|
||||
printf("%.*s:\n\0", procedure^.length, procedure^.name);
|
||||
|
||||
elna_riscv_instructions(procedure^.body);
|
||||
_write_z("\tret\n\0");
|
||||
@@ -1613,17 +1633,9 @@ proc elna_riscv_variable(variable: ^ElnaInstructionDeclaration);
|
||||
begin
|
||||
.elna_riscv_variable_loop;
|
||||
if variable <> 0 then
|
||||
_write_z(".type \0");
|
||||
_write_s(variable^.name, variable^.length);
|
||||
_write_z(", @object\n\0");
|
||||
printf(".type %.*s, @object\n\0", variable^.length, variable^.name);
|
||||
|
||||
_write_s(variable^.name, variable^.length);
|
||||
_write_c(':');
|
||||
|
||||
_write_z(" .zero \0");
|
||||
_write_i(variable^.body);
|
||||
|
||||
_write_c('\n');
|
||||
printf("%.*s: .zero %i\n\0", variable^.length, variable^.name, variable^.body);
|
||||
variable := variable^.next;
|
||||
|
||||
goto elna_riscv_variable_loop
|
||||
@@ -1850,7 +1862,7 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc _elna_tac_string_literal(string_literal_node: ^ElnaTreeStringLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
|
||||
proc elna_tac_string_literal(string_literal_node: ^ElnaTreeStringLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
|
||||
var
|
||||
offset: Word;
|
||||
first_instruction: Word;
|
||||
@@ -1858,20 +1870,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;
|
||||
|
||||
@@ -1989,7 +1999,7 @@ begin
|
||||
if parser_node^.kind = ElnaTreeKind.character_literal then
|
||||
instruction := elna_tac_character_literal(parser_node, operand_type, operand_value, operand_length)
|
||||
elsif parser_node^.kind = ElnaTreeKind.string_literal then
|
||||
instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length)
|
||||
instruction := elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length)
|
||||
elsif parser_node^.kind = ElnaTreeKind.integer_literal then
|
||||
instruction := elna_tac_integer_literal(parser_node, operand_type, operand_value, operand_length)
|
||||
elsif parser_node^.kind = ElnaTreeKind.boolean_literal then
|
||||
@@ -2047,6 +2057,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 +2069,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;
|
||||
|
||||
@@ -2164,36 +2175,20 @@ proc elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_t
|
||||
var
|
||||
first_instruction: Word;
|
||||
instruction: Word;
|
||||
current_instruction: Word;
|
||||
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. *)
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
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
|
||||
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);
|
||||
current_instruction := elna_instruction_list_concatenate(current_instruction, instruction);
|
||||
instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @rhs_type, @rhs_value, @rhs_length);
|
||||
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction);
|
||||
|
||||
if parser_node^.operator = ElnaLexerKind.plus then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add)
|
||||
@@ -2224,15 +2219,13 @@ 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)
|
||||
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction)
|
||||
end;
|
||||
return first_instruction
|
||||
end;
|
||||
@@ -2299,30 +2292,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 +2318,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 +2543,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 +2565,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 +2582,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 +2593,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);
|
||||
|
||||
@@ -2678,69 +2650,63 @@ var
|
||||
operand_type: Word;
|
||||
operand_value: Word;
|
||||
operand_length: Word;
|
||||
assignment_type: Word;
|
||||
assignment_value: Word;
|
||||
assignment_length: Word;
|
||||
assignee_type: Word;
|
||||
assignee_value: Word;
|
||||
assignee_length: Word;
|
||||
begin
|
||||
operand_type := 0;
|
||||
operand_value := 0;
|
||||
operand_length := 0;
|
||||
first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length);
|
||||
first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table,
|
||||
@is_address, @assignee_type, @assignee_value, @assignee_length);
|
||||
(* Compile the assignment. *)
|
||||
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table,
|
||||
@assignment_type, @assignment_value, @assignment_length);
|
||||
|
||||
if assignee_type = ElnaTacKind.pseudo then
|
||||
current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
|
||||
if operand_type = ElnaTacKind.pseudo then
|
||||
if is_address then
|
||||
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length);
|
||||
|
||||
(* Save the assignee address on the stack. *)
|
||||
current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacKind.pseudo, "$assign", 7);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, assignee_type, assignee_value, assignee_length);
|
||||
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
|
||||
|
||||
(* Compile the assignment. *)
|
||||
operand_type := 0;
|
||||
operand_value := 0;
|
||||
operand_length := 0;
|
||||
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
|
||||
|
||||
if instruction <> 0 then
|
||||
if instruction <> nil then
|
||||
elna_instruction_list_concatenate(current_instruction, instruction);
|
||||
current_instruction := instruction
|
||||
end;
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.store);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.pseudo, "$assign", 7);
|
||||
elna_tac_instruction_set_operand(instruction, 1, assignment_type, assignment_value, assignment_length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length);
|
||||
|
||||
elna_instruction_list_concatenate(current_instruction, instruction)
|
||||
else
|
||||
current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length);
|
||||
|
||||
operand_type := 0;
|
||||
operand_value := 0;
|
||||
operand_length := 0;
|
||||
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, assignee_type, assignee_value, assignee_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, assignment_type, assignment_value, assignment_length);
|
||||
|
||||
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction)
|
||||
end
|
||||
else
|
||||
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length);
|
||||
|
||||
(* Save the assignee address on the stack. *)
|
||||
current_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacKind.pseudo, "$assign", 7);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(current_instruction, 2, assignee_type, assignee_value, assignee_length);
|
||||
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
|
||||
|
||||
(* Compile the assignment. *)
|
||||
operand_type := 0;
|
||||
operand_value := 0;
|
||||
operand_length := 0;
|
||||
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
|
||||
|
||||
if instruction <> 0 then
|
||||
if instruction <> nil then
|
||||
elna_instruction_list_concatenate(current_instruction, instruction);
|
||||
current_instruction := instruction
|
||||
end;
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.store);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.pseudo, "$assign", 7);
|
||||
elna_tac_instruction_set_operand(instruction, 1, assignment_type, assignment_value, assignment_length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length);
|
||||
|
||||
elna_instruction_list_concatenate(current_instruction, instruction)
|
||||
end;
|
||||
@@ -2798,15 +2764,11 @@ var
|
||||
first_byte: Word;
|
||||
begin
|
||||
if length = 0 then
|
||||
_write_s(".L", 2);
|
||||
_write_i(counter)
|
||||
printf(".L%i\0", counter)
|
||||
else
|
||||
first_byte := _load_byte(counter);
|
||||
if first_byte <> '.' then
|
||||
_write_c('.')
|
||||
end;
|
||||
_write_s(counter, length)
|
||||
end
|
||||
printf(".%.*s\0", length, counter);
|
||||
end;
|
||||
fflush(nil)
|
||||
end;
|
||||
|
||||
proc elna_parser_conditional_statements();
|
||||
@@ -2979,6 +2941,8 @@ begin
|
||||
first_instruction := nil;
|
||||
|
||||
.elna_tac_statements_loop;
|
||||
pseudo_counter := 0;
|
||||
|
||||
if current_statement <> nil then
|
||||
instruction := elna_tac_statement(current_statement, symbol_table);
|
||||
current_statement := current_statement^.next;
|
||||
@@ -3962,26 +3926,18 @@ end;
|
||||
|
||||
proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration);
|
||||
var
|
||||
name: Word;
|
||||
name_length: Word;
|
||||
variable_type: ^ElnaTreeNamedTypeExpression;
|
||||
result: ^ElnaInstructionDeclaration;
|
||||
begin
|
||||
result := malloc(#size(ElnaInstructionDeclaration));
|
||||
|
||||
result^.next := nil;
|
||||
|
||||
name := parser_tree^.name;
|
||||
name_length := parser_tree^.length;
|
||||
variable_type := parser_tree^._type;
|
||||
|
||||
result^.name := name;
|
||||
result^.length := name_length;
|
||||
result^.name := parser_tree^.name;
|
||||
result^.length := parser_tree^.length;
|
||||
|
||||
name := variable_type^.name;
|
||||
name_length := variable_type^.length;
|
||||
|
||||
if string_compare("Array", 5, name, name_length) then
|
||||
if string_compare("Array", 5, variable_type^.name, variable_type^.length) then
|
||||
(* Else we assume this is a zeroed 4096 bytes big array. *)
|
||||
result^.body := 4096
|
||||
else
|
||||
@@ -5467,3 +5423,10 @@ begin
|
||||
exit(4)
|
||||
end;
|
||||
end;
|
||||
|
||||
proc f();
|
||||
var
|
||||
a: Word;
|
||||
begin
|
||||
return a
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user