[orc-rt] Add endian_read/write operations. (#166892)

The endian_read and endian_write operations read and write unsigned
integers stored in a given endianness.
This commit is contained in:
Lang Hames
2025-11-07 18:25:04 +11:00
committed by GitHub
parent 3aa7a24263
commit c8adbd7a8b
3 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
//===----- Endian.h - Endianness helpers for the ORC runtime ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Endianness helper functions for the ORC runtime.
//
//===----------------------------------------------------------------------===//
#ifndef ORC_RT_ENDIAN_H
#define ORC_RT_ENDIAN_H
#include "bit.h"
#include <cstring>
#include <type_traits>
namespace orc_rt {
/// Read a value with the given endianness from memory.
template <typename T>
[[nodiscard]] inline std::enable_if_t<std::is_integral_v<T>, T>
endian_read(const void *Src, orc_rt::endian E) noexcept {
T Val;
memcpy(&Val, Src, sizeof(T));
if (E != orc_rt::endian::native)
Val = orc_rt::byteswap(Val);
return Val;
}
/// Write a value with the given endianness to memory.
template <typename T>
inline std::enable_if_t<std::is_integral_v<T>>
endian_write(void *Dst, T Val, orc_rt::endian E) noexcept {
if (E != orc_rt::endian::native)
Val = orc_rt::byteswap(Val);
memcpy(Dst, &Val, sizeof(T));
}
} // namespace orc_rt
#endif // ORC_RT_ENDIAN_H

View File

@@ -15,6 +15,7 @@ add_orc_rt_unittest(CoreTests
AllocActionTest.cpp
BitmaskEnumTest.cpp
CallableTraitsHelperTest.cpp
EndianTest.cpp
ErrorTest.cpp
ExecutorAddressTest.cpp
IntervalMapTest.cpp

View File

@@ -0,0 +1,100 @@
//===- EndianTest.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Tests for orc-rt's Endian.h APIs.
//
//===----------------------------------------------------------------------===//
#include "orc-rt/Endian.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <limits>
using namespace orc_rt;
template <typename T> static void endianRead(T Value, endian E) {
char Buffer[sizeof(T)];
memcpy(Buffer, &Value, sizeof(T));
if (E != endian::native)
std::reverse(Buffer, Buffer + sizeof(T));
T NewVal = endian_read<T>(Buffer, E);
EXPECT_EQ(NewVal, Value);
}
template <typename T> static void endianWrite(T Value, endian E) {
char Buffer[sizeof(T)];
endian_write(Buffer, Value, E);
if (E != endian::native)
std::reverse(Buffer, Buffer + sizeof(T));
T NewVal;
memcpy(&NewVal, Buffer, sizeof(T));
EXPECT_EQ(NewVal, Value);
}
template <typename T> static void endianReadAndWrite(T Value, endian E) {
endianRead(Value, E);
endianWrite(Value, E);
}
template <typename T> static void bothEndiansReadAndWrite(T Value) {
endianReadAndWrite(Value, endian::little);
endianReadAndWrite(Value, endian::big);
}
// Rotate the given bit pattern through all valid rotations for T, testing that
// the given operation works for the given pattern.
template <typename Op, typename T>
void forAllRotatedValues(Op O, T InitialValue) {
T V = InitialValue;
for (size_t I = 0; I != CHAR_BIT * sizeof(T); ++I) {
O(V);
V = llvm::rotl(V, 1);
}
}
template <typename Op, typename T>
void forAllShiftedValues(Op O, T InitialValue) {
T V = InitialValue;
constexpr T TopValueBit = 1 << (std::numeric_limits<T>::digits - 1);
for (size_t I = 0; I != CHAR_BIT * sizeof(T); ++I) {
O(V);
if (V & TopValueBit)
break;
V << 1;
}
}
TEST(EndianTest, ReadWrite) {
bothEndiansReadAndWrite<uint8_t>(0);
bothEndiansReadAndWrite<uint8_t>(0xff);
forAllRotatedValues(bothEndiansReadAndWrite<uint8_t>, uint8_t(1));
forAllRotatedValues(bothEndiansReadAndWrite<uint8_t>, uint8_t(0x5A));
bothEndiansReadAndWrite<uint16_t>(0);
bothEndiansReadAndWrite<uint16_t>(0xffff);
forAllRotatedValues(bothEndiansReadAndWrite<uint16_t>, uint16_t(1));
forAllRotatedValues(bothEndiansReadAndWrite<uint16_t>, uint16_t(0x5A5A));
bothEndiansReadAndWrite<uint32_t>(0);
bothEndiansReadAndWrite<uint32_t>(0xffffffff);
forAllRotatedValues(bothEndiansReadAndWrite<uint32_t>, uint32_t(1));
forAllRotatedValues(bothEndiansReadAndWrite<uint32_t>, uint32_t(0x5A5A5A5A));
bothEndiansReadAndWrite<uint64_t>(0);
bothEndiansReadAndWrite<uint64_t>(0xffffffffffffffff);
forAllRotatedValues(bothEndiansReadAndWrite<uint64_t>, uint64_t(1));
forAllRotatedValues(bothEndiansReadAndWrite<uint64_t>,
uint64_t(0x5A5A5A5A5A5A5A5A));
}