Skip to content

Commit 17fe75b

Browse files
committed
Emit call to old initialization function for older OSes
1 parent df17f7b commit 17fe75b

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,10 @@ class ASTContext final {
937937
/// descriptors.
938938
AvailabilityContext getSignedDescriptorAvailability();
939939

940+
/// Get the runtime availability of the swift_initRawStructMetadata entrypoint
941+
/// that fixes up the value witness table of @_rawLayout dependent types.
942+
AvailabilityContext getInitRawStructMetadataAvailability();
943+
940944
/// Get the runtime availability of features introduced in the Swift 5.2
941945
/// compiler for the target platform.
942946
AvailabilityContext getSwift52Availability();

lib/AST/Availability.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ ASTContext::getSignedDescriptorAvailability() {
540540
return getSwift59Availability();
541541
}
542542

543+
AvailabilityContext
544+
ASTContext::getInitRawStructMetadataAvailability() {
545+
return getSwiftFutureAvailability();
546+
}
547+
543548
AvailabilityContext ASTContext::getSwift52Availability() {
544549
auto target = LangOpts.Target;
545550

lib/IRGen/GenMeta.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,10 +2983,103 @@ static void emitInitializeFieldOffsetVectorWithLayoutString(
29832983
IGM.getPointerSize() * numFields);
29842984
}
29852985

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+
auto alignMaskMask = IGM.getInt32(ValueWitnessFlags::AlignmentMask);
3030+
3031+
// This will zero out the other bits like isPOD, isBitwiseTakeable, etc.
3032+
auto alignMask = IGF.Builder.CreateAnd(flags, alignMaskMask, "alignMask");
3033+
3034+
// Set the noncopyable bit even though older runtimes don't use this bit at
3035+
// all.
3036+
auto vwtFlags = IGF.Builder.CreateOr(alignMask,
3037+
ValueWitnessFlags::IsNonCopyable,
3038+
"vwtFlags");
3039+
3040+
// Count is only ever -1 if we're not an array like layout.
3041+
if (count != Size(-1)) {
3042+
stride = IGF.Builder.CreateMul(stride, IGM.getSize(count));
3043+
size = stride;
3044+
}
3045+
3046+
llvm::Value *resultAgg = llvm::UndefValue::get(IGM.TypeLayoutTy);
3047+
resultAgg = IGF.Builder.CreateInsertValue(resultAgg, size, 0);
3048+
resultAgg = IGF.Builder.CreateInsertValue(resultAgg, stride, 1);
3049+
resultAgg = IGF.Builder.CreateInsertValue(resultAgg, vwtFlags, 2);
3050+
resultAgg = IGF.Builder.CreateInsertValue(resultAgg, xi, 3);
3051+
3052+
IGF.Builder.CreateStore(resultAgg, ourTypeLayout);
3053+
3054+
StructLayoutFlags fnFlags = StructLayoutFlags::Swift5Algorithm;
3055+
3056+
// Call swift_initStructMetadata().
3057+
IGF.Builder.CreateCall(IGM.getInitStructMetadataFunctionPointer(),
3058+
{metadata, IGM.getSize(Size(uintptr_t(fnFlags))),
3059+
IGM.getSize(Size(1)), fieldLayouts.getAddress(),
3060+
fieldOffsets.getAddress()});
3061+
3062+
IGF.Builder.CreateLifetimeEnd(ourTypeLayout, IGM.getPointerSize());
3063+
IGF.Builder.CreateLifetimeEnd(fieldOffsets, Size(4));
3064+
IGF.Builder.CreateLifetimeEnd(fieldLayouts, IGM.getPointerSize());
3065+
}
3066+
29863067
static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType,
29873068
Size count, SILType T,
29883069
llvm::Value *metadata,
29893070
MetadataDependencyCollector *collector) {
3071+
// If our deployment target doesn't contain the new swift_initRawStructMetadata,
3072+
// emit a call to the swift_initStructMetadata tricking it into thinking
3073+
// we have a single field.
3074+
auto deploymentAvailability =
3075+
AvailabilityContext::forDeploymentTarget(IGF.IGM.Context);
3076+
auto initRawAvail = IGF.IGM.Context.getInitRawStructMetadataAvailability();
3077+
3078+
if (!deploymentAvailability.isContainedIn(initRawAvail)) {
3079+
emitInitializeRawLayoutOld(IGF, likeType, count, T, metadata, collector);
3080+
return;
3081+
}
3082+
29903083
auto &IGM = IGF.IGM;
29913084
auto likeTypeLayout = emitTypeLayoutRef(IGF, likeType, collector);
29923085
StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm;

0 commit comments

Comments
 (0)