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::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::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::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::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::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::Edge, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
// ---------------------------------------------------------------------------------------------
// LocalProcessorResultComputationTask implementation

View File

@ -49,9 +49,11 @@ namespace {
// TODO: thread-safe? Unlikely that multiple threads access this member -
// 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 ti_to_class_map_t *sp_ti_to_class = 0;
// NOTE: MacOS/clang seems to have some issue with RTTI across shared objects. This map provides a name-based fallback
static std::vector<const ClassBase *> *sp_classes = 0;
typedef std::map<const ClassBase *, size_t> class_to_index_map_t;
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;
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);
// invalidate the "typeinfo to class" map
if (sp_ti_to_class) {
delete sp_ti_to_class;
sp_ti_to_class = 0;
if (sp_classes) {
delete sp_classes;
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) {
delete sp_tname_to_class;
@ -826,14 +836,25 @@ static void add_class_to_map (const gsi::ClassBase *c)
ti = &c->type ();
}
if (! sp_ti_to_class) {
sp_ti_to_class = new ti_to_class_map_t ();
if (! sp_classes) {
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) {
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
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
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)
{
if (! sp_ti_to_class || sp_ti_to_class->empty ()) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (! sp_ti_to_class_index || sp_ti_to_class_index->empty ()) {
for (auto c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
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-> ());
}
}
if (! sp_ti_to_class) {
if (! sp_ti_to_class_index) {
return 0;
} else {
ti_to_class_map_t::const_iterator c = sp_ti_to_class->find (&ti);
if (c != sp_ti_to_class->end ()) {
return c->second;
auto c = sp_ti_to_class_index->find (&ti);
if (c != sp_ti_to_class_index->end ()) {
return sp_classes->operator[] (c->second);
} else {
// 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 ()) {
// 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;
} else {
return 0;

View File

@ -144,22 +144,25 @@ struct VariantUserClassTableKey
if (is_const != k.is_const) {
return is_const < k.is_const;
}
if (*type != *k.type) {
return type->before (*k.type);
if (type != k.type) {
return type < k.type;
}
return false;
}
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;
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;
void
@ -191,7 +194,7 @@ VariantUserClassBase::find_cls_by_name (const std::string &name)
{
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 ()) {
return 0;
}
@ -199,33 +202,94 @@ VariantUserClassBase::find_cls_by_name (const std::string &name)
return s->second;
}
// type-info based interface
const tl::VariantUserClassBase *VariantUserClassBase::instance (const std::type_info &type, bool is_const)
{
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 ());
return c->second;
const tl::VariantUserClassBase *inst = 0;
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)
{
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)
{
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_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 ()) {
delete sp_class_table;
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;
}
}
}