Skip to content

Commit 27626ec

Browse files
authored
Merge pull request swiftlang#35994 from eeckstein/fix-function-globals
2 parents e05cf76 + 184ee71 commit 27626ec

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed

lib/IRGen/GenConstant.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ llvm::Constant *irgen::emitConstantValue(IRGenModule &IGM, SILValue operand) {
249249
fnPtr = IGM.getConstantSignedPointer(fnPtr, authInfo.getKey(), nullptr,
250250
constantDiscriminator);
251251
}
252+
llvm::Type *ty = IGM.getTypeInfo(FRI->getType()).getStorageType();
253+
fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, ty);
252254
return fnPtr;
253255
} else {
254256
llvm_unreachable("Unsupported SILInstruction in static initializer!");

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,8 +1326,8 @@ void IRGenerator::addLazyFunction(SILFunction *f) {
13261326
// f is a specialization. Try to emit all specializations of the same
13271327
// original function into the same IGM. This increases the chances that
13281328
// specializations are merged by LLVM's function merging.
1329-
auto iter =
1330-
IGMForSpecializations.insert(std::make_pair(orig, CurrentIGM)).first;
1329+
IRGenModule *IGM = CurrentIGM ? CurrentIGM : getPrimaryIGM();
1330+
auto iter = IGMForSpecializations.insert(std::make_pair(orig, IGM)).first;
13311331
DefaultIGMForFunction.insert(std::make_pair(f, iter->second));
13321332
return;
13331333
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Test
2+
3+
testit(0)
4+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Testcase for an IRGen crash with function pointers in static globals and multi-threaded compilation.
2+
3+
// First test: check if the compilation succeeds and the code is correct.
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: %target-build-swift -O -module-name=Test %s -o %t/a.out
7+
// RUN: %target-codesign %t/a.out
8+
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
9+
10+
// Second test (bonus): check if the optimization is done: statically initialize a global with a C-function pointer
11+
12+
// RUN: %target-build-swift -O -module-name=Test %s -emit-sil | %FileCheck %s -check-prefix=CHECK-SIL
13+
14+
// REQUIRES: executable_test
15+
16+
17+
internal func cFn(_ i: Int) -> Int {
18+
return i + 1
19+
}
20+
21+
public struct S {
22+
// CHECK-SIL-LABEL: sil_global @$s4Test1SV6cFnPtryS2iXCvpZ : $@convention(c) (Int) -> Int = {
23+
// CHECK-SIL: %initval = function_ref @$s4Test3cFnyS2iFTo : $@convention(c) (Int) -> Int
24+
static public var cFnPtr: @convention(c) (Int) -> Int = cFn
25+
}
26+
27+
func testit() {
28+
// CHECK-OUTPUT: 28
29+
print(S.cFnPtr(27))
30+
}
31+
32+
testit()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Testcase for an IRGen crash with function pointers in static globals and multi-threaded compilation.
2+
3+
// First test: check if the compilation succeeds and the code is correct.
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: touch %t/empty.swift
7+
// RUN: %target-build-swift -O -wmo -parse-as-library -num-threads 2 -emit-module -emit-module-path=%t/Test.swiftmodule -module-name=Test %s %t/empty.swift -c -o %t/test.o
8+
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %S/Inputs/global-functionptr-main.swift -c -o %t/main.o
9+
// RUN: %target-swiftc_driver %t/main.o %t/test.o -o %t/a.out
10+
// RUN: %target-codesign %t/a.out
11+
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
12+
13+
// Second test (bonus): check if the optimization is done: statically initialize the array of function pointers.
14+
15+
// RUN: %target-build-swift -O -wmo -parse-as-library -module-name=Test %s -emit-sil | %FileCheck %s -check-prefix=CHECK-SIL
16+
17+
// REQUIRES: executable_test
18+
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
19+
20+
internal protocol P {
21+
init()
22+
}
23+
24+
private struct FuncPtr {
25+
let cl: () -> Void
26+
27+
init<C: P>(_: C.Type) {
28+
self.cl = { _ = C.init() }
29+
}
30+
}
31+
32+
public struct S: P {
33+
init() {
34+
print("init S")
35+
}
36+
}
37+
38+
// CHECK-SIL-LABEL: sil_global private @$s4Test8funcPtrs{{.*}}_WZTv_ : $_ContiguousArrayStorage<FuncPtr> = {
39+
// CHECK-SIL: %0 = function_ref @$s4Test7FuncPtr{{.*}}Tg5 : $@convention(thin) () -> ()
40+
// CHECK-SIL: %initval = object $_ContiguousArrayStorage<FuncPtr> ({{%[0-9]+}} : $_ArrayBody, [tail_elems] {{%[0-9]+}} : $FuncPtr, {{%[0-9]+}} : $FuncPtr)
41+
private let funcPtrs = [
42+
FuncPtr(S.self),
43+
FuncPtr(S.self)]
44+
45+
public func testit(_ i: Int) {
46+
// CHECK-OUTPUT: init S
47+
funcPtrs[i].cl()
48+
}
49+

0 commit comments

Comments
 (0)