From c95a59f75e5ed0ba23b0cf39db6e29d865a869aa Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Fri, 29 Sep 2017 15:15:48 +0200 Subject: [PATCH] ConvertOBJ: sort modules to go easy on 16-bit relative references --- ConvertObj/ConvertObj.cc | 87 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/ConvertObj/ConvertObj.cc b/ConvertObj/ConvertObj.cc index 20c5726ef5..4e15620688 100644 --- a/ConvertObj/ConvertObj.cc +++ b/ConvertObj/ConvertObj.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "BinaryIO.h" #include @@ -66,6 +67,8 @@ struct Module unordered_map> labels; unordered_map relocs; + std::vector> nearrefs; + void write(std::ostream& out); }; @@ -137,12 +140,83 @@ void Module::write(std::ostream& out) out << "# ######\n\n"; } +void sortModules(std::vector>& modules) +{ + std::unordered_set> unemitted; + for(auto& m : modules) + unemitted.insert(m); + + std::unordered_map> nameMap; + for(auto& m : modules) + for(auto& l : m->labels) + for(auto& str : l.second) + nameMap[str] = m; + + + for(auto& m : modules) + for(auto& r : m->relocs) + { + if(r.second.size != 2) + continue; + if(r.second.name2.empty()) + { + std::shared_ptr m1; + m1 = nameMap.find(r.second.name1)->second; + m1->nearrefs.push_back(m); + m->nearrefs.push_back(m1); + } + else + { + std::shared_ptr m1; + m1 = nameMap.find(r.second.name1)->second; + std::shared_ptr m2; + m2 = nameMap.find(r.second.name2)->second; + m1->nearrefs.push_back(m2); + m2->nearrefs.push_back(m1); + } + } + + + std::vector> sorted; + sorted.reserve(modules.size()); + + auto p = sorted.begin(); + + while(!unemitted.empty()) + { + while(p != sorted.end()) + { + for(auto& m2weak : (*p)->nearrefs) + { + if(std::shared_ptr m2 = m2weak.lock()) + { + auto unemittedP = unemitted.find(m2); + if(unemittedP != unemitted.end()) + { + sorted.push_back(m2); + unemitted.erase(unemittedP); + } + } + } + ++p; + } + sorted.push_back(*unemitted.begin()); + unemitted.erase(unemitted.begin()); + } + + sorted.swap(modules); +} + int main(int argc, char* argv[]) { std::ifstream in(argv[1]); unordered_map stringDictionary; - std::unique_ptr module; + + bool shouldSortModules = true; + + std::shared_ptr module; + std::vector> modules; std::cout << "\t.text\n\t.align 2\n"; @@ -206,12 +280,10 @@ int main(int argc, char* argv[]) if(verbose) std::cerr << "Module " << name << "(" << segment << "), flags = " << flags << "\n"; - if(module) - module->write(std::cout); - module.reset(new Module()); module->name = name; module->labels[0].push_back(name); + modules.push_back(module); } break; case kContent: @@ -311,14 +383,15 @@ int main(int argc, char* argv[]) case kLast: byte(in); endOfObject = true; - if(module) - module->write(std::cout); break; default: std::cerr << "Unknown record (type " << recordType << ") at " << std::hex << in.tellg() << std::endl; return 1; } } - + if(shouldSortModules) + sortModules(modules); + for(auto& m : modules) + m->write(std::cout); return 0; }