elna/gcc/elna-tree.cc

166 lines
5.1 KiB
C++

#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<boot::symbol_table<tree>> builtin_symbol_table()
{
std::shared_ptr<boot::symbol_table<tree>> initial_table =
std::make_shared<boot::symbol_table<tree>>();
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;
}
}
}
}