123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725 |
- //===- 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/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(int 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(int DwarfReg, int 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(int 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 (!llvm::Register::isPhysicalRegister(MachineReg)) {
- if (isFrameRegister(TRI, MachineReg)) {
- DwarfRegs.push_back(Register::createRegister(-1, nullptr));
- return true;
- }
- return false;
- }
- int 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 (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
- 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 (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
- unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR);
- unsigned Size = TRI.getSubRegIdxSize(Idx);
- unsigned Offset = TRI.getSubRegIdxOffset(Idx);
- Reg = TRI.getDwarfRegNum(*SR, false);
- if (Reg < 0)
- 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.test(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::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;
- }
- assert(DwarfRegs.size() == 1);
- 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;
- 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");
- Optional<DIExpression::ExprOperand> PrevConvertOp = None;
- 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_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:
- 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 = None;
- } 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;
- 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;
- }
- }
|