#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-diagnostic.h" #include "stor-layout.h" #include "fold-const.h" #include "diagnostic-core.h" tree elna_global_trees[ELNA_TI_MAX]; namespace elna { namespace gcc { void init_ttree() { elna_string_type_node = build_pointer_type( build_qualified_type(char_type_node, TYPE_QUAL_CONST)); /* const char* */ } bool is_pointer_type(tree type) { gcc_assert(TYPE_P(type)); return TREE_CODE(type) == POINTER_TYPE; } bool is_integral_type(tree type) { gcc_assert(TYPE_P(type)); return TREE_CODE(type) == INTEGER_TYPE; } bool are_compatible_pointers(tree lhs, tree rhs) { return (lhs == null_pointer_node || rhs == null_pointer_node) && is_pointer_type(TREE_TYPE(lhs)) && is_pointer_type(TREE_TYPE(rhs)); } tree tree_chain_base::head() { return first; } void tree_chain_base::append(tree t) { gcc_assert(t != NULL_TREE); if (this->first == NULL_TREE) { this->first = this->last = t; } else { chain(t); this->last = t; } } void tree_chain::chain(tree t) { TREE_CHAIN(this->last) = t; } tree_symbol_mapping::tree_symbol_mapping(tree bind_expression, tree block) : m_bind_expression(bind_expression), m_block(block) { } tree tree_symbol_mapping::bind_expression() { return m_bind_expression; } tree tree_symbol_mapping::block() { return m_block; } std::shared_ptr> builtin_symbol_table() { std::shared_ptr> initial_table = std::make_shared>(); initial_table->enter("Int", long_integer_type_node); initial_table->enter("Word", size_type_node); initial_table->enter("Bool", boolean_type_node); initial_table->enter("Float", double_type_node); initial_table->enter("Char", unsigned_char_type_node); initial_table->enter("Byte", make_unsigned_type(8)); initial_table->enter("String", elna_string_type_node); return initial_table; } tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right) { if (binary_operator == boot::binary_operator::sum) { tree pointer{ NULL_TREE }; tree offset{ NULL_TREE }; if (is_pointer_type(TREE_TYPE(left)) && is_integral_type(TREE_TYPE(right))) { pointer = left; offset = right; } else if (is_integral_type(TREE_TYPE(left)) && is_pointer_type(TREE_TYPE(right))) { pointer = right; offset = left; } else { return error_mark_node; } tree size_exp = fold_convert(TREE_TYPE(offset), size_in_bytes(TREE_TYPE(TREE_TYPE(pointer)))); offset = fold_build2(MULT_EXPR, TREE_TYPE(offset), offset, size_exp); offset = fold_convert(sizetype, offset); return fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset); } else if (binary_operator == boot::binary_operator::subtraction) { if (is_pointer_type(TREE_TYPE(left)) && is_integral_type(TREE_TYPE(right))) { tree pointer_type = TREE_TYPE(left); tree offset_type = TREE_TYPE(right); tree size_exp = fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type))); tree convert_expression = fold_build2(MULT_EXPR, offset_type, right, size_exp); convert_expression = fold_convert(sizetype, convert_expression); convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression); return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression); } else if (is_pointer_type(TREE_TYPE(left)) && is_pointer_type(TREE_TYPE(right)) && TREE_TYPE(left) == TREE_TYPE(right)) { return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right); } } return error_mark_node; } tree build_binary_operation(bool condition, boot::binary_expression *expression, tree_code operator_code, tree left, tree right, tree target_type) { location_t expression_location = get_location(&expression->position()); tree left_type = TREE_TYPE(left); tree right_type = TREE_TYPE(right); if (condition) { return build2_loc(expression_location, operator_code, target_type, left, right); } else { error_at(expression_location, "invalid operands of type %s and %s for operator %s", print_type(left_type), print_type(right_type), elna::boot::print_binary_operator(expression->operation())); return error_mark_node; } } } }