Skip to content

Commit

Permalink
[JITLink] Add convenience methods for creating block readers / writers.
Browse files Browse the repository at this point in the history
This saves clients some boilerplate compared to setting up the readers and
writers manually.

To obtain a BinaryStreamWriter / BinaryStreamReader for a given block, B,
clients can now write:

auto Reader = G.getBlockContentReader(B);

and

auto Writer = G.getBlockContentWriter(B);

The latter will trigger a copy to mutable memory allocated on the graph's
allocator if the block is currently marked as backed by read-only memory.

This commit also introduces a new createMutableContentBlock overload that
creates a block with a given size and zero-filled content (by default --
passing false for the ZeroInitialize bypasses initialization entirely).
This overload is intended to be used with getBlockContentWriter above when
creating new content for the graph.
  • Loading branch information
lhames committed Oct 18, 2022
1 parent b96cbbd commit 5f15479
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
32 changes: 32 additions & 0 deletions llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
Expand Up @@ -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"
Expand Down Expand Up @@ -1031,13 +1033,43 @@ 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,
uint64_t AlignmentOffset) {
return createBlock(Parent, Size, Address, Alignment, AlignmentOffset);
}

/// Returns a BinaryStreamReader for the given block.
BinaryStreamReader getBlockContentReader(Block &B) {
ArrayRef<uint8_t> C(
reinterpret_cast<const uint8_t *>(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<uint8_t> C(
reinterpret_cast<uint8_t *>(B.getMutableContent(*this).data()),
B.getSize());
return BinaryStreamWriter(C, getEndianness());
}

/// Cache type for the splitBlock function.
using SplitBlockCache = Optional<SmallVector<Symbol *, 8>>;

Expand Down
12 changes: 12 additions & 0 deletions llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 5f15479

Please sign in to comment.