Skip to content

Commit 6e4ccca

Browse files
authored
Merge pull request #72817 from kubamracek/embedded-print-on-assert
[embedded] In -assert-config Debug, print errors in assertions, preconditions, fatalErrors
2 parents 7f0a859 + 67f3d34 commit 6e4ccca

15 files changed

+311
-7
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,20 @@ class SILFunction
13541354
WasmImportModuleAndField = std::make_pair(module, field);
13551355
}
13561356

1357+
bool isExternForwardDeclaration() const {
1358+
if (isExternalDeclaration()) {
1359+
if (auto declContext = getDeclContext()) {
1360+
if (auto decl = declContext->getAsDecl()) {
1361+
if (decl->getAttrs().hasAttribute<ExternAttr>())
1362+
return true;
1363+
if (decl->getAttrs().hasAttribute<SILGenNameAttr>())
1364+
return true;
1365+
}
1366+
}
1367+
}
1368+
return false;
1369+
}
1370+
13571371
/// Returns true if this function belongs to a declaration that returns
13581372
/// an opaque result type with one or more availability conditions that are
13591373
/// allowed to produce a different underlying type at runtime.

lib/SIL/IR/Linker.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void SILLinkerVisitor::maybeAddFunctionToWorklist(SILFunction *F,
102102
bool setToSerializable) {
103103
SILLinkage linkage = F->getLinkage();
104104
assert((!setToSerializable || F->hasValidLinkageForFragileRef() ||
105-
hasSharedVisibility(linkage)) &&
105+
hasSharedVisibility(linkage) || F->isExternForwardDeclaration()) &&
106106
"called function has wrong linkage for serialized function");
107107

108108
if (!F->isExternalDeclaration()) {
@@ -422,7 +422,7 @@ void SILLinkerVisitor::visitMetatypeInst(MetatypeInst *MI) {
422422
}
423423

424424
void SILLinkerVisitor::visitGlobalAddrInst(GlobalAddrInst *GAI) {
425-
if (!Mod.getASTContext().LangOpts.hasFeature(Feature::Embedded))
425+
if (!Mod.getOptions().EmbeddedSwift)
426426
return;
427427

428428
SILGlobalVariable *G = GAI->getReferencedGlobal();
@@ -448,7 +448,7 @@ void SILLinkerVisitor::process() {
448448
Fn->setSerialized(IsSerialized_t::IsNotSerialized);
449449
}
450450

451-
if (Fn->getModule().getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
451+
if (Fn->getModule().getOptions().EmbeddedSwift &&
452452
Fn->getModule().getASTContext().LangOpts.DebuggerSupport) {
453453
// LLDB requires that functions with bodies are not external.
454454
Fn->setLinkage(stripExternalFromLinkage(Fn->getLinkage()));

lib/SIL/IR/Linker.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
146146
/// Is the current mode link all? Link all implies we should try and link
147147
/// everything, not just transparent/shared functions.
148148
bool isLinkAll() const {
149-
return Mode == LinkingMode::LinkAll ||
150-
Mod.getASTContext().LangOpts.hasFeature(Feature::Embedded);
149+
return Mode == LinkingMode::LinkAll || Mod.getOptions().EmbeddedSwift;
151150
}
152151

153152
void linkInVTable(ClassDecl *D);

stdlib/public/core/Assert.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,14 @@ public func fatalError(
278278
_ message: @autoclosure () -> StaticString = StaticString(),
279279
file: StaticString = #file, line: UInt = #line
280280
) -> Never {
281-
_assertionFailure("Fatal error", message(), file: file, line: line,
282-
flags: _fatalErrorFlags())
281+
if _isDebugAssertConfiguration() {
282+
_assertionFailure("Fatal error", message(), file: file, line: line,
283+
flags: _fatalErrorFlags())
284+
} else {
285+
Builtin.condfail_message(true._value,
286+
StaticString("fatal error").unsafeRawPointer)
287+
Builtin.unreachable()
288+
}
283289
}
284290
#endif
285291

stdlib/public/core/AssertCommon.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ internal func _assertionFailure(
110110
}
111111
}
112112
}
113+
#else
114+
_embeddedReportFatalErrorInFile(prefix: prefix, message: message, file: file,
115+
line: line)
113116
#endif
114117
Builtin.int_trap()
115118
}
@@ -183,6 +186,8 @@ internal func _assertionFailure(
183186
_ prefix: StaticString, _ message: StaticString,
184187
flags: UInt32
185188
) -> Never {
189+
_embeddedReportFatalError(prefix: prefix, message: message)
190+
186191
Builtin.int_trap()
187192
}
188193
#endif

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,18 @@ public func swift_clearSensitive(buf: UnsafeMutableRawPointer, nbytes: Int) {
351351
}
352352
}
353353

354+
@usableFromInline
355+
func _embeddedReportFatalError(prefix: StaticString, message: StaticString) {
356+
print(prefix, terminator: "")
357+
if message.utf8CodeUnitCount > 0 { print(": ", terminator: "") }
358+
print(message)
359+
}
360+
361+
@usableFromInline
362+
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: StaticString, file: StaticString, line: UInt) {
363+
print(file, terminator: ":")
364+
print(line, terminator: ": ")
365+
print(prefix, terminator: "")
366+
if message.utf8CodeUnitCount > 0 { print(": ", terminator: "") }
367+
print(message)
368+
}

test/SIL/modules-extern.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-as-library
5+
// RUN: %target-swift-frontend -c -I %t %t/Main.swift -o %t/a.o
6+
7+
// BEGIN MyModule.swift
8+
9+
@_extern(c)
10+
@_alwaysEmitIntoClient
11+
func some_c_api()
12+
13+
@_transparent
14+
public func publicFuncInAModule() {
15+
some_c_api()
16+
}
17+
18+
// BEGIN Main.swift
19+
20+
import MyModule
21+
22+
@_extern(c)
23+
func some_c_api()
24+
25+
some_c_api()
26+
publicFuncInAModule()

test/SIL/modules-extern2.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-as-library
5+
// RUN: %target-swift-frontend -c -I %t %t/Main.swift -o %t/a.o
6+
7+
// BEGIN MyModule.swift
8+
9+
@_silgen_name("some_forward_declared_api")
10+
@_alwaysEmitIntoClient
11+
func some_forward_declared_api()
12+
13+
@_transparent
14+
public func publicFuncInAModule() {
15+
some_forward_declared_api()
16+
}
17+
18+
// BEGIN Main.swift
19+
20+
import MyModule
21+
22+
@_silgen_name("some_forward_declared_api")
23+
func some_forward_declared_api()
24+
25+
some_forward_declared_api()
26+
publicFuncInAModule()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
4+
int putchar(int c) {
5+
putchar_unlocked(c);
6+
fflush(stdout);
7+
return 0;
8+
}

test/embedded/modules-extern.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
5+
// RUN: %target-swift-frontend -c -I %t %t/Main.swift -enable-experimental-feature Embedded -o %t/a.o
6+
7+
// REQUIRES: swift_in_compiler
8+
// REQUIRES: OS=macosx || OS=linux-gnu
9+
10+
// BEGIN MyModule.swift
11+
12+
@_extern(c)
13+
func some_c_api()
14+
15+
@_transparent
16+
public func publicFuncInAModule() {
17+
internalFuncInAModule()
18+
}
19+
20+
@usableFromInline
21+
internal func internalFuncInAModule() {
22+
some_c_api()
23+
}
24+
25+
// BEGIN Main.swift
26+
27+
import MyModule
28+
29+
@_extern(c)
30+
func some_c_api()
31+
32+
some_c_api()
33+
publicFuncInAModule()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang -x c -c %S/Inputs/unbuffered-putchar.c -o %t/unbuffered-putchar.o
3+
4+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out
5+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
6+
7+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O
8+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
9+
10+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize
11+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
12+
13+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O -assert-config Debug
14+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
15+
16+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize -assert-config Debug
17+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
18+
19+
// REQUIRES: swift_in_compiler
20+
// REQUIRES: executable_test
21+
// REQUIRES: optimized_stdlib
22+
// REQUIRES: OS=macosx
23+
24+
func test() {
25+
fatalError("task failed successfully")
26+
// CHECK-MESSAGE: {{.*}}/traps-fatalerror-exec.swift:[[@LINE-1]]: Fatal error: task failed successfully
27+
// CHECK-NOMESSAGE-NOT: Fatal error
28+
// CHECK-NOMESSAGE-NOT: task failed successfully
29+
}
30+
31+
test()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo %s | %FileCheck %s --check-prefix=CHECK-MESSAGE
2+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo %s -O | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
3+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo %s -Osize | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
4+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo %s -O -assert-config Debug | %FileCheck %s --check-prefix=CHECK-MESSAGE
5+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo %s -Osize -assert-config Debug | %FileCheck %s --check-prefix=CHECK-MESSAGE
6+
7+
// REQUIRES: swift_in_compiler
8+
// REQUIRES: optimized_stdlib
9+
// REQUIRES: OS=macosx || OS=linux-gnu
10+
11+
public func test() {
12+
fatalError("task failed successfully")
13+
}
14+
15+
// CHECK-MESSAGE: define {{.*}}void @"$s4main4testyyF"(){{.*}} {
16+
// CHECK-MESSAGE: entry:
17+
// CHECK-MESSAGE: {{.*}}call {{.*}}void @"$ss17_assertionFailure__
18+
// CHECK-MESSAGE-SAME: Fatal error
19+
// CHECK-MESSAGE-SAME: task failed successfully
20+
// CHECK-MESSAGE-SAME: traps-fatalerror-ir.swift
21+
// CHECK-MESSAGE: unreachable
22+
// CHECK-MESSAGE: }
23+
24+
// CHECK-NOMESSAGE: define {{.*}}void @"$s4main4testyyF"(){{.*}} {
25+
// CHECK-NOMESSAGE-NEXT: entry:
26+
// CHECK-NOMESSAGE-NEXT: tail call void asm sideeffect "", "n"(i32 0)
27+
// CHECK-NOMESSAGE-NEXT: tail call void @llvm.trap()
28+
// CHECK-NOMESSAGE-NEXT: unreachable
29+
// CHECK-NOMESSAGE-NEXT: }
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo -Xllvm -link-embedded-runtime=0 %s -O | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
2+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo -Xllvm -link-embedded-runtime=0 %s -Osize | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
3+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo -Xllvm -link-embedded-runtime=0 %s -O -assert-config Debug | %FileCheck %s --check-prefix=CHECK-MESSAGE
4+
// RUN: %target-swift-emit-ir -enable-experimental-feature Embedded -wmo -Xllvm -link-embedded-runtime=0 %s -Osize -assert-config Debug | %FileCheck %s --check-prefix=CHECK-MESSAGE
5+
6+
// REQUIRES: swift_in_compiler
7+
// REQUIRES: optimized_stdlib
8+
// REQUIRES: OS=macosx || OS=linux-gnu
9+
10+
@_extern(c)
11+
public func external()
12+
13+
public func test(i: Int) {
14+
precondition(i % 2 == 0, "precondition 1")
15+
external()
16+
precondition(i % 3 == 0, "precondition 3")
17+
external()
18+
precondition(i % 5 == 0, "precondition 5")
19+
external()
20+
precondition(i % 7 == 0, "precondition 7")
21+
}
22+
23+
// "Non-production builds" - We expect 4 separate _assertionFailure() calls with different values
24+
// CHECK-MESSAGE: define {{.*}}void @"$s4main4test1iySi_tF"(i64 %0) {{.*}}{
25+
// CHECK-MESSAGE: call {{.*}}@"$ss17_assertionFailure
26+
// CHECK-MESSAGE: unreachable
27+
// CHECK-MESSAGE: call {{.*}}@"$ss17_assertionFailure
28+
// CHECK-MESSAGE: unreachable
29+
// CHECK-MESSAGE: call {{.*}}@"$ss17_assertionFailure
30+
// CHECK-MESSAGE: unreachable
31+
// CHECK-MESSAGE: call {{.*}}@"$ss17_assertionFailure
32+
// CHECK-MESSAGE: unreachable
33+
// CHECK-MESSAGE: }
34+
35+
// "Production builds" - We expect 4 separate trap blocks in the IR.
36+
// CHECK-NOMESSAGE: define {{.*}}void @"$s4main4test1iySi_tF"(i64 %0) {{.*}}{
37+
// CHECK-NOMESSAGE: tail call void asm sideeffect "", "n"(i32 0) #3
38+
// CHECK-NOMESSAGE: tail call void @llvm.trap()
39+
// CHECK-NOMESSAGE: unreachable
40+
// CHECK-NOMESSAGE: tail call void asm sideeffect "", "n"(i32 1) #3
41+
// CHECK-NOMESSAGE: tail call void @llvm.trap()
42+
// CHECK-NOMESSAGE: unreachable
43+
// CHECK-NOMESSAGE: tail call void asm sideeffect "", "n"(i32 2) #3
44+
// CHECK-NOMESSAGE: tail call void @llvm.trap()
45+
// CHECK-NOMESSAGE: unreachable
46+
// CHECK-NOMESSAGE: tail call void asm sideeffect "", "n"(i32 3) #3
47+
// CHECK-NOMESSAGE: tail call void @llvm.trap()
48+
// CHECK-NOMESSAGE: unreachable
49+
// CHECK-NOMESSAGE: }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang -x c -c %S/Inputs/unbuffered-putchar.c -o %t/unbuffered-putchar.o
3+
4+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out
5+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
6+
7+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O
8+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
9+
10+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize
11+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
12+
13+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O -assert-config Debug
14+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
15+
16+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize -assert-config Debug
17+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
18+
19+
// REQUIRES: swift_in_compiler
20+
// REQUIRES: executable_test
21+
// REQUIRES: optimized_stdlib
22+
// REQUIRES: OS=macosx
23+
24+
func test(i: Int) {
25+
precondition(i == 0, "task failed successfully")
26+
// CHECK-MESSAGE: {{.*}}/traps-precondition-exec.swift:[[@LINE-1]]: Precondition failed: task failed successfully
27+
// CHECK-NOMESSAGE-NOT: Fatal error
28+
// CHECK-NOMESSAGE-NOT: Precondition failed
29+
// CHECK-NOMESSAGE-NOT: task failed successfully
30+
}
31+
32+
test(i: 42)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang -x c -c %S/Inputs/unbuffered-putchar.c -o %t/unbuffered-putchar.o
3+
4+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out
5+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
6+
7+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O
8+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
9+
10+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize
11+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-NOMESSAGE
12+
13+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -O -assert-config Debug
14+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
15+
16+
// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo -runtime-compatibility-version none %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out -Osize -assert-config Debug
17+
// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s --check-prefix=CHECK-MESSAGE
18+
19+
// REQUIRES: swift_in_compiler
20+
// REQUIRES: executable_test
21+
// REQUIRES: optimized_stdlib
22+
// REQUIRES: OS=macosx
23+
24+
func test() {
25+
preconditionFailure("task failed successfully")
26+
// CHECK-MESSAGE: {{.*}}/traps-preconditionfailure-exec.swift:[[@LINE-1]]: Fatal error: task failed successfully
27+
// CHECK-NOMESSAGE-NOT: Fatal error
28+
// CHECK-NOMESSAGE-NOT: task failed successfully
29+
}
30+
31+
test()

0 commit comments

Comments
 (0)