diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 7f8dd7303050fd..f6e7706a7e9e33 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -22,6 +22,8 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" @@ -1031,6 +1033,20 @@ class LinkGraph { AlignmentOffset); } + /// Create a content block with initially mutable data of the given size. + /// Content will be allocated via the LinkGraph's allocateBuffer method. + /// By default the memory will be zero-initialized. Passing false for + /// ZeroInitialize will prevent this. + Block &createMutableContentBlock(Section &Parent, size_t ContentSize, + orc::ExecutorAddr Address, + uint64_t Alignment, uint64_t AlignmentOffset, + bool ZeroInitialize = true) { + auto Content = allocateContent(ContentSize); + if (ZeroInitialize) + memset(Content.data(), 0, Content.size()); + return createBlock(Parent, Content, Address, Alignment, AlignmentOffset); + } + /// Create a zero-fill block. Block &createZeroFillBlock(Section &Parent, orc::ExecutorAddrDiff Size, orc::ExecutorAddr Address, uint64_t Alignment, @@ -1038,6 +1054,22 @@ class LinkGraph { return createBlock(Parent, Size, Address, Alignment, AlignmentOffset); } + /// Returns a BinaryStreamReader for the given block. + BinaryStreamReader getBlockContentReader(Block &B) { + ArrayRef C( + reinterpret_cast(B.getContent().data()), B.getSize()); + return BinaryStreamReader(C, getEndianness()); + } + + /// Returns a BinaryStreamWriter for the given block. + /// This will call getMutableContent to obtain mutable content for the block. + BinaryStreamWriter getBlockContentWriter(Block &B) { + MutableArrayRef C( + reinterpret_cast(B.getMutableContent(*this).data()), + B.getSize()); + return BinaryStreamWriter(C, getEndianness()); + } + /// Cache type for the splitBlock function. using SplitBlockCache = Optional>; diff --git a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp index bbb93ceb4b2432..c16757d7c55af1 100644 --- a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp +++ b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp @@ -10,6 +10,8 @@ #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Memory.h" + +#include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" using namespace llvm; @@ -196,6 +198,16 @@ TEST(LinkGraphTest, ContentAccessAndUpdate) { EXPECT_EQ(MutableContent3.size(), MutableContent.size()) << "Unexpected mutable content 2 size"; + // Check that we can obtain a writer and reader over the content. + // Check that we can get a BinaryStreamReader for B. + auto Writer = G.getBlockContentWriter(B); + EXPECT_THAT_ERROR(Writer.writeInteger((uint32_t)0xcafef00d), Succeeded()); + + auto Reader = G.getBlockContentReader(B); + uint32_t Initial32Bits = 0; + EXPECT_THAT_ERROR(Reader.readInteger(Initial32Bits), Succeeded()); + EXPECT_EQ(Initial32Bits, (uint32_t)0xcafef00d); + // Set content back to immutable and check that everything behaves as // expected again. B.setContent(BlockContent);