diff --git a/bolt/include/bolt/Core/MCPlusAnnotation.h b/bolt/include/bolt/Core/MCPlusAnnotation.h new file mode 100644 --- /dev/null +++ b/bolt/include/bolt/Core/MCPlusAnnotation.h @@ -0,0 +1,41 @@ +//===- bolt/Core/MCPlusAnnotation.h - Interface for MCPlus ------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains the definitions of annotation encoding/decoding functions. +// +//===----------------------------------------------------------------------===// + +#ifndef BOLT_CORE_MCPLUSANNOTATION_H +#define BOLT_CORE_MCPLUSANNOTATION_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" + +/// We encode Index and Value into a 64-bit immediate operand value. +inline int64_t encodeAnnotationImm(uint8_t Index, int64_t Value) { + if (LLVM_UNLIKELY(Value != + llvm::SignExtend64<56>(Value & 0xff'ffff'ffff'ffff))) + llvm::report_fatal_error("annotation value out of range"); + + Value &= 0xff'ffff'ffff'ffff; + Value |= (int64_t)Index << 56; + + return Value; +} + +/// Extract annotation index from immediate operand value. +inline uint8_t extractAnnotationIndex(int64_t ImmValue) { + return ImmValue >> 56; +} + +/// Extract annotation value from immediate operand value. +inline int64_t extractAnnotationValue(int64_t ImmValue) { + return llvm::SignExtend64<56>(ImmValue & 0xff'ffff'ffff'ffffULL); +} + +#endif diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -15,6 +15,7 @@ #define BOLT_CORE_MCPLUSBUILDER_H #include "bolt/Core/MCPlus.h" +#include "bolt/Core/MCPlusAnnotation.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -73,28 +74,6 @@ /// A variable that is used to generate unique ids for annotation allocators AllocatorIdTy MaxAllocatorId = 0; - /// We encode Index and Value into a 64-bit immediate operand value. - static int64_t encodeAnnotationImm(unsigned Index, int64_t Value) { - assert(Index < 256 && "annotation index max value exceeded"); - assert((Value == (Value << 8) >> 8) && "annotation value out of range"); - - Value &= 0xff'ffff'ffff'ffff; - Value |= (int64_t)Index << 56; - - return Value; - } - - /// Extract annotation index from immediate operand value. - static unsigned extractAnnotationIndex(int64_t ImmValue) { - return ImmValue >> 56; - } - - /// Extract annotation value from immediate operand value. - static int64_t extractAnnotationValue(int64_t ImmValue) { - ImmValue &= 0xff'ffff'ffff'ffff; - return (ImmValue << 8) >> 8; - } - MCInst *getAnnotationInst(const MCInst &Inst) const { if (Inst.getNumOperands() == 0) return nullptr; diff --git a/bolt/unittests/Core/CMakeLists.txt b/bolt/unittests/Core/CMakeLists.txt --- a/bolt/unittests/Core/CMakeLists.txt +++ b/bolt/unittests/Core/CMakeLists.txt @@ -1,8 +1,10 @@ set(LLVM_LINK_COMPONENTS BOLTCore BOLTRewrite + BOLTUtils DebugInfoDWARF Object + MC ${LLVM_TARGETS_TO_BUILD} ) diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -6,6 +6,7 @@ #include "X86Subtarget.h" #endif // X86_AVAILABLE +#include "bolt/Core/MCPlusAnnotation.h" #include "bolt/Rewrite/RewriteInstance.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" @@ -110,3 +111,18 @@ } #endif // X86_AVAILABLE + +TEST_P(MCPlusBuilderTester, Annotation) { + // Round-trip encoding-decoding check for negative values + int64_t Value = INT32_MIN; + uint8_t Index = 123; + int64_t EncodedAnnotation = encodeAnnotationImm(Index, Value); + int64_t DecodedValue = extractAnnotationValue(EncodedAnnotation); + uint8_t DecodedIndex = extractAnnotationIndex(EncodedAnnotation); + ASSERT_EQ(Value, DecodedValue); + ASSERT_EQ(Index, DecodedIndex); + + // Large int64 should trigger an out of range assertion + Value = 0x1FF'FFFF'FFFF'FFFFULL; + ASSERT_DEATH(encodeAnnotationImm(0, Value), "annotation value out of range"); +}