@@ -364,48 +364,29 @@ void PropertyMap::addSuperclassProperty(
364
364
}
365
365
}
366
366
367
- // / Given two rules (V.[LHS] => V) and (V' .[RHS] => V'), build a rewrite
368
- // / path from T.[RHS] to T.[LHS], where T is the longer of the two terms
369
- // / V and V'.
370
- static void buildRewritePathForUnifier ( unsigned lhsRuleID,
371
- unsigned rhsRuleID ,
367
+ // / Given a rule (V.[LHS] => V) and a rewrite path (T .[RHS] => T) where
368
+ // / T == U.V, build a rewrite path from T.[RHS] to T.[LHS].
369
+ static void buildRewritePathForUnifier (Term key,
370
+ unsigned lhsRuleID,
371
+ const RewritePath &rhsPath ,
372
372
const RewriteSystem &system,
373
- RewritePath & path) {
373
+ RewritePath * path) {
374
374
unsigned lhsLength = system.getRule (lhsRuleID).getRHS ().size ();
375
- unsigned rhsLength = system.getRule (rhsRuleID).getRHS ().size ();
376
-
377
- unsigned lhsPrefix = 0 , rhsPrefix = 0 ;
378
- if (lhsLength < rhsLength)
379
- lhsPrefix = rhsLength - lhsLength;
380
- if (rhsLength < lhsLength)
381
- rhsPrefix = lhsLength - rhsLength;
382
-
383
- assert (lhsPrefix == 0 || rhsPrefix == 0 );
384
-
385
- // If the rule was actually (V.[RHS] => V) with T == U.V for some
386
- // |U| > 0, strip U from the prefix of each substitution of [RHS].
387
- if (rhsPrefix > 0 ) {
388
- path.add (RewriteStep::forPrefixSubstitutions (/* prefix=*/ rhsPrefix,
389
- /* endOffset=*/ 0 ,
390
- /* inverse=*/ true ));
391
- }
375
+ unsigned lhsPrefix = key.size () - lhsLength;
392
376
393
- // Apply the rule (V.[RHS] => V).
394
- path.add (RewriteStep::forRewriteRule (
395
- /* startOffset=*/ rhsPrefix, /* endOffset=*/ 0 ,
396
- /* ruleID=*/ rhsRuleID, /* inverse=*/ false ));
377
+ path->append (rhsPath);
397
378
398
- // Apply the inverted rule (V' => V' .[LHS]).
399
- path. add (RewriteStep::forRewriteRule (
379
+ // Apply the inverted rule U.(V => V.[LHS]).
380
+ path-> add (RewriteStep::forRewriteRule (
400
381
/* startOffset=*/ lhsPrefix, /* endOffset=*/ 0 ,
401
382
/* ruleID=*/ lhsRuleID, /* inverse=*/ true ));
402
383
403
384
// If the rule was actually (V.[LHS] => V) with T == U.V for some
404
385
// |U| > 0, prefix each substitution of [LHS] with U.
405
386
if (lhsPrefix > 0 ) {
406
- path. add (RewriteStep::forPrefixSubstitutions (/* prefix=*/ lhsPrefix,
407
- /* endOffset=*/ 0 ,
408
- /* inverse=*/ false ));
387
+ path-> add (RewriteStep::forPrefixSubstitutions (/* prefix=*/ lhsPrefix,
388
+ /* endOffset=*/ 0 ,
389
+ /* inverse=*/ false ));
409
390
}
410
391
}
411
392
@@ -460,21 +441,39 @@ static void buildRewritePathForUnifier(unsigned lhsRuleID,
460
441
// / T, so T = U.V for some |U| > 0, (or vice versa). In this case we need
461
442
// / an additional step in the middle to prefix the concrete substitutions
462
443
// / of [LHS] (or [LHS]) with U.
463
- static void buildRewritePathForInducedRule (unsigned differenceID,
444
+ static void buildRewritePathForInducedRule (Term key,
445
+ unsigned differenceID,
464
446
unsigned lhsRuleID,
465
- unsigned rhsRuleID ,
447
+ const RewritePath &rhsPath ,
466
448
unsigned substitutionIndex,
467
449
const RewriteSystem &system,
468
- RewritePath & path) {
450
+ RewritePath * path) {
469
451
// Replace f(Xn) with Xn and push T.[RHS] on the stack.
470
- path. add (RewriteStep::forRightConcreteProjection (
452
+ path-> add (RewriteStep::forRightConcreteProjection (
471
453
differenceID, substitutionIndex, /* inverse=*/ false ));
472
454
473
- buildRewritePathForUnifier (lhsRuleID, rhsRuleID , system, path);
455
+ buildRewritePathForUnifier (key, lhsRuleID, rhsPath , system, path);
474
456
475
457
// Pop T.[LHS] from the stack, leaving behind Xn.
476
- path.add (RewriteStep::forLeftConcreteProjection (
477
- differenceID, substitutionIndex, /* inverse=*/ true ));
458
+ path->add (RewriteStep::forLeftConcreteProjection (
459
+ differenceID, substitutionIndex, /* inverse=*/ true ));
460
+ }
461
+
462
+ // / Given that LHS and RHS are known to simplify to the same term, build a
463
+ // / rewrite path from RHS to LHS.
464
+ static void buildPathJoiningTerms (MutableTerm lhsTerm,
465
+ MutableTerm rhsTerm,
466
+ RewriteSystem &system,
467
+ RewritePath *path) {
468
+ (void ) system.simplify (rhsTerm, path);
469
+
470
+ RewritePath lhsPath;
471
+ (void ) system.simplify (lhsTerm, &lhsPath);
472
+ lhsPath.invert ();
473
+
474
+ path->append (lhsPath);
475
+
476
+ assert (lhsTerm == rhsTerm);
478
477
}
479
478
480
479
// / Given two concrete type rules (T.[LHS] => T) and (T.[RHS] => T) and
@@ -491,7 +490,7 @@ static void buildRewritePathForInducedRule(unsigned differenceID,
491
490
void PropertyMap::processTypeDifference (const TypeDifference &difference,
492
491
unsigned differenceID,
493
492
unsigned lhsRuleID,
494
- unsigned rhsRuleID ) {
493
+ const RewritePath &rhsPath ) {
495
494
bool debug = Debug.contains (DebugFlags::ConcreteUnification);
496
495
497
496
if (debug) {
@@ -520,8 +519,9 @@ void PropertyMap::processTypeDifference(const TypeDifference &difference,
520
519
auto rhsTerm = difference.getOriginalSubstitution (index);
521
520
522
521
RewritePath inducedRulePath;
523
- buildRewritePathForInducedRule (differenceID, lhsRuleID, rhsRuleID,
524
- index, System, inducedRulePath);
522
+ buildRewritePathForInducedRule (difference.BaseTerm , differenceID,
523
+ lhsRuleID, rhsPath, index,
524
+ System, &inducedRulePath);
525
525
526
526
if (debug) {
527
527
llvm::dbgs () << " %% Induced rule " << lhsTerm
@@ -531,19 +531,7 @@ void PropertyMap::processTypeDifference(const TypeDifference &difference,
531
531
}
532
532
533
533
System.addRule (lhsTerm, rhsTerm, &inducedRulePath);
534
-
535
- // Build a path from rhsTerm (the original substitution) to
536
- // lhsTerm (the replacement substitution).
537
- MutableTerm mutRhsTerm (rhsTerm);
538
- (void ) System.simplify (mutRhsTerm, &unificationPath);
539
-
540
- RewritePath lhsPath;
541
- MutableTerm mutLhsTerm (lhsTerm);
542
- (void ) System.simplify (mutLhsTerm, &lhsPath);
543
-
544
- assert (mutLhsTerm == mutRhsTerm && " Terms should be joinable" );
545
- lhsPath.invert ();
546
- unificationPath.append (lhsPath);
534
+ buildPathJoiningTerms (lhsTerm, rhsTerm, System, &unificationPath);
547
535
}
548
536
549
537
// All simplified substitutions are now on the primary stack. Collect them to
@@ -554,7 +542,8 @@ void PropertyMap::processTypeDifference(const TypeDifference &difference,
554
542
// We now have a unification path from T.[RHS] to T.[LHS] using the
555
543
// newly-recorded induced rules. Close the loop with a path from
556
544
// T.[RHS] to R.[LHS] via the concrete type rules being unified.
557
- buildRewritePathForUnifier (lhsRuleID, rhsRuleID, System, unificationPath);
545
+ buildRewritePathForUnifier (difference.BaseTerm , lhsRuleID, rhsPath,
546
+ System, &unificationPath);
558
547
559
548
// Record a rewrite loop at T.[LHS].
560
549
MutableTerm basepoint (difference.BaseTerm );
@@ -635,33 +624,21 @@ void PropertyMap::unifyConcreteTypes(
635
624
}
636
625
637
626
// This rule does not need a rewrite path because it will be related
638
- // to the existing rule in concretelySimplifyLeftHandSideSubstitutions() .
627
+ // to the two existing rules by the processTypeDifference() calls below .
639
628
System.addRule (lhsTerm, rhsTerm);
640
- }
641
-
642
- // Recover the (LHS ∧ RHS) rule.
643
- RewritePath path;
644
- bool simplified = System.simplify (lhsTerm, &path);
645
- assert (simplified);
646
- (void ) simplified;
647
-
648
- // FIXME: This is unsound! While 'key' was canonical at the time we
649
- // started property map construction, we might have added other rules
650
- // since then that made it non-canonical.
651
- assert (path.size () == 1 );
652
- assert (path.begin ()->Kind == RewriteStep::Rule);
653
629
654
- unsigned newRuleID = path.begin ()->getRuleID ();
630
+ // Recover a rewrite path from T to T.[LHS ∧ RHS].
631
+ RewritePath path;
632
+ buildPathJoiningTerms (rhsTerm, lhsTerm, System, &path);
655
633
656
- // Process LHS -> (LHS ∧ RHS).
657
- if (checkRulePairOnce (*existingRuleID, newRuleID))
634
+ // Process LHS -> (LHS ∧ RHS).
658
635
processTypeDifference (lhsDifference, *lhsDifferenceID,
659
- *existingRuleID, newRuleID );
636
+ *existingRuleID, path );
660
637
661
- // Process RHS -> (LHS ∧ RHS).
662
- if (checkRulePairOnce (ruleID, newRuleID))
638
+ // Process RHS -> (LHS ∧ RHS).
663
639
processTypeDifference (rhsDifference, *rhsDifferenceID,
664
- ruleID, newRuleID);
640
+ ruleID, path);
641
+ }
665
642
666
643
// The new property is more specific, so update ConcreteType and
667
644
// ConcreteTypeRule.
@@ -679,9 +656,16 @@ void PropertyMap::unifyConcreteTypes(
679
656
assert (*existingProperty == lhsDifference.LHS );
680
657
assert (property == lhsDifference.RHS );
681
658
682
- if (checkRulePairOnce (*existingRuleID, ruleID))
659
+ if (checkRulePairOnce (*existingRuleID, ruleID)) {
660
+ // Build a rewrite path (T.[RHS] => T).
661
+ RewritePath path;
662
+ path.add (RewriteStep::forRewriteRule (
663
+ /* startOffset=*/ 0 , /* endOffset=*/ 0 ,
664
+ /* ruleID=*/ ruleID, /* inverse=*/ false ));
665
+
683
666
processTypeDifference (lhsDifference, *lhsDifferenceID,
684
- *existingRuleID, ruleID);
667
+ *existingRuleID, path);
668
+ }
685
669
686
670
// The new property is more specific, so update existingProperty and
687
671
// existingRuleID.
@@ -691,17 +675,32 @@ void PropertyMap::unifyConcreteTypes(
691
675
return ;
692
676
}
693
677
694
- // Handle the case where LHS == (LHS ∧ RHS) by processing LHS -> (LHS ∧ RHS).
678
+ // Handle the case where LHS == (LHS ∧ RHS) by processing RHS -> (LHS ∧ RHS).
695
679
if (rhsDifferenceID) {
696
680
assert (!lhsDifferenceID);
697
681
698
682
const auto &rhsDifference = System.getTypeDifference (*rhsDifferenceID);
699
683
assert (property == rhsDifference.LHS );
700
684
assert (*existingProperty == rhsDifference.RHS );
701
685
702
- if (checkRulePairOnce (*existingRuleID, ruleID))
686
+ if (checkRulePairOnce (*existingRuleID, ruleID)) {
687
+ // Build a rewrite path (T.[LHS] => T).
688
+ RewritePath path;
689
+ unsigned lhsLength = System.getRule (*existingRuleID).getRHS ().size ();
690
+ unsigned prefix = key.size () - lhsLength;
691
+
692
+ if (prefix > 0 ) {
693
+ path.add (RewriteStep::forPrefixSubstitutions (
694
+ prefix, /* endOffset=*/ 0 , /* inverse=*/ true ));
695
+ }
696
+
697
+ path.add (RewriteStep::forRewriteRule (
698
+ /* startOffset=*/ prefix, /* endOffset=*/ 0 ,
699
+ /* ruleID=*/ *existingRuleID, /* inverse=*/ false ));
700
+
703
701
processTypeDifference (rhsDifference, *rhsDifferenceID,
704
- ruleID, *existingRuleID);
702
+ ruleID, path);
703
+ }
705
704
706
705
// The new property is less specific, so existingProperty and existingRuleID
707
706
// remain unchanged.
@@ -725,8 +724,13 @@ void PropertyMap::unifyConcreteTypes(
725
724
//
726
725
// Since the new rule appears without context, it becomes redundant.
727
726
if (checkRulePairOnce (*existingRuleID, ruleID)) {
727
+ RewritePath rhsPath;
728
+ rhsPath.add (RewriteStep::forRewriteRule (
729
+ /* startOffset=*/ 0 , /* endOffset=*/ 0 ,
730
+ /* ruleID=*/ ruleID, /* inverse=*/ false ));
731
+
728
732
RewritePath path;
729
- buildRewritePathForUnifier (*existingRuleID, ruleID , System, path);
733
+ buildRewritePathForUnifier (key, *existingRuleID, rhsPath , System, & path);
730
734
System.recordRewriteLoop (MutableTerm (rule.getLHS ()), path);
731
735
732
736
rule.markSubstitutionSimplified ();
0 commit comments