chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/psm/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"f2f607fa3fdeeaac287a1d5326535c51029f0251ac41d16e68f994b9a1b0627e","Cargo.lock":"10fba3439499530e3b767884d5b3bd2d136723ff9b62bb6ab9a2e488dced0908","Cargo.toml":"3430680cee566548a6d6b0e301cbbc7804f68d041f244d17a960f78b268ff728","Cargo.toml.orig":"94426ad9e979700145a773cd1a93b75fd123444456029dd099b8d21fe8cf37bc","LICENSE-APACHE":"965a63a81d9a2fbeb5f9096954dabb49690f9dffcdac9825f675b25c807252a2","LICENSE-MIT":"3e3714aa69bd874601741fd7d7ad5298740cece37778e279fc1ab4451c5a11af","README.mkd":"973e82d1604900e47b087c81511d021c68ca296ba9ca92a3211b048482bac502","build.rs":"c9bae07a7bf7a1760798fc4307accd306fcce93a766f399d99978b6a022341d6","examples/info.rs":"8ffb89912304ecbf3d714dcc094f42e86fdd0738625b2e76be2e7d59ab0736cf","examples/on_stack_fibo.rs":"287f0a08b177a97366a5da39e24e33e1f4bbe30a1f2473956721c8a9d93926a4","examples/on_stack_fibo_alloc_each_frame.rs":"e084041bbb81d51b195a4db539a765409272916df29c83a62213a93de4b6fca3","examples/panics.rs":"6791fe0dda9456b3becf989cbc89bc45ae27302e633572a57bbf10a57b830076","examples/replace_stack_1.rs":"374a28881f5e5dbf9db9b9e34929fb7a7e6f3910d782a6718f53ac269807b990","examples/thread.rs":"3cf92882aff96151608584d63535701cc8e5ae953d7ecf706d77371180bff025","src/arch/aarch64_armasm.asm":"1c737338287f3de981fbae97f104ac5e49425ba7fbcb4f7d80120afae47a86d5","src/arch/aarch_aapcs64.s":"2f3cd95021c0c2cc7e69ab3f1e3375c5860c5fa3c9b7be1e95063e7b3c7541af","src/arch/arm64ec_armasm.asm":"3f22a84961e9ee7b632c467a499cc54fb07235d6befd1eab681182b3d2d9974d","src/arch/arm_aapcs.s":"934defb8db2c59e4f5cb7e51d2b70638b0ace9c222a9c966f4de7403dfaf69b7","src/arch/arm_armasm.asm":"e3b514169f19368b0b49374412de38bd9f50576e7b93b64d685a0f84fa8f4c91","src/arch/gnu_stack_note.s":"485ed1b4bcc9e7e3b8d7767b158eb8cc8dfea62081647e7d27c4a796854aced8","src/arch/loongarch64.s":"2e067c55c56b20f333131afed7f382d77adb60fe7aaea523b485a1b8c6e4fdc5","src/arch/mips64_eabi.s":"5c69bec1db1ea56a4da1bd86037c2d1ba7636e48aa5816e0dd0f999613208f7c","src/arch/mips_eabi.s":"d32095fcf9ab26a23a807644f173ef6000359ec8dd1ae6a563ee9b935e299b71","src/arch/powerpc32.s":"9d8ba32e5e1e566e358f5dde9b500df83fe79d1ad05105c483344ebfa95fc071","src/arch/powerpc64.s":"ecb2936e92624c9263c4eaeed221933bb725f84b2e38043a29a99a4647a240ea","src/arch/powerpc64_aix.s":"79af120692de207ea9e78efca92127ed1b522dcac62f6d17ed48f88458203a01","src/arch/powerpc64_openpower.s":"520635f779a997c3d24f2f9979a44171867f9673692bc1de714bb43e35cb07b1","src/arch/psm.h":"2cebda3740aa73b167b8ec18e3d2202ca46e400a081a46329b86051abd1a872a","src/arch/riscv.s":"dd54d95280b91f2936f0dc169a578f91a0a5c154dcef2bca7361183e6f8b5552","src/arch/riscv64.s":"ef1f6534c33391e1bb70b9f72d59d1bf96361adbb4def0f13b32a074eb8a0d44","src/arch/sparc64.s":"1e1db97d06922cecf2fdaa2e420428df9b480e7dcca5c4d442fdbdc752eab19b","src/arch/sparc_sysv.s":"a8843b12b0a56ddbd41220e21cebfeaaf6979ff6a76816250b68c62a9a45629a","src/arch/wasm32.o":"d7279f419cb7e169cae2af2463507652e0393b801c2f4580244de70d3def58b6","src/arch/wasm32.s":"91b4c17cab9185406ca7f8d5ca168581505acc0d302854ad9aad6b3f834f2dff","src/arch/x86.s":"667094ac83138b9c73fb1540bc8e8ce2d938b6809d91c77afbbdb7ba5cedab12","src/arch/x86_64.s":"4c9829c9a77d6660948003f7bdc53a035fdc49644eee3be73cc0a1334aa5142b","src/arch/x86_64_msvc.asm":"85683bc65a03371ea7d8d79dcbe487f690cc2460c359817fc63c30d575ad8957","src/arch/x86_64_windows_gnu.s":"ea2638b4716dd99d56df7b9dd299b7bd991930a53aa6b1d8e9cf08ba6bbff116","src/arch/x86_msvc.asm":"1735d4b19f8e46d0699fc9538baa7ab0885d27531ef7d9960e2027ad8137769b","src/arch/x86_windows_gnu.s":"b94d907a86f230c5c8ca1c708ede173f73c5269496f3959e08e4a92155e160d7","src/arch/zseries_linux.s":"536452bebea51b450fe470a59a5266fa509b948824045025c1f91bffd4681e66","src/lib.rs":"0a9aa69a3b47cf2f572f9fe46f247e5db011e43f8960a3e6695a324ccf32287b","tests/stack_direction.rs":"77d8f9dee196e99e70d569f59fef82bc2f88a8ec17bfe07ebe2f005fcb815c8b","tests/stack_direction_2.rs":"f9191394de5b6381af6ba8223e7717230059dc335f639238c0ddbc7eb87bfc0e"},"package":"3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8"}

6
vendor/psm/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "93c7abc0c82c6c9f811298d0c02c3c132ffdbfa2"
},
"path_in_vcs": "psm"
}

57
vendor/psm/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,57 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ar_archive_writer"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b"
dependencies = [
"object",
]
[[package]]
name = "cc"
version = "1.2.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "memchr"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
]
[[package]]
name = "psm"
version = "0.1.30"
dependencies = [
"ar_archive_writer",
"cc",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"

75
vendor/psm/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,75 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "psm"
version = "0.1.30"
authors = ["Simonas Kazlauskas <psm@kazlauskas.me>"]
build = "build.rs"
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Portable Stack Manipulation: stack manipulation and introspection routines"
documentation = "https://docs.rs/psm/0.1.30"
readme = "README.mkd"
keywords = [
"stack",
"no_std",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/stacker/"
[lib]
name = "psm"
path = "src/lib.rs"
[[example]]
name = "info"
path = "examples/info.rs"
[[example]]
name = "on_stack_fibo"
path = "examples/on_stack_fibo.rs"
[[example]]
name = "on_stack_fibo_alloc_each_frame"
path = "examples/on_stack_fibo_alloc_each_frame.rs"
[[example]]
name = "panics"
path = "examples/panics.rs"
[[example]]
name = "replace_stack_1"
path = "examples/replace_stack_1.rs"
[[example]]
name = "thread"
path = "examples/thread.rs"
[[test]]
name = "stack_direction"
path = "tests/stack_direction.rs"
[[test]]
name = "stack_direction_2"
path = "tests/stack_direction_2.rs"
[dependencies]
[build-dependencies.ar_archive_writer]
version = "0.5.0"
[build-dependencies.cc]
version = "1.2.33"

201
vendor/psm/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

16
vendor/psm/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,16 @@
Copyright © 2018, Simonas Kazlauskas
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

520
vendor/psm/README.mkd vendored Normal file
View File

@@ -0,0 +1,520 @@
# Portable Stack Manipulation
This crate provides very portable functions to control the stack pointer and inspect the properties
of the stack. This crate does not attempt to provide safe abstractions to any operations, the
only goals are correctness, portability and efficiency (in that exact order). As a consequence most
functions youll see in this crate are unsafe.
Unless youre writing a safe abstraction over stack manipulation, this is not the crate you
want. Instead consider one of the safe abstractions over this crate. A good place to look at is
the crates.ios reverse dependency list.
# Platform support
The following table lists supported targets and architectures with notes on the level of current
support and knowledge about the target. The three columns “Available”, “Tested” and “Callstack”
imply an increasingly high level of support.
* “Available” basically means that the code builds and the assembly files have been written for the
target;
* “Tested” means that the assembly code has been tested or otherwise verified to be correct. For
most targets it also means that continuous integration is set up;
* “Callstack” means that the assembly code has been written with due care to support unwinding the
stack and displaying the call frames (i.e. `gdb backtrace` works as expected).
<table>
<tr>
<th rowspan="1" colspan="2">Target</th>
<th colspan="3">Support</th>
</tr>
<tr>
<th rowspan="2">Architecture</th>
<th rowspan="2">OS</th>
<th>Available</th>
<th>Tested</th>
<th>Callstack</th>
</tr>
<tr>
<th colspan="3">Notes</th>
</tr>
<tr>
<td rowspan="6">x86_64</td>
<td rowspan="2">apple-ios</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Target has been tested locally.
</td>
</tr>
<tr>
<td rowspan="2">windows</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes, but disabled</td>
</tr>
<tr>
<td colspan="3">
Stacks allocated the usual way are not valid to be used on Windows and the functions to allocate a
stack in a proper way is a Windows implementation detail. As a (unnecessarily slow and inflexible)
alternative use [Fibers][fibers].
</td>
</tr>
<tr>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td rowspan="8">i686<br>i586<br>i386</td>
<td rowspan="2">apple-ios</td>
<td>Yes</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">linux-android</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
The assembly files are available, but the target hasnt been verified to build
</td>
</tr>
<tr>
<td rowspan="2">windows</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
The code technically works on my local machine, but exception handling does not correctly work on
appveyor, which makes me unwilling to mark this as working yet.
Stacks allocated the usual way are not valid to be used on Windows and the functions to allocate a
stack in a proper way is a Windows implementation detail. As a (unnecessarily slow and inflexible)
alternative use [Fibers][fibers].
</td>
</tr>
<tr>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="8">aarch64</td>
<td rowspan="2">apple-ios</td>
<td>Yes</td>
<td>Unknown</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
aarch64-apple-ios has not been tested. iOS hardware is necessary to run these tests.
</td>
</tr>
<tr>
<td rowspan="2">fuchsia<br>unknown-cloudabi</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">windows</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
Stacks allocated the usual way are not valid to be used on Windows and the functions to allocate a
stack in a proper way is a Windows implementation detail. As a (unnecessarily slow and inflexible)
alternative use [Fibers][fibers].
</td>
</tr>
<tr>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="6">arm<br>armv7</td>
<td rowspan="2">apple-ios</td>
<td>Yes</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
armv7-apple-ios has not been tested. iOS hardware is necessary to run these tests.
</td>
</tr>
<tr>
<td rowspan="2">windows</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
Stacks allocated the usual way are not valid to be used on Windows and the functions to allocate a
stack in a proper way is a Windows implementation detail. As a (unnecessarily slow and inflexible)
alternative use [Fibers][fibers].
</td>
</tr>
<tr>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">armv5te</td>
<td rowspan="2">&#42;</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">thumbv6<br>thumbv7</td>
<td rowspan="2">&#42;</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">mips<br>mipsel</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Only the o32 ABI is supported and will be used for all 32-bit MIPS targets.
</td>
</tr>
<tr>
<td rowspan="2">mips64<br>mips64el</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">powerpc</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Callstack generation may fail at certain well defined ranges of the program, although the usual
compiler-generated code fails at similar points itself.
</td>
</tr>
<tr>
<td rowspan="4">powerpc64</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Callstack generation may fail at certain well defined ranges of the program, although the usual
compiler-generated code fails at similar points itself.
</td>
</tr>
<tr>
<td rowspan="2">AIX</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<tr>
<td colspan="3">
</td>
</tr>
<tr>
<td rowspan="2">powerpc64le</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Callstack generation may fail at certain well defined ranges of the program, although the usual
compiler-generated code fails at similar points itself.
</td>
</tr>
<tr>
<td rowspan="2">s390x</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Locally</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Test runner on CI hangs, local verification has been done on a qemu-system-s390x VM. It may be
possible to add CI testing in the future via qemus full-system emulation.
</td>
</tr>
<tr>
<td rowspan="2">sparc</td>
<td rowspan="2">linux</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
A Rust target for 32-bit SPARC exists, but no Linux distributions actually have a 32-bit SPARC
distribution, so verification is infeasible.
The actual assembly code has been written conservatively, modelled after the 64-bit SPARC code.
and so has a non-zero chance of working.
</td>
</tr>
<tr>
<td rowspan="2">sparc64</td>
<td rowspan="2">linux</td>
<td>Yes</td>
<td>Locally</td>
<td>Yes</td>
</tr>
<tr>
<td colspan="3">
Has been manually verified to work on the [GCC Farm Project] machines. It may be possible to
add CI testing in the future via qemus full-system emulation.
</td>
</tr>
<tr>
<td rowspan="2">sparc9</td>
<td rowspan="2">solaris</td>
<td>Yes</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
Uses the same assembly as the sparc64-linux-gnu target. This target has no rustc builds and
therefore the correct operation of this target could not be verified at the moment.
</td>
</tr>
<tr>
<td rowspan="2">wasm</td>
<td rowspan="2">&#42;</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
This library is not applicable to the target. WASM hasnt a specified C ABI, the callstack is
not even in an address space and does not appear to be manipulatable.
</td>
</tr>
<tr>
<td rowspan="2">asmjs</td>
<td rowspan="2">&#42;</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
Feasibility/necessity hasnt been acertained.
</td>
</tr>
<tr>
<td rowspan="2">nvptx</td>
<td rowspan="2">&#42;</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
Feasibility/necessity hasnt been acertained.
</td>
</tr>
<tr>
<td rowspan="2">msp430</td>
<td rowspan="2">&#42;</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td colspan="3">
Havent gotten to it yet...
</td>
</tr>
<tr>
<td rowspan="2">riscv32</td>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>No</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
Although the assembly code has not been tested, it is a straightforward copy of the 64-bit version.
Unless there is a non-obvious mistake, this should work fine.
</td>
</tr>
<tr>
<td rowspan="2">riscv64</td>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Locally</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
The assembly code for riscv64 has been tested locally with a C caller.
</td>
</tr>
<tr>
<td rowspan="2">loongarch64</td>
<td rowspan="2">&#42;</td>
<td>Yes</td>
<td>Locally</td>
<td>Unknown</td>
</tr>
<tr>
<td colspan="3">
The assembly code for loongarch64 has been tested locally with a C caller.
</td>
</tr>
</table>
[GCC Farm Project]: https://cfarm.tetaneutral.net/
[fibers]: https://docs.microsoft.com/en-gb/windows/desktop/ProcThread/fibers
# License
PSM is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
https://opensource.org/licenses/MIT)
at your option.

190
vendor/psm/build.rs vendored Normal file
View File

@@ -0,0 +1,190 @@
fn find_assembly(
arch: &str,
endian: &str,
os: &str,
env: &str,
masm: bool,
) -> Option<(&'static str, bool)> {
match (arch, endian, os, env) {
// The implementations for stack switching exist, but, officially, doing so without Fibers
// is not supported in Windows. For x86_64 the implementation actually works locally,
// but failed tests in CI (???). Might want to have a feature for experimental support
// here.
("x86", _, "windows", _) => {
if masm {
Some(("src/arch/x86_msvc.asm", false))
} else {
Some(("src/arch/x86_windows_gnu.s", false))
}
}
("x86_64", _, "windows", _) => {
if masm {
Some(("src/arch/x86_64_msvc.asm", false))
} else {
Some(("src/arch/x86_64_windows_gnu.s", false))
}
}
("x86_64", _, "cygwin", _) => Some(("src/arch/x86_64_windows_gnu.s", false)),
("arm", _, "windows", "msvc") => Some(("src/arch/arm_armasm.asm", false)),
("arm64ec", _, "windows", "msvc") => Some(("src/arch/arm64ec_armasm.asm", false)),
("aarch64", _, "windows", _) => {
if masm {
Some(("src/arch/aarch64_armasm.asm", false))
} else {
Some(("src/arch/aarch_aapcs64.s", false))
}
}
("x86", _, _, _) => Some(("src/arch/x86.s", true)),
("x86_64", _, _, _) => Some(("src/arch/x86_64.s", true)),
("arm", _, _, _) => Some(("src/arch/arm_aapcs.s", true)),
("aarch64", _, _, _) => Some(("src/arch/aarch_aapcs64.s", true)),
("powerpc", _, _, _) => Some(("src/arch/powerpc32.s", true)),
("powerpc64", _, _, "musl") => Some(("src/arch/powerpc64_openpower.s", true)),
("powerpc64", "little", _, _) => Some(("src/arch/powerpc64_openpower.s", true)),
("powerpc64", _, "aix", _) => Some(("src/arch/powerpc64_aix.s", true)),
("powerpc64", _, _, _) => Some(("src/arch/powerpc64.s", true)),
("s390x", _, _, _) => Some(("src/arch/zseries_linux.s", true)),
("mips", _, _, _) => Some(("src/arch/mips_eabi.s", true)),
("mips64", _, _, _) => Some(("src/arch/mips64_eabi.s", true)),
("sparc64", _, _, _) => Some(("src/arch/sparc64.s", true)),
("sparc", _, _, _) => Some(("src/arch/sparc_sysv.s", true)),
("riscv32", _, _, _) => Some(("src/arch/riscv.s", true)),
("riscv64", _, _, _) => Some(("src/arch/riscv64.s", true)),
("wasm32", _, _, _) => Some(("src/arch/wasm32.o", true)),
("loongarch64", _, _, _) => Some(("src/arch/loongarch64.s", true)),
_ => None,
}
}
fn main() {
use std::env::var;
println!("cargo:rustc-check-cfg=cfg(switchable_stack,asm,link_asm)");
if var("CARGO_CFG_MIRI").is_ok() {
// Miri doesn't have a stack limit and the inline asm wouldn't work on miri anyway.
return;
}
let arch = var("CARGO_CFG_TARGET_ARCH").unwrap();
let env = var("CARGO_CFG_TARGET_ENV").unwrap();
let os = var("CARGO_CFG_TARGET_OS").unwrap();
let endian = var("CARGO_CFG_TARGET_ENDIAN").unwrap();
let mut cfg = cc::Build::new();
let msvc = cfg.get_compiler().is_like_msvc();
// If we're targeting msvc, either via regular MS toolchain or clang-cl, we
// will _usually_ want to use the regular Microsoft assembler if it exists,
// which is done for us within cc, however it _probably_ won't exist if
// we're in a cross-compilation context pm a platform that can't natively
// run Windows executables, so in that case we instead use the the equivalent
// GAS assembly file instead. This logic can be removed once LLVM natively
// supports compiling MASM, but that is not stable yet
let masm = msvc && var("HOST").expect("HOST env not set").contains("windows");
let asm = if let Some((asm, canswitch)) = find_assembly(&arch, &endian, &os, &env, masm) {
println!("cargo:rustc-cfg=asm");
println!("cargo:rustc-cfg=link_asm");
if canswitch {
println!("cargo:rustc-cfg=switchable_stack")
}
asm
} else {
println!(
"cargo:warning=Target {}-{}-{} has no assembly files!",
arch, os, env
);
return;
};
if !msvc {
cfg.flag("-xassembler-with-cpp");
cfg.define(&*format!("CFG_TARGET_OS_{}", os), None);
cfg.define(&*format!("CFG_TARGET_ARCH_{}", arch), None);
cfg.define(&*format!("CFG_TARGET_ENV_{}", env), None);
}
// For wasm targets we ship a precompiled `*.o` file so we just pass that
// directly to `ar` to assemble an archive. Otherwise we're actually
// compiling the source assembly file.
if asm.ends_with(".o") {
use ar_archive_writer::{
write_archive_to_stream, ArchiveKind, NewArchiveMember, ObjectReader,
};
use std::fs::{metadata, read};
use std::io::Cursor;
use std::path::PathBuf;
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set");
let output_path = PathBuf::from(&out_dir).join("libpsm_s.a");
let object_data = read(asm).expect("Failed to read object file");
let file_metadata = metadata(asm).expect("Failed to read file metadata");
// Extract file metadata
let mtime = file_metadata
.modified()
.ok()
.and_then(|time| time.duration_since(std::time::UNIX_EPOCH).ok())
.map(|duration| duration.as_secs())
.unwrap_or(0);
#[cfg(unix)]
let (uid, gid, perms) = {
use std::os::unix::fs::MetadataExt;
(
file_metadata.uid(),
file_metadata.gid(),
file_metadata.mode(),
)
};
#[cfg(not(unix))]
let (uid, gid, perms) = (0, 0, 0o644);
let filename = asm.rsplit('/').next().unwrap_or(asm);
let member = NewArchiveMember {
buf: Box::new(object_data),
object_reader:
&ObjectReader {
get_symbols: |_data: &[u8],
_callback: &mut dyn FnMut(
&[u8],
)
-> Result<(), std::io::Error>| Ok(true),
get_xcoff_member_alignment: |_data| 0,
is_64_bit_object_file: |_data| false,
is_any_arm64_coff: |_data| false,
is_ec_object_file: |_data| false,
},
member_name: filename.to_string(),
mtime,
uid,
gid,
perms,
};
let mut output_bytes = Cursor::new(Vec::new());
write_archive_to_stream(
&mut output_bytes,
&[member],
// Unfortunately, getDefaultKind() is not available in ar_archive_writer
// however looking at the llvm-ar source it looks like for wasm32-any-any
// it falls through to Gnu https://llvm.org/doxygen/Object_2Archive_8cpp_source.html
ArchiveKind::Gnu,
false,
None,
)
.expect("Failed to write archive");
std::fs::write(&output_path, output_bytes.into_inner())
.expect("Failed to write archive file");
println!("cargo:rustc-link-search=native={}", out_dir);
println!("cargo:rustc-link-lib=static=psm_s");
} else {
cfg.file(asm);
cfg.compile("libpsm_s.a");
}
}

20
vendor/psm/examples/info.rs vendored Normal file
View File

@@ -0,0 +1,20 @@
extern crate psm;
psm::psm_stack_information! {
yes {
fn main() {
println!("Stack is {:?} and is at {:p} currently",
psm::StackDirection::new(), psm::stack_pointer());
}
}
no {
fn main() {
eprintln!("Stack information not supported by this target");
}
}
}
#[test]
fn run_example() {
main();
}

77
vendor/psm/examples/on_stack_fibo.rs vendored Normal file
View File

@@ -0,0 +1,77 @@
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
#[inline(never)]
fn fib(n: usize, stack_limit: *mut u8) -> Option<u64> {
// match psm::StackDirection::new() {
// psm::StackDirection::Ascending => if psm::stack_pointer() > stack_limit {
// return None;
// }
// psm::StackDirection::Descending => if psm::stack_pointer() < stack_limit {
// return None;
// }
// }
match n {
0 => Some(0),
1 => Some(1),
_ => fib(n - 1, stack_limit).and_then(|x| fib(n - 2, stack_limit).map(|y| x + y)),
}
}
const STACK_ALIGN: usize = 4096;
const STACK_REDLINE: usize = 512;
const FIB_COUNTS: [(usize, u64); 3] = [
(8, 21),
(16, 987),
(32, 2178309),
];
fn main() {
let mut stack_size = 1024 * 128;
unsafe {
for &(n, expected) in FIB_COUNTS.iter() {
loop {
println!("fib({}) with {} bytes of stack", n, stack_size - STACK_REDLINE);
let layout = alloc::Layout::from_size_align(stack_size, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let max_stack = match psm::StackDirection::new() {
psm::StackDirection::Ascending =>
new_stack.offset((stack_size - STACK_REDLINE) as isize),
psm::StackDirection::Descending =>
new_stack.offset(STACK_REDLINE as isize),
};
let result = psm::on_stack(new_stack, stack_size, || {
fib(n, max_stack)
});
alloc::dealloc(new_stack, layout);
if let Some(res) = result {
assert_eq!(res, expected);
println!("fib({}) = {}", n, res);
break;
} else {
println!("Stack not large enough!");
stack_size *= 2;
}
}
}
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
main()
}

View File

@@ -0,0 +1,53 @@
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
const STACK_ALIGN: usize = 4096;
const FRAME_SIZE: usize = 4096;
const FIB_COUNTS: [(usize, u64); 3] = [
(8, 21),
(16, 987),
(24, 46368),
];
#[inline(never)]
fn fib(n: usize) -> u64 {
unsafe {
let layout = alloc::Layout::from_size_align(FRAME_SIZE, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let r = match n {
0 => 0,
1 => 1,
_ => {
psm::on_stack(new_stack, FRAME_SIZE, || {
fib(n - 1) + fib(n - 2)
})
}
};
alloc::dealloc(new_stack, layout);
r
}
}
fn main() {
for &(n, expected) in FIB_COUNTS.iter() {
let res = fib(n);
assert_eq!(res, expected);
println!("fib({}) = {}", n, res);
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
main()
}

52
vendor/psm/examples/panics.rs vendored Normal file
View File

@@ -0,0 +1,52 @@
extern crate psm;
use std::panic;
const CHAIN_DEPTH: usize = 16;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
const STACK_ALIGN: usize = 4096;
// Generating backraces (because of RUST_BACKTRACE) create a few quite large frames, so it is
// important, that all frames have sufficient amount of available memory to not run over the
// stack...
const FRAME_SIZE: usize = 4096 * 10;
fn panic_chain(depth: usize) {
if depth == 0 {
panic!("full chain!");
} else {
unsafe {
let layout = alloc::Layout::from_size_align(FRAME_SIZE, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let p = psm::on_stack(new_stack, FRAME_SIZE, || {
panic::catch_unwind(|| {
panic_chain(depth - 1);
})
});
alloc::dealloc(new_stack, layout);
p.map_err(panic::resume_unwind).unwrap()
}
}
}
fn main() {
panic_chain(CHAIN_DEPTH);
}
#[test]
fn run_example() {
assert!(panic::catch_unwind(|| {
panic_chain(CHAIN_DEPTH);
}).is_err(), "Panic did not propagate!");
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}

33
vendor/psm/examples/replace_stack_1.rs vendored Normal file
View File

@@ -0,0 +1,33 @@
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
const STACK_SIZE: usize = 4096 * 64;
const STACK_ALIGN: usize = 4096;
fn main() {
println!("current stack pointer is {:p}", psm::stack_pointer());
unsafe {
let new_stack = alloc::alloc(alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGN).unwrap());
println!("new stack is between {:p} and {:p}", new_stack, new_stack.offset(STACK_SIZE as isize));
psm::replace_stack(new_stack, STACK_SIZE, || {
println!("after replacement stack pointer is {:p}", psm::stack_pointer());
::std::process::exit(0);
});
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
// NOTE: intentionally out-of-processes, as the example exits with `process::exit(0)`.
main()
}

60
vendor/psm/examples/thread.rs vendored Normal file
View File

@@ -0,0 +1,60 @@
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
const STACK_ALIGN: usize = 4096;
const FRAME_SIZE: usize = 4096;
const FIB_COUNTS: [(usize, u64); 3] = [
(8, 21),
(16, 987),
(24, 46368),
];
#[inline(never)]
fn fib(n: usize) -> u64 {
unsafe {
let layout = alloc::Layout::from_size_align(FRAME_SIZE, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let r = match n {
0 => 0,
1 => 1,
_ => {
psm::on_stack(new_stack, FRAME_SIZE, || {
fib(n - 1) + fib(n - 2)
})
}
};
alloc::dealloc(new_stack, layout);
r
}
}
fn main() {
for (n, expected, handle) in FIB_COUNTS.iter().map(|&(n, expected)|
(n, expected, std::thread::spawn(move || {
fib(n)
}))
) {
if let Ok(res) = handle.join() {
assert_eq!(res, expected);
println!("fib({}) = {}", n, res);
} else {
panic!("joining a thread returned an Err");
}
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
main()
}

38
vendor/psm/src/arch/aarch64_armasm.asm vendored Normal file
View File

@@ -0,0 +1,38 @@
AREA |.text|, CODE, READONLY
GLOBAL |rust_psm_stack_direction|
ALIGN 4
|rust_psm_stack_direction| PROC
orr w0, wzr, #2
ret
ENDP
GLOBAL |rust_psm_stack_pointer|
ALIGN 4
|rust_psm_stack_pointer| PROC
mov x0, sp
ret
ENDP
GLOBAL |rust_psm_replace_stack|
ALIGN 4
|rust_psm_replace_stack| PROC
mov sp, x2
br x1
ENDP
GLOBAL |rust_psm_on_stack|
ALIGN 4
|rust_psm_on_stack| PROC
stp x29, x30, [sp, #-16]!
mov x29, sp
mov sp, x3
blr x2
mov sp, x29
ldp x29, x30, [sp], #16
ret
ENDP
END

89
vendor/psm/src/arch/aarch_aapcs64.s vendored Normal file
View File

@@ -0,0 +1,89 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
#if defined(CFG_TARGET_OS_darwin) || defined(CFG_TARGET_OS_macos) || defined(CFG_TARGET_OS_ios)
#define GLOBL(fnname) .globl _##fnname
#define TYPE(fnname)
#define FUNCTION(fnname) _##fnname
#define END_FUNCTION(fnname)
#elif defined(CFG_TARGET_OS_windows)
#define GLOBL(fnname) .globl fnname
#define TYPE(fnname)
#define FUNCTION(fnname) fnname
#define END_FUNCTION(fnname)
#else
#define GLOBL(fnname) .globl fnname
#define TYPE(fnname) .type fnname,@function
#define FUNCTION(fnname) fnname
#define END_FUNCTION(fnname) .size fnname,.-fnname
#endif
GLOBL(rust_psm_stack_direction)
.p2align 2
TYPE(rust_psm_stack_direction)
FUNCTION(rust_psm_stack_direction):
/* extern "C" fn() -> u8 */
.cfi_startproc
orr w0, wzr, #STACK_DIRECTION_DESCENDING
ret
END_FUNCTION(rust_psm_stack_direction)
.cfi_endproc
GLOBL(rust_psm_stack_pointer)
.p2align 2
TYPE(rust_psm_stack_pointer)
FUNCTION(rust_psm_stack_pointer):
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
mov x0, sp
ret
END_FUNCTION(rust_psm_stack_pointer)
.cfi_endproc
GLOBL(rust_psm_replace_stack)
.p2align 2
TYPE(rust_psm_replace_stack)
FUNCTION(rust_psm_replace_stack):
/* extern "C" fn(r0: usize, r1: extern "C" fn(usize), r2: *mut u8) */
.cfi_startproc
/* All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi */
mov sp, x2
br x1
END_FUNCTION(rust_psm_replace_stack)
.cfi_endproc
GLOBL(rust_psm_on_stack)
.p2align 2
TYPE(rust_psm_on_stack)
FUNCTION(rust_psm_on_stack):
/* extern "C" fn(r0: usize, r1: usize, r2: extern "C" fn(usize, usize), r3: *mut u8) */
.cfi_startproc
stp x29, x30, [sp, #-16]!
.cfi_def_cfa sp, 16
mov x29, sp
.cfi_def_cfa x29, 16
.cfi_offset x29, -16
.cfi_offset x30, -8
mov sp, x3
blr x2
mov sp, x29
.cfi_def_cfa sp, 16
ldp x29, x30, [sp], #16
.cfi_def_cfa sp, 0
.cfi_restore x29
.cfi_restore x30
ret
END_FUNCTION(rust_psm_on_stack)
.cfi_endproc

38
vendor/psm/src/arch/arm64ec_armasm.asm vendored Normal file
View File

@@ -0,0 +1,38 @@
AREA |.text|, CODE, READONLY
GLOBAL |#rust_psm_stack_direction|
ALIGN 4
|#rust_psm_stack_direction| PROC
orr w0, wzr, #2
ret
ENDP
GLOBAL |#rust_psm_stack_pointer|
ALIGN 4
|#rust_psm_stack_pointer| PROC
mov x0, sp
ret
ENDP
GLOBAL |#rust_psm_replace_stack|
ALIGN 4
|#rust_psm_replace_stack| PROC
mov sp, x2
br x1
ENDP
GLOBAL |#rust_psm_on_stack|
ALIGN 4
|#rust_psm_on_stack| PROC
stp x29, x30, [sp, #-16]!
mov x29, sp
mov sp, x3
blr x2
mov sp, x29
ldp x29, x30, [sp], #16
ret
ENDP
END

107
vendor/psm/src/arch/arm_aapcs.s vendored Normal file
View File

@@ -0,0 +1,107 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
.syntax unified
#if defined(CFG_TARGET_OS_darwin) || defined(CFG_TARGET_OS_macos) || defined(CFG_TARGET_OS_ios)
#define GLOBL(fnname) .globl _##fnname
#define THUMBTYPE(fnname) .thumb_func _##fnname
#define FUNCTION(fnname) _##fnname
#define THUMBFN .code 16
#define SIZE(fnname,endlabel)
#define FNSTART
#define CANTUNWIND
#define FNEND
#else
#define GLOBL(fnname) .globl fnname
#define THUMBTYPE(fnname) .type fnname,%function
#define FUNCTION(fnname) fnname
#define THUMBFN .code 16
#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname
#define FNSTART .fnstart
#define CANTUNWIND .cantunwind
#define FNEND .fnend
#endif
GLOBL(rust_psm_stack_direction)
.p2align 2
THUMBTYPE(rust_psm_stack_direction)
THUMBFN
FUNCTION(rust_psm_stack_direction):
/* extern "C" fn() -> u8 */
FNSTART
.cfi_startproc
/* movs to support Thumb-1 */
movs r0, #STACK_DIRECTION_DESCENDING
bx lr
.rust_psm_stack_direction_end:
SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end)
.cfi_endproc
CANTUNWIND
FNEND
GLOBL(rust_psm_stack_pointer)
.p2align 2
THUMBTYPE(rust_psm_stack_pointer)
THUMBFN
FUNCTION(rust_psm_stack_pointer):
/* extern "C" fn() -> *mut u8 */
FNSTART
.cfi_startproc
mov r0, sp
bx lr
.rust_psm_stack_pointer_end:
SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end)
.cfi_endproc
CANTUNWIND
FNEND
GLOBL(rust_psm_replace_stack)
.p2align 2
THUMBTYPE(rust_psm_replace_stack)
THUMBFN
FUNCTION(rust_psm_replace_stack):
/* extern "C" fn(r0: usize, r1: extern "C" fn(usize), r2: *mut u8) */
FNSTART
.cfi_startproc
/* All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi */
mov sp, r2
bx r1
.rust_psm_replace_stack_end:
SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end)
.cfi_endproc
CANTUNWIND
FNEND
GLOBL(rust_psm_on_stack)
.p2align 2
THUMBTYPE(rust_psm_on_stack)
THUMBFN
FUNCTION(rust_psm_on_stack):
/* extern "C" fn(r0: usize, r1: usize, r2: extern "C" fn(usize, usize), r3: *mut u8) */
FNSTART
.cfi_startproc
push {r4, lr}
.cfi_def_cfa_offset 8
mov r4, sp
.cfi_def_cfa_register r4
.cfi_offset lr, -4
.cfi_offset r4, -8
mov sp, r3
blx r2
mov sp, r4
.cfi_restore sp
pop {r4, pc}
.rust_psm_on_stack_end:
SIZE(rust_psm_on_stack,.rust_psm_on_stack_end)
.cfi_endproc
CANTUNWIND
FNEND

39
vendor/psm/src/arch/arm_armasm.asm vendored Normal file
View File

@@ -0,0 +1,39 @@
THUMB
AREA |.text|, CODE, READONLY
GLOBAL |rust_psm_stack_direction|
ALIGN 4
|rust_psm_stack_direction| PROC
movs r0, #2
bx lr
ENDP
GLOBAL |rust_psm_stack_pointer|
ALIGN 4
|rust_psm_stack_pointer| PROC
mov r0, sp
bx lr
ENDP
GLOBAL |rust_psm_replace_stack|
ALIGN 4
|rust_psm_replace_stack| PROC
mov sp, r2
bx r1
ENDP
GLOBAL |rust_psm_on_stack|
ALIGN 4
|rust_psm_on_stack| PROC
push {r4, lr}
mov r4, sp
mov sp, r3
blx r2
mov sp, r4
pop {r4, pc}
ENDP
END

3
vendor/psm/src/arch/gnu_stack_note.s vendored Normal file
View File

@@ -0,0 +1,3 @@
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

64
vendor/psm/src/arch/loongarch64.s vendored Normal file
View File

@@ -0,0 +1,64 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li.w $r4, STACK_DIRECTION_DESCENDING
jr $r1
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
move $r4, $r3
jr $r1
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */
.cfi_startproc
move $r3, $r6
jr $r5
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(r4: usize, r5: usize, r6: extern "C" fn(usize, usize), r7: *mut u8) */
.cfi_startproc
st.d $r1, $r7, -8
st.d $r3, $r7, -16
addi.d $r3, $r7, -16
.cfi_def_cfa 3, 16
.cfi_offset 1, -8
.cfi_offset 3, -16
jirl $r1, $r6, 0
ld.d $r1, $r3, 8
.cfi_restore 1
ld.d $r3, $r3, 0
.cfi_restore 3
jr $r1
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

88
vendor/psm/src/arch/mips64_eabi.s vendored Normal file
View File

@@ -0,0 +1,88 @@
/*
Not only MIPS has 20 different ABIs... nobody tells anybody what specific variant of which ABI is
used where.
This is an "EABI" implementation based on the following page:
http://www.cygwin.com/ml/binutils/2003-06/msg00436.html
*/
#include "psm.h"
#include "gnu_stack_note.s"
.set noreorder /* well manage the delay slots on our own, thanks! */
.text
.globl rust_psm_stack_direction
.p2align 3
.type rust_psm_stack_direction,@function
.ent rust_psm_stack_direction
/* extern "C" fn() -> u8 */
rust_psm_stack_direction:
.cfi_startproc
jr $31
addiu $2, $zero, STACK_DIRECTION_DESCENDING
.end rust_psm_stack_direction
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 3
.type rust_psm_stack_pointer,@function
.ent rust_psm_stack_pointer
/* extern "C" fn() -> *mut u8 */
rust_psm_stack_pointer:
.cfi_startproc
jr $31
move $2, $29
.end rust_psm_stack_pointer
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 3
.type rust_psm_replace_stack,@function
.ent rust_psm_replace_stack
/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */
rust_psm_replace_stack:
.cfi_startproc
move $25, $5
jr $5
move $29, $6
.end rust_psm_replace_stack
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 3
.type rust_psm_on_stack,@function
.ent rust_psm_on_stack
/* extern "C" fn(r4: usize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */
rust_psm_on_stack:
.cfi_startproc
sd $29, -8($7)
sd $31, -16($7)
.cfi_def_cfa 7, 0
.cfi_offset 31, -16
.cfi_offset 29, -8
move $25, $6
jalr $31, $6
daddiu $29, $7, -16
.cfi_def_cfa 29, 16
ld $31, 0($29)
.cfi_restore 31
ld $29, 8($29)
.cfi_restore 29
jr $31
nop
.end rust_psm_on_stack
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

89
vendor/psm/src/arch/mips_eabi.s vendored Normal file
View File

@@ -0,0 +1,89 @@
/*
Not only MIPS has 20 different ABIs... nobody tells anybody what specific variant of which ABI is
used where.
This is an "EABI" implementation based on the following page:
http://www.cygwin.com/ml/binutils/2003-06/msg00436.html
*/
#include "psm.h"
#include "gnu_stack_note.s"
.set noreorder /* well manage the delay slots on our own, thanks! */
.text
.abicalls
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
.ent rust_psm_stack_direction
/* extern "C" fn() -> u8 */
rust_psm_stack_direction:
.cfi_startproc
jr $31
addiu $2, $zero, STACK_DIRECTION_DESCENDING
.end rust_psm_stack_direction
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
.ent rust_psm_stack_pointer
/* extern "C" fn() -> *mut u8 */
rust_psm_stack_pointer:
.cfi_startproc
jr $31
move $2, $29
.end rust_psm_stack_pointer
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
.ent rust_psm_replace_stack
/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */
rust_psm_replace_stack:
.cfi_startproc
move $25, $5
jr $5
move $29, $6
.end rust_psm_replace_stack
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
.ent rust_psm_on_stack
/* extern "C" fn(r4: usize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */
rust_psm_on_stack:
.cfi_startproc
sw $29, -4($7)
sw $31, -8($7)
.cfi_def_cfa 7, 0
.cfi_offset 31, -8
.cfi_offset 29, -4
move $25, $6
jalr $31, $6
addiu $29, $7, -8
.cfi_def_cfa 29, 8
lw $31, 0($29)
.cfi_restore 31
lw $29, 4($29)
.cfi_restore 29
jr $31
nop
.end rust_psm_on_stack
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

77
vendor/psm/src/arch/powerpc32.s vendored Normal file
View File

@@ -0,0 +1,77 @@
#include "psm.h"
#include "gnu_stack_note.s"
/* FIXME: this probably does not cover all ABIs? Tested with sysv only, possibly works for AIX as
well?
*/
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li 3, STACK_DIRECTION_DESCENDING
blr
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
mr 3, 1
blr
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */
.cfi_startproc
/* NOTE: perhaps add a debug-assertion for stack alignment? */
addi 5, 5, -16
mr 1, 5
mtctr 4
bctr
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */
.cfi_startproc
mflr 0
stw 0, -24(6)
sub 6, 6, 1
addi 6, 6, -32
stwux 1, 1, 6
.cfi_def_cfa r1, 32
.cfi_offset r1, -32
.cfi_offset lr, -24
mtctr 5
bctrl
lwz 0, 8(1)
mtlr 0
.cfi_restore lr
/* FIXME: after this instruction backtrace breaks until control returns to the caller
That being said compiler-generated code has the same issue, so I guess that is fine for now?
*/
lwz 1, 0(1)
.cfi_restore r1
blr
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

91
vendor/psm/src/arch/powerpc64.s vendored Normal file
View File

@@ -0,0 +1,91 @@
/* Implementation of the AIX-like PowerPC ABI. Seems to be used by the big-endian PowerPC targets.
The following references were used during the implementation of this code:
https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.alangref/idalangref_rntime_stack.htm
https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.alangref/idalangref_reg_use_conv.htm
https://www.ibm.com/developerworks/library/l-powasm4/index.html
*/
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li 3, STACK_DIRECTION_DESCENDING
blr
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
mr 3, 1
blr
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */
.cfi_startproc
ld 2, 8(4)
ld 4, 0(4)
/* do not allocate the whole 112-byte sized frame, we know wont be used */
addi 5, 5, -48
mr 1, 5
mtctr 4
bctr
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */
.cfi_startproc
mflr 0
std 2, -72(6)
std 0, -8(6)
sub 6, 6, 1
addi 6, 6, -112
stdux 1, 1, 6
.cfi_def_cfa r1, 112
.cfi_offset r1, -112
.cfi_offset r2, -72
.cfi_offset lr, -8
/* load the function pointer from TOC and make the call */
ld 2, 8(5)
ld 5, 0(5)
mtctr 5
bctrl
ld 2, 40(1)
.cfi_restore r2
ld 0, 104(1)
mtlr 0
.cfi_restore lr
/* FIXME: after this instruction backtrace breaks until control returns to the caller.
That being said compiler-generated code has the same issue, so I guess that is fine for now?
*/
ld 1, 0(1)
.cfi_restore r1
blr
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

137
vendor/psm/src/arch/powerpc64_aix.s vendored Normal file
View File

@@ -0,0 +1,137 @@
.csect .text[PR],2
.file "powerpc64_aix.s"
.globl rust_psm_stack_direction[DS]
.globl .rust_psm_stack_direction
.align 4
.csect rust_psm_stack_direction[DS],3
.vbyte 8, .rust_psm_stack_direction
.vbyte 8, TOC[TC0]
.vbyte 8, 0
.csect .text[PR],2
.rust_psm_stack_direction:
# extern "C" fn() -> u8
li 3, 2
blr
L..rust_psm_stack_direction_end:
# Following bytes form the traceback table on AIX.
# For specification, see https://www.ibm.com/docs/en/aix/7.2?topic=processor-traceback-tables.
# For implementation, see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp,
# `PPCAIXAsmPrinter::emitTracebackTable`.
.vbyte 4, 0x00000000 # Traceback table begin, for unwinder to search the table.
.byte 0x00 # Version = 0
.byte 0x09 # Language = CPlusPlus, since rust is using C++-like LSDA.
.byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue
# +HasTraceBackTableOffset, -IsInternalProcedure
# -HasControlledStorage, -IsTOCless
# -IsFloatingPointPresent
# -IsFloatingPointOperationLogOrAbortEnabled
.byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed
# OnConditionDirective = 0, -IsCRSaved, -IsLRSaved
.byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0
.byte 0x00 # -HasExtensionTable, -HasVectorInfo, NumOfGPRsSaved = 0
.byte 0x00 # NumberOfFixedParms = 0
.byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack
.vbyte 4, L..rust_psm_stack_direction_end-.rust_psm_stack_direction #Function size
.vbyte 2, 0x0018 # Function name len = 24
.byte "rust_psm_stack_direction" # Function Name
.globl rust_psm_stack_pointer[DS]
.globl .rust_psm_stack_pointer
.align 4
.csect rust_psm_stack_pointer[DS],3
.vbyte 8, .rust_psm_stack_pointer
.vbyte 8, TOC[TC0]
.vbyte 8, 0
.csect .text[PR],2
.rust_psm_stack_pointer:
# extern "C" fn() -> *mut u8
mr 3, 1
blr
L..rust_psm_stack_pointer_end:
.vbyte 4, 0x00000000
.byte 0x00
.byte 0x09
.byte 0x20
.byte 0x40
.byte 0x80
.byte 0x00
.byte 0x00
.byte 0x01
.vbyte 4, L..rust_psm_stack_pointer_end-.rust_psm_stack_pointer
.vbyte 2, 0x0016
.byte "rust_psm_stack_pointer"
.globl rust_psm_replace_stack[DS]
.globl .rust_psm_replace_stack
.align 4
.csect rust_psm_replace_stack[DS],3
.vbyte 8, .rust_psm_replace_stack
.vbyte 8, TOC[TC0]
.vbyte 8, 0
.csect .text[PR],2
.rust_psm_replace_stack:
# extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8)
# Load the function pointer and toc pointer from TOC and make the call.
ld 2, 8(4)
ld 4, 0(4)
addi 5, 5, -48
mr 1, 5
mtctr 4
bctr
L..rust_psm_replace_stack_end:
.vbyte 4, 0x00000000
.byte 0x00
.byte 0x09
.byte 0x20
.byte 0x40
.byte 0x80
.byte 0x00
.byte 0x03
.byte 0x01
.vbyte 4, 0x00000000 # Parameter type = i, i, i
.vbyte 4, L..rust_psm_replace_stack_end-.rust_psm_replace_stack
.vbyte 2, 0x0016
.byte "rust_psm_replace_stack"
.globl rust_psm_on_stack[DS]
.globl .rust_psm_on_stack
.align 4
.csect rust_psm_on_stack[DS],3
.vbyte 8, .rust_psm_on_stack
.vbyte 8, TOC[TC0]
.vbyte 8, 0
.csect .text[PR],2
.rust_psm_on_stack:
# extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8)
mflr 0
std 2, -72(6)
std 0, -8(6)
sub 6, 6, 1
addi 6, 6, -112
stdux 1, 1, 6
ld 2, 8(5)
ld 5, 0(5)
mtctr 5
bctrl
ld 2, 40(1)
ld 0, 104(1)
mtlr 0
ld 1, 0(1)
blr
L..rust_psm_on_stack_end:
.vbyte 4, 0x00000000
.byte 0x00
.byte 0x09
.byte 0x20
.byte 0x41
.byte 0x80
.byte 0x00
.byte 0x04
.byte 0x01
.vbyte 4, 0x00000000 # Parameter type = i, i, i, i
.vbyte 4, L..rust_psm_on_stack_end-.rust_psm_on_stack
.vbyte 2, 0x0011
.byte "rust_psm_on_stack"
.toc

View File

@@ -0,0 +1,87 @@
/* Implementation of stack swtiching routines for OpenPOWER 64-bit ELF ABI
The specification can be found at
http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/ch_preface.html
This ABI is usually used by the ppc64le targets.
*/
#include "psm.h"
#include "gnu_stack_note.s"
.text
.abiversion 2
.globl rust_psm_stack_direction
.p2align 4
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li 3, STACK_DIRECTION_DESCENDING
blr
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 4
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
mr 3, 1
blr
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 4
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */
.cfi_startproc
addi 5, 5, -32
mtctr 4
mr 12, 4
mr 1, 5
bctr
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 4
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */
.cfi_startproc
mflr 0
std 0, -8(6)
std 2, -24(6)
sub 6, 6, 1
addi 6, 6, -48
stdux 1, 1, 6
.cfi_def_cfa r1, 48
.cfi_offset r1, -48
.cfi_offset r2, -24
.cfi_offset lr, -8
mr 12, 5
mtctr 5
bctrl
ld 2, 24(1)
.cfi_restore r2
ld 0, 40(1)
mtlr 0
.cfi_restore lr
/* FIXME: after this instructin backtrace breaks until control returns to the caller */
ld 1, 0(1)
blr
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

10
vendor/psm/src/arch/psm.h vendored Normal file
View File

@@ -0,0 +1,10 @@
#define STACK_DIRECTION_ASCENDING 1
#define STACK_DIRECTION_DESCENDING 2
/*
Various defines for values produced by `-DCFG_TARGET_*` flags. Only needs to be mutually unique
*/
#define darwin 1
#define macos 2
#define ios 3

64
vendor/psm/src/arch/riscv.s vendored Normal file
View File

@@ -0,0 +1,64 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li x10, STACK_DIRECTION_DESCENDING
jr x1
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
add x10, x2, x0
jr x1
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(x10: usize, x11: extern "C" fn(usize), x12: *mut u8) */
.cfi_startproc
add x2, x12, x0
jr x11
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(x10: usize, x11: usize, x12: extern "C" fn(usize, usize), x13: *mut u8) */
.cfi_startproc
sw x1, -12(x13)
sw x2, -16(x13)
addi x2, x13, -16
.cfi_def_cfa x2, 16
.cfi_offset x1, -12
.cfi_offset x2, -16
jalr x1, x12, 0
lw x1, 4(x2)
.cfi_restore x1
lw x2, 0(x2)
.cfi_restore x2
jr x1
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

64
vendor/psm/src/arch/riscv64.s vendored Normal file
View File

@@ -0,0 +1,64 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
li x10, STACK_DIRECTION_DESCENDING
jr x1
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
add x10, x2, x0
jr x1
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(x10: usize, x11: extern "C" fn(usize), x12: *mut u8) */
.cfi_startproc
add x2, x12, x0
jr x11
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(x10: usize, x11: usize, x12: extern "C" fn(usize, usize), x13: *mut u8) */
.cfi_startproc
sd x1, -8(x13)
sd x2, -16(x13)
addi x2, x13, -16
.cfi_def_cfa x2, 16
.cfi_offset x1, -8
.cfi_offset x2, -16
jalr x1, x12, 0
ld x1, 8(x2)
.cfi_restore x1
ld x2, 0(x2)
.cfi_restore x2
jr x1
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

68
vendor/psm/src/arch/sparc64.s vendored Normal file
View File

@@ -0,0 +1,68 @@
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
jmpl %o7 + 8, %g0
mov STACK_DIRECTION_DESCENDING, %o0
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
jmpl %o7 + 8, %g0
mov %o6, %o0
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(%i0: usize, %i1: extern "C" fn(usize), %i2: *mut u8) */
.cfi_startproc
.cfi_def_cfa 0, 0
.cfi_return_column 0
jmpl %o1, %g0
/* WEIRD: Why is the LSB set for the %sp and %fp on SPARC?? */
add %o2, -0x7ff, %o6
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(%i0: usize, %i1: usize, %i2: extern "C" fn(usize, usize), %i3: *mut u8) */
.cfi_startproc
/* The fact that locals and saved register windows are offset by 2kB is
very nasty property of SPARC architecture and ABI. In this case it forces us to slice off
2kB of the stack space outright for no good reason other than adapting to a botched design.
*/
save %o3, -0x87f, %o6
.cfi_def_cfa_register %fp
.cfi_window_save
.cfi_register %r15, %r31
mov %i1, %o1
jmpl %i2, %o7
mov %i0, %o0
ret
restore
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

66
vendor/psm/src/arch/sparc_sysv.s vendored Normal file
View File

@@ -0,0 +1,66 @@
#include "psm.h"
#include "gnu_stack_note.s"
/* FIXME: this ABI has definitely not been verified at all */
.text
.globl rust_psm_stack_direction
.p2align 2
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
jmpl %o7 + 8, %g0
mov STACK_DIRECTION_DESCENDING, %o0
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 2
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
jmpl %o7 + 8, %g0
mov %o6, %o0
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 2
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(%i0: usize, %i1: extern "C" fn(usize), %i2: *mut u8) */
.cfi_startproc
.cfi_def_cfa 0, 0
.cfi_return_column 0
jmpl %o1, %g0
/* WEIRD: Why is the LSB set for the %sp and %fp on SPARC?? */
add %o2, -0x3ff, %o6
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 2
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(%i0: usize, %i1: usize, %i2: extern "C" fn(usize, usize), %i3: *mut u8) */
.cfi_startproc
save %o3, -0x43f, %o6
.cfi_def_cfa_register %fp
.cfi_window_save
.cfi_register %r15, %r31
mov %i1, %o1
jmpl %i2, %o7
mov %i0, %o0
ret
restore
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

BIN
vendor/psm/src/arch/wasm32.o vendored Normal file

Binary file not shown.

61
vendor/psm/src/arch/wasm32.s vendored Normal file
View File

@@ -0,0 +1,61 @@
#include "psm.h"
#include "gnu_stack_note.s"
# Note that this function is not compiled when this package is uploaded to
# crates.io, this source is only here as a reference for how the corresponding
# wasm32.o was generated. This file can be compiled with:
#
# cpp psm/src/arch/wasm32.s | llvm-mc -o psm/src/arch/wasm32.o --arch=wasm32 -filetype=obj
#
# where you'll want to ensure that `llvm-mc` is from a relatively recent
# version of LLVM.
.globaltype __stack_pointer, i32
.globl rust_psm_stack_direction
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
.functype rust_psm_stack_direction () -> (i32)
i32.const STACK_DIRECTION_DESCENDING
end_function
.globl rust_psm_stack_pointer
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
.functype rust_psm_stack_pointer () -> (i32)
global.get __stack_pointer
end_function
.globl rust_psm_on_stack
.type rust_psm_on_stack,@function
rust_psm_on_stack:
.functype rust_psm_on_stack (i32, i32, i32, i32) -> ()
# get our new stack argument, then save the old stack
# pointer into that local
local.get 3
global.get __stack_pointer
local.set 3
global.set __stack_pointer
# Call our indirect function specified
local.get 0
local.get 1
local.get 2
call_indirect (i32, i32) -> ()
# restore the stack pointer before returning
local.get 3
global.set __stack_pointer
end_function
.globl rust_psm_replace_stack
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
.functype rust_psm_replace_stack (i32, i32, i32) -> ()
local.get 2
global.set __stack_pointer
local.get 0
local.get 1
call_indirect (i32) -> ()
unreachable
end_function

92
vendor/psm/src/arch/x86.s vendored Normal file
View File

@@ -0,0 +1,92 @@
#include "psm.h"
#include "gnu_stack_note.s"
/* NOTE: fastcall calling convention used on all x86 targets */
.text
#if defined(CFG_TARGET_OS_darwin) || defined(CFG_TARGET_OS_macos) || defined(CFG_TARGET_OS_ios)
#define GLOBL(fnname) .globl _##fnname
#define TYPE(fnname)
#define FUNCTION(fnname) _##fnname
#define SIZE(fnname,endlabel)
#else
#define GLOBL(fnname) .globl fnname
#define TYPE(fnname) .type fnname,@function
#define FUNCTION(fnname) fnname
#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname
#endif
GLOBL(rust_psm_stack_direction)
.p2align 4
TYPE(rust_psm_stack_direction)
FUNCTION(rust_psm_stack_direction):
/* extern "fastcall" fn() -> u8 (%al) */
.cfi_startproc
movb $STACK_DIRECTION_DESCENDING, %al # always descending on x86_64
retl
.rust_psm_stack_direction_end:
SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end)
.cfi_endproc
GLOBL(rust_psm_stack_pointer)
.p2align 4
TYPE(rust_psm_stack_pointer)
FUNCTION(rust_psm_stack_pointer):
/* extern "fastcall" fn() -> *mut u8 (%rax) */
.cfi_startproc
leal 4(%esp), %eax
retl
.rust_psm_stack_pointer_end:
SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end)
.cfi_endproc
GLOBL(rust_psm_replace_stack)
.p2align 4
TYPE(rust_psm_replace_stack)
FUNCTION(rust_psm_replace_stack):
/* extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize), 4(%esp): *mut u8) */
.cfi_startproc
/*
All we gotta do is set the stack pointer to 4(%esp) & tail-call the callback in %edx
Note, that the callee expects the stack to be offset by 4 bytes (normally, a return address
would be store there) off the required stack alignment on entry. To offset the stack in such a
way we use the `calll` instruction, however it would also be possible to to use plain `jmpl` but
would require to adjust the stack manually, which cannot be easily done, because the stack
pointer argument is already stored in memory.
*/
movl 4(%esp), %esp
calll *%edx
ud2
.rust_psm_replace_stack_end:
SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end)
.cfi_endproc
GLOBL(rust_psm_on_stack)
.p2align 4
TYPE(rust_psm_on_stack)
FUNCTION(rust_psm_on_stack):
/* extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize), 8(%esp): *mut u8) */
.cfi_startproc
pushl %ebp
.cfi_def_cfa %esp, 8
.cfi_offset %ebp, -8
movl %esp, %ebp
.cfi_def_cfa_register %ebp
movl 12(%ebp), %esp
calll *8(%ebp)
movl %ebp, %esp
popl %ebp
.cfi_def_cfa %esp, 4
retl $8
.rust_psm_on_stack_end:
SIZE(rust_psm_on_stack,.rust_psm_on_stack_end)
.cfi_endproc

86
vendor/psm/src/arch/x86_64.s vendored Normal file
View File

@@ -0,0 +1,86 @@
#include "psm.h"
#include "gnu_stack_note.s"
/* NOTE: sysv64 calling convention is used on all x86_64 targets, including Windows! */
.text
#if defined(CFG_TARGET_OS_darwin) || defined(CFG_TARGET_OS_macos) || defined(CFG_TARGET_OS_ios)
#define GLOBL(fnname) .globl _##fnname
#define TYPE(fnname)
#define FUNCTION(fnname) _##fnname
#define END_FUNCTION(fnname)
#else
#define GLOBL(fnname) .globl fnname
#define TYPE(fnname) .type fnname,@function
#define FUNCTION(fnname) fnname
#define END_FUNCTION(fnname) .size fnname,.-fnname
#endif
GLOBL(rust_psm_stack_direction)
.p2align 4
TYPE(rust_psm_stack_direction)
FUNCTION(rust_psm_stack_direction):
/* extern "sysv64" fn() -> u8 (%al) */
.cfi_startproc
movb $STACK_DIRECTION_DESCENDING, %al # always descending on x86_64
retq
END_FUNCTION(rust_psm_stack_direction)
.cfi_endproc
GLOBL(rust_psm_stack_pointer)
.p2align 4
TYPE(rust_psm_stack_pointer)
FUNCTION(rust_psm_stack_pointer):
/* extern "sysv64" fn() -> *mut u8 (%rax) */
.cfi_startproc
leaq 8(%rsp), %rax
retq
.rust_psm_stack_pointer_end:
END_FUNCTION(rust_psm_stack_pointer)
.cfi_endproc
GLOBL(rust_psm_replace_stack)
.p2align 4
TYPE(rust_psm_replace_stack)
FUNCTION(rust_psm_replace_stack):
/* extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8) */
.cfi_startproc
/*
All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi.
8-byte offset necessary to account for the "return" pointer that would otherwise be placed onto
stack with a regular call
*/
leaq -8(%rdx), %rsp
jmpq *%rsi
.rust_psm_replace_stack_end:
END_FUNCTION(rust_psm_replace_stack)
.cfi_endproc
GLOBL(rust_psm_on_stack)
.p2align 4
TYPE(rust_psm_on_stack)
FUNCTION(rust_psm_on_stack):
/* extern "sysv64" fn(%rdi: usize, %rsi: usize, %rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8) */
.cfi_startproc
pushq %rbp
.cfi_def_cfa %rsp, 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movq %rcx, %rsp
callq *%rdx
movq %rbp, %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
END_FUNCTION(rust_psm_on_stack)
.cfi_endproc

61
vendor/psm/src/arch/x86_64_msvc.asm vendored Normal file
View File

@@ -0,0 +1,61 @@
PUBLIC rust_psm_stack_direction
PUBLIC rust_psm_stack_pointer
PUBLIC rust_psm_replace_stack
PUBLIC rust_psm_on_stack
_TEXT SEGMENT
; extern "sysv64" fn() -> u8 (%al)
rust_psm_stack_direction PROC
mov al, 2
ret
rust_psm_stack_direction ENDP
; extern "sysv64" fn() -> *mut u8 (%rax)
rust_psm_stack_pointer PROC
lea rax, [rsp + 8]
ret
rust_psm_stack_pointer ENDP
; extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8, %rcx: *mut u8)
rust_psm_replace_stack PROC
mov gs:[08h], rdx
mov gs:[10h], rcx
lea rsp, [rdx - 8]
jmp rsi
rust_psm_replace_stack ENDP
; extern "sysv64" fn(%rdi: usize, %rsi: usize,
; %rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8, %r8: *mut u8)
;
; NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be
; fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for
; exception handlers at *all* if they happen to fall outside the are specified in TIB.
;
; This necessitates an API difference from the usual 4-argument signature used elsewhere.
;
; FIXME: this needs a catch-all exception handler that aborts in case somebody unwinds into here.
rust_psm_on_stack PROC FRAME
push rbp
.pushreg rbp
mov rbp, rsp
.setframe rbp, 0
.endprolog
push gs:[08h]
mov gs:[08h], rcx
push gs:[10h]
mov gs:[10h], r8
mov rsp, rcx
call rdx
lea rsp, [rbp - 010h]
pop gs:[10h]
pop gs:[08h]
pop rbp
ret
rust_psm_on_stack ENDP
_TEXT ENDS
END

View File

@@ -0,0 +1,97 @@
#include "gnu_stack_note.s"
.text
.def rust_psm_stack_direction
.scl 2
.type 32
.endef
.globl rust_psm_stack_direction
.p2align 4
rust_psm_stack_direction:
/* extern "sysv64" fn() -> u8 (%al) */
.cfi_startproc
movb $2, %al # always descending on x86_64
retq
.cfi_endproc
.def rust_psm_stack_pointer
.scl 2
.type 32
.endef
.globl rust_psm_stack_pointer
.p2align 4
rust_psm_stack_pointer:
/* extern "sysv64" fn() -> *mut u8 (%rax) */
.cfi_startproc
leaq 8(%rsp), %rax
retq
.cfi_endproc
.def rust_psm_replace_stack
.scl 2
.type 32
.endef
.globl rust_psm_replace_stack
.p2align 4
rust_psm_replace_stack:
/* extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8, %rcx: *mut u8) */
.cfi_startproc
/*
All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi.
8-byte offset necessary to account for the "return" pointer that would otherwise be placed onto
stack with a regular call
*/
movq %gs:0x08, %rdx
movq %gs:0x10, %rcx
leaq -8(%rdx), %rsp
jmpq *%rsi
.cfi_endproc
.def rust_psm_on_stack
.scl 2
.type 32
.endef
.globl rust_psm_on_stack
.p2align 4
rust_psm_on_stack:
/*
extern "sysv64" fn(%rdi: usize, %rsi: usize,
%rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8, %r8: *mut u8)
NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be
fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for
exception handlers at *all* if they happen to fall outside the are specified in TIB.
This necessitates an API difference from the usual 4-argument signature used elsewhere.
FIXME: this needs a catch-all exception handler that aborts in case somebody unwinds into here.
*/
.cfi_startproc
pushq %rbp
.cfi_def_cfa %rsp, 16
.cfi_offset %rbp, -16
pushq %gs:0x08
.cfi_def_cfa %rsp, 24
pushq %gs:0x10
.cfi_def_cfa %rsp, 32
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movq %rcx, %gs:0x08
movq %r8, %gs:0x10
movq %rcx, %rsp
callq *%rdx
movq %rbp, %rsp
popq %gs:0x10
.cfi_def_cfa %rsp, 24
popq %gs:0x08
.cfi_def_cfa %rsp, 16
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.cfi_endproc

70
vendor/psm/src/arch/x86_msvc.asm vendored Normal file
View File

@@ -0,0 +1,70 @@
; FIXME: this is weird, this works locally but not on appveyor?!??!
.386
.model flat
ASSUME FS:NOTHING
; WTF: PUBLIC conflicts with "SYSCALL" but "SYSCALL" is the only way to stop MASM from manging the
; symbol names?
;
; PUBLIC @rust_psm_stack_direction@0
; PUBLIC @rust_psm_stack_pointer@0
; PUBLIC @rust_psm_replace_stack@12
; PUBLIC @rust_psm_on_stack@16
_TEXT SEGMENT
; extern "fastcall" fn() -> u8 (%al)
@rust_psm_stack_direction@0 PROC SYSCALL
mov al, 2
ret
@rust_psm_stack_direction@0 ENDP
; extern "fastcall" fn() -> *mut u8 (%rax)
@rust_psm_stack_pointer@0 PROC SYSCALL
lea eax, [esp + 4]
ret
@rust_psm_stack_pointer@0 ENDP
; extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize),
; 4(%esp): *mut u8, 8(%esp): *mut u8)
@rust_psm_replace_stack@16 PROC SYSCALL
mov eax, dword ptr [esp + 8]
mov fs:[08h], eax
mov esp, dword ptr [esp + 4]
mov fs:[04h], esp
jmp edx
@rust_psm_replace_stack@16 ENDP
; extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize),
; 8(%esp): *mut u8, 12(%esp): *mut u8)
;
; NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be
; fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for
; exception handlers at *all* if they happen to fall outside the are specified in TIB.
;
; This necessitates an API difference from the usual 4-argument signature used elsewhere.
@rust_psm_on_stack@20 PROC SYSCALL
push ebp
mov ebp, esp
push fs:[0E0Ch]
push fs:[08h]
mov eax, dword ptr [ebp + 4 + 12]
mov dword ptr fs:[08h], eax
mov dword ptr fs:[0E0Ch], eax
push fs:[04h]
mov esp, dword ptr [ebp + 4 + 8]
mov dword ptr fs:[04h], esp
call dword ptr [ebp + 4 + 4]
lea esp, [ebp - 12]
pop fs:[04h]
pop fs:[08h]
pop fs:[0E0Ch]
pop ebp
ret 12
@rust_psm_on_stack@20 ENDP
END

94
vendor/psm/src/arch/x86_windows_gnu.s vendored Normal file
View File

@@ -0,0 +1,94 @@
/* FIXME: this works locally but not on appveyor??!? */
/* NOTE: fastcall calling convention used on all x86 targets */
.text
.def @rust_psm_stack_direction@0
.scl 2
.type 32
.endef
.globl @rust_psm_stack_direction@0
.p2align 4
@rust_psm_stack_direction@0:
/* extern "fastcall" fn() -> u8 (%al) */
.cfi_startproc
movb $2, %al # always descending on x86_64
retl
.cfi_endproc
.def @rust_psm_stack_pointer@0
.scl 2
.type 32
.endef
.globl @rust_psm_stack_pointer@0
.p2align 4
@rust_psm_stack_pointer@0:
/* extern "fastcall" fn() -> *mut u8 (%rax) */
.cfi_startproc
leal 4(%esp), %eax
retl
.cfi_endproc
.def @rust_psm_replace_stack@16
.scl 2
.type 32
.endef
.globl @rust_psm_replace_stack@16
.p2align 4
@rust_psm_replace_stack@16:
/* extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize), 4(%esp): *mut u8) */
.cfi_startproc
/*
All we gotta do is set the stack pointer to 4(%esp) & tail-call the callback in %edx
Note, that the callee expects the stack to be offset by 4 bytes (normally, a return address
would be store there) off the required stack alignment on entry. To offset the stack in such a
way we use the `calll` instruction, however it would also be possible to to use plain `jmpl` but
would require to adjust the stack manually, which cannot be easily done, because the stack
pointer argument is already stored in memory.
*/
movl 8(%esp), %eax
mov %eax, %fs:0x08
movl 4(%esp), %esp
mov %esp, %fs:0x04
calll *%edx
ud2
.cfi_endproc
.def @rust_psm_on_stack@16
.scl 2
.type 32
.endef
.globl @rust_psm_on_stack@16
.p2align 4
@rust_psm_on_stack@16:
/* extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize), 8(%esp): *mut u8) */
.cfi_startproc
pushl %ebp
.cfi_def_cfa %esp, 8
.cfi_offset %ebp, -8
pushl %fs:0x04
.cfi_def_cfa %esp, 12
pushl %fs:0x08
.cfi_def_cfa %esp, 16
movl %esp, %ebp
.cfi_def_cfa_register %ebp
movl 24(%ebp), %eax
movl %eax, %fs:0x08
movl 20(%ebp), %esp
movl %esp, %fs:0x04
calll *16(%ebp)
movl %ebp, %esp
popl %fs:0x08
.cfi_def_cfa %esp, 12
popl %fs:0x04
.cfi_def_cfa %esp, 8
popl %ebp
.cfi_def_cfa %esp, 4
retl $12
.cfi_endproc

76
vendor/psm/src/arch/zseries_linux.s vendored Normal file
View File

@@ -0,0 +1,76 @@
/* Implementation of stack swtiching routines for zSeries LINUX ABI.
This ABI is used by the s390x-unknown-linux-gnu target.
Documents used:
* LINUX for zSeries: ELF Application Binary Interface Supplement (1st ed., 2001) (LNUX-1107-01)
* z/Architecture: Principles of Operation (4th ed., 2004) (SA22-7832-03)
*/
#include "psm.h"
#include "gnu_stack_note.s"
.text
.globl rust_psm_stack_direction
.p2align 4
.type rust_psm_stack_direction,@function
rust_psm_stack_direction:
/* extern "C" fn() -> u8 */
.cfi_startproc
lghi %r2, STACK_DIRECTION_DESCENDING
br %r14
.rust_psm_stack_direction_end:
.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction
.cfi_endproc
.globl rust_psm_stack_pointer
.p2align 4
.type rust_psm_stack_pointer,@function
rust_psm_stack_pointer:
/* extern "C" fn() -> *mut u8 */
.cfi_startproc
la %r2, 0(%r15)
br %r14
.rust_psm_stack_pointer_end:
.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer
.cfi_endproc
.globl rust_psm_replace_stack
.p2align 4
.type rust_psm_replace_stack,@function
rust_psm_replace_stack:
/* extern "C" fn(r2: usize, r3: extern "C" fn(usize), r4: *mut u8) */
.cfi_startproc
/* FIXME: backtrace does not terminate cleanly for some reason */
lay %r15, -160(%r4)
/* FIXME: this is `basr` instead of `br` purely to remove the backtrace link to the caller */
basr %r14, %r3
.rust_psm_replace_stack_end:
.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack
.cfi_endproc
.globl rust_psm_on_stack
.p2align 4
.type rust_psm_on_stack,@function
rust_psm_on_stack:
/* extern "C" fn(r2: usize, r3: usize, r4: extern "C" fn(usize, usize), r5: *mut u8) */
.cfi_startproc
stmg %r14, %r15, -16(%r5)
lay %r15, -176(%r5)
.cfi_def_cfa %r15, 176
.cfi_offset %r14, -16
.cfi_offset %r15, -8
basr %r14, %r4
lmg %r14, %r15, 160(%r15)
.cfi_restore %r14
.cfi_restore %r15
br %r14
.rust_psm_on_stack_end:
.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack
.cfi_endproc

406
vendor/psm/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,406 @@
//! # **P**ortable **S**tack **M**anipulation
//! This crate provides portable functions to control the stack pointer and inspect the properties
//! of the stack. This crate does not attempt to provide safe abstractions to any operations, the
//! only goals are correctness, portability and efficiency (in that exact order). As a consequence
//! most functions you will find in this crate are unsafe.
//!
//! Note, that the stack allocation is left up to the user. Unless youre writing a safe
//! abstraction over stack manipulation, this is unlikely to be the crate you want. Instead
//! consider one of the safe abstractions over this crate such as `stacker`. Another good place to
//! look at is the crates.ios reverse dependency list.
#![allow(unused_macros)]
#![no_std]
macro_rules! extern_item {
(unsafe $($toks: tt)+) => {
unsafe extern "C" $($toks)+
};
($($toks: tt)+) => {
extern "C" $($toks)+
};
}
// Surprising: turns out subsequent macro_rules! override previous definitions, instead of
// erroring? Convenient for us in this case, though.
#[cfg(target_arch = "x86_64")]
macro_rules! extern_item {
(unsafe $($toks: tt)+) => {
unsafe extern "sysv64" $($toks)+
};
($($toks: tt)+) => {
extern "sysv64" $($toks)+
};
}
#[cfg(target_arch = "x86")]
macro_rules! extern_item {
(unsafe $($toks: tt)+) => {
unsafe extern "fastcall" $($toks)+
};
($($toks: tt)+) => {
extern "fastcall" $($toks)+
};
}
#[cfg(target_arch = "arm")]
macro_rules! extern_item {
(unsafe $($toks: tt)+) => {
unsafe extern "aapcs" $($toks)+
};
($($toks: tt)+) => {
extern "aapcs" $($toks)+
};
}
// NB: this could be nicer across multiple blocks but we cannot do it because of
// https://github.com/rust-lang/rust/issues/65847
extern_item! { {
#![cfg_attr(link_asm, link(name="psm_s"))]
#[cfg(asm)]
fn rust_psm_stack_direction() -> u8;
#[cfg(asm)]
fn rust_psm_stack_pointer() -> *mut u8;
#[cfg(all(switchable_stack, not(target_os = "windows")))]
#[link_name="rust_psm_replace_stack"]
fn _rust_psm_replace_stack(
data: usize,
callback: extern_item!(unsafe fn(usize) -> !),
sp: *mut u8
) -> !;
#[cfg(all(switchable_stack, not(target_os = "windows")))]
#[link_name="rust_psm_on_stack"]
fn _rust_psm_on_stack(
data: usize,
return_ptr: usize,
callback: extern_item!(unsafe fn(usize, usize)),
sp: *mut u8,
);
#[cfg(all(switchable_stack, target_os = "windows"))]
fn rust_psm_replace_stack(
data: usize,
callback: extern_item!(unsafe fn(usize) -> !),
sp: *mut u8,
stack_base: *mut u8
) -> !;
#[cfg(all(switchable_stack, target_os = "windows"))]
fn rust_psm_on_stack(
data: usize,
return_ptr: usize,
callback: extern_item!(unsafe fn(usize, usize)),
sp: *mut u8,
stack_base: *mut u8
);
} }
#[cfg(all(switchable_stack, not(target_os = "windows")))]
#[inline(always)]
unsafe fn rust_psm_replace_stack(
data: usize,
callback: extern_item!(unsafe fn(usize) -> !),
sp: *mut u8,
_: *mut u8,
) -> ! {
_rust_psm_replace_stack(data, callback, sp)
}
#[cfg(all(switchable_stack, not(target_os = "windows")))]
#[inline(always)]
unsafe fn rust_psm_on_stack(
data: usize,
return_ptr: usize,
callback: extern_item!(unsafe fn(usize, usize)),
sp: *mut u8,
_: *mut u8,
) {
_rust_psm_on_stack(data, return_ptr, callback, sp)
}
/// Run the closure on the provided stack.
///
/// Once the closure completes its execution, the original stack pointer is restored and execution
/// returns to the caller.
///
/// `base` address must be the low address of the stack memory region, regardless of the stack
/// growth direction. It is not necessary for the whole region `[base; base + size]` to be usable
/// at the time this function called, however it is required that at least the following hold:
///
/// * Both `base` and `base + size` are aligned up to the target-specific requirements;
/// * Depending on `StackDirection` value for the platform, the end of the stack memory region,
/// which would end up containing the first frame(s), must have sufficient number of pages
/// allocated to execute code until more pages are commited. The other end should contain a guard
/// page (not writable, readable or executable) to ensure Rusts soundness guarantees.
///
/// Note, that some or all of these considerations are irrelevant to some applications. For
/// example, Rusts soundness story relies on all stacks having a guard-page, however if the user
/// is able to guarantee that the memory region used for stack cannot be exceeded, a guard page may
/// end up being an expensive unnecessity.
///
/// The previous stack may not be deallocated. If an ability to deallocate the old stack is desired
/// consider `replace_stack` instead.
///
/// # Guidelines
///
/// Memory regions that are aligned to a single page (usually 4kB) are an extremely portable choice
/// for stacks.
///
/// Allocate at least 4kB of stack. Some architectures (such as SPARC) consume stack memory
/// significantly faster compared to the more usual architectures such as x86 or ARM. Allocating
/// less than 4kB of memory may make it impossible to commit more pages without overflowing the
/// stack later on.
///
/// # Unsafety
///
/// The stack `base` address must be aligned as appropriate for the target.
///
/// The stack `size` must be a multiple of stack alignment required by target.
///
/// The `size` must not overflow `isize`.
///
/// `callback` must not unwind or return control flow by any other means than directly returning.
///
/// # Examples
///
/// ```
/// use std::alloc;
/// const STACK_ALIGN: usize = 4096;
/// const STACK_SIZE: usize = 4096;
/// unsafe {
/// let layout = alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGN).unwrap();
/// let new_stack = alloc::alloc(layout);
/// assert!(!new_stack.is_null(), "allocations must succeed!");
/// let (stack, result) = psm::on_stack(new_stack, STACK_SIZE, || {
/// (psm::stack_pointer(), 4 + 4)
/// });
/// println!("4 + 4 = {} has been calculated on stack {:p}", result, stack);
/// }
/// ```
#[cfg(switchable_stack)]
pub unsafe fn on_stack<R, F: FnOnce() -> R>(base: *mut u8, size: usize, callback: F) -> R {
use core::mem::MaybeUninit;
extern_item! {
unsafe fn with_on_stack<R, F: FnOnce() -> R>(callback_ptr: usize, return_ptr: usize) {
let return_ptr = (*(return_ptr as *mut MaybeUninit<R>)).as_mut_ptr();
let callback = (*(callback_ptr as *mut MaybeUninit<F>)).as_ptr();
// Safe to move out from `F`, because closure in is forgotten in `on_stack` and dropping
// only occurs in this callback.
return_ptr.write((callback.read())());
}
}
let sp = match StackDirection::new() {
StackDirection::Ascending => base,
StackDirection::Descending => base.offset(size as isize),
};
let mut callback: MaybeUninit<F> = MaybeUninit::new(callback);
let mut return_value: MaybeUninit<R> = MaybeUninit::uninit();
rust_psm_on_stack(
&mut callback as *mut MaybeUninit<F> as usize,
&mut return_value as *mut MaybeUninit<R> as usize,
with_on_stack::<R, F>,
sp,
base,
);
return return_value.assume_init();
}
/// Run the provided non-terminating computation on an entirely new stack.
///
/// `base` address must be the low address of the stack memory region, regardless of the stack
/// growth direction. It is not necessary for the whole region `[base; base + size]` to be usable
/// at the time this function called, however it is required that at least the following hold:
///
/// * Both `base` and `base + size` are aligned up to the target-specific requirements;
/// * Depending on `StackDirection` value for the platform, the end of the stack memory region,
/// which would end up containing the first frame(s), must have sufficient number of pages
/// allocated to execute code until more pages are commited. The other end should contain a guard
/// page (not writable, readable or executable) to ensure Rusts soundness guarantees.
///
/// Note, that some or all of these considerations are irrelevant to some applications. For
/// example, Rusts soundness story relies on all stacks having a guard-page, however if the user
/// is able to guarantee that the memory region used for stack cannot be exceeded, a guard page may
/// end up being an expensive unnecessity.
///
/// The previous stack is not deallocated and may not be deallocated unless the data on the old
/// stack is not referenced in any way (by e.g. the `callback` closure).
///
/// On platforms where multiple stack pointers are available, the “current” stack pointer is
/// replaced.
///
/// # Guidelines
///
/// Memory regions that are aligned to a single page (usually 4kB) are an extremely portable choice
/// for stacks.
///
/// Allocate at least 4kB of stack. Some architectures (such as SPARC) consume stack memory
/// significantly faster compared to the more usual architectures such as x86 or ARM. Allocating
/// less than 4kB of memory may make it impossible to commit more pages without overflowing the
/// stack later on.
///
/// # Unsafety
///
/// The stack `base` address must be aligned as appropriate for the target.
///
/// The stack `size` must be a multiple of stack alignment required by target.
///
/// The `size` must not overflow `isize`.
///
/// `callback` must not return (not enforced by typesystem currently because `!` is unstable),
/// unwind or otherwise return control flow to any of the previous frames.
#[cfg(switchable_stack)]
pub unsafe fn replace_stack<F: FnOnce()>(base: *mut u8, size: usize, callback: F) -> ! {
extern_item! { unsafe fn with_replaced_stack<F: FnOnce()>(d: usize) -> ! {
// Safe to move out, because the closure is essentially forgotten by
// this being required to never return...
::core::ptr::read(d as *const F)();
::core::hint::unreachable_unchecked();
} }
let sp = match StackDirection::new() {
StackDirection::Ascending => base,
StackDirection::Descending => base.offset(size as isize),
};
rust_psm_replace_stack(
&callback as *const F as usize,
with_replaced_stack::<F>,
sp,
base,
);
}
/// The direction into which stack grows as stack frames are made.
///
/// This is a target-specific property that can be obtained at runtime by calling
/// `StackDirection::new()`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum StackDirection {
Ascending = 1,
Descending = 2,
}
impl StackDirection {
/// Obtain the stack growth direction.
#[cfg(asm)]
pub fn new() -> StackDirection {
const ASC: u8 = StackDirection::Ascending as u8;
const DSC: u8 = StackDirection::Descending as u8;
unsafe {
match rust_psm_stack_direction() {
ASC => StackDirection::Ascending,
DSC => StackDirection::Descending,
_ => ::core::hint::unreachable_unchecked(),
}
}
}
}
/// Returns current stack pointer.
///
/// Note, that the stack pointer returned is from the perspective of the caller. From the
/// perspective of `stack_pointer` function the pointer returned is the frame pointer.
///
/// While it is a goal to minimize the amount of stack used by this function, implementations for
/// some targets may be unable to avoid allocating a stack frame. This makes this function
/// suitable for stack exhaustion detection only in conjunction with sufficient padding.
///
/// Using `stack_pointer` to check for stack exhaustion is tricky to get right. It is impossible to
/// know the callees frame size, therefore such value must be derived some other way. A common
/// approach is to use stack padding (reserve enough stack space for any function to be called) and
/// check against the padded threshold. If padding is chosen incorrectly, a situation similar to
/// one described below may occur:
///
/// 1. For stack exhaustion check, remaining stack is checked against `stack_pointer` with the
/// padding applied;
/// 2. Callee allocates more stack than was accounted for with padding, and accesses pages outside
/// the stack, invalidating the execution (by e.g. crashing).
#[cfg(asm)]
pub fn stack_pointer() -> *mut u8 {
unsafe { rust_psm_stack_pointer() }
}
/// Macro that outputs its tokens only if `psm::on_stack` and `psm::replace_stack` are available.
///
/// # Examples
///
/// ```
/// # use psm::psm_stack_manipulation;
/// psm_stack_manipulation! {
/// yes {
/// /* Functions `on_stack` and `replace_stack` are available here */
/// }
/// no {
/// /* Functions `on_stack` and `replace_stack` are not available here */
/// }
/// }
/// ```
#[cfg(switchable_stack)]
#[macro_export]
macro_rules! psm_stack_manipulation {
(yes { $($yes: tt)* } no { $($no: tt)* }) => { $($yes)* };
}
/// Macro that outputs its tokens only if `psm::on_stack` and `psm::replace_stack` are available.
///
/// # Examples
///
/// ```
/// # use psm::psm_stack_manipulation;
/// psm_stack_manipulation! {
/// yes {
/// /* Functions `on_stack` and `replace_stack` are available here */
/// }
/// no {
/// /* Functions `on_stack` and `replace_stack` are not available here */
/// }
/// }
/// ```
#[cfg(not(switchable_stack))]
#[macro_export]
macro_rules! psm_stack_manipulation {
(yes { $($yes: tt)* } no { $($no: tt)* }) => { $($no)* };
}
/// Macro that outputs its tokens only if `psm::stack_pointer` and `psm::StackDirection::new` are
/// available.
///
/// # Examples
///
/// ```
/// # use psm::psm_stack_information;
/// psm_stack_information! {
/// yes {
/// /* `psm::stack_pointer` and `psm::StackDirection::new` are available here */
/// }
/// no {
/// /* `psm::stack_pointer` and `psm::StackDirection::new` are not available here */
/// }
/// }
/// ```
#[cfg(asm)]
#[macro_export]
macro_rules! psm_stack_information {
(yes { $($yes: tt)* } no { $($no: tt)* }) => { $($yes)* };
}
/// Macro that outputs its tokens only if `psm::stack_pointer` and `psm::StackDirection::new` are
/// available.
///
/// # Examples
///
/// ```
/// # use psm::psm_stack_information;
/// psm_stack_information! {
/// yes {
/// /* `psm::stack_pointer` and `psm::StackDirection::new` are available here */
/// }
/// no {
/// /* `psm::stack_pointer` and `psm::StackDirection::new` are not available here */
/// }
/// }
/// ```
#[cfg(not(asm))]
#[macro_export]
macro_rules! psm_stack_information {
(yes { $($yes: tt)* } no { $($no: tt)* }) => { $($no)* };
}

Binary file not shown.

View File

View File

@@ -0,0 +1 @@
{"name":"psm","vers":"0.1.30","deps":[{"name":"ar_archive_writer","req":"^0.5.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"build","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"cc","req":"^1.2.33","features":[],"optional":false,"default_features":true,"target":null,"kind":"build","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{},"features2":null,"cksum":"c911d20a4fe1c046ef8004d6e99183a066e3ee77ee8ad4a2b21ccdd046be5cac","yanked":null,"links":null,"rust_version":null,"v":2}

Binary file not shown.

6
vendor/psm/tests/stack_direction.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
extern crate psm;
#[test]
fn always_equal() {
assert_eq!(psm::StackDirection::new(), psm::StackDirection::new());
}

29
vendor/psm/tests/stack_direction_2.rs vendored Normal file
View File

@@ -0,0 +1,29 @@
extern crate psm;
#[inline(never)]
fn test_direction(previous_sp: *mut u8) {
let current_sp = psm::stack_pointer();
match psm::StackDirection::new() {
psm::StackDirection::Ascending => {
assert!(
current_sp > previous_sp,
"the stack pointer is not ascending! current = {:p}, previous = {:p}",
current_sp,
previous_sp
);
}
psm::StackDirection::Descending => {
assert!(
current_sp < previous_sp,
"the stack pointer is not descending! current = {:p}, previous = {:p}",
current_sp,
previous_sp
);
}
}
}
#[test]
fn direction_right() {
test_direction(psm::stack_pointer());
}