本文整理汇总了C++中SILDeclRef::asForeign方法的典型用法代码示例。如果您正苦于以下问题:C++ SILDeclRef::asForeign方法的具体用法?C++ SILDeclRef::asForeign怎么用?C++ SILDeclRef::asForeign使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SILDeclRef
的用法示例。
在下文中一共展示了SILDeclRef::asForeign方法的5个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: emitForeignToNativeThunk
void SILGenModule::emitForeignToNativeThunk(SILDeclRef thunk) {
// Thunks are always emitted by need, so don't need delayed emission.
assert(!thunk.isForeign && "foreign-to-native thunks only");
SILFunction *f = getFunction(thunk, ForDefinition);
f->setThunk(IsThunk);
if (thunk.asForeign().isClangGenerated())
f->setSerialized(IsSerialized);
preEmitFunction(thunk, thunk.getDecl(), f, thunk.getDecl());
PrettyStackTraceSILFunction X("silgen emitForeignToNativeThunk", f);
SILGenFunction(*this, *f).emitForeignToNativeThunk(thunk);
postEmitFunction(thunk, f);
}
示例2: getNextUncurryLevelRef
static SILValue getNextUncurryLevelRef(SILGenFunction &gen,
SILLocation loc,
SILDeclRef next,
bool direct,
ArrayRef<SILValue> curriedArgs,
ArrayRef<Substitution> curriedSubs) {
// For a foreign function, reference the native thunk.
if (next.isForeign)
return gen.emitGlobalFunctionRef(loc, next.asForeign(false));
// If the fully-uncurried reference is to a native dynamic class method, emit
// the dynamic dispatch.
auto fullyAppliedMethod = !next.isCurried && !next.isForeign && !direct &&
next.hasDecl();
auto constantInfo = gen.SGM.Types.getConstantInfo(next);
SILValue thisArg;
if (!curriedArgs.empty())
thisArg = curriedArgs.back();
if (fullyAppliedMethod &&
isa<AbstractFunctionDecl>(next.getDecl()) &&
gen.getMethodDispatch(cast<AbstractFunctionDecl>(next.getDecl()))
== MethodDispatch::Class) {
SILValue thisArg = curriedArgs.back();
// Use the dynamic thunk if dynamic.
if (next.getDecl()->isDynamic()) {
auto dynamicThunk = gen.SGM.getDynamicThunk(next, constantInfo);
return gen.B.createFunctionRef(loc, dynamicThunk);
}
return gen.B.createClassMethod(loc, thisArg, next);
}
// If the fully-uncurried reference is to a generic method, look up the
// witness.
if (fullyAppliedMethod &&
constantInfo.SILFnType->getRepresentation()
== SILFunctionTypeRepresentation::WitnessMethod) {
auto thisType = curriedSubs[0].getReplacement()->getCanonicalType();
assert(isa<ArchetypeType>(thisType) && "no archetype for witness?!");
SILValue OpenedExistential;
if (!cast<ArchetypeType>(thisType)->getOpenedExistentialType().isNull())
OpenedExistential = thisArg;
return gen.B.createWitnessMethod(loc, thisType, nullptr, next,
constantInfo.getSILType(),
OpenedExistential);
}
// Otherwise, emit a direct call.
return gen.emitGlobalFunctionRef(loc, next);
}
示例3: emitGlobalFunctionRef
SILValue SILGenFunction::emitGlobalFunctionRef(SILLocation loc,
SILDeclRef constant,
SILConstantInfo constantInfo) {
assert(constantInfo == getConstantInfo(constant));
// Builtins must be fully applied at the point of reference.
if (constant.hasDecl() &&
isa<BuiltinUnit>(constant.getDecl()->getDeclContext())) {
SGM.diagnose(loc.getSourceLoc(), diag::not_implemented,
"delayed application of builtin");
return SILUndef::get(constantInfo.getSILType(), SGM.M);
}
// If the constant is a thunk we haven't emitted yet, emit it.
if (!SGM.hasFunction(constant)) {
if (constant.isCurried) {
auto vd = constant.getDecl();
// Reference the next uncurrying level of the function.
SILDeclRef next = SILDeclRef(vd, constant.kind,
SILDeclRef::ConstructAtBestResilienceExpansion,
constant.uncurryLevel + 1);
// If the function is fully uncurried and natively foreign, reference its
// foreign entry point.
if (!next.isCurried) {
if (requiresForeignToNativeThunk(vd))
next = next.asForeign();
}
// Preserve whether the curry thunks lead to a direct reference to the
// method implementation.
next = next.asDirectReference(constant.isDirectReference);
SGM.emitCurryThunk(vd, constant, next);
}
// Otherwise, if this is a calling convention thunk we haven't emitted yet,
// emit it.
else if (constant.isForeignToNativeThunk()) {
SGM.emitForeignToNativeThunk(constant);
} else if (constant.isNativeToForeignThunk()) {
SGM.emitNativeToForeignThunk(constant);
} else if (constant.kind == SILDeclRef::Kind::EnumElement) {
SGM.emitEnumConstructor(cast<EnumElementDecl>(constant.getDecl()));
}
}
auto f = SGM.getFunction(constant, NotForDefinition);
assert(f->getLoweredFunctionType() == constantInfo.SILFnType);
return B.createFunctionRef(loc, f);
}
示例4: emitForeignToNativeThunk
/// Generate code to emit a thunk with native conventions that calls a
/// function with foreign conventions.
void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
assert(!thunk.isForeign && "foreign-to-native thunks only");
// Wrap the function in its original form.
auto fd = cast<AbstractFunctionDecl>(thunk.getDecl());
auto nativeCI = getConstantInfo(thunk);
auto nativeFormalResultTy = nativeCI.LoweredInterfaceType.getResult();
auto nativeFnTy = F.getLoweredFunctionType();
assert(nativeFnTy == nativeCI.SILFnType);
// Find the foreign error convention and 'self' parameter index.
Optional<ForeignErrorConvention> foreignError;
if (nativeFnTy->hasErrorResult()) {
foreignError = fd->getForeignErrorConvention();
assert(foreignError && "couldn't find foreign error convention!");
}
ImportAsMemberStatus memberStatus = fd->getImportAsMemberStatus();
// Forward the arguments.
auto forwardedParameters = fd->getParameterLists();
// For allocating constructors, 'self' is a metatype, not the 'self' value
// formally present in the constructor body.
Type allocatorSelfType;
if (thunk.kind == SILDeclRef::Kind::Allocator) {
allocatorSelfType = forwardedParameters[0]->getType(getASTContext())
->getLValueOrInOutObjectType();
forwardedParameters = forwardedParameters.slice(1);
}
SmallVector<SILValue, 8> params;
for (auto *paramList : reversed(forwardedParameters))
bindParametersForForwarding(paramList, params);
if (allocatorSelfType) {
auto selfMetatype =
CanMetatypeType::get(allocatorSelfType->getCanonicalType());
auto selfArg = new (F.getModule()) SILArgument(
F.begin(),
getLoweredLoadableType(selfMetatype),
fd->getImplicitSelfDecl());
params.push_back(selfArg);
}
// Set up the throw destination if necessary.
CleanupLocation cleanupLoc(fd);
if (foreignError) {
prepareRethrowEpilog(cleanupLoc);
}
SILValue result;
{
Scope scope(Cleanups, fd);
SILDeclRef foreignDeclRef = thunk.asForeign(true);
SILConstantInfo foreignCI = getConstantInfo(foreignDeclRef);
auto foreignFnTy = foreignCI.SILFnType;
// Bridge all the arguments.
SmallVector<ManagedValue, 8> args;
unsigned foreignArgIndex = 0;
// A helper function to add a function error argument in the
// appropriate position.
auto maybeAddForeignErrorArg = [&] {
if (foreignError &&
foreignArgIndex == foreignError->getErrorParameterIndex()) {
args.push_back(ManagedValue());
foreignArgIndex++;
}
};
for (unsigned nativeParamIndex : indices(params)) {
// Bring the parameter to +1.
auto paramValue = params[nativeParamIndex];
auto thunkParam = nativeFnTy->getParameters()[nativeParamIndex];
// TODO: Could avoid a retain if the bridged parameter is also +0 and
// doesn't require a bridging conversion.
ManagedValue param;
switch (thunkParam.getConvention()) {
case ParameterConvention::Direct_Owned:
param = emitManagedRValueWithCleanup(paramValue);
break;
case ParameterConvention::Direct_Guaranteed:
case ParameterConvention::Direct_Unowned:
param = emitManagedRetain(fd, paramValue);
break;
case ParameterConvention::Direct_Deallocating:
param = ManagedValue::forUnmanaged(paramValue);
break;
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
param = ManagedValue::forUnmanaged(paramValue);
break;
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
llvm_unreachable("indirect args in foreign thunked method not implemented");
//.........这里部分代码省略.........
示例5: emitNativeToForeignThunk
void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
assert(thunk.isForeign);
SILDeclRef native = thunk.asForeign(false);
auto loc = thunk.getAsRegularLocation();
loc.markAutoGenerated();
Scope scope(Cleanups, CleanupLocation::get(loc));
// Bridge the arguments.
SmallVector<SILValue, 4> args;
Optional<ForeignErrorConvention> foreignError;
SILValue foreignErrorSlot;
auto objcFnTy = emitObjCThunkArguments(*this, loc, thunk, args,
foreignErrorSlot, foreignError);
auto nativeInfo = getConstantInfo(native);
auto swiftResultTy =
F.mapTypeIntoContext(nativeInfo.SILFnType->getSILResult());
auto objcResultTy =
F.mapTypeIntoContext(objcFnTy->getSILResult());
// Call the native entry point.
SILValue nativeFn = emitGlobalFunctionRef(loc, native, nativeInfo);
auto subs = F.getForwardingSubstitutions();
auto substTy = nativeInfo.SILFnType->substGenericArgs(
SGM.M, SGM.M.getSwiftModule(), subs);
SILType substSILTy = SILType::getPrimitiveObjectType(substTy);
CanType bridgedResultType = objcResultTy.getSwiftRValueType();
SILValue result;
assert(foreignError.hasValue() == substTy->hasErrorResult());
if (!substTy->hasErrorResult()) {
// Create the apply.
result = B.createApply(loc, nativeFn, substSILTy,
swiftResultTy, subs, args);
// Leave the scope immediately. This isn't really necessary; it
// just limits lifetimes a little bit more.
scope.pop();
// Now bridge the return value.
result = emitBridgeReturnValue(*this, loc, result,
objcFnTy->getRepresentation(),
bridgedResultType);
} else {
SILBasicBlock *contBB = createBasicBlock();
SILBasicBlock *errorBB = createBasicBlock();
SILBasicBlock *normalBB = createBasicBlock();
B.createTryApply(loc, nativeFn, substSILTy, subs, args,
normalBB, errorBB);
// Emit the non-error destination.
{
B.emitBlock(normalBB);
SILValue nativeResult = normalBB->createBBArg(swiftResultTy);
// In this branch, the eventual return value is mostly created
// by bridging the native return value, but we may need to
// adjust it slightly.
SILValue bridgedResult =
emitBridgeReturnValueForForeignError(loc, nativeResult,
objcFnTy->getRepresentation(),
objcResultTy,
foreignErrorSlot, *foreignError);
B.createBranch(loc, contBB, bridgedResult);
}
// Emit the error destination.
{
B.emitBlock(errorBB);
SILValue nativeError =
errorBB->createBBArg(substTy->getErrorResult().getSILType());
// In this branch, the eventual return value is mostly invented.
// Store the native error in the appropriate location and return.
SILValue bridgedResult =
emitBridgeErrorForForeignError(loc, nativeError, objcResultTy,
foreignErrorSlot, *foreignError);
B.createBranch(loc, contBB, bridgedResult);
}
// Emit the join block.
B.emitBlock(contBB);
result = contBB->createBBArg(objcResultTy);
// Leave the scope now.
scope.pop();
}
B.createReturn(loc, result);
}