Issue 1114 (#1121)

* Two patches to enable building on MSYS with gcc 12.1

1. Complete explicit instantiations in dbHierProcessor
2. Strict weak ordering is not present for std::type_info
   (using "before" on gcc 12.1). We need to work with plain
   pointers and use a translation table to associate pointers
   with classes.

* Fixed another place where std::type_info got important

Co-authored-by: Matthias Koefferlein <matthias@klayout.de>
This commit is contained in:
Matthias Köfferlein 2022-07-17 19:59:49 +02:00 committed by GitHub
parent b1661d3c5e
commit 6ba372f1a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 30 deletions

View File

@ -1261,13 +1261,20 @@ template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, d
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>; template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>; template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>; template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>; template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>; template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>; template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>; template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>; template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>; template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>; template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
// LocalProcessorResultComputationTask implementation // LocalProcessorResultComputationTask implementation

View File

@ -49,9 +49,11 @@ namespace {
// TODO: thread-safe? Unlikely that multiple threads access this member - // TODO: thread-safe? Unlikely that multiple threads access this member -
// we do a initial scan and after this no more write access here. // we do a initial scan and after this no more write access here.
typedef std::map<const std::type_info *, const ClassBase *, type_info_compare> ti_to_class_map_t; static std::vector<const ClassBase *> *sp_classes = 0;
static ti_to_class_map_t *sp_ti_to_class = 0; typedef std::map<const ClassBase *, size_t> class_to_index_map_t;
// NOTE: MacOS/clang seems to have some issue with RTTI across shared objects. This map provides a name-based fallback static class_to_index_map_t *sp_class_to_index = 0;
typedef std::map<const std::type_info *, size_t> ti_to_class_map_t;
static ti_to_class_map_t *sp_ti_to_class_index = 0;
typedef std::map<std::string, const ClassBase *> tname_to_class_map_t; typedef std::map<std::string, const ClassBase *> tname_to_class_map_t;
static tname_to_class_map_t *sp_tname_to_class = 0; static tname_to_class_map_t *sp_tname_to_class = 0;
@ -67,9 +69,17 @@ ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_registe
mp_new_class_collection->push_back (this); mp_new_class_collection->push_back (this);
// invalidate the "typeinfo to class" map // invalidate the "typeinfo to class" map
if (sp_ti_to_class) { if (sp_classes) {
delete sp_ti_to_class; delete sp_classes;
sp_ti_to_class = 0; sp_classes = 0;
}
if (sp_class_to_index) {
delete sp_class_to_index;
sp_class_to_index = 0;
}
if (sp_ti_to_class_index) {
delete sp_ti_to_class_index;
sp_ti_to_class_index = 0;
} }
if (sp_tname_to_class) { if (sp_tname_to_class) {
delete sp_tname_to_class; delete sp_tname_to_class;
@ -826,14 +836,25 @@ static void add_class_to_map (const gsi::ClassBase *c)
ti = &c->type (); ti = &c->type ();
} }
if (! sp_ti_to_class) { if (! sp_classes) {
sp_ti_to_class = new ti_to_class_map_t (); sp_classes = new std::vector<const ClassBase *> ();
}
if (! sp_class_to_index) {
sp_class_to_index = new class_to_index_map_t ();
}
if (! sp_ti_to_class_index) {
sp_ti_to_class_index = new ti_to_class_map_t ();
} }
if (! sp_tname_to_class) { if (! sp_tname_to_class) {
sp_tname_to_class = new tname_to_class_map_t (); sp_tname_to_class = new tname_to_class_map_t ();
} }
if (!sp_ti_to_class->insert (std::make_pair (ti, c)).second) { auto c2i = sp_class_to_index->insert (std::make_pair (c, sp_classes->size ())).first;
if (c2i->second >= sp_classes->size ()) {
sp_classes->push_back (c);
}
if (!sp_ti_to_class_index->insert (std::make_pair (ti, c2i->second)).second) {
// Duplicate registration of this class // Duplicate registration of this class
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")"; tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
tl_assert (false); tl_assert (false);
@ -844,27 +865,27 @@ static void add_class_to_map (const gsi::ClassBase *c)
const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti) const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti)
{ {
if (! sp_ti_to_class || sp_ti_to_class->empty ()) { if (! sp_ti_to_class_index || sp_ti_to_class_index->empty ()) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { for (auto c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
add_class_to_map (c.operator-> ()); add_class_to_map (c.operator-> ());
} }
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { for (auto c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) {
add_class_to_map (c.operator-> ()); add_class_to_map (c.operator-> ());
} }
} }
if (! sp_ti_to_class) { if (! sp_ti_to_class_index) {
return 0; return 0;
} else { } else {
ti_to_class_map_t::const_iterator c = sp_ti_to_class->find (&ti); auto c = sp_ti_to_class_index->find (&ti);
if (c != sp_ti_to_class->end ()) { if (c != sp_ti_to_class_index->end ()) {
return c->second; return sp_classes->operator[] (c->second);
} else { } else {
// try name lookup // try name lookup
tname_to_class_map_t::const_iterator cn = sp_tname_to_class->find (std::string (ti.name ())); auto cn = sp_tname_to_class->find (std::string (ti.name ()));
if (cn != sp_tname_to_class->end ()) { if (cn != sp_tname_to_class->end ()) {
// we can use this typeinfo as alias // we can use this typeinfo as alias
sp_ti_to_class->insert (std::make_pair (&ti, cn->second)); sp_ti_to_class_index->insert (std::make_pair (&ti, sp_class_to_index->operator[] (cn->second)));
return cn->second; return cn->second;
} else { } else {
return 0; return 0;

View File

@ -144,22 +144,25 @@ struct VariantUserClassTableKey
if (is_const != k.is_const) { if (is_const != k.is_const) {
return is_const < k.is_const; return is_const < k.is_const;
} }
if (*type != *k.type) { if (type != k.type) {
return type->before (*k.type); return type < k.type;
} }
return false; return false;
} }
bool operator== (const VariantUserClassTableKey &k) const bool operator== (const VariantUserClassTableKey &k) const
{ {
return is_const == k.is_const && *type == *k.type; return is_const == k.is_const && type == k.type;
} }
const std::type_info *type; const std::type_info *type;
bool is_const; bool is_const;
}; };
static std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *> *sp_class_table = 0; static std::vector<const VariantUserClassBase *> *sp_classes = 0;
static std::map<const VariantUserClassBase *, size_t> *sp_class_to_index = 0;
static std::map<std::pair<std::string, bool>, size_t> *sp_class_index_by_name = 0;
static std::map<VariantUserClassTableKey, size_t> *sp_class_table = 0;
static std::map <std::string, const VariantUserClassBase *> s_user_type_by_name; static std::map <std::string, const VariantUserClassBase *> s_user_type_by_name;
void void
@ -191,7 +194,7 @@ VariantUserClassBase::find_cls_by_name (const std::string &name)
{ {
tl_assert (! s_user_type_by_name.empty ()); tl_assert (! s_user_type_by_name.empty ());
std::map <std::string, const VariantUserClassBase *>::const_iterator s = s_user_type_by_name.find (tl::to_lower_case (name)); auto s = s_user_type_by_name.find (tl::to_lower_case (name));
if (s == s_user_type_by_name.end ()) { if (s == s_user_type_by_name.end ()) {
return 0; return 0;
} }
@ -199,33 +202,94 @@ VariantUserClassBase::find_cls_by_name (const std::string &name)
return s->second; return s->second;
} }
// type-info based interface
const tl::VariantUserClassBase *VariantUserClassBase::instance (const std::type_info &type, bool is_const) const tl::VariantUserClassBase *VariantUserClassBase::instance (const std::type_info &type, bool is_const)
{ {
tl_assert (sp_class_table != 0); tl_assert (sp_class_table != 0);
std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *>::const_iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
tl_assert (c != sp_class_table->end ()); const tl::VariantUserClassBase *inst = 0;
return c->second;
auto c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
if (c == sp_class_table->end ()) {
// fallback: lookup by name and update if required - sometimes, there may be two different type info objects for the same thing
auto c2i = sp_class_index_by_name->find (std::make_pair (std::string (type.name ()), is_const));
tl_assert (c2i != sp_class_index_by_name->end ());
sp_class_table->insert (std::make_pair (VariantUserClassTableKey (type, is_const), c2i->second));
inst = sp_classes->operator[] (c2i->second);
} else {
inst = sp_classes->operator[] (c->second);
}
tl_assert (inst != 0);
return inst;
} }
void VariantUserClassBase::register_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const) void VariantUserClassBase::register_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const)
{ {
if (! sp_class_table) { if (! sp_class_table) {
sp_class_table = new std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *> (); sp_class_table = new std::map<VariantUserClassTableKey, size_t> ();
} }
(*sp_class_table)[VariantUserClassTableKey (type, is_const)] = inst; if (! sp_classes) {
sp_classes = new std::vector<const tl::VariantUserClassBase *> ();
}
if (! sp_class_index_by_name) {
sp_class_index_by_name = new std::map<std::pair<std::string, bool>, size_t> ();
}
if (! sp_class_to_index) {
sp_class_to_index = new std::map<const VariantUserClassBase *, size_t> ();
}
size_t index = sp_class_to_index->insert (std::make_pair (inst, sp_classes->size ())).first->second;
if (index == sp_classes->size ()) {
sp_classes->push_back (inst);
}
(*sp_class_table)[VariantUserClassTableKey (type, is_const)] = index;
(*sp_class_index_by_name) [std::make_pair (std::string (type.name ()), is_const)] = index;
} }
void VariantUserClassBase::unregister_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const) void VariantUserClassBase::unregister_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const)
{ {
if (sp_class_table) { if (sp_class_table) {
std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *>::iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
if (c != sp_class_table->end () && c->second == inst) { auto c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
if (c != sp_class_table->end ()) {
sp_class_table->erase (c); sp_class_table->erase (c);
sp_classes->operator[] (c->second) = 0;
while (!sp_classes->empty () && sp_classes->back () == 0) {
sp_classes->pop_back ();
}
} }
auto cn = sp_class_index_by_name->find (std::make_pair (std::string (type.name ()), is_const));
if (cn != sp_class_index_by_name->end ()) {
sp_class_index_by_name->erase (cn);
}
sp_class_to_index->erase (inst);
if (sp_class_table->empty ()) { if (sp_class_table->empty ()) {
delete sp_class_table; delete sp_class_table;
sp_class_table = 0; sp_class_table = 0;
} }
if (sp_classes->empty ()) {
delete sp_classes;
sp_classes = 0;
}
if (sp_class_index_by_name->empty ()) {
delete sp_class_index_by_name;
sp_class_index_by_name = 0;
}
if (sp_class_to_index->empty ()) {
delete sp_class_to_index;
sp_class_to_index = 0;
}
} }
} }