예제 #1
0
SubstitutionMap GenericEnvironment::
getSubstitutionMap(SubstitutionList subs) const {
  SubstitutionMap result;

  for (auto depTy : getGenericSignature()->getAllDependentTypes()) {

    // Map the interface type to a context type.
    auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
                                 MakeAbstractConformanceForGenericType());

    auto sub = subs.front();
    subs = subs.slice(1);

    // Record the replacement type and its conformances.
    if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
      result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
      for (auto conformance : sub.getConformances())
        result.addConformance(CanType(archetype), conformance);
      continue;
    }

    // FIXME: getAllDependentTypes() includes generic type parameters that
    // have been made concrete.
    assert(contextTy->hasError() || depTy->is<GenericTypeParamType>());
  }

  assert(subs.empty() && "did not use all substitutions?!");

  populateParentMap(result);
  return result;
}
예제 #2
0
static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &SGF,
                                              SILLocation loc,
                                              SubstitutionMap subs,
                                              ArrayRef<ManagedValue> args,
                                              SGFContext C) {
  unsigned NumTailTypes = subs.getReplacementTypes().size() - 1;
  assert(args.size() == NumTailTypes * 2 + 1 &&
         "wrong number of substitutions for allocWithTailElems");

  // The substitution determines the element type for bound memory.
  auto replacementTypes = subs.getReplacementTypes();
  SILType RefType = SGF.getLoweredType(replacementTypes[0]->
                                  getCanonicalType()).getObjectType();

  SmallVector<ManagedValue, 4> Counts;
  SmallVector<SILType, 4> ElemTypes;
  for (unsigned Idx = 0; Idx < NumTailTypes; ++Idx) {
    Counts.push_back(args[Idx * 2 + 1]);
    ElemTypes.push_back(SGF.getLoweredType(replacementTypes[Idx+1]->
                                          getCanonicalType()).getObjectType());
  }
  ManagedValue Metatype = args[0];
  if (isa<MetatypeInst>(Metatype)) {
    auto InstanceType =
      Metatype.getType().castTo<MetatypeType>().getInstanceType();
    assert(InstanceType == RefType.getASTType() &&
           "substituted type does not match operand metatype");
    (void) InstanceType;
    return SGF.B.createAllocRef(loc, RefType, false, false,
                                ElemTypes, Counts);
  } else {
    return SGF.B.createAllocRefDynamic(loc, Metatype, RefType, false,
                                       ElemTypes, Counts);
  }
}
예제 #3
0
SubstitutionMap
SubstitutionMap::combineSubstitutionMaps(const SubstitutionMap &baseSubMap,
                                         const SubstitutionMap &origSubMap,
                                         unsigned baseDepth,
                                         unsigned origDepth,
                                         GenericSignature *baseSig) {
  auto replaceGenericParameter = [&](Type type) -> Type {
    if (auto gp = type->getAs<GenericTypeParamType>()) {
      if (gp->getDepth() < baseDepth) return Type();
      return GenericTypeParamType::get(gp->getDepth() + origDepth - baseDepth,
                                       gp->getIndex(),
                                       baseSig->getASTContext());
    }

    return type;
  };

  return baseSig->getSubstitutionMap(
    [&](SubstitutableType *type) {
      auto replacement = replaceGenericParameter(type);
      if (replacement)
        return Type(replacement).subst(origSubMap);
      return Type(type).subst(baseSubMap);
    },
    [&](CanType type, Type substType, ProtocolType *conformedProtocol) {
      auto replacement = type.transform(replaceGenericParameter);
      if (replacement)
        return origSubMap.lookupConformance(replacement->getCanonicalType(),
                                            conformedProtocol->getDecl());
      return baseSubMap.lookupConformance(type,
                                          conformedProtocol->getDecl());
    });
}
예제 #4
0
/// Specialized emitter for Builtin.castToBridgeObject.
static ManagedValue emitBuiltinCastToBridgeObject(SILGenFunction &SGF,
                                                  SILLocation loc,
                                                  SubstitutionMap subs,
                                                  ArrayRef<ManagedValue> args,
                                                  SGFContext C) {
  assert(args.size() == 2 && "cast should have two arguments");
  assert(subs.getReplacementTypes().size() == 1 &&
         "cast should have a type substitution");
  
  // Take the reference type argument and cast it to BridgeObject.
  SILType objPointerType = SILType::getBridgeObjectType(SGF.F.getASTContext());

  // Bail if the source type is not a class reference of some kind.
  auto sourceType = subs.getReplacementTypes()[0];
  if (!sourceType->mayHaveSuperclass() &&
      !sourceType->isClassExistentialType()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToBridgeObject source must be a class");
    return SGF.emitUndef(objPointerType);
  }

  ManagedValue ref = args[0];
  SILValue bits = args[1].getUnmanagedValue();
  
  // If the argument is existential, open it.
  if (sourceType->isClassExistentialType()) {
    auto openedTy = OpenedArchetypeType::get(sourceType);
    SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
    ref = SGF.B.createOpenExistentialRef(loc, ref, loweredOpenedTy);
  }

  return SGF.B.createRefToBridgeObject(loc, ref, bits);
}
예제 #5
0
파일: Linker.cpp 프로젝트: nkcsgexi/swift
void SILLinkerVisitor::visitApplySubstitutions(const SubstitutionMap &subs) {
  for (auto &reqt : subs.getGenericSignature()->getRequirements()) {
    switch (reqt.getKind()) {
    case RequirementKind::Conformance: {
      auto conformance = subs.lookupConformance(
          reqt.getFirstType()->getCanonicalType(),
          cast<ProtocolDecl>(reqt.getSecondType()->getAnyNominal()))
        .getValue();
      
      // Formally all conformances referenced in a function application are
      // used. However, eagerly visiting them all at this point leads to a
      // large blowup in the amount of SIL we read in, and we aren't very
      // systematic about laziness. For optimization purposes we can defer
      // reading in most conformances until we need them for devirtualization.
      // However, we *must* pull in shared clang-importer-derived conformances
      // we potentially use, since we may not otherwise have a local definition.
      if (mustDeserializeProtocolConformance(Mod, conformance)) {
        visitProtocolConformance(conformance, None);
      }
      break;
    }
    case RequirementKind::Layout:
    case RequirementKind::SameType:
    case RequirementKind::Superclass:
      break;
    }
  }
}
예제 #6
0
/// Specialized emitter for Builtin.beginUnpairedModifyAccess.
static ManagedValue emitBuiltinBeginUnpairedModifyAccess(SILGenFunction &SGF,
                                                    SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
        "Builtin.beginUnpairedModifyAccess should have one substitution");
  assert(args.size() == 3 &&
         "beginUnpairedModifyAccess should be given three arguments");

  SILType elemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               elemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);

  SILType valueBufferTy =
      SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);

  SILValue buffer =
    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 valueBufferTy.getAddressType(),
                                 /*strict*/ true,
                                 /*invariant*/ false);
  SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
                                  SILAccessEnforcement::Dynamic,
                                  /*noNestedConflict*/ false,
                                  /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
예제 #7
0
/// Specialized emitter for Builtin.load and Builtin.take.
static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionMap substitutions,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C,
                                          IsTake_t isTake,
                                          bool isStrict,
                                          bool isInvariant) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "load should have single substitution");
  assert(args.size() == 1 && "load should have a single argument");
  
  // The substitution gives the type of the load.  This is always a
  // first-class type; there is no way to e.g. produce a @weak load
  // with this builtin.
  auto &rvalueTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  SILType loadedType = rvalueTL.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
                                               loadedType.getAddressType(),
                                               isStrict, isInvariant);
  // Perform the load.
  return SGF.emitLoad(loc, addr, rvalueTL, C, isTake);
}
예제 #8
0
static ManagedValue emitCastToReferenceType(SILGenFunction &SGF,
                                            SILLocation loc,
                                            SubstitutionMap substitutions,
                                            ArrayRef<ManagedValue> args,
                                            SGFContext C,
                                            SILType objPointerType) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "cast should have a type substitution");
  
  // Bail if the source type is not a class reference of some kind.
  Type argTy = substitutions.getReplacementTypes()[0];
  if (!argTy->mayHaveSuperclass() && !argTy->isClassExistentialType()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToNativeObject source must be a class");
    return SGF.emitUndef(objPointerType);
  }

  // Grab the argument.
  ManagedValue arg = args[0];

  // If the argument is existential, open it.
  if (argTy->isClassExistentialType()) {
    auto openedTy = OpenedArchetypeType::get(argTy);
    SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
    arg = SGF.B.createOpenExistentialRef(loc, arg, loweredOpenedTy);
  }

  // Return the cast result.
  return SGF.B.createUncheckedRefCast(loc, arg, objPointerType);
}
예제 #9
0
static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
                                      SILLocation loc,
                                      SubstitutionMap substitutions,
                                      ArrayRef<ManagedValue> args,
                                      SGFContext C) {
  assert(args.size() >= 2 && "assign should have two arguments");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "assign should have a single substitution");

  // The substitution determines the type of the thing we're destroying.
  CanType assignFormalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  SILType assignType = SGF.getLoweredType(assignFormalType);
  
  // Convert the destination pointer argument to a SIL address.
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args.back().getUnmanagedValue(),
                                               assignType.getAddressType(),
                                               /*isStrict*/ true,
                                               /*isInvariant*/ false);
  
  // Build the value to be assigned, reconstructing tuples if needed.
  auto src = RValue(SGF, args.slice(0, args.size() - 1), assignFormalType);
  
  std::move(src).ensurePlusOne(SGF, loc).assignInto(SGF, loc, addr);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
예제 #10
0
/// Specialized emitter for Builtin.destroy.
static ManagedValue emitBuiltinDestroy(SILGenFunction &SGF,
                                       SILLocation loc,
                                       SubstitutionMap substitutions,
                                       ArrayRef<ManagedValue> args,
                                       SGFContext C) {
  assert(args.size() == 2 && "destroy should have two arguments");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "destroy should have a single substitution");
  // The substitution determines the type of the thing we're destroying.
  auto &ti = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  
  // Destroy is a no-op for trivial types.
  if (ti.isTrivial())
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
  
  SILType destroyType = ti.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr =
    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 destroyType.getAddressType(),
                                 /*isStrict*/ true,
                                 /*isInvariant*/ false);
  
  // Destroy the value indirectly. Canonicalization will promote to loads
  // and releases if appropriate.
  SGF.B.createDestroyAddr(loc, addr);
  
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
예제 #11
0
/// Specialized emitter for Builtin.reinterpretCast.
static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  assert(args.size() == 1 && "reinterpretCast should be given one argument");
  assert(substitutions.getReplacementTypes().size() == 2 &&
         "reinterpretCast should have two subs");
  
  auto &fromTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  auto &toTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[1]);
  
  // If casting between address types, cast the address.
  if (fromTL.isAddress() || toTL.isAddress()) {
    SILValue fromAddr;

    // If the from value is not an address, move it to a buffer.
    if (!fromTL.isAddress()) {
      fromAddr = SGF.emitTemporaryAllocation(loc, args[0].getValue()->getType());
      fromTL.emitStore(SGF.B, loc, args[0].getValue(), fromAddr,
                       StoreOwnershipQualifier::Init);
    } else {
      fromAddr = args[0].getValue();
    }
    auto toAddr = SGF.B.createUncheckedAddrCast(loc, fromAddr,
                                      toTL.getLoweredType().getAddressType());
    
    // Load and retain the destination value if it's loadable. Leave the cleanup
    // on the original value since we don't know anything about it's type.
    if (!toTL.isAddress()) {
      return SGF.emitManagedLoadCopy(loc, toAddr, toTL);
    }
    // Leave the cleanup on the original value.
    if (toTL.isTrivial())
      return ManagedValue::forUnmanaged(toAddr);

    // Initialize the +1 result buffer without taking the incoming value. The
    // source and destination cleanups will be independent.
    return SGF.B.bufferForExpr(
        loc, toTL.getLoweredType(), toTL, C,
        [&](SILValue bufferAddr) {
          SGF.B.createCopyAddr(loc, toAddr, bufferAddr, IsNotTake,
                               IsInitialization);
        });
  }
  // Create the appropriate bitcast based on the source and dest types.
  ManagedValue in = args[0];
  SILType resultTy = toTL.getLoweredType();
  if (resultTy.isTrivial(SGF.F))
    return SGF.B.createUncheckedTrivialBitCast(loc, in, resultTy);

  // If we can perform a ref cast, just return.
  if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, in, resultTy))
    return refCast;

  // Otherwise leave the original cleanup and retain the cast value.
  SILValue out = SGF.B.createUncheckedBitwiseCast(loc, in.getValue(), resultTy);
  return SGF.emitManagedRetain(loc, out, toTL);
}
예제 #12
0
void GenericEnvironment::
getSubstitutionMap(ModuleDecl *mod,
                   GenericSignature *sig,
                   ArrayRef<Substitution> subs,
                   SubstitutionMap &result) const {
  for (auto depTy : sig->getAllDependentTypes()) {

    // Map the interface type to a context type.
    auto contextTy = depTy.subst(mod, InterfaceToArchetypeMap, SubstOptions());
    auto *archetype = contextTy->castTo<ArchetypeType>();

    auto sub = subs.front();
    subs = subs.slice(1);

    // Record the replacement type and its conformances.
    result.addSubstitution(CanType(archetype), sub.getReplacement());
    result.addConformances(CanType(archetype), sub.getConformances());
  }

  for (auto reqt : sig->getRequirements()) {
    if (reqt.getKind() != RequirementKind::SameType)
      continue;

    auto first = reqt.getFirstType()->getAs<DependentMemberType>();
    auto second = reqt.getSecondType()->getAs<DependentMemberType>();

    if (!first || !second)
      continue;

    auto archetype = mapTypeIntoContext(mod, first)->getAs<ArchetypeType>();
    if (!archetype)
      continue;

    auto firstBase = first->getBase();
    auto secondBase = second->getBase();

    auto firstBaseArchetype = mapTypeIntoContext(mod, firstBase)->getAs<ArchetypeType>();
    auto secondBaseArchetype = mapTypeIntoContext(mod, secondBase)->getAs<ArchetypeType>();

    if (!firstBaseArchetype || !secondBaseArchetype)
      continue;

    if (archetype->getParent() != firstBaseArchetype)
      result.addParent(CanType(archetype),
                       CanType(firstBaseArchetype),
                       first->getAssocType());
    if (archetype->getParent() != secondBaseArchetype)
      result.addParent(CanType(archetype),
                       CanType(secondBaseArchetype),
                       second->getAssocType());
  }

  assert(subs.empty() && "did not use all substitutions?!");
}
예제 #13
0
SubstitutionMap SubstitutionMap::get(GenericSignature *genericSig,
                                     SubstitutionMap substitutions) {
  if (!genericSig) {
    assert(!substitutions.hasAnySubstitutableParams() &&
           "Shouldn't have substitutions here");
    return SubstitutionMap();
  }

  return SubstitutionMap::get(genericSig,
           [&](SubstitutableType *type) -> Type {
             return substitutions.lookupSubstitution(
                      CanSubstitutableType(type));
           },
           LookUpConformanceInSubstitutionMap(substitutions));
}
예제 #14
0
void SubstitutionMap::addSubstitutions(SubstitutionMap& subMap, bool invalidateCache)
{
  SubstitutionMap::NodeMap::const_iterator it = subMap.begin();
  SubstitutionMap::NodeMap::const_iterator it_end = subMap.end();
  for (; it != it_end; ++ it) {
    Assert(d_substitutions.find((*it).first) == d_substitutions.end());
    d_substitutions[(*it).first] = (*it).second;
    if (!invalidateCache) {
      d_substitutionCache[(*it).first] = d_substitutions[(*it).first];
    }
  }
  if (invalidateCache) {
    d_cacheInvalidated = true;
  }
}
예제 #15
0
SubstitutionMap
SubstitutionMap::combineSubstitutionMaps(SubstitutionMap firstSubMap,
                                         SubstitutionMap secondSubMap,
                                         CombineSubstitutionMaps how,
                                         unsigned firstDepthOrIndex,
                                         unsigned secondDepthOrIndex,
                                         GenericSignature *genericSig) {
  auto &ctx = genericSig->getASTContext();

  auto replaceGenericParameter = [&](Type type) -> Type {
    if (auto gp = type->getAs<GenericTypeParamType>()) {
      if (how == CombineSubstitutionMaps::AtDepth) {
        if (gp->getDepth() < firstDepthOrIndex)
          return Type();
        return GenericTypeParamType::get(
          gp->getDepth() + secondDepthOrIndex - firstDepthOrIndex,
          gp->getIndex(),
          ctx);
      }

      assert(how == CombineSubstitutionMaps::AtIndex);
      if (gp->getIndex() < firstDepthOrIndex)
        return Type();
      return GenericTypeParamType::get(
        gp->getDepth(),
        gp->getIndex() + secondDepthOrIndex - firstDepthOrIndex,
        ctx);
    }

    return type;
  };

  return get(
    genericSig,
    [&](SubstitutableType *type) {
      auto replacement = replaceGenericParameter(type);
      if (replacement)
        return Type(replacement).subst(secondSubMap);
      return Type(type).subst(firstSubMap);
    },
    [&](CanType type, Type substType, ProtocolDecl *conformedProtocol) {
      auto replacement = type.transform(replaceGenericParameter);
      if (replacement)
        return secondSubMap.lookupConformance(replacement->getCanonicalType(),
                                              conformedProtocol);
      return firstSubMap.lookupConformance(type, conformedProtocol);
    });
}
예제 #16
0
void GenericEnvironment::populateParentMap(SubstitutionMap &subMap) const {
  for (auto reqt : getGenericSignature()->getRequirements()) {
    if (reqt.getKind() != RequirementKind::SameType)
      continue;

    auto first = reqt.getFirstType();
    auto second = reqt.getSecondType();

    auto archetype = first.subst(
        QueryInterfaceTypeSubstitutions(this),
        MakeAbstractConformanceForGenericType())
      ->getAs<ArchetypeType>();
    if (!archetype)
      continue;

#ifndef NDEBUG
    auto secondArchetype = second.subst(
        QueryInterfaceTypeSubstitutions(this),
        MakeAbstractConformanceForGenericType())
      ->getAs<ArchetypeType>();
    assert(secondArchetype == archetype);
#endif

    if (auto *firstMemTy = first->getAs<DependentMemberType>()) {
      auto parent = firstMemTy->getBase().subst(
        QueryInterfaceTypeSubstitutions(this),
        MakeAbstractConformanceForGenericType())
          ->getAs<ArchetypeType>();
      if (parent && archetype->getParent() != parent) {
        subMap.addParent(CanType(archetype),
                         CanType(parent),
                         firstMemTy->getAssocType());
      }
    }

    if (auto *secondMemTy = second->getAs<DependentMemberType>()) {
      auto parent = secondMemTy->getBase().subst(
        QueryInterfaceTypeSubstitutions(this),
        MakeAbstractConformanceForGenericType())
          ->getAs<ArchetypeType>();
      if (parent && archetype->getParent() != parent) {
        subMap.addParent(CanType(archetype),
                         CanType(parent),
                         secondMemTy->getAssocType());
      }
    }
  }
}
예제 #17
0
/// Emit Builtin.initialize by evaluating the operand directly into
/// the address.
static ManagedValue emitBuiltinInit(SILGenFunction &SGF,
                                    SILLocation loc,
                                    SubstitutionMap substitutions,
                                    PreparedArguments &&preparedArgs,
                                    SGFContext C) {
  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
  if (!argsOrError)
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));

  auto args = *argsOrError;

  CanType formalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  auto &formalTL = SGF.getTypeLowering(formalType);

  SILValue addr = SGF.emitRValueAsSingleValue(args[1]).getUnmanagedValue();
  addr = SGF.B.createPointerToAddress(
    loc, addr, formalTL.getLoweredType().getAddressType(),
    /*isStrict*/ true,
    /*isInvariant*/ false);

  TemporaryInitialization init(addr, CleanupHandle::invalid());
  SGF.emitExprInto(args[0], &init);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
예제 #18
0
static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionMap subs,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C) {
  assert(subs.getReplacementTypes().size() == 1 && "bindMemory should have a single substitution");
  assert(args.size() == 3 && "bindMemory should have three argument");

  // The substitution determines the element type for bound memory.
  CanType boundFormalType = subs.getReplacementTypes()[0]->getCanonicalType();
  SILType boundType = SGF.getLoweredType(boundFormalType);

  SGF.B.createBindMemory(loc, args[0].getValue(),
                         args[1].getValue(), boundType);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
예제 #19
0
파일: abstraction.cpp 프로젝트: jinala/CVC4
void AbstractionModule::makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map) {
  if (map.hasSubstitution(node)) {
    return;
  }
  if (node.getMetaKind() == kind::metakind::VARIABLE) {
    Node skolem = utils::mkVar(utils::getSize(node));
    map.addSubstitution(node, skolem);
    reverse_map.addSubstitution(skolem, node);
    return;
  }
  if (node.isConst())
    return;

  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
    makeFreshSkolems(node[i], map, reverse_map);
  }
}
예제 #20
0
Witness::Witness(ValueDecl *decl, SubstitutionMap substitutions,
                 GenericEnvironment *syntheticEnv,
                 SubstitutionMap reqToSynthesizedEnvSubs) {
  if (!syntheticEnv && substitutions.empty() &&
      reqToSynthesizedEnvSubs.empty()) {
    storage = decl;
    return;
  }

  auto &ctx = decl->getASTContext();
  auto declRef = ConcreteDeclRef(decl, substitutions);
  auto storedMem = ctx.Allocate(sizeof(StoredWitness), alignof(StoredWitness));
  auto stored = new (storedMem) StoredWitness{declRef, syntheticEnv,
                                              reqToSynthesizedEnvSubs};

  storage = stored;
}
예제 #21
0
static ManagedValue emitBuiltinTypeTrait(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1
         && "type trait should take a single type parameter");
  assert(args.size() == 1
         && "type trait should take a single argument");
  
  unsigned result;
  
  auto traitTy = substitutions.getReplacementTypes()[0]->getCanonicalType();
  
  switch ((traitTy.getPointer()->*Trait)()) {
  // If the type obviously has or lacks the trait, emit a constant result.
  case TypeTraitResult::IsNot:
    result = 0;
    break;
  case TypeTraitResult::Is:
    result = 1;
    break;
      
  // If not, emit the builtin call normally. Specialization may be able to
  // eliminate it later, or we'll lower it away at IRGen time.
  case TypeTraitResult::CanBe: {
    auto &C = SGF.getASTContext();
    auto int8Ty = BuiltinIntegerType::get(8, C)->getCanonicalType();
    auto apply = SGF.B.createBuiltin(loc,
                                     C.getIdentifier(getBuiltinName(Kind)),
                                     SILType::getPrimitiveObjectType(int8Ty),
                                     substitutions, args[0].getValue());
    
    return ManagedValue::forUnmanaged(apply);
  }
  }
  
  // Produce the result as an integer literal constant.
  auto val = SGF.B.createIntegerLiteral(
      loc, SILType::getBuiltinIntegerType(8, SGF.getASTContext()),
      (uintmax_t)result);
  return ManagedValue::forUnmanaged(val);
}
예제 #22
0
static std::pair<ManagedValue, SILDeclRef>
getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk,
                       ManagedValue selfArg, SubstitutionMap curriedSubs) {
  auto *vd = thunk.getDecl();

  // Reference the next uncurrying level of the function.
  SILDeclRef next = SILDeclRef(vd, thunk.kind);
  assert(!next.isCurried);

  auto constantInfo = SGF.SGM.Types.getConstantInfo(next);

  // If the function is natively foreign, reference its foreign entry point.
  if (requiresForeignToNativeThunk(vd))
    return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
            next};

  // If the thunk is a curry thunk for a direct method reference, we are
  // doing a direct dispatch (eg, a fragile 'super.foo()' call).
  if (thunk.isDirectReference)
    return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
            next};

  if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
    if (getMethodDispatch(func) == MethodDispatch::Class) {
      // Use the dynamic thunk if dynamic.
      if (vd->isObjCDynamic()) {
        return {SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType),
                next};
      }

      auto methodTy = SGF.SGM.Types.getConstantOverrideType(next);
      SILValue result =
          SGF.emitClassMethodRef(loc, selfArg.getValue(), next, methodTy);
      return {ManagedValue::forUnmanaged(result),
              next.getOverriddenVTableEntry()};
    }

    // If the fully-uncurried reference is to a generic method, look up the
    // witness.
    if (constantInfo.SILFnType->getRepresentation()
          == SILFunctionTypeRepresentation::WitnessMethod) {
      auto protocol = func->getDeclContext()->getSelfProtocolDecl();
      auto origSelfType = protocol->getSelfInterfaceType()->getCanonicalType();
      auto substSelfType = origSelfType.subst(curriedSubs)->getCanonicalType();
      auto conformance = curriedSubs.lookupConformance(origSelfType, protocol);
      auto result = SGF.B.createWitnessMethod(loc, substSelfType, *conformance,
                                              next, constantInfo.getSILType());
      return {ManagedValue::forUnmanaged(result), next};
    }
  }

  // Otherwise, emit a direct call.
  return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
          next};
}
예제 #23
0
// Initialize SpecializedType iff the specialization is allowed.
ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
                                     ArrayRef<Substitution> ParamSubs) {
  if (!OrigF->shouldOptimize()) {
    DEBUG(llvm::dbgs() << "    Cannot specialize function " << OrigF->getName()
                       << " marked to be excluded from optimizations.\n");
    return;
  }

  SubstitutionMap InterfaceSubs;
  if (OrigF->getLoweredFunctionType()->getGenericSignature())
    InterfaceSubs = OrigF->getLoweredFunctionType()->getGenericSignature()
      ->getSubstitutionMap(ParamSubs);

  // We do not support partial specialization.
  if (hasUnboundGenericTypes(InterfaceSubs.getMap())) {
    DEBUG(llvm::dbgs() <<
          "    Cannot specialize with unbound interface substitutions.\n");
    DEBUG(for (auto Sub : ParamSubs) {
            Sub.dump();
          });
예제 #24
0
static ManagedValue emitBuiltinClassifyBridgeObject(SILGenFunction &SGF,
                                                    SILLocation loc,
                                                    SubstitutionMap subs,
                                                    ArrayRef<ManagedValue> args,
                                                    SGFContext C) {
  assert(args.size() == 1 && "classify should have one argument");
  assert(subs.empty() && "classify should not have subs");

  SILValue result = SGF.B.createClassifyBridgeObject(loc, args[0].getValue());
  return ManagedValue::forUnmanaged(result);
}
예제 #25
0
static ManagedValue emitBuiltinValueToBridgeObject(SILGenFunction &SGF,
                                                   SILLocation loc,
                                                   SubstitutionMap subs,
                                                   ArrayRef<ManagedValue> args,
                                                   SGFContext C) {
  assert(args.size() == 1 && "ValueToBridgeObject should have one argument");
  assert(subs.getReplacementTypes().size() == 1 &&
         "ValueToBridgeObject should have one sub");

  Type argTy = subs.getReplacementTypes()[0];
  if (!argTy->is<BuiltinIntegerType>()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "argument to builtin should be a builtin integer");
    SILType objPointerType = SILType::getBridgeObjectType(SGF.F.getASTContext());
    return SGF.emitUndef(objPointerType);
  }

  SILValue result = SGF.B.createValueToBridgeObject(loc, args[0].getValue());
  return SGF.emitManagedRetain(loc, result);
}
예제 #26
0
static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
                                                SILLocation loc,
                                                SubstitutionMap subs,
                                                ArrayRef<ManagedValue> args,
                                                SGFContext C) {
  assert(subs.getReplacementTypes().size() == 2 &&
         "allocWithTailElems should have two substitutions");
  assert(args.size() == 2 &&
         "allocWithTailElems should have three arguments");

  // The substitution determines the element type for bound memory.
  SILType ElemType = SGF.getLoweredType(subs.getReplacementTypes()[1]->
                                        getCanonicalType()).getObjectType();

  SILValue result = SGF.B.createRefTailAddr(loc, args[0].getValue(),
                                            ElemType.getAddressType());
  SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
  result = SGF.B.createAddressToPointer(loc, result, rawPointerType);
  return ManagedValue::forUnmanaged(result);
}
예제 #27
0
/// Specialized emitter for Builtin.gep.
static ManagedValue emitBuiltinGep(SILGenFunction &SGF,
                                   SILLocation loc,
                                   SubstitutionMap substitutions,
                                   ArrayRef<ManagedValue> args,
                                   SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "gep should have two substitutions");
  assert(args.size() == 3 && "gep should be given three arguments");

  SILType ElemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILType RawPtrType = args[0].getUnmanagedValue()->getType();
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               ElemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);
  addr = SGF.B.createIndexAddr(loc, addr, args[1].getUnmanagedValue());
  addr = SGF.B.createAddressToPointer(loc, addr, RawPtrType);

  return ManagedValue::forUnmanaged(addr);
}
예제 #28
0
/// Specialized emitter for Builtin.bridgeFromRawPointer.
static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "bridge should have a single substitution");
  assert(args.size() == 1 && "bridge should have a single argument");
  
  // The substitution determines the destination type.
  // FIXME: Archetype destination type?
  auto &destLowering =
    SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  assert(destLowering.isLoadable());
  SILType destType = destLowering.getLoweredType();

  // Take the raw pointer argument and cast it to the destination type.
  SILValue result = SGF.B.createRawPointerToRef(loc, args[0].getUnmanagedValue(),
                                                destType);
  // The result has ownership semantics, so retain it with a cleanup.
  return SGF.emitManagedRetain(loc, result, destLowering);
}
예제 #29
0
SubstitutionMap ProtocolConformance::getSubstitutions(ModuleDecl *M) const {
  // Walk down to the base NormalProtocolConformance.
  SubstitutionMap subMap;
  const ProtocolConformance *parent = this;
  while (!isa<NormalProtocolConformance>(parent)) {
    switch (parent->getKind()) {
    case ProtocolConformanceKind::Normal:
      llvm_unreachable("should have exited the loop?!");
    case ProtocolConformanceKind::Inherited:
      parent =
          cast<InheritedProtocolConformance>(parent)->getInheritedConformance();
      break;
    case ProtocolConformanceKind::Specialized: {
      auto SC = cast<SpecializedProtocolConformance>(parent);
      parent = SC->getGenericConformance();
      assert(subMap.empty() && "multiple conformance specializations?!");
      subMap = SC->getSubstitutionMap();
      break;
    }
    }
  }

  // Found something; we're done!
  if (!subMap.empty())
    return subMap;

  // If the normal conformance is for a generic type, and we didn't hit a
  // specialized conformance, collect the substitutions from the generic type.
  // FIXME: The AST should do this for us.
  const NormalProtocolConformance *normalC =
      cast<NormalProtocolConformance>(parent);

  if (!normalC->getType()->isSpecialized())
    return SubstitutionMap();

  auto *DC = normalC->getDeclContext();
  return normalC->getType()->getContextSubstitutionMap(M, DC);
}
예제 #30
0
SubstitutionMap
GenericEnvironment::
getSubstitutionMap(TypeSubstitutionFn subs,
                   GenericSignature::LookupConformanceFn lookupConformance) const {
  SubstitutionMap subMap;

  getGenericSignature()->enumeratePairedRequirements(
    [&](Type depTy, ArrayRef<Requirement> reqs) -> bool {

      // Map the interface type to a context type.
      auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
                                   MakeAbstractConformanceForGenericType());

      // Compute the replacement type.
      Type currentReplacement = contextTy.subst(subs, lookupConformance,
                                                SubstFlags::UseErrorType);
      if (auto archetypeTy = contextTy->getAs<ArchetypeType>()) {
        subMap.addSubstitution(CanArchetypeType(archetypeTy),
                               currentReplacement);

        // Collect the conformances.
        for (auto req: reqs) {
          assert(req.getKind() == RequirementKind::Conformance);
          auto protoType = req.getSecondType()->castTo<ProtocolType>();
          auto conformance = lookupConformance(CanArchetypeType(archetypeTy),
                                               currentReplacement,
                                               protoType);
          if (conformance)
            subMap.addConformance(CanArchetypeType(archetypeTy), *conformance);
        }
      }

      return false;
    });

  populateParentMap(subMap);
  return subMap;
}