Skip to content

Commit 96ef644

Browse files
authored
Merge pull request swiftlang#68658 from kubamracek/embedded-pointer-conversions
[embedded] Un-fatalError array to pointer conversion APIs, add test
2 parents a69bcf8 + 9898fc2 commit 96ef644

File tree

3 files changed

+117
-18
lines changed

3 files changed

+117
-18
lines changed

stdlib/public/core/Array.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,6 @@ extension Array: CustomStringConvertible, CustomDebugStringConvertible {
14861486

14871487
extension Array {
14881488
@usableFromInline @_transparent
1489-
@_unavailableInEmbedded
14901489
internal func _cPointerArgs() -> (AnyObject?, UnsafeRawPointer?) {
14911490
let p = _baseAddressIfContiguous
14921491
if _fastPath(p != nil || isEmpty) {

stdlib/public/core/Pointer.swift

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,12 @@ func _convertInOutToPointerArgument<
415415
return ToPointer(from)
416416
}
417417

418-
#if !$Embedded
419418

420419
/// Derive a pointer argument from a value array parameter.
421420
///
422421
/// This always produces a non-null pointer, even if the array doesn't have any
423422
/// storage.
423+
#if !$Embedded
424424
@_transparent
425425
public // COMPILER_INTRINSIC
426426
func _convertConstArrayToPointerArgument<
@@ -439,10 +439,31 @@ func _convertConstArrayToPointerArgument<
439439
}
440440
return (owner, validPointer)
441441
}
442+
#else
443+
@_transparent
444+
public // COMPILER_INTRINSIC
445+
func _convertConstArrayToPointerArgument<
446+
FromElement,
447+
ToPointer: _Pointer
448+
>(_ arr: [FromElement]) -> (Builtin.NativeObject?, ToPointer) {
449+
let (owner, opaquePointer) = arr._cPointerArgs()
450+
451+
let validPointer: ToPointer
452+
if let addr = opaquePointer {
453+
validPointer = ToPointer(addr._rawValue)
454+
} else {
455+
let lastAlignedValue = ~(MemoryLayout<FromElement>.alignment - 1)
456+
let lastAlignedPointer = UnsafeRawPointer(bitPattern: lastAlignedValue)!
457+
validPointer = ToPointer(lastAlignedPointer._rawValue)
458+
}
459+
return (owner, validPointer)
460+
}
461+
#endif
442462

443463
/// Derive a pointer argument from an inout array parameter.
444464
///
445465
/// This always produces a non-null pointer, even if the array's length is 0.
466+
#if !$Embedded
446467
@_transparent
447468
public // COMPILER_INTRINSIC
448469
func _convertMutableArrayToPointerArgument<
@@ -458,8 +479,26 @@ func _convertMutableArrayToPointerArgument<
458479

459480
return _convertConstArrayToPointerArgument(a)
460481
}
482+
#else
483+
@_transparent
484+
public // COMPILER_INTRINSIC
485+
func _convertMutableArrayToPointerArgument<
486+
FromElement,
487+
ToPointer: _Pointer
488+
>(_ a: inout [FromElement]) -> (Builtin.NativeObject?, ToPointer) {
489+
// TODO: Putting a canary at the end of the array in checked builds might
490+
// be a good idea
491+
492+
// Call reserve to force contiguous storage.
493+
a.reserveCapacity(0)
494+
_debugPrecondition(a._baseAddressIfContiguous != nil || a.isEmpty)
495+
496+
return _convertConstArrayToPointerArgument(a)
497+
}
498+
#endif
461499

462500
/// Derive a UTF-8 pointer argument from a value string parameter.
501+
#if !$Embedded
463502
@_transparent
464503
public // COMPILER_INTRINSIC
465504
func _convertConstStringToUTF8PointerArgument<
@@ -468,25 +507,12 @@ func _convertConstStringToUTF8PointerArgument<
468507
let utf8 = Array(str.utf8CString)
469508
return _convertConstArrayToPointerArgument(utf8)
470509
}
471-
472510
#else
473-
474-
@_unavailableInEmbedded public
475-
func _convertConstArrayToPointerArgument<FromElement,ToPointer: _Pointer>(
476-
_ arr: [FromElement]) -> (Builtin.NativeObject?, ToPointer) {
477-
fatalError("unreachable in embedded Swift (marked as unavailable)")
478-
}
479-
480-
@_unavailableInEmbedded public
481-
func _convertMutableArrayToPointerArgument<FromElement, ToPointer: _Pointer>(
482-
_ a: inout [FromElement]) -> (Builtin.NativeObject?, ToPointer) {
483-
fatalError("unreachable in embedded Swift (marked as unavailable)")
484-
}
485-
486-
@_unavailableInEmbedded public
511+
@_transparent
512+
@_unavailableInEmbedded
513+
public
487514
func _convertConstStringToUTF8PointerArgument<ToPointer: _Pointer>(
488515
_ str: String) -> (Builtin.NativeObject?, ToPointer) {
489516
fatalError("unreachable in embedded Swift (marked as unavailable)")
490517
}
491-
492518
#endif

test/embedded/array-to-pointer.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -c -o %t/main.o
3+
// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o
4+
// RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o
5+
// RUN: %target-clang %t/main.o %t/runtime.o %t/print.o -o %t/a.out -dead_strip
6+
// RUN: %target-run %t/a.out | %FileCheck %s
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: VENDOR=apple
10+
// REQUIRES: OS=macosx
11+
12+
@_silgen_name("putchar")
13+
func putchar(_: UInt8)
14+
15+
public func print(_ s: StaticString, terminator: StaticString = "\n") {
16+
var p = s.utf8Start
17+
while p.pointee != 0 {
18+
putchar(p.pointee)
19+
p += 1
20+
}
21+
p = terminator.utf8Start
22+
while p.pointee != 0 {
23+
putchar(p.pointee)
24+
p += 1
25+
}
26+
}
27+
28+
@_silgen_name("print_long")
29+
func print_long(_: Int)
30+
31+
public func print(_ n: Int, terminator: StaticString = "\n") {
32+
print_long(n)
33+
print("", terminator: terminator)
34+
}
35+
36+
func print(_ array: [Int]) {
37+
print("[", terminator: "")
38+
for i in 0 ..< array.count {
39+
print_long(array[i])
40+
if i != array.count - 1 { print(", ", terminator: "") }
41+
}
42+
print("]")
43+
}
44+
45+
@_silgen_name("memcmp")
46+
func memcmp(_: UnsafeRawPointer, _: UnsafeRawPointer, _: Int) -> CInt
47+
48+
@_silgen_name("memcpy")
49+
func memcpy(_: UnsafeMutableRawPointer, _: UnsafeRawPointer, _: Int) -> UnsafeRawPointer
50+
51+
func test() {
52+
print("Calling memcmp")
53+
// CHECK: Calling memcmp
54+
55+
// const arrays
56+
print(Int(memcmp([1, 2, 3], [1, 2, 3], MemoryLayout<Int>.size * 3)))
57+
print(Int(memcmp([1, 2, 3], [1, 2, 4], MemoryLayout<Int>.size * 3)))
58+
// CHECK-NEXT: 0
59+
// CHECK-NEXT: 1
60+
61+
let a1 = [1, 2, 3]
62+
let a2 = [1, 2, 4]
63+
print(Int(memcmp(a1, a2, MemoryLayout<Int>.size * 3)))
64+
// CHECK-NEXT: 1
65+
66+
// mutable array
67+
var arr = [1, 2, 3, 4, 5]
68+
var int42 = 42
69+
memcpy(&arr, &int42, MemoryLayout<Int>.size)
70+
print(arr)
71+
// CHECK-NEXT: [42, 2, 3, 4, 5]
72+
}
73+
74+
test()

0 commit comments

Comments
 (0)