Unverified Commit 74e0a26f authored by maksfb's avatar maksfb Committed by GitHub
Browse files

[BOLT] Modify MCPlus annotation internals. NFCI. (#70412)

When annotating MCInst instructions, attach extra annotation operands
directly to the annotated instruction, instead of attaching them to an
instruction pointed to by a special kInst operand.

With this change, it's no longer necessary to allocate MCInst and most
of the first-class annotations come with free memory as currently MCInst
is declared with:

    SmallVector<MCOperand, 10> Operands;

i.e. more operands than are normally being used.

We still create a kInst operand with a nullptr instruction value to
designate the beginning of annotation operands. However, this special
operand might not be needed if we can rely on MCInstrDesc::NumOperands.
parent cc05b47f
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -32,11 +32,16 @@ namespace MCPlus {
/// pad and the uint64_t represents the action.
using MCLandingPad = std::pair<const MCSymbol *, uint64_t>;

/// An extension to MCInst is provided via an extra operand of type MCInst with
/// ANNOTATION_LABEL opcode (i.e. we are tying an annotation instruction to an
/// existing one). The annotation instruction contains a list of Immediate
/// operands. Each operand either contains a value, or is a pointer to
/// an instance of class MCAnnotation.
/// An extension to MCInst is provided via extra operands, i.e. operands that
/// are not used in the instruction assembly. Any kind of metadata can be
/// attached to MCInst with this "annotation" extension using MCPlusBuilder
/// interface.
//
/// The first extra operand must be of type kInst with an empty (nullptr)
/// value. The kInst operand type is unused on most non-VLIW architectures.
/// We use it to mark the beginning of annotations operands. The rest of the
/// operands are of Immediate type with annotation info encoded into the value
/// of the immediate.
///
/// There are 2 distinct groups of annotations. The first group is a first-class
/// annotation that affects semantics of the instruction, such as an
@@ -55,7 +60,7 @@ using MCLandingPad = std::pair<const MCSymbol *, uint64_t>;
/// of their corresponding operand.
///
/// Annotations in the second group could be addressed either by name, or by
/// by and index which could be queried by providing a name.
/// by index which could be queried by providing the name.
class MCAnnotation {
public:
  enum Kind {
@@ -106,10 +111,11 @@ private:
/// Return a number of operands in \Inst excluding operands representing
/// annotations.
inline unsigned getNumPrimeOperands(const MCInst &Inst) {
  if (Inst.getNumOperands() > 0 && std::prev(Inst.end())->isInst()) {
    assert(std::prev(Inst.end())->getInst()->getOpcode() ==
           TargetOpcode::ANNOTATION_LABEL);
    return Inst.getNumOperands() - 1;
  for (signed I = Inst.getNumOperands() - 1; I >= 0; --I) {
    if (Inst.getOperand(I).isInst())
      return I;
    if (!Inst.getOperand(I).isImm())
      return Inst.getNumOperands();
  }
  return Inst.getNumOperands();
}
+54 −59
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ public:
private:
  /// A struct that represents a single annotation allocator
  struct AnnotationAllocator {
    SpecificBumpPtrAllocator<MCInst> MCInstAllocator;
    BumpPtrAllocator ValueAllocator;
    std::unordered_set<MCPlus::MCAnnotation *> AnnotationPool;
  };
@@ -97,61 +96,63 @@ private:
    return SignExtend64<56>(ImmValue & 0xff'ffff'ffff'ffffULL);
  }

  MCInst *getAnnotationInst(const MCInst &Inst) const {
    if (Inst.getNumOperands() == 0)
      return nullptr;

    const MCOperand &LastOp = Inst.getOperand(Inst.getNumOperands() - 1);
    if (!LastOp.isInst())
      return nullptr;
  std::optional<unsigned> getFirstAnnotationOpIndex(const MCInst &Inst) const {
    const unsigned NumPrimeOperands = MCPlus::getNumPrimeOperands(Inst);
    if (Inst.getNumOperands() == NumPrimeOperands)
      return std::nullopt;

    MCInst *AnnotationInst = const_cast<MCInst *>(LastOp.getInst());
    assert(AnnotationInst->getOpcode() == TargetOpcode::ANNOTATION_LABEL);
    assert(Inst.getOperand(NumPrimeOperands).getInst() == nullptr &&
           "Empty instruction expected.");

    return AnnotationInst;
    return NumPrimeOperands + 1;
  }

  void removeAnnotationInst(MCInst &Inst) const {
    assert(getAnnotationInst(Inst) && "Expected annotation instruction.");
    Inst.erase(std::prev(Inst.end()));
    assert(!getAnnotationInst(Inst) &&
           "More than one annotation instruction detected.");
  MCInst::iterator getAnnotationInstOp(MCInst &Inst) const {
    for (MCInst::iterator Iter = Inst.begin(); Iter != Inst.end(); ++Iter) {
      if (Iter->isInst()) {
        assert(Iter->getInst() == nullptr && "Empty instruction expected.");
        return Iter;
      }
    }
    return Inst.end();
  }

  void setAnnotationOpValue(MCInst &Inst, unsigned Index, int64_t Value,
                            AllocatorIdTy AllocatorId = 0) {
    MCInst *AnnotationInst = getAnnotationInst(Inst);
    if (!AnnotationInst) {
      AnnotationAllocator &Allocator = getAnnotationAllocator(AllocatorId);
      AnnotationInst = new (Allocator.MCInstAllocator.Allocate()) MCInst();
      AnnotationInst->setOpcode(TargetOpcode::ANNOTATION_LABEL);
      Inst.addOperand(MCOperand::createInst(AnnotationInst));
  void removeAnnotations(MCInst &Inst) const {
    Inst.erase(getAnnotationInstOp(Inst), Inst.end());
  }

  void setAnnotationOpValue(MCInst &Inst, unsigned Index, int64_t Value) const {
    const int64_t AnnotationValue = encodeAnnotationImm(Index, Value);
    for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
      int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
    const std::optional<unsigned> FirstAnnotationOp =
        getFirstAnnotationOpIndex(Inst);
    if (!FirstAnnotationOp) {
      Inst.addOperand(MCOperand::createInst(nullptr));
      Inst.addOperand(MCOperand::createImm(AnnotationValue));
      return;
    }

    for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) {
      const int64_t ImmValue = Inst.getOperand(I).getImm();
      if (extractAnnotationIndex(ImmValue) == Index) {
        AnnotationInst->getOperand(I).setImm(AnnotationValue);
        Inst.getOperand(I).setImm(AnnotationValue);
        return;
      }
    }

    AnnotationInst->addOperand(MCOperand::createImm(AnnotationValue));
    Inst.addOperand(MCOperand::createImm(AnnotationValue));
  }

  std::optional<int64_t> getAnnotationOpValue(const MCInst &Inst,
                                              unsigned Index) const {
    const MCInst *AnnotationInst = getAnnotationInst(Inst);
    if (!AnnotationInst)
    std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);
    if (!FirstAnnotationOp)
      return std::nullopt;

    for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
      int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
      if (extractAnnotationIndex(ImmValue) == Index) {
    for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) {
      const int64_t ImmValue = Inst.getOperand(I).getImm();
      if (extractAnnotationIndex(ImmValue) == Index)
        return extractAnnotationValue(ImmValue);
    }
    }

    return std::nullopt;
  }
@@ -172,21 +173,18 @@ protected:
  /// AnnotationNameIndexMap and AnnotationsNames.
  mutable llvm::sys::RWMutex AnnotationNameMutex;

  /// Allocate the TailCall annotation value. Clients of the target-specific
  /// Set TailCall annotation value to true. Clients of the target-specific
  /// MCPlusBuilder classes must use convert/lower/create* interfaces instead.
  void setTailCall(MCInst &Inst);
  void setTailCall(MCInst &Inst) const;

public:
  /// Transfer annotations from \p SrcInst to \p DstInst.
  void moveAnnotations(MCInst &&SrcInst, MCInst &DstInst) const {
    assert(!getAnnotationInst(DstInst) &&
           "Destination instruction should not have annotations.");
    const MCInst *AnnotationInst = getAnnotationInst(SrcInst);
    if (!AnnotationInst)
      return;
    MCInst::iterator AnnotationOp = getAnnotationInstOp(SrcInst);
    for (MCInst::iterator Iter = AnnotationOp; Iter != SrcInst.end(); ++Iter)
      DstInst.addOperand(*Iter);

    DstInst.addOperand(MCOperand::createInst(AnnotationInst));
    removeAnnotationInst(SrcInst);
    SrcInst.erase(AnnotationOp, SrcInst.end());
  }

  /// Return iterator range covering def operands.
@@ -390,7 +388,6 @@ public:

      Allocator.AnnotationPool.clear();
      Allocator.ValueAllocator.Reset();
      Allocator.MCInstAllocator.DestroyAll();
    }
  }

@@ -1128,20 +1125,19 @@ public:
  std::optional<MCPlus::MCLandingPad> getEHInfo(const MCInst &Inst) const;

  /// Add handler and action info for call instruction.
  void addEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP);
  void addEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP) const;

  /// Update exception-handling info for the invoke instruction \p Inst.
  /// Return true on success and false otherwise, e.g. if the instruction is
  /// not an invoke.
  bool updateEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP);
  bool updateEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP) const;

  /// Return non-negative GNU_args_size associated with the instruction
  /// or -1 if there's no associated info.
  int64_t getGnuArgsSize(const MCInst &Inst) const;

  /// Add the value of GNU_args_size to Inst if it already has EH info.
  void addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize,
                      AllocatorIdTy AllocId = 0);
  void addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const;

  /// Return jump table addressed by this instruction.
  uint64_t getJumpTable(const MCInst &Inst) const;
@@ -1154,7 +1150,7 @@ public:
                    AllocatorIdTy AllocId = 0);

  /// Disassociate instruction with a jump table.
  bool unsetJumpTable(MCInst &Inst);
  bool unsetJumpTable(MCInst &Inst) const;

  /// Return destination of conditional tail call instruction if \p Inst is one.
  std::optional<uint64_t> getConditionalTailCall(const MCInst &Inst) const;
@@ -1162,11 +1158,11 @@ public:
  /// Mark the \p Instruction as a conditional tail call, and set its
  /// destination address if it is known. If \p Instruction was already marked,
  /// update its destination with \p Dest.
  bool setConditionalTailCall(MCInst &Inst, uint64_t Dest = 0);
  bool setConditionalTailCall(MCInst &Inst, uint64_t Dest = 0) const;

  /// If \p Inst was marked as a conditional tail call convert it to a regular
  /// branch. Return true if the instruction was converted.
  bool unsetConditionalTailCall(MCInst &Inst);
  bool unsetConditionalTailCall(MCInst &Inst) const;

  /// Return offset of \p Inst in the original function, if available.
  std::optional<uint32_t> getOffset(const MCInst &Inst) const;
@@ -1175,10 +1171,10 @@ public:
  uint32_t getOffsetWithDefault(const MCInst &Inst, uint32_t Default) const;

  /// Set offset of \p Inst in the original function.
  bool setOffset(MCInst &Inst, uint32_t Offset, AllocatorIdTy AllocatorId = 0);
  bool setOffset(MCInst &Inst, uint32_t Offset) const;

  /// Remove offset annotation.
  bool clearOffset(MCInst &Inst);
  bool clearOffset(MCInst &Inst) const;

  /// Return the label of \p Inst, if available.
  MCSymbol *getLabel(const MCInst &Inst) const;
@@ -1827,8 +1823,7 @@ public:

    if (!std::is_trivial<ValueType>::value)
      Allocator.AnnotationPool.insert(A);
    setAnnotationOpValue(Inst, Index, reinterpret_cast<int64_t>(A),
                         AllocatorId);
    setAnnotationOpValue(Inst, Index, reinterpret_cast<int64_t>(A));
    return A->getValue();
  }

@@ -1961,21 +1956,21 @@ public:
  ///
  /// Return true if the annotation was removed, false if the annotation
  /// was not present.
  bool removeAnnotation(MCInst &Inst, unsigned Index);
  bool removeAnnotation(MCInst &Inst, unsigned Index) const;

  /// Remove annotation associated with \p Name.
  ///
  /// Return true if the annotation was removed, false if the annotation
  /// was not present.
  bool removeAnnotation(MCInst &Inst, StringRef Name) {
  bool removeAnnotation(MCInst &Inst, StringRef Name) const {
    const auto Index = getAnnotationIndex(Name);
    if (!Index)
      return false;
    return removeAnnotation(Inst, *Index);
  }

  /// Remove meta-data, but don't destroy it.
  void stripAnnotations(MCInst &Inst, bool KeepTC = false);
  /// Remove meta-data from the instruction, but don't destroy it.
  void stripAnnotations(MCInst &Inst, bool KeepTC = false) const;

  virtual InstructionListType
  createInstrumentedIndirectCall(MCInst &&CallInst, MCSymbol *HandlerFuncAddr,
+10 −9
Original line number Diff line number Diff line
@@ -1999,7 +1999,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
      }
    }
    if (LastNonNop && !MIB->getOffset(*LastNonNop))
      MIB->setOffset(*LastNonNop, static_cast<uint32_t>(Offset), AllocatorId);
      MIB->setOffset(*LastNonNop, static_cast<uint32_t>(Offset));
  };

  for (auto I = Instructions.begin(), E = Instructions.end(); I != E; ++I) {
@@ -2022,7 +2022,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
    if (MIB->isNoop(Instr) && !MIB->getOffset(Instr)) {
      // If "Offset" annotation is not present, set it and mark the nop for
      // deletion.
      MIB->setOffset(Instr, static_cast<uint32_t>(Offset), AllocatorId);
      MIB->setOffset(Instr, static_cast<uint32_t>(Offset));
      // Annotate ordinary nops, so we can safely delete them if required.
      MIB->addAnnotation(Instr, "NOP", static_cast<uint32_t>(1), AllocatorId);
    }
@@ -2303,6 +2303,13 @@ void BinaryFunction::removeConditionalTailCalls() {
    assert(CTCTargetLabel && "symbol expected for conditional tail call");
    MCInst TailCallInstr;
    BC.MIB->createTailCall(TailCallInstr, CTCTargetLabel, BC.Ctx.get());

    // Move offset from CTCInstr to TailCallInstr.
    if (const std::optional<uint32_t> Offset = BC.MIB->getOffset(*CTCInstr)) {
      BC.MIB->setOffset(TailCallInstr, *Offset);
      BC.MIB->clearOffset(*CTCInstr);
    }

    // Link new BBs to the original input offset of the BB where the CTC
    // is, so we can map samples recorded in new BBs back to the original BB
    // seem in the input binary (if using BAT)
@@ -2331,12 +2338,6 @@ void BinaryFunction::removeConditionalTailCalls() {

    // This branch is no longer a conditional tail call.
    BC.MIB->unsetConditionalTailCall(*CTCInstr);

    // Move offset from CTCInstr to TailCallInstr.
    if (std::optional<uint32_t> Offset = BC.MIB->getOffset(*CTCInstr)) {
      BC.MIB->setOffset(TailCallInstr, *Offset);
      BC.MIB->clearOffset(*CTCInstr);
    }
  }

  insertBasicBlocks(std::prev(end()), std::move(NewBlocks),
@@ -3373,7 +3374,7 @@ void BinaryFunction::propagateGnuArgsSizeInfo(
        }
      } else if (BC.MIB->isInvoke(Instr)) {
        // Add the value of GNU_args_size as an extra operand to invokes.
        BC.MIB->addGnuArgsSize(Instr, CurrentGnuArgsSize, AllocId);
        BC.MIB->addGnuArgsSize(Instr, CurrentGnuArgsSize);
      }
      ++II;
    }
+26 −36
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
  llvm_unreachable("target-specific expressions are unsupported");
}

void MCPlusBuilder::setTailCall(MCInst &Inst) {
void MCPlusBuilder::setTailCall(MCInst &Inst) const {
  assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));
  setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);
}
@@ -149,7 +149,7 @@ std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {
                        static_cast<uint64_t>(*Action));
}

void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) {
void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const {
  if (isCall(Inst)) {
    assert(!getEHInfo(Inst));
    setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
@@ -159,7 +159,7 @@ void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) {
  }
}

bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) {
bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const {
  if (!isInvoke(Inst))
    return false;

@@ -178,13 +178,12 @@ int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {
  return *Value;
}

void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize,
                                   AllocatorIdTy AllocId) {
void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const {
  assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");
  assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");
  assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");

  setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize, AllocId);
  setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize);
}

uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {
@@ -203,12 +202,12 @@ bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,
                                 uint16_t IndexReg, AllocatorIdTy AllocId) {
  if (!isIndirectBranch(Inst))
    return false;
  setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value, AllocId);
  setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value);
  getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;
  return true;
}

bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) {
bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const {
  if (!getJumpTable(Inst))
    return false;
  removeAnnotation(Inst, MCAnnotation::kJumpTable);
@@ -225,7 +224,7 @@ MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {
  return static_cast<uint64_t>(*Value);
}

bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) {
bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const {
  if (!isConditionalBranch(Inst))
    return false;

@@ -233,7 +232,7 @@ bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) {
  return true;
}

bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) {
bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const {
  if (!getConditionalTailCall(Inst))
    return false;
  removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);
@@ -255,13 +254,12 @@ uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst,
  return Default;
}

bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset,
                              AllocatorIdTy AllocatorId) {
  setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset, AllocatorId);
bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const {
  setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset);
  return true;
}

bool MCPlusBuilder::clearOffset(MCInst &Inst) {
bool MCPlusBuilder::clearOffset(MCInst &Inst) const {
  if (!hasAnnotation(Inst, MCAnnotation::kOffset))
    return false;
  removeAnnotation(Inst, MCAnnotation::kOffset);
@@ -282,49 +280,41 @@ bool MCPlusBuilder::setLabel(MCInst &Inst, MCSymbol *Label,
}

bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {
  const MCInst *AnnotationInst = getAnnotationInst(Inst);
  if (!AnnotationInst)
    return false;

  return (bool)getAnnotationOpValue(Inst, Index);
}

bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) {
  MCInst *AnnotationInst = getAnnotationInst(Inst);
  if (!AnnotationInst)
bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const {
  std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);
  if (!FirstAnnotationOp)
    return false;

  for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
    int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
  for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) {
    const int64_t ImmValue = Inst.getOperand(I).getImm();
    if (extractAnnotationIndex(ImmValue) == Index) {
      AnnotationInst->erase(AnnotationInst->begin() + I);
      Inst.erase(Inst.begin() + I);
      return true;
    }
  }
  return false;
}

void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) {
  MCInst *AnnotationInst = getAnnotationInst(Inst);
  if (!AnnotationInst)
    return;
  // Preserve TailCall annotation.
  auto IsTC = hasAnnotation(Inst, MCAnnotation::kTailCall);
void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const {
  KeepTC &= hasAnnotation(Inst, MCAnnotation::kTailCall);

  removeAnnotationInst(Inst);
  removeAnnotations(Inst);

  if (KeepTC && IsTC)
  if (KeepTC)
    setTailCall(Inst);
}

void MCPlusBuilder::printAnnotations(const MCInst &Inst,
                                     raw_ostream &OS) const {
  const MCInst *AnnotationInst = getAnnotationInst(Inst);
  if (!AnnotationInst)
  std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);
  if (!FirstAnnotationOp)
    return;

  for (unsigned I = 0; I < AnnotationInst->getNumOperands(); ++I) {
    const int64_t Imm = AnnotationInst->getOperand(I).getImm();
  for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) {
    const int64_t Imm = Inst.getOperand(I).getImm();
    const unsigned Index = extractAnnotationIndex(Imm);
    const int64_t Value = extractAnnotationValue(Imm);
    const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);