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

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)* };
}