1 //===-- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains support for writing dwarf debug info into asm files. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "DwarfExpression.h" 15 #include "DwarfDebug.h" 16 #include "llvm/ADT/SmallBitVector.h" 17 #include "llvm/CodeGen/AsmPrinter.h" 18 #include "llvm/Support/Dwarf.h" 19 #include "llvm/Target/TargetMachine.h" 20 #include "llvm/Target/TargetRegisterInfo.h" 21 #include "llvm/Target/TargetSubtargetInfo.h" 22 23 using namespace llvm; 24 25 void DwarfExpression::AddReg(int DwarfReg, const char *Comment) { 26 assert(DwarfReg >= 0 && "invalid negative dwarf register number"); 27 if (DwarfReg < 32) { 28 EmitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment); 29 } else { 30 EmitOp(dwarf::DW_OP_regx, Comment); 31 EmitUnsigned(DwarfReg); 32 } 33 } 34 35 void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) { 36 assert(DwarfReg >= 0 && "invalid negative dwarf register number"); 37 if (DwarfReg < 32) { 38 EmitOp(dwarf::DW_OP_breg0 + DwarfReg); 39 } else { 40 EmitOp(dwarf::DW_OP_bregx); 41 EmitUnsigned(DwarfReg); 42 } 43 EmitSigned(Offset); 44 if (Deref) 45 EmitOp(dwarf::DW_OP_deref); 46 } 47 48 void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { 49 assert(SizeInBits > 0 && "piece has size zero"); 50 const unsigned SizeOfByte = 8; 51 if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { 52 EmitOp(dwarf::DW_OP_bit_piece); 53 EmitUnsigned(SizeInBits); 54 EmitUnsigned(OffsetInBits); 55 } else { 56 EmitOp(dwarf::DW_OP_piece); 57 unsigned ByteSize = SizeInBits / SizeOfByte; 58 EmitUnsigned(ByteSize); 59 } 60 } 61 62 void DwarfExpression::AddShr(unsigned ShiftBy) { 63 EmitOp(dwarf::DW_OP_constu); 64 EmitUnsigned(ShiftBy); 65 EmitOp(dwarf::DW_OP_shr); 66 } 67 68 bool DwarfExpression::AddMachineRegIndirect(const TargetRegisterInfo &TRI, 69 unsigned MachineReg, int Offset) { 70 if (isFrameRegister(TRI, MachineReg)) { 71 // If variable offset is based in frame register then use fbreg. 72 EmitOp(dwarf::DW_OP_fbreg); 73 EmitSigned(Offset); 74 return true; 75 } 76 77 int DwarfReg = TRI.getDwarfRegNum(MachineReg, false); 78 if (DwarfReg < 0) 79 return false; 80 81 AddRegIndirect(DwarfReg, Offset); 82 return true; 83 } 84 85 bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI, 86 unsigned MachineReg, 87 unsigned FragmentSizeInBits, 88 unsigned FragmentOffsetInBits) { 89 if (!TRI.isPhysicalRegister(MachineReg)) 90 return false; 91 92 int Reg = TRI.getDwarfRegNum(MachineReg, false); 93 94 // If this is a valid register number, emit it. 95 if (Reg >= 0) { 96 AddReg(Reg); 97 if (FragmentSizeInBits) 98 AddOpPiece(FragmentSizeInBits, FragmentOffsetInBits); 99 return true; 100 } 101 102 // Walk up the super-register chain until we find a valid number. 103 // For example, EAX on x86_64 is a 32-bit fragment of RAX with offset 0. 104 for (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) { 105 Reg = TRI.getDwarfRegNum(*SR, false); 106 if (Reg >= 0) { 107 unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); 108 unsigned Size = TRI.getSubRegIdxSize(Idx); 109 unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); 110 AddReg(Reg, "super-register"); 111 if (FragmentOffsetInBits == RegOffset) { 112 AddOpPiece(Size, RegOffset); 113 } else { 114 // If this is part of a variable in a sub-register at a non-zero offset, 115 // we need to manually shift the value into place, since the 116 // DW_OP_LLVM_fragment describes the part of the variable, not the 117 // position of the subregister. 118 if (RegOffset) 119 AddShr(RegOffset); 120 AddOpPiece(Size, FragmentOffsetInBits); 121 } 122 return true; 123 } 124 } 125 126 // Otherwise, attempt to find a covering set of sub-register numbers. 127 // For example, Q0 on ARM is a composition of D0+D1. 128 unsigned CurPos = FragmentOffsetInBits; 129 // The size of the register in bits, assuming 8 bits per byte. 130 unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8; 131 // Keep track of the bits in the register we already emitted, so we 132 // can avoid emitting redundant aliasing subregs. 133 SmallBitVector Coverage(RegSize, false); 134 for (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) { 135 unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR); 136 unsigned Size = TRI.getSubRegIdxSize(Idx); 137 unsigned Offset = TRI.getSubRegIdxOffset(Idx); 138 Reg = TRI.getDwarfRegNum(*SR, false); 139 140 // Intersection between the bits we already emitted and the bits 141 // covered by this subregister. 142 SmallBitVector Intersection(RegSize, false); 143 Intersection.set(Offset, Offset + Size); 144 Intersection ^= Coverage; 145 146 // If this sub-register has a DWARF number and we haven't covered 147 // its range, emit a DWARF piece for it. 148 if (Reg >= 0 && Intersection.any()) { 149 AddReg(Reg, "sub-register"); 150 AddOpPiece(Size, Offset == CurPos ? 0 : Offset); 151 CurPos = Offset + Size; 152 153 // Mark it as emitted. 154 Coverage.set(Offset, Offset + Size); 155 } 156 } 157 158 return CurPos > FragmentOffsetInBits; 159 } 160 161 void DwarfExpression::AddStackValue() { 162 if (DwarfVersion >= 4) 163 EmitOp(dwarf::DW_OP_stack_value); 164 } 165 166 void DwarfExpression::AddSignedConstant(int64_t Value) { 167 EmitOp(dwarf::DW_OP_consts); 168 EmitSigned(Value); 169 AddStackValue(); 170 } 171 172 void DwarfExpression::AddUnsignedConstant(uint64_t Value) { 173 EmitOp(dwarf::DW_OP_constu); 174 EmitUnsigned(Value); 175 AddStackValue(); 176 } 177 178 void DwarfExpression::AddUnsignedConstant(const APInt &Value) { 179 unsigned Size = Value.getBitWidth(); 180 const uint64_t *Data = Value.getRawData(); 181 182 // Chop it up into 64-bit pieces, because that's the maximum that 183 // AddUnsignedConstant takes. 184 unsigned Offset = 0; 185 while (Offset < Size) { 186 AddUnsignedConstant(*Data++); 187 if (Offset == 0 && Size <= 64) 188 break; 189 AddOpPiece(std::min(Size-Offset, 64u), Offset); 190 Offset += 64; 191 } 192 } 193 194 static unsigned getOffsetOrZero(unsigned OffsetInBits, 195 unsigned FragmentOffsetInBits) { 196 if (OffsetInBits == FragmentOffsetInBits) 197 return 0; 198 assert(OffsetInBits >= FragmentOffsetInBits && "overlapping fragments"); 199 return OffsetInBits; 200 } 201 202 bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI, 203 DIExpressionCursor &ExprCursor, 204 unsigned MachineReg, 205 unsigned FragmentOffsetInBits) { 206 if (!ExprCursor) 207 return AddMachineRegFragment(TRI, MachineReg); 208 209 // Pattern-match combinations for which more efficient representations exist 210 // first. 211 bool ValidReg = false; 212 auto Op = ExprCursor.peek(); 213 switch (Op->getOp()) { 214 case dwarf::DW_OP_LLVM_fragment: { 215 unsigned OffsetInBits = Op->getArg(0); 216 unsigned SizeInBits = Op->getArg(1); 217 // Piece always comes at the end of the expression. 218 AddMachineRegFragment(TRI, MachineReg, SizeInBits, 219 getOffsetOrZero(OffsetInBits, FragmentOffsetInBits)); 220 ExprCursor.take(); 221 break; 222 } 223 case dwarf::DW_OP_plus: 224 case dwarf::DW_OP_minus: { 225 // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset]. 226 // [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset]. 227 auto N = ExprCursor.peekNext(); 228 if (N && N->getOp() == dwarf::DW_OP_deref) { 229 unsigned Offset = Op->getArg(0); 230 ValidReg = AddMachineRegIndirect( 231 TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset); 232 ExprCursor.consume(2); 233 } else 234 ValidReg = AddMachineRegFragment(TRI, MachineReg); 235 break; 236 } 237 case dwarf::DW_OP_deref: 238 // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg]. 239 ValidReg = AddMachineRegIndirect(TRI, MachineReg); 240 ExprCursor.take(); 241 break; 242 } 243 244 return ValidReg; 245 } 246 247 void DwarfExpression::AddExpression(DIExpressionCursor &&ExprCursor, 248 unsigned FragmentOffsetInBits) { 249 while (ExprCursor) { 250 auto Op = ExprCursor.take(); 251 switch (Op->getOp()) { 252 case dwarf::DW_OP_LLVM_fragment: { 253 unsigned OffsetInBits = Op->getArg(0); 254 unsigned SizeInBits = Op->getArg(1); 255 AddOpPiece(SizeInBits, 256 getOffsetOrZero(OffsetInBits, FragmentOffsetInBits)); 257 break; 258 } 259 case dwarf::DW_OP_plus: 260 EmitOp(dwarf::DW_OP_plus_uconst); 261 EmitUnsigned(Op->getArg(0)); 262 break; 263 case dwarf::DW_OP_minus: 264 // There is no OP_minus_uconst. 265 EmitOp(dwarf::DW_OP_constu); 266 EmitUnsigned(Op->getArg(0)); 267 EmitOp(dwarf::DW_OP_minus); 268 break; 269 case dwarf::DW_OP_deref: 270 EmitOp(dwarf::DW_OP_deref); 271 break; 272 case dwarf::DW_OP_constu: 273 EmitOp(dwarf::DW_OP_constu); 274 EmitUnsigned(Op->getArg(0)); 275 break; 276 case dwarf::DW_OP_stack_value: 277 AddStackValue(); 278 break; 279 default: 280 llvm_unreachable("unhandled opcode found in expression"); 281 } 282 } 283 } 284