Skip to content

Commit 3168a62

Browse files
authored
[MLIR][Bytecode] Followup 8106c81 (#157136)
Addressed code review feedback: - Fixed some issues in the unit test - Adjusted line wrapping in the docs - Clarified comments in the bytecode reader
1 parent d67ab11 commit 3168a62

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

mlir/docs/BytecodeFormat.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ lazy-loading, and more. Each section contains a Section ID, whose high bit
125125
indicates if the section has alignment requirements, a length (which allows for
126126
skipping over the section), and an optional alignment. When an alignment is
127127
present, a variable number of padding bytes (0xCB) may appear before the section
128-
data. The alignment of a section must be a power of 2. The input bytecode buffer must satisfy the same alignment requirements as those of every section.
128+
data. The alignment of a section must be a power of 2.
129+
The input bytecode buffer must satisfy the same alignment requirements as
130+
those of every section.
129131

130132
## MLIR Encoding
131133

mlir/lib/Bytecode/Reader/BytecodeReader.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
#include "llvm/ADT/StringExtras.h"
2323
#include "llvm/ADT/StringRef.h"
2424
#include "llvm/Support/Endian.h"
25-
#include "llvm/Support/Format.h"
26-
#include "llvm/Support/LogicalResult.h"
2725
#include "llvm/Support/MemoryBufferRef.h"
2826
#include "llvm/Support/SourceMgr.h"
2927

@@ -296,12 +294,38 @@ class EncodingReader {
296294
if (failed(parseVarInt(alignment)))
297295
return failure();
298296

299-
// Check that the requested alignment is less than or equal to the
300-
// alignment of the root buffer. If it is not, we cannot safely guarantee
301-
// that the specified alignment is globally correct.
297+
// Check that the requested alignment must not exceed the alignment of
298+
// the root buffer itself. Otherwise we cannot guarantee that pointers
299+
// derived from this buffer will actually satisfy the requested alignment
300+
// globally.
302301
//
303-
// E.g. if the buffer is 8k aligned and the section is 16k aligned,
304-
// we could end up at an offset of 24k, which is not globally 16k aligned.
302+
// Consider a bytecode buffer that is guaranteed to be 8k aligned, but not
303+
// 16k aligned (e.g. absolute address 40960. If a section inside this
304+
// buffer declares a 16k alignment requirement, two problems can arise:
305+
//
306+
// (a) If we "align forward" the current pointer to the next
307+
// 16k boundary, the amount of padding we skip depends on the
308+
// buffer's starting address. For example:
309+
//
310+
// buffer_start = 40960
311+
// next 16k boundary = 49152
312+
// bytes skipped = 49152 - 40960 = 8192
313+
//
314+
// This leaves behind variable padding that could be misinterpreted
315+
// as part of the next section.
316+
//
317+
// (b) If we align relative to the buffer start, we may
318+
// obtain addresses that are multiples of "buffer_start +
319+
// section_alignment" rather than truly globally aligned
320+
// addresses. For example:
321+
//
322+
// buffer_start = 40960 (5×8k, 8k aligned but not 16k)
323+
// offset = 16384 (first multiple of 16k)
324+
// section_ptr = 40960 + 16384 = 57344
325+
//
326+
// 57344 is 8k aligned but not 16k aligned.
327+
// Any consumer expecting true 16k alignment would see this as a
328+
// violation.
305329
if (failed(alignmentValidator(alignment)))
306330
return emitError("failed to align section ID: ", unsigned(sectionID));
307331

mlir/unittests/Bytecode/BytecodeTest.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ TEST(Bytecode, MultiModuleWithResource) {
7272
ASSERT_TRUE(module);
7373

7474
// Write the module to bytecode.
75+
// Ensure that reserveExtraSpace is called with the size needed to write the
76+
// bytecode buffer.
7577
MockOstream ostream;
7678
EXPECT_CALL(ostream, reserveExtraSpace).WillOnce([&](uint64_t space) {
7779
ostream.buffer = std::make_unique<std::byte[]>(space);
@@ -128,31 +130,28 @@ TEST(Bytecode, AlignmentFailure) {
128130
ASSERT_TRUE(module);
129131

130132
// Write the module to bytecode.
131-
MockOstream ostream;
132-
EXPECT_CALL(ostream, reserveExtraSpace).WillOnce([&](uint64_t space) {
133-
ostream.buffer = std::make_unique<std::byte[]>(space);
134-
ostream.size = space;
135-
});
133+
std::string serializedBytecode;
134+
llvm::raw_string_ostream ostream(serializedBytecode);
136135
ASSERT_TRUE(succeeded(writeBytecodeToFile(module.get(), ostream)));
137136

138137
// Create copy of buffer which is not aligned to requested resource alignment.
139-
std::string buffer((char *)ostream.buffer.get(),
140-
(char *)ostream.buffer.get() + ostream.size);
138+
std::string buffer(serializedBytecode);
141139
size_t bufferSize = buffer.size();
142140

143-
// Increment into the buffer until we get to a power of 2 alignment that is
144-
// not 32 bit aligned.
141+
// Increment into the buffer until we get to an address that is 2 byte aligned
142+
// but not 32 byte aligned.
145143
size_t pad = 0;
146144
while (true) {
147-
if (llvm::isAddrAligned(Align(2), &buffer[pad]) &&
148-
!llvm::isAddrAligned(Align(32), &buffer[pad]))
145+
if (llvm::isAddrAligned(Align(2), buffer.data() + pad) &&
146+
!llvm::isAddrAligned(Align(32), buffer.data() + pad))
149147
break;
150148

151149
pad++;
152-
buffer.reserve(bufferSize + pad);
150+
// Pad the beginning of the buffer to push the start point to an unaligned
151+
// value.
152+
buffer.insert(0, 1, ' ');
153153
}
154154

155-
buffer.insert(0, pad, ' ');
156155
StringRef alignedBuffer(buffer.data() + pad, bufferSize);
157156

158157
// Attach a diagnostic handler to get the error message.

0 commit comments

Comments
 (0)