Esempio n. 1
0
 // a function which searches for the key in the map passed in. Returns 0 if unsuccessful or the instruction number on success
 int findKey(llvm::DenseMap<llvm::Instruction*, int>& map, llvm::Instruction* key){
     llvm::DenseMap<llvm::Instruction*, int>::iterator iter = map.find(key);
     if(iter == map.end())
         return 0;    
     else
         return iter->second;
 }
Esempio n. 2
0
ICInfo* getICInfo(void* rtn_addr) {
    // TODO: load this from the CF instead of tracking it separately
    auto&& it = ics_by_return_addr.find(rtn_addr);
    if (it == ics_by_return_addr.end())
        return NULL;
    return it->second;
}
Esempio n. 3
0
static
llvm::MDNode *myGetType(const Type *type) {
  typedef llvm::DenseMap<const Type*, llvm::MDNode *>::const_iterator TypeNodeIter;
  TypeNodeIter i = myTypeDescriptors.find(type);
  if(i != myTypeDescriptors.end())
    return i->second;
  return NULL;
}
Esempio n. 4
0
static void
updateSSAForUseOfInst(SILSSAUpdater &Updater,
                      SmallVectorImpl<SILArgument*> &InsertedPHIs,
                      const llvm::DenseMap<ValueBase *, SILValue> &ValueMap,
                      SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock,
                      ValueBase *Inst) {
    if (Inst->use_empty())
        return;

    // Find the mapped instruction.
    assert(ValueMap.count(Inst) && "Expected to find value in map!");
    SILValue MappedValue = ValueMap.find(Inst)->second;
    assert(MappedValue);

    // For each use of a specific result value of the instruction.
    if (Inst->hasValue()) {
        SILValue Res(Inst);
        assert(Res->getType() == MappedValue->getType() && "The types must match");

        InsertedPHIs.clear();
        Updater.Initialize(Res->getType());
        Updater.AddAvailableValue(Header, Res);
        Updater.AddAvailableValue(EntryCheckBlock, MappedValue);


        // Because of the way that phi nodes are represented we have to collect all
        // uses before we update SSA. Modifying one phi node can invalidate another
        // unrelated phi nodes operands through the common branch instruction (that
        // has to be modified). This would invalidate a plain ValueUseIterator.
        // Instead we collect uses wrapping uses in branches specially so that we
        // can reconstruct the use even after the branch has been modified.
        SmallVector<UseWrapper, 8> StoredUses;
        for (auto *U : Res->getUses())
            StoredUses.push_back(UseWrapper(U));
        for (auto U : StoredUses) {
            Operand *Use = U;
            SILInstruction *User = Use->getUser();
            assert(User && "Missing user");

            // Ignore uses in the same basic block.
            if (User->getParent() == Header)
                continue;

            assert(User->getParent() != EntryCheckBlock &&
                   "The entry check block should dominate the header");
            Updater.RewriteUse(*Use);
        }
        // Canonicalize inserted phis to avoid extra BB Args.
        for (SILArgument *Arg : InsertedPHIs) {
            if (SILInstruction *Inst = replaceBBArgWithCast(Arg)) {
                Arg->replaceAllUsesWith(Inst);
                // DCE+SimplifyCFG runs as a post-pass cleanup.
                // DCE replaces dead arg values with undef.
                // SimplifyCFG deletes the dead BB arg.
            }
        }
    }
}
Esempio n. 5
0
 // Return a range of scopes for the given closure. The elements of the
 // returned range have type `SILFunction *` and are non-null. Return an empty
 // range for a SILFunction that is not a closure or is a dead closure.
 ScopeRange getClosureScopes(SILFunction *ClosureF) {
   IndexRange indexRange(nullptr, nullptr);
   auto closureScopesPos = closureToScopesMap.find(ClosureF);
   if (closureScopesPos != closureToScopesMap.end()) {
     auto &indexedScopes = closureScopesPos->second;
     indexRange = IndexRange(indexedScopes.begin(), indexedScopes.end());
   }
   return makeOptionalTransformRange(indexRange,
                                     IndexLookupFunc(indexedScopes));
 }
Esempio n. 6
0
  int lookupScopeIndex(SILFunction *scopeFunc) {
    auto indexPos = scopeToIndexMap.find(scopeFunc);
    if (indexPos != scopeToIndexMap.end())
      return indexPos->second;

    int scopeIdx = indexedScopes.size();
    scopeToIndexMap[scopeFunc] = scopeIdx;
    indexedScopes.push_back(scopeFunc);
    return scopeIdx;
  }
Esempio n. 7
0
 void erase(SILFunction *F) {
   // If this function is a mapped closure scope, remove it, leaving a nullptr
   // sentinel.
   auto indexPos = scopeToIndexMap.find(F);
   if (indexPos != scopeToIndexMap.end()) {
     indexedScopes[indexPos->second] = nullptr;
     scopeToIndexMap.erase(F);
   }
   // If this function is a closure, remove it.
   closureToScopesMap.erase(F);
 }
Esempio n. 8
0
static void mapOperands(SILInstruction *I,
                        const llvm::DenseMap<ValueBase *, SILValue> &ValueMap) {
  for (auto &Opd : I->getAllOperands()) {
    SILValue OrigVal = Opd.get();
    ValueBase *OrigDef = OrigVal;
    auto Found = ValueMap.find(OrigDef);
    if (Found != ValueMap.end()) {
      SILValue MappedVal = Found->second;
      Opd.set(MappedVal);
    }
  }
}
Esempio n. 9
0
  void addDecl(llvm::DenseMap<K, FoundDecl> &Map, K Key, FoundDecl FD) {
    // Add the declaration if we haven't found an equivalent yet, otherwise
    // replace the equivalent if the found decl has a higher access level.
    auto existingDecl = Map.find(Key);

    if ((existingDecl == Map.end()) ||
        (Map[Key].first->getFormalAccess() < FD.first->getFormalAccess())) {
      if (existingDecl != Map.end())
        declsToReport.erase({existingDecl->getSecond().first});
      Map[Key] = FD;
      declsToReport.insert(FD);
    }
  }
 void VisitCallExpr(CallExpr* CE) {
    Visit(CE->getCallee());
    FunctionDecl* FDecl = CE->getDirectCallee();
    if (FDecl && isDeclCandidate(FDecl)) {
      decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
      const std::bitset<32>& ArgIndexs = it->second;
      Sema::ContextRAII pushedDC(m_Sema, FDecl);
      for (int index = 0; index < 32; ++index) {
        if (ArgIndexs.test(index)) {
          // Get the argument with the nonnull attribute.
          Expr* Arg = CE->getArg(index);
          CE->setArg(index, SynthesizeCheck(Arg));
        }
      }
    }
  }
Esempio n. 11
0
 /// Insert a block into the worklist and set its stack depth.
 void insert(SILBasicBlock *BB, int StackDepth) {
   auto Iter = Block2StackDepth.find(BB);
   if (Iter != Block2StackDepth.end()) {
     // We already handled the block.
     assert(StackDepth >= 0);
     if (Iter->second < 0) {
       // Update the stack depth if we didn't set it yet for the block.
       Iter->second = StackDepth;
     } else {
       assert(Iter->second == StackDepth &&
                "inconsistent stack depth at a CFG merge point");
     }
   } else {
     Block2StackDepth[BB] = StackDepth;
     ToHandle.push_back(BB);
   }
 }
Esempio n. 12
0
static void mapOperands(SILInstruction *I,
                        const llvm::DenseMap<ValueBase *, SILValue> &ValueMap) {
  for (auto &Opd : I->getAllOperands()) {
    SILValue OrigVal = Opd.get();
    ValueBase *OrigDef = OrigVal.getDef();
    auto Found = ValueMap.find(OrigDef);
    if (Found != ValueMap.end()) {
      SILValue MappedVal = Found->second;
      unsigned ResultIdx = OrigVal.getResultNumber();
      // All mapped instructions have their result number set to zero. Except
      // for arguments that we followed along one edge to their incoming value
      // on that edge.
      if (isa<SILArgument>(OrigDef))
        ResultIdx = MappedVal.getResultNumber();
      Opd.set(SILValue(MappedVal.getDef(), ResultIdx));
    }
  }
}
 bool VisitCallExpr(CallExpr* CE) {
   VisitStmt(CE->getCallee());
   FunctionDecl* FDecl = CE->getDirectCallee();
   if (FDecl && isDeclCandidate(FDecl)) {
     decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
     const std::bitset<32>& ArgIndexs = it->second;
     Sema::ContextRAII pushedDC(m_Sema, FDecl);
     for (int index = 0; index < 32; ++index) {
       if (ArgIndexs.test(index)) {
         // Get the argument with the nonnull attribute.
         Expr* Arg = CE->getArg(index);
         if (Arg->getType().getTypePtr()->isPointerType()
             && !llvm::isa<clang::CXXThisExpr>(Arg))
           CE->setArg(index, SynthesizeCheck(Arg));
       }
     }
   }
   return true;
 }
Esempio n. 14
0
  ModuleDecl *loadModule(SourceLoc importLoc,
                         ArrayRef<std::pair<Identifier, SourceLoc>> path) {
    // FIXME: Implement submodule support!
    Identifier name = path[0].first;

    auto it = ModuleWrappers.find(name);
    if (it != ModuleWrappers.end())
      return it->second->getParentModule();

    auto *decl = ModuleDecl::create(name, SwiftContext);
    // Silence error messages about testably importing a Clang module.
    decl->setTestingEnabled();
    decl->setHasResolvedImports();
    auto wrapperUnit = new (SwiftContext) DWARFModuleUnit(*decl);
    ModuleWrappers.insert({name, wrapperUnit});
    decl->addFile(*wrapperUnit);

    // Force load adapter modules for all imported modules.
    decl->forAllVisibleModules({}, [](ModuleDecl::ImportedModule import) {});

    return decl;
  }
Esempio n. 15
0
 int getStackDepth(SILBasicBlock *BB) {
   assert(Block2StackDepth.find(BB) != Block2StackDepth.end());
   int Depth = Block2StackDepth.lookup(BB);
   assert(Depth >= 0 && "EndBlock not reachable from StartBlock");
   return Depth;
 }
Esempio n. 16
0
SolutionCompareResult ConstraintSystem::compareSolutions(
    ConstraintSystem &cs, ArrayRef<Solution> solutions,
    const SolutionDiff &diff, unsigned idx1, unsigned idx2,
    llvm::DenseMap<Expr *, unsigned> &weights) {
  if (cs.TC.getLangOpts().DebugConstraintSolver) {
    auto &log = cs.getASTContext().TypeCheckerDebug->getStream();
    log.indent(cs.solverState->depth * 2)
      << "comparing solutions " << idx1 << " and " << idx2 <<"\n";
  }

  // Whether the solutions are identical.
  bool identical = true;

  // Compare the fixed scores by themselves.
  if (solutions[idx1].getFixedScore() != solutions[idx2].getFixedScore()) {
    return solutions[idx1].getFixedScore() < solutions[idx2].getFixedScore()
             ? SolutionCompareResult::Better
             : SolutionCompareResult::Worse;
  }
  
  // Compute relative score.
  unsigned score1 = 0;
  unsigned score2 = 0;
  
  auto foundRefinement1 = false;
  auto foundRefinement2 = false;

  bool isStdlibOptionalMPlusOperator1 = false;
  bool isStdlibOptionalMPlusOperator2 = false;

  auto getWeight = [&](ConstraintLocator *locator) -> unsigned {
    if (auto *anchor = locator->getAnchor()) {
      auto weight = weights.find(anchor);
      if (weight != weights.end())
        return weight->getSecond() + 1;
    }

    return 1;
  };

  // Compare overload sets.
  for (auto &overload : diff.overloads) {
    unsigned weight = getWeight(overload.locator);

    auto choice1 = overload.choices[idx1];
    auto choice2 = overload.choices[idx2];

    // If the systems made the same choice, there's nothing interesting here.
    if (sameOverloadChoice(choice1, choice2))
      continue;

    auto decl1 = choice1.getDecl();
    auto dc1 = decl1->getDeclContext();
    auto decl2 = choice2.getDecl();
    auto dc2 = decl2->getDeclContext();

    // The two systems are not identical. If the decls in question are distinct
    // protocol members, let the checks below determine if the two choices are
    // 'identical' or not. This allows us to structurally unify disparate
    // protocol members during overload resolution.
    // FIXME: Along with the FIXME below, this is a hack to work around
    // problems with restating requirements in protocols.
    identical = false;
    bool decl1InSubprotocol = false;
    bool decl2InSubprotocol = false;
    if (dc1->getContextKind() == DeclContextKind::GenericTypeDecl &&
        dc1->getContextKind() == dc2->getContextKind()) {
      auto pd1 = dyn_cast<ProtocolDecl>(dc1);
      auto pd2 = dyn_cast<ProtocolDecl>(dc2);

      // FIXME: This hack tells us to prefer members of subprotocols over
      // those of the protocols they inherit, if all else fails.
      // If we were properly handling overrides of protocol members when
      // requirements get restated, it would not be necessary.
      if (pd1 && pd2 && pd1 != pd2) {
        identical = true;
        decl1InSubprotocol = pd1->inheritsFrom(pd2);
        decl2InSubprotocol = pd2->inheritsFrom(pd1);
      }
    }
    
    // If the kinds of overload choice don't match...
    if (choice1.getKind() != choice2.getKind()) {
      identical = false;
      
      // A declaration found directly beats any declaration found via dynamic
      // lookup, bridging, or optional unwrapping.
      if ((choice1.getKind() == OverloadChoiceKind::Decl) &&
          (choice2.getKind() == OverloadChoiceKind::DeclViaDynamic ||
           choice2.getKind() == OverloadChoiceKind::DeclViaBridge ||
           choice2.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional)) {
        score1 += weight;
        continue;
      }

      if ((choice1.getKind() == OverloadChoiceKind::DeclViaDynamic ||
           choice1.getKind() == OverloadChoiceKind::DeclViaBridge ||
           choice1.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional) &&
          choice2.getKind() == OverloadChoiceKind::Decl) {
        score2 += weight;
        continue;
      }

      continue;
    }

    // The kinds of overload choice match, but the contents don't.
    auto &tc = cs.getTypeChecker();
    switch (choice1.getKind()) {
    case OverloadChoiceKind::TupleIndex:
      continue;

    case OverloadChoiceKind::BaseType:
    case OverloadChoiceKind::KeyPathApplication:
      llvm_unreachable("Never considered different");

    case OverloadChoiceKind::DeclViaDynamic:
    case OverloadChoiceKind::Decl:
    case OverloadChoiceKind::DeclViaBridge:
    case OverloadChoiceKind::DeclViaUnwrappedOptional:
    case OverloadChoiceKind::DynamicMemberLookup:
      break;
    }
    
    // Determine whether one declaration is more specialized than the other.
    bool firstAsSpecializedAs = false;
    bool secondAsSpecializedAs = false;
    if (isDeclAsSpecializedAs(tc, cs.DC, decl1, decl2)) {
      score1 += weight;
      firstAsSpecializedAs = true;
    }
    if (isDeclAsSpecializedAs(tc, cs.DC, decl2, decl1)) {
      score2 += weight;
      secondAsSpecializedAs = true;
    }

    // If each is as specialized as the other, and both are constructors,
    // check the constructor kind.
    if (firstAsSpecializedAs && secondAsSpecializedAs) {
      if (auto ctor1 = dyn_cast<ConstructorDecl>(decl1)) {
        if (auto ctor2 = dyn_cast<ConstructorDecl>(decl2)) {
          if (ctor1->getInitKind() != ctor2->getInitKind()) {
            if (ctor1->getInitKind() < ctor2->getInitKind())
              score1 += weight;
            else
              score2 += weight;
          } else if (ctor1->getInitKind() ==
                     CtorInitializerKind::Convenience) {
            
            // If both are convenience initializers, and the instance type of
            // one is a subtype of the other's, favor the subtype constructor.
            auto resType1 = ctor1->mapTypeIntoContext(
                ctor1->getResultInterfaceType());
            auto resType2 = ctor2->mapTypeIntoContext(
                ctor2->getResultInterfaceType());
            
            if (!resType1->isEqual(resType2)) {
              if (tc.isSubtypeOf(resType1, resType2, cs.DC)) {
                score1 += weight;
              } else if (tc.isSubtypeOf(resType2, resType1, cs.DC)) {
                score2 += weight;
              }
            }
          }
        }
      }
    }

    // If both declarations come from Clang, and one is a type and the other
    // is a function, prefer the function.
    if (decl1->hasClangNode() &&
        decl2->hasClangNode() &&
        ((isa<TypeDecl>(decl1) &&
          isa<AbstractFunctionDecl>(decl2)) ||
         (isa<AbstractFunctionDecl>(decl1) &&
          isa<TypeDecl>(decl2)))) {
      if (isa<TypeDecl>(decl1))
        score2 += weight;
      else
        score1 += weight;
    }

    // A class member is always better than a curried instance member.
    // If the members agree on instance-ness, a property is better than a
    // method (because a method is usually immediately invoked).
    if (!decl1->isInstanceMember() && decl2->isInstanceMember())
      score1 += weight;
    else if (!decl2->isInstanceMember() && decl1->isInstanceMember())
      score2 += weight;
    else if (isa<VarDecl>(decl1) && isa<FuncDecl>(decl2))
      score1 += weight;
    else if (isa<VarDecl>(decl2) && isa<FuncDecl>(decl1))
      score2 += weight;

    // If both are class properties with the same name, prefer
    // the one attached to the subclass because it could only be
    // found if requested directly.
    if (!decl1->isInstanceMember() && !decl2->isInstanceMember()) {
      if (isa<VarDecl>(decl1) && isa<VarDecl>(decl2)) {
        auto *nominal1 = dc1->getAsNominalTypeOrNominalTypeExtensionContext();
        auto *nominal2 = dc2->getAsNominalTypeOrNominalTypeExtensionContext();

        if (nominal1 && nominal2 && nominal1 != nominal2) {
          auto base1 = nominal1->getDeclaredType();
          auto base2 = nominal2->getDeclaredType();

          if (isNominallySuperclassOf(base1, base2))
            score2 += weight;

          if (isNominallySuperclassOf(base2, base1))
            score1 += weight;
        }
      }
    }

    // If we haven't found a refinement, record whether one overload is in
    // any way more constrained than another. We'll only utilize this
    // information in the case of a potential ambiguity.
    if (!(foundRefinement1 && foundRefinement2)) {
      if (isDeclMoreConstrainedThan(decl1, decl2)) {
        foundRefinement1 = true;
      }
      
      if (isDeclMoreConstrainedThan(decl2, decl1)) {
        foundRefinement2 = true;
      }
    }

    // FIXME: The rest of the hack for restating requirements.
    if (!(foundRefinement1 && foundRefinement2)) {
      if (identical && decl1InSubprotocol != decl2InSubprotocol) {
        foundRefinement1 = decl1InSubprotocol;
        foundRefinement2 = decl2InSubprotocol;
      }
    }

    // FIXME: Lousy hack for ?? to prefer the catamorphism (flattening)
    // over the mplus (non-flattening) overload if all else is equal.
    if (decl1->getBaseName() == "??") {
      assert(decl2->getBaseName() == "??");

      auto check = [](const ValueDecl *VD) -> bool {
        if (!VD->getModuleContext()->isStdlibModule())
          return false;
        auto fnTy = VD->getInterfaceType()->castTo<AnyFunctionType>();
        if (!fnTy->getResult()->getOptionalObjectType())
          return false;

        // Check that the standard library hasn't added another overload of
        // the ?? operator.
        auto params = fnTy->getParams();
        assert(params.size() == 2);

        auto param1 = params[0].getType();
        auto param2 = params[1].getType()->castTo<AnyFunctionType>();

        assert(param1->getOptionalObjectType());
        assert(param2->isAutoClosure());
        assert(param2->getResult()->getOptionalObjectType());

        (void) param1;
        (void) param2;

        return true;
      };

      isStdlibOptionalMPlusOperator1 = check(decl1);
      isStdlibOptionalMPlusOperator2 = check(decl2);
    }
  }

  // Compare the type variable bindings.
  auto &tc = cs.getTypeChecker();
  for (auto &binding : diff.typeBindings) {
    // If the type variable isn't one for which we should be looking at the
    // bindings, don't.
    if (!binding.typeVar->getImpl().prefersSubtypeBinding())
      continue;

    auto type1 = binding.bindings[idx1];
    auto type2 = binding.bindings[idx2];

    // If the types are equivalent, there's nothing more to do.
    if (type1->isEqual(type2))
      continue;
    
    // If either of the types still contains type variables, we can't
    // compare them.
    // FIXME: This is really unfortunate. More type variable sharing
    // (when it's sane) would help us do much better here.
    if (type1->hasTypeVariable() || type2->hasTypeVariable()) {
      identical = false;
      continue;
    }

    // If one type is a subtype of the other, but not vice-versa,
    // we prefer the system with the more-constrained type.
    // FIXME: Collapse this check into the second check.
    auto type1Better = tc.isSubtypeOf(type1, type2, cs.DC);
    auto type2Better = tc.isSubtypeOf(type2, type1, cs.DC);
    if (type1Better || type2Better) {
      if (type1Better)
        ++score1;
      if (type2Better)
        ++score2;

      // Prefer the unlabeled form of a type.
      auto unlabeled1 = type1->getUnlabeledType(cs.getASTContext());
      auto unlabeled2 = type2->getUnlabeledType(cs.getASTContext());
      if (unlabeled1->isEqual(unlabeled2)) {
        if (type1->isEqual(unlabeled1)) {
          ++score1;
          continue;
        }
        if (type2->isEqual(unlabeled2)) {
          ++score2;
          continue;
        }
      }

      identical = false;
      continue;
    }

    // The systems are not considered equivalent.
    identical = false;

    // If one type is convertible to of the other, but not vice-versa.
    type1Better = tc.isConvertibleTo(type1, type2, cs.DC);
    type2Better = tc.isConvertibleTo(type2, type1, cs.DC);
    if (type1Better || type2Better) {
      if (type1Better)
        ++score1;
      if (type2Better)
        ++score2;
      continue;
    }

    // A concrete type is better than an archetype.
    // FIXME: Total hack.
    if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) {
      if (type1->is<ArchetypeType>())
        ++score2;
      else
        ++score1;
      continue;
    }
    
    // FIXME:
    // This terrible hack is in place to support equality comparisons of non-
    // equatable option types to 'nil'. Until we have a way to constrain a type
    // variable on "!Equatable", if all other aspects of the overload choices
    // are equal, favor the overload that does not require an implicit literal
    // argument conversion to 'nil'.
    // Post-1.0, we'll need to remove this hack in favor of richer constraint
    // declarations.
    if (!(score1 || score2)) {
      if (auto nominalType2 = type2->getNominalOrBoundGenericNominal()) {
        if ((nominalType2->getName() ==
             cs.TC.Context.Id_OptionalNilComparisonType)) {
          ++score2;
        }
      }

      if (auto nominalType1 = type1->getNominalOrBoundGenericNominal()) {
        if ((nominalType1->getName() ==
             cs.TC.Context.Id_OptionalNilComparisonType)) {
          ++score1;
        }
      }
    }
  }
  
  // All other things considered equal, if any overload choice is more
  // more constrained than the other, increment the score.
  if (score1 == score2) {
    if (foundRefinement1) {
      ++score1;
    }
    if (foundRefinement2) {
      ++score2;
    }
  }

  // FIXME: All other things being equal, prefer the catamorphism (flattening)
  // overload of ?? over the mplus (non-flattening) overload.
  if (score1 == score2) {
    // This is correct: we want to /disprefer/ the mplus.
    score2 += isStdlibOptionalMPlusOperator1;
    score1 += isStdlibOptionalMPlusOperator2;
  }

  // FIXME: There are type variables and overloads not common to both solutions
  // that haven't been considered. They make the systems different, but don't
  // affect ranking. We need to handle this.

  // If the scores are different, we have a winner.
  if (score1 != score2) {
    return score1 > score2? SolutionCompareResult::Better
                          : SolutionCompareResult::Worse;
  }

  // Neither system wins; report whether they were identical or not.
  return identical? SolutionCompareResult::Identical
                  : SolutionCompareResult::Incomparable;
}