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