diff --git a/boot/stage21/cl.elna b/boot/stage21/cl.elna index 5cf3744..8c613e1 100644 --- a/boot/stage21/cl.elna +++ b/boot/stage21/cl.elna @@ -317,6 +317,7 @@ type end; ElnaSymbolTable = record count: Word; + parent: Word; symbols: ^ElnaSymbolEntry end; ElnaSymbolInfoKind = (type_info, parameter_info, temporary_info, procedure_info); @@ -659,6 +660,7 @@ type var symbol_table_global: ^ElnaSymbolTable; + variable_map_global: ^ElnaSymbolTable; compiler_strings: [1024]Word; classification: [256]Word; @@ -928,7 +930,7 @@ begin elna_list_append(instructions, instruction) elsif operand^.kind = ElnaTacKind.variable then pseudo_symbol := elna_symbol_table_lookup(variable_map, operand^.value, operand^.length); - if pseudo_symbol = nil then + if pseudo_symbol^.kind = ElnaRtlInfoKind.static_info then instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.data, operand^.value, operand^.length, 0); @@ -963,7 +965,7 @@ begin elna_list_append(instructions, instruction) elsif tac_operand^.kind = ElnaTacKind.variable then pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_operand^.value, tac_operand^.length); - if pseudo_symbol = nil then + if pseudo_symbol^.kind = ElnaRtlInfoKind.static_info then elna_rtl_generate_pseudo(rtl_operand, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); @@ -1104,9 +1106,14 @@ begin elna_rtl_instruction_set_operand(instruction, 1, target_operand^.kind, target_operand^.value, target_operand^.length, 0); + (* "strings" variable with static strings is in the end object and should be addressable, + but not in the symbol table. *) if pseudo_symbol = nil then elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.data, addressable^.value, addressable^.length, 0) + elsif pseudo_symbol^.kind = ElnaRtlInfoKind.static_info then + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.data, + addressable^.value, addressable^.length, 0) elsif pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo_mem, addressable^.value, addressable^.length, 0) @@ -1272,7 +1279,7 @@ begin pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); - if pseudo_symbol = nil then + if pseudo_symbol^.kind = ElnaRtlInfoKind.static_info then elna_rtl_generate_pseudo(@target_operand, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); @@ -1933,9 +1940,40 @@ end; proc elna_rtl_module_declaration(tac_module: ^ElnaInstructionModule) -> ^ElnaInstructionModule; var result: ^ElnaInstructionModule; + count: Word; + current_entry: ^ElnaSymbolEntry; + pseudo_symbol: ^ElnaRtlStaticInfo; + variable_info: ^ElnaSymbolTemporaryInfo; + info: ^ElnaSymbolInfo; begin result := malloc(#size(ElnaInstructionModule)); result^.data := elna_rtl_globals(tac_module^.data); + + (* Rewrite global symbol table into global backend symbol table. *) + variable_map_global := elna_symbol_table_create(nil); + count := symbol_table_global^.count; + current_entry := symbol_table_global^.symbols; + + .elna_rtl_module_declaration_loop; + if count = 0 then + goto elna_rtl_module_declaration_end + end; + info := current_entry^.symbol_info; + if info^.kind = ElnaSymbolInfoKind.temporary_info then + variable_info := current_entry^.symbol_info; + + pseudo_symbol := malloc(#size(ElnaRtlStaticInfo)); + pseudo_symbol^.kind := ElnaRtlInfoKind.static_info; + pseudo_symbol^.rtl_type := elna_rtl_symbol_type(variable_info^.variable_type); + + elna_symbol_table_enter(variable_map_global, current_entry^.name, current_entry^.length, pseudo_symbol) + end; + count := count - 1; + current_entry := current_entry + 1; + + goto elna_rtl_module_declaration_loop; + + .elna_rtl_module_declaration_end; result^.code := elna_rtl_procedures(tac_module^.code); return result @@ -3846,54 +3884,35 @@ begin return pseudo_symbol end; -proc elna_rtl_symbol_table(symbol_table: ^ElnaSymbolTable) -> ^ElnaSymbolTable; +proc elna_rtl_symbol_type(variable_type: ^ElnaType); var - variable_map: ^ElnaSymbolTable; - count: Word; - current_entry: ^ElnaSymbolEntry; - pseudo_symbol: ^ElnaRtlObjectInfo; - variable_info: ^ElnaSymbolTemporaryInfo; byte_array: ^ElnaRtlTypeByteArray; long_word: ^ElnaRtlTypeWord; + rtl_type: ^ElnaRtlType; begin - variable_map := elna_symbol_table_create(); - count := symbol_table^.count; - current_entry := symbol_table^.symbols; + if elna_type_is_aggregate(variable_type) then + byte_array := malloc(#size(ElnaRtlTypeByteArray)); + byte_array^.kind := ElnaRtlTypeKind.byte_array; + byte_array^.size := variable_type^.size; + byte_array^.alignment := variable_type^.alignment; - .elna_rtl_symbol_table_loop; - if count > 0 then - variable_info := current_entry^.symbol_info; + rtl_type := byte_array + else + long_word := malloc(#size(ElnaRtlTypeWord)); + long_word^.kind := ElnaRtlTypeKind.long_word; - pseudo_symbol := malloc(#size(ElnaRtlObjectInfo)); - pseudo_symbol^.allocated := false; - pseudo_symbol^.kind := ElnaRtlInfoKind.object_info; - - if elna_type_is_aggregate(variable_info^.variable_type) then - byte_array := malloc(#size(ElnaRtlTypeByteArray)); - byte_array^.kind := ElnaRtlTypeKind.byte_array; - byte_array^.size := variable_info^.variable_type^.size; - byte_array^.alignment := variable_info^.variable_type^.alignment; - - pseudo_symbol^.rtl_type := byte_array - else - long_word := malloc(#size(ElnaRtlTypeWord)); - long_word^.kind := ElnaRtlTypeKind.long_word; - - pseudo_symbol^.rtl_type := long_word - end; - elna_symbol_table_enter(variable_map, current_entry^.name, current_entry^.length, pseudo_symbol); - - count := count - 1; - current_entry := current_entry + 1; - - goto elna_rtl_symbol_table_loop + rtl_type := long_word end; - - return variable_map; + return rtl_type end; proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaTacProcedure) -> ^ElnaRtlProcedure; var + count: Word; + current_entry: ^ElnaSymbolEntry; + pseudo_symbol: ^ElnaRtlObjectInfo; + variable_info: ^ElnaSymbolTemporaryInfo; + info: ^ElnaSymbolInfo; result: ^ElnaRtlProcedure; begin result := malloc(#size(ElnaRtlProcedure)); @@ -3906,7 +3925,32 @@ begin pseudo_counter := 0; elna_rtl_parameters(@result^.body, tac_declaration^.parameters, tac_declaration^.count); - result^.variable_map := elna_rtl_symbol_table(tac_declaration^.symbol_table); + result^.variable_map := elna_symbol_table_create(variable_map_global); + count := tac_declaration^.symbol_table^.count; + current_entry := tac_declaration^.symbol_table^.symbols; + + .elna_rtl_procedure_declaration_loop; + if count = 0 then + goto elna_rtl_procedure_declaration_end + end; + info := current_entry^.symbol_info; + if info^.kind = ElnaSymbolInfoKind.temporary_info then + variable_info := current_entry^.symbol_info; + + pseudo_symbol := malloc(#size(ElnaRtlObjectInfo)); + pseudo_symbol^.allocated := false; + pseudo_symbol^.kind := ElnaRtlInfoKind.object_info; + pseudo_symbol^.rtl_type := elna_rtl_symbol_type(variable_info^.variable_type); + + elna_symbol_table_enter(result^.variable_map, current_entry^.name, current_entry^.length, pseudo_symbol) + end; + count := count - 1; + current_entry := current_entry + 1; + + goto elna_rtl_procedure_declaration_loop; + + .elna_rtl_procedure_declaration_end; + elna_rtl_instructions(@result^.body, tac_declaration^.body.first, result^.variable_map); return result @@ -4352,7 +4396,7 @@ var new_symbol_table: ^ElnaSymbolTable; symbol_info: Word; begin - new_symbol_table := elna_symbol_table_create(); + new_symbol_table := elna_symbol_table_create(symbol_table_global); symbol_info := procedure_info_create(new_symbol_table); elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); @@ -4366,7 +4410,7 @@ var new_symbol_table: ^ElnaSymbolTable; symbol_info: Word; begin - new_symbol_table := elna_symbol_table_create(); + new_symbol_table := elna_symbol_table_create(symbol_table_global); symbol_info := procedure_info_create(new_symbol_table); elna_symbol_table_enter(symbol_table_global, "main", 4, symbol_info) @@ -4492,9 +4536,6 @@ var begin variable_info := elna_symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length); - if variable_info = nil then - variable_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name, parser_node^.length) - end; if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then temporary_info := variable_info; parser_node^.type_decoration := temporary_info^.variable_type @@ -4748,11 +4789,9 @@ proc elna_symbol_table_lookup(symbol_table: ^ElnaSymbolTable, symbol_name: Word, var result: Word; symbol_table_length: Word; - current_name: Word; - current_length: Word; current_entry: ^ElnaSymbolEntry; begin - result := 0; + result := nil; symbol_table_length := symbol_table^.count; (* Go to the first symbol position. *) @@ -4760,19 +4799,13 @@ begin .symbol_table_lookup_loop; if symbol_table_length = 0 then + if symbol_table^.parent <> nil then + result := elna_symbol_table_lookup(symbol_table^.parent, symbol_name, name_length) + end; goto symbol_table_lookup_end end; - - (* Symbol name pointer and length. *) - current_name := current_entry^.name; - current_length := current_entry^.length; - - (* If lengths don't match, exit and return nil. *) - if name_length <> current_length then - goto symbol_table_lookup_repeat - end; - (* If names don't match, exit and return nil. *) - if memcmp(symbol_name, current_name, name_length) then + (* If names don't match, try the next entry. *) + if string_compare(current_entry^.name, current_entry^.length, symbol_name, name_length) = false then goto symbol_table_lookup_repeat end; (* Otherwise, the symbol is found. *) @@ -4791,14 +4824,20 @@ end; (** * Create a new local symbol table in the symbol memory region after the last * known symbol table. + * + * Parameters: + * parent - Outer scope. + * + * Returns newly allocated, empty symbol table. *) -proc elna_symbol_table_create(); +proc elna_symbol_table_create(parent: ^ElnaSymbolTable); var new_symbol_table: ^ElnaSymbolTable; begin new_symbol_table := malloc(#size(ElnaSymbolTable)); new_symbol_table^.symbols := malloc(16384); new_symbol_table^.count := 0; + new_symbol_table^.parent := parent; return new_symbol_table end; @@ -4827,14 +4866,14 @@ begin symbol_table^.count := symbol_table^.count + 1 end; +(* Build global symbol table with predefined symbols. *) proc elna_symbol_table_build(); var current_info: ^ElnaSymbolTypeInfo; current_type: ^ElnaType; global_pointer: ^Word; begin - (* Set the table length to 0. *) - symbol_table_global := elna_symbol_table_create(); + symbol_table_global := elna_symbol_table_create(nil); (* Enter built-in symbols. *) word_type := malloc(#size(ElnaType)); @@ -4863,8 +4902,7 @@ begin current_type^.size := 1; current_type^.alignment := 1; current_info := type_info_create(current_type); - elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info); - + elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info) end; (** @@ -5214,16 +5252,15 @@ begin cursor^.position.end_location.column := 1 end; -(* Returns true of false depending whether to strings are equal. *) +(* Returns true or false depending whether two strings are equal. *) proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word); var result: Word; begin - result := 0; - if lhs_length = rhs_length then - result := memcmp(lhs_pointer, rhs_pointer, lhs_length); - result := result = 0 + result := memcmp(lhs_pointer, rhs_pointer, lhs_length) = 0 + else + result := false end; return result end;