[PECOFF] Change export table type.
This patch changes the type of export table set from std::set to std::vector. The new code is slightly inefficient, but because export table elements are actually mutable, std::vector is better here. No functionality change. llvm-svn: 218343
This commit is contained in:
parent
7ea46bab26
commit
75c0127bb3
|
@ -252,8 +252,8 @@ public:
|
|||
ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
|
||||
|
||||
void addDllExport(ExportDesc &desc);
|
||||
std::set<ExportDesc> &getDllExports() { return _dllExports; }
|
||||
const std::set<ExportDesc> &getDllExports() const { return _dllExports; }
|
||||
std::vector<ExportDesc> &getDllExports() { return _dllExports; }
|
||||
const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
|
||||
|
||||
StringRef allocate(StringRef ref) const {
|
||||
_allocMutex.lock();
|
||||
|
@ -385,7 +385,7 @@ private:
|
|||
std::map<std::string, uint32_t> _sectionClearMask;
|
||||
|
||||
// DLLExport'ed symbols.
|
||||
std::set<ExportDesc> _dllExports;
|
||||
std::vector<ExportDesc> _dllExports;
|
||||
|
||||
// List of files that will be removed on destruction.
|
||||
std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
|
||||
|
|
|
@ -29,17 +29,21 @@ namespace lld {
|
|||
namespace pecoff {
|
||||
|
||||
static void assignOrdinals(PECOFFLinkingContext &ctx) {
|
||||
std::set<PECOFFLinkingContext::ExportDesc> exports;
|
||||
std::vector<PECOFFLinkingContext::ExportDesc> &exports = ctx.getDllExports();
|
||||
int maxOrdinal = -1;
|
||||
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports())
|
||||
for (PECOFFLinkingContext::ExportDesc &desc : exports)
|
||||
maxOrdinal = std::max(maxOrdinal, desc.ordinal);
|
||||
|
||||
std::sort(exports.begin(), exports.end(),
|
||||
[](const PECOFFLinkingContext::ExportDesc &a,
|
||||
const PECOFFLinkingContext::ExportDesc &b) {
|
||||
return a.name.compare(b.name) < 0;
|
||||
});
|
||||
|
||||
int nextOrdinal = (maxOrdinal == -1) ? 1 : (maxOrdinal + 1);
|
||||
for (PECOFFLinkingContext::ExportDesc desc : ctx.getDllExports()) {
|
||||
for (PECOFFLinkingContext::ExportDesc &desc : exports)
|
||||
if (desc.ordinal == -1)
|
||||
desc.ordinal = nextOrdinal++;
|
||||
exports.insert(desc);
|
||||
}
|
||||
ctx.getDllExports().swap(exports);
|
||||
}
|
||||
|
||||
static StringRef removeStdcallSuffix(StringRef sym) {
|
||||
|
@ -63,8 +67,7 @@ static bool getExportedAtoms(PECOFFLinkingContext &ctx, MutableFile *file,
|
|||
for (const DefinedAtom *atom : file->defined())
|
||||
definedAtoms[removeStdcallSuffix(atom->name())] = atom;
|
||||
|
||||
std::set<PECOFFLinkingContext::ExportDesc> exports;
|
||||
for (PECOFFLinkingContext::ExportDesc desc : ctx.getDllExports()) {
|
||||
for (PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
|
||||
auto it = definedAtoms.find(desc.name);
|
||||
if (it == definedAtoms.end()) {
|
||||
llvm::errs() << "Symbol <" << desc.name
|
||||
|
@ -82,9 +85,7 @@ static bool getExportedAtoms(PECOFFLinkingContext &ctx, MutableFile *file,
|
|||
|
||||
if (desc.externalName.empty())
|
||||
desc.externalName = removeLeadingUnderscore(atom->name());
|
||||
exports.insert(desc);
|
||||
}
|
||||
ctx.getDllExports().swap(exports);
|
||||
std::sort(ret.begin(), ret.end(),
|
||||
[](const TableEntry &a, const TableEntry &b) {
|
||||
return a.exportName.compare(b.exportName) < 0;
|
||||
|
|
|
@ -272,11 +272,23 @@ static bool sameExportDesc(const PECOFFLinkingContext::ExportDesc &a,
|
|||
|
||||
void PECOFFLinkingContext::addDllExport(ExportDesc &desc) {
|
||||
addInitialUndefinedSymbol(allocate(desc.name));
|
||||
auto existing = _dllExports.insert(desc);
|
||||
if (existing.second || sameExportDesc(*existing.first, desc))
|
||||
|
||||
// Scan the vector to look for existing entry. It's not very fast,
|
||||
// but because the number of exported symbol is usually not that
|
||||
// much, it should be okay.
|
||||
ExportDesc *existing = nullptr;
|
||||
for (ExportDesc &e : _dllExports) {
|
||||
if (e.name == desc.name) {
|
||||
existing = &e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (existing && !sameExportDesc(*existing, desc)) {
|
||||
llvm::errs() << "Export symbol '" << desc.name
|
||||
<< "' specified more than once.\n";
|
||||
return;
|
||||
llvm::errs() << "Export symbol '" << desc.name
|
||||
<< "' specified more than once.\n";
|
||||
}
|
||||
_dllExports.push_back(desc);
|
||||
}
|
||||
|
||||
std::string PECOFFLinkingContext::getOutputImportLibraryPath() const {
|
||||
|
|
|
@ -158,43 +158,39 @@ TEST_F(WinLinkParserTest, AlternateName) {
|
|||
|
||||
TEST_F(WinLinkParserTest, Export) {
|
||||
EXPECT_TRUE(parse("link.exe", "/export:foo", "a.out", nullptr));
|
||||
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
_context.getDllExports();
|
||||
EXPECT_EQ(1U, exports.size());
|
||||
auto it = exports.begin();
|
||||
EXPECT_EQ("_foo", it->name);
|
||||
EXPECT_EQ(-1, it->ordinal);
|
||||
EXPECT_FALSE(it->noname);
|
||||
EXPECT_FALSE(it->isData);
|
||||
EXPECT_EQ("_foo", exports[0].name);
|
||||
EXPECT_EQ(-1, exports[0].ordinal);
|
||||
EXPECT_FALSE(exports[0].noname);
|
||||
EXPECT_FALSE(exports[0].isData);
|
||||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, ExportWithOptions) {
|
||||
EXPECT_TRUE(parse("link.exe", "/export:foo,@8,noname,data",
|
||||
"/export:bar,@10,data", "a.out", nullptr));
|
||||
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
_context.getDllExports();
|
||||
EXPECT_EQ(2U, exports.size());
|
||||
auto it = exports.begin();
|
||||
EXPECT_EQ("_bar", it->name);
|
||||
EXPECT_EQ(10, it->ordinal);
|
||||
EXPECT_FALSE(it->noname);
|
||||
EXPECT_TRUE(it->isData);
|
||||
++it;
|
||||
EXPECT_EQ("_foo", it->name);
|
||||
EXPECT_EQ(8, it->ordinal);
|
||||
EXPECT_TRUE(it->noname);
|
||||
EXPECT_TRUE(it->isData);
|
||||
EXPECT_EQ("_foo", exports[0].name);
|
||||
EXPECT_EQ(8, exports[0].ordinal);
|
||||
EXPECT_TRUE(exports[0].noname);
|
||||
EXPECT_TRUE(exports[0].isData);
|
||||
EXPECT_EQ("_bar", exports[1].name);
|
||||
EXPECT_EQ(10, exports[1].ordinal);
|
||||
EXPECT_FALSE(exports[1].noname);
|
||||
EXPECT_TRUE(exports[1].isData);
|
||||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, ExportDuplicateExports) {
|
||||
EXPECT_TRUE(
|
||||
parse("link.exe", "/export:foo", "/export:foo,@2", "a.out", nullptr));
|
||||
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
_context.getDllExports();
|
||||
EXPECT_EQ(1U, exports.size());
|
||||
auto it = exports.begin();
|
||||
EXPECT_EQ("_foo", it->name);
|
||||
EXPECT_EQ(-1, it->ordinal);
|
||||
EXPECT_EQ("_foo", exports[0].name);
|
||||
EXPECT_EQ(-1, exports[0].ordinal);
|
||||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, ExportDuplicateOrdinals) {
|
||||
|
|
Loading…
Reference in New Issue