1111#include " smack/VectorOperations.h"
1212#include " llvm/Analysis/LoopInfo.h"
1313#include " llvm/BinaryFormat/Dwarf.h"
14+ #include " llvm/IR/DataLayout.h"
1415#include " llvm/IR/DebugInfo.h"
1516#include " llvm/IR/DebugInfoMetadata.h"
1617#include " llvm/IR/GetElementPtrTypeIterator.h"
1718#include " llvm/IR/InstVisitor.h"
1819#include " llvm/Support/GraphWriter.h"
20+ #include < algorithm>
1921#include < sstream>
2022
2123#include " llvm/Support/raw_ostream.h"
@@ -90,20 +92,71 @@ const DIType *dereferenceDIType(const DIType *T) {
9092 }
9193}
9294
93- const DIDerivedType *getDIMember (const DIType *T, unsigned index) {
95+ // The n-th LLVM struct element is not the n-th DW_TAG_member: bitfields share
96+ // a storage unit, clang inserts padding, and a base class occupies a field
97+ // without being a member. Matching on the byte offset instead keeps the name
98+ // tied to the field whose value is actually recorded.
99+ const DIDerivedType *getDIMemberAtOffset (const DIType *T,
100+ uint64_t offsetInBits) {
94101 auto *CT = dyn_cast_or_null<DICompositeType>(stripDIAliases (T));
95102 if (!CT )
96103 return nullptr ;
97104
98- unsigned memberIndex = 0 ;
105+ switch (CT ->getTag ()) {
106+ case dwarf::DW_TAG_structure_type:
107+ case dwarf::DW_TAG_class_type:
108+ break ;
109+ default :
110+ // Every union member sits at offset zero, so a field index cannot pick one
111+ // out; arrays and enumerations have no members to pick at all.
112+ return nullptr ;
113+ }
114+
115+ const DIDerivedType *found = nullptr ;
99116 for (DINode *N : CT ->getElements ()) {
100117 auto *Member = dyn_cast<DIDerivedType>(N);
101118 if (!Member || Member->getTag () != dwarf::DW_TAG_member)
102119 continue ;
103- if (memberIndex++ == index)
104- return Member;
120+ // A static member has no storage in the object, and an artificial one
121+ // (a vtable pointer) is not something the source can name.
122+ if (Member->isStaticMember () || Member->isArtificial ())
123+ continue ;
124+ if (Member->getOffsetInBits () != offsetInBits)
125+ continue ;
126+ // Several bitfields share one storage unit, so the recorded value is not
127+ // the value of any single one of them.
128+ if (Member->isBitField ())
129+ return nullptr ;
130+ if (found)
131+ return nullptr ;
132+ found = Member;
105133 }
106- return nullptr ;
134+ return found;
135+ }
136+
137+ unsigned countDIArrayDims (const DICompositeType *CT ) {
138+ unsigned dims = 0 ;
139+ for (DINode *N : CT ->getElements ())
140+ if (isa<DISubrange>(N))
141+ ++dims;
142+ return dims;
143+ }
144+
145+ // DWARF folds every dimension of a multi-dimensional array into one node, so
146+ // consuming a subscript may leave the remaining dimensions in place.
147+ const DIType *stepIntoDIArray (const DIType *T, unsigned &dimsLeft) {
148+ auto *CT = dyn_cast_or_null<DICompositeType>(stripDIAliases (T));
149+ if (!CT || CT ->getTag () != dwarf::DW_TAG_array_type)
150+ return nullptr ;
151+
152+ if (dimsLeft == 0 )
153+ dimsLeft = countDIArrayDims (CT );
154+ if (dimsLeft == 0 )
155+ return nullptr ;
156+
157+ if (--dimsLeft > 0 )
158+ return T;
159+ return stripDIAliases (CT ->getBaseType ());
107160}
108161
109162std::string sourceIndex (const Value *V) {
@@ -142,8 +195,11 @@ SmackInstGenerator::findSourceExprs(const llvm::Value *V) const {
142195 if (I != sourceExprs.end ())
143196 return &I->second ;
144197
198+ // Only follow a strip that preserves the pointee type; a bitcast to another
199+ // pointee would let the next GEP resolve field indices against the wrong
200+ // debug type.
145201 const Value *Stripped = V->stripPointerCastsAndAliases ();
146- if (Stripped != V) {
202+ if (Stripped != V && Stripped-> getType () == V-> getType () ) {
147203 I = sourceExprs.find (Stripped);
148204 if (I != sourceExprs.end ())
149205 return &I->second ;
@@ -178,8 +234,9 @@ SmackInstGenerator::sourceLValues(const llvm::Value *Pointer) const {
178234 return Results;
179235}
180236
181- void SmackInstGenerator::rememberLoadSourceExpr (llvm::LoadInst &I) {
182- for (const auto &E : sourceLValues (I.getPointerOperand ()))
237+ void SmackInstGenerator::rememberLoadSourceExpr (
238+ llvm::LoadInst &I, const std::vector<SourceExpr> &LValues) {
239+ for (const auto &E : LValues)
183240 rememberSourceExpr (&I, {E.name , E.type , false , E.isDerived });
184241}
185242
@@ -188,34 +245,55 @@ void SmackInstGenerator::rememberGEPSourceExpr(llvm::GetElementPtrInst &I) {
188245 if (!Bases)
189246 return ;
190247
191- for (const auto &Base : *Bases) {
248+ // Copy the bases: recording a new expression for this instruction may grow
249+ // the map, and we would otherwise be iterating a vector inside it.
250+ const std::vector<SourceExpr> Sources = *Bases;
251+
252+ for (const auto &Base : Sources) {
192253 std::string Name = Base.name ;
193254 const DIType *DITy = Base.isAddress ? stripDIAliases (Base.type )
194255 : dereferenceDIType (Base.type );
195256 Type *IRTy = I.getSourceElementType ();
196- bool UseArrow = !Base.isAddress ;
257+ // A pointer value still owes a dereference: the first member access spends
258+ // it as '->', and the first subscript spends it as '(*p)[i]'.
259+ bool PendingDeref = !Base.isAddress ;
197260 bool Derived = Base.isDerived ;
198261 bool Valid = DITy != nullptr ;
262+ unsigned Dims = 0 ;
199263 unsigned Position = 0 ;
200264
201265 for (auto Index = I.idx_begin (), End = I.idx_end (); Valid && Index != End;
202266 ++Index, ++Position) {
203267 Value *IndexValue = Index->get ();
204268
205269 // The first index steps through the pointer operand. A zero index names
206- // the same source object and leaves '.' versus '->' to the first member .
270+ // the same source object and leaves the dereference to the next index .
207271 if (Position == 0 ) {
208272 auto *CI = dyn_cast<ConstantInt>(IndexValue);
209- if (!CI || !CI ->isZero ()) {
210- std::string IndexName = sourceIndex (IndexValue);
211- if (IndexName.empty ()) {
273+ if (CI && CI ->isZero ())
274+ continue ;
275+
276+ std::string IndexName = sourceIndex (IndexValue);
277+ if (IndexName.empty ()) {
278+ Valid = false ;
279+ break ;
280+ }
281+
282+ if (Base.isAddress ) {
283+ // Subscripting the address of an object only names an element when
284+ // that object is an array; otherwise this is pointer arithmetic
285+ // running past it, and 'x[1]' would name something that x is not.
286+ const DIType *ElemDITy = stepIntoDIArray (DITy, Dims);
287+ if (!ElemDITy) {
212288 Valid = false ;
213289 break ;
214290 }
215- Name += " [" + IndexName + " ]" ;
216- UseArrow = false ;
217- Derived = true ;
291+ DITy = ElemDITy;
218292 }
293+
294+ Name += " [" + IndexName + " ]" ;
295+ PendingDeref = false ;
296+ Derived = true ;
219297 continue ;
220298 }
221299
@@ -227,17 +305,22 @@ void SmackInstGenerator::rememberGEPSourceExpr(llvm::GetElementPtrInst &I) {
227305 }
228306
229307 unsigned Field = CI ->getZExtValue ();
230- const DIDerivedType *Member = getDIMember (DITy, Field);
308+ const DIDerivedType *Member =
309+ getDIMemberAtOffset (DITy, I.getModule ()
310+ ->getDataLayout ()
311+ .getStructLayout (ST )
312+ ->getElementOffsetInBits (Field));
231313 if (!Member || Member->getName ().empty ()) {
232314 Valid = false ;
233315 break ;
234316 }
235317
236- Name += (UseArrow ? " ->" : " ." ) + Member->getName ().str ();
237- UseArrow = false ;
318+ Name += (PendingDeref ? " ->" : " ." ) + Member->getName ().str ();
319+ PendingDeref = false ;
238320 Derived = true ;
239321 IRTy = ST ->getElementType (Field);
240322 DITy = stripDIAliases (Member->getBaseType ());
323+ Dims = 0 ;
241324 continue ;
242325 }
243326
@@ -246,21 +329,27 @@ void SmackInstGenerator::rememberGEPSourceExpr(llvm::GetElementPtrInst &I) {
246329 Valid = false ;
247330 break ;
248331 }
249- Name += " [" + IndexName + " ]" ;
250- UseArrow = false ;
251- Derived = true ;
252332
253- if (auto *AT = dyn_cast<ArrayType>(IRTy)) {
254- IRTy = AT ->getElementType ();
255- auto *CT = dyn_cast_or_null<DICompositeType>(stripDIAliases (DITy));
256- DITy = CT ? stripDIAliases (CT ->getBaseType ()) : nullptr ;
257- } else if (auto *VT = dyn_cast<VectorType>(IRTy)) {
258- IRTy = VT ->getElementType ();
259- auto *CT = dyn_cast_or_null<DICompositeType>(stripDIAliases (DITy));
260- DITy = CT ? stripDIAliases (CT ->getBaseType ()) : nullptr ;
261- } else {
333+ Type *ElemIRTy = nullptr ;
334+ if (auto *AT = dyn_cast<ArrayType>(IRTy))
335+ ElemIRTy = AT ->getElementType ();
336+ else if (auto *VT = dyn_cast<FixedVectorType>(IRTy))
337+ ElemIRTy = VT ->getElementType ();
338+
339+ const DIType *ElemDITy = stepIntoDIArray (DITy, Dims);
340+ if (!ElemIRTy || !ElemDITy) {
262341 Valid = false ;
342+ break ;
263343 }
344+
345+ // '*p' subscripted is '(*p)[i]'; 'p[i]' would name a different address.
346+ if (PendingDeref)
347+ Name = " (*" + Name + " )" ;
348+ Name += " [" + IndexName + " ]" ;
349+ PendingDeref = false ;
350+ Derived = true ;
351+ IRTy = ElemIRTy;
352+ DITy = ElemDITy;
264353 }
265354
266355 if (Valid)
@@ -269,26 +358,42 @@ void SmackInstGenerator::rememberGEPSourceExpr(llvm::GetElementPtrInst &I) {
269358}
270359
271360void SmackInstGenerator::rememberCastSourceExpr (llvm::CastInst &I) {
361+ // A cast that changes the type no longer describes the same source object:
362+ // the pointee of a bitcast decides which struct the next GEP resolves its
363+ // field indices against, and an integer cast changes the value outright.
364+ if (I.getSrcTy () != I.getDestTy ())
365+ return ;
366+
272367 auto *Exprs = findSourceExprs (I.getOperand (0 ));
273368 if (!Exprs)
274369 return ;
275- for (const auto &E : *Exprs)
370+ const std::vector<SourceExpr> Sources = *Exprs;
371+ for (const auto &E : Sources)
276372 rememberSourceExpr (&I, E);
277373}
278374
279- void SmackInstGenerator::recordSourceLValues (const llvm::Value *Pointer,
280- const llvm::Value *Value) {
281- if (!SmackOptions::SourceLocSymbols || Value->getType ()->isAggregateType ())
375+ void SmackInstGenerator::recordDerivedLValues (
376+ const std::vector<SourceExpr> &LValues, const llvm::Value *V) {
377+ // boogie_si_record_* models a single scalar; an aggregate or a vector has no
378+ // counterexample value to print.
379+ llvm::Type *T = V->getType ();
380+ if (!SmackOptions::SourceLocSymbols || T->isAggregateType () ||
381+ T->isVectorTy () || T->isVoidTy ())
282382 return ;
283383
284384 std::set<std::string> Recorded;
285- for (const auto &E : sourceLValues (Pointer) ) {
385+ for (const auto &E : LValues ) {
286386 if (!E.isDerived || !Recorded.insert (E.name ).second )
287387 continue ;
288- emit (recordProcedureCall (Value , {Attr::attr (" cexpr" , E.name )}));
388+ emit (recordProcedureCall (V , {Attr::attr (" cexpr" , E.name )}));
289389 }
290390}
291391
392+ void SmackInstGenerator::recordSourceLValues (const llvm::Value *Pointer,
393+ const llvm::Value *V) {
394+ recordDerivedLValues (sourceLValues (Pointer), V);
395+ }
396+
292397const Stmt *
293398SmackInstGenerator::recordProcedureCall (const llvm::Value *V,
294399 std::list<const Attr *> attrs) {
@@ -725,8 +830,9 @@ void SmackInstGenerator::visitLoadInst(llvm::LoadInst &li) {
725830 }
726831
727832 emit (Stmt::assign (rep->expr (&li), E));
728- rememberLoadSourceExpr (li);
729- recordSourceLValues (P, &li);
833+ auto LValues = sourceLValues (P);
834+ rememberLoadSourceExpr (li, LValues);
835+ recordDerivedLValues (LValues, &li);
730836
731837 if (SmackOptions::MemoryModelDebug) {
732838 emit (Stmt::call (Naming::REC_MEM_OP , {Expr::id (Naming::MEM_OP_VAL )}));
@@ -1474,7 +1580,6 @@ void SmackInstGenerator::visitIntrinsicInst(llvm::IntrinsicInst &ii) {
14741580 {llvm::Intrinsic::ctlz, ctlz},
14751581 {llvm::Intrinsic::ctpop, ctpop},
14761582 {llvm::Intrinsic::cttz, cttz},
1477- {llvm::Intrinsic::dbg_declare, ignore},
14781583 {llvm::Intrinsic::dbg_label, ignore},
14791584 {llvm::Intrinsic::copysign, copysign},
14801585 {llvm::Intrinsic::expect, identity},
0 commit comments