@@ -1926,208 +1926,38 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
1926
1926
assert (functionPointer.getKind () != FunctionPointer::Kind::Function);
1927
1927
bool emitFunction = values.first ;
1928
1928
bool emitSize = values.second ;
1929
- // TODO: This calculation should be extracted out into standalone functions
1930
- // emitted on-demand per-module to improve codesize.
1931
- switch (representation) {
1932
- case SILFunctionTypeRepresentation::Thick: {
1933
- assert (!functionPointer.useStaticContextSize ());
1934
- // If the called function is thick, the size of the called function's
1935
- // async context is not statically knowable.
1936
- //
1937
- // Specifically, if the thick function was produced by a partial_apply,
1938
- // the function which was originally partially applied determines the
1939
- // size of the needed async context. That original function isn't known
1940
- // statically. The dynamic size is available within the context as an
1941
- // i32 at the first index: <{ %swift.refcounted*, /*size*/ i32, ... }>.
1942
- // In this case, the function pointer is actually a pointer to an llvm
1943
- // function.
1944
- //
1945
- // On the other hand, if the thick function was produced by a
1946
- // thin_to_thick_function, then the context will be nullptr. In that
1947
- // case, the dynamic size of the needed async context is available within
1948
- // the struct, an AsyncFunctionPointer pointed to by the "function" pointer
1949
- // as an i32 at the second index: <{ /*fn rel addr*/ i32, /*size*/ i32 }>.
1950
- //
1951
- // We are currently emitting into some basic block. To handle these two
1952
- // cases, we need to branch based on whether the context is nullptr; each
1953
- // branch must then determine the size and function pointer in the manner
1954
- // appropriate to it. Finally, both blocks must join back together to make
1955
- // the call:
1956
- //
1957
- // +-------------------------+
1958
- // |%cond = %ctx == nullptr |
1959
- // +----------------|br %cond, thin, thick |----------------------+
1960
- // | +-------------------------+ |
1961
- // | |
1962
- // V |
1963
- // +-thin-------------------------------------------+ |
1964
- // |%afp = bitcast %fp to %swift.async_func_pointer*| |
1965
- // |%size_ptr = getelementptr %afp, i32 0, i32 1 | |
1966
- // |%size = load %size_ptr | |
1967
- // |%offset_ptr = getelementptr %afp, i32 0, i32 1 | |
1968
- // |%offset = load i32 %offset_ptr | |
1969
- // |%offset64 = sext %offset to i64 | |
1970
- // |%raw_fp = add %offset64, %offset_ptr | |
1971
- // |br join(%raw_fp, %size) | |
1972
- // +------------------------------------------------+ |
1973
- // | |
1974
- // | V
1975
- // | +-thick--------------------------------------------+
1976
- // | |%layout = bitcast %ctx to <{%swift.context*, i32}>|
1977
- // | |%size_addr = getelementptr %layout, i32 0, i32 1 |
1978
- // | |%size = load %size_addr |
1979
- // | |br join(%fp, %size) |
1980
- // | +---/----------------------------------------------+
1981
- // | /
1982
- // | /
1983
- // V V
1984
- // +-join(%fn, %size)------------------------------------------------------+
1985
- // |%dataAddr = swift_taskAlloc(%task, %size) |
1986
- // |%async_context = bitcast %dataAddr to ASYNC_CONTEXT(static_callee_type)|
1987
- // |... // populate the fields %ctx with arguments |
1988
- // |call %fn(%async_context, %ctx) |
1989
- // +-----------------------------------------------------------------------+
1990
- auto *thinBlock = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1991
- auto *thickBlock = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1992
- auto *joinBlock = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1993
-
1994
- auto hasThickContext =
1995
- IGF.Builder .CreateICmpNE (thickContext, IGF.IGM .RefCountedNull );
1996
- IGF.Builder .CreateCondBr (hasThickContext, thickBlock, thinBlock);
1997
-
1998
- SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 2 > fnPhiValues;
1999
- SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 2 > sizePhiValues;
2000
- { // thin
2001
- IGF.Builder .emitBlock (thinBlock);
2002
- auto *ptr = functionPointer.getRawPointer ();
2003
- if (auto authInfo = functionPointer.getAuthInfo ()) {
2004
- ptr = emitPointerAuthAuth (IGF, ptr, authInfo);
2005
- }
2006
- auto *afpPtr =
2007
- IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
2008
- if (emitFunction) {
2009
- llvm::Value *addrPtr = IGF.Builder .CreateStructGEP (afpPtr, 0 );
2010
- auto *uncastFnPtr = IGF.emitLoadOfRelativePointer (
2011
- Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
2012
- /* expectedType*/ functionPointer.getFunctionType ()->getPointerTo ());
2013
- auto *fnPtr = IGF.Builder .CreateBitCast (uncastFnPtr, IGF.IGM .Int8PtrTy );
2014
- if (auto authInfo = functionPointer.getAuthInfo ()) {
2015
- fnPtr = emitPointerAuthSign (IGF, fnPtr, authInfo);
2016
- }
2017
- fnPhiValues.push_back ({thinBlock, fnPtr});
2018
- }
2019
- if (emitSize) {
2020
- auto *sizePtr = IGF.Builder .CreateStructGEP (afpPtr, 1 );
2021
- auto *size =
2022
- IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
2023
- sizePhiValues.push_back ({thinBlock, size});
2024
- }
2025
- IGF.Builder .CreateBr (joinBlock);
2026
- }
2027
-
2028
- { // thick
2029
- IGF.Builder .emitBlock (thickBlock);
2030
- if (emitFunction) {
2031
- auto *uncastFnPtr = functionPointer.getRawPointer ();
2032
- auto *fnPtr = IGF.Builder .CreateBitCast (uncastFnPtr, IGF.IGM .Int8PtrTy );
2033
- fnPhiValues.push_back ({thickBlock, fnPtr});
2034
- }
2035
- if (emitSize) {
2036
- SmallVector<const TypeInfo *, 4 > argTypeInfos;
2037
- SmallVector<SILType, 4 > argValTypes;
2038
- auto int32ASTType =
2039
- BuiltinIntegerType::get (32 , IGF.IGM .IRGen .SIL .getASTContext ())
2040
- ->getCanonicalType ();
2041
- auto int32SILType = SILType::getPrimitiveObjectType (int32ASTType);
2042
- const TypeInfo &int32TI = IGF.IGM .getTypeInfo (int32SILType);
2043
- argValTypes.push_back (int32SILType);
2044
- argTypeInfos.push_back (&int32TI);
2045
- HeapLayout layout (IGF.IGM , LayoutStrategy::Optimal, argValTypes,
2046
- argTypeInfos,
2047
- /* typeToFill*/ nullptr , NecessaryBindings ());
2048
- auto castThickContext =
2049
- layout.emitCastTo (IGF, thickContext, " context.prefix" );
2050
- auto sizeLayout = layout.getElement (0 );
2051
- auto sizeAddr = sizeLayout.project (IGF, castThickContext,
2052
- /* NonFixedOffsets*/ llvm::None);
2053
- auto *sizeValue = IGF.Builder .CreateLoad (sizeAddr);
2054
- sizePhiValues.push_back ({thickBlock, sizeValue});
2055
- }
2056
- IGF.Builder .CreateBr (joinBlock);
2057
- }
2058
-
2059
- { // join
2060
- IGF.Builder .emitBlock (joinBlock);
2061
- llvm::Value *fn = nullptr ;
2062
- llvm::PHINode *fnPhi = nullptr ;
2063
- llvm::PHINode *sizePhi = nullptr ;
2064
- if (emitFunction) {
2065
- fnPhi = IGF.Builder .CreatePHI (IGF.IGM .Int8PtrTy , fnPhiValues.size ());
2066
- }
2067
- if (emitSize) {
2068
- sizePhi = IGF.Builder .CreatePHI (IGF.IGM .Int32Ty , sizePhiValues.size ());
2069
- }
2070
- if (emitFunction) {
2071
- assert (fnPhi);
2072
- for (auto &entry : fnPhiValues) {
2073
- fnPhi->addIncoming (entry.second , entry.first );
2074
- }
2075
- fn = IGF.Builder .CreateBitCast (
2076
- fnPhi, functionPointer.getFunctionType ()->getPointerTo ());
2077
- }
2078
- llvm::Value *size = nullptr ;
2079
- if (emitSize) {
2080
- assert (sizePhi);
2081
- for (auto &entry : sizePhiValues) {
2082
- sizePhi->addIncoming (entry.second , entry.first );
2083
- }
2084
- size = sizePhi;
2085
- }
2086
- return {fn, size};
1929
+ auto *ptr = functionPointer.getRawPointer ();
1930
+ if (auto authInfo = functionPointer.getAuthInfo ()) {
1931
+ ptr = emitPointerAuthAuth (IGF, ptr, authInfo);
1932
+ }
1933
+ auto *afpPtr =
1934
+ IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
1935
+ llvm::Value *fn = nullptr ;
1936
+ if (emitFunction) {
1937
+ if (functionPointer.useStaticContextSize ()) {
1938
+ fn = functionPointer.getRawPointer ();
1939
+ } else {
1940
+ llvm::Value *addrPtr = IGF.Builder .CreateStructGEP (afpPtr, 0 );
1941
+ fn = IGF.emitLoadOfRelativePointer (
1942
+ Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
1943
+ /* expectedType*/ functionPointer.getFunctionType ()->getPointerTo ());
2087
1944
}
2088
- }
2089
- case SILFunctionTypeRepresentation::Thin:
2090
- case SILFunctionTypeRepresentation::CFunctionPointer:
2091
- case SILFunctionTypeRepresentation::Method:
2092
- case SILFunctionTypeRepresentation::ObjCMethod:
2093
- case SILFunctionTypeRepresentation::WitnessMethod:
2094
- case SILFunctionTypeRepresentation::Closure:
2095
- case SILFunctionTypeRepresentation::Block: {
2096
- auto *ptr = functionPointer.getRawPointer ();
2097
1945
if (auto authInfo = functionPointer.getAuthInfo ()) {
2098
- ptr = emitPointerAuthAuth (IGF, ptr , authInfo);
1946
+ fn = emitPointerAuthSign (IGF, fn , authInfo);
2099
1947
}
2100
- auto *afpPtr =
2101
- IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
2102
- llvm::Value *fn = nullptr ;
2103
- if (emitFunction) {
2104
- if (functionPointer.useStaticContextSize ()) {
2105
- fn = functionPointer.getRawPointer ();
2106
- } else {
2107
- llvm::Value *addrPtr = IGF.Builder .CreateStructGEP (afpPtr, 0 );
2108
- fn = IGF.emitLoadOfRelativePointer (
2109
- Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
2110
- /* expectedType*/ functionPointer.getFunctionType ()->getPointerTo ());
2111
- }
2112
- if (auto authInfo = functionPointer.getAuthInfo ()) {
2113
- fn = emitPointerAuthSign (IGF, fn, authInfo);
2114
- }
2115
- }
2116
- llvm::Value *size = nullptr ;
2117
- if (emitSize) {
2118
- if (functionPointer.useStaticContextSize ()) {
2119
- size = llvm::ConstantInt::get (IGF.IGM .Int32Ty ,
2120
- initialContextSize.getValue ());
2121
- } else {
2122
- assert (!functionPointer.useStaticContextSize ());
2123
- auto *sizePtr = IGF.Builder .CreateStructGEP (afpPtr, 1 );
2124
- size = IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
2125
- }
2126
- }
2127
- return {fn, size};
2128
1948
}
1949
+ llvm::Value *size = nullptr ;
1950
+ if (emitSize) {
1951
+ if (functionPointer.useStaticContextSize ()) {
1952
+ size = llvm::ConstantInt::get (IGF.IGM .Int32Ty ,
1953
+ initialContextSize.getValue ());
1954
+ } else {
1955
+ assert (!functionPointer.useStaticContextSize ());
1956
+ auto *sizePtr = IGF.Builder .CreateStructGEP (afpPtr, 1 );
1957
+ size = IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
1958
+ }
2129
1959
}
2130
- llvm_unreachable ( " unhandled case " ) ;
1960
+ return {fn, size} ;
2131
1961
}
2132
1962
2133
1963
static void externalizeArguments (IRGenFunction &IGF, const Callee &callee,
0 commit comments