Index strings

This commit is contained in:
2025-02-12 20:47:47 +01:00
parent f991686330
commit 62d9398772
10 changed files with 166 additions and 76 deletions

View File

@ -46,36 +46,44 @@ namespace gcc
void generic_visitor::visit(boot::call_expression *expression)
{
tree symbol = this->lookup(expression->name());
location_t call_location = get_location(&expression->position());
if (symbol == NULL_TREE)
{
error_at(get_location(&expression->position()),
"procedure '%s' not declared",
error_at(call_location, "procedure '%s' not declared",
expression->name().c_str());
this->current_expression = error_mark_node;
return;
}
tree return_type = TREE_TYPE(TREE_TYPE(symbol));
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol));
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol);
std::vector<tree> arguments(expression->arguments().size());
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
{
expression->arguments().at(i)->accept(this);
arguments[i] = this->current_expression;
}
tree stmt = build_call_array_loc(get_location(&expression->position()),
return_type, printf_fn, arguments.size(), arguments.data());
tree return_type = TREE_TYPE(TREE_TYPE(symbol));
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol));
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol);
if (return_type == void_type_node)
{
append_statement(stmt);
this->current_expression = NULL_TREE;
std::vector<tree> arguments(expression->arguments().size());
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
{
expression->arguments().at(i)->accept(this);
arguments[i] = this->current_expression;
}
tree stmt = build_call_array_loc(get_location(&expression->position()),
return_type, printf_fn, arguments.size(), arguments.data());
if (return_type == void_type_node)
{
append_statement(stmt);
this->current_expression = NULL_TREE;
}
else
{
this->current_expression = stmt;
}
}
else
{
this->current_expression = stmt;
error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
print_type(TYPE_P(symbol) ? symbol : TREE_TYPE(symbol)).c_str());
this->current_expression = error_mark_node;
}
}
@ -347,14 +355,14 @@ namespace gcc
TREE_READONLY(string_literal) = 1;
TREE_STATIC(string_literal) = 1;
string_type = TREE_TYPE(TREE_CHAIN(TYPE_FIELDS(elna_string_type_node)));
string_type = TREE_TYPE(elna_string_ptr_field_node);
string_literal = build4(ARRAY_REF, elna_char_type_node,
string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
string_literal = build1(ADDR_EXPR, string_type, string_literal);
vec<constructor_elt, va_gc> *elms = NULL;
CONSTRUCTOR_APPEND_ELT(elms, TYPE_FIELDS(elna_string_type_node), index_constant);
CONSTRUCTOR_APPEND_ELT(elms, TREE_CHAIN(TYPE_FIELDS(elna_string_type_node)), string_literal);
CONSTRUCTOR_APPEND_ELT(elms, elna_string_ptr_field_node, string_literal);
CONSTRUCTOR_APPEND_ELT(elms, elna_string_length_field_node, index_constant);
this->current_expression = build_constructor(elna_string_type_node, elms);
}
@ -401,14 +409,15 @@ namespace gcc
}
if (TREE_TYPE(left) == elna_string_type_node)
{
tree length_field = TYPE_FIELDS(elna_string_type_node);
tree ptr_field = TREE_CHAIN(length_field);
tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(elna_string_length_field_node),
left, elna_string_length_field_node, NULL_TREE);
tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
left, elna_string_ptr_field_node, NULL_TREE);
tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), left, length_field, NULL_TREE);
tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), left, ptr_field, NULL_TREE);
tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), right, length_field, NULL_TREE);
tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), right, ptr_field, NULL_TREE);
tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(elna_string_length_field_node),
right, elna_string_length_field_node, NULL_TREE);
tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
right, elna_string_ptr_field_node, NULL_TREE);
tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
tree *memcmp = elna_global_decls->get("__builtin_memcmp");
@ -732,14 +741,46 @@ namespace gcc
{
expression->base().accept(this);
tree designator = this->current_expression;
location_t location = get_location(&expression->position());
expression->index().accept(this);
tree index = this->current_expression;
if (!is_integral_type(TREE_TYPE(this->current_expression)))
{
error_at(location, "type '%s' cannot be used as index",
print_type(TREE_TYPE(this->current_expression)).c_str());
this->current_expression = error_mark_node;
return;
}
if (this->current_expression != elna_word_type_node)
{
this->current_expression = fold_convert(elna_word_type_node, this->current_expression);
}
tree offset = build2(MINUS_EXPR, elna_word_type_node,
this->current_expression, size_one_node);
tree element_type = TREE_TYPE(TREE_TYPE(designator));
if (is_array_type(TREE_TYPE(designator)))
{
tree element_type = TREE_TYPE(TREE_TYPE(designator));
this->current_expression = build4_loc(get_location(&expression->position()),
ARRAY_REF, element_type, designator, index, NULL_TREE, NULL_TREE);
this->current_expression = build4_loc(location,
ARRAY_REF, element_type, designator, offset, NULL_TREE, NULL_TREE);
}
else if (TREE_TYPE(designator) == elna_string_type_node)
{
tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
designator, elna_string_ptr_field_node, NULL_TREE);
tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset);
this->current_expression = build1_loc(location, INDIRECT_REF,
elna_char_type_node, target_pointer);
}
else
{
error_at(location, "indexing is not allowed on type '%s'",
print_type(TREE_TYPE(designator)).c_str());
this->current_expression = error_mark_node;
}
}
void generic_visitor::visit(boot::field_access_expression *expression)