Allow exporting global external variables

This commit is contained in:
2025-08-24 16:54:48 +02:00
parent fd3729ba16
commit c95466622a
7 changed files with 56 additions and 52 deletions

View File

@@ -57,8 +57,6 @@ namespace elna::gcc
tree identifier = get_identifier(name); tree identifier = get_identifier(name);
tree type_declaration = build_decl(UNKNOWN_LOCATION, TYPE_DECL, identifier, type); tree type_declaration = build_decl(UNKNOWN_LOCATION, TYPE_DECL, identifier, type);
TREE_PUBLIC(type_declaration) = 1;
symbol_table->enter(name, type_declaration); symbol_table->enter(name, type_declaration);
return type_declaration; return type_declaration;
@@ -82,24 +80,6 @@ namespace elna::gcc
return symbol_table; return symbol_table;
} }
tree build_type_declaration(const std::string& identifier, tree type)
{
tree definition_tree = build_decl(UNKNOWN_LOCATION, TYPE_DECL,
get_identifier(identifier.c_str()), type);
TREE_PUBLIC(definition_tree) = 1;
if (is_unique_type(type))
{
TYPE_NAME(type) = DECL_NAME(definition_tree);
TYPE_STUB_DECL(type) = definition_tree;
}
else
{
TYPE_NAME(type) = definition_tree;
}
return definition_tree;
}
tree build_composite_type(const std::vector<boot::type_field>& fields, tree composite_type_node, tree build_composite_type(const std::vector<boot::type_field>& fields, tree composite_type_node,
std::shared_ptr<symbol_table> symbols) std::shared_ptr<symbol_table> symbols)
{ {
@@ -178,7 +158,7 @@ namespace elna::gcc
} }
else if (auto reference = type.get<boot::alias_type>()) else if (auto reference = type.get<boot::alias_type>())
{ {
return handle_symbol(reference->name, reference, symbols); return TREE_TYPE(handle_symbol(reference->name, reference, symbols));
} }
return error_mark_node; return error_mark_node;
} }
@@ -190,13 +170,21 @@ namespace elna::gcc
if (looked_up == NULL_TREE) if (looked_up == NULL_TREE)
{ {
looked_up = get_inner_alias(reference->reference, symbols); tree type_tree = get_inner_alias(reference->reference, symbols);
looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL,
get_identifier(symbol_name.c_str()), type_tree);
symbols->enter(symbol_name, build_type_declaration(symbol_name, looked_up)); TREE_PUBLIC(looked_up) = 1;
} if (is_unique_type(type_tree))
else {
{ TYPE_NAME(type_tree) = DECL_NAME(looked_up);
looked_up = TREE_TYPE(looked_up); TYPE_STUB_DECL(type_tree) = looked_up;
}
else
{
TYPE_NAME(type_tree) = looked_up;
}
symbols->enter(symbol_name, looked_up);
} }
return looked_up; return looked_up;
} }
@@ -236,6 +224,7 @@ namespace elna::gcc
DECL_ARGUMENTS(fndecl) = argument_chain; DECL_ARGUMENTS(fndecl) = argument_chain;
TREE_ADDRESSABLE(fndecl) = 1; TREE_ADDRESSABLE(fndecl) = 1;
DECL_EXTERNAL(fndecl) = info.is_extern(); DECL_EXTERNAL(fndecl) = info.is_extern();
TREE_PUBLIC(fndecl) = info.exported;
} }
tree declare_variable(const std::string& name, const boot::variable_info& info, tree declare_variable(const std::string& name, const boot::variable_info& info,
@@ -246,23 +235,31 @@ namespace elna::gcc
TREE_ADDRESSABLE(declaration_tree) = 1; TREE_ADDRESSABLE(declaration_tree) = 1;
DECL_EXTERNAL(declaration_tree) = info.is_extern; DECL_EXTERNAL(declaration_tree) = info.is_extern;
TREE_PUBLIC(declaration_tree) = info.exported;
symbols->enter(name, declaration_tree); symbols->enter(name, declaration_tree);
return declaration_tree; return declaration_tree;
} }
void declare_type(const std::string& name, const boot::type_info& info, std::shared_ptr<symbol_table> symbols)
{
// The top level symbol table has basic (builtin) types in it which are not aliases.
if (auto alias_type = info.symbol.get<boot::alias_type>())
{
tree type_declaration = handle_symbol(name, alias_type, symbols);
TREE_PUBLIC(type_declaration) = info.exported;
}
}
void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols) void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols)
{ {
for (auto& [symbol_name, symbol_info] : *info_table) for (auto& [symbol_name, symbol_info] : *info_table)
{ {
if (auto type_info = symbol_info->is_type()) if (auto type_info = symbol_info->is_type())
{ {
// The top level symbol table has basic (builtin) types in it which are not aliases. declare_type(symbol_name, *type_info, symbols);
if (auto alias_type = type_info->symbol.get<boot::alias_type>())
{
handle_symbol(symbol_name, alias_type, symbols);
}
} }
else if (auto variable_info = symbol_info->is_variable()) else if (auto variable_info = symbol_info->is_variable())
{ {

View File

@@ -21,6 +21,16 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc namespace elna::gcc
{ {
linemap_guard::linemap_guard(const char *filename)
{
linemap_add(line_table, LC_ENTER, 0, filename, 1);
}
linemap_guard::~linemap_guard()
{
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
}
location_t get_location(const boot::position *position) location_t get_location(const boot::position *position)
{ {
linemap_line_start(line_table, position->line, 0); linemap_line_start(line_table, position->line, 0);

View File

@@ -295,10 +295,6 @@ namespace elna::gcc
{ {
constant->accept(this); constant->accept(this);
} }
for (boot::type_declaration *const type : unit->types)
{
type->accept(this);
}
for (boot::variable_declaration *const variable : unit->variables) for (boot::variable_declaration *const variable : unit->variables)
{ {
variable->accept(this); variable->accept(this);
@@ -312,13 +308,11 @@ namespace elna::gcc
void generic_visitor::visit(boot::procedure_declaration *definition) void generic_visitor::visit(boot::procedure_declaration *definition)
{ {
tree fndecl = this->symbols->lookup(definition->identifier.name); tree fndecl = this->symbols->lookup(definition->identifier.name);
TREE_PUBLIC(fndecl) = definition->identifier.exported;
if (!definition->body.has_value()) if (!definition->body.has_value())
{ {
return; return;
} }
push_struct_function(fndecl, false); push_struct_function(fndecl, false);
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>(); DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
@@ -738,11 +732,6 @@ namespace elna::gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(boot::type_declaration *declaration)
{
TREE_PUBLIC(this->symbols->lookup(declaration->identifier.name)) = declaration->identifier.exported;
}
void generic_visitor::visit(boot::variable_declaration *declaration) void generic_visitor::visit(boot::variable_declaration *declaration)
{ {
for (const auto& variable_identifier : declaration->identifiers) for (const auto& variable_identifier : declaration->identifiers)
@@ -775,12 +764,11 @@ namespace elna::gcc
{ {
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
} }
TREE_PUBLIC(declaration_tree) = variable_identifier.exported;
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
if (lang_hooks.decls.global_bindings_p()) if (lang_hooks.decls.global_bindings_p())
{ {
TREE_STATIC(declaration_tree) = 1; TREE_STATIC(declaration_tree) = !variable_identifier.exported && !declaration->is_extern;
varpool_node::get_create(declaration_tree); varpool_node::get_create(declaration_tree);
varpool_node::finalize_decl(declaration_tree); varpool_node::finalize_decl(declaration_tree);
} }

View File

@@ -72,12 +72,13 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
{ {
fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename); fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename);
} }
linemap_add(line_table, LC_ENTER, 0, filename, 1); elna::gcc::linemap_guard{ filename };
elna::boot::dependency outcome = elna::boot::read_source(entry_point, filename); elna::boot::dependency outcome = elna::boot::read_source(entry_point, filename);
if (outcome.has_errors()) if (outcome.has_errors())
{ {
elna::gcc::report_errors(outcome.errors()); elna::gcc::report_errors(outcome.errors());
return outcome;
} }
elna::boot::symbol_bag outcome_bag = elna::boot::symbol_bag{ std::move(outcome.unresolved), state.globals }; elna::boot::symbol_bag outcome_bag = elna::boot::symbol_bag{ std::move(outcome.unresolved), state.globals };
@@ -94,15 +95,15 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
} }
outcome_bag.add_import(cached_import->second); outcome_bag.add_import(cached_import->second);
} }
elna::boot::error_list semantic_errors = analyze_semantics(filename, outcome.tree, outcome_bag); outcome.errors() = analyze_semantics(filename, outcome.tree, outcome_bag);
if (!semantic_errors.empty()) if (outcome.has_errors())
{ {
elna::gcc::report_errors(semantic_errors); elna::gcc::report_errors(outcome.errors());
return outcome;
} }
state.cache.insert({ filename, outcome_bag }); state.cache.insert({ filename, outcome_bag });
elna::gcc::rewrite_symbol_table(outcome_bag.leave(), state.custom); elna::gcc::rewrite_symbol_table(outcome_bag.leave(), state.custom);
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
return outcome; return outcome;
} }

View File

@@ -31,7 +31,7 @@ namespace elna::boot
public: public:
std::unique_ptr<unit> tree; std::unique_ptr<unit> tree;
std::unordered_map<std::string, std::shared_ptr<alias_type>> unresolved; forward_table unresolved;
explicit dependency(const char *path); explicit dependency(const char *path);
}; };

View File

@@ -31,6 +31,15 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc namespace elna::gcc
{ {
struct linemap_guard
{
explicit linemap_guard(const char *filename);
linemap_guard(const linemap_guard&) = delete;
linemap_guard(linemap_guard&&) = delete;
~linemap_guard();
};
location_t get_location(const boot::position *position); location_t get_location(const boot::position *position);
std::string print_type(tree type); std::string print_type(tree type);
void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors); void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors);

View File

@@ -80,7 +80,6 @@ namespace elna::gcc
void visit(boot::binary_expression *expression) override; void visit(boot::binary_expression *expression) override;
void visit(boot::unary_expression *expression) override; void visit(boot::unary_expression *expression) override;
void visit(boot::constant_declaration *definition) override; void visit(boot::constant_declaration *definition) override;
void visit(boot::type_declaration *declaration) override;
void visit(boot::variable_declaration *declaration) override; void visit(boot::variable_declaration *declaration) override;
void visit(boot::variable_expression *expression) override; void visit(boot::variable_expression *expression) override;
void visit(boot::array_access_expression *expression) override; void visit(boot::array_access_expression *expression) override;