Skip to content

Commit d418b91

Browse files
authored
Merge pull request #59612 from eeckstein/reenable-readonly-arrays
IRGen: re-enable generate static arrays in read-only data sections.
2 parents 5b899e5 + 24d077e commit d418b91

File tree

13 files changed

+213
-36
lines changed

13 files changed

+213
-36
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,10 @@ class ASTContext final {
880880
/// for extended existential types.
881881
AvailabilityContext getParameterizedExistentialRuntimeAvailability();
882882

883+
/// Get the runtime availability of immortal ref-count symbols, which are
884+
/// needed to place array buffers into constant data sections.
885+
AvailabilityContext getImmortalRefCountSymbolsAvailability();
886+
883887
/// Get the runtime availability of features introduced in the Swift 5.2
884888
/// compiler for the target platform.
885889
AvailabilityContext getSwift52Availability();

include/swift/AST/IRGenOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ class IRGenOptions {
402402
/// and protocol conformance caches.
403403
unsigned NoPreallocatedInstantiationCaches : 1;
404404

405+
unsigned DisableReadonlyStaticObjects : 1;
406+
405407
/// The number of threads for multi-threaded code generation.
406408
unsigned NumThreads = 0;
407409

@@ -470,7 +472,8 @@ class IRGenOptions {
470472
EnableGlobalISel(false), VirtualFunctionElimination(false),
471473
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
472474
InternalizeAtLink(false), InternalizeSymbols(false),
473-
NoPreallocatedInstantiationCaches(false), CmdArgs(),
475+
NoPreallocatedInstantiationCaches(false),
476+
DisableReadonlyStaticObjects(false), CmdArgs(),
474477
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
475478
TypeInfoFilter(TypeInfoDumpFilter::All) {
476479
#ifndef NDEBUG

include/swift/IRGen/Linking.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ class LinkEntity {
364364
/// A SIL global variable. The pointer is a SILGlobalVariable*.
365365
SILGlobalVariable,
366366

367+
/// An outlined read-only global object. The pointer is a SILGlobalVariable*.
368+
ReadOnlyGlobalObject,
369+
367370
// These next few are protocol-conformance kinds.
368371

369372
/// A direct protocol witness table. The secondary pointer is a
@@ -993,13 +996,7 @@ class LinkEntity {
993996
return entity;
994997
}
995998

996-
static LinkEntity forSILGlobalVariable(SILGlobalVariable *G) {
997-
LinkEntity entity;
998-
entity.Pointer = G;
999-
entity.SecondaryPointer = nullptr;
1000-
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::SILGlobalVariable));
1001-
return entity;
1002-
}
999+
static LinkEntity forSILGlobalVariable(SILGlobalVariable *G, IRGenModule &IGM);
10031000

10041001
static LinkEntity
10051002
forDifferentiabilityWitness(const SILDifferentiabilityWitness *witness) {
@@ -1420,7 +1417,8 @@ class LinkEntity {
14201417
}
14211418

14221419
SILGlobalVariable *getSILGlobalVariable() const {
1423-
assert(getKind() == Kind::SILGlobalVariable);
1420+
assert(getKind() == Kind::SILGlobalVariable ||
1421+
getKind() == Kind::ReadOnlyGlobalObject);
14241422
return reinterpret_cast<SILGlobalVariable*>(Pointer);
14251423
}
14261424

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,10 @@ def disable_preallocated_instantiation_caches : Flag<["-"], "disable-preallocate
641641
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
642642
HelpText<"Avoid preallocating metadata instantiation caches in globals">;
643643

644+
def disable_readonly_static_objects : Flag<["-"], "disable-readonly-static-objects">,
645+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
646+
HelpText<"Avoid allocating static objects in a read-only data section">;
647+
644648
def trap_function
645649
: Separate<["-"], "trap-function">, MetaVarName<"<name>">,
646650
HelpText<"Lower traps to calls to this function instead of trap instructions">;

lib/AST/Availability.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,13 @@ ASTContext::getParameterizedExistentialRuntimeAvailability() {
399399
return getSwift57Availability();
400400
}
401401

402+
AvailabilityContext
403+
ASTContext::getImmortalRefCountSymbolsAvailability() {
404+
// TODO: replace this with a concrete swift version once we have it.
405+
// rdar://94185998
406+
return getSwiftFutureAvailability();
407+
}
408+
402409
AvailabilityContext ASTContext::getSwift52Availability() {
403410
auto target = LangOpts.Target;
404411

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,6 +2329,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
23292329
Opts.NoPreallocatedInstantiationCaches = true;
23302330
}
23312331

2332+
if (Args.hasArg(OPT_disable_readonly_static_objects)) {
2333+
Opts.DisableReadonlyStaticObjects = true;
2334+
}
2335+
23322336
// Default to disabling swift async extended frame info on anything but
23332337
// darwin. Other platforms are unlikely to have support for extended frame
23342338
// pointer information.

lib/IRGen/GenConstant.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,27 @@ llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
278278
}
279279
}
280280
// Construct the object header.
281-
llvm::Type *ObjectHeaderTy = sTy->getElementType(0);
282-
assert(ObjectHeaderTy->isStructTy());
283-
elts[0] = llvm::Constant::getNullValue(ObjectHeaderTy);
281+
llvm::StructType *ObjectHeaderTy = cast<llvm::StructType>(sTy->getElementType(0));
282+
283+
if (IGM.canMakeStaticObjectsReadOnly()) {
284+
if (!IGM.swiftImmortalRefCount) {
285+
auto *var = new llvm::GlobalVariable(IGM.Module, IGM.Int8Ty,
286+
/*constant*/ true, llvm::GlobalValue::ExternalLinkage,
287+
/*initializer*/ nullptr, "_swiftImmortalRefCount");
288+
IGM.swiftImmortalRefCount = var;
289+
}
290+
if (!IGM.swiftStaticArrayMetadata) {
291+
auto *var = new llvm::GlobalVariable(IGM.Module, IGM.TypeMetadataStructTy,
292+
/*constant*/ true, llvm::GlobalValue::ExternalLinkage,
293+
/*initializer*/ nullptr, "_swiftStaticArrayMetadata");
294+
IGM.swiftStaticArrayMetadata = var;
295+
}
296+
elts[0] = llvm::ConstantStruct::get(ObjectHeaderTy, {
297+
IGM.swiftStaticArrayMetadata,
298+
llvm::ConstantExpr::getPtrToInt(IGM.swiftImmortalRefCount, IGM.IntPtrTy)});
299+
} else {
300+
elts[0] = llvm::Constant::getNullValue(ObjectHeaderTy);
301+
}
284302
insertPadding(elts, sTy);
285303
return llvm::ConstantStruct::get(sTy, elts);
286304
}

lib/IRGen/GenDecl.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,7 +2482,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
24822482
return Address(addr, alignment);
24832483
}
24842484

2485-
LinkEntity entity = LinkEntity::forSILGlobalVariable(var);
2485+
LinkEntity entity = LinkEntity::forSILGlobalVariable(var, *this);
24862486
ResilienceExpansion expansion = getResilienceExpansionForLayout(var);
24872487

24882488
llvm::Type *storageType;
@@ -2528,28 +2528,33 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
25282528

25292529
// Check whether we've created the global variable already.
25302530
// FIXME: We should integrate this into the LinkEntity cache more cleanly.
2531-
auto gvar = Module.getGlobalVariable(var->getName(), /*allowInternal*/ true);
2531+
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
2532+
auto gvar = Module.getGlobalVariable(link.getName(), /*allowInternal*/ true);
25322533
if (gvar) {
25332534
if (forDefinition)
25342535
updateLinkageForDefinition(*this, gvar, entity);
25352536
} else {
2536-
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
25372537
llvm::Type *storageTypeWithContainer = storageType;
25382538
if (var->isInitializedObject()) {
2539-
// A statically initialized object must be placed into a container struct
2540-
// because the swift_initStaticObject needs a swift_once_t at offset -1:
2541-
// struct Container {
2542-
// swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
2543-
// HeapObject object;
2544-
// };
2545-
std::string typeName = storageType->getStructName().str() + 'c';
2546-
assert(fixedAlignment >= getPointerAlignment());
2547-
unsigned numTokens = fixedAlignment.getValue() /
2548-
getPointerAlignment().getValue();
2549-
storageTypeWithContainer = llvm::StructType::create(getLLVMContext(),
2550-
{llvm::ArrayType::get(OnceTy, numTokens), storageType}, typeName);
2551-
gvar = createVariable(*this, link, storageTypeWithContainer,
2552-
fixedAlignment);
2539+
if (canMakeStaticObjectsReadOnly()) {
2540+
gvar = createVariable(*this, link, storageType, fixedAlignment);
2541+
gvar->setConstant(true);
2542+
} else {
2543+
// A statically initialized object must be placed into a container struct
2544+
// because the swift_initStaticObject needs a swift_once_t at offset -1:
2545+
// struct Container {
2546+
// swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
2547+
// HeapObject object;
2548+
// };
2549+
std::string typeName = storageType->getStructName().str() + 'c';
2550+
assert(fixedAlignment >= getPointerAlignment());
2551+
unsigned numTokens = fixedAlignment.getValue() /
2552+
getPointerAlignment().getValue();
2553+
storageTypeWithContainer = llvm::StructType::create(getLLVMContext(),
2554+
{llvm::ArrayType::get(OnceTy, numTokens), storageType}, typeName);
2555+
gvar = createVariable(*this, link, storageTypeWithContainer,
2556+
fixedAlignment);
2557+
}
25532558
} else {
25542559
StringRef name;
25552560
Optional<SILLocation> loc;
@@ -2574,7 +2579,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
25742579
gvar->setComdat(nullptr);
25752580
}
25762581
llvm::Constant *addr = gvar;
2577-
if (var->isInitializedObject()) {
2582+
if (var->isInitializedObject() && !canMakeStaticObjectsReadOnly()) {
25782583
// Project out the object from the container.
25792584
llvm::Constant *Indices[2] = {
25802585
llvm::ConstantExpr::getIntegerValue(Int32Ty, APInt(32, 0)),

lib/IRGen/IRGenModule.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,6 +1785,19 @@ bool IRGenModule::shouldPrespecializeGenericMetadata() {
17851785
canPrespecializeTarget;
17861786
}
17871787

1788+
bool IRGenModule::canMakeStaticObjectsReadOnly() {
1789+
if (getOptions().DisableReadonlyStaticObjects)
1790+
return false;
1791+
1792+
// TODO: Support constant static arrays on other platforms, too.
1793+
// See also the comment in GlobalObjects.cpp.
1794+
if (!Triple.isOSDarwin())
1795+
return false;
1796+
1797+
return getAvailabilityContext().isContainedIn(
1798+
Context.getImmortalRefCountSymbolsAvailability());
1799+
}
1800+
17881801
void IRGenerator::addGenModule(SourceFile *SF, IRGenModule *IGM) {
17891802
assert(GenModules.count(SF) == 0);
17901803
GenModules[SF] = IGM;

lib/IRGen/IRGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,9 @@ class IRGenModule {
763763

764764
llvm::GlobalVariable *TheTrivialPropertyDescriptor = nullptr;
765765

766+
llvm::GlobalVariable *swiftImmortalRefCount = nullptr;
767+
llvm::GlobalVariable *swiftStaticArrayMetadata = nullptr;
768+
766769
/// Used to create unique names for class layout types with tail allocated
767770
/// elements.
768771
unsigned TailElemTypeID = 0;
@@ -886,6 +889,8 @@ class IRGenModule {
886889

887890
bool shouldPrespecializeGenericMetadata();
888891

892+
bool canMakeStaticObjectsReadOnly();
893+
889894
Size getAtomicBoolSize() const { return AtomicBoolSize; }
890895
Alignment getAtomicBoolAlignment() const { return AtomicBoolAlign; }
891896

0 commit comments

Comments
 (0)