Allow assigning nil to any pointer
This commit is contained in:
@ -25,37 +25,37 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::call_expression *expression)
|
||||
{
|
||||
if (auto symbol = this->symbol_map->lookup(expression->name()))
|
||||
{
|
||||
tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
|
||||
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
|
||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
||||
tree symbol = this->symbol_map->lookup(expression->name());
|
||||
|
||||
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_to_statement_list(stmt, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (symbol == NULL_TREE)
|
||||
{
|
||||
error_at(get_location(&expression->position()),
|
||||
"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)
|
||||
{
|
||||
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_to_statement_list(stmt, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,22 +74,21 @@ namespace gcc
|
||||
{
|
||||
auto body_type = build_type(expression->body());
|
||||
|
||||
this->current_expression = build1(CONVERT_EXPR,
|
||||
this->symbol_map->lookup("Word")->payload, TYPE_SIZE_UNIT(body_type));
|
||||
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")->payload
|
||||
|| type == this->symbol_map->lookup("Word")->payload;
|
||||
return type == this->symbol_map->lookup("Int")
|
||||
|| type == this->symbol_map->lookup("Word");
|
||||
}
|
||||
|
||||
bool generic_visitor::is_numeric_type(tree type)
|
||||
{
|
||||
return is_integral_type(type)
|
||||
|| type == this->symbol_map->lookup("Float")->payload;
|
||||
|| type == this->symbol_map->lookup("Float");
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::program *program)
|
||||
@ -130,7 +129,7 @@ namespace gcc
|
||||
get_identifier(argument_name.c_str()), parameter_types[i]);
|
||||
DECL_CONTEXT(argc_declaration_tree) = this->main_fndecl;
|
||||
DECL_ARG_TYPE(argc_declaration_tree) = parameter_types[i];
|
||||
this->symbol_map->enter(argument_name, boot::make_info(argc_declaration_tree));
|
||||
this->symbol_map->enter(argument_name, argc_declaration_tree);
|
||||
argument_chain.append(argc_declaration_tree);
|
||||
}
|
||||
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
||||
@ -171,7 +170,7 @@ namespace gcc
|
||||
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(), boot::make_info(this->main_fndecl));
|
||||
this->symbol_map->enter(definition->identifier(), this->main_fndecl);
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
@ -193,7 +192,7 @@ namespace gcc
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
this->symbol_map->enter(parameter->identifier(), boot::make_info(declaration_tree));
|
||||
this->symbol_map->enter(parameter->identifier(), declaration_tree);
|
||||
}
|
||||
argument_chain.append(declaration_tree);
|
||||
}
|
||||
@ -243,14 +242,14 @@ namespace gcc
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Int");
|
||||
|
||||
this->current_expression = build_int_cst(symbol->payload, literal->number());
|
||||
this->current_expression = build_int_cst(symbol, literal->number());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Word");
|
||||
|
||||
this->current_expression = build_int_cstu(symbol->payload, literal->number());
|
||||
this->current_expression = build_int_cstu(symbol, literal->number());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<double> *literal)
|
||||
@ -272,14 +271,14 @@ namespace gcc
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Bool");
|
||||
|
||||
this->current_expression = build_int_cst_type(symbol->payload, boolean->number());
|
||||
this->current_expression = build_int_cst_type(symbol, boolean->number());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Char");
|
||||
|
||||
this->current_expression = build_int_cstu(symbol->payload, character->number());
|
||||
this->current_expression = build_int_cstu(symbol, character->number());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
||||
@ -303,7 +302,7 @@ namespace gcc
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
||||
expression, operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
||||
expression, operator_code, left, right, this->symbol_map->lookup("Bool"));
|
||||
}
|
||||
|
||||
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
||||
@ -311,15 +310,15 @@ namespace gcc
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup("Bool");
|
||||
|
||||
return build_binary_operation(TREE_TYPE(left) == symbol->payload,
|
||||
expression, operator_code, left, right, symbol->payload);
|
||||
return build_binary_operation(TREE_TYPE(left) == symbol,
|
||||
expression, operator_code, left, right, symbol);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(true, expression,
|
||||
operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
||||
operator_code, left, right, this->symbol_map->lookup("Bool"));
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::binary_expression *expression)
|
||||
@ -425,7 +424,7 @@ namespace gcc
|
||||
|
||||
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(), boot::make_info(definition_tree));
|
||||
auto result = this->symbol_map->enter(definition->identifier(), definition_tree);
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -457,7 +456,7 @@ namespace gcc
|
||||
location_t definition_location = get_location(&definition->position());
|
||||
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(), boot::make_info(tree_type));
|
||||
auto result = this->symbol_map->enter(definition->identifier(), tree_type);
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -480,11 +479,11 @@ namespace gcc
|
||||
{
|
||||
if (boot::basic_type_expression *basic_type = type.is_basic())
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||
tree symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||
|
||||
if (symbol && TYPE_P(symbol->payload))
|
||||
if (symbol != NULL_TREE && TYPE_P(symbol))
|
||||
{
|
||||
return symbol->payload;
|
||||
return symbol;
|
||||
}
|
||||
error_at(get_location(&basic_type->position()),
|
||||
"type '%s' not declared", basic_type->base_name().c_str());
|
||||
@ -590,7 +589,7 @@ 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(), boot::make_info(declaration_tree));
|
||||
bool result = this->symbol_map->enter(declaration->identifier(), declaration_tree);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
@ -618,7 +617,7 @@ namespace gcc
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup(expression->name());
|
||||
|
||||
if (!symbol)
|
||||
if (symbol == NULL_TREE)
|
||||
{
|
||||
error_at(get_location(&expression->position()),
|
||||
"variable '%s' not declared in the current scope",
|
||||
@ -626,7 +625,7 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
this->current_expression = symbol->payload;
|
||||
this->current_expression = symbol;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::array_access_expression *expression)
|
||||
@ -699,20 +698,23 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue))
|
||||
if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue)
|
||||
|| (is_pointer_type(TREE_TYPE(lvalue)) && this->current_expression == null_pointer_node))
|
||||
{
|
||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
||||
append_to_statement_list(assignment, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(statement_location,
|
||||
"cannot assign value of type %s to variable of type %s",
|
||||
print_type(TREE_TYPE(this->current_expression)),
|
||||
print_type(TREE_TYPE(lvalue)));
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
auto assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
||||
append_to_statement_list(assignment, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::if_statement *statement)
|
||||
|
@ -74,13 +74,13 @@ namespace gcc
|
||||
std::shared_ptr<boot::symbol_table<tree>> initial_table =
|
||||
std::make_shared<boot::symbol_table<tree>>();
|
||||
|
||||
initial_table->enter("Int", boot::make_info(long_integer_type_node));
|
||||
initial_table->enter("Word", boot::make_info(size_type_node));
|
||||
initial_table->enter("Bool", boot::make_info(boolean_type_node));
|
||||
initial_table->enter("Float", boot::make_info(double_type_node));
|
||||
initial_table->enter("Char", boot::make_info(unsigned_char_type_node));
|
||||
initial_table->enter("Byte", boot::make_info(make_unsigned_type(8)));
|
||||
initial_table->enter("String", boot::make_info(elna_string_type_node));
|
||||
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;
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* gcc/gcc.cc */
|
||||
{".elna", "@elna", nullptr, 0, 0},
|
||||
{"@elna",
|
||||
"elna1 %{!Q:-quiet} \
|
||||
%i %{!fsyntax-only:%(invoke_as)}",
|
||||
"elna1 %i \
|
||||
%{!Q:-quiet} \
|
||||
%{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}} \
|
||||
%{fsyntax-only:-o %j} %{-param*} \
|
||||
%{!fsyntax-only:%(invoke_as)}",
|
||||
nullptr, 0, 0},
|
||||
|
Reference in New Issue
Block a user