diff --git a/boot/stage19/cl.elna b/boot/stage19/cl.elna index 0f0b832..698f85a 100644 --- a/boot/stage19/cl.elna +++ b/boot/stage19/cl.elna @@ -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);