From 6ca427c5d03ac29344b0bc7685052a89a1e29b04 Mon Sep 17 00:00:00 2001 From: HÃ¥vard Pettersen Date: Thu, 23 Jun 2022 15:17:01 +0000 Subject: well defined unaligned access --- fsa/src/vespa/fsa/automaton.cpp | 8 +++--- fsa/src/vespa/fsa/fsa.cpp | 16 ++++++------ fsa/src/vespa/fsa/fsa.h | 15 +++++------ fsa/src/vespa/fsa/unaligned.h | 56 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 fsa/src/vespa/fsa/unaligned.h (limited to 'fsa') diff --git a/fsa/src/vespa/fsa/automaton.cpp b/fsa/src/vespa/fsa/automaton.cpp index 91592078c98..57bcfb180a8 100644 --- a/fsa/src/vespa/fsa/automaton.cpp +++ b/fsa/src/vespa/fsa/automaton.cpp @@ -11,7 +11,7 @@ #include "fsa.h" #include "automaton.h" #include "checksum.h" - +#include "unaligned.h" namespace fsa { @@ -354,7 +354,7 @@ void Automaton::PackedAutomaton::finalize() uint32_t j=lastsize; bool fixedsize = true; while(i<_blob_used){ - currsize = *((uint32_t*)(void *)(_blob+i)); + currsize = Unaligned::at(_blob+i); if(currsize!=lastsize){ fixedsize = false; break; @@ -597,14 +597,14 @@ bool Automaton::PackedAutomaton::getFSA(FSA::Descriptor &d) d._version = FSA::VER; d._serial = 0; - d._state = _packed_idx; + d._state = Unaligned::ptr(_packed_idx); d._symbol = _symbol; d._size = size; d._data = _blob; d._data_size = _blob_used; d._data_type = _blob_type; d._fixed_data_size = _fixed_blob_size; - d._perf_hash = _perf_hash; + d._perf_hash = Unaligned::ptr(_perf_hash); d._start = _start_state; _symbol = NULL; diff --git a/fsa/src/vespa/fsa/fsa.cpp b/fsa/src/vespa/fsa/fsa.cpp index 50fd8bff85d..4abc6f979d8 100644 --- a/fsa/src/vespa/fsa/fsa.cpp +++ b/fsa/src/vespa/fsa/fsa.cpp @@ -227,7 +227,7 @@ bool FSA::read(const char *file, FileAccessMethod fam) checksum += Checksum::compute(_symbol,_size*sizeof(symbol_t)); if(_mmap_addr==NULL){ - _state = (state_t*)malloc(_size*sizeof(state_t)); + _state = Unaligned::ptr(malloc(_size*sizeof(state_t))); r=::read(fd,_state,_size*sizeof(state_t)); if(r!=_size*sizeof(state_t)){ ::close(fd); @@ -236,8 +236,8 @@ bool FSA::read(const char *file, FileAccessMethod fam) } } else { - _state = (state_t*)(void *)((uint8_t*)_mmap_addr + sizeof(header) + - _size*sizeof(symbol_t)); + _state = Unaligned::ptr((uint8_t*)_mmap_addr + sizeof(header) + + _size*sizeof(symbol_t)); } checksum += Checksum::compute(_state,_size*sizeof(state_t)); @@ -259,7 +259,7 @@ bool FSA::read(const char *file, FileAccessMethod fam) if(header._has_perfect_hash){ if(_mmap_addr==NULL){ - _perf_hash = (hash_t*)malloc(_size*sizeof(hash_t)); + _perf_hash = Unaligned::ptr(malloc(_size*sizeof(hash_t))); r=::read(fd,_perf_hash,_size*sizeof(hash_t)); if(r!=_size*sizeof(hash_t)){ ::close(fd); @@ -268,10 +268,10 @@ bool FSA::read(const char *file, FileAccessMethod fam) } } else { - _perf_hash = (hash_t*)(void *)((uint8_t*)_mmap_addr + sizeof(header) + - _size*sizeof(symbol_t) + - _size*sizeof(state_t) + - _data_size); + _perf_hash = Unaligned::ptr((uint8_t*)_mmap_addr + sizeof(header) + + _size*sizeof(symbol_t) + + _size*sizeof(state_t) + + _data_size); } checksum += Checksum::compute(_perf_hash,_size*sizeof(hash_t)); _has_perfect_hash = true; diff --git a/fsa/src/vespa/fsa/fsa.h b/fsa/src/vespa/fsa/fsa.h index 915aeb17a17..f3703b398ba 100644 --- a/fsa/src/vespa/fsa/fsa.h +++ b/fsa/src/vespa/fsa/fsa.h @@ -15,6 +15,7 @@ #include #include "file.h" // for FileAccessMethod +#include "unaligned.h" namespace fsa { @@ -614,10 +615,10 @@ public: return (uint32_t)((const uint8_t*)da)[0]; case 2: case 3: - return (uint32_t)((const uint16_t*)(const void *)da)[0]; + return (uint32_t)Unaligned::at(da).read(); case 4: default: - return ((const uint32_t*)(const void *) da)[0]; + return Unaligned::at(da).read(); } } @@ -2019,14 +2020,14 @@ public: struct Descriptor { uint32_t _version; uint32_t _serial; - state_t *_state; + Unaligned *_state; symbol_t *_symbol; uint32_t _size; data_t *_data; uint32_t _data_size; uint32_t _data_type; uint32_t _fixed_data_size; - hash_t *_perf_hash; + Unaligned *_perf_hash; uint32_t _start; }; @@ -2040,7 +2041,7 @@ private: uint32_t _version; /**< Version of fsalib used to build this fsa. */ uint32_t _serial; /**< Serial number of this fsa. */ - state_t *_state; /**< State table for transitions. */ + Unaligned *_state; /**< State table for transitions. */ symbol_t *_symbol; /**< Symbol table for transitions. */ uint32_t _size; /**< Size (number of cells). */ @@ -2050,7 +2051,7 @@ private: uint32_t _fixed_data_size; /**< Size of data items if fixed. */ bool _has_perfect_hash; /**< Indicator of perfect hash present. */ - hash_t *_perf_hash; /**< Perfect hash table, if present. */ + Unaligned *_perf_hash; /**< Perfect hash table, if present. */ state_t _start; /**< Index of start state. */ @@ -2205,7 +2206,7 @@ public: if(_data_type==DATA_FIXED) return _fixed_data_size; else - return (int)(*((uint32_t*)(void *)(_data+_state[fs+FINAL_SYMBOL]))); + return (int)Unaligned::at(_data+_state[fs+FINAL_SYMBOL]).read(); } return -1; } diff --git a/fsa/src/vespa/fsa/unaligned.h b/fsa/src/vespa/fsa/unaligned.h new file mode 100644 index 00000000000..ff645194e4f --- /dev/null +++ b/fsa/src/vespa/fsa/unaligned.h @@ -0,0 +1,56 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include + +namespace fsa { + +template +class Unaligned { +private: + char _data[sizeof(T)]; + +public: + Unaligned() = delete; + Unaligned(const Unaligned &) = delete; + Unaligned(Unaligned &&) = delete; + + Unaligned &operator=(const Unaligned &) = default; + Unaligned &operator=(Unaligned &&) = default; + + static_assert(std::is_trivial_v); + static_assert(alignof(T) > 1, "value is always aligned"); + + constexpr static Unaligned &at(void *p) noexcept { + return *reinterpret_cast(p); + } + constexpr static const Unaligned &at(const void *p) noexcept { + return *reinterpret_cast(p); + } + + constexpr static Unaligned *ptr(void *p) noexcept { + return reinterpret_cast(p); + } + constexpr static const Unaligned *ptr(const void *p) noexcept { + return reinterpret_cast(p); + } + + T read() const noexcept { + T value; + static_assert(sizeof(_data) == sizeof(value)); + memcpy(&value, _data, sizeof(value)); + return value; + } + void write(const T &value) noexcept { + static_assert(sizeof(_data) == sizeof(value)); + memcpy(_data, &value, sizeof(value)); + } + operator T () const noexcept { return read(); } + Unaligned &operator=(const T &value) noexcept { + write(value); + return *this; + } +}; + +} -- cgit v1.2.3