Support procedures returning values
This commit is contained in:
@ -40,10 +40,18 @@ namespace gcc
|
||||
{
|
||||
return "pointer";
|
||||
}
|
||||
else if (is_array_type(type))
|
||||
else if (TREE_CODE(type) == ARRAY_TYPE)
|
||||
{
|
||||
return "array";
|
||||
}
|
||||
else if (TREE_CODE(type) == RECORD_TYPE)
|
||||
{
|
||||
return "record";
|
||||
}
|
||||
else if (TREE_CODE(type) == UNION_TYPE)
|
||||
{
|
||||
return "union";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<<unknown-type>>";
|
||||
|
@ -20,7 +20,7 @@ namespace gcc
|
||||
this->symbol_map = symbol_table;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::call_statement *statement)
|
||||
void generic_visitor::visit(source::call_expression *statement)
|
||||
{
|
||||
auto symbol = this->symbol_map->lookup(statement->name());
|
||||
|
||||
@ -87,7 +87,8 @@ namespace gcc
|
||||
}
|
||||
else if (symbol)
|
||||
{
|
||||
tree fndecl_type = build_function_type(void_type_node, TYPE_ARG_TYPES(symbol->payload));
|
||||
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);
|
||||
|
||||
std::vector<tree> arguments(statement->arguments().size());
|
||||
@ -97,10 +98,17 @@ namespace gcc
|
||||
arguments[i] = this->current_expression;
|
||||
}
|
||||
tree stmt = build_call_array_loc(get_location(&statement->position()),
|
||||
void_type_node, printf_fn, arguments.size(), arguments.data());
|
||||
return_type, printf_fn, arguments.size(), arguments.data());
|
||||
|
||||
append_to_statement_list(stmt, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
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
|
||||
{
|
||||
@ -126,9 +134,6 @@ namespace gcc
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||
DECL_RESULT(this->main_fndecl) = resdecl;
|
||||
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);
|
||||
|
||||
enter_scope();
|
||||
|
||||
@ -140,6 +145,9 @@ namespace gcc
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
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);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
|
||||
@ -163,15 +171,17 @@ namespace gcc
|
||||
{
|
||||
parameter_types[i] = build_type(definition->parameters.at(i)->type());
|
||||
}
|
||||
tree declaration_type = build_function_type_array(void_type_node,
|
||||
tree return_type = definition->return_type() == nullptr
|
||||
? void_type_node
|
||||
: 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(), source::make_info(this->main_fndecl));
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL,
|
||||
NULL_TREE, TREE_TYPE(TREE_TYPE(this->main_fndecl)));
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||
DECL_RESULT(this->main_fndecl) = resdecl;
|
||||
|
||||
@ -454,7 +464,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(), source::make_info(definition_tree));
|
||||
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(tree_type));
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -477,31 +487,11 @@ namespace gcc
|
||||
{
|
||||
if (source::basic_type_expression *basic_type = type.is_basic())
|
||||
{
|
||||
if (basic_type->base_name() == "Int")
|
||||
{
|
||||
return integer_type_node;
|
||||
}
|
||||
else if (basic_type->base_name() == "Bool")
|
||||
{
|
||||
return boolean_type_node;
|
||||
}
|
||||
else if (basic_type->base_name() == "Float")
|
||||
{
|
||||
return double_type_node;
|
||||
}
|
||||
else if (basic_type->base_name() == "Char")
|
||||
{
|
||||
return elna_char_type_node;
|
||||
}
|
||||
else if (basic_type->base_name() == "String")
|
||||
{
|
||||
return elna_string_type_node;
|
||||
}
|
||||
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||
|
||||
if (symbol)
|
||||
if (symbol && TYPE_P(symbol->payload))
|
||||
{
|
||||
return TREE_TYPE(symbol->payload);
|
||||
return symbol->payload;
|
||||
}
|
||||
error_at(get_location(&basic_type->position()),
|
||||
"type '%s' not declared", basic_type->base_name().c_str());
|
||||
@ -844,5 +834,26 @@ namespace gcc
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::expression_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::return_statement *statement)
|
||||
{
|
||||
source::expression *return_expression = statement->return_expression();
|
||||
|
||||
if (return_expression == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return_expression->accept(this);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,12 +28,6 @@ namespace gcc
|
||||
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
||||
}
|
||||
|
||||
bool is_array_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
return TREE_CODE(type) == ARRAY_TYPE;
|
||||
}
|
||||
|
||||
tree tree_chain_base::head()
|
||||
{
|
||||
return first;
|
||||
@ -76,7 +70,16 @@ namespace gcc
|
||||
|
||||
std::shared_ptr<elna::source::symbol_table<tree>> builtin_symbol_table()
|
||||
{
|
||||
return std::make_shared<elna::source::symbol_table<tree>>();
|
||||
std::shared_ptr<elna::source::symbol_table<tree>> initial_table =
|
||||
std::make_shared<elna::source::symbol_table<tree>>();
|
||||
|
||||
initial_table->enter("Int", source::make_info(integer_type_node));
|
||||
initial_table->enter("Bool", source::make_info(boolean_type_node));
|
||||
initial_table->enter("Float", source::make_info(double_type_node));
|
||||
initial_table->enter("Char", source::make_info(elna_char_type_node));
|
||||
initial_table->enter("String", source::make_info(elna_string_type_node));
|
||||
|
||||
return initial_table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ static void elna_parse_file(const char *filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
elna::gcc::generic_visitor generic_visitor;
|
||||
elna::gcc::generic_visitor generic_visitor{ elna::gcc::builtin_symbol_table() };
|
||||
|
||||
generic_visitor.visit(driver.tree.get());
|
||||
}
|
||||
|
Reference in New Issue
Block a user