Skip to content

Commit 7c69bec

Browse files
authored
Merge pull request swiftlang#73782 from eeckstein/static-arrays-in-embedded
IRGen: support read-only statically initialized arrays in embedded swift
2 parents 4a1662d + 1621393 commit 7c69bec

File tree

11 files changed

+182
-26
lines changed

11 files changed

+182
-26
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ extension Instruction {
370370
is VectorInst,
371371
is AllocVectorInst,
372372
is UncheckedRefCastInst,
373+
is UpcastInst,
373374
is ValueToBridgeObjectInst,
374375
is ConvertFunctionInst,
375376
is ThinToThickFunctionInst,

include/swift/IRGen/Linking.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ class LinkEntity {
127127
// This field appears in the TypeMetadata and ObjCResilientClassStub kinds.
128128
MetadataAddressShift = 8, MetadataAddressMask = 0x0300,
129129

130+
// This field appears in the TypeMetadata kind.
131+
ForceSharedShift = 12, ForceSharedMask = 0x1000,
132+
130133
// This field appears in associated type access functions.
131134
AssociatedTypeIndexShift = 8, AssociatedTypeIndexMask = ~KindMask,
132135

@@ -847,12 +850,14 @@ class LinkEntity {
847850
}
848851

849852
static LinkEntity forTypeMetadata(CanType concreteType,
850-
TypeMetadataAddress addr) {
853+
TypeMetadataAddress addr,
854+
bool forceShared = false) {
851855
assert(!isObjCImplementation(concreteType));
852856
assert(!isEmbedded(concreteType) || isMetadataAllowedInEmbedded(concreteType));
853857
LinkEntity entity;
854858
entity.setForType(Kind::TypeMetadata, concreteType);
855859
entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr));
860+
entity.Data |= LINKENTITY_SET_FIELD(ForceShared, unsigned(forceShared));
856861
return entity;
857862
}
858863

@@ -1584,6 +1589,10 @@ class LinkEntity {
15841589
getKind() == Kind::ObjCResilientClassStub);
15851590
return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress);
15861591
}
1592+
bool isForcedShared() const {
1593+
assert(getKind() == Kind::TypeMetadata);
1594+
return (bool)LINKENTITY_GET_FIELD(Data, ForceShared);
1595+
}
15871596
bool isObjCClassRef() const {
15881597
return getKind() == Kind::ObjCClassRef;
15891598
}

include/swift/SIL/SILBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,10 @@ class SILBuilder {
12511251
UpcastInst *createUpcast(SILLocation Loc, SILValue Op, SILType Ty,
12521252
ValueOwnershipKind forwardingOwnershipKind) {
12531253
assert(Ty.isObject());
1254+
if (isInsertingIntoGlobal()) {
1255+
return insert(UpcastInst::create(getSILDebugLocation(Loc), Op, Ty,
1256+
getModule(), forwardingOwnershipKind));
1257+
}
12541258
return insert(UpcastInst::create(getSILDebugLocation(Loc), Op, Ty,
12551259
getFunction(), forwardingOwnershipKind));
12561260
}

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5879,6 +5879,10 @@ class UpcastInst final : public UnaryInstructionWithTypeDependentOperandsBase<
58795879
forwardingOwnershipKind) {
58805880
}
58815881

5882+
static UpcastInst *create(SILDebugLocation DebugLoc, SILValue Operand,
5883+
SILType Ty, SILModule &Mod,
5884+
ValueOwnershipKind forwardingOwnershipKind);
5885+
58825886
static UpcastInst *create(SILDebugLocation DebugLoc, SILValue Operand,
58835887
SILType Ty, SILFunction &F,
58845888
ValueOwnershipKind forwardingOwnershipKind);

lib/IRGen/GenConstant.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ Explosion irgen::emitConstantValue(IRGenModule &IGM, SILValue operand,
358358
} else if (auto *URCI = dyn_cast<UncheckedRefCastInst>(operand)) {
359359
return emitConstantValue(IGM, URCI->getOperand(), flatten);
360360

361+
} else if (auto *UCI = dyn_cast<UpcastInst>(operand)) {
362+
return emitConstantValue(IGM, UCI->getOperand(), flatten);
363+
361364
} else if (auto *T2TFI = dyn_cast<ThinToThickFunctionInst>(operand)) {
362365
SILType type = operand->getType();
363366
auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());
@@ -453,22 +456,37 @@ llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
453456

454457
if (IGM.canMakeStaticObjectReadOnly(OI->getType())) {
455458
if (!IGM.swiftImmortalRefCount) {
456-
auto *var = new llvm::GlobalVariable(IGM.Module, IGM.Int8Ty,
457-
/*constant*/ true, llvm::GlobalValue::ExternalLinkage,
458-
/*initializer*/ nullptr, "_swiftImmortalRefCount");
459-
IGM.swiftImmortalRefCount = var;
459+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
460+
// = HeapObject.immortalRefCount
461+
IGM.swiftImmortalRefCount = llvm::ConstantInt::get(IGM.IntPtrTy, -1);
462+
} else {
463+
IGM.swiftImmortalRefCount = llvm::ConstantExpr::getPtrToInt(
464+
new llvm::GlobalVariable(IGM.Module, IGM.Int8Ty,
465+
/*constant*/ true, llvm::GlobalValue::ExternalLinkage,
466+
/*initializer*/ nullptr, "_swiftImmortalRefCount"),
467+
IGM.IntPtrTy);
468+
}
460469
}
461470
if (!IGM.swiftStaticArrayMetadata) {
462471
auto *classDecl = IGM.getStaticArrayStorageDecl();
463472
assert(classDecl && "no __StaticArrayStorage in stdlib");
464473
CanType classTy = CanType(ClassType::get(classDecl, Type(), IGM.Context));
465-
LinkEntity entity = LinkEntity::forTypeMetadata(classTy, TypeMetadataAddress::AddressPoint);
466-
auto *metatype = IGM.getAddrOfLLVMVariable(entity, NotForDefinition, DebugTypeInfo());
467-
IGM.swiftStaticArrayMetadata = cast<llvm::GlobalVariable>(metatype);
474+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
475+
LinkEntity entity = LinkEntity::forTypeMetadata(classTy, TypeMetadataAddress::AddressPoint,
476+
/*forceShared=*/ true);
477+
// In embedded swift, the metadata for the array buffer class only needs to be very minimal:
478+
// No vtable needed, because the object is never destructed. It only contains the null super-
479+
// class pointer.
480+
llvm::Constant *superClass = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
481+
IGM.swiftStaticArrayMetadata = IGM.getAddrOfLLVMVariable(entity, superClass, DebugTypeInfo());
482+
} else {
483+
LinkEntity entity = LinkEntity::forTypeMetadata(classTy, TypeMetadataAddress::AddressPoint);
484+
IGM.swiftStaticArrayMetadata = IGM.getAddrOfLLVMVariable(entity, NotForDefinition, DebugTypeInfo());
485+
}
468486
}
469487
elements[0].add(llvm::ConstantStruct::get(ObjectHeaderTy, {
470488
IGM.swiftStaticArrayMetadata,
471-
llvm::ConstantExpr::getPtrToInt(IGM.swiftImmortalRefCount, IGM.IntPtrTy)}));
489+
IGM.swiftImmortalRefCount }));
472490
} else {
473491
elements[0].add(llvm::Constant::getNullValue(ObjectHeaderTy));
474492
}

lib/IRGen/IRGenModule.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,8 +2029,14 @@ void IRGenModule::error(SourceLoc loc, const Twine &message) {
20292029

20302030
bool IRGenModule::useDllStorage() { return ::useDllStorage(Triple); }
20312031

2032+
// In embedded swift features are available independent of deployment and
2033+
// runtime targets because the runtime library is always statically linked
2034+
// to the program.
2035+
20322036
#define FEATURE(N, V) \
20332037
bool IRGenModule::is##N##FeatureAvailable(const ASTContext &context) { \
2038+
if (Context.LangOpts.hasFeature(Feature::Embedded)) \
2039+
return true; \
20342040
auto deploymentAvailability \
20352041
= AvailabilityContext::forDeploymentTarget(context); \
20362042
auto runtimeAvailability \

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,8 @@ class IRGenModule {
837837

838838
llvm::GlobalVariable *TheTrivialPropertyDescriptor = nullptr;
839839

840-
llvm::GlobalVariable *swiftImmortalRefCount = nullptr;
841-
llvm::GlobalVariable *swiftStaticArrayMetadata = nullptr;
840+
llvm::Constant *swiftImmortalRefCount = nullptr;
841+
llvm::Constant *swiftStaticArrayMetadata = nullptr;
842842

843843
/// Used to create unique names for class layout types with tail allocated
844844
/// elements.

lib/IRGen/Linking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,9 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
642642
return SILLinkage::Shared;
643643

644644
case Kind::TypeMetadata: {
645+
if (isForcedShared())
646+
return SILLinkage::Shared;
647+
645648
auto *nominal = getType().getAnyNominal();
646649
switch (getMetadataAddress()) {
647650
case TypeMetadataAddress::FullMetadata:

lib/SIL/IR/SILInstructions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2714,6 +2714,15 @@ MetatypeInst *MetatypeInst::create(SILDebugLocation Loc, SILType Ty,
27142714
return ::new (Buffer) MetatypeInst(Loc, Ty, TypeDependentOperands);
27152715
}
27162716

2717+
UpcastInst *UpcastInst::create(SILDebugLocation DebugLoc, SILValue Operand,
2718+
SILType Ty, SILModule &Mod,
2719+
ValueOwnershipKind forwardingOwnershipKind) {
2720+
unsigned size = totalSizeToAlloc<swift::Operand>(1);
2721+
void *Buffer = Mod.allocateInst(size, alignof(UpcastInst));
2722+
return ::new (Buffer) UpcastInst(DebugLoc, Operand, {}, Ty,
2723+
forwardingOwnershipKind);
2724+
}
2725+
27172726
UpcastInst *UpcastInst::create(SILDebugLocation DebugLoc, SILValue Operand,
27182727
SILType Ty, SILFunction &F,
27192728
ValueOwnershipKind forwardingOwnershipKind) {

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public struct HeapObject {
4646
static let refcountMask = Int(bitPattern: 0x7fff_ffff)
4747
#endif
4848

49+
// Note: The immortalRefCount value of -1 is also hard-coded in IRGen in `irgen::emitConstantObject`.
4950
static let immortalRefCount = -1
5051
}
5152

0 commit comments

Comments
 (0)