Implement defer

This commit is contained in:
2025-02-07 22:12:59 +01:00
parent 077de53c74
commit 8a0f282714
13 changed files with 484 additions and 335 deletions

View File

@ -50,7 +50,7 @@ namespace gcc
if (return_type == void_type_node)
{
append_to_statement_list(stmt, &this->current_statements);
this->scope.front().append_statement(stmt);
this->current_expression = NULL_TREE;
}
else
@ -133,7 +133,7 @@ namespace gcc
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
build_int_cst_type(integer_type_node, 0));
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
append_to_statement_list(return_stmt, &this->current_statements);
this->scope.front().append_statement(return_stmt);
tree_symbol_mapping mapping = leave_scope();
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
@ -161,8 +161,8 @@ namespace gcc
: build_type(*definition->return_type());
tree declaration_type = build_function_type_array(return_type,
definition->parameters.size(), parameter_types.data());
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
this->symbol_map->enter(definition->identifier(), this->main_fndecl);
this->main_fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
this->symbol_map->enter(definition->identifier, this->main_fndecl);
if (definition->body() != nullptr)
{
@ -178,17 +178,18 @@ namespace gcc
auto parameter = definition->parameters.at(i);
tree declaration_tree = build_decl(get_location(&parameter->position()), PARM_DECL,
get_identifier(parameter->identifier().c_str()), parameter_types[i]);
get_identifier(parameter->identifier.c_str()), parameter_types[i]);
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
if (definition->body() != nullptr)
{
this->symbol_map->enter(parameter->identifier(), declaration_tree);
this->symbol_map->enter(parameter->identifier, declaration_tree);
}
argument_chain.append(declaration_tree);
}
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
TREE_PUBLIC(this->main_fndecl) = definition->exported;
if (definition->body() != nullptr)
{
@ -214,19 +215,29 @@ namespace gcc
void generic_visitor::enter_scope()
{
this->current_statements = alloc_stmt_list();
this->variable_chain = tree_chain();
scope.emplace_front();
this->symbol_map = std::make_shared<boot::symbol_table<tree>>(this->symbol_map);
}
tree_symbol_mapping generic_visitor::leave_scope()
{
tree new_block = build_block(variable_chain.head(),
NULL_TREE, NULL_TREE, NULL_TREE);
tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(),
this->current_statements, new_block);
tree new_block = build_block(this->scope.front().variables.head(),
this->scope.front().blocks.head(), NULL_TREE, NULL_TREE);
for (tree it = this->scope.front().blocks.head(); it != NULL_TREE; it = BLOCK_CHAIN(it))
{
BLOCK_SUPERCONTEXT(it) = new_block;
}
tree bind_expr = build3(BIND_EXPR, void_type_node, this->scope.front().variables.head(),
this->scope.front().chain_defer(), new_block);
this->symbol_map = this->symbol_map->scope();
scope.pop_front();
if (!scope.empty())
{
scope.front().blocks.append(new_block);
}
return tree_symbol_mapping{ bind_expr, new_block };
}
@ -278,9 +289,29 @@ namespace gcc
this->current_expression = null_pointer_node;
}
void generic_visitor::visit(boot::string_literal *string)
void generic_visitor::visit(boot::number_literal<std::string> *string)
{
this->current_expression = build_string_literal(string->string().size() + 1, string->string().c_str());
tree index_type = this->symbol_map->lookup("Word");
tree index_constant = build_int_cstu(index_type, string->number().size());
tree element_type = this->symbol_map->lookup("Char");
tree string_type = build_array_type(element_type, build_index_type(index_constant));
tree string_literal = build_string(string->number().size(), string->number().c_str());
TREE_TYPE(string_literal) = string_type;
TREE_CONSTANT(string_literal) = 1;
TREE_READONLY(string_literal) = 1;
TREE_STATIC(string_literal) = 1;
string_type = build_pointer_type(element_type);
string_literal = build4(ARRAY_REF, element_type, 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;
tree string_record = this->symbol_map->lookup("String");
CONSTRUCTOR_APPEND_ELT(elms, TYPE_FIELDS(string_record), index_constant);
CONSTRUCTOR_APPEND_ELT(elms, TREE_CHAIN(TYPE_FIELDS(string_record)), string_literal);
this->current_expression = build_constructor(string_record, elms);
}
tree generic_visitor::build_arithmetic_operation(boot::binary_expression *expression,
@ -424,55 +455,49 @@ namespace gcc
definition->body().accept(this);
tree definition_tree = build_decl(definition_location, CONST_DECL,
get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression));
auto result = this->symbol_map->enter(definition->identifier(), definition_tree);
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
auto result = this->symbol_map->enter(definition->identifier, definition_tree);
if (result)
{
DECL_INITIAL(definition_tree) = this->current_expression;
TREE_CONSTANT(definition_tree) = 1;
TREE_READONLY(definition_tree) = 1;
TREE_PUBLIC(definition_tree) = definition->exported;
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
void_type_node, definition_tree);
append_to_statement_list(declaration_statement, &this->current_statements);
if (!scope.empty())
{
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
void_type_node, definition_tree);
this->scope.front().append_statement(declaration_statement);
}
}
else
{
error_at(definition_location,
"variable '%s' already declared in this scope",
definition->identifier().c_str());
definition->identifier.c_str());
}
this->current_expression = NULL_TREE;
}
void generic_visitor::visit(boot::type_definition *definition)
{
tree tree_type = build_type(definition->body());
if (tree_type == NULL_TREE)
{
return;
}
location_t definition_location = get_location(&definition->position());
tree tree_type = build_type(definition->body());
tree definition_tree = build_decl(definition_location, TYPE_DECL,
get_identifier(definition->identifier().c_str()), tree_type);
auto result = this->symbol_map->enter(definition->identifier(), tree_type);
get_identifier(definition->identifier.c_str()), tree_type);
auto result = this->symbol_map->enter(definition->identifier, tree_type);
if (result)
{
DECL_CONTEXT(definition_tree) = this->main_fndecl;
variable_chain.append(definition_tree);
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
void_type_node, definition_tree);
append_to_statement_list(declaration_statement, &this->current_statements);
TREE_PUBLIC(definition_tree) = definition->exported;
}
else
{
error_at(definition_location,
error_at(get_location(&definition->position()),
"type '%s' already declared in this scope",
definition->identifier().c_str());
definition->identifier.c_str());
}
}
@ -535,11 +560,8 @@ namespace gcc
{
return field_type;
}
tree field_declaration = build_decl(get_location(&field.second->position()),
FIELD_DECL, get_identifier(field.first.c_str()), field_type);
TREE_ADDRESSABLE(field_declaration) = 1;
DECL_CONTEXT(field_declaration) = record_type_node;
tree field_declaration = build_field(get_location(&field.second->position()),
record_type_node, field.first, field_type);
record_chain.append(field_declaration);
}
TYPE_FIELDS(record_type_node) = record_chain.head();
@ -567,11 +589,8 @@ namespace gcc
{
return field_type;
}
tree field_declaration = build_decl(get_location(&field.second->position()),
FIELD_DECL, get_identifier(field.first.c_str()), field_type);
TREE_ADDRESSABLE(field_declaration) = 1;
DECL_CONTEXT(field_declaration) = union_type_node;
tree field_declaration = build_field(get_location(&field.second->position()),
union_type_node, field.first, field_type);
union_chain.append(field_declaration);
}
TYPE_FIELDS(union_type_node) = union_chain.head();
@ -589,13 +608,13 @@ namespace gcc
location_t declaration_location = get_location(&declaration->position());
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
get_identifier(declaration->identifier().c_str()), declaration_type);
bool result = this->symbol_map->enter(declaration->identifier(), declaration_tree);
get_identifier(declaration->identifier.c_str()), declaration_type);
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
if (!result)
{
error_at(declaration_location, "variable '%s' already declared in this scope",
declaration->identifier().c_str());
declaration->identifier.c_str());
}
else if (this->main_fndecl == NULL_TREE)
{
@ -606,11 +625,11 @@ namespace gcc
else
{
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
variable_chain.append(declaration_tree);
this->scope.front().variables.append(declaration_tree);
auto declaration_statement = build1_loc(declaration_location, DECL_EXPR,
void_type_node, declaration_tree);
append_to_statement_list(declaration_statement, &this->current_statements);
this->scope.front().append_statement(declaration_statement);
}
}
@ -705,7 +724,7 @@ namespace gcc
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
void_type_node, lvalue, this->current_expression);
append_to_statement_list(assignment, &this->current_statements);
this->scope.front().append_statement(assignment);
this->current_expression = NULL_TREE;
}
else
@ -731,14 +750,16 @@ namespace gcc
}
if (statement->alternative() != nullptr)
{
enter_scope();
for (const auto body_statement : *statement->alternative())
{
body_statement->accept(this);
}
tree_symbol_mapping mapping = leave_scope();
scope.front().append_statement(mapping.bind_expression());
}
tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
append_to_statement_list(endif_label_expr, &this->current_statements);
this->scope.front().append_statement(endif_label_expr);
this->current_expression = NULL_TREE;
}
@ -761,19 +782,22 @@ namespace gcc
tree goto_else = build1(GOTO_EXPR, void_type_node, else_label_decl);
auto cond_expr = build3(COND_EXPR, void_type_node, this->current_expression, goto_then, goto_else);
append_to_statement_list(cond_expr, &this->current_statements);
this->scope.front().append_statement(cond_expr);
tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
append_to_statement_list(then_label_expr, &this->current_statements);
this->scope.front().append_statement(then_label_expr);
enter_scope();
for (const auto body_statement : branch.statements)
{
body_statement->accept(this);
}
append_to_statement_list(goto_endif, &this->current_statements);
tree_symbol_mapping mapping = leave_scope();
this->scope.front().append_statement(mapping.bind_expression());
this->scope.front().append_statement(goto_endif);
tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
append_to_statement_list(else_label_expr, &this->current_statements);
this->scope.front().append_statement(else_label_expr);
}
tree generic_visitor::build_label_decl(const char *name, location_t loc)
@ -798,13 +822,15 @@ namespace gcc
this->current_expression = error_mark_node;
return;
}
enter_scope();
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
auto body_location = get_location(&statement->position());
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
void_type_node, prerequisite_label_decl);
append_to_statement_list(prerequisite_label_expr, &this->current_statements);
this->scope.front().append_statement(prerequisite_label_expr);
auto body_label_decl = build_label_decl("while_body", body_location);
auto end_label_decl = build_label_decl("end_while", UNKNOWN_LOCATION);
@ -816,21 +842,24 @@ namespace gcc
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
void_type_node, this->current_expression, goto_body, goto_end);
append_to_statement_list(cond_expr, &this->current_statements);
this->scope.front().append_statement(cond_expr);
auto body_label_expr = build1_loc(body_location, LABEL_EXPR,
void_type_node, body_label_decl);
append_to_statement_list(body_label_expr, &this->current_statements);
this->scope.front().append_statement(body_label_expr);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
tree_symbol_mapping mapping = leave_scope();
this->scope.front().append_statement(mapping.bind_expression());
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
append_to_statement_list(goto_check, &this->current_statements);
this->scope.front().append_statement(goto_check);
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, end_label_decl);
append_to_statement_list(endif_label_expr, &this->current_statements);
this->scope.front().append_statement(endif_label_expr);
this->current_expression = NULL_TREE;
}
@ -838,7 +867,8 @@ namespace gcc
void generic_visitor::visit(boot::call_statement *statement)
{
statement->body().accept(this);
append_to_statement_list(this->current_expression, &this->current_statements);
this->scope.front().append_statement(this->current_expression);
this->current_expression = NULL_TREE;
}
void generic_visitor::visit(boot::return_statement *statement)
@ -854,7 +884,18 @@ namespace gcc
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
this->current_expression);
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
append_to_statement_list(return_stmt, &this->current_statements);
this->scope.front().append_statement(return_stmt);
}
void generic_visitor::visit(boot::defer_statement *statement)
{
enter_scope();
for (boot::statement *const body_statement : statement->statements)
{
body_statement->accept(this);
}
tree_symbol_mapping mapping = leave_scope();
scope.front().defer(mapping.bind_expression());
}
}
}