IRGen: internalize symbols with -static

This pipes the `-static` flag when building a static library into IRGen.
This should have no impact on non-Windows targets as the usage of the
information simply removes the `dllexport` attribute on the generated
interfaces.  This ensures that a library built with `-static` will not
re-export its interfaces from the consumer.  This is important to ensure
that the consumer does not vend the API surface when it statically links
a library.  In conjunction with the removal of the force load symbol,
this allows the generation of static libraries which may be linked
against on Windows.  However, a subsequent change is needed to ensure
that the consumer does not mark the symbol as being imported from a
foreign module (i.e. `dllimport`).
This commit is contained in:
Saleem Abdulrasool
2022-02-15 10:39:44 -08:00
parent b296d41b33
commit 98bd2dba57
9 changed files with 102 additions and 10 deletions

View File

@@ -377,6 +377,9 @@ public:
unsigned InternalizeAtLink : 1; unsigned InternalizeAtLink : 1;
/// Internalize symbols (static library) - do not export any public symbols.
unsigned InternalizeSymbols : 1;
/// Whether to avoid emitting zerofill globals as preallocated type metadata /// Whether to avoid emitting zerofill globals as preallocated type metadata
/// and prototol conformance caches. /// and prototol conformance caches.
unsigned NoPreallocatedInstantiationCaches : 1; unsigned NoPreallocatedInstantiationCaches : 1;
@@ -443,7 +446,7 @@ public:
DisableStandardSubstitutionsInReflectionMangling(false), DisableStandardSubstitutionsInReflectionMangling(false),
EnableGlobalISel(false), VirtualFunctionElimination(false), EnableGlobalISel(false), VirtualFunctionElimination(false),
WitnessMethodElimination(false), ConditionalRuntimeRecords(false), WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
InternalizeAtLink(false), InternalizeAtLink(false), InternalizeSymbols(false),
NoPreallocatedInstantiationCaches(false), NoPreallocatedInstantiationCaches(false),
CmdArgs(), CmdArgs(),
SanitizeCoverage(llvm::SanitizerCoverageOptions()), SanitizeCoverage(llvm::SanitizerCoverageOptions()),

View File

@@ -46,6 +46,7 @@ class UniversalLinkageInfo {
public: public:
bool IsELFObject; bool IsELFObject;
bool UseDLLStorage; bool UseDLLStorage;
bool Internalize;
/// True iff are multiple llvm modules. /// True iff are multiple llvm modules.
bool HasMultipleIGMs; bool HasMultipleIGMs;
@@ -57,7 +58,7 @@ public:
explicit UniversalLinkageInfo(IRGenModule &IGM); explicit UniversalLinkageInfo(IRGenModule &IGM);
UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs, UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs,
bool forcePublicDecls); bool forcePublicDecls, bool isStaticLibrary);
/// In case of multiple llvm modules (in multi-threaded compilation) all /// In case of multiple llvm modules (in multi-threaded compilation) all
/// private decls must be visible from other files. /// private decls must be visible from other files.

View File

@@ -2190,6 +2190,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
Opts.InternalizeAtLink = true; Opts.InternalizeAtLink = true;
} }
Opts.InternalizeSymbols = FrontendOpts.Static;
if (Args.hasArg(OPT_disable_preallocated_instantiation_caches)) { if (Args.hasArg(OPT_disable_preallocated_instantiation_caches)) {
Opts.NoPreallocatedInstantiationCaches = true; Opts.NoPreallocatedInstantiationCaches = true;
} }

View File

@@ -2020,7 +2020,9 @@ void IRGenModule::emitVTableStubs() {
if (F.getEffectiveSymbolLinkage() == SILLinkage::Hidden) if (F.getEffectiveSymbolLinkage() == SILLinkage::Hidden)
alias->setVisibility(llvm::GlobalValue::HiddenVisibility); alias->setVisibility(llvm::GlobalValue::HiddenVisibility);
else else
ApplyIRLinkage(IRLinkage::ExternalExport).to(alias); ApplyIRLinkage(IRGen.Opts.InternalizeSymbols
? IRLinkage::Internal
: IRLinkage::ExternalExport).to(alias);
} }
} }
@@ -2090,7 +2092,8 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
switch (linkage) { switch (linkage) {
case SILLinkage::Public: case SILLinkage::Public:
return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility, return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility,
ExportedStorage}; info.Internalize ? llvm::GlobalValue::DefaultStorageClass
: ExportedStorage};
case SILLinkage::PublicNonABI: case SILLinkage::PublicNonABI:
return isDefinition ? RESULT(WeakODR, Hidden, Default) return isDefinition ? RESULT(WeakODR, Hidden, Default)

View File

@@ -1352,7 +1352,9 @@ void IRGenModule::emitSILProperty(SILProperty *prop) {
TheTrivialPropertyDescriptor); TheTrivialPropertyDescriptor);
ApplyIRLinkage({linkInfo.getLinkage(), ApplyIRLinkage({linkInfo.getLinkage(),
linkInfo.getVisibility(), linkInfo.getVisibility(),
llvm::GlobalValue::DLLExportStorageClass}) IRGen.Opts.InternalizeSymbols
? llvm::GlobalValue::DefaultStorageClass
: llvm::GlobalValue::DLLExportStorageClass})
.to(GA, linkInfo.isForDefinition()); .to(GA, linkInfo.isForDefinition());
} }
return; return;

View File

@@ -1574,7 +1574,9 @@ static llvm::GlobalObject *createForceImportThunk(IRGenModule &IGM) {
llvm::GlobalValue::LinkOnceODRLinkage, buf, llvm::GlobalValue::LinkOnceODRLinkage, buf,
&IGM.Module); &IGM.Module);
ForceImportThunk->setAttributes(IGM.constructInitialAttributes()); ForceImportThunk->setAttributes(IGM.constructInitialAttributes());
ApplyIRLinkage(IRLinkage::ExternalExport).to(ForceImportThunk); ApplyIRLinkage(IGM.IRGen.Opts.InternalizeSymbols
? IRLinkage::Internal
: IRLinkage::ExternalExport).to(ForceImportThunk);
if (IGM.Triple.supportsCOMDAT()) if (IGM.Triple.supportsCOMDAT())
if (auto *GO = cast<llvm::GlobalObject>(ForceImportThunk)) if (auto *GO = cast<llvm::GlobalObject>(ForceImportThunk))
GO->setComdat(IGM.Module.getOrInsertComdat(ForceImportThunk->getName())); GO->setComdat(IGM.Module.getOrInsertComdat(ForceImportThunk->getName()));

View File

@@ -80,14 +80,16 @@ bool swift::irgen::useDllStorage(const llvm::Triple &triple) {
UniversalLinkageInfo::UniversalLinkageInfo(IRGenModule &IGM) UniversalLinkageInfo::UniversalLinkageInfo(IRGenModule &IGM)
: UniversalLinkageInfo(IGM.Triple, IGM.IRGen.hasMultipleIGMs(), : UniversalLinkageInfo(IGM.Triple, IGM.IRGen.hasMultipleIGMs(),
IGM.IRGen.Opts.ForcePublicLinkage) {} IGM.IRGen.Opts.ForcePublicLinkage,
IGM.IRGen.Opts.InternalizeSymbols) {}
UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple, UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple,
bool hasMultipleIGMs, bool hasMultipleIGMs,
bool forcePublicDecls) bool forcePublicDecls,
bool isStaticLibrary)
: IsELFObject(triple.isOSBinFormatELF()), : IsELFObject(triple.isOSBinFormatELF()),
UseDLLStorage(useDllStorage(triple)), HasMultipleIGMs(hasMultipleIGMs), UseDLLStorage(useDllStorage(triple)), HasMultipleIGMs(hasMultipleIGMs),
ForcePublicDecls(forcePublicDecls) {} Internalize(isStaticLibrary), ForcePublicDecls(forcePublicDecls) {}
/// Mangle this entity into the given buffer. /// Mangle this entity into the given buffer.
void LinkEntity::mangle(SmallVectorImpl<char> &buffer) const { void LinkEntity::mangle(SmallVectorImpl<char> &buffer) const {

View File

@@ -173,7 +173,8 @@ public:
ModuleDecl *swiftModule, const TBDGenOptions &opts, ModuleDecl *swiftModule, const TBDGenOptions &opts,
APIRecorder &recorder) APIRecorder &recorder)
: DataLayoutDescription(dataLayoutString), : DataLayoutDescription(dataLayoutString),
UniversalLinkInfo(target, opts.HasMultipleIGMs, /*forcePublic*/ false), UniversalLinkInfo(target, opts.HasMultipleIGMs, /*forcePublic*/ false,
/*static=*/false),
SwiftModule(swiftModule), Opts(opts), recorder(recorder), SwiftModule(swiftModule), Opts(opts), recorder(recorder),
previousInstallNameMap(parsePreviousModuleInstallNameMap()) {} previousInstallNameMap(parsePreviousModuleInstallNameMap()) {}

View File

@@ -0,0 +1,76 @@
// RUN: %empty-directory(%t)
// RUN: %swiftc_driver_plain -target x86_64-unknown-windows-msvc -DLIBRARY -module-name Library -emit-library -static -autolink-force-load -module-link-name Library %s -o %t/library.lib -emit-module-path %t
// RUN: %swiftc_driver_plain -target x86_64-unknown-windows-msvc -DLIBRARY -module-name Library -emit-library -static -autolink-force-load -module-link-name Library %s -S -emit-ir -o - | %FileCheck -check-prefix CHECK-LIBRARY %s
// RUN: %swiftc_driver_plain -target x86_64-unknown-windows-msvc -I %t -emit-library -S -emit-ir -o - %s | %FileCheck -check-prefix CHECK-EMBEDDING %s
// REQUIRES: OS=windows-msvc
#if LIBRARY
// nominal type descriptor for Library.C
// CHECK-LIBRARY: @"$s7Library1CCMn" = constant
// nominal type descriptor for Library.S
// CHECK-LIBRARY: @"$s7Library1SVMn" = constant
// method descriptor for Library.C.method
// CHECK-LBRARY: @"$s7Library1CC6methodyyFTq" = alias
// type metadata for Library.C
// CHECK-LIBRARY: @"$s7Library1CCN" = alias
// type metadata for Library.S
// CHECK-LIBRARY: @"$s7Library1SVN" = alias
public func f() {
}
// Library.f() -> ()
// CHECK-LIBRARY: define swiftcc void @"$s7Library1fyyF"()
open class C {
var property: () -> () {
return f
}
open func method() {
}
}
// Library.C.method() -> ()
// CHECK-LIBRARY: define swiftcc void @"$s7Library1CC6methodyyF"(%T7Library1CC* swiftself %0)
// Library.C.deinit
// CHECK-LIBRARY: define swiftcc %swift.refcounted* @"$s7Library1CCfd"(%T7Library1CC* swiftself %0)
// Library.C.__deallocating_deinit
// CHECK-LIBRARY: define swiftcc void @"$s7Library1CCfD"(%T7Library1CC* swiftself %0)
// Library.C.__allocating_init() -> Library.C
// CHECK-LIBRARY: define swiftcc %T7Library1CC* @"$s7Library1CCACycfC"(%swift.type* swiftself %0)
public struct S {
var member: () -> Void = f
}
// variable initialization expression of Library.S.member : () -> ()
// CHECK-LIBRARY: define swiftcc { i8*, %swift.refcounted* } @"$s7Library1SV6memberyycvpfi"()
// type metadata accessor for Library.C
// CHECK-LIBRARY: define swiftcc %swift.metadata_response @"$s7Library1CCMa"(i64 %0)
// type metadata accessor for Library.S
// CHECK-LIBRARY: define swiftcc %swift.metadata_response @"$s7Library1SVMa"(i64 %0)
// CHECK-LIBRARY: define internal void @"_swift_FORCE_LOAD_$_Library"()
#else
import Library
func f() {
Library.f()
}
// CHECK-EMBEDDING-NOT: @"_swift_FORCE_LOAD_$_Library"
#endif