Skip to content

Commit 0e5a6c4

Browse files
committed
[embedded] Allow string-interpolating fatalError in Embedded Swift
1 parent 874c625 commit 0e5a6c4

File tree

6 files changed

+100
-8
lines changed

6 files changed

+100
-8
lines changed

stdlib/public/core/Assert.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,16 +275,26 @@ public func preconditionFailure(
275275
/// - line: The line number to print along with `message`. The default is the
276276
/// line number where `fatalError(_:file:line:)` is called.
277277
@_transparent
278-
@_unavailableInEmbedded
279278
#if $Embedded
280279
@_disfavoredOverload
281280
#endif
282281
public func fatalError(
283282
_ message: @autoclosure () -> String = String(),
284283
file: StaticString = #file, line: UInt = #line
285284
) -> Never {
285+
#if !$Embedded
286286
_assertionFailure("Fatal error", message(), file: file, line: line,
287287
flags: _fatalErrorFlags())
288+
#else
289+
if _isDebugAssertConfiguration() {
290+
_assertionFailure("Fatal error", message(), file: file, line: line,
291+
flags: _fatalErrorFlags())
292+
} else {
293+
Builtin.condfail_message(true._value,
294+
StaticString("fatal error").unsafeRawPointer)
295+
Builtin.unreachable()
296+
}
297+
#endif
288298
}
289299

290300
#if $Embedded

stdlib/public/core/AssertCommon.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,22 +134,20 @@ internal func _assertionFailure(
134134
#if !$Embedded
135135
@inline(never)
136136
#else
137+
@_disfavoredOverload
137138
@inline(__always)
138139
#endif
139140
@_semantics("programtermination_point")
140-
@_unavailableInEmbedded
141141
internal func _assertionFailure(
142142
_ prefix: StaticString, _ message: String,
143143
file: StaticString, line: UInt,
144144
flags: UInt32
145145
) -> Never {
146-
prefix.withUTF8Buffer {
147-
(prefix) -> Void in
146+
#if !$Embedded
147+
prefix.withUTF8Buffer { (prefix) -> Void in
148148
var message = message
149-
message.withUTF8 {
150-
(messageUTF8) -> Void in
151-
file.withUTF8Buffer {
152-
(file) -> Void in
149+
message.withUTF8 { (messageUTF8) -> Void in
150+
file.withUTF8Buffer { (file) -> Void in
153151
_swift_stdlib_reportFatalErrorInFile(
154152
prefix.baseAddress!, CInt(prefix.count),
155153
messageUTF8.baseAddress!, CInt(messageUTF8.count),
@@ -158,6 +156,14 @@ internal func _assertionFailure(
158156
}
159157
}
160158
}
159+
#else
160+
if _isDebugAssertConfiguration() {
161+
var message = message
162+
message.withUTF8 { (messageUTF8) -> Void in
163+
_embeddedReportFatalErrorInFile(prefix: prefix, message: messageUTF8, file: file, line: line)
164+
}
165+
}
166+
#endif
161167

162168
Builtin.int_trap()
163169
}

stdlib/public/core/EmbeddedPrint.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ public func print(_ object: some CustomStringConvertible, terminator: StaticStri
6363
}
6464
}
6565
66+
func print(_ buf: UnsafeBufferPointer<UInt8>, terminator: StaticString = "\n") {
67+
for c in buf {
68+
putchar(CInt(c))
69+
}
70+
var p = terminator.utf8Start
71+
while p.pointee != 0 {
72+
putchar(CInt(p.pointee))
73+
p += 1
74+
}
75+
}
76+
6677
func printCharacters(_ buf: UnsafeRawBufferPointer) {
6778
for c in buf {
6879
putchar(CInt(c))

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,17 +526,29 @@ public func swift_clearSensitive(buf: UnsafeMutableRawPointer, nbytes: Int) {
526526
}
527527

528528
@usableFromInline
529+
@inline(never)
529530
func _embeddedReportFatalError(prefix: StaticString, message: StaticString) {
530531
print(prefix, terminator: "")
531532
if message.utf8CodeUnitCount > 0 { print(": ", terminator: "") }
532533
print(message)
533534
}
534535

535536
@usableFromInline
537+
@inline(never)
536538
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: StaticString, file: StaticString, line: UInt) {
537539
print(file, terminator: ":")
538540
print(line, terminator: ": ")
539541
print(prefix, terminator: "")
540542
if message.utf8CodeUnitCount > 0 { print(": ", terminator: "") }
541543
print(message)
542544
}
545+
546+
@usableFromInline
547+
@inline(never)
548+
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: UnsafeBufferPointer<UInt8>, file: StaticString, line: UInt) {
549+
print(file, terminator: ":")
550+
print(line, terminator: ": ")
551+
print(prefix, terminator: "")
552+
if message.count > 0 { print(": ", terminator: "") }
553+
print(message)
554+
}
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: %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 || OS=linux-gnu
23+
// REQUIRES: swift_test_mode_optimize_none
24+
// REQUIRES: swift_feature_Embedded
25+
26+
func testWithInterpolation(i: Int) {
27+
fatalError("task failed successfully \(i)")
28+
// CHECK-MESSAGE: {{.*}}/traps-fatalerror-exec2.swift:[[@LINE-1]]: Fatal error: task failed successfully 42
29+
// CHECK-NOMESSAGE-NOT: Fatal error
30+
// CHECK-NOMESSAGE-NOT: task failed successfully 42
31+
}
32+
33+
testWithInterpolation(i: 42)

test/embedded/traps-fatalerror-ir.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,23 @@ public func test() {
2727
// CHECK-NOMESSAGE-NEXT: tail call void @llvm.trap()
2828
// CHECK-NOMESSAGE-NEXT: unreachable
2929
// CHECK-NOMESSAGE-NEXT: }
30+
31+
public func testWithInterpolation(i: Int) {
32+
fatalError("task failed successfully \(i)")
33+
}
34+
35+
// CHECK-MESSAGE: define {{.*}}void @"$e4main21testWithInterpolation1iySi_tF"(i64 %0){{.*}} {
36+
// CHECK-MESSAGE: entry:
37+
// CHECK-MESSAGE: task failed successfully
38+
// CHECK-MESSAGE: {{.*}}call {{.*}}void @"${{(es17_assertionFailure__|es31_embeddedReportFatalErrorInFile6prefix7message4file4lineys12StaticStringV_SRys5UInt8VGAGSutF)}}
39+
// CHECK-MESSAGE-SAME: Fatal error
40+
// CHECK-MESSAGE-SAME: traps-fatalerror-ir.swift
41+
// CHECK-MESSAGE: unreachable
42+
// CHECK-MESSAGE: }
43+
44+
// CHECK-NOMESSAGE: define {{.*}}void @"$e4main21testWithInterpolation1iySi_tF"(i64 %0){{.*}} {
45+
// CHECK-NOMESSAGE-NEXT: entry:
46+
// CHECK-NOMESSAGE-NEXT: tail call void asm sideeffect "", "n"(i32 0)
47+
// CHECK-NOMESSAGE-NEXT: tail call void @llvm.trap()
48+
// CHECK-NOMESSAGE-NEXT: unreachable
49+
// CHECK-NOMESSAGE-NEXT: }

0 commit comments

Comments
 (0)