Add multiple of the pointer target size
This commit is contained in:
@ -74,15 +74,7 @@ namespace gcc
|
||||
{
|
||||
auto body_type = build_type(expression->body());
|
||||
|
||||
this->current_expression = build1(CONVERT_EXPR, this->symbol_map->lookup("Word"), TYPE_SIZE_UNIT(body_type));
|
||||
}
|
||||
|
||||
bool generic_visitor::is_integral_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
|
||||
return type == this->symbol_map->lookup("Int")
|
||||
|| type == this->symbol_map->lookup("Word");
|
||||
this->current_expression = build1(CONVERT_EXPR, this->symbol_map->lookup("Word"), size_in_bytes(body_type));
|
||||
}
|
||||
|
||||
bool generic_visitor::is_numeric_type(tree type)
|
||||
@ -333,7 +325,9 @@ namespace gcc
|
||||
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
|
||||
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||
if ((is_pointer_type(left_type) || is_pointer_type(right_type))
|
||||
&& (expression->operation() == boot::binary_operator::sum
|
||||
|| expression->operation() == boot::binary_operator::subtraction))
|
||||
{
|
||||
this->current_expression = do_pointer_arithmetic(expression->operation(), left, right);
|
||||
if (this->current_expression == error_mark_node)
|
||||
@ -342,6 +336,10 @@ namespace gcc
|
||||
"invalid operation %s on a pointer and an integral type",
|
||||
boot::print_binary_operator(expression->operation()));
|
||||
}
|
||||
else if (TREE_TYPE(this->current_expression) == ssizetype)
|
||||
{
|
||||
this->current_expression = fold_convert(this->symbol_map->lookup("Int"), this->current_expression);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (left_type != right_type && !are_compatible_pointers(left, right))
|
||||
|
@ -23,6 +23,12 @@ namespace gcc
|
||||
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)
|
||||
@ -87,19 +93,52 @@ namespace gcc
|
||||
|
||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right)
|
||||
{
|
||||
tree result = error_mark_node;
|
||||
tree convert_expression = fold_convert(sizetype, right);
|
||||
|
||||
if (binary_operator == boot::binary_operator::sum)
|
||||
{
|
||||
result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression);
|
||||
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)
|
||||
{
|
||||
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
||||
result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression);
|
||||
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 result;
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
tree build_binary_operation(bool condition, boot::binary_expression *expression,
|
||||
|
Reference in New Issue
Block a user