diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index e11ed947d..bfc185c34 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -586,8 +586,10 @@ void VerilatedVcd::declTriArray(vluint32_t code, const char* name, bool array, i //============================================================================= // Trace rendering prinitives -void VerilatedVcd::finishLine(vluint32_t code, char* writep) { - const char* const suffixp = m_suffixesp + code * VL_TRACE_SUFFIX_ENTRY_SIZE; +static inline void +VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) VL_ATTR_NO_SANITIZE_ALIGN; + +static inline void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) { // Copy the whole suffix (this avoid having hard to predict branches which // helps a lot). Note: The maximum length of the suffix is // VL_TRACE_MAX_VCD_CODE_SIZE + 2 == 7, but we unroll this here for speed. @@ -605,6 +607,12 @@ void VerilatedVcd::finishLine(vluint32_t code, char* writep) { writep[5] = suffixp[5]; writep[6] = '\n'; // The 6th index is always '\n' if it's relevant, no need to fetch it. #endif +} + +void VerilatedVcd::finishLine(vluint32_t code, char* writep) { + const char* const suffixp = m_suffixesp + code * VL_TRACE_SUFFIX_ENTRY_SIZE; + VerilatedVcdCCopyAndAppendNewLine(writep, suffixp); + // Now write back the write pointer incremented by the actual size of the // suffix, which was stored in the last byte of the suffix buffer entry. m_writep = writep + suffixp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1]; diff --git a/include/verilatedos.h b/include/verilatedos.h index 21cc1447f..4b1b0874d 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -43,6 +43,12 @@ # define VL_ATTR_COLD __attribute__((cold)) # define VL_ATTR_HOT __attribute__((hot)) # define VL_ATTR_NORETURN __attribute__((noreturn)) +// clang and gcc-8.0+ support no_sanitize("string") style attribute +# if defined(__clang__) || (__GNUC__ >= 8) +# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize("alignment"))) +#else // The entire undefined sanitizer has to be disabled for older gcc +# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize_undefined)) +#endif # define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1))) # define VL_ATTR_PURE __attribute__((pure)) # define VL_ATTR_UNUSED __attribute__((unused)) @@ -85,6 +91,9 @@ #ifndef VL_ATTR_NORETURN # define VL_ATTR_NORETURN ///< Attribute that function does not ever return #endif +#ifndef VL_ATTR_NO_SANITIZE_ALIGN +# define VL_ATTR_NO_SANITIZE_ALIGN ///< Attribute that the function contains intended unaligned access +#endif #ifndef VL_ATTR_PRINTF # define VL_ATTR_PRINTF(fmtArgNum) ///< Attribute for function with printf format checking #endif