[PECOFF] Use std::set to store export symbol descriptors.

Each export symbol descriptor has unique name attribute, so std::set is
better container than std::vector for it. No functionality change.

llvm-svn: 198102
This commit is contained in:
Rui Ueyama 2013-12-28 08:11:21 +00:00
parent 51cff7199d
commit ad79838aa8
3 changed files with 36 additions and 25 deletions

View File

@ -59,6 +59,10 @@ public:
struct ExportDesc {
ExportDesc() : ordinal(-1), noname(false), isData(false) {}
bool operator<(const ExportDesc &other) const {
return name.compare(other.name) < 0;
}
std::string name;
int ordinal;
bool noname;
@ -218,8 +222,8 @@ public:
ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
void addDllExport(ExportDesc &desc);
std::vector<ExportDesc> &getDllExports() { return _dllExports; }
const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
std::set<ExportDesc> &getDllExports() { return _dllExports; }
const std::set<ExportDesc> &getDllExports() const { return _dllExports; }
StringRef allocate(StringRef ref) const {
char *x = _allocator.Allocate<char>(ref.size() + 1);
@ -299,8 +303,7 @@ private:
std::map<std::string, uint32_t> _sectionClearMask;
// DLLExport'ed symbols.
std::vector<ExportDesc> _dllExports;
std::set<StringRef> _dllExportSet;
std::set<ExportDesc> _dllExports;
// List of files that will be removed on destruction.
std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;

View File

@ -33,13 +33,17 @@
namespace lld {
static void assignOrdinals(PECOFFLinkingContext &ctx) {
std::set<PECOFFLinkingContext::ExportDesc> exports;
int maxOrdinal = -1;
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports())
maxOrdinal = std::max(maxOrdinal, desc.ordinal);
int nextOrdinal = (maxOrdinal == -1) ? 1 : (maxOrdinal + 1);
for (PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports())
for (PECOFFLinkingContext::ExportDesc desc : ctx.getDllExports()) {
if (desc.ordinal == -1)
desc.ordinal = nextOrdinal++;
exports.insert(desc);
}
ctx.getDllExports().swap(exports);
}
bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
@ -245,13 +249,12 @@ uint32_t PECOFFLinkingContext::getSectionAttributes(StringRef sectionName,
}
void PECOFFLinkingContext::addDllExport(ExportDesc &desc) {
if (_dllExportSet.count(desc.name)) {
auto exists = _dllExports.insert(desc);
if (!exists.second) {
llvm::errs() << "Export symbol '" << desc.name
<< "' specified more than once.\n";
return;
}
_dllExports.push_back(desc);
_dllExportSet.insert(_dllExports.back().name);
}
void PECOFFLinkingContext::addPasses(PassManager &pm) {

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/Support/COFF.h"
#include <set>
#include <vector>
using namespace llvm;
@ -158,39 +159,43 @@ TEST_F(WinLinkParserTest, AlternateName) {
TEST_F(WinLinkParserTest, Export) {
EXPECT_TRUE(parse("link.exe", "/export:foo", "a.out", nullptr));
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
_context.getDllExports();
EXPECT_EQ(1U, exports.size());
EXPECT_EQ("_foo", exports[0].name);
EXPECT_EQ(1, exports[0].ordinal);
EXPECT_FALSE(exports[0].noname);
EXPECT_FALSE(exports[0].isData);
auto it = exports.begin();
EXPECT_EQ("_foo", it->name);
EXPECT_EQ(1, it->ordinal);
EXPECT_FALSE(it->noname);
EXPECT_FALSE(it->isData);
}
TEST_F(WinLinkParserTest, ExportWithOptions) {
EXPECT_TRUE(parse("link.exe", "/export:foo,@8,noname,data",
"/export:bar,@10,data", "a.out", nullptr));
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
_context.getDllExports();
EXPECT_EQ(2U, exports.size());
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);
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);
}
TEST_F(WinLinkParserTest, ExportDuplicateExports) {
EXPECT_TRUE(
parse("link.exe", "/export:foo,@1", "/export:foo,@2", "a.out", nullptr));
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
const std::set<PECOFFLinkingContext::ExportDesc> &exports =
_context.getDllExports();
EXPECT_EQ(1U, exports.size());
EXPECT_EQ("_foo", exports[0].name);
EXPECT_EQ(1, exports[0].ordinal);
auto it = exports.begin();
EXPECT_EQ("_foo", it->name);
EXPECT_EQ(1, it->ordinal);
}
TEST_F(WinLinkParserTest, ExportDuplicateOrdinals) {