@@ -404,6 +404,14 @@ SymbolicValue::getAddressValue(SmallVectorImpl<unsigned> &accessPath) const {
404
404
return dav->memoryObject ;
405
405
}
406
406
407
+ // / Return just the memory object for an address value.
408
+ SymbolicValueMemoryObject *SymbolicValue::getAddressValueMemoryObject () const {
409
+ if (representationKind == RK_DirectAddress)
410
+ return value.directAddress ;
411
+ assert (representationKind == RK_DerivedAddress);
412
+ return value.derivedAddress ->memoryObject ;
413
+ }
414
+
407
415
// ===----------------------------------------------------------------------===//
408
416
// Higher level code
409
417
// ===----------------------------------------------------------------------===//
@@ -521,3 +529,124 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
521
529
emittedFirstNote = true ;
522
530
}
523
531
}
532
+
533
+ // / Returns the element of `aggregate` specified by the access path.
534
+ // /
535
+ // / This is a helper for `SymbolicValueMemoryObject::getIndexedElement`. See
536
+ // / there for more detailed documentation.
537
+ static SymbolicValue getIndexedElement (SymbolicValue aggregate,
538
+ ArrayRef<unsigned > accessPath,
539
+ Type type) {
540
+ // We're done if we've run out of access path.
541
+ if (accessPath.empty ())
542
+ return aggregate;
543
+
544
+ // Everything inside uninit memory is uninit memory.
545
+ if (aggregate.getKind () == SymbolicValue::UninitMemory)
546
+ return SymbolicValue::getUninitMemory ();
547
+
548
+ assert (aggregate.getKind () == SymbolicValue::Aggregate &&
549
+ " the accessPath is invalid for this type" );
550
+
551
+ unsigned elementNo = accessPath.front ();
552
+
553
+ SymbolicValue elt = aggregate.getAggregateValue ()[elementNo];
554
+ Type eltType;
555
+ if (auto *decl = type->getStructOrBoundGenericStruct ()) {
556
+ auto it = decl->getStoredProperties ().begin ();
557
+ std::advance (it, elementNo);
558
+ eltType = (*it)->getType ();
559
+ } else if (auto tuple = type->getAs <TupleType>()) {
560
+ assert (elementNo < tuple->getNumElements () && " invalid index" );
561
+ eltType = tuple->getElement (elementNo).getType ();
562
+ } else {
563
+ llvm_unreachable (" the accessPath is invalid for this type" );
564
+ }
565
+
566
+ return getIndexedElement (elt, accessPath.drop_front (), eltType);
567
+ }
568
+
569
+ // / Given that this memory object contains an aggregate value like
570
+ // / {{1, 2}, 3}, and given an access path like [0,1], return the indexed
571
+ // / element, e.g. "2" in this case.
572
+ // /
573
+ // / Returns uninit memory if the access path points at or into uninit memory.
574
+ // /
575
+ // / Precondition: The access path must be valid for this memory object's type.
576
+ SymbolicValue
577
+ SymbolicValueMemoryObject::getIndexedElement (ArrayRef<unsigned > accessPath) {
578
+ return ::getIndexedElement (value, accessPath, type);
579
+ }
580
+
581
+ // / Returns `aggregate` with the element specified by the access path set to
582
+ // / `newElement`.
583
+ // /
584
+ // / This is a helper for `SymbolicValueMemoryObject::setIndexedElement`. See
585
+ // / there for more detailed documentation.
586
+ static SymbolicValue setIndexedElement (SymbolicValue aggregate,
587
+ ArrayRef<unsigned > accessPath,
588
+ SymbolicValue newElement, Type type,
589
+ ASTContext &astCtx) {
590
+ // We're done if we've run out of access path.
591
+ if (accessPath.empty ())
592
+ return newElement;
593
+
594
+ // If we have an uninit memory, then scalarize it into an aggregate to
595
+ // continue. This happens when memory objects are initialized piecewise.
596
+ if (aggregate.getKind () == SymbolicValue::UninitMemory) {
597
+ unsigned numMembers;
598
+ // We need to have either a struct or a tuple type.
599
+ if (auto *decl = type->getStructOrBoundGenericStruct ()) {
600
+ numMembers = std::distance (decl->getStoredProperties ().begin (),
601
+ decl->getStoredProperties ().end ());
602
+ } else if (auto tuple = type->getAs <TupleType>()) {
603
+ numMembers = tuple->getNumElements ();
604
+ } else {
605
+ llvm_unreachable (" the accessPath is invalid for this type" );
606
+ }
607
+
608
+ SmallVector<SymbolicValue, 4 > newElts (numMembers,
609
+ SymbolicValue::getUninitMemory ());
610
+ aggregate = SymbolicValue::getAggregate (newElts, astCtx);
611
+ }
612
+
613
+ assert (aggregate.getKind () == SymbolicValue::Aggregate &&
614
+ " the accessPath is invalid for this type" );
615
+
616
+ unsigned elementNo = accessPath.front ();
617
+
618
+ ArrayRef<SymbolicValue> oldElts = aggregate.getAggregateValue ();
619
+ Type eltType;
620
+ if (auto *decl = type->getStructOrBoundGenericStruct ()) {
621
+ auto it = decl->getStoredProperties ().begin ();
622
+ std::advance (it, elementNo);
623
+ eltType = (*it)->getType ();
624
+ } else if (auto tuple = type->getAs <TupleType>()) {
625
+ assert (elementNo < tuple->getNumElements () && " invalid index" );
626
+ eltType = tuple->getElement (elementNo).getType ();
627
+ } else {
628
+ llvm_unreachable (" the accessPath is invalid for this type" );
629
+ }
630
+
631
+ // Update the indexed element of the aggregate.
632
+ SmallVector<SymbolicValue, 4 > newElts (oldElts.begin (), oldElts.end ());
633
+ newElts[elementNo] = setIndexedElement (newElts[elementNo],
634
+ accessPath.drop_front (), newElement,
635
+ eltType, astCtx);
636
+
637
+ aggregate = SymbolicValue::getAggregate (newElts, astCtx);
638
+
639
+ return aggregate;
640
+ }
641
+
642
+ // / Given that this memory object contains an aggregate value like
643
+ // / {{1, 2}, 3}, given an access path like [0,1], and given a new element like
644
+ // / "4", set the indexed element to the specified scalar, producing {{1, 4},
645
+ // / 3} in this case.
646
+ // /
647
+ // / Precondition: The access path must be valid for this memory object's type.
648
+ void SymbolicValueMemoryObject::setIndexedElement (
649
+ ArrayRef<unsigned > accessPath, SymbolicValue newElement,
650
+ ASTContext &astCtx) {
651
+ value = ::setIndexedElement (value, accessPath, newElement, type, astCtx);
652
+ }
0 commit comments