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