Skip to content

Commit 77fc49c

Browse files
authored
Merge pull request #79581 from kubamracek/embedded-fatalerror-stringinterp
[embedded] Allow string-interpolating fatalError in Embedded Swift
2 parents e97db1c + 01d7e23 commit 77fc49c

File tree

6 files changed

+97
-2
lines changed

6 files changed

+97
-2
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: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,16 @@ 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+
#if !$Embedded
146147
prefix.withUTF8Buffer {
147148
(prefix) -> Void in
148149
var message = message
@@ -158,6 +159,14 @@ internal func _assertionFailure(
158159
}
159160
}
160161
}
162+
#else
163+
if _isDebugAssertConfiguration() {
164+
var message = message
165+
message.withUTF8 { (messageUTF8) -> Void in
166+
_embeddedReportFatalErrorInFile(prefix: prefix, message: messageUTF8, file: file, line: line)
167+
}
168+
}
169+
#endif
161170

162171
Builtin.int_trap()
163172
}

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 unsafe c in unsafe buf {
6879
putchar(CInt(c))

stdlib/public/core/EmbeddedRuntime.swift

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

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

536537
@usableFromInline
538+
@inline(never)
537539
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: StaticString, file: StaticString, line: UInt) {
538540
print(file, terminator: ":")
539541
print(line, terminator: ": ")
540542
print(prefix, terminator: "")
541543
if message.utf8CodeUnitCount > 0 { print(": ", terminator: "") }
542544
print(message)
543545
}
546+
547+
@usableFromInline
548+
@inline(never)
549+
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: UnsafeBufferPointer<UInt8>, file: StaticString, line: UInt) {
550+
print(file, terminator: ":")
551+
print(line, terminator: ": ")
552+
print(prefix, terminator: "")
553+
if message.count > 0 { print(": ", terminator: "") }
554+
print(message)
555+
}
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)