Esempio n. 1
0
ManagedValue
SILGenFunction::emitPreconditionOptionalHasValue(SILLocation loc,
                                                 ManagedValue optional) {
  // Generate code to the optional is present, and if not, abort with a message
  // (provided by the stdlib).
  SILBasicBlock *contBB = createBasicBlock();
  SILBasicBlock *failBB = createBasicBlock();

  bool hadCleanup = optional.hasCleanup();
  bool hadLValue = optional.isLValue();

  auto noneDecl = getASTContext().getOptionalNoneDecl();
  auto someDecl = getASTContext().getOptionalSomeDecl();
  if (optional.getType().isAddress()) {
    // We forward in the creation routine for
    // unchecked_take_enum_data_addr. switch_enum_addr is a +0 operation.
    B.createSwitchEnumAddr(loc, optional.getValue(),
                           /*defaultDest*/ nullptr,
                           {{someDecl, contBB}, {noneDecl, failBB}});
  } else {
    B.createSwitchEnum(loc, optional.forward(*this),
                       /*defaultDest*/ nullptr,
                       {{someDecl, contBB}, {noneDecl, failBB}});
  }
  B.emitBlock(failBB);

  // Call the standard library implementation of _diagnoseUnexpectedNilOptional.
  if (auto diagnoseFailure =
        getASTContext().getDiagnoseUnexpectedNilOptional(nullptr)) {
    ManagedValue args[4];
    emitSourceLocationArgs(*this, loc, args);
    
    emitApplyOfLibraryIntrinsic(loc, diagnoseFailure, SubstitutionMap(), args,
                                SGFContext());
  }

  B.createUnreachable(loc);
  B.clearInsertionPoint();
  B.emitBlock(contBB);

  ManagedValue result;
  SILType payloadType = optional.getType().getAnyOptionalObjectType();

  if (payloadType.isObject()) {
    result = B.createOwnedPHIArgument(payloadType);
  } else {
    result =
        B.createUncheckedTakeEnumDataAddr(loc, optional, someDecl, payloadType);
  }

  if (hadCleanup) {
    return result;
  }

  if (hadLValue) {
    return ManagedValue::forLValue(result.forward(*this));
  }

  return ManagedValue::forUnmanaged(result.forward(*this));
}
Esempio n. 2
0
ManagedValue SILGenFunction::emitCheckedGetOptionalValueFrom(SILLocation loc,
                                                      ManagedValue src,
                                                      const TypeLowering &optTL,
                                                      SGFContext C) {
  SILType optType = src.getType().getObjectType();
  OptionalTypeKind optionalKind;
  CanType valueType = getOptionalValueType(optType, optionalKind);

  FuncDecl *fn = getASTContext().getOptionalUnwrappedDecl(
      nullptr, optionalKind);
  Substitution sub = getSimpleSubstitution(fn, valueType);

  // The intrinsic takes its parameter indirectly.
  if (src.getType().isObject()) {
    auto buf = emitTemporaryAllocation(loc, src.getType());
    B.createStore(loc, src.forward(*this), buf);
    src = emitManagedBufferWithCleanup(buf);
  }

  RValue result = emitApplyOfLibraryIntrinsic(loc, fn, sub, src, C);
  if (result) {
    return std::move(result).getAsSingleValue(*this, loc);
  } else {
    return ManagedValue::forInContext();
  }
}
Esempio n. 3
0
static ManagedValue emitNativeToCBridgedValue(SILGenFunction &gen,
                                              SILLocation loc,
                                              ManagedValue v,
                                              SILType bridgedTy) {
  assert(v.getType().isLoadable(gen.F.getModule()) &&
         "Cannot bridge address-only types");

  CanType loweredBridgedTy = bridgedTy.getSwiftRValueType();
  CanType loweredNativeTy = v.getType().getSwiftRValueType();
  if (loweredNativeTy == loweredBridgedTy)
    return v;

  if (loweredNativeTy.getAnyOptionalObjectType()) {
    return gen.emitOptionalToOptional(loc, v, bridgedTy,
                                      emitNativeToCBridgedValue);
  }
  
  // Check if we need to wrap the bridged result in an optional.
  OptionalTypeKind OTK;
  if (SILType bridgedObjectType =
        bridgedTy.getAnyOptionalObjectType(gen.SGM.M, OTK)) {
    auto bridgedPayload
      = emitNativeToCBridgedNonoptionalValue(gen, loc, v, bridgedObjectType);
    
    return gen.getOptionalSomeValue(loc, bridgedPayload,
                                    gen.getTypeLowering(bridgedTy));
  }
  
  return emitNativeToCBridgedNonoptionalValue(gen, loc, v, bridgedTy);
}
Esempio n. 4
0
ManagedValue SILGenBuilder::createBlockToAnyObject(SILLocation loc,
                                                   ManagedValue v,
                                                   SILType destType) {
  assert(SGF.getASTContext().LangOpts.EnableObjCInterop);
  assert(destType.isAnyObject());
  assert(v.getType().is<SILFunctionType>());
  assert(v.getType().castTo<SILFunctionType>()->getRepresentation() ==
           SILFunctionTypeRepresentation::Block);

  // For now, we don't have a better instruction than this.
  return createUncheckedRefCast(loc, v, destType);
}
Esempio n. 5
0
ManagedValue Scope::popPreservingValue(ManagedValue mv) {
  // If we have a value, make sure that it is an object. The reason why is
  // that we want to make sure that we are not forwarding a cleanup for a
  // stack location that will be destroyed by this scope.
  assert(mv && mv.getType().isObject() &&
         (mv.getType().isTrivial(cleanups.SGF.getModule()) ||
          mv.getOwnershipKind() == ValueOwnershipKind::Trivial ||
          mv.hasCleanup()));
  CleanupCloner cloner(cleanups.SGF, mv);
  SILValue value = mv.forward(cleanups.SGF);
  pop();
  return cloner.clone(value);
}
Esempio n. 6
0
void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
  assert(thunk.isCurried);

  auto *vd = thunk.getDecl();

  if (auto *fd = dyn_cast<AbstractFunctionDecl>(vd)) {
    assert(!SGM.M.Types.hasLoweredLocalCaptures(fd) &&
           "methods cannot have captures");
    (void) fd;
  }

  auto selfTy = vd->getInterfaceType()->castTo<AnyFunctionType>()
    ->getInput();
  selfTy = vd->getInnermostDeclContext()->mapTypeIntoContext(selfTy);
  ManagedValue selfArg =
      B.createFunctionArgument(getLoweredType(selfTy), nullptr);

  // Forward substitutions.
  auto subs = F.getForwardingSubstitutions();

  ManagedValue toFn = getNextUncurryLevelRef(*this, vd, thunk, selfArg, subs);

  // FIXME: Using the type from the ConstantInfo instead of looking at
  // getConstantOverrideInfo() for methods looks suspect in the presence
  // of covariant overrides and multiple vtable entries.
  SILFunctionConventions fromConv(
      SGM.Types.getConstantInfo(thunk).SILFnType, SGM.M);
  SILType resultTy = fromConv.getSingleSILResultType();
  resultTy = F.mapTypeIntoContext(resultTy);
  auto substTy = toFn.getType().substGenericArgs(SGM.M, subs);

  // Partially apply the next uncurry level and return the result closure.
  selfArg = selfArg.ensurePlusOne(*this, vd);
  auto calleeConvention = ParameterConvention::Direct_Guaranteed;
  auto closureTy = SILGenBuilder::getPartialApplyResultType(
      toFn.getType(), /*appliedParams=*/1, SGM.M, subs, calleeConvention);
  ManagedValue toClosure =
      B.createPartialApply(vd, toFn, substTy, subs, {selfArg}, closureTy);
  if (resultTy != closureTy) {
    CanSILFunctionType resultFnTy = resultTy.castTo<SILFunctionType>();
    CanSILFunctionType closureFnTy = closureTy.castTo<SILFunctionType>();
    if (resultFnTy->isABICompatibleWith(closureFnTy).isCompatible()) {
      toClosure = B.createConvertFunction(vd, toClosure, resultTy);
    } else {
      toClosure =
          emitCanonicalFunctionThunk(vd, toClosure, closureFnTy, resultFnTy);
    }
  }
  B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(vd), toClosure);
}
Esempio n. 7
0
/// Bridge an optional foreign error type to ErrorProtocol.
ManagedValue SILGenFunction::emitBridgedToNativeError(SILLocation loc,
                                                  ManagedValue bridgedError) {
#ifndef NDEBUG
  {
    OptionalTypeKind optKind;
    auto objType = bridgedError.getType().getSwiftRValueType()
                                         .getAnyOptionalObjectType(optKind);
    assert(optKind == OTK_Optional && "not Optional type");
    assert(objType == SGM.Types.getNSErrorType() &&
           "only handling NSError for now");
  }
#endif

  auto bridgeFn = emitGlobalFunctionRef(loc, SGM.getNSErrorToErrorProtocolFn());
  auto bridgeFnType = bridgeFn->getType().castTo<SILFunctionType>();
  assert(bridgeFnType->getNumAllResults() == 1);
  assert(bridgeFnType->getAllResults()[0].getConvention()
           == ResultConvention::Owned);
  auto nativeErrorProtocol = bridgeFnType->getAllResults()[0].getSILType();
  assert(bridgeFnType->getParameters()[0].getConvention()
           == ParameterConvention::Direct_Owned);

  SILValue nativeError = B.createApply(loc, bridgeFn, bridgeFn->getType(),
                                       nativeErrorProtocol, {},
                                       bridgedError.forward(*this));
  return emitManagedRValueWithCleanup(nativeError);
}
Esempio n. 8
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);
  }
}
Esempio n. 9
0
static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &gen,
                                              SILLocation loc,
                                              SubstitutionList subs,
                                              ArrayRef<ManagedValue> args,
                                              CanFunctionType formalApplyType,
                                              SGFContext C) {
  unsigned NumTailTypes = subs.size() - 1;
  assert(args.size() == NumTailTypes * 2 + 1 &&
         "wrong number of substitutions for allocWithTailElems");

  // The substitution determines the element type for bound memory.
  SILType RefType = gen.getLoweredType(subs[0].getReplacement()->
                                  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(gen.getLoweredType(subs[Idx+1].getReplacement()->
                                           getCanonicalType()).getObjectType());
  }
  ManagedValue Metatype = args[0];
  if (isa<MetatypeInst>(Metatype)) {
    assert(Metatype.getType().getMetatypeInstanceType(gen.SGM.M) == RefType &&
           "substituted type does not match operand metatype");
    return gen.B.createAllocRef(loc, RefType, false, false,
                                ElemTypes, Counts);
  } else {
    return gen.B.createAllocRefDynamic(loc, Metatype, RefType, false,
                                       ElemTypes, Counts);
  }
}
Esempio n. 10
0
static ManagedValue emitBridgeCollectionToNative(SILGenFunction &gen,
                                                 SILLocation loc,
                                                 SILDeclRef bridgeFnRef,
                                                 ManagedValue collection,
                                                 SILType nativeTy) {
  SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, bridgeFnRef);

  auto collectionTy = nativeTy.getSwiftRValueType()->castTo<BoundGenericType>();
  auto subs = collectionTy->getSubstitutions(gen.SGM.M.getSwiftModule(),
                                             nullptr);
  auto substFnType = bridgeFn.getType().substGenericArgs(gen.SGM.M, subs);

  Type inputType = collection.getType().getSwiftRValueType();
  if (!inputType->getOptionalObjectType()) {
    SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(inputType));
    auto *someDecl = gen.getASTContext().getOptionalSomeDecl();
    auto *enumInst = gen.B.createEnum(loc, collection.getValue(), someDecl,
                                      loweredOptTy);
    collection = ManagedValue(enumInst, collection.getCleanup());
  }

  SILValue result = gen.B.createApply(loc, bridgeFn,
                                      substFnType,
                                      nativeTy,
                                      subs,
                                      { collection.forward(gen) });

  return gen.emitManagedRValueWithCleanup(result);
}
Esempio n. 11
0
static ManagedValue emitBridgeCollectionFromNative(SILGenFunction &gen,
                                                   SILLocation loc,
                                                   SILDeclRef bridgeFnRef,
                                                   ManagedValue collection,
                                                   SILType bridgedTy) {
  SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, bridgeFnRef);

  // If the expected return is optional, we'll need to wrap it.
  OptionalTypeKind OTK = OTK_None;
  SILType origBridgedTy = bridgedTy;
  if (auto bridgedObjTy = bridgedTy.getAnyOptionalObjectType(gen.SGM.M, OTK)) {
    bridgedTy = bridgedObjTy;
  }

  // Figure out the type parameters.
  auto inputTy
    = collection.getType().getSwiftRValueType()->castTo<BoundGenericType>();
  auto subs = inputTy->getSubstitutions(gen.SGM.M.getSwiftModule(), nullptr);
  auto substFnType = bridgeFn.getType().substGenericArgs(gen.SGM.M, subs);
  SILValue bridged = gen.B.createApply(loc, bridgeFn,
                                       substFnType,
                                       bridgedTy,
                                       subs,
                                       { collection.forward(gen) });
  // Wrap the result if necessary.
  if (OTK != OTK_None) {
    bridged = gen.B.createEnum(loc, bridged,
                               gen.getASTContext().getOptionalSomeDecl(OTK),
                               origBridgedTy);
  }

  return gen.emitManagedRValueWithCleanup(bridged);
}
Esempio n. 12
0
RValue
SILGenFunction::emitPointerToPointer(SILLocation loc,
                                     ManagedValue input,
                                     CanType inputType,
                                     CanType outputType,
                                     SGFContext C) {
  auto converter = getASTContext().getConvertPointerToPointerArgument(nullptr);

  // The generic function currently always requires indirection, but pointers
  // are always loadable.
  auto origBuf = emitTemporaryAllocation(loc, input.getType());
  B.emitStoreValueOperation(loc, input.forward(*this), origBuf,
                            StoreOwnershipQualifier::Init);
  auto origValue = emitManagedBufferWithCleanup(origBuf);
  
  // Invoke the conversion intrinsic to convert to the destination type.
  auto *M = SGM.M.getSwiftModule();
  auto *proto = getPointerProtocol();
  auto firstSubMap = inputType->getContextSubstitutionMap(M, proto);
  auto secondSubMap = outputType->getContextSubstitutionMap(M, proto);

  auto *genericSig = converter->getGenericSignature();
  auto subMap =
    SubstitutionMap::combineSubstitutionMaps(firstSubMap,
                                             secondSubMap,
                                             CombineSubstitutionMaps::AtIndex,
                                             1, 0,
                                             genericSig);
  
  return emitApplyOfLibraryIntrinsic(loc, converter, subMap, origValue, C);
}
Esempio n. 13
0
/// Bridge a native function to a block with a thunk.
ManagedValue
SILGenFunction::emitBlockToFunc(SILLocation loc,
                                ManagedValue block,
                                CanSILFunctionType funcTy) {
  CanSILFunctionType substFnTy;
  SmallVector<Substitution, 4> subs;

  // Declare the thunk.
  auto blockTy = block.getType().castTo<SILFunctionType>();
  auto thunkTy = buildThunkType(block, funcTy, substFnTy, subs);
  auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(),
                                                 thunkTy,
                                                 blockTy,
                                                 funcTy,
                                                 F.isFragile());

  // Build it if necessary.
  if (thunk->empty()) {
    SILGenFunction thunkSGF(SGM, *thunk);
    thunk->setContextGenericParams(F.getContextGenericParams());
    auto loc = RegularLocation::getAutoGeneratedLocation();
    buildBlockToFuncThunkBody(thunkSGF, loc, blockTy, funcTy);
  }

  // Create it in the current function.
  auto thunkValue = B.createFunctionRef(loc, thunk);
  auto thunkedFn = B.createPartialApply(loc, thunkValue,
                                    SILType::getPrimitiveObjectType(substFnTy),
                                    subs, block.forward(*this),
                                    SILType::getPrimitiveObjectType(funcTy));
  return emitManagedRValueWithCleanup(thunkedFn);
}
Esempio n. 14
0
/// Bridge a native function to a block with a thunk.
ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc,
                                             ManagedValue fn,
                                             CanSILFunctionType blockTy) {
  // Build the invoke function signature. The block will capture the original
  // function value.
  auto fnTy = fn.getType().castTo<SILFunctionType>();
  auto storageTy = SILBlockStorageType::get(fnTy);

  // Build the invoke function type.
  SmallVector<SILParameterInfo, 4> params;
  params.push_back(SILParameterInfo(storageTy,
                                 ParameterConvention::Indirect_InoutAliasable));
  std::copy(blockTy->getParameters().begin(),
            blockTy->getParameters().end(),
            std::back_inserter(params));

  auto invokeTy =
    SILFunctionType::get(nullptr,
                     SILFunctionType::ExtInfo()
                       .withRepresentation(SILFunctionType::Representation::
                                           CFunctionPointer),
                     ParameterConvention::Direct_Unowned,
                     params,
                     blockTy->getAllResults(),
                     blockTy->getOptionalErrorResult(),
                     getASTContext());

  // Create the invoke function. Borrow the mangling scheme from reabstraction
  // thunks, which is what we are in spirit.
  auto thunk = SGM.getOrCreateReabstractionThunk(nullptr,
                                                 invokeTy,
                                                 fnTy,
                                                 blockTy,
                                                 F.isFragile());

  // Build it if necessary.
  if (thunk->empty()) {
    SILGenFunction thunkSGF(SGM, *thunk);
    auto loc = RegularLocation::getAutoGeneratedLocation();
    buildFuncToBlockInvokeBody(thunkSGF, loc, blockTy, storageTy, fnTy);
  }

  // Form the block on the stack.
  auto storageAddrTy = SILType::getPrimitiveAddressType(storageTy);
  auto storage = emitTemporaryAllocation(loc, storageAddrTy);
  auto capture = B.createProjectBlockStorage(loc, storage);
  // Store the function to the block without claiming it, so that it still
  // gets cleaned up in scope. Copying the block will create an independent
  // reference.
  B.createStore(loc, fn.getValue(), capture);
  auto invokeFn = B.createFunctionRef(loc, thunk);
  auto stackBlock = B.createInitBlockStorageHeader(loc, storage, invokeFn,
                                      SILType::getPrimitiveObjectType(blockTy));

  // Copy the block so we have an independent heap object we can hand off.
  auto heapBlock = B.createCopyBlock(loc, stackBlock);
  return emitManagedRValueWithCleanup(heapBlock);
}
Esempio n. 15
0
static ManagedValue emitCBridgedToNativeValue(SILGenFunction &gen,
                                              SILLocation loc,
                                              ManagedValue v,
                                              SILType nativeTy) {
  CanType loweredNativeTy = nativeTy.getSwiftRValueType();
  CanType loweredBridgedTy = v.getType().getSwiftRValueType();
  if (loweredNativeTy == loweredBridgedTy)
    return v;

  if (loweredNativeTy.getAnyOptionalObjectType()) {
    return gen.emitOptionalToOptional(loc, v, nativeTy,
                                      emitCBridgedToNativeValue);
  }

  // Bridge Bool to ObjCBool or DarwinBoolean when requested.
  if (loweredNativeTy == gen.SGM.Types.getBoolType()) {
    if (loweredBridgedTy == gen.SGM.Types.getObjCBoolType()) {
      return emitBridgeForeignBoolToBool(gen, loc, v,
                                         gen.SGM.getObjCBoolToBoolFn());
    }
    if (loweredBridgedTy == gen.SGM.Types.getDarwinBooleanType()) {
      return emitBridgeForeignBoolToBool(gen, loc, v,
                                         gen.SGM.getDarwinBooleanToBoolFn());
    }
  }

  // Bridge Objective-C to thick metatypes.
  if (auto bridgedMetaTy = dyn_cast<AnyMetatypeType>(loweredBridgedTy)){
    if (bridgedMetaTy->getRepresentation() == MetatypeRepresentation::ObjC) {
      SILValue native = gen.B.emitObjCToThickMetatype(loc, v.getValue(),
                                        gen.getLoweredType(loweredNativeTy));
      return ManagedValue(native, v.getCleanup());
    }
  }

  // Bridge blocks back into native function types.
  auto bridgedFTy = dyn_cast<SILFunctionType>(loweredBridgedTy);
  if (bridgedFTy
      && bridgedFTy->getRepresentation() == SILFunctionType::Representation::Block){
    auto nativeFTy = cast<SILFunctionType>(loweredNativeTy);

    if (nativeFTy->getRepresentation() != SILFunctionType::Representation::Block)
      return gen.emitBlockToFunc(loc, v, nativeFTy);
  }

  // Bridge via _ObjectiveCBridgeable.
  if (auto conformance =
        gen.SGM.getConformanceToObjectiveCBridgeable(loc, loweredNativeTy)) {
    if (auto result = emitBridgeObjectiveCToNative(gen, loc, v, conformance))
      return *result;

    assert(gen.SGM.getASTContext().Diags.hadAnyError() &&
           "Bridging code should have complained");
    return gen.emitUndef(loc, nativeTy);
  }

  return v;
}
Esempio n. 16
0
static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &gen,
                                                         SILLocation loc,
                                                         ManagedValue v,
                                                         SILType bridgedTy) {
  CanType loweredBridgedTy = bridgedTy.getSwiftRValueType();
  CanType loweredNativeTy = v.getType().getSwiftRValueType();
  if (loweredNativeTy == loweredBridgedTy)
    return v;

  // FIXME: Handle this via an _ObjectiveCBridgeable query rather than
  // hardcoding String -> NSString.
  if (loweredNativeTy == gen.SGM.Types.getStringType()
      && loweredBridgedTy == gen.SGM.Types.getNSStringType()) {
    if (auto result = emitBridgeNativeToObjectiveC(gen, loc, v))
      return *result;

    return gen.emitUndef(loc, bridgedTy);
  }

  // If the input is a native type with a bridged mapping, convert it.
#define BRIDGE_TYPE(BridgedModule,BridgedType, NativeModule,NativeType,Opt) \
  if (loweredNativeTy == gen.SGM.Types.get##NativeType##Type()              \
      && loweredBridgedTy == gen.SGM.Types.get##BridgedType##Type()) {      \
    return emitBridge##NativeType##To##BridgedType(gen, loc, v);            \
  }
#include "swift/SIL/BridgedTypes.def"

  // Bridge thick to Objective-C metatypes.
  if (auto bridgedMetaTy = dyn_cast<AnyMetatypeType>(loweredBridgedTy)) {
    if (bridgedMetaTy->getRepresentation() == MetatypeRepresentation::ObjC) {
      SILValue native = gen.B.emitThickToObjCMetatype(loc, v.getValue(),
                           SILType::getPrimitiveObjectType(loweredBridgedTy));
      return ManagedValue(native, v.getCleanup());
    }
  }

  // Bridge native functions to blocks.
  auto bridgedFTy = dyn_cast<SILFunctionType>(loweredBridgedTy);
  if (bridgedFTy
      && bridgedFTy->getRepresentation() == SILFunctionType::Representation::Block){
    auto nativeFTy = cast<SILFunctionType>(loweredNativeTy);

    if (nativeFTy->getRepresentation() != SILFunctionType::Representation::Block)
      return gen.emitFuncToBlock(loc, v, bridgedFTy);
  }

  // If the native type conforms to _ObjectiveCBridgeable, use its
  // _bridgeToObjectiveC witness.
  if (auto conformance =
          gen.SGM.getConformanceToObjectiveCBridgeable(loc, loweredNativeTy)) {
    if (auto result = emitBridgeNativeToObjectiveC(gen, loc, v, conformance))
      return *result;

    return gen.emitUndef(loc, bridgedTy);
  }

  return v;
}
Esempio n. 17
0
SILValue Lowering::emitIsa(SILGenFunction &SGF, SILLocation loc,
                           Expr *operand, Type targetType,
                           CheckedCastKind castKind) {
  // Handle collection downcasts separately.
  if (castKind == CheckedCastKind::ArrayDowncast ||
      castKind == CheckedCastKind::DictionaryDowncast ||
      castKind == CheckedCastKind::SetDowncast) {
    ManagedValue operandMV = SGF.emitRValueAsSingleValue(operand);
    ManagedValue optValue = emitCollectionDowncastExpr(
                              SGF, operandMV, operand->getType(), loc,
                              targetType,
                              SGFContext(), /*conditional=*/true)
      .getAsSingleValue(SGF, loc);

    // Materialize the input.
    SILValue optValueTemp;
    if (optValue.getType().isAddress()) {
      optValueTemp = optValue.forward(SGF);
    } else {
      optValueTemp = SGF.emitTemporaryAllocation(loc, optValue.getType());
      optValue.forwardInto(SGF, loc, optValueTemp);
    }

    return SGF.emitDoesOptionalHaveValue(loc, optValueTemp);
  }

  // Prepare a jump destination here.
  ExitableFullExpr scope(SGF, CleanupLocation::get(loc));

  auto i1Ty = SILType::getBuiltinIntegerType(1, SGF.getASTContext());

  SGF.emitCheckedCastBranch(loc, operand, targetType, SGFContext(),
    [&](ManagedValue value) {
      SILValue yes = SGF.B.createIntegerLiteral(loc, i1Ty, 1);
      SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, yes);
    },
    [&] {
      SILValue no = SGF.B.createIntegerLiteral(loc, i1Ty, 0);
      SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, no);
    });

  auto contBB = scope.exit();
  auto isa = new (SGF.SGM.M) SILArgument(contBB, i1Ty);
  return isa;
}
Esempio n. 18
0
static ManagedValue
adjustForConditionalCheckedCastOperand(SILLocation loc, ManagedValue src,
                                       CanType sourceType, CanType targetType,
                                       SILGenFunction &SGF) {
  // Reabstract to the most general abstraction, and put it into a
  // temporary if necessary.
  
  // Figure out if we need the value to be in a temporary.
  bool requiresAddress =
    !canUseScalarCheckedCastInstructions(SGF.SGM.M, sourceType, targetType);
  
  AbstractionPattern abstraction = SGF.SGM.M.Types.getMostGeneralAbstraction();
  auto &srcAbstractTL = SGF.getTypeLowering(abstraction, sourceType);
  
  bool hasAbstraction = (src.getType() != srcAbstractTL.getLoweredType());
  
  // Fast path: no re-abstraction required.
  if (!hasAbstraction && (!requiresAddress || src.getType().isAddress())) {
    return src;
  }
  
  std::unique_ptr<TemporaryInitialization> init;
  SGFContext ctx;
  if (requiresAddress) {
    init = SGF.emitTemporary(loc, srcAbstractTL);
    
    // Okay, if all we need to do is drop the value in an address,
    // this is easy.
    if (!hasAbstraction) {
      SGF.B.createStore(loc, src.forward(SGF), init->getAddress());
      init->finishInitialization(SGF);
      return init->getManagedAddress();
    }
    
    ctx = SGFContext(init.get());
  }
  
  assert(hasAbstraction);
  assert(src.getType().isObject() &&
         "address-only type with abstraction difference?");
  
  // Produce the value at +1.
  return SGF.emitSubstToOrigValue(loc, src, abstraction, sourceType);
}
Esempio n. 19
0
/// Emit a materializeForSet operation that calls a mutable addressor.
///
/// If it's not an unsafe addressor, this uses a callback function to
/// write the l-value back.
SILValue MaterializeForSetEmitter::emitUsingAddressor(SILGenFunction &SGF,
                                                      SILLocation loc,
                                                      ManagedValue self,
                                                      RValue &&indices,
                                                      SILValue callbackBuffer,
                                                      SILFunction *&callback) {
  bool isDirect = (TheAccessSemantics != AccessSemantics::Ordinary);

  // Call the mutable addressor.
  auto addressor = SGF.getAddressorDeclRef(WitnessStorage,
                                           AccessKind::ReadWrite,
                                           isDirect);
  std::pair<ManagedValue, ManagedValue> result;
  {
    FormalEvaluationScope Scope(SGF);

    SILType addressType = WitnessStorageType.getAddressType();
    ArgumentSource baseRV =
        SGF.prepareAccessorBaseArg(loc, self, SubstSelfType, addressor);
    result = SGF.emitAddressorAccessor(loc, addressor, WitnessSubs,
                                       std::move(baseRV), IsSuper, isDirect,
                                       std::move(indices), addressType);
  }

  SILValue address = result.first.getUnmanagedValue();

  AddressorKind addressorKind =
    WitnessStorage->getMutableAddressor()->getAddressorKind();
  ManagedValue owner = result.second;
  if (!owner) {
    assert(addressorKind == AddressorKind::Unsafe);
  } else {
    SILValue allocatedCallbackBuffer =
      SGF.B.createAllocValueBuffer(loc, owner.getType(), callbackBuffer);
    SGF.B.emitStoreValueOperation(loc, owner.forward(SGF),
                                  allocatedCallbackBuffer,
                                  StoreOwnershipQualifier::Init);

    callback = createAddressorCallback(SGF.F, owner.getType(), addressorKind);
  }

  return address;
}
Esempio n. 20
0
ManagedValue SILGenFunction::emitUncheckedGetOptionalValueFrom(SILLocation loc,
                                                    ManagedValue addrOrValue,
                                                    const TypeLowering &optTL,
                                                    SGFContext C) {
  OptionalTypeKind OTK;
  SILType origPayloadTy =
    addrOrValue.getType().getAnyOptionalObjectType(SGM.M, OTK);

  auto formalOptionalTy = addrOrValue.getType().getSwiftRValueType();
  auto formalPayloadTy = formalOptionalTy
    ->getAnyOptionalObjectType()
    ->getCanonicalType();
  
  auto someDecl = getASTContext().getOptionalSomeDecl(OTK);
 
  ManagedValue payload;

  // Take the payload from the optional.  Cheat a bit in the +0
  // case—UncheckedTakeEnumData will never actually invalidate an Optional enum
  // value.
  SILValue payloadVal;
  if (!addrOrValue.getType().isAddress()) {
    payloadVal = B.createUncheckedEnumData(loc, addrOrValue.forward(*this),
                                           someDecl);
  } else {
    payloadVal =
      B.createUncheckedTakeEnumDataAddr(loc, addrOrValue.forward(*this),
                                        someDecl, origPayloadTy);
  
    if (optTL.isLoadable())
      payloadVal = B.createLoad(loc, payloadVal);
  }

  // Produce a correctly managed value.
  if (addrOrValue.hasCleanup())
    payload = emitManagedRValueWithCleanup(payloadVal);
  else
    payload = ManagedValue::forUnmanaged(payloadVal);
  
  // Reabstract it to the substituted form, if necessary.
  return emitOrigToSubstValue(loc, payload, AbstractionPattern::getOpaque(),
                              formalPayloadTy, C);
}
Esempio n. 21
0
ManagedValue SILGenBuilder::createCopyUnownedValue(SILLocation loc,
                                                   ManagedValue originalValue) {
  auto unownedType = originalValue.getType().castTo<UnownedStorageType>();
  assert(unownedType->isLoadable(ResilienceExpansion::Maximal));
  (void)unownedType;

  SILValue result =
      SILBuilder::createCopyUnownedValue(loc, originalValue.getValue());
  return gen.emitManagedRValueWithCleanup(result);
}
Esempio n. 22
0
ManagedValue SILGenBuilder::createStore(SILLocation loc, ManagedValue value,
                                        SILValue address,
                                        StoreOwnershipQualifier qualifier) {
  SILModule &M = SGF.F.getModule();
  CleanupCloner cloner(*this, value);
  if (value.getType().isTrivial(M) || value.getOwnershipKind() == ValueOwnershipKind::Any)
    qualifier = StoreOwnershipQualifier::Trivial;
  createStore(loc, value.forward(SGF), address, qualifier);
  return cloner.clone(address);
}
Esempio n. 23
0
ManagedValue
SILGenBuilder::createUnsafeCopyUnownedValue(SILLocation loc,
                                            ManagedValue originalValue) {
  auto unmanagedType = originalValue.getType().getAs<UnmanagedStorageType>();
  SILValue result = SILBuilder::createUnmanagedToRef(
      loc, originalValue.getValue(),
      SILType::getPrimitiveObjectType(unmanagedType.getReferentType()));
  SILBuilder::createUnmanagedRetainValue(loc, result, getDefaultAtomicity());
  return gen.emitManagedRValueWithCleanup(result);
}
Esempio n. 24
0
ManagedValue SILGenBuilder::createOptionalSome(SILLocation loc,
                                               ManagedValue arg) {
  CleanupCloner cloner(*this, arg);
  auto &argTL = SGF.getTypeLowering(arg.getType());
  SILType optionalType = SILType::getOptionalType(arg.getType());
  if (argTL.isLoadable() || !SGF.silConv.useLoweredAddresses()) {
    SILValue someValue =
        createOptionalSome(loc, arg.forward(SGF), optionalType);
    return cloner.clone(someValue);
  }

  SILValue tempResult = SGF.emitTemporaryAllocation(loc, optionalType);
  RValue rvalue(SGF, loc, arg.getType().getASTType(), arg);
  ArgumentSource argValue(loc, std::move(rvalue));
  SGF.emitInjectOptionalValueInto(
      loc, std::move(argValue), tempResult,
      SGF.getTypeLowering(tempResult->getType()));
  return ManagedValue::forUnmanaged(tempResult);
}
Esempio n. 25
0
ManagedValue SILGenBuilder::createLoadTake(SILLocation loc, ManagedValue v,
                                           const TypeLowering &lowering) {
  assert(lowering.getLoweredType().getAddressType() == v.getType());
  SILValue result =
      lowering.emitLoadOfCopy(*this, loc, v.forward(SGF), IsTake);
  if (lowering.isTrivial())
    return ManagedValue::forUnmanaged(result);
  assert(!lowering.isAddressOnly() && "cannot retain an unloadable type");
  return SGF.emitManagedRValueWithCleanup(result, lowering);
}
Esempio n. 26
0
ManagedValue SILGenBuilder::createLoadBorrow(SILLocation loc,
                                             ManagedValue base) {
  if (SGF.getTypeLowering(base.getType()).isTrivial()) {
    auto *i = createLoad(loc, base.getValue(), LoadOwnershipQualifier::Trivial);
    return ManagedValue::forUnmanaged(i);
  }

  auto *i = createLoadBorrow(loc, base.getValue());
  return SGF.emitManagedBorrowedRValueWithCleanup(base.getValue(), i);
}
Esempio n. 27
0
static void boxIndirectEnumPayload(SILGenFunction &gen,
                                   ManagedValue &payload,
                                   SILLocation loc,
                                   EnumElementDecl *element) {
  // If the payload is indirect, we'll need to box it.
  if (payload && (element->isIndirect() ||
                  element->getParentEnum()->isIndirect())) {
    auto box = gen.B.createAllocBox(loc, payload.getType());
    payload.forwardInto(gen, loc, box->getAddressResult());
    payload = gen.emitManagedRValueWithCleanup(box);
  }
}
Esempio n. 28
0
/// Recursively walk into the given formal index type, expanding tuples,
/// in order to form the arguments to a subscript accessor.
static void translateIndices(SILGenFunction &gen, SILLocation loc,
                             AbstractionPattern pattern, CanType formalType,
                             ArrayRef<ManagedValue> &sourceIndices,
                             RValue &result) {
  // Expand if the pattern was a tuple.
  if (pattern.isTuple()) {
    auto formalTupleType = cast<TupleType>(formalType);
    for (auto i : indices(formalTupleType.getElementTypes())) {
      translateIndices(gen, loc, pattern.getTupleElementType(i),
                       formalTupleType.getElementType(i),
                       sourceIndices, result);
    }
    return;
  }

  assert(!sourceIndices.empty() && "ran out of elements in index!");
  ManagedValue value = sourceIndices.front();
  sourceIndices = sourceIndices.slice(1);

  // We're going to build an RValue here, so make sure we translate
  // indirect arguments to be scalar if we have a loadable type.
  if (value.getType().isAddress()) {
    auto &valueTL = gen.getTypeLowering(value.getType());
    if (!valueTL.isAddressOnly()) {
      value = gen.emitLoad(loc, value.forward(gen), valueTL,
                           SGFContext(), IsTake);
    }
  }

  // Reabstract the subscripts from the requirement pattern to the
  // formal type.
  value = gen.emitOrigToSubstValue(loc, value, pattern, formalType);

  // Invoking the accessor will expect a value of the formal type, so
  // don't reabstract to that here.

  // Add that to the result, further expanding if necessary.
  result.addElement(gen, value, formalType, loc);
}
Esempio n. 29
0
ManagedValue SILGenBuilder::createFormalAccessLoadBorrow(SILLocation loc,
                                                         ManagedValue base) {
  if (getFunction().getTypeLowering(base.getType()).isTrivial()) {
    auto *i = SILBuilder::createLoad(loc, base.getValue(),
                                     LoadOwnershipQualifier::Trivial);
    return ManagedValue::forUnmanaged(i);
  }

  SILValue baseValue = base.getValue();
  auto *i = SILBuilder::createLoadBorrow(loc, baseValue);
  return gen.emitFormalEvaluationManagedBorrowedRValueWithCleanup(loc,
                                                                  baseValue, i);
}
Esempio n. 30
0
// FIXME: With some changes to their callers, all of the below functions
// could be re-worked to use emitInjectEnum().
ManagedValue
SILGenFunction::emitInjectOptional(SILLocation loc,
                                   ManagedValue v,
                                   CanType inputFormalType,
                                   CanType substFormalType,
                                   const TypeLowering &expectedTL,
                                   SGFContext ctxt) {
  // Optional's payload is currently maximally abstracted. FIXME: Eventually
  // it shouldn't be.
  auto opaque = AbstractionPattern::getOpaque();

  OptionalTypeKind substOTK;
  auto substObjectType = substFormalType.getAnyOptionalObjectType(substOTK);

  auto loweredTy = getLoweredType(opaque, substObjectType);
  if (v.getType() != loweredTy)
    v = emitTransformedValue(loc, v,
                             AbstractionPattern(inputFormalType), inputFormalType,
                             opaque, substObjectType);

  auto someDecl = getASTContext().getOptionalSomeDecl(substOTK);
  SILType optTy = getLoweredType(substFormalType);
  if (v.getType().isAddress()) {
    auto buf = getBufferForExprResult(loc, optTy.getObjectType(), ctxt);
    auto payload = B.createInitEnumDataAddr(loc, buf, someDecl,
                                            v.getType());
    // FIXME: Is it correct to use IsTake here even if v doesn't have a cleanup?
    B.createCopyAddr(loc, v.forward(*this), payload,
                     IsTake, IsInitialization);
    B.createInjectEnumAddr(loc, buf, someDecl);
    v = manageBufferForExprResult(buf, expectedTL, ctxt);
  } else {
    auto some = B.createEnum(loc, v.getValue(), someDecl, optTy);
    v = ManagedValue(some, v.getCleanup());
  }

  return v;
}