Provide binary and unary TAC operations
This commit is contained in:
		| @@ -155,9 +155,27 @@ type | ||||
| 	ElnaGeneratorKind = ( | ||||
| 		load_immediate, | ||||
| 		load_address, | ||||
| 		add | ||||
| 		add, | ||||
| 		add_immediate, | ||||
| 		load_word, | ||||
| 		store_word, | ||||
| 		call, | ||||
| 		move, | ||||
| 		sub, | ||||
| 		div, | ||||
| 		rem, | ||||
| 		mul, | ||||
| 		_xor, | ||||
| 		_or, | ||||
| 		and, | ||||
| 		seqz, | ||||
| 		snez, | ||||
| 		slt, | ||||
| 		xor_immediate, | ||||
| 		neg, | ||||
| 		not | ||||
| 	); | ||||
| 	ElnaGeneratorOperand = (register, immediate, symbol); | ||||
| 	ElnaGeneratorOperand = (register, immediate, symbol, offset); | ||||
| 	ElnaGeneratorRegister = ( | ||||
| 		zero, | ||||
| 		ra, | ||||
| @@ -615,7 +633,7 @@ begin | ||||
| 	this^ := operand_length | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word); | ||||
| proc _elna_generator_instruction_create(kind: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| 	instruction_size: Word; | ||||
| @@ -623,8 +641,18 @@ begin | ||||
| 	instruction_size := _elna_generator_instruction_size(); | ||||
| 	result := _allocate(instruction_size); | ||||
|  | ||||
| 	_elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_immediate); | ||||
| 	_elna_generator_instruction_set_kind(result, kind); | ||||
| 	_elna_generator_instruction_set_next(result, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.load_immediate); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.immediate, source_immediate, immediate_length); | ||||
|  | ||||
| @@ -634,19 +662,253 @@ end; | ||||
| proc _elna_generator_load_address(target_register: Word, source_symbol: Word, symbol_length: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| 	instruction_size: Word; | ||||
| begin | ||||
| 	instruction_size := _elna_generator_instruction_size(); | ||||
| 	result := _allocate(instruction_size); | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.load_address); | ||||
|  | ||||
| 	_elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_address); | ||||
| 	_elna_generator_instruction_set_next(result, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_add(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.add); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_mul(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.mul); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_sub(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.sub); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_div(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.div); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_rem(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.rem); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_xor(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind._xor); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_xor_immediate(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind._xor); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_or(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind._or); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_and(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.and); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_add_immediate(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.add_immediate); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_slt(destination: Word, lhs: Word, rhs: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.slt); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_call(symbol: Word, length: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.call); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.symbol, symbol, length); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_load_word(target: Word, register: Word, offset: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.load_word); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_store_word(target: Word, register: Word, offset: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.store_word); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_move(destination: Word, source: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.move); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_seqz(destination: Word, source: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.seqz); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_snez(destination: Word, source: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.snez); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_neg(destination: Word, source: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.neg); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_generator_not(destination: Word, source: Word); | ||||
| var | ||||
| 	result: Word; | ||||
| begin | ||||
| 	result := _elna_generator_instruction_create(ElnaGeneratorKind.not); | ||||
|  | ||||
| 	_elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); | ||||
| 	_elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); | ||||
|  | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _elna_writer_instruction_name(instruction_kind: Word); | ||||
| var | ||||
| 	argument_count: Word; | ||||
| @@ -660,6 +922,60 @@ begin | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.add then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tadd", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.add_immediate then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\taddi", 5) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.load_word then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tlw", 3) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.store_word then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tsw", 3) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.call then | ||||
| 		argument_count := 1; | ||||
| 		_write_s("\tcall", 5) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.move then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tmv", 3) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.sub then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tsub", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.mul then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tmul", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.div then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tdiv", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.rem then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\trem", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind._xor then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\txor", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.xor_immediate then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\txori", 5) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind._or then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tor", 3) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.and then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tand", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.seqz then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tseqz", 5) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.snez then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tsnez", 5) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.slt then | ||||
| 		argument_count := 3; | ||||
| 		_write_s("\tslt", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.neg then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tneg", 4) | ||||
| 	elsif instruction_kind = ElnaGeneratorKind.not then | ||||
| 		argument_count := 2; | ||||
| 		_write_s("\tnot", 4) | ||||
| 	end; | ||||
| 	return argument_count | ||||
| end; | ||||
| @@ -686,6 +1002,11 @@ begin | ||||
| 	_write_c(' '); | ||||
| 	if operand_type = ElnaGeneratorOperand.register then | ||||
| 		_elna_writer_register(operand_value) | ||||
| 	elsif operand_type = ElnaGeneratorOperand.offset then | ||||
| 		_write_i(operand_length); | ||||
| 		_write_c('('); | ||||
| 		_elna_writer_register(operand_value); | ||||
| 		_write_c(')') | ||||
| 	elsif operand_length = 0 then | ||||
| 		_write_i(operand_value) | ||||
| 	else | ||||
| @@ -696,13 +1017,22 @@ end; | ||||
| proc _elna_writer_instruction(instruction: Word); | ||||
| var | ||||
| 	instruction_kind: Word; | ||||
| 	argument_count: Word; | ||||
| 	current_argument: Word; | ||||
| begin | ||||
| 	instruction_kind := _elna_generator_instruction_get_kind(instruction); | ||||
| 	_elna_writer_instruction_name(instruction_kind); | ||||
| 	argument_count := _elna_writer_instruction_name(instruction_kind); | ||||
| 	current_argument := 1; | ||||
|  | ||||
| 	_elna_writer_operand(instruction, 1); | ||||
| 	_write_c(','); | ||||
| 	_elna_writer_operand(instruction, 2); | ||||
| 	.elna_writer_instruction_loop; | ||||
| 	if current_argument <= argument_count then | ||||
| 		_elna_writer_operand(instruction, current_argument); | ||||
| 		current_argument := current_argument + 1 | ||||
| 	end; | ||||
| 	if current_argument <= argument_count then | ||||
| 		_write_c(','); | ||||
| 		goto elna_writer_instruction_loop | ||||
| 	end; | ||||
|  | ||||
| 	_write_c('\n') | ||||
| end; | ||||
| @@ -776,13 +1106,11 @@ var | ||||
| 	integer_token: Word; | ||||
| 	integer_length: Word; | ||||
| 	token_kind: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	integer_token := _integer_literal_node_get_value(integer_literal_node); | ||||
| 	integer_length := _integer_literal_node_get_length(integer_literal_node); | ||||
|  | ||||
| 	instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length); | ||||
| 	_elna_writer_instructions(instruction) | ||||
| 	return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length) | ||||
| end; | ||||
|  | ||||
| proc _character_literal_node_size(); | ||||
| @@ -839,13 +1167,11 @@ proc _compile_character_literal(character_literal_node: Word); | ||||
| var | ||||
| 	character: Word; | ||||
| 	character_length: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	character := _character_literal_node_get_value(character_literal_node); | ||||
| 	character_length := _character_literal_node_get_length(character_literal_node); | ||||
|  | ||||
| 	instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length); | ||||
| 	_elna_writer_instructions(instruction) | ||||
| 	return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length) | ||||
| end; | ||||
|  | ||||
| proc _variable_expression_size(); | ||||
| @@ -912,16 +1238,18 @@ var | ||||
| 	name: Word; | ||||
| 	name_token: Word; | ||||
| 	lookup_result: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	name := _variable_expression_get_name(variable_expression); | ||||
| 	name_token := _variable_expression_get_length(variable_expression); | ||||
|  | ||||
| 	lookup_result := _symbol_table_lookup(symbol_table, name, name_token); | ||||
| 	if lookup_result <> 0 then | ||||
| 		_compile_local_designator(lookup_result) | ||||
| 		instruction := _compile_local_designator(lookup_result) | ||||
| 	else | ||||
| 		_compile_global_designator(variable_expression) | ||||
| 	end | ||||
| 		instruction := _compile_global_designator(variable_expression) | ||||
| 	end; | ||||
| 	return instruction | ||||
| end; | ||||
|  | ||||
| proc _string_literal_node_size(); | ||||
| @@ -980,6 +1308,7 @@ var | ||||
| 	offset: Word; | ||||
| 	instruction: Word; | ||||
| 	first_instruction: Word; | ||||
| 	next_instruction: Word; | ||||
| begin | ||||
| 	token_start := _string_literal_node_get_value(string_literal_node); | ||||
| 	length := _string_literal_node_get_length(string_literal_node); | ||||
| @@ -988,10 +1317,10 @@ begin | ||||
| 	first_instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, "strings", 7); | ||||
| 	instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0); | ||||
| 	_elna_generator_instruction_set_next(first_instruction, instruction); | ||||
| 	next_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); | ||||
| 	_elna_generator_instruction_set_next(instruction, next_instruction); | ||||
|  | ||||
| 	_elna_writer_instructions(first_instruction); | ||||
|  | ||||
| 	_write_z("\tadd t0, t0, t1\n\0") | ||||
| 	return first_instruction | ||||
| end; | ||||
|  | ||||
| proc _parse_simple_expression(); | ||||
| @@ -1065,25 +1394,26 @@ begin | ||||
| 	return simple_expression | ||||
| end; | ||||
|  | ||||
| proc _compile_simple_expression(parser_node: Word, symbol_table: Word); | ||||
| proc _compile_simple_expression(parser_node: Word, symbol_table: Word, is_address: Word); | ||||
| var | ||||
| 	is_address: Word; | ||||
| 	node_kind: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	is_address := 0; | ||||
| 	is_address^ := 0; | ||||
| 	node_kind := _node_get_kind(parser_node); | ||||
|  | ||||
| 	if node_kind = NodeKind.character_literal then | ||||
| 		_compile_character_literal(parser_node) | ||||
| 		instruction := _compile_character_literal(parser_node) | ||||
| 	elsif node_kind = NodeKind.string_literal then | ||||
| 		_compile_string_literal(parser_node) | ||||
| 		instruction := _compile_string_literal(parser_node) | ||||
| 	elsif node_kind = NodeKind.integer_literal then | ||||
| 		_compile_integer_literal(parser_node) | ||||
| 		instruction := _compile_integer_literal(parser_node) | ||||
| 	else | ||||
| 		_compile_variable_expression(parser_node, symbol_table); | ||||
| 		is_address := 1 | ||||
| 		instruction := _compile_variable_expression(parser_node, symbol_table); | ||||
| 		is_address^ := 1 | ||||
| 	end; | ||||
| 	return is_address | ||||
| 	_elna_writer_instructions(instruction) | ||||
| end; | ||||
|  | ||||
| proc _unary_expression_size(); | ||||
| @@ -1157,6 +1487,8 @@ var | ||||
| 	expression_kind: Word; | ||||
| 	operator: Word; | ||||
| 	operand: Word; | ||||
| 	is_address: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	operator := 0; | ||||
| 	operand := 0; | ||||
| @@ -1171,14 +1503,20 @@ begin | ||||
| 	end; | ||||
|  | ||||
| 	if operator = '@' then | ||||
| 		_compile_designator(operand, symbol_table) | ||||
| 	elsif _compile_designator(operand, symbol_table) then | ||||
| 		_write_z("\tlw t0, (t0) # Designator is an address.\n\0") | ||||
| 		_compile_designator(operand, symbol_table, @is_address) | ||||
| 	else | ||||
| 		_compile_designator(operand, symbol_table, @is_address); | ||||
| 		if is_address then | ||||
| 			instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0); | ||||
| 			_elna_writer_instruction(instruction) | ||||
| 		end | ||||
| 	end; | ||||
| 	if operator = '-' then | ||||
| 		_write_z("\tneg t0, t0\n\0") | ||||
| 		instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); | ||||
| 		_elna_writer_instruction(instruction) | ||||
| 	elsif operator = '~' then | ||||
| 		_write_z("\tnot t0, t0\n\0") | ||||
| 		instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); | ||||
| 		_elna_writer_instruction(instruction) | ||||
| 	end | ||||
| end; | ||||
|  | ||||
| @@ -1296,6 +1634,8 @@ var | ||||
| 	token_kind: Word; | ||||
| 	expression_kind: Word; | ||||
| 	operand_node: Word; | ||||
| 	first_instruction: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	expression_kind := _node_get_kind(parser_node); | ||||
|  | ||||
| @@ -1307,42 +1647,53 @@ begin | ||||
| 		operand_node := _binary_expression_get_lhs(parser_node); | ||||
| 		_compile_unary_expression(operand_node, symbol_table); | ||||
| 		(* Save the value of the left expression on the stack. *) | ||||
| 		_write_z("\tsw t0, 64(sp)\n\0"); | ||||
| 		instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 64); | ||||
| 		_elna_writer_instruction(instruction); | ||||
|  | ||||
| 		operand_node := _binary_expression_get_rhs(parser_node); | ||||
| 		_compile_unary_expression(operand_node, symbol_table); | ||||
| 		(* Load the left expression from the stack; *) | ||||
| 		_write_z("\tlw t1, 64(sp)\n\0"); | ||||
| 		instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 64); | ||||
| 		_elna_writer_instruction(instruction); | ||||
|  | ||||
| 		if token_kind = LexerTokenKind.plus then | ||||
| 			_write_z("\tadd t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind.minus then | ||||
| 			_write_z("\tsub t0, t1, t0\n\0"); | ||||
| 			first_instruction := _elna_generator_sub(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) | ||||
| 		elsif token_kind = LexerTokenKind.multiplication then | ||||
| 			_write_z("\tmul t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_mul(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind.and then | ||||
| 			_write_z("\tand t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_and(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind._or then | ||||
| 			_write_z("\tor t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_or(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind._xor then | ||||
| 			_write_z("\txor t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind.equals then | ||||
| 			_write_z("\txor t0, t0, t1\n\tseqz t0, t0\n\0") | ||||
| 			first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); | ||||
| 			instruction := _elna_generator_seqz(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); | ||||
| 			_elna_generator_instruction_set_next(first_instruction, instruction) | ||||
| 		elsif token_kind = LexerTokenKind.remainder then | ||||
| 			_write_z("\trem t0, t1, t0\n\0") | ||||
| 			first_instruction := _elna_generator_rem(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) | ||||
| 		elsif token_kind = LexerTokenKind.division then | ||||
| 			_write_z("\tdiv t0, t1, t0\n\0") | ||||
| 			first_instruction := _elna_generator_div(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) | ||||
| 		elsif token_kind = LexerTokenKind.less_than then | ||||
| 			_write_z("\tslt t0, t1, t0\n\0") | ||||
| 			first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) | ||||
| 		elsif token_kind = LexerTokenKind.greater_than then | ||||
| 			_write_z("\tslt t0, t0, t1\n\0") | ||||
| 			first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) | ||||
| 		elsif token_kind = LexerTokenKind.less_equal then | ||||
| 			_write_z("\tslt t0, t0, t1\n\txori t0, t0, 1\n\0") | ||||
| 			first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); | ||||
| 			instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1); | ||||
| 			_elna_generator_instruction_set_next(first_instruction, instruction) | ||||
| 		elsif token_kind = LexerTokenKind.not_equal then | ||||
| 			_write_z("\txor t0, t0, t1\n\tsnez t0, t0\n\0") | ||||
| 			first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); | ||||
| 			instruction := _elna_generator_snez(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); | ||||
| 			_elna_generator_instruction_set_next(first_instruction, instruction) | ||||
| 		elsif token_kind = LexerTokenKind.greater_equal then | ||||
| 			_write_z("\tslt t0, t1, t0\n\txori t0, t0, 1\n\0") | ||||
| 		end | ||||
| 			first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0); | ||||
| 			instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1); | ||||
| 			_elna_generator_instruction_set_next(first_instruction, instruction) | ||||
| 		end; | ||||
| 		_elna_writer_instructions(first_instruction) | ||||
| 	end | ||||
| end; | ||||
|  | ||||
| @@ -1429,11 +1780,15 @@ var | ||||
| 	argument_count: Word; | ||||
| 	stack_offset: Word; | ||||
| 	parsed_expression: Word; | ||||
| 	instruction: Word; | ||||
| 	first_instruction: Word; | ||||
| 	current_instruction: Word; | ||||
| begin | ||||
| 	parsed_expression := _call_get_name(parsed_call); | ||||
| 	name := _variable_expression_get_name(parsed_expression); | ||||
| 	name_length := _variable_expression_get_length(parsed_expression); | ||||
| 	argument_count := 0; | ||||
| 	first_instruction := 0; | ||||
|  | ||||
| 	.compile_call_loop; | ||||
|  | ||||
| @@ -1444,11 +1799,11 @@ begin | ||||
| 		_compile_binary_expression(parsed_expression, symbol_table); | ||||
|  | ||||
| 		(* Save the argument on the stack. *) | ||||
| 		_write_z("\tsw t0, \0"); | ||||
|  | ||||
| 		stack_offset := argument_count * 4; | ||||
| 		_write_i(116 - stack_offset); | ||||
| 		_write_z("(sp)\n\0"); | ||||
|  | ||||
| 		instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, | ||||
| 			ElnaGeneratorRegister.sp, 116 - stack_offset); | ||||
| 		_elna_writer_instruction(instruction); | ||||
|  | ||||
| 		argument_count := argument_count + 1; | ||||
| 		goto compile_call_loop | ||||
| @@ -1460,24 +1815,27 @@ begin | ||||
| 	if argument_count <> 0 then | ||||
| 		(* Decrement the argument counter. *) | ||||
| 		argument_count := argument_count - 1; | ||||
|  | ||||
| 		_write_z("\tlw a\0"); | ||||
| 		_write_i(argument_count); | ||||
|  | ||||
| 		_write_z(", \0"); | ||||
| 		stack_offset := argument_count * 4; | ||||
|  | ||||
| 		(* Calculate the stack offset: 116 - (4 * argument_counter) *) | ||||
| 		stack_offset := argument_count * 4; | ||||
| 		_write_i(116 - stack_offset); | ||||
|  | ||||
| 		_write_z("(sp)\n\0"); | ||||
| 		instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count, | ||||
| 			ElnaGeneratorRegister.sp, 116 - stack_offset); | ||||
| 		if first_instruction = 0 then | ||||
| 			first_instruction := instruction | ||||
| 		else | ||||
| 			_elna_generator_instruction_set_next(current_instruction, instruction) | ||||
| 		end; | ||||
| 		current_instruction := instruction; | ||||
|  | ||||
| 		goto compile_call_finalize | ||||
| 	end; | ||||
|  | ||||
| 	_write_z("\tcall \0"); | ||||
| 	_write_s(name, name_length); | ||||
| 	_write_c('\n') | ||||
| 	instruction := _elna_generator_call(name, name_length); | ||||
| 	if first_instruction = 0 then | ||||
| 		first_instruction := instruction | ||||
| 	else | ||||
| 		_elna_generator_instruction_set_next(current_instruction, instruction) | ||||
| 	end; | ||||
| 	_elna_writer_instructions(first_instruction) | ||||
| end; | ||||
|  | ||||
| (** | ||||
| @@ -1633,25 +1991,24 @@ end; | ||||
| proc _compile_local_designator(symbol: Word); | ||||
| var | ||||
| 	variable_offset: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	_write_z("\taddi t0, sp, \0"); | ||||
| 	variable_offset := _parameter_info_get_offset(symbol); | ||||
| 	_write_i(variable_offset); | ||||
| 	_write_c('\n') | ||||
| 	instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, variable_offset); | ||||
| 	return instruction | ||||
| end; | ||||
|  | ||||
| proc _compile_global_designator(variable_expression: Word); | ||||
| var | ||||
| 	name: Word; | ||||
| 	token_length: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	_write_z("\tla t0, \0"); | ||||
|  | ||||
| 	name := _variable_expression_get_name(variable_expression); | ||||
| 	token_length := _variable_expression_get_length(variable_expression); | ||||
| 	instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, name, token_length); | ||||
|  | ||||
| 	_write_s(name, token_length); | ||||
| 	_write_c('\n') | ||||
| 	return instruction | ||||
| end; | ||||
|  | ||||
| proc _field_access_expression_size(); | ||||
| @@ -1706,6 +2063,7 @@ var | ||||
| 	member_length: Word; | ||||
| 	counter: Word; | ||||
| 	symbol: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	symbol := _field_access_expression_get_aggregate(field_access_expression); | ||||
| 	value_name := _variable_expression_get_name(symbol); | ||||
| @@ -1736,9 +2094,8 @@ begin | ||||
| 			counter := counter + 1; | ||||
| 			goto compile_enumeration_value_members | ||||
| 		end; | ||||
| 		_write_z("\tli t0, \0"); | ||||
| 		_write_i(counter); | ||||
| 		_write_c('\n') | ||||
| 		instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0); | ||||
| 		_elna_writer_instructions(instruction) | ||||
| 	end | ||||
| end; | ||||
|  | ||||
| @@ -1769,31 +2126,32 @@ begin | ||||
| 	return result | ||||
| end; | ||||
|  | ||||
| proc _compile_designator(parser_node: Word, symbol_table: Word); | ||||
| proc _compile_designator(parser_node: Word, symbol_table: Word, is_address: Word); | ||||
| var | ||||
| 	name_token: Word; | ||||
| 	lookup_result: Word; | ||||
| 	token_kind: Word; | ||||
| 	parser_node: Word; | ||||
| 	is_address: Word; | ||||
| 	node_kind: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	is_address := 1; | ||||
| 	node_kind := _node_get_kind(parser_node); | ||||
|  | ||||
| 	if node_kind = NodeKind.dereference_expression then | ||||
| 		parser_node := _dereference_expression_get_pointer(parser_node); | ||||
| 		_compile_simple_expression(parser_node, symbol_table); | ||||
| 		_write_z("\tlw t0, (t0)\n\0") | ||||
| 		_compile_simple_expression(parser_node, symbol_table, is_address); | ||||
| 		instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0); | ||||
| 		_elna_writer_instructions(instruction) | ||||
| 	elsif node_kind = NodeKind.field_access_expression then | ||||
| 		_compile_enumeration_value(parser_node); | ||||
| 		is_address := 0 | ||||
| 		is_address^ := 0 | ||||
| 	elsif node_kind = NodeKind.call then | ||||
| 		_compile_call(parser_node, symbol_table); | ||||
| 		_write_z("\tmv t0, a0\n\0"); | ||||
| 		is_address := 0 | ||||
| 		instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0); | ||||
| 		_elna_writer_instructions(instruction); | ||||
| 		is_address^ := 0 | ||||
| 	else | ||||
| 		is_address := _compile_simple_expression(parser_node, symbol_table) | ||||
| 		_compile_simple_expression(parser_node, symbol_table, is_address) | ||||
| 	end; | ||||
| 	return is_address | ||||
| end; | ||||
| @@ -1853,18 +2211,25 @@ end; | ||||
| proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word); | ||||
| var | ||||
| 	current_expression: Word; | ||||
| 	is_address: Word; | ||||
| 	first_instruction: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	current_expression := _assignment_statement_get_assignee(parser_tree); | ||||
| 	_compile_designator(current_expression, symbol_table); | ||||
| 	_compile_designator(current_expression, symbol_table, @is_address); | ||||
|  | ||||
| 	(* Save the assignee address on the stack. *) | ||||
| 	_write_z("\tsw t0, 60(sp)\n\0"); | ||||
| 	instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60); | ||||
| 	_elna_writer_instructions(instruction); | ||||
|  | ||||
| 	(* Compile the assignment. *) | ||||
| 	current_expression := _assignment_statement_get_assignment(parser_tree); | ||||
| 	_compile_binary_expression(current_expression, symbol_table); | ||||
|  | ||||
| 	_write_z("\tlw t1, 60(sp)\n\tsw t0, (t1)\n\0") | ||||
| 	first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 60); | ||||
| 	instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, 0); | ||||
| 	_elna_generator_instruction_set_next(first_instruction, instruction); | ||||
| 	_elna_writer_instructions(first_instruction) | ||||
| end; | ||||
|  | ||||
| proc _return_statement_size(); | ||||
| @@ -1910,10 +2275,12 @@ end; | ||||
| proc _compile_return_statement(parser_node: Word, symbol_table: Word); | ||||
| var | ||||
| 	return_expression: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	return_expression := _return_statement_get_returned(parser_node); | ||||
| 	_compile_binary_expression(return_expression, symbol_table); | ||||
| 	_write_z("\tmv a0, t0\n\0") | ||||
| 	instruction := _elna_generator_move(ElnaGeneratorRegister.a0, ElnaGeneratorRegister.t0); | ||||
| 	_elna_writer_instructions(instruction) | ||||
| end; | ||||
|  | ||||
| (** | ||||
| @@ -1959,6 +2326,7 @@ proc _compile_conditional_statements(parser_node: Word, after_end_label: Word, s | ||||
| var | ||||
| 	condition_label: Word; | ||||
| 	current_node: Word; | ||||
| 	instruction: Word; | ||||
| begin | ||||
| 	(* Compile condition. *) | ||||
| 	current_node := _conditional_statements_get_condition(parser_node); | ||||
| @@ -2821,6 +3189,9 @@ var | ||||
| 	current_parameter: Word; | ||||
| 	new_symbol_table: Word; | ||||
| 	symbol_info: Word; | ||||
| 	instruction: Word; | ||||
| 	first_instruction: Word; | ||||
| 	current_instruction: Word; | ||||
| begin | ||||
| 	name_pointer := _declaration_get_name(parser_node); | ||||
| 	name_length := _declaration_get_length(parser_node); | ||||
| @@ -2843,6 +3214,7 @@ begin | ||||
|  | ||||
| 	current_parameter := _procedure_declaration_get_parameters(parser_node); | ||||
| 	parameter_counter := 0; | ||||
| 	first_instruction := 0; | ||||
| 	.compile_procedure_declaration_parameters; | ||||
| 	if current_parameter <> 0 then | ||||
| 		name_pointer := _declaration_get_name(current_parameter); | ||||
| @@ -2851,12 +3223,14 @@ begin | ||||
|  | ||||
| 		symbol_info := _parameter_info_get_offset(symbol_info); | ||||
|  | ||||
| 		_write_z("\tsw a\0"); | ||||
| 		_write_i(parameter_counter); | ||||
| 		_write_z(", \0"); | ||||
| 		_write_i(symbol_info); | ||||
|  | ||||
| 		_write_z("(sp)\n\0"); | ||||
| 		instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter, | ||||
| 			ElnaGeneratorRegister.sp, symbol_info); | ||||
| 		if first_instruction = 0 then | ||||
| 			first_instruction := instruction | ||||
| 		else | ||||
| 			_elna_generator_instruction_set_next(current_instruction, instruction) | ||||
| 		end; | ||||
| 		current_instruction := instruction; | ||||
|  | ||||
| 		(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *) | ||||
| 		parameter_counter := parameter_counter + 1; | ||||
| @@ -2864,6 +3238,7 @@ begin | ||||
| 		current_parameter := _declaration_get_next(current_parameter); | ||||
| 		goto compile_procedure_declaration_parameters | ||||
| 	end; | ||||
| 	_elna_writer_instructions(first_instruction); | ||||
| 	current_parameter := _procedure_declaration_get_body(parser_node); | ||||
| 	_compile_statements(current_parameter, new_symbol_table); | ||||
|  | ||||
| @@ -4255,7 +4630,7 @@ end; | ||||
| proc _initialize_global_state(); | ||||
| begin | ||||
| 	compiler_strings_position := @compiler_strings; | ||||
| 	memory_free_pointer := _mmap(495616); | ||||
| 	memory_free_pointer := _mmap(1048576); | ||||
| 	source_code := _mmap(495616); | ||||
| 	symbol_table_store := _mmap(495616) | ||||
| end; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user