Implement copy_to_offset and copy_from_offset TAC instructions
This commit is contained in:
@@ -9,6 +9,7 @@ program;
|
||||
|
||||
(* - Aggregates can be allocated on the stack. *)
|
||||
(* - Procedure return type is parsed. *)
|
||||
(* - "|" can be used as binary "+" for pointer arithmetic. *)
|
||||
|
||||
type
|
||||
(**
|
||||
@@ -2167,6 +2168,9 @@ begin
|
||||
elsif token_kind = ElnaLexerKind.minus then
|
||||
_elna_lexer_skip_token();
|
||||
rhs_node := elna_parser_unary_expression()
|
||||
elsif token_kind = ElnaLexerKind.pipe then
|
||||
_elna_lexer_skip_token();
|
||||
rhs_node := elna_parser_unary_expression()
|
||||
elsif token_kind = ElnaLexerKind.multiplication then
|
||||
_elna_lexer_skip_token();
|
||||
rhs_node := elna_parser_unary_expression()
|
||||
@@ -2241,6 +2245,8 @@ begin
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add)
|
||||
elsif parser_node^.operator = ElnaLexerKind.minus then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.subtract)
|
||||
elsif parser_node^.operator = ElnaLexerKind.pipe then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add)
|
||||
elsif parser_node^.operator = ElnaLexerKind.multiplication then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.multiply)
|
||||
elsif parser_node^.operator = ElnaLexerKind.and then
|
||||
@@ -5165,6 +5171,8 @@ begin
|
||||
result := ElnaLexerKind.left_square
|
||||
elsif character = ']' then
|
||||
result := ElnaLexerKind.right_square
|
||||
elsif character = '|' then
|
||||
result := ElnaLexerKind.pipe
|
||||
end;
|
||||
return result
|
||||
end;
|
||||
|
||||
@@ -503,6 +503,7 @@ type
|
||||
jump_if_not_zero,
|
||||
label,
|
||||
_return,
|
||||
add_ptr,
|
||||
nop
|
||||
);
|
||||
ElnaTacKind = (list, label, constant, variable);
|
||||
@@ -841,7 +842,7 @@ begin
|
||||
existing^.next := new
|
||||
end;
|
||||
|
||||
proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable);
|
||||
proc elna_tac_make_variable(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable);
|
||||
var
|
||||
buffer: Word;
|
||||
temporary_info: ^ElnaSymbolTemporaryInfo;
|
||||
@@ -938,9 +939,8 @@ var
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
begin
|
||||
rtl_operand^.kind := ElnaRtlKind.pseudo;
|
||||
if tac_operand^.kind = ElnaTacKind.constant then
|
||||
elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map);
|
||||
elna_rtl_generate_pseudo(rtl_operand, variable_map);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0);
|
||||
@@ -949,7 +949,7 @@ begin
|
||||
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
|
||||
elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map);
|
||||
elna_rtl_generate_pseudo(rtl_operand, variable_map);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0);
|
||||
@@ -961,6 +961,7 @@ begin
|
||||
elna_rtl_instruction_set_operand(instruction, 2, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
else
|
||||
rtl_operand^.kind := ElnaRtlKind.pseudo;
|
||||
rtl_operand^.value := tac_operand^.value;
|
||||
rtl_operand^.length := tac_operand^.length
|
||||
end
|
||||
@@ -1041,25 +1042,37 @@ begin
|
||||
elna_list_append(instructions, xor_instruction)
|
||||
end;
|
||||
|
||||
proc elna_rtl_get_address(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
|
||||
proc elna_rtl_operand_address(variable_map: ^ElnaSymbolTable,
|
||||
addressable: ^ElnaTacOperand, target_operand: ^ElnaRtlOperand) -> ^ElnaRtlInstruction;
|
||||
var
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
begin
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map,
|
||||
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map, addressable^.value, addressable^.length);
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo,
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, target_operand^.kind,
|
||||
target_operand^.value, target_operand^.length, 0);
|
||||
if pseudo_symbol = nil then
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol,
|
||||
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0)
|
||||
addressable^.value, addressable^.length, 0)
|
||||
else
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
|
||||
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0)
|
||||
addressable^.value, addressable^.length, 0)
|
||||
end;
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc elna_rtl_get_address(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
rtl_operand: ElnaRtlOperand;
|
||||
begin
|
||||
rtl_operand.kind := ElnaRtlKind.pseudo;
|
||||
rtl_operand.value := tac_instruction^.operands[2].value;
|
||||
rtl_operand.length := tac_instruction^.operands[2].length;
|
||||
|
||||
instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[1], @rtl_operand);
|
||||
elna_list_append(instructions, instruction)
|
||||
end;
|
||||
|
||||
@@ -1142,6 +1155,25 @@ begin
|
||||
elna_list_append(instructions, instruction)
|
||||
end;
|
||||
|
||||
proc elna_rtl_copy_to_offset(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
target_operand: ElnaRtlOperand;
|
||||
source_operand: ElnaRtlOperand;
|
||||
begin
|
||||
elna_rtl_generate_pseudo(@target_operand, variable_map);
|
||||
instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[2], @target_operand);
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @source_operand);
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, source_operand.kind, source_operand.value, source_operand.length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, target_operand.kind, target_operand.value,
|
||||
target_operand.length, tac_instruction^.operands[3].value);
|
||||
elna_list_append(instructions, instruction)
|
||||
end;
|
||||
|
||||
proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
@@ -1150,9 +1182,28 @@ begin
|
||||
elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand);
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo,
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
end;
|
||||
|
||||
proc elna_rtl_copy_from_offset(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction;
|
||||
rtl_operand: ElnaRtlOperand;
|
||||
begin
|
||||
rtl_operand.kind := ElnaRtlKind.pseudo;
|
||||
rtl_operand.value := tac_instruction^.operands[3].value;
|
||||
rtl_operand.length := tac_instruction^.operands[3].length;
|
||||
instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[1], @rtl_operand);
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo,
|
||||
tac_instruction^.operands[3].value, tac_instruction^.operands[3].length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, tac_instruction^.operands[3].value,
|
||||
tac_instruction^.operands[3].length, tac_instruction^.operands[2].value);
|
||||
elna_list_append(instructions, instruction)
|
||||
end;
|
||||
|
||||
@@ -1166,11 +1217,10 @@ begin
|
||||
if tac_instruction^.operands[2].kind = ElnaTacKind.variable then
|
||||
elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @source_operand);
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map,
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
|
||||
|
||||
if pseudo_symbol = nil then
|
||||
target_operand.kind := ElnaRtlKind.pseudo;
|
||||
elna_rtl_generate_pseudo(@target_operand.value, @target_operand.length, variable_map);
|
||||
elna_rtl_generate_pseudo(@target_operand, variable_map);
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, target_operand.kind, target_operand.value, target_operand.length, 0);
|
||||
@@ -1203,8 +1253,12 @@ begin
|
||||
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.add, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.load then
|
||||
elna_rtl_load(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.copy_from_offset then
|
||||
elna_rtl_copy_from_offset(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.store then
|
||||
elna_rtl_store(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.copy_to_offset then
|
||||
elna_rtl_copy_to_offset(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.proc_call then
|
||||
elna_rtl_call(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.subtract then
|
||||
@@ -1257,10 +1311,10 @@ begin
|
||||
elna_rtl_copy(instructions, tac_instruction, variable_map)
|
||||
elsif tac_instruction^.operator = ElnaTacOperator.nop then
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.nop);
|
||||
elna_tac_instruction_set_operand(instruction, 1, tac_instruction^.operands[1].kind,
|
||||
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, tac_instruction^.operands[2].kind,
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[1].kind,
|
||||
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, tac_instruction^.operands[2].kind,
|
||||
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
end
|
||||
end;
|
||||
@@ -1467,7 +1521,8 @@ begin
|
||||
store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
|
||||
|
||||
elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0);
|
||||
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t1, 0, 0);
|
||||
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t1, 0,
|
||||
instruction^.operands[2].offset);
|
||||
|
||||
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
|
||||
variable_map);
|
||||
@@ -1494,7 +1549,8 @@ begin
|
||||
memcpy(new_instruction, instruction, #size(ElnaRtlInstruction));
|
||||
new_instruction^.next := nil;
|
||||
|
||||
elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t0, 0, 0);
|
||||
elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t0, 0,
|
||||
instruction^.operands[2].offset);
|
||||
|
||||
instruction^.operator := ElnaRtlOperator.lw;
|
||||
|
||||
@@ -2021,11 +2077,11 @@ proc elna_tac_string_literal(instructions: ^ElnaList, string_literal_node: ^Elna
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
var
|
||||
offset: Word;
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
begin
|
||||
offset := _add_string(string_literal_node^.value);
|
||||
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.variable, "strings", 7);
|
||||
@@ -2198,21 +2254,32 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_tac_copy_address(instructions: ^ElnaList, operand_type: ElnaTacOperandType, from: ^ElnaTacOperand, to: ^ElnaTacOperand);
|
||||
proc elna_tac_copy_address(instructions: ^ElnaList, operand_result: ^ElnaTacOperandResult, from: ^ElnaTacOperand, to: ^ElnaTacOperand);
|
||||
var
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
begin
|
||||
if operand_type = ElnaTacOperandType.dereferenced_pointer then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy)
|
||||
elsif operand_type = ElnaTacOperandType.sub_object then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy)
|
||||
else
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address)
|
||||
end;
|
||||
elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length);
|
||||
if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operand_result^.kind = ElnaTacOperandType.sub_object then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length);
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
elna_list_append(instructions, instruction)
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, operand_result^.offset, 0);
|
||||
elna_tac_instruction_set_operand(instruction, 3, to^.kind, to^.value, to^.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
else (* ElnaTacOperandType.plain_object *)
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
|
||||
elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_tac_unary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
@@ -2234,35 +2301,36 @@ begin
|
||||
elna_tac_designator(instructions, unary_operand, symbol_table, @operand_result, @base);
|
||||
|
||||
if operator = '@' then
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_copy_address(instructions, operand_result.kind, @base, operand)
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_copy_address(instructions, @operand_result, @base, operand)
|
||||
elsif operator = '-' then
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operator = '~' then
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.load);
|
||||
elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operand_result.kind = ElnaTacOperandType.sub_object then
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.load);
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
|
||||
elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, operand_result.offset, 0);
|
||||
elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length);
|
||||
elna_list_append(instructions, instruction)
|
||||
else
|
||||
operand^.kind := base.kind;
|
||||
@@ -2279,7 +2347,7 @@ var
|
||||
token: ^ElnaLexerToken;
|
||||
begin
|
||||
lhs_node := elna_parser_unary_expression(cursor);
|
||||
rhs_node := 0;
|
||||
rhs_node := nil;
|
||||
token := elna_lexer_peek(cursor);
|
||||
|
||||
if token^.kind = ElnaLexerKind.plus then
|
||||
@@ -2288,6 +2356,9 @@ begin
|
||||
elsif token^.kind = ElnaLexerKind.minus then
|
||||
elna_lexer_read(cursor);
|
||||
rhs_node := elna_parser_unary_expression(cursor)
|
||||
elsif token^.kind = ElnaLexerKind.pipe then
|
||||
elna_lexer_read(cursor);
|
||||
rhs_node := elna_parser_unary_expression(cursor)
|
||||
elsif token^.kind = ElnaLexerKind.multiplication then
|
||||
elna_lexer_read(cursor);
|
||||
rhs_node := elna_parser_unary_expression(cursor)
|
||||
@@ -2339,9 +2410,40 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
proc elna_tac_sum_create(operator: ElnaTacOperator, lhs: ^ElnaTacOperand, rhs: ^ElnaTacOperand,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> ^ElnaTacInstruction;
|
||||
var
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
begin
|
||||
instruction := elna_tac_instruction_create(operator);
|
||||
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, lhs^.kind, lhs^.value, lhs^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, rhs^.kind, rhs^.value, rhs^.length);
|
||||
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc elna_tac_binary_create(operator: ElnaTacOperator, lhs: ^ElnaTacOperand, rhs: ^ElnaTacOperand,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> ^ElnaTacInstruction;
|
||||
var
|
||||
instruction: ^ElnaTacInstruction;
|
||||
begin
|
||||
instruction := elna_tac_instruction_create(operator);
|
||||
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, lhs^.kind, lhs^.value, lhs^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, rhs^.kind, rhs^.value, rhs^.length);
|
||||
|
||||
return instruction
|
||||
end;
|
||||
|
||||
proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
var
|
||||
instruction: ^ElnaTacInstruction;
|
||||
lhs: ElnaTacOperand;
|
||||
rhs: ElnaTacOperand;
|
||||
begin
|
||||
@@ -2352,40 +2454,36 @@ begin
|
||||
elna_tac_unary_expression(instructions, parser_node^.rhs, symbol_table, @rhs);
|
||||
|
||||
if parser_node^.operator = ElnaLexerKind.plus then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.minus then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.subtract)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.subtract, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.pipe then
|
||||
instruction := elna_tac_sum_create(ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.multiplication then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.multiply)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.multiply, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.and then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.and)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.and, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind._or then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator._or)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator._or, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind._xor then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator._xor)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator._xor, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.equals then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.equal)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.equal, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.remainder then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.remainder)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.remainder, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.division then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.divide)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.divide, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.less_than then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.less_than)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.less_than, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.greater_than then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.greater_than)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.greater_than, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.less_equal then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.less_or_equal)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.less_or_equal, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.greater_equal then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.greater_or_equal)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.greater_or_equal, @lhs, @rhs, symbol_table, operand)
|
||||
elsif parser_node^.operator = ElnaLexerKind.not_equal then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.not_equal)
|
||||
instruction := elna_tac_binary_create(ElnaTacOperator.not_equal, @lhs, @rhs, symbol_table, operand)
|
||||
end;
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, lhs.kind, lhs.value, lhs.length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, rhs.kind, rhs.value, rhs.length);
|
||||
|
||||
elna_list_append(instructions, instruction)
|
||||
end
|
||||
end;
|
||||
@@ -2442,13 +2540,13 @@ proc elna_tac_call(instructions: ^ElnaList, parsed_call: ^ElnaTreeCall, symbol_t
|
||||
var
|
||||
parsed_expression: ^ElnaTreeVariableExpression;
|
||||
arguments_operand: ^ElnaTacOperand;
|
||||
call_instruction: Word;
|
||||
call_instruction: ^ElnaTacInstruction;
|
||||
argument_entry: ^ElnaTreeExpressionList;
|
||||
begin
|
||||
parsed_expression := parsed_call^.callee;
|
||||
arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand));
|
||||
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
|
||||
elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.label, parsed_expression^.name, parsed_expression^.length);
|
||||
@@ -2489,7 +2587,7 @@ proc elna_tac_goto_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeGoto
|
||||
var
|
||||
label_length: Word;
|
||||
label_with_dot: Word;
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
begin
|
||||
label_length := parser_node^.length + 1;
|
||||
label_with_dot := malloc(label_length);
|
||||
@@ -2606,7 +2704,7 @@ end;
|
||||
proc elna_tac_dereference_expression(instructions: ^ElnaList, dereference_expression: ^ElnaTreeDereferenceExpression,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
var
|
||||
load_instruction: Word;
|
||||
load_instruction: ^ElnaTacInstruction;
|
||||
operand_result: ElnaTacOperandResult;
|
||||
begin
|
||||
elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @operand_result, operand);
|
||||
@@ -2618,10 +2716,10 @@ begin
|
||||
|
||||
elna_list_append(instructions, load_instruction)
|
||||
elsif operand_result.kind = ElnaTacOperandType.sub_object then
|
||||
load_instruction := elna_tac_instruction_create(ElnaTacOperator.load);
|
||||
load_instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
|
||||
elna_tac_instruction_set_operand(load_instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(load_instruction, 2, operand^.kind, operand^.value, operand^.length);
|
||||
|
||||
elna_tac_instruction_set_operand(load_instruction, 2, ElnaTacKind.constant, operand_result.offset, 0);
|
||||
elna_tac_instruction_set_operand(load_instruction, 3, operand^.kind, operand^.value, operand^.length);
|
||||
elna_list_append(instructions, load_instruction)
|
||||
end
|
||||
end;
|
||||
@@ -2645,9 +2743,8 @@ begin
|
||||
if designator_base^.type_decoration = nil then
|
||||
elna_tac_enumeration_value(field_access_expression, operand)
|
||||
else
|
||||
operand_result^.offset := elna_tac_field_access_expression(instructions,
|
||||
field_access_expression, symbol_table, operand);
|
||||
operand_result^.kind := ElnaTacOperandType.sub_object
|
||||
elna_tac_field_access_expression(instructions,
|
||||
field_access_expression, symbol_table, operand_result, operand)
|
||||
end
|
||||
elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
|
||||
elna_tac_array_access_expression(instructions, parser_node, symbol_table, operand);
|
||||
@@ -2660,22 +2757,21 @@ begin
|
||||
end;
|
||||
|
||||
proc elna_tac_field_access_expression(instructions: ^ElnaList, field_access_expression: ^ElnaTreeFieldAccessExpression,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> Word;
|
||||
symbol_table: ^ElnaSymbolTable, operand_result: ^ElnaTacOperandResult, operand: ^ElnaTacOperand);
|
||||
var
|
||||
field_type: ^ElnaType;
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
designator_base: ^ElnaTreeExpression;
|
||||
aggregate_type: ^ElnaTypeRecord;
|
||||
field_count: Word;
|
||||
current_field: ^ElnaTypeField;
|
||||
field_offset: Word;
|
||||
operand_result: ElnaTacOperandResult;
|
||||
base: ElnaTacOperand;
|
||||
begin
|
||||
designator_base := field_access_expression^.aggregate;
|
||||
aggregate_type := designator_base^.type_decoration;
|
||||
|
||||
elna_tac_designator(instructions, designator_base, symbol_table, @operand_result, @base);
|
||||
elna_tac_designator(instructions, designator_base, symbol_table, operand_result, @base);
|
||||
|
||||
field_count := aggregate_type^.length;
|
||||
current_field := aggregate_type^.members;
|
||||
@@ -2690,22 +2786,29 @@ begin
|
||||
field_offset := field_offset + field_type^.size;
|
||||
goto elna_tac_field_access_expression_field
|
||||
end;
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_copy_address(instructions, operand_result.kind, @base, operand);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, field_offset, 0);
|
||||
elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length);
|
||||
elna_list_append(instructions, instruction);
|
||||
if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
return field_offset
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, field_offset, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operand_result^.kind = ElnaTacOperandType.sub_object then
|
||||
memcpy(operand, @base, #size(ElnaTacOperand));
|
||||
operand_result^.offset := operand_result^.offset + field_offset
|
||||
else (* ElnaTacOperandType.plain_object *)
|
||||
memcpy(operand, @base, #size(ElnaTacOperand));
|
||||
operand_result^.kind := ElnaTacOperandType.sub_object;
|
||||
operand_result^.offset := field_offset
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_tac_array_access_expression(instructions: ^ElnaList, array_access_expression: ^ElnaTreeArrayAccessExpression,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
var
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
operand_result: ElnaTacOperandResult;
|
||||
inter_operand: ElnaTacOperand;
|
||||
index_type: Word;
|
||||
@@ -2720,7 +2823,7 @@ begin
|
||||
element_type := aggregate_type^.base;
|
||||
|
||||
elna_tac_binary_expression(instructions, array_access_expression^.index, symbol_table, @inter_operand);
|
||||
elna_tac_generate_pseudo(@index_type, @index_value, @index_length, symbol_table);
|
||||
elna_tac_make_variable(@index_type, @index_value, @index_length, symbol_table);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
|
||||
elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length);
|
||||
@@ -2736,9 +2839,9 @@ begin
|
||||
|
||||
elna_tac_designator(instructions, array_access_expression^.array,
|
||||
symbol_table, @operand_result, @inter_operand);
|
||||
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
|
||||
|
||||
elna_tac_copy_address(instructions, operand_result.kind, @inter_operand, operand);
|
||||
elna_tac_copy_address(instructions, @operand_result, @inter_operand, operand);
|
||||
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
|
||||
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
|
||||
@@ -2768,7 +2871,7 @@ end;
|
||||
proc elna_tac_assign_statement(instructions: ^ElnaList, parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable);
|
||||
var
|
||||
operand_result: ElnaTacOperandResult;
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
assignment_operand: ElnaTacOperand;
|
||||
assignee: ElnaTacOperand;
|
||||
symbol_info: ^ElnaSymbolInfo;
|
||||
@@ -2784,10 +2887,12 @@ begin
|
||||
assignment_operand.value, assignment_operand.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length)
|
||||
elsif operand_result.kind = ElnaTacOperandType.sub_object then
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.store);
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
|
||||
elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind,
|
||||
assignment_operand.value, assignment_operand.length);
|
||||
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length)
|
||||
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
|
||||
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, operand_result.offset, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
else
|
||||
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
|
||||
elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind,
|
||||
@@ -2818,7 +2923,7 @@ end;
|
||||
|
||||
proc elna_tac_return_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable);
|
||||
var
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
operand: ElnaTacOperand;
|
||||
begin
|
||||
elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand);
|
||||
@@ -2869,7 +2974,7 @@ proc elna_tac_conditional_statements(instructions: ^ElnaList, parser_node: ^Elna
|
||||
after_end_label: Word, symbol_table: ^ElnaSymbolTable);
|
||||
var
|
||||
condition_label: Word;
|
||||
instruction: Word;
|
||||
instruction: ^ElnaTacInstruction;
|
||||
operand: ElnaTacOperand;
|
||||
begin
|
||||
(* Compile condition. *)
|
||||
@@ -3631,12 +3736,13 @@ begin
|
||||
return lhs or rhs
|
||||
end;
|
||||
|
||||
proc elna_rtl_generate_pseudo(operand_value: Word, operand_length: Word, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInfo;
|
||||
proc elna_rtl_generate_pseudo(operand: ^ElnaRtlOperand, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInfo;
|
||||
var
|
||||
pseudo_symbol: ^ElnaRtlInfo;
|
||||
pseudo_type: ^ElnaRtlTypeWord;
|
||||
buffer: Word;
|
||||
begin
|
||||
operand^.kind := ElnaRtlKind.pseudo;
|
||||
pseudo_counter := pseudo_counter + 1;
|
||||
pseudo_symbol := malloc(#size(ElnaRtlInfo));
|
||||
buffer := malloc(7);
|
||||
@@ -3647,11 +3753,11 @@ begin
|
||||
pseudo_type := malloc(#size(ElnaRtlTypeWord));
|
||||
pseudo_type^.kind := ElnaRtlTypeKind.long_word;
|
||||
|
||||
operand_value^ := buffer;
|
||||
operand_length^ := strlen(buffer);
|
||||
operand^.value := buffer;
|
||||
operand^.length := strlen(buffer);
|
||||
|
||||
pseudo_symbol^.rtl_type := pseudo_type;
|
||||
elna_symbol_table_enter(variable_map, buffer, operand_length^, pseudo_symbol);
|
||||
elna_symbol_table_enter(variable_map, buffer, operand^.length, pseudo_symbol);
|
||||
|
||||
return pseudo_symbol
|
||||
end;
|
||||
@@ -5180,6 +5286,8 @@ begin
|
||||
result := elna_lexer_token_create(ElnaLexerKind.left_square, position)
|
||||
elsif character = ']' then
|
||||
result := elna_lexer_token_create(ElnaLexerKind.right_square, position)
|
||||
elsif character = '|' then
|
||||
result := elna_lexer_token_create(ElnaLexerKind.pipe, position)
|
||||
end;
|
||||
return result
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user