[SILGen] do not clear parent module when emitting stored initializer function

When SILGen was emitting the stored initializer function, it updated the location to a new autogenerated location tied to the initialization expression. That in turn reset the function's parent module to null, as the initialization expression is not a decl, and thus it didn't produce a decl context SIL could use when looking for the parent module. That lead to a this function having no parent module when it was serialized, and thus a user that used this function from code in another Swift module thought that this function should use 'dllimport' on Windows, even when the parent module was built with as the static library (i.e. using the -static flag). This lead to spurious LNK4217 diagnostics when building the Swift package manager using CMake on windows. This change fixes that by preserving the parent module for such function.
This commit is contained in:
Alex Lorenz
2024-01-25 14:56:54 -08:00
parent daebcc3fdf
commit 7b2d7124b3
2 changed files with 62 additions and 0 deletions

View File

@@ -967,6 +967,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
auto *init = constant.getInitializationExpr();
assert(init);
auto *parentMod = f->getParentModule();
auto loc = RegularLocation::getAutoGeneratedLocation(init);
preEmitFunction(constant, f, loc);
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
@@ -974,6 +975,12 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
SILGenFunction SGF(*this, *f, initDC);
SGF.emitGeneratorFunction(constant, init, /*EmitProfilerIncrement=*/true);
postEmitFunction(constant, f);
// Ensure that the SIL function has a module associated with it. This
// ensures that SIL serializer serializes the module id for this function
// correctly. The parent module can be reset when the function's location is
// updated to the autogenerated location above.
if (!f->getParentModule())
f->setParentModule(parentMod);
break;
}

View File

@@ -0,0 +1,55 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -c %t/inlinedStruct.swift -static -O -parse-as-library -module-name InlinedStructs -emit-module-path %t/InlinedStructs.swiftmodule -o %t/inlinedStruct.swift.o
// RUN: %target-swift-frontend -c -emit-ir -O %t/use.swift -I %t -o %t/use.swift.ir
// RUN: cat %t/use.swift.ir | %FileCheck %s
// RUN: rm -rf %t/InlinedStructs.swiftmodule
// RUN: %target-swift-frontend -c %t/inlinedStruct.swift -O -parse-as-library -module-name InlinedStructs -emit-module-path %t/InlinedStructs.swiftmodule -o %t/inlinedStruct.swift.o
// RUN: %target-swift-frontend -c -emit-ir -O %t/use.swift -I %t -o %t/use.swift.ir
// RUN: cat %t/use.swift.ir | %FileCheck --check-prefix=DLLIMPORT %s
// REQUIRES: OS=windows-msvc
//--- inlinedStruct.swift
@usableFromInline
struct CMSSignedData {
@usableFromInline var field: Bool?
@inlinable
init(field: Bool?) {
self.field = field
}
}
public struct TestS {
@usableFromInline
let x: CMSSignedData = CMSSignedData(field: false)
@inlinable
public init() { }
@inlinable
public var field: Bool {
return x.field!
}
}
//--- use.swift
import InlinedStructs
public struct TestTwo {
let field: TestS = TestS()
}
public func testTwo() -> Bool {
let x = TestTwo()
return x.field.field
}
// Ensure that the variable initialization expression is not dllimported on Windows.
// CHECK: declare swiftcc i8 @"$s14InlinedStructs5TestSV1xAA13CMSSignedDataVvpfi"()
// DLLIMPORT: declare dllimport swiftcc i8 @"$s14InlinedStructs5TestSV1xAA13CMSSignedDataVvpfi"()