diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -116,7 +116,8 @@ using namespace llvm::support; /// Rewrite the operand of all jumps to this label. - void *Location = Code.data() + Reloc - sizeof(int32_t); + void *Location = Code.data() + Reloc - align(sizeof(int32_t)); + assert(aligned(Location)); const int32_t Offset = Target - static_cast(Reloc); endian::write(Location, Offset); } @@ -126,7 +127,9 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) { // Compute the PC offset which the jump is relative to. - const int64_t Position = Code.size() + sizeof(Opcode) + sizeof(int32_t); + const int64_t Position = + Code.size() + align(sizeof(Opcode)) + align(sizeof(int32_t)); + assert(aligned(Position)); // If target is known, compute jump offset. auto It = LabelOffsets.find(Label); @@ -162,13 +165,17 @@ return; } + // Access must be aligned! + size_t ValPos = align(Code.size()); + Size = align(Size); + assert(aligned(ValPos + Size)); + Code.resize(ValPos + Size); + if constexpr (!std::is_pointer_v) { - const char *Data = reinterpret_cast(&Val); - Code.insert(Code.end(), Data, Data + Size); + new (Code.data() + ValPos) T(Val); } else { uint32_t ID = P.getOrCreateNativePointer(Val); - const char *Data = reinterpret_cast(&ID); - Code.insert(Code.end(), Data, Data + Size); + new (Code.data() + ValPos) uint32_t(ID); } } diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/Interp/PrimType.h --- a/clang/lib/AST/Interp/PrimType.h +++ b/clang/lib/AST/Interp/PrimType.h @@ -59,6 +59,13 @@ return ((Size + alignof(void *) - 1) / alignof(void *)) * alignof(void *); } +constexpr bool aligned(uintptr_t Value) { return Value == align(Value); } +static_assert(aligned(sizeof(void *))); + +static inline bool aligned(const void *P) { + return aligned(reinterpret_cast(P)); +} + inline bool isPrimitiveIntegral(PrimType Type) { switch (Type) { case PT_Bool: diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h --- a/clang/lib/AST/Interp/Source.h +++ b/clang/lib/AST/Interp/Source.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_SOURCE_H #define LLVM_CLANG_AST_INTERP_SOURCE_H +#include "PrimType.h" #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" #include "llvm/Support/Endian.h" @@ -47,9 +48,10 @@ /// Reads data and advances the pointer. template std::enable_if_t::value, T> read() { + assert(aligned(Ptr)); using namespace llvm::support; T Value = endian::read(Ptr); - Ptr += sizeof(T); + Ptr += align(sizeof(T)); return Value; }