Implement 2 word argument support
This commit is contained in:
@@ -37,18 +37,36 @@ end
|
||||
desc 'Convert previous stage language into the current stage language'
|
||||
task :convert do
|
||||
File.open('boot/stage23/cl.elna', 'w') do |current_stage|
|
||||
seen_var = false
|
||||
seen_proc = false
|
||||
|
||||
File.readlines('boot/stage22/cl.elna').each do |line|
|
||||
if line.start_with? 'var'
|
||||
seen_var = true
|
||||
current_stage << "var\n"
|
||||
elsif line.start_with? 'begin'
|
||||
seen_var = false
|
||||
current_stage << "begin\n"
|
||||
elsif seen_var && line.end_with?(";\n")
|
||||
current_stage << line[0..-3]
|
||||
current_stage << "\n"
|
||||
if line.start_with? 'proc'
|
||||
seen_proc = true
|
||||
current_stage << line
|
||||
elsif seen_proc && line.start_with?('begin')
|
||||
seen_proc = false
|
||||
current_stage << line
|
||||
elsif !seen_proc && line.start_with?('begin')
|
||||
current_stage << <<~CODE
|
||||
proc g(location: ElnaLocation)
|
||||
begin
|
||||
\tprintf("# %i %i\\n\\0", location.line, location.column)
|
||||
end
|
||||
|
||||
proc f()
|
||||
var
|
||||
\tlocation: ElnaLocation
|
||||
begin
|
||||
\tlocation.line := 2;
|
||||
\tlocation.column := 3;
|
||||
\tg(location)
|
||||
end
|
||||
|
||||
CODE
|
||||
current_stage << line
|
||||
current_stage << <<~CODE
|
||||
\tf();
|
||||
CODE
|
||||
else
|
||||
current_stage << line
|
||||
end
|
||||
|
||||
+147
-36
@@ -7,6 +7,8 @@ program;
|
||||
|
||||
(* Stage 22 compiler. *)
|
||||
|
||||
(* - Support 2 word procedure arguments. *)
|
||||
|
||||
type
|
||||
ElnaListNode = record
|
||||
next: Word
|
||||
@@ -55,7 +57,7 @@ type
|
||||
kind: ElnaTypeKind;
|
||||
size: Word;
|
||||
alignment: Word;
|
||||
members: Word;
|
||||
members: ^ElnaTypeField;
|
||||
length: Word
|
||||
end
|
||||
ElnaTypePointer = record
|
||||
@@ -689,6 +691,7 @@ var
|
||||
word_type: ^ElnaType
|
||||
char_type: ^ElnaType
|
||||
bool_type: ^ElnaType
|
||||
string_type: ^ElnaTypeRecord
|
||||
|
||||
source_code: Word
|
||||
compiler_strings_position: ^Char
|
||||
@@ -879,21 +882,57 @@ end
|
||||
* Loads or moves the value from a TAC operand into the given register.
|
||||
*)
|
||||
proc elna_rtl_hardware_value(instructions: ^ElnaList, operand: ^ElnaTacOperand,
|
||||
into: ElnaRtlRegister, variable_map: ^ElnaSymbolTable)
|
||||
into: ElnaRtlRegister, variable_map: ^ElnaSymbolTable) -> Word
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction
|
||||
pseudo_symbol: ^ElnaRtlObjectInfo
|
||||
target_operand: ElnaRtlOperand
|
||||
long_word_type: ^ElnaRtlType
|
||||
registers_used: Word
|
||||
begin
|
||||
registers_used := 1;
|
||||
|
||||
if operand^.kind = ElnaTacKind.constant then
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, operand^.value, 0, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
elsif operand^.kind = ElnaTacKind.variable then
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand^.value, operand^.length, 0);
|
||||
elna_list_append(instructions, instruction)
|
||||
end
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map, operand^.value, operand^.length);
|
||||
long_word_type := elna_rtl_constant_type(4);
|
||||
|
||||
if pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then
|
||||
target_operand.kind := ElnaRtlKind.register;
|
||||
target_operand.value := ElnaRtlRegister.t0;
|
||||
target_operand.length := 0;
|
||||
target_operand.offset := 0;
|
||||
|
||||
instruction := elna_rtl_variable_address(variable_map, pseudo_symbol, operand, @target_operand);
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, target_operand.value, target_operand.length, 0);
|
||||
instruction^.types[1] := long_word_type;
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into + 1, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, target_operand.value, target_operand.length, 4);
|
||||
instruction^.types[1] := long_word_type;
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
registers_used := 2
|
||||
else
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand^.value, operand^.length, 0);
|
||||
instruction^.types[1] := long_word_type;
|
||||
|
||||
elna_list_append(instructions, instruction)
|
||||
end
|
||||
end;
|
||||
return registers_used
|
||||
end
|
||||
|
||||
proc elna_rtl_operand_value(instructions: ^ElnaList, tac_operand: ^ElnaTacOperand, variable_map: ^ElnaSymbolTable,
|
||||
@@ -1038,13 +1077,11 @@ begin
|
||||
elna_list_append(instructions, xor_instruction)
|
||||
end
|
||||
|
||||
proc elna_rtl_operand_address(variable_map: ^ElnaSymbolTable,
|
||||
proc elna_rtl_variable_address(variable_map: ^ElnaSymbolTable, pseudo_symbol: ^ElnaRtlObjectInfo,
|
||||
addressable: ^ElnaTacOperand, target_operand: ^ElnaRtlOperand) -> ^ElnaRtlInstruction
|
||||
var
|
||||
pseudo_symbol: ^ElnaRtlObjectInfo
|
||||
instruction: ^ElnaRtlInstruction
|
||||
begin
|
||||
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, target_operand^.kind,
|
||||
@@ -1067,6 +1104,17 @@ begin
|
||||
return instruction
|
||||
end
|
||||
|
||||
proc elna_rtl_operand_address(variable_map: ^ElnaSymbolTable,
|
||||
addressable: ^ElnaTacOperand, target_operand: ^ElnaRtlOperand) -> ^ElnaRtlInstruction
|
||||
var
|
||||
pseudo_symbol: ^ElnaRtlObjectInfo
|
||||
instruction: ^ElnaRtlInstruction
|
||||
begin
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map, addressable^.value, addressable^.length);
|
||||
|
||||
return elna_rtl_variable_address(variable_map, pseudo_symbol, addressable, target_operand)
|
||||
end
|
||||
|
||||
proc elna_rtl_get_address(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable)
|
||||
var
|
||||
instruction: ^ElnaRtlInstruction
|
||||
@@ -1116,6 +1164,7 @@ var
|
||||
current_argument: ^ElnaTacOperand
|
||||
instruction: ^ElnaRtlInstruction
|
||||
current_register: Word
|
||||
registers_used: Word
|
||||
begin
|
||||
current_register := 0;
|
||||
current_argument := tac_instruction^.operands[2].value;
|
||||
@@ -1126,9 +1175,9 @@ begin
|
||||
if argument_count > 0 then
|
||||
argument_count := argument_count - 1;
|
||||
|
||||
elna_rtl_hardware_value(instructions, current_argument, ElnaRtlRegister.a0 + current_register, variable_map);
|
||||
registers_used := elna_rtl_hardware_value(instructions, current_argument, ElnaRtlRegister.a0 + current_register, variable_map);
|
||||
current_argument := current_argument + 1;
|
||||
current_register := current_register + 1;
|
||||
current_register := current_register + registers_used;
|
||||
|
||||
goto elna_rtl_call_loop
|
||||
end;
|
||||
@@ -1328,7 +1377,7 @@ end
|
||||
|
||||
proc elna_rtl_memcpy(instructions: ^ElnaList, byte_array: ^ElnaRtlTypeByteArray)
|
||||
var
|
||||
instruction: ElnaRtlInstruction
|
||||
instruction: ^ElnaRtlInstruction
|
||||
begin
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a2, 0, 0);
|
||||
@@ -1685,8 +1734,7 @@ begin
|
||||
variable_map);
|
||||
instruction^.operator := ElnaRtlOperator.lw;
|
||||
(* Because it is an address. *)
|
||||
instruction^.types[1] := malloc(#size(ElnaRtlTypeWord));
|
||||
instruction^.types[1]^.kind := ElnaRtlTypeKind.long_word;
|
||||
instruction^.types[1] := elna_rtl_constant_type(4);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory,
|
||||
@@ -1715,8 +1763,7 @@ begin
|
||||
|
||||
instruction^.operator := ElnaRtlOperator.lw;
|
||||
(* Because it is an address. *)
|
||||
instruction^.types[1] := malloc(#size(ElnaRtlTypeWord));
|
||||
instruction^.types[1]^.kind := ElnaRtlTypeKind.long_word;
|
||||
instruction^.types[1] := elna_rtl_constant_type(4);
|
||||
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory,
|
||||
@@ -1980,7 +2027,7 @@ begin
|
||||
instruction^.operands[1].kind, instruction^.operands[1].value,
|
||||
instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
|
||||
else
|
||||
printf("\n# copy %i (%i %.*s) (%i %.*s)\n\0", instruction^.operands[3].kind,
|
||||
printf("\n# copy (%i %.*s) (%i %.*s)\n\0",
|
||||
instruction^.operands[1].kind, instruction^.operands[1].length, instruction^.operands[1].value,
|
||||
instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
|
||||
end;
|
||||
@@ -2075,7 +2122,7 @@ begin
|
||||
(* Write procedure label, _procedure_name: *)
|
||||
printf("%.*s:\n\0", procedure^.length, procedure^.name);
|
||||
|
||||
elna_riscv_instructions(procedure^.body);
|
||||
elna_riscv_instructions(procedure^.body.first);
|
||||
printf("\tret\n\0");
|
||||
fflush(nil);
|
||||
|
||||
@@ -3127,7 +3174,7 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable,
|
||||
proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ^ElnaSymbolTable,
|
||||
operand_result: ^ElnaTacOperandResult, operand: ^ElnaTacOperand)
|
||||
var
|
||||
field_access_expression: ^ElnaTreeFieldAccessExpression
|
||||
@@ -3502,7 +3549,7 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
proc elna_tac_if_statement(instructions: ElnaList, parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable)
|
||||
proc elna_tac_if_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable)
|
||||
var
|
||||
current_node: ^ElnaTreeConditionalStatements
|
||||
after_end_label: Word
|
||||
@@ -3529,7 +3576,7 @@ begin
|
||||
elna_tac_label(instructions, after_end_label, 0)
|
||||
end
|
||||
|
||||
proc elna_tac_statement(instructions: ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable)
|
||||
proc elna_tac_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable)
|
||||
var
|
||||
operand: ElnaTacOperand
|
||||
begin
|
||||
@@ -4070,28 +4117,63 @@ begin
|
||||
return result
|
||||
end
|
||||
|
||||
proc elna_rtl_parameters(instructions: ^ElnaList, parameters: Word, count: Word) -> ^ElnaRtlInstruction
|
||||
proc elna_rtl_parameters(instructions: ^ElnaList, parameters: Word, count: Word,
|
||||
variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction
|
||||
var
|
||||
result: ^ElnaRtlInstruction
|
||||
instruction: ^ElnaRtlInstruction
|
||||
parameter_index: Word
|
||||
parameter_name: Word
|
||||
name_length: Word
|
||||
pseudo_symbol: ^ElnaRtlObjectInfo
|
||||
current_register: Word
|
||||
target_operand: ElnaRtlOperand
|
||||
source_operand: ElnaTacOperand
|
||||
long_word_type: ^ElnaRtlType
|
||||
begin
|
||||
result := nil;
|
||||
parameter_index := 0;
|
||||
current_register := ElnaRtlRegister.a0;
|
||||
|
||||
.elna_rtl_parameters_loop;
|
||||
if parameter_index < count then
|
||||
parameter_name := parameters^;
|
||||
source_operand.kind := ElnaTacKind.variable;
|
||||
source_operand.value := parameters^;
|
||||
parameters := parameters + 4;
|
||||
name_length := parameters^;
|
||||
source_operand.length := parameters^;
|
||||
parameters := parameters + 4;
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, parameter_name, name_length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0, 0);
|
||||
elna_list_append(instructions, instruction);
|
||||
pseudo_symbol := elna_symbol_table_lookup(variable_map, source_operand.value, source_operand.length);
|
||||
long_word_type := elna_rtl_constant_type(4);
|
||||
|
||||
if pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then
|
||||
target_operand.kind := ElnaRtlKind.register;
|
||||
target_operand.value := ElnaRtlRegister.t0;
|
||||
target_operand.length := 0;
|
||||
target_operand.offset := 0;
|
||||
instruction := elna_rtl_variable_address(variable_map, pseudo_symbol, @source_operand, @target_operand);
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, current_register, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, target_operand.value, target_operand.length, 0);
|
||||
instruction^.types[1] := long_word_type;
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, current_register + 1, 0, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, target_operand.value, target_operand.length, 4);
|
||||
instruction^.types[1] := long_word_type;
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
current_register := current_register + 2
|
||||
else
|
||||
instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv);
|
||||
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, source_operand.value, source_operand.length, 0);
|
||||
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, current_register, 0, 0);
|
||||
instruction^.types[1] := long_word_type;
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
current_register := current_register + 1
|
||||
end;
|
||||
|
||||
parameter_index := parameter_index + 1;
|
||||
goto elna_rtl_parameters_loop
|
||||
@@ -4185,8 +4267,6 @@ begin
|
||||
result^.length := tac_declaration^.length;
|
||||
|
||||
pseudo_counter := 0;
|
||||
elna_rtl_parameters(@result^.body, tac_declaration^.parameters, tac_declaration^.count);
|
||||
|
||||
result^.variable_map := elna_symbol_table_create(variable_map_global);
|
||||
count := tac_declaration^.symbol_table^.count;
|
||||
current_entry := tac_declaration^.symbol_table^.symbols;
|
||||
@@ -4213,6 +4293,7 @@ begin
|
||||
|
||||
.elna_rtl_procedure_declaration_end;
|
||||
|
||||
elna_rtl_parameters(@result^.body, tac_declaration^.parameters, tac_declaration^.count, result^.variable_map);
|
||||
elna_rtl_instructions(@result^.body, tac_declaration^.body.first, result^.variable_map);
|
||||
|
||||
return result
|
||||
@@ -5269,16 +5350,42 @@ begin
|
||||
symbol_table^.count := symbol_table^.count + 1
|
||||
end
|
||||
|
||||
proc elna_symbol_string_build()
|
||||
var
|
||||
current_field: ^ElnaTypeField
|
||||
char_pointer: ^ElnaTypePointer
|
||||
begin
|
||||
string_type := malloc(#size(ElnaTypeRecord));
|
||||
string_type^.kind := ElnaTypeKind._record;
|
||||
string_type^.size := 8;
|
||||
string_type^.alignment := 4;
|
||||
string_type^.members := malloc(2 * #size(ElnaTypeField));
|
||||
|
||||
char_pointer := malloc(#size(ElnaTypePointer));
|
||||
char_pointer^.kind := ElnaTypeKind.pointer;
|
||||
char_pointer^.size := 4;
|
||||
char_pointer^.alignment := 4;
|
||||
char_pointer^.base := char_type;
|
||||
|
||||
current_field := string_type^.members;
|
||||
current_field^.name := "ptr";
|
||||
current_field^.length := 3;
|
||||
current_field^.field_type := char_pointer;
|
||||
|
||||
current_field := current_field + 1;
|
||||
current_field^.name := "length";
|
||||
current_field^.length := 6;
|
||||
current_field^.field_type := word_type;
|
||||
end
|
||||
|
||||
(* Build global symbol table with predefined symbols. *)
|
||||
proc elna_symbol_table_build()
|
||||
var
|
||||
current_info: ^ElnaSymbolTypeInfo
|
||||
current_type: ^ElnaType
|
||||
global_pointer: ^Word
|
||||
begin
|
||||
symbol_table_global := elna_symbol_table_create(nil);
|
||||
|
||||
(* Enter built-in symbols. *)
|
||||
word_type := malloc(#size(ElnaType));
|
||||
word_type^.kind := ElnaTypeKind.primitive;
|
||||
word_type^.size := 4;
|
||||
@@ -5305,7 +5412,11 @@ begin
|
||||
char_type^.size := 1;
|
||||
char_type^.alignment := 1;
|
||||
current_info := type_info_create(char_type);
|
||||
elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info)
|
||||
elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info);
|
||||
|
||||
elna_symbol_string_build();
|
||||
current_info := type_info_create(string_type);
|
||||
elna_symbol_table_enter(symbol_table_global, "String", 6, current_info)
|
||||
end
|
||||
|
||||
proc elna_lexer_classifications1()
|
||||
|
||||
Reference in New Issue
Block a user