@@ -44,7 +44,8 @@ KType *CXXTypeManager::getWrappedType(llvm::Type *type) {
4444      /*  Vector types are considered as their elements type */ 
4545      llvm::Type *unwrappedRawType = type;
4646      if  (unwrappedRawType->isVectorTy ()) {
47-         unwrappedRawType = llvm::cast<llvm::VectorType>(unwrappedRawType)->getElementType ();
47+         unwrappedRawType =
48+             llvm::cast<llvm::VectorType>(unwrappedRawType)->getElementType ();
4849      }
4950
5051      switch  (unwrappedRawType->getTypeID ()) {
@@ -54,6 +55,10 @@ KType *CXXTypeManager::getWrappedType(llvm::Type *type) {
5455      case  (llvm::Type::IntegerTyID):
5556        kt = new  cxxtypes::KCXXIntegerType (unwrappedRawType, this );
5657        break ;
58+       case  (llvm::Type::PPC_FP128TyID):
59+       case  (llvm::Type::FP128TyID):
60+       case  (llvm::Type::X86_FP80TyID):
61+       case  (llvm::Type::DoubleTyID):
5762      case  (llvm::Type::FloatTyID):
5863        kt = new  cxxtypes::KCXXFloatingPointType (unwrappedRawType, this );
5964        break ;
@@ -172,6 +177,38 @@ void CXXTypeManager::onFinishInitModule() {
172177  }
173178}
174179
180+ /* *
181+  * Util method to create constraints for pointers 
182+  * for complex structures that can have many types located 
183+  * by different offsets. 
184+  */  
185+ static  ref<Expr> getComplexPointerRestrictions (
186+     ref<Expr> object,
187+     const  std::vector<std::pair<size_t , KType *>> &offsetsToTypes) {
188+   ref<Expr> resultCondition;
189+   for  (auto  &offsetToTypePair : offsetsToTypes) {
190+     size_t  offset = offsetToTypePair.first ;
191+     KType *extractedType = offsetToTypePair.second ;
192+ 
193+     ref<Expr> extractedOffset = ExtractExpr::create (
194+         object, offset * CHAR_BIT, extractedType->getSize () * CHAR_BIT);
195+     ref<Expr> innerAlignmentRequirement =
196+         llvm::cast<cxxtypes::KCXXType>(extractedType)
197+             ->getPointersRestrictions (extractedOffset);
198+     if  (innerAlignmentRequirement.isNull ()) {
199+       continue ;
200+     }
201+ 
202+     if  (resultCondition.isNull ()) {
203+       resultCondition = innerAlignmentRequirement;
204+     } else  {
205+       resultCondition =
206+           AndExpr::create (resultCondition, innerAlignmentRequirement);
207+     }
208+   }
209+   return  resultCondition;
210+ }
211+ 
175212/*  C++ KType base class */ 
176213cxxtypes::KCXXType::KCXXType (llvm::Type *type, TypeManager *parent)
177214    : KType(type, parent) {
@@ -193,6 +230,19 @@ bool cxxtypes::KCXXType::isAccessableFrom(KType *accessingType) const {
193230  assert (false  && " Attempted to compare raw llvm type with C++ type!" 
194231}
195232
233+ ref<Expr> cxxtypes::KCXXType::getContentRestrictions (ref<Expr> object) const  {
234+   if  (type == nullptr ) {
235+     return  nullptr ;
236+   }
237+   llvm::Type *elementType = type->getPointerElementType ();
238+   return  llvm::cast<cxxtypes::KCXXType>(parent->getWrappedType (elementType))
239+       ->getPointersRestrictions (object);
240+ }
241+ 
242+ ref<Expr> cxxtypes::KCXXType::getPointersRestrictions (ref<Expr>) const  {
243+   return  nullptr ;
244+ }
245+ 
196246bool  cxxtypes::KCXXType::isAccessingFromChar (KCXXType *accessingType) {
197247  /*  Special case for unknown type */ 
198248  if  (accessingType->getRawType () == nullptr ) {
@@ -231,6 +281,19 @@ cxxtypes::KCXXCompositeType::KCXXCompositeType(KType *type, TypeManager *parent,
231281  insertedTypes.emplace (type);
232282}
233283
284+ ref<Expr>
285+ cxxtypes::KCXXCompositeType::getPointersRestrictions (ref<Expr> object) const  {
286+   if  (containsSymbolic) {
287+     return  nullptr ;
288+   }
289+   std::vector<std::pair<size_t , KType *>> offsetToTypes;
290+   for  (auto  &offsetToTypePair : typesLocations) {
291+     offsetToTypes.emplace_back (offsetToTypePair.first ,
292+                                offsetToTypePair.second .first );
293+   }
294+   return  getComplexPointerRestrictions (object, offsetToTypes);
295+ }
296+ 
234297void  cxxtypes::KCXXCompositeType::handleMemoryAccess (KType *type,
235298                                                     ref<Expr> offset,
236299                                                     ref<Expr> size,
@@ -411,6 +474,21 @@ cxxtypes::KCXXStructType::KCXXStructType(llvm::Type *type, TypeManager *parent)
411474  }
412475}
413476
477+ ref<Expr>
478+ cxxtypes::KCXXStructType::getPointersRestrictions (ref<Expr> object) const  {
479+   std::vector<std::pair<size_t , KType *>> offsetsToTypes;
480+   for  (auto  &innerTypeToOffsets : innerTypes) {
481+     KType *innerType = innerTypeToOffsets.first ;
482+     if  (!llvm::isa<KCXXPointerType>(innerType)) {
483+       continue ;
484+     }
485+     for  (auto  &offset : innerTypeToOffsets.second ) {
486+       offsetsToTypes.emplace_back (offset, innerType);
487+     }
488+   }
489+   return  getComplexPointerRestrictions (object, offsetsToTypes);
490+ }
491+ 
414492bool  cxxtypes::KCXXStructType::isAccessableFrom (KCXXType *accessingType) const  {
415493  /*  FIXME: this is a temporary hack for vtables in C++. Ideally, we
416494   * should demangle global variables to get additional info, at least 
@@ -460,6 +538,15 @@ cxxtypes::KCXXArrayType::KCXXArrayType(llvm::Type *type, TypeManager *parent)
460538  arrayElementsCount = rawArrayType->getArrayNumElements ();
461539}
462540
541+ ref<Expr>
542+ cxxtypes::KCXXArrayType::getPointersRestrictions (ref<Expr> object) const  {
543+   std::vector<std::pair<size_t , KType *>> offsetsToTypes;
544+   for  (unsigned  idx = 0 ; idx < arrayElementsCount; ++idx) {
545+     offsetsToTypes.emplace_back (idx * elementType->getSize (), elementType);
546+   }
547+   return  getComplexPointerRestrictions (object, offsetsToTypes);
548+ }
549+ 
463550bool  cxxtypes::KCXXArrayType::isAccessableFrom (KCXXType *accessingType) const  {
464551  if  (llvm::isa<KCXXArrayType>(accessingType)) {
465552    return  innerIsAccessableFrom (llvm::cast<KCXXArrayType>(accessingType));
@@ -575,6 +662,26 @@ bool cxxtypes::KCXXPointerType::innerIsAccessableFrom(
575662  return  accessingType->getRawType () == nullptr ;
576663}
577664
665+ ref<Expr>
666+ cxxtypes::KCXXPointerType::getPointersRestrictions (ref<Expr> object) const  {
667+   /* *
668+    * We assume that alignment is always a power of 2 and has 
669+    * a bit representation as 00...010...00. By subtracting 1 
670+    * we are getting 00...011...1. Then we apply this mask to 
671+    * address and require, that bitwise AND should give 0 (i.e. 
672+    * non of the last bits is 1). 
673+    */  
674+   ref<Expr> appliedAlignmentMask = AndExpr::create (
675+       Expr::createPointer (elementType->getAlignment () - 1 ), object);
676+ 
677+   ref<Expr> sizeExpr = Expr::createPointer (elementType->getSize () - 1 );
678+ 
679+   ref<Expr> objectUpperBound = AddExpr::create (object, sizeExpr);
680+ 
681+   return  AndExpr::create (Expr::createIsZero (appliedAlignmentMask),
682+                          UgeExpr::create (objectUpperBound, sizeExpr));
683+ }
684+ 
578685bool  cxxtypes::KCXXPointerType::innerIsAccessableFrom (
579686    KCXXPointerType *accessingType) const  {
580687  return  elementType->isAccessableFrom (accessingType->elementType );
0 commit comments