Example #1
0
ManagedValue SILGenFunction::emitFunctionRef(SILLocation loc,
                                             SILDeclRef constant,
                                             SILConstantInfo constantInfo) {
  // If the function has captures, apply them.
  if (auto fn = constant.getAnyFunctionRef()) {
    if (fn->getCaptureInfo().hasLocalCaptures() ||
        fn->getCaptureInfo().hasGenericParamCaptures()) {
      return emitClosureValue(loc, constant, *fn);
    }
  }

  // Otherwise, use a global FunctionRefInst.
  SILValue c = emitGlobalFunctionRef(loc, constant, constantInfo);
  return ManagedValue::forUnmanaged(c);
}
Example #2
0
ManagedValue
SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
                                 CanType expectedType,
                                 ArrayRef<Substitution> subs) {
  auto closure = *constant.getAnyFunctionRef();
  auto captureInfo = closure.getCaptureInfo();

  assert(((constant.uncurryLevel == 1 &&
           captureInfo.hasLocalCaptures()) ||
          (constant.uncurryLevel == 0 &&
           !captureInfo.hasLocalCaptures())) &&
         "curried local functions not yet supported");

  auto constantInfo = getConstantInfo(constant);
  SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo);
  SILType functionTy = functionRef->getType();

  // Apply substitutions.
  auto pft = constantInfo.SILFnType;

  bool wasSpecialized = false;
  if (pft->isPolymorphic()) {
    // If the lowered function type is generic but Sema did not hand us any
    // substitutions, the function is a local function that appears in a
    // generic context but does not have a generic parameter list of its own;
    // just use our forwarding substitutions.
    if (subs.empty()) {
      assert(closure.getAsDeclContext()->isLocalContext() &&
             "cannot reference generic global function without substitutions");
      subs = getForwardingSubstitutions();
    }
    auto specialized = pft->substGenericArgs(F.getModule(),
                                             F.getModule().getSwiftModule(),
                                             subs);
    functionTy = SILType::getPrimitiveObjectType(specialized);
    wasSpecialized = true;
  }

  // If we're in top-level code, we don't need to physically capture script
  // globals, but we still need to mark them as escaping so that DI can flag
  // uninitialized uses.
  if (this == SGM.TopLevelSGF) {
    SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals(
        loc, captureInfo);
  }

  if (!captureInfo.hasLocalCaptures() && !wasSpecialized) {
    auto result = ManagedValue::forUnmanaged(functionRef);
    return emitOrigToSubstValue(loc, result,
                                AbstractionPattern(expectedType),
                                expectedType);
  }

  SmallVector<ManagedValue, 4> capturedArgs;
  emitCaptures(loc, closure, CaptureEmission::PartialApplication,
               capturedArgs);

  // The partial application takes ownership of the context parameters.
  SmallVector<SILValue, 4> forwardedArgs;
  for (auto capture : capturedArgs)
    forwardedArgs.push_back(capture.forward(*this));

  SILType closureTy =
    SILGenBuilder::getPartialApplyResultType(functionRef->getType(),
                                             capturedArgs.size(), SGM.M,
                                             subs);
  auto toClosure =
    B.createPartialApply(loc, functionRef, functionTy,
                         subs, forwardedArgs, closureTy);
  auto result = emitManagedRValueWithCleanup(toClosure);

  // Get the lowered AST types:
  //  - the original type
  auto origLoweredFormalType =
      AbstractionPattern(constantInfo.LoweredInterfaceType);
  if (captureInfo.hasLocalCaptures()) {
    // Get the unlowered formal type of the constant, stripping off
    // the first level of function application, which applies captures.
    origLoweredFormalType =
      AbstractionPattern(constantInfo.FormalInterfaceType)
          .getFunctionResultType();

    // Lower it, being careful to use the right generic signature.
    origLoweredFormalType =
      AbstractionPattern(
          origLoweredFormalType.getGenericSignature(),
          SGM.Types.getLoweredASTFunctionType(
              cast<FunctionType>(origLoweredFormalType.getType()),
              0, constant));
  }

  // - the substituted type
  auto substFormalType = cast<FunctionType>(expectedType);
  auto substLoweredFormalType =
    SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant);

  // Generalize if necessary.
  result = emitOrigToSubstValue(loc, result, origLoweredFormalType,
                                substLoweredFormalType);

  return result;
}
Example #3
0
ManagedValue
SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
                                 CanType expectedType,
                                 SubstitutionList subs) {
  auto closure = *constant.getAnyFunctionRef();
  auto captureInfo = closure.getCaptureInfo();
  auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(closure);
  auto hasCaptures = SGM.Types.hasLoweredLocalCaptures(closure);
  assert(((constant.uncurryLevel == 1 && hasCaptures) ||
          (constant.uncurryLevel == 0 && !hasCaptures)) &&
         "curried local functions not yet supported");

  auto constantInfo = getConstantInfo(constant);
  SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo);
  SILType functionTy = functionRef->getType();

  // Apply substitutions.
  auto pft = constantInfo.SILFnType;

  auto *dc = closure.getAsDeclContext()->getParent();
  if (dc->isLocalContext() && !loweredCaptureInfo.hasGenericParamCaptures()) {
    // If the lowered function type is not polymorphic but we were given
    // substitutions, we have a closure in a generic context which does not
    // capture generic parameters. Just drop the substitutions.
    subs = { };
  } else if (closure.getAbstractClosureExpr()) {
    // If we have a closure expression in generic context, Sema won't give
    // us substitutions, so we just use the forwarding substitutions from
    // context.
    subs = getForwardingSubstitutions();
  }

  bool wasSpecialized = false;
  if (!subs.empty()) {
    auto specialized = pft->substGenericArgs(F.getModule(), subs);
    functionTy = SILType::getPrimitiveObjectType(specialized);
    wasSpecialized = true;
  }

  // If we're in top-level code, we don't need to physically capture script
  // globals, but we still need to mark them as escaping so that DI can flag
  // uninitialized uses.
  if (this == SGM.TopLevelSGF) {
    SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals(
        loc, captureInfo);
  }

  if (!hasCaptures && !wasSpecialized) {
    auto result = ManagedValue::forUnmanaged(functionRef);
    return emitOrigToSubstValue(loc, result,
                                AbstractionPattern(expectedType),
                                expectedType);
  }

  SmallVector<ManagedValue, 4> capturedArgs;
  emitCaptures(loc, closure, CaptureEmission::PartialApplication,
               capturedArgs);

  // The partial application takes ownership of the context parameters.
  SmallVector<SILValue, 4> forwardedArgs;
  for (auto capture : capturedArgs)
    forwardedArgs.push_back(capture.forward(*this));

  SILType closureTy =
    SILGenBuilder::getPartialApplyResultType(functionRef->getType(),
                                             capturedArgs.size(), SGM.M,
                                             subs,
                                             ParameterConvention::Direct_Owned);
  auto toClosure =
    B.createPartialApply(loc, functionRef, functionTy,
                         subs, forwardedArgs, closureTy);
  auto result = emitManagedRValueWithCleanup(toClosure);

  // Get the lowered AST types:
  //  - the original type
  auto origLoweredFormalType =
      AbstractionPattern(constantInfo.LoweredInterfaceType);
  if (hasCaptures) {
    // Get the unlowered formal type of the constant, stripping off
    // the first level of function application, which applies captures.
    origLoweredFormalType =
      AbstractionPattern(constantInfo.FormalInterfaceType)
          .getFunctionResultType();

    // Lower it, being careful to use the right generic signature.
    origLoweredFormalType =
      AbstractionPattern(
          origLoweredFormalType.getGenericSignature(),
          SGM.Types.getLoweredASTFunctionType(
              cast<FunctionType>(origLoweredFormalType.getType()),
              0, constant));
  }

  // - the substituted type
  auto substFormalType = cast<FunctionType>(expectedType);
  auto substLoweredFormalType =
    SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant);

  // Generalize if necessary.
  result = emitOrigToSubstValue(loc, result, origLoweredFormalType,
                                substLoweredFormalType);

  return result;
}