@@ -2983,10 +2983,106 @@ static void emitInitializeFieldOffsetVectorWithLayoutString(
2983
2983
IGM.getPointerSize () * numFields);
2984
2984
}
2985
2985
2986
+ static void emitInitializeRawLayoutOld (IRGenFunction &IGF, SILType likeType,
2987
+ Size count, SILType T,
2988
+ llvm::Value *metadata,
2989
+ MetadataDependencyCollector *collector) {
2990
+ auto &IGM = IGF.IGM ;
2991
+
2992
+ // This is the list of field type layouts that we're going to pass to the init
2993
+ // function. This will only ever hold 1 field which is the temporary one we're
2994
+ // going to build up from our like type's layout.
2995
+ auto fieldLayouts = IGF.createAlloca (
2996
+ llvm::ArrayType::get (IGM.TypeLayoutTy ->getPointerTo (), 1 ),
2997
+ IGM.getPointerAlignment (), " fieldLayouts" );
2998
+ IGF.Builder .CreateLifetimeStart (fieldLayouts, IGM.getPointerSize ());
2999
+
3000
+ // We're going to pretend that this is our field offset vector for the init to
3001
+ // write to. We don't actually have fields, so we don't want to write a field
3002
+ // offset in our metadata.
3003
+ auto fieldOffsets = IGF.createAlloca (IGM.Int32Ty , Alignment (4 ), " fieldOffsets" );
3004
+ IGF.Builder .CreateLifetimeStart (fieldOffsets, Size (4 ));
3005
+
3006
+ // We need to make a temporary type layout with most of the same information
3007
+ // from the type we're like.
3008
+ auto ourTypeLayout = IGF.createAlloca (IGM.TypeLayoutTy ,
3009
+ IGM.getPointerAlignment (),
3010
+ " ourTypeLayout" );
3011
+ IGF.Builder .CreateLifetimeStart (ourTypeLayout, IGM.getPointerSize ());
3012
+
3013
+ // Put our temporary type layout in the list of layouts we're using to
3014
+ // initialize.
3015
+ IGF.Builder .CreateStore (ourTypeLayout.getAddress (), fieldLayouts);
3016
+
3017
+ // Get the like type's type layout.
3018
+ auto likeTypeLayout = emitTypeLayoutRef (IGF, likeType, collector);
3019
+
3020
+ // Grab the size, stride, and alignmentMask out of the layout.
3021
+ auto loadedTyLayout = IGF.Builder .CreateLoad (
3022
+ Address (likeTypeLayout, IGM.TypeLayoutTy , IGM.getPointerAlignment ()),
3023
+ " typeLayout" );
3024
+ auto size = IGF.Builder .CreateExtractValue (loadedTyLayout, 0 , " size" );
3025
+ auto stride = IGF.Builder .CreateExtractValue (loadedTyLayout, 1 , " stride" );
3026
+ auto flags = IGF.Builder .CreateExtractValue (loadedTyLayout, 2 , " flags" );
3027
+ auto xi = IGF.Builder .CreateExtractValue (loadedTyLayout, 3 , " xi" );
3028
+
3029
+ // This will zero out the other bits.
3030
+ auto alignMask = IGF.Builder .CreateAnd (flags,
3031
+ ValueWitnessFlags::AlignmentMask,
3032
+ " alignMask" );
3033
+
3034
+ // Set the isNonPOD bit. This is important because older runtimes will attempt
3035
+ // to replace various vwt functions with more optimized ones. In this case, we
3036
+ // want to preserve the fact that noncopyable types have unreachable copy vwt
3037
+ // functions.
3038
+ auto vwtFlags = IGF.Builder .CreateOr (alignMask,
3039
+ ValueWitnessFlags::IsNonPOD,
3040
+ " vwtFlags" );
3041
+
3042
+ // Count is only ever -1 if we're not an array like layout.
3043
+ if (count != Size (-1 )) {
3044
+ stride = IGF.Builder .CreateMul (stride, IGM.getSize (count));
3045
+ size = stride;
3046
+ }
3047
+
3048
+ llvm::Value *resultAgg = llvm::UndefValue::get (IGM.TypeLayoutTy );
3049
+ resultAgg = IGF.Builder .CreateInsertValue (resultAgg, size, 0 );
3050
+ resultAgg = IGF.Builder .CreateInsertValue (resultAgg, stride, 1 );
3051
+ resultAgg = IGF.Builder .CreateInsertValue (resultAgg, vwtFlags, 2 );
3052
+ resultAgg = IGF.Builder .CreateInsertValue (resultAgg, xi, 3 );
3053
+
3054
+ IGF.Builder .CreateStore (resultAgg, ourTypeLayout);
3055
+
3056
+ StructLayoutFlags fnFlags = StructLayoutFlags::Swift5Algorithm;
3057
+
3058
+ // Call swift_initStructMetadata().
3059
+ IGF.Builder .CreateCall (IGM.getInitStructMetadataFunctionPointer (),
3060
+ {metadata, IGM.getSize (Size (uintptr_t (fnFlags))),
3061
+ IGM.getSize (Size (1 )), fieldLayouts.getAddress (),
3062
+ fieldOffsets.getAddress ()});
3063
+
3064
+ IGF.Builder .CreateLifetimeEnd (ourTypeLayout, IGM.getPointerSize ());
3065
+ IGF.Builder .CreateLifetimeEnd (fieldOffsets, Size (4 ));
3066
+ IGF.Builder .CreateLifetimeEnd (fieldLayouts, IGM.getPointerSize ());
3067
+ }
3068
+
2986
3069
static void emitInitializeRawLayout (IRGenFunction &IGF, SILType likeType,
2987
3070
Size count, SILType T,
2988
3071
llvm::Value *metadata,
2989
3072
MetadataDependencyCollector *collector) {
3073
+ // If our deployment target doesn't contain the new swift_initRawStructMetadata,
3074
+ // emit a call to the swift_initStructMetadata tricking it into thinking
3075
+ // we have a single field.
3076
+ auto deploymentAvailability =
3077
+ AvailabilityContext::forDeploymentTarget (IGF.IGM .Context );
3078
+ auto initRawAvail = IGF.IGM .Context .getInitRawStructMetadataAvailability ();
3079
+
3080
+ if (!IGF.IGM .Context .LangOpts .DisableAvailabilityChecking &&
3081
+ !deploymentAvailability.isContainedIn (initRawAvail)) {
3082
+ emitInitializeRawLayoutOld (IGF, likeType, count, T, metadata, collector);
3083
+ return ;
3084
+ }
3085
+
2990
3086
auto &IGM = IGF.IGM ;
2991
3087
auto likeTypeLayout = emitTypeLayoutRef (IGF, likeType, collector);
2992
3088
StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm;
0 commit comments