mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Finish off PR23080 by renaming the debug info IR constructs from `MD*` to `DI*`. The last of the `DIDescriptor` classes were deleted in r235356, and the last of the related typedefs removed in r235413, so this has all baked for about a week. Note: If you have out-of-tree code (like a frontend), I recommend that you get everything compiling and tests passing with the *previous* commit before updating to this one. It'll be easier to keep track of what code is using the `DIDescriptor` hierarchy and what you've already updated, and I think you're extremely unlikely to insert bugs. YMMV of course. Back to *this* commit: I did this using the rename-md-di-nodes.sh upgrade script I've attached to PR23080 (both code and testcases) and filtered through clang-format-diff.py. I edited the tests for test/Assembler/invalid-generic-debug-node-*.ll by hand since the columns were off-by-three. It should work on your out-of-tree testcases (and code, if you've followed the advice in the previous paragraph). Some of the tests are in badly named files now (e.g., test/Assembler/invalid-mdcompositetype-missing-tag.ll should be 'dicompositetype'); I'll come back and move the files in a follow-up commit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236120 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			266 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework ----------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains support for writing dwarf debug info into asm files.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "DwarfExpression.h"
 | |
| #include "DwarfDebug.h"
 | |
| #include "llvm/ADT/SmallBitVector.h"
 | |
| #include "llvm/CodeGen/AsmPrinter.h"
 | |
| #include "llvm/Support/Dwarf.h"
 | |
| #include "llvm/Target/TargetMachine.h"
 | |
| #include "llvm/Target/TargetRegisterInfo.h"
 | |
| #include "llvm/Target/TargetSubtargetInfo.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| void DwarfExpression::AddReg(int DwarfReg, const char *Comment) {
 | |
|   assert(DwarfReg >= 0 && "invalid negative dwarf register number");
 | |
|   if (DwarfReg < 32) {
 | |
|     EmitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
 | |
|   } else {
 | |
|     EmitOp(dwarf::DW_OP_regx, Comment);
 | |
|     EmitUnsigned(DwarfReg);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) {
 | |
|   assert(DwarfReg >= 0 && "invalid negative dwarf register number");
 | |
|   if (DwarfReg < 32) {
 | |
|     EmitOp(dwarf::DW_OP_breg0 + DwarfReg);
 | |
|   } else {
 | |
|     EmitOp(dwarf::DW_OP_bregx);
 | |
|     EmitUnsigned(DwarfReg);
 | |
|   }
 | |
|   EmitSigned(Offset);
 | |
|   if (Deref)
 | |
|     EmitOp(dwarf::DW_OP_deref);
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
 | |
|   assert(SizeInBits > 0 && "piece has size zero");
 | |
|   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);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddShr(unsigned ShiftBy) {
 | |
|   EmitOp(dwarf::DW_OP_constu);
 | |
|   EmitUnsigned(ShiftBy);
 | |
|   EmitOp(dwarf::DW_OP_shr);
 | |
| }
 | |
| 
 | |
| bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
 | |
|   if (isFrameRegister(MachineReg)) {
 | |
|     // If variable offset is based in frame register then use fbreg.
 | |
|     EmitOp(dwarf::DW_OP_fbreg);
 | |
|     EmitSigned(Offset);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   int DwarfReg = TRI.getDwarfRegNum(MachineReg, false);
 | |
|   if (DwarfReg < 0)
 | |
|     return false;
 | |
| 
 | |
|   AddRegIndirect(DwarfReg, Offset);
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool DwarfExpression::AddMachineRegPiece(unsigned MachineReg,
 | |
|                                          unsigned PieceSizeInBits,
 | |
|                                          unsigned PieceOffsetInBits) {
 | |
|   if (!TRI.isPhysicalRegister(MachineReg))
 | |
|     return false;
 | |
| 
 | |
|   int Reg = TRI.getDwarfRegNum(MachineReg, false);
 | |
| 
 | |
|   // If this is a valid register number, emit it.
 | |
|   if (Reg >= 0) {
 | |
|     AddReg(Reg);
 | |
|     if (PieceSizeInBits)
 | |
|       AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // Walk up the super-register chain until we find a valid number.
 | |
|   // For example, EAX on x86_64 is a 32-bit piece 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);
 | |
|       AddReg(Reg, "super-register");
 | |
|       if (PieceOffsetInBits == RegOffset) {
 | |
|         AddOpPiece(Size, RegOffset);
 | |
|       } else {
 | |
|         // If this is part of a variable in a sub-register at a
 | |
|         // non-zero offset, we need to manually shift the value into
 | |
|         // place, since the DW_OP_piece describes the part of the
 | |
|         // variable, not the position of the subregister.
 | |
|         if (RegOffset)
 | |
|           AddShr(RegOffset);
 | |
|         AddOpPiece(Size, PieceOffsetInBits);
 | |
|       }
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Otherwise, attempt to find a covering set of sub-register numbers.
 | |
|   // For example, Q0 on ARM is a composition of D0+D1.
 | |
|   //
 | |
|   // Keep track of the current position so we can emit the more
 | |
|   // efficient DW_OP_piece.
 | |
|   unsigned CurPos = PieceOffsetInBits;
 | |
|   // The size of the register in bits, assuming 8 bits per byte.
 | |
|   unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
 | |
|   // Keep track of the bits in the register we already emitted, so we
 | |
|   // can avoid emitting redundant aliasing subregs.
 | |
|   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);
 | |
| 
 | |
|     // Intersection between the bits we already emitted and the bits
 | |
|     // covered by this subregister.
 | |
|     SmallBitVector Intersection(RegSize, false);
 | |
|     Intersection.set(Offset, Offset + Size);
 | |
|     Intersection ^= Coverage;
 | |
| 
 | |
|     // If this sub-register has a DWARF number and we haven't covered
 | |
|     // its range, emit a DWARF piece for it.
 | |
|     if (Reg >= 0 && Intersection.any()) {
 | |
|       AddReg(Reg, "sub-register");
 | |
|       AddOpPiece(Size, Offset == CurPos ? 0 : Offset);
 | |
|       CurPos = Offset + Size;
 | |
| 
 | |
|       // Mark it as emitted.
 | |
|       Coverage.set(Offset, Offset + Size);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return CurPos > PieceOffsetInBits;
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddSignedConstant(int Value) {
 | |
|   EmitOp(dwarf::DW_OP_consts);
 | |
|   EmitSigned(Value);
 | |
|   // The proper way to describe a constant value is
 | |
|   // DW_OP_constu <const>, DW_OP_stack_value.
 | |
|   // Unfortunately, DW_OP_stack_value was not available until DWARF-4,
 | |
|   // so we will continue to generate DW_OP_constu <const> for DWARF-2
 | |
|   // and DWARF-3. Technically, this is incorrect since DW_OP_const <const>
 | |
|   // actually describes a value at a constant addess, not a constant value.
 | |
|   // However, in the past there was no better way  to describe a constant
 | |
|   // value, so the producers and consumers started to rely on heuristics
 | |
|   // to disambiguate the value vs. location status of the expression.
 | |
|   // See PR21176 for more details.
 | |
|   if (DwarfVersion >= 4)
 | |
|     EmitOp(dwarf::DW_OP_stack_value);
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddUnsignedConstant(unsigned Value) {
 | |
|   EmitOp(dwarf::DW_OP_constu);
 | |
|   EmitUnsigned(Value);
 | |
|   // cf. comment in DwarfExpression::AddSignedConstant().
 | |
|   if (DwarfVersion >= 4)
 | |
|     EmitOp(dwarf::DW_OP_stack_value);
 | |
| }
 | |
| 
 | |
| static unsigned getOffsetOrZero(unsigned OffsetInBits,
 | |
|                                 unsigned PieceOffsetInBits) {
 | |
|   if (OffsetInBits == PieceOffsetInBits)
 | |
|     return 0;
 | |
|   assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces");
 | |
|   return OffsetInBits;
 | |
| }
 | |
| 
 | |
| bool DwarfExpression::AddMachineRegExpression(const DIExpression *Expr,
 | |
|                                               unsigned MachineReg,
 | |
|                                               unsigned PieceOffsetInBits) {
 | |
|   auto I = Expr->expr_op_begin();
 | |
|   auto E = Expr->expr_op_end();
 | |
|   if (I == E)
 | |
|     return AddMachineRegPiece(MachineReg);
 | |
| 
 | |
|   // Pattern-match combinations for which more efficient representations exist
 | |
|   // first.
 | |
|   bool ValidReg = false;
 | |
|   switch (I->getOp()) {
 | |
|   case dwarf::DW_OP_bit_piece: {
 | |
|     unsigned OffsetInBits = I->getArg(0);
 | |
|     unsigned SizeInBits   = I->getArg(1);
 | |
|     // Piece always comes at the end of the expression.
 | |
|     return AddMachineRegPiece(MachineReg, SizeInBits,
 | |
|                getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
 | |
|   }
 | |
|   case dwarf::DW_OP_plus: {
 | |
|     // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
 | |
|     auto N = I.getNext();
 | |
|     if (N != E && N->getOp() == dwarf::DW_OP_deref) {
 | |
|       unsigned Offset = I->getArg(0);
 | |
|       ValidReg = AddMachineRegIndirect(MachineReg, Offset);
 | |
|       std::advance(I, 2);
 | |
|       break;
 | |
|     } else
 | |
|       ValidReg = AddMachineRegPiece(MachineReg);
 | |
|   }
 | |
|   case dwarf::DW_OP_deref: {
 | |
|       // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
 | |
|       ValidReg = AddMachineRegIndirect(MachineReg);
 | |
|       ++I;
 | |
|       break;
 | |
|   }
 | |
|   default:
 | |
|     llvm_unreachable("unsupported operand");
 | |
|   }
 | |
| 
 | |
|   if (!ValidReg)
 | |
|     return false;
 | |
| 
 | |
|   // Emit remaining elements of the expression.
 | |
|   AddExpression(I, E, PieceOffsetInBits);
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void DwarfExpression::AddExpression(DIExpression::expr_op_iterator I,
 | |
|                                     DIExpression::expr_op_iterator E,
 | |
|                                     unsigned PieceOffsetInBits) {
 | |
|   for (; I != E; ++I) {
 | |
|     switch (I->getOp()) {
 | |
|     case dwarf::DW_OP_bit_piece: {
 | |
|       unsigned OffsetInBits = I->getArg(0);
 | |
|       unsigned SizeInBits   = I->getArg(1);
 | |
|       AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
 | |
|       break;
 | |
|     }
 | |
|     case dwarf::DW_OP_plus:
 | |
|       EmitOp(dwarf::DW_OP_plus_uconst);
 | |
|       EmitUnsigned(I->getArg(0));
 | |
|       break;
 | |
|     case dwarf::DW_OP_deref:
 | |
|       EmitOp(dwarf::DW_OP_deref);
 | |
|       break;
 | |
|     default:
 | |
|       llvm_unreachable("unhandled opcode found in expression");
 | |
|     }
 | |
|   }
 | |
| }
 |