Loading llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +95 −37 Original line number Diff line number Diff line Loading @@ -562,6 +562,16 @@ public: /// Returns the ordinal for this section. SectionOrdinal getOrdinal() const { return SecOrdinal; } /// Returns an iterator over the blocks defined in this section. iterator_range<block_iterator> blocks() { return make_range(Blocks.begin(), Blocks.end()); } /// Returns an iterator over the blocks defined in this section. iterator_range<const_block_iterator> blocks() const { return make_range(Blocks.begin(), Blocks.end()); } /// Returns an iterator over the symbols defined in this section. iterator_range<symbol_iterator> symbols() { return make_range(Symbols.begin(), Symbols.end()); Loading Loading @@ -592,10 +602,21 @@ private: Symbols.erase(&Sym); } void addBlock(Block &B) { assert(!Blocks.count(&B) && "Block is already in this section"); Blocks.insert(&B); } void removeBlock(Block &B) { assert(Blocks.count(&B) && "Block is not in this section"); Blocks.erase(&B); } StringRef Name; sys::Memory::ProtectionFlags Prot; SectionOrdinal SecOrdinal = 0; BlockOrdinal NextBlockOrdinal = 0; BlockSet Blocks; SymbolSet Symbols; }; Loading Loading @@ -663,12 +684,11 @@ private: template <typename... ArgTs> Block &createBlock(ArgTs &&... Args) { Block *B = reinterpret_cast<Block *>(Allocator.Allocate<Block>()); new (B) Block(std::forward<ArgTs>(Args)...); Blocks.insert(B); B->getSection().addBlock(*B); return *B; } void destroyBlock(Block &B) { Blocks.erase(&B); B.~Block(); Allocator.Deallocate(&B); } Loading @@ -678,69 +698,102 @@ private: Allocator.Deallocate(&S); } static iterator_range<Section::block_iterator> getSectionBlocks(Section &S) { return S.blocks(); } static iterator_range<Section::const_block_iterator> getSectionConstBlocks(Section &S) { return S.blocks(); } static iterator_range<Section::symbol_iterator> getSectionSymbols(Section &S) { return S.symbols(); } static iterator_range<Section::const_symbol_iterator> getSectionConstSymbols(Section &S) { return S.symbols(); } public: using external_symbol_iterator = ExternalSymbolSet::iterator; using block_iterator = BlockSet::iterator; using section_iterator = pointee_iterator<SectionList::iterator>; using const_section_iterator = pointee_iterator<SectionList::const_iterator>; template <typename SectionItrT, typename SymbolItrT, typename T> class defined_symbol_iterator_impl template <typename OuterItrT, typename InnerItrT, typename T, iterator_range<InnerItrT> getInnerRange( typename OuterItrT::reference)> class nested_collection_iterator : public iterator_facade_base< defined_symbol_iterator_impl<SectionItrT, SymbolItrT, T>, nested_collection_iterator<OuterItrT, InnerItrT, T, getInnerRange>, std::forward_iterator_tag, T> { public: defined_symbol_iterator_impl() = default; nested_collection_iterator() = default; defined_symbol_iterator_impl(SectionItrT SecI, SectionItrT SecE) : SecI(SecI), SecE(SecE), SymI(SecI != SecE ? SecI->symbols().begin() : SymbolItrT()) { moveToNextSymbolOrEnd(); nested_collection_iterator(OuterItrT OuterI, OuterItrT OuterE) : OuterI(OuterI), OuterE(OuterE), InnerI(getInnerBegin(OuterI, OuterE)) { moveToNonEmptyInnerOrEnd(); } bool operator==(const defined_symbol_iterator_impl &RHS) const { return (SecI == RHS.SecI) && (SymI == RHS.SymI); bool operator==(const nested_collection_iterator &RHS) const { return (OuterI == RHS.OuterI) && (InnerI == RHS.InnerI); } T operator*() const { assert(SymI != SecI->symbols().end() && "Dereferencing end?"); return *SymI; assert(InnerI != getInnerRange(*OuterI).end() && "Dereferencing end?"); return *InnerI; } defined_symbol_iterator_impl operator++() { ++SymI; moveToNextSymbolOrEnd(); nested_collection_iterator operator++() { ++InnerI; moveToNonEmptyInnerOrEnd(); return *this; } private: void moveToNextSymbolOrEnd() { while (SecI != SecE && SymI == SecI->symbols().end()) { ++SecI; SymI = SecI == SecE ? SymbolItrT() : SecI->symbols().begin(); static InnerItrT getInnerBegin(OuterItrT OuterI, OuterItrT OuterE) { return OuterI != OuterE ? getInnerRange(*OuterI).begin() : InnerItrT(); } void moveToNonEmptyInnerOrEnd() { while (OuterI != OuterE && InnerI == getInnerRange(*OuterI).end()) { ++OuterI; InnerI = getInnerBegin(OuterI, OuterE); } } SectionItrT SecI, SecE; SymbolItrT SymI; OuterItrT OuterI, OuterE; InnerItrT InnerI; }; using defined_symbol_iterator = defined_symbol_iterator_impl<const_section_iterator, Section::symbol_iterator, Symbol *>; nested_collection_iterator<const_section_iterator, Section::symbol_iterator, Symbol *, getSectionSymbols>; using const_defined_symbol_iterator = nested_collection_iterator<const_section_iterator, Section::const_symbol_iterator, const Symbol *, getSectionConstSymbols>; using block_iterator = nested_collection_iterator<const_section_iterator, Section::block_iterator, Block *, getSectionBlocks>; using const_defined_symbol_iterator = defined_symbol_iterator_impl< const_section_iterator, Section::const_symbol_iterator, const Symbol *>; using const_block_iterator = nested_collection_iterator<const_section_iterator, Section::const_block_iterator, const Block *, getSectionConstBlocks>; LinkGraph(std::string Name, unsigned PointerSize, support::endianness Endianness) : Name(std::move(Name)), PointerSize(PointerSize), Endianness(Endianness) {} ~LinkGraph(); /// Returns the name of this graph (usually the name of the original /// underlying MemoryBuffer). const std::string &getName() { return Name; } Loading Loading @@ -864,6 +917,16 @@ public: return nullptr; } iterator_range<block_iterator> blocks() { return make_range(block_iterator(Sections.begin(), Sections.end()), block_iterator(Sections.end(), Sections.end())); } iterator_range<const_block_iterator> blocks() const { return make_range(const_block_iterator(Sections.begin(), Sections.end()), const_block_iterator(Sections.end(), Sections.end())); } iterator_range<external_symbol_iterator> external_symbols() { return make_range(ExternalSymbols.begin(), ExternalSymbols.end()); } Loading @@ -883,10 +946,6 @@ public: const_defined_symbol_iterator(Sections.end(), Sections.end())); } iterator_range<block_iterator> blocks() { return make_range(Blocks.begin(), Blocks.end()); } /// Turn a defined symbol into an external one. void makeExternal(Symbol &Sym) { if (Sym.getAddressable().isAbsolute()) { Loading Loading @@ -934,7 +993,7 @@ public: /// Remove a block. void removeBlock(Block &B) { Blocks.erase(&B); B.getSection().removeBlock(B); destroyBlock(B); } Loading @@ -955,7 +1014,6 @@ private: std::string Name; unsigned PointerSize; support::endianness Endianness; BlockSet Blocks; SectionList Sections; ExternalSymbolSet ExternalSymbols; ExternalSymbolSet AbsoluteSymbols; Loading llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -145,10 +145,6 @@ void printEdge(raw_ostream &OS, const Block &B, const Edge &E, Section::~Section() { for (auto *Sym : Symbols) Sym->~Symbol(); } LinkGraph::~LinkGraph() { // Destroy blocks. for (auto *B : Blocks) B->~Block(); } Loading llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp +57 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ using namespace llvm; using namespace llvm::jitlink; static auto RWFlags = sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE); TEST(LinkGraphTest, Construction) { // Check that LinkGraph construction works as expected. LinkGraph G("foo", 8, support::little); Loading @@ -27,6 +30,59 @@ TEST(LinkGraphTest, Construction) { EXPECT_TRUE(llvm::empty(G.blocks())); } TEST(LinkGraphTest, BlockAndSymbolIteration) { // Check that we can iterate over blocks within Sections and across sections. const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x00}; StringRef BlockContent(BlockContentBytes); LinkGraph G("foo", 8, support::little); auto &Sec1 = G.createSection("__data.1", RWFlags); auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0); auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0); auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, false, false); auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default, false, false); auto &Sec2 = G.createSection("__data.1", RWFlags); auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0); auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0); auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default, false, false); auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default, false, false); // Check that iteration of blocks within a section behaves as expected. EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2U); EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1)); EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2)); // Check that iteration of symbols within a section behaves as expected. EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2U); EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1)); EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2)); // Check that iteration of blocks across sections behaves as expected. EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4U); EXPECT_TRUE(llvm::count(G.blocks(), &B1)); EXPECT_TRUE(llvm::count(G.blocks(), &B2)); EXPECT_TRUE(llvm::count(G.blocks(), &B3)); EXPECT_TRUE(llvm::count(G.blocks(), &B4)); // Check that iteration of defined symbols across sections behaves as // expected. EXPECT_EQ( std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4U); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4)); } TEST(LinkGraphTest, SplitBlock) { // Check that the LinkGraph::splitBlock test works as expected. Loading @@ -36,9 +92,7 @@ TEST(LinkGraphTest, SplitBlock) { StringRef BlockContent(BlockContentBytes); LinkGraph G("foo", 8, support::little); auto &Sec = G.createSection( "test", sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE)); auto &Sec = G.createSection("__data", RWFlags); // Create the block to split. auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); Loading Loading
llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +95 −37 Original line number Diff line number Diff line Loading @@ -562,6 +562,16 @@ public: /// Returns the ordinal for this section. SectionOrdinal getOrdinal() const { return SecOrdinal; } /// Returns an iterator over the blocks defined in this section. iterator_range<block_iterator> blocks() { return make_range(Blocks.begin(), Blocks.end()); } /// Returns an iterator over the blocks defined in this section. iterator_range<const_block_iterator> blocks() const { return make_range(Blocks.begin(), Blocks.end()); } /// Returns an iterator over the symbols defined in this section. iterator_range<symbol_iterator> symbols() { return make_range(Symbols.begin(), Symbols.end()); Loading Loading @@ -592,10 +602,21 @@ private: Symbols.erase(&Sym); } void addBlock(Block &B) { assert(!Blocks.count(&B) && "Block is already in this section"); Blocks.insert(&B); } void removeBlock(Block &B) { assert(Blocks.count(&B) && "Block is not in this section"); Blocks.erase(&B); } StringRef Name; sys::Memory::ProtectionFlags Prot; SectionOrdinal SecOrdinal = 0; BlockOrdinal NextBlockOrdinal = 0; BlockSet Blocks; SymbolSet Symbols; }; Loading Loading @@ -663,12 +684,11 @@ private: template <typename... ArgTs> Block &createBlock(ArgTs &&... Args) { Block *B = reinterpret_cast<Block *>(Allocator.Allocate<Block>()); new (B) Block(std::forward<ArgTs>(Args)...); Blocks.insert(B); B->getSection().addBlock(*B); return *B; } void destroyBlock(Block &B) { Blocks.erase(&B); B.~Block(); Allocator.Deallocate(&B); } Loading @@ -678,69 +698,102 @@ private: Allocator.Deallocate(&S); } static iterator_range<Section::block_iterator> getSectionBlocks(Section &S) { return S.blocks(); } static iterator_range<Section::const_block_iterator> getSectionConstBlocks(Section &S) { return S.blocks(); } static iterator_range<Section::symbol_iterator> getSectionSymbols(Section &S) { return S.symbols(); } static iterator_range<Section::const_symbol_iterator> getSectionConstSymbols(Section &S) { return S.symbols(); } public: using external_symbol_iterator = ExternalSymbolSet::iterator; using block_iterator = BlockSet::iterator; using section_iterator = pointee_iterator<SectionList::iterator>; using const_section_iterator = pointee_iterator<SectionList::const_iterator>; template <typename SectionItrT, typename SymbolItrT, typename T> class defined_symbol_iterator_impl template <typename OuterItrT, typename InnerItrT, typename T, iterator_range<InnerItrT> getInnerRange( typename OuterItrT::reference)> class nested_collection_iterator : public iterator_facade_base< defined_symbol_iterator_impl<SectionItrT, SymbolItrT, T>, nested_collection_iterator<OuterItrT, InnerItrT, T, getInnerRange>, std::forward_iterator_tag, T> { public: defined_symbol_iterator_impl() = default; nested_collection_iterator() = default; defined_symbol_iterator_impl(SectionItrT SecI, SectionItrT SecE) : SecI(SecI), SecE(SecE), SymI(SecI != SecE ? SecI->symbols().begin() : SymbolItrT()) { moveToNextSymbolOrEnd(); nested_collection_iterator(OuterItrT OuterI, OuterItrT OuterE) : OuterI(OuterI), OuterE(OuterE), InnerI(getInnerBegin(OuterI, OuterE)) { moveToNonEmptyInnerOrEnd(); } bool operator==(const defined_symbol_iterator_impl &RHS) const { return (SecI == RHS.SecI) && (SymI == RHS.SymI); bool operator==(const nested_collection_iterator &RHS) const { return (OuterI == RHS.OuterI) && (InnerI == RHS.InnerI); } T operator*() const { assert(SymI != SecI->symbols().end() && "Dereferencing end?"); return *SymI; assert(InnerI != getInnerRange(*OuterI).end() && "Dereferencing end?"); return *InnerI; } defined_symbol_iterator_impl operator++() { ++SymI; moveToNextSymbolOrEnd(); nested_collection_iterator operator++() { ++InnerI; moveToNonEmptyInnerOrEnd(); return *this; } private: void moveToNextSymbolOrEnd() { while (SecI != SecE && SymI == SecI->symbols().end()) { ++SecI; SymI = SecI == SecE ? SymbolItrT() : SecI->symbols().begin(); static InnerItrT getInnerBegin(OuterItrT OuterI, OuterItrT OuterE) { return OuterI != OuterE ? getInnerRange(*OuterI).begin() : InnerItrT(); } void moveToNonEmptyInnerOrEnd() { while (OuterI != OuterE && InnerI == getInnerRange(*OuterI).end()) { ++OuterI; InnerI = getInnerBegin(OuterI, OuterE); } } SectionItrT SecI, SecE; SymbolItrT SymI; OuterItrT OuterI, OuterE; InnerItrT InnerI; }; using defined_symbol_iterator = defined_symbol_iterator_impl<const_section_iterator, Section::symbol_iterator, Symbol *>; nested_collection_iterator<const_section_iterator, Section::symbol_iterator, Symbol *, getSectionSymbols>; using const_defined_symbol_iterator = nested_collection_iterator<const_section_iterator, Section::const_symbol_iterator, const Symbol *, getSectionConstSymbols>; using block_iterator = nested_collection_iterator<const_section_iterator, Section::block_iterator, Block *, getSectionBlocks>; using const_defined_symbol_iterator = defined_symbol_iterator_impl< const_section_iterator, Section::const_symbol_iterator, const Symbol *>; using const_block_iterator = nested_collection_iterator<const_section_iterator, Section::const_block_iterator, const Block *, getSectionConstBlocks>; LinkGraph(std::string Name, unsigned PointerSize, support::endianness Endianness) : Name(std::move(Name)), PointerSize(PointerSize), Endianness(Endianness) {} ~LinkGraph(); /// Returns the name of this graph (usually the name of the original /// underlying MemoryBuffer). const std::string &getName() { return Name; } Loading Loading @@ -864,6 +917,16 @@ public: return nullptr; } iterator_range<block_iterator> blocks() { return make_range(block_iterator(Sections.begin(), Sections.end()), block_iterator(Sections.end(), Sections.end())); } iterator_range<const_block_iterator> blocks() const { return make_range(const_block_iterator(Sections.begin(), Sections.end()), const_block_iterator(Sections.end(), Sections.end())); } iterator_range<external_symbol_iterator> external_symbols() { return make_range(ExternalSymbols.begin(), ExternalSymbols.end()); } Loading @@ -883,10 +946,6 @@ public: const_defined_symbol_iterator(Sections.end(), Sections.end())); } iterator_range<block_iterator> blocks() { return make_range(Blocks.begin(), Blocks.end()); } /// Turn a defined symbol into an external one. void makeExternal(Symbol &Sym) { if (Sym.getAddressable().isAbsolute()) { Loading Loading @@ -934,7 +993,7 @@ public: /// Remove a block. void removeBlock(Block &B) { Blocks.erase(&B); B.getSection().removeBlock(B); destroyBlock(B); } Loading @@ -955,7 +1014,6 @@ private: std::string Name; unsigned PointerSize; support::endianness Endianness; BlockSet Blocks; SectionList Sections; ExternalSymbolSet ExternalSymbols; ExternalSymbolSet AbsoluteSymbols; Loading
llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -145,10 +145,6 @@ void printEdge(raw_ostream &OS, const Block &B, const Edge &E, Section::~Section() { for (auto *Sym : Symbols) Sym->~Symbol(); } LinkGraph::~LinkGraph() { // Destroy blocks. for (auto *B : Blocks) B->~Block(); } Loading
llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp +57 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ using namespace llvm; using namespace llvm::jitlink; static auto RWFlags = sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE); TEST(LinkGraphTest, Construction) { // Check that LinkGraph construction works as expected. LinkGraph G("foo", 8, support::little); Loading @@ -27,6 +30,59 @@ TEST(LinkGraphTest, Construction) { EXPECT_TRUE(llvm::empty(G.blocks())); } TEST(LinkGraphTest, BlockAndSymbolIteration) { // Check that we can iterate over blocks within Sections and across sections. const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x00}; StringRef BlockContent(BlockContentBytes); LinkGraph G("foo", 8, support::little); auto &Sec1 = G.createSection("__data.1", RWFlags); auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0); auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0); auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, false, false); auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default, false, false); auto &Sec2 = G.createSection("__data.1", RWFlags); auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0); auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0); auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default, false, false); auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default, false, false); // Check that iteration of blocks within a section behaves as expected. EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2U); EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1)); EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2)); // Check that iteration of symbols within a section behaves as expected. EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2U); EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1)); EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2)); // Check that iteration of blocks across sections behaves as expected. EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4U); EXPECT_TRUE(llvm::count(G.blocks(), &B1)); EXPECT_TRUE(llvm::count(G.blocks(), &B2)); EXPECT_TRUE(llvm::count(G.blocks(), &B3)); EXPECT_TRUE(llvm::count(G.blocks(), &B4)); // Check that iteration of defined symbols across sections behaves as // expected. EXPECT_EQ( std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4U); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3)); EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4)); } TEST(LinkGraphTest, SplitBlock) { // Check that the LinkGraph::splitBlock test works as expected. Loading @@ -36,9 +92,7 @@ TEST(LinkGraphTest, SplitBlock) { StringRef BlockContent(BlockContentBytes); LinkGraph G("foo", 8, support::little); auto &Sec = G.createSection( "test", sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE)); auto &Sec = G.createSection("__data", RWFlags); // Create the block to split. auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); Loading