From 1221af99281c87d35c65110a75f87893ff0fc947 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Fri, 2 Dec 2022 08:19:14 +0100 Subject: [PATCH] [clang][Interp] Use placement new to construct opcode args into vector Differential Revision: https://reviews.llvm.org/D139185 --- clang/lib/AST/Interp/ByteCodeEmitter.cpp | 19 +++++++++++++------ clang/lib/AST/Interp/PrimType.h | 7 +++++++ clang/lib/AST/Interp/Source.h | 4 +++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index ff2136d..4633d1e 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -116,7 +116,8 @@ void ByteCodeEmitter::emitLabel(LabelTy Label) { 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 @@ void ByteCodeEmitter::emitLabel(LabelTy Label) { 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 @@ static void emit(Program &P, std::vector &Code, const T &Val, 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 index 8490c1f..3a77c66 100644 --- a/clang/lib/AST/Interp/PrimType.h +++ b/clang/lib/AST/Interp/PrimType.h @@ -59,6 +59,13 @@ constexpr size_t align(size_t Size) { 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 index de4ae55..99ffce3 100644 --- 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 @@ public: /// 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; } -- 2.7.4