//===- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework -----------===//
//
// 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 support for writing dwarf debug info into asm files.
//
//===----------------------------------------------------------------------===//

#include "DwarfExpression.h"
#include "DwarfCompileUnit.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>

using namespace llvm;

#define DEBUG_TYPE "dwarfdebug"

void DwarfExpression::emitConstu(uint64_t Value) {
  if (Value < 32)
    emitOp(dwarf::DW_OP_lit0 + Value);
  else if (Value == std::numeric_limits<uint64_t>::max()) {
    // Only do this for 64-bit values as the DWARF expression stack uses
    // target-address-size values.
    emitOp(dwarf::DW_OP_lit0);
    emitOp(dwarf::DW_OP_not);
  } else {
    emitOp(dwarf::DW_OP_constu);
    emitUnsigned(Value);
  }
}

void DwarfExpression::addReg(int64_t DwarfReg, const char *Comment) {
  assert(DwarfReg >= 0 && "invalid negative dwarf register number");
  assert((isUnknownLocation() || isRegisterLocation()) &&
         "location description already locked down");
  LocationKind = Register;
  if (DwarfReg < 32) {
    emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
  } else {
    emitOp(dwarf::DW_OP_regx, Comment);
    emitUnsigned(DwarfReg);
  }
}

void DwarfExpression::addBReg(int64_t DwarfReg, int64_t Offset) {
  assert(DwarfReg >= 0 && "invalid negative dwarf register number");
  assert(!isRegisterLocation() && "location description already locked down");
  if (DwarfReg < 32) {
    emitOp(dwarf::DW_OP_breg0 + DwarfReg);
  } else {
    emitOp(dwarf::DW_OP_bregx);
    emitUnsigned(DwarfReg);
  }
  emitSigned(Offset);
}

void DwarfExpression::addFBReg(int64_t Offset) {
  emitOp(dwarf::DW_OP_fbreg);
  emitSigned(Offset);
}

void DwarfExpression::addOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
  if (!SizeInBits)
    return;

  const unsigned SizeOfByte = 8;
  if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
    emitOp(dwarf::DW_OP_bit_piece);
    emitUnsigned(SizeInBits);
    emitUnsigned(OffsetInBits);
  } else {
    emitOp(dwarf::DW_OP_piece);
    unsigned ByteSize = SizeInBits / SizeOfByte;
    emitUnsigned(ByteSize);
  }
  this->OffsetInBits += SizeInBits;
}

void DwarfExpression::addShr(unsigned ShiftBy) {
  emitConstu(ShiftBy);
  emitOp(dwarf::DW_OP_shr);
}

void DwarfExpression::addAnd(unsigned Mask) {
  emitConstu(Mask);
  emitOp(dwarf::DW_OP_and);
}

bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
                                    llvm::Register MachineReg,
                                    unsigned MaxSize) {
  if (!MachineReg.isPhysical()) {
    if (isFrameRegister(TRI, MachineReg)) {
      DwarfRegs.push_back(Register::createRegister(-1, nullptr));
      return true;
    }
    // Try getting dwarf register for targets that use virtual registers.
    int64_t Reg = TRI.getDwarfRegNumForVirtReg(MachineReg, false);
    if (Reg > 0) {
      DwarfRegs.push_back(Register::createRegister(Reg, nullptr));
      return true;
    }
    return false;
  }

  int64_t Reg = TRI.getDwarfRegNum(MachineReg, false);

  // If this is a valid register number, emit it.
  if (Reg >= 0) {
    DwarfRegs.push_back(Register::createRegister(Reg, nullptr));
    return true;
  }

  // Walk up the super-register chain until we find a valid number.
  // For example, EAX on x86_64 is a 32-bit fragment of RAX with offset 0.
  for (MCPhysReg SR : TRI.superregs(MachineReg)) {
    Reg = TRI.getDwarfRegNum(SR, false);
    if (Reg >= 0) {
      unsigned Idx = TRI.getSubRegIndex(SR, MachineReg);
      unsigned Size = TRI.getSubRegIdxSize(Idx);
      unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
      DwarfRegs.push_back(Register::createRegister(Reg, "super-register"));
      // Use a DW_OP_bit_piece to describe the sub-register.
      setSubRegisterPiece(Size, RegOffset);
      return true;
    }
  }

  // Otherwise, attempt to find a covering set of sub-register numbers.
  // For example, Q0 on ARM is a composition of D0+D1.
  unsigned CurPos = 0;
  // The size of the register in bits.
  const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(MachineReg);
  unsigned RegSize = TRI.getRegSizeInBits(*RC);
  // Keep track of the bits in the register we already emitted, so we
  // can avoid emitting redundant aliasing subregs. Because this is
  // just doing a greedy scan of all subregisters, it is possible that
  // this doesn't find a combination of subregisters that fully cover
  // the register (even though one may exist).
  SmallBitVector Coverage(RegSize, false);
  for (MCPhysReg SR : TRI.subregs(MachineReg)) {
    unsigned Idx = TRI.getSubRegIndex(MachineReg, SR);
    unsigned Size = TRI.getSubRegIdxSize(Idx);
    unsigned Offset = TRI.getSubRegIdxOffset(Idx);
    Reg = TRI.getDwarfRegNum(SR, false);
    if (Reg < 0 || Offset + Size > RegSize)
      continue;

    // Used to build the intersection between the bits we already
    // emitted and the bits covered by this subregister.
    SmallBitVector CurSubReg(RegSize, false);
    CurSubReg.set(Offset, Offset + Size);

    // If this sub-register has a DWARF number and we haven't covered
    // its range, and its range covers the value, emit a DWARF piece for it.
    if (Offset < MaxSize && !CurSubReg.subsetOf(Coverage)) {
      // Emit a piece for any gap in the coverage.
      if (Offset > CurPos)
        DwarfRegs.push_back(Register::createSubRegister(
            -1, Offset - CurPos, "no DWARF register encoding"));
      if (Offset == 0 && Size >= MaxSize)
        DwarfRegs.push_back(Register::createRegister(Reg, "sub-register"));
      else
        DwarfRegs.push_back(Register::createSubRegister(
            Reg, std::min<unsigned>(Size, MaxSize - Offset), "sub-register"));
    }
    // Mark it as emitted.
    Coverage.set(Offset, Offset + Size);
    CurPos = Offset + Size;
  }
  // Failed to find any DWARF encoding.
  if (CurPos == 0)
    return false;
  // Found a partial or complete DWARF encoding.
  if (CurPos < RegSize)
    DwarfRegs.push_back(Register::createSubRegister(
        -1, RegSize - CurPos, "no DWARF register encoding"));
  return true;
}

void DwarfExpression::addStackValue() {
  if (DwarfVersion >= 4)
    emitOp(dwarf::DW_OP_stack_value);
}

void DwarfExpression::addBooleanConstant(int64_t Value) {
  assert(isImplicitLocation() || isUnknownLocation());
  LocationKind = Implicit;
  if (Value == 0)
    emitOp(dwarf::DW_OP_lit0);
  else
    emitOp(dwarf::DW_OP_lit1);
}

void DwarfExpression::addSignedConstant(int64_t Value) {
  assert(isImplicitLocation() || isUnknownLocation());
  LocationKind = Implicit;
  emitOp(dwarf::DW_OP_consts);
  emitSigned(Value);
}

void DwarfExpression::addUnsignedConstant(uint64_t Value) {
  assert(isImplicitLocation() || isUnknownLocation());
  LocationKind = Implicit;
  emitConstu(Value);
}

void DwarfExpression::addUnsignedConstant(const APInt &Value) {
  assert(isImplicitLocation() || isUnknownLocation());
  LocationKind = Implicit;

  unsigned Size = Value.getBitWidth();
  const uint64_t *Data = Value.getRawData();

  // Chop it up into 64-bit pieces, because that's the maximum that
  // addUnsignedConstant takes.
  unsigned Offset = 0;
  while (Offset < Size) {
    addUnsignedConstant(*Data++);
    if (Offset == 0 && Size <= 64)
      break;
    addStackValue();
    addOpPiece(std::min(Size - Offset, 64u), Offset);
    Offset += 64;
  }
}

void DwarfExpression::addConstantFP(const APFloat &APF, const AsmPrinter &AP) {
  assert(isImplicitLocation() || isUnknownLocation());
  APInt API = APF.bitcastToAPInt();
  int NumBytes = API.getBitWidth() / 8;
  if (NumBytes == 4 /*float*/ || NumBytes == 8 /*double*/) {
    // FIXME: Add support for `long double`.
    emitOp(dwarf::DW_OP_implicit_value);
    emitUnsigned(NumBytes /*Size of the block in bytes*/);

    // The loop below is emitting the value starting at least significant byte,
    // so we need to perform a byte-swap to get the byte order correct in case
    // of a big-endian target.
    if (AP.getDataLayout().isBigEndian())
      API = API.byteSwap();

    for (int i = 0; i < NumBytes; ++i) {
      emitData1(API.getZExtValue() & 0xFF);
      API = API.lshr(8);
    }

    return;
  }
  LLVM_DEBUG(
      dbgs() << "Skipped DW_OP_implicit_value creation for ConstantFP of size: "
             << API.getBitWidth() << " bits\n");
}

bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
                                              DIExpressionCursor &ExprCursor,
                                              llvm::Register MachineReg,
                                              unsigned FragmentOffsetInBits) {
  auto Fragment = ExprCursor.getFragmentInfo();
  if (!addMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U)) {
    LocationKind = Unknown;
    return false;
  }

  bool HasComplexExpression = false;
  auto Op = ExprCursor.peek();
  if (Op && Op->getOp() != dwarf::DW_OP_LLVM_fragment)
    HasComplexExpression = true;

  // If the register can only be described by a complex expression (i.e.,
  // multiple subregisters) it doesn't safely compose with another complex
  // expression. For example, it is not possible to apply a DW_OP_deref
  // operation to multiple DW_OP_pieces, since composite location descriptions
  // do not push anything on the DWARF stack.
  //
  // DW_OP_entry_value operations can only hold a DWARF expression or a
  // register location description, so we can't emit a single entry value
  // covering a composite location description. In the future we may want to
  // emit entry value operations for each register location in the composite
  // location, but until that is supported do not emit anything.
  if ((HasComplexExpression || IsEmittingEntryValue) && DwarfRegs.size() > 1) {
    if (IsEmittingEntryValue)
      cancelEntryValue();
    DwarfRegs.clear();
    LocationKind = Unknown;
    return false;
  }

  // Handle simple register locations. If we are supposed to emit
  // a call site parameter expression and if that expression is just a register
  // location, emit it with addBReg and offset 0, because we should emit a DWARF
  // expression representing a value, rather than a location.
  if ((!isParameterValue() && !isMemoryLocation() && !HasComplexExpression) ||
      isEntryValue()) {
    auto FragmentInfo = ExprCursor.getFragmentInfo();
    unsigned RegSize = 0;
    for (auto &Reg : DwarfRegs) {
      RegSize += Reg.SubRegSize;
      if (Reg.DwarfRegNo >= 0)
        addReg(Reg.DwarfRegNo, Reg.Comment);
      if (FragmentInfo)
        if (RegSize > FragmentInfo->SizeInBits)
          // If the register is larger than the current fragment stop
          // once the fragment is covered.
          break;
      addOpPiece(Reg.SubRegSize);
    }

    if (isEntryValue()) {
      finalizeEntryValue();

      if (!isIndirect() && !isParameterValue() && !HasComplexExpression &&
          DwarfVersion >= 4)
        emitOp(dwarf::DW_OP_stack_value);
    }

    DwarfRegs.clear();
    // If we need to mask out a subregister, do it now, unless the next
    // operation would emit an OpPiece anyway.
    auto NextOp = ExprCursor.peek();
    if (SubRegisterSizeInBits && NextOp &&
        (NextOp->getOp() != dwarf::DW_OP_LLVM_fragment))
      maskSubRegister();
    return true;
  }

  // Don't emit locations that cannot be expressed without DW_OP_stack_value.
  if (DwarfVersion < 4)
    if (any_of(ExprCursor, [](DIExpression::ExprOperand Op) -> bool {
          return Op.getOp() == dwarf::DW_OP_stack_value;
        })) {
      DwarfRegs.clear();
      LocationKind = Unknown;
      return false;
    }

  // TODO: We should not give up here but the following code needs to be changed
  //       to deal with multiple (sub)registers first.
  if (DwarfRegs.size() > 1) {
    LLVM_DEBUG(dbgs() << "TODO: giving up on debug information due to "
                         "multi-register usage.\n");
    DwarfRegs.clear();
    LocationKind = Unknown;
    return false;
  }

  auto Reg = DwarfRegs[0];
  bool FBReg = isFrameRegister(TRI, MachineReg);
  int SignedOffset = 0;
  assert(!Reg.isSubRegister() && "full register expected");

  // Pattern-match combinations for which more efficient representations exist.
  // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset].
  if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
    uint64_t Offset = Op->getArg(0);
    uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits<int>::max());
    if (Offset <= IntMax) {
      SignedOffset = Offset;
      ExprCursor.take();
    }
  }

  // [Reg, DW_OP_constu, Offset, DW_OP_plus]  --> [DW_OP_breg, Offset]
  // [Reg, DW_OP_constu, Offset, DW_OP_minus] --> [DW_OP_breg,-Offset]
  // If Reg is a subregister we need to mask it out before subtracting.
  if (Op && Op->getOp() == dwarf::DW_OP_constu) {
    uint64_t Offset = Op->getArg(0);
    uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits<int>::max());
    auto N = ExprCursor.peekNext();
    if (N && N->getOp() == dwarf::DW_OP_plus && Offset <= IntMax) {
      SignedOffset = Offset;
      ExprCursor.consume(2);
    } else if (N && N->getOp() == dwarf::DW_OP_minus &&
               !SubRegisterSizeInBits && Offset <= IntMax + 1) {
      SignedOffset = -static_cast<int64_t>(Offset);
      ExprCursor.consume(2);
    }
  }

  if (FBReg)
    addFBReg(SignedOffset);
  else
    addBReg(Reg.DwarfRegNo, SignedOffset);
  DwarfRegs.clear();

  // If we need to mask out a subregister, do it now, unless the next
  // operation would emit an OpPiece anyway.
  auto NextOp = ExprCursor.peek();
  if (SubRegisterSizeInBits && NextOp &&
      (NextOp->getOp() != dwarf::DW_OP_LLVM_fragment))
    maskSubRegister();

  return true;
}

void DwarfExpression::setEntryValueFlags(const MachineLocation &Loc) {
  LocationFlags |= EntryValue;
  if (Loc.isIndirect())
    LocationFlags |= Indirect;
}

void DwarfExpression::setLocation(const MachineLocation &Loc,
                                  const DIExpression *DIExpr) {
  if (Loc.isIndirect())
    setMemoryLocationKind();

  if (DIExpr->isEntryValue())
    setEntryValueFlags(Loc);
}

void DwarfExpression::beginEntryValueExpression(
    DIExpressionCursor &ExprCursor) {
  auto Op = ExprCursor.take();
  (void)Op;
  assert(Op && Op->getOp() == dwarf::DW_OP_LLVM_entry_value);
  assert(!IsEmittingEntryValue && "Already emitting entry value?");
  assert(Op->getArg(0) == 1 &&
         "Can currently only emit entry values covering a single operation");

  SavedLocationKind = LocationKind;
  LocationKind = Register;
  LocationFlags |= EntryValue;
  IsEmittingEntryValue = true;
  enableTemporaryBuffer();
}

void DwarfExpression::finalizeEntryValue() {
  assert(IsEmittingEntryValue && "Entry value not open?");
  disableTemporaryBuffer();

  emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));

  // Emit the entry value's size operand.
  unsigned Size = getTemporaryBufferSize();
  emitUnsigned(Size);

  // Emit the entry value's DWARF block operand.
  commitTemporaryBuffer();

  LocationFlags &= ~EntryValue;
  LocationKind = SavedLocationKind;
  IsEmittingEntryValue = false;
}

void DwarfExpression::cancelEntryValue() {
  assert(IsEmittingEntryValue && "Entry value not open?");
  disableTemporaryBuffer();

  // The temporary buffer can't be emptied, so for now just assert that nothing
  // has been emitted to it.
  assert(getTemporaryBufferSize() == 0 &&
         "Began emitting entry value block before cancelling entry value");

  LocationKind = SavedLocationKind;
  IsEmittingEntryValue = false;
}

unsigned DwarfExpression::getOrCreateBaseType(unsigned BitSize,
                                              dwarf::TypeKind Encoding) {
  // Reuse the base_type if we already have one in this CU otherwise we
  // create a new one.
  unsigned I = 0, E = CU.ExprRefedBaseTypes.size();
  for (; I != E; ++I)
    if (CU.ExprRefedBaseTypes[I].BitSize == BitSize &&
        CU.ExprRefedBaseTypes[I].Encoding == Encoding)
      break;

  if (I == E)
    CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding);
  return I;
}

/// Assuming a well-formed expression, match "DW_OP_deref*
/// DW_OP_LLVM_fragment?".
static bool isMemoryLocation(DIExpressionCursor ExprCursor) {
  while (ExprCursor) {
    auto Op = ExprCursor.take();
    switch (Op->getOp()) {
    case dwarf::DW_OP_deref:
    case dwarf::DW_OP_LLVM_fragment:
      break;
    default:
      return false;
    }
  }
  return true;
}

void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor) {
  addExpression(std::move(ExprCursor),
                [](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
                  llvm_unreachable("unhandled opcode found in expression");
                });
}

bool DwarfExpression::addExpression(
    DIExpressionCursor &&ExprCursor,
    llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg) {
  // Entry values can currently only cover the initial register location,
  // and not any other parts of the following DWARF expression.
  assert(!IsEmittingEntryValue && "Can't emit entry value around expression");

  std::optional<DIExpression::ExprOperand> PrevConvertOp;

  while (ExprCursor) {
    auto Op = ExprCursor.take();
    uint64_t OpNum = Op->getOp();

    if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
      emitOp(OpNum);
      continue;
    } else if (OpNum >= dwarf::DW_OP_breg0 && OpNum <= dwarf::DW_OP_breg31) {
      addBReg(OpNum - dwarf::DW_OP_breg0, Op->getArg(0));
      continue;
    }

    switch (OpNum) {
    case dwarf::DW_OP_LLVM_arg:
      if (!InsertArg(Op->getArg(0), ExprCursor)) {
        LocationKind = Unknown;
        return false;
      }
      break;
    case dwarf::DW_OP_LLVM_fragment: {
      unsigned SizeInBits = Op->getArg(1);
      unsigned FragmentOffset = Op->getArg(0);
      // The fragment offset must have already been adjusted by emitting an
      // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base
      // location.
      assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
      assert(SizeInBits >= OffsetInBits - FragmentOffset && "size underflow");

      // If addMachineReg already emitted DW_OP_piece operations to represent
      // a super-register by splicing together sub-registers, subtract the size
      // of the pieces that was already emitted.
      SizeInBits -= OffsetInBits - FragmentOffset;

      // If addMachineReg requested a DW_OP_bit_piece to stencil out a
      // sub-register that is smaller than the current fragment's size, use it.
      if (SubRegisterSizeInBits)
        SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);

      // Emit a DW_OP_stack_value for implicit location descriptions.
      if (isImplicitLocation())
        addStackValue();

      // Emit the DW_OP_piece.
      addOpPiece(SizeInBits, SubRegisterOffsetInBits);
      setSubRegisterPiece(0, 0);
      // Reset the location description kind.
      LocationKind = Unknown;
      return true;
    }
    case dwarf::DW_OP_LLVM_extract_bits_sext:
    case dwarf::DW_OP_LLVM_extract_bits_zext: {
      unsigned SizeInBits = Op->getArg(1);
      unsigned BitOffset = Op->getArg(0);
      unsigned DerefSize = 0;
      //  Operations are done in the DWARF "generic type" whose size
      // is the size of a pointer.
      unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();

      // If we have a memory location then dereference to get the value, though
      // we have to make sure we don't dereference any bytes past the end of the
      // object.
      if (isMemoryLocation()) {
        DerefSize = alignTo(BitOffset + SizeInBits, 8) / 8;
        if (DerefSize == PtrSizeInBytes) {
          emitOp(dwarf::DW_OP_deref);
        } else {
          emitOp(dwarf::DW_OP_deref_size);
          emitUnsigned(DerefSize);
        }
      }

      // If a dereference was emitted for an unsigned value, and
      // there's no bit offset, then a bit of optimization is
      // possible.
      if (OpNum == dwarf::DW_OP_LLVM_extract_bits_zext && BitOffset == 0) {
        if (8 * DerefSize == SizeInBits) {
          // The correct value is already on the stack.
        } else {
          // No need to shift, we can just mask off the desired bits.
          emitOp(dwarf::DW_OP_constu);
          emitUnsigned((1u << SizeInBits) - 1);
          emitOp(dwarf::DW_OP_and);
        }
      } else {
        // Extract the bits by a shift left (to shift out the bits after what we
        // want to extract) followed by shift right (to shift the bits to
        // position 0 and also sign/zero extend).
        unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
        unsigned RightShift = LeftShift + BitOffset;
        if (LeftShift) {
          emitOp(dwarf::DW_OP_constu);
          emitUnsigned(LeftShift);
          emitOp(dwarf::DW_OP_shl);
        }
        if (RightShift) {
          emitOp(dwarf::DW_OP_constu);
          emitUnsigned(RightShift);
          emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext
                     ? dwarf::DW_OP_shra
                     : dwarf::DW_OP_shr);
        }
      }

      // The value is now at the top of the stack, so set the location to
      // implicit so that we get a stack_value at the end.
      LocationKind = Implicit;
      break;
    }
    case dwarf::DW_OP_plus_uconst:
      assert(!isRegisterLocation());
      emitOp(dwarf::DW_OP_plus_uconst);
      emitUnsigned(Op->getArg(0));
      break;
    case dwarf::DW_OP_plus:
    case dwarf::DW_OP_minus:
    case dwarf::DW_OP_mul:
    case dwarf::DW_OP_div:
    case dwarf::DW_OP_mod:
    case dwarf::DW_OP_or:
    case dwarf::DW_OP_and:
    case dwarf::DW_OP_xor:
    case dwarf::DW_OP_shl:
    case dwarf::DW_OP_shr:
    case dwarf::DW_OP_shra:
    case dwarf::DW_OP_lit0:
    case dwarf::DW_OP_not:
    case dwarf::DW_OP_dup:
    case dwarf::DW_OP_push_object_address:
    case dwarf::DW_OP_over:
    case dwarf::DW_OP_rot:
    case dwarf::DW_OP_eq:
    case dwarf::DW_OP_ne:
    case dwarf::DW_OP_gt:
    case dwarf::DW_OP_ge:
    case dwarf::DW_OP_lt:
    case dwarf::DW_OP_le:
    case dwarf::DW_OP_neg:
    case dwarf::DW_OP_abs:
      emitOp(OpNum);
      break;
    case dwarf::DW_OP_deref:
      assert(!isRegisterLocation());
      if (!isMemoryLocation() && ::isMemoryLocation(ExprCursor))
        // Turning this into a memory location description makes the deref
        // implicit.
        LocationKind = Memory;
      else
        emitOp(dwarf::DW_OP_deref);
      break;
    case dwarf::DW_OP_constu:
      assert(!isRegisterLocation());
      emitConstu(Op->getArg(0));
      break;
    case dwarf::DW_OP_consts:
      assert(!isRegisterLocation());
      emitOp(dwarf::DW_OP_consts);
      emitSigned(Op->getArg(0));
      break;
    case dwarf::DW_OP_LLVM_convert: {
      unsigned BitSize = Op->getArg(0);
      dwarf::TypeKind Encoding = static_cast<dwarf::TypeKind>(Op->getArg(1));
      if (DwarfVersion >= 5 && CU.getDwarfDebug().useOpConvert()) {
        emitOp(dwarf::DW_OP_convert);
        // If targeting a location-list; simply emit the index into the raw
        // byte stream as ULEB128, DwarfDebug::emitDebugLocEntry has been
        // fitted with means to extract it later.
        // If targeting a inlined DW_AT_location; insert a DIEBaseTypeRef
        // (containing the index and a resolve mechanism during emit) into the
        // DIE value list.
        emitBaseTypeRef(getOrCreateBaseType(BitSize, Encoding));
      } else {
        if (PrevConvertOp && PrevConvertOp->getArg(0) < BitSize) {
          if (Encoding == dwarf::DW_ATE_signed)
            emitLegacySExt(PrevConvertOp->getArg(0));
          else if (Encoding == dwarf::DW_ATE_unsigned)
            emitLegacyZExt(PrevConvertOp->getArg(0));
          PrevConvertOp = std::nullopt;
        } else {
          PrevConvertOp = Op;
        }
      }
      break;
    }
    case dwarf::DW_OP_stack_value:
      LocationKind = Implicit;
      break;
    case dwarf::DW_OP_swap:
      assert(!isRegisterLocation());
      emitOp(dwarf::DW_OP_swap);
      break;
    case dwarf::DW_OP_xderef:
      assert(!isRegisterLocation());
      emitOp(dwarf::DW_OP_xderef);
      break;
    case dwarf::DW_OP_deref_size:
      emitOp(dwarf::DW_OP_deref_size);
      emitData1(Op->getArg(0));
      break;
    case dwarf::DW_OP_LLVM_tag_offset:
      TagOffset = Op->getArg(0);
      break;
    case dwarf::DW_OP_regx:
      emitOp(dwarf::DW_OP_regx);
      emitUnsigned(Op->getArg(0));
      break;
    case dwarf::DW_OP_bregx:
      emitOp(dwarf::DW_OP_bregx);
      emitUnsigned(Op->getArg(0));
      emitSigned(Op->getArg(1));
      break;
    case dwarf::DW_OP_LLVM_implicit_pointer:
      // Handled in DwarfCompileUnit::emitImplicitPointerLocation for
      // Loc::Single variables. If we reach here, the variable has a
      // location list or other unsupported path. Drop the
      // location rather than crashing.
      return false;
    default:
      llvm_unreachable("unhandled opcode found in expression");
    }
  }

  if (isImplicitLocation() && !isParameterValue())
    // Turn this into an implicit location description.
    addStackValue();

  return true;
}

/// add masking operations to stencil out a subregister.
void DwarfExpression::maskSubRegister() {
  assert(SubRegisterSizeInBits && "no subregister was registered");
  if (SubRegisterOffsetInBits > 0)
    addShr(SubRegisterOffsetInBits);
  uint64_t Mask = (1ULL << (uint64_t)SubRegisterSizeInBits) - 1ULL;
  addAnd(Mask);
}

void DwarfExpression::finalize() {
  assert(DwarfRegs.size() == 0 && "dwarf registers not emitted");
  // Emit any outstanding DW_OP_piece operations to mask out subregisters.
  if (SubRegisterSizeInBits == 0)
    return;
  // Don't emit a DW_OP_piece for a subregister at offset 0.
  if (SubRegisterOffsetInBits == 0)
    return;
  addOpPiece(SubRegisterSizeInBits, SubRegisterOffsetInBits);
}

void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
  if (!Expr || !Expr->isFragment())
    return;

  uint64_t FragmentOffset = Expr->getFragmentInfo()->OffsetInBits;
  assert(FragmentOffset >= OffsetInBits &&
         "overlapping or duplicate fragments");
  if (FragmentOffset > OffsetInBits)
    addOpPiece(FragmentOffset - OffsetInBits);
  OffsetInBits = FragmentOffset;
}

void DwarfExpression::emitLegacySExt(unsigned FromBits) {
  // (((X >> (FromBits - 1)) * (~0)) << FromBits) | X
  emitOp(dwarf::DW_OP_dup);
  emitOp(dwarf::DW_OP_constu);
  emitUnsigned(FromBits - 1);
  emitOp(dwarf::DW_OP_shr);
  emitOp(dwarf::DW_OP_lit0);
  emitOp(dwarf::DW_OP_not);
  emitOp(dwarf::DW_OP_mul);
  emitOp(dwarf::DW_OP_constu);
  emitUnsigned(FromBits);
  emitOp(dwarf::DW_OP_shl);
  emitOp(dwarf::DW_OP_or);
}

void DwarfExpression::emitLegacyZExt(unsigned FromBits) {
  // Heuristic to decide the most efficient encoding.
  // A ULEB can encode 7 1-bits per byte.
  if (FromBits / 7 < 1+1+1+1+1) {
    // (X & (1 << FromBits - 1))
    emitOp(dwarf::DW_OP_constu);
    emitUnsigned((1ULL << FromBits) - 1);
  } else {
    // Note that the DWARF 4 stack consists of pointer-sized elements,
    // so technically it doesn't make sense to shift left more than 64
    // bits. We leave that for the consumer to decide though. LLDB for
    // example uses APInt for the stack elements and can still deal
    // with this.
    emitOp(dwarf::DW_OP_lit1);
    emitOp(dwarf::DW_OP_constu);
    emitUnsigned(FromBits);
    emitOp(dwarf::DW_OP_shl);
    emitOp(dwarf::DW_OP_lit1);
    emitOp(dwarf::DW_OP_minus);
  }
  emitOp(dwarf::DW_OP_and);
}

void DwarfExpression::addWasmLocation(unsigned Index, uint64_t Offset) {
  emitOp(dwarf::DW_OP_WASM_location);
  emitUnsigned(Index == 4/*TI_LOCAL_INDIRECT*/ ? 0/*TI_LOCAL*/ : Index);
  emitUnsigned(Offset);
  if (Index == 4 /*TI_LOCAL_INDIRECT*/) {
    assert(LocationKind == Unknown);
    LocationKind = Memory;
  } else {
    assert(LocationKind == Implicit || LocationKind == Unknown);
    LocationKind = Implicit;
  }
}
