summary refs log tree commit diff stats
path: root/lib/arch
diff options
context:
space:
mode:
authorRokas Kupstys <rokups@zoho.com>2017-02-20 17:10:50 +0200
committerRokas Kupstys <rokups@zoho.com>2017-02-20 17:24:19 +0200
commit373e667dbc6aff5dd74f5ada139d867287e9dc1f (patch)
tree41da1a7c7298e8ae5f146b528446b3d279480aca /lib/arch
parenta3b8bf300df20f2922275ff62293e3f882cad090 (diff)
downloadNim-373e667dbc6aff5dd74f5ada139d867287e9dc1f.tar.gz
Coroutine rework.
* ucontext backend (default on unix)
* setjmp backend
* fibers backend (default and required on windows)
* Fixed coroutine loop timing issues
* Fixed saving of xmm registers on x64 windows
* Fixed alignment issues
* Updated coroutine sample with cooperative fibonacci calculation.
* Disable glibc security features only when platform jump functions are used
* Removed dependency on fasm.
    * Using fiber api on windows.
    * Other platforms and compilers  will use built in assembler and .S files or API provided by platform libc.
* Replaced stack switching procs with `coroExecWithStack()` which never returns. This makes compiler always generate proper code.
Diffstat (limited to 'lib/arch')
-rw-r--r--lib/arch/arch.nim62
-rw-r--r--lib/arch/i386.asm79
-rw-r--r--lib/arch/ms_amd64.asm90
-rw-r--r--lib/arch/ms_i386.asm12
-rw-r--r--lib/arch/unix_amd64.asm89
-rw-r--r--lib/arch/unix_i386.asm12
-rw-r--r--lib/arch/x86/amd64.S96
-rw-r--r--lib/arch/x86/i386.S64
8 files changed, 160 insertions, 344 deletions
diff --git a/lib/arch/arch.nim b/lib/arch/arch.nim
deleted file mode 100644
index 0b3df3d3c..000000000
--- a/lib/arch/arch.nim
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Rokas Kupstys
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-# Architecture-specific optimizations and features.
-# arch.nim can be imported by only a subset of the
-# architectures supported by Nim.
-
-when defined(windows):
-  const
-    ABI* = "ms"
-elif defined(unix):
-  const
-    ABI* = "unix"
-else:
-  {.error: "Unsupported ABI".}
-
-when defined(amd64):
-  when defined(unix):
-    # unix (sysv) ABI
-    type
-      JmpBufReg* {.pure.} = enum
-        BX, BP, R12, R13, R14, R15, SP, IP, TOTAL
-  elif defined(windows):
-    # ms ABI
-    type
-      JmpBufReg* {.pure.} = enum
-        BX, BP, R12, R13, R14, R15, SP, IP, SI, DI, TOTAL
-  type
-    Reg* {.pure.} = enum
-      AX, BX, CX, DX, SI, DI, BP, SP, IP, R8, R9, R10, R11, R12, R13, R14, R15, TOTAL
-
-elif defined(i386) or defined(nimdoc):
-    # identical fastcall calling convention on all x86 OS
-    type
-      JmpBufReg* {.pure.} = enum
-        BX, SI, DI, BP, SP, IP, TOTAL
-
-      Reg* {.pure.} = enum
-        AX, BX, CX, BP, SP, DI, SI, TOTAL
-
-else:
-  {.error: "Unsupported architecture".}
-
-{.compile: "./" & ABI & "_" & hostCPU & ".asm"}
-
-type
-  JmpBuf* = array[JmpBufReg.TOTAL, pointer]
-  Registers* = array[Reg.TOTAL, pointer]
-
-
-proc getRegisters*(ctx: var Registers) {.importc: "narch_$1", fastcall.}
-
-proc setjmp*(ctx: var JmpBuf): int {.importc: "narch_$1", fastcall.}
-proc longjmp*(ctx: JmpBuf, ret=1) {.importc: "narch_$1", fastcall.}
-
-proc coroSwitchStack*(sp: pointer) {.importc: "narch_$1", fastcall.}
-proc coroRestoreStack*() {.importc: "narch_$1", fastcall.}
diff --git a/lib/arch/i386.asm b/lib/arch/i386.asm
deleted file mode 100644
index 61f6fdda7..000000000
--- a/lib/arch/i386.asm
+++ /dev/null
@@ -1,79 +0,0 @@
-;
-;
-;            Nim's Runtime Library
-;        (c) Copyright 2015 Rokas Kupstys
-;
-;    See the file "copying.txt", included in this
-;    distribution, for details about the copyright.
-;
-
-section ".text" executable
-public narch_getRegisters
-public @narch_getRegisters@4
-public narch_setjmp
-public @narch_setjmp@4
-public narch_longjmp
-public @narch_longjmp@8
-public narch_coroSwitchStack
-public @narch_coroSwitchStack@4
-public narch_coroRestoreStack
-public @narch_coroRestoreStack@0
-
-@narch_getRegisters@4:
-narch_getRegisters:
-    mov   [ecx], eax
-    mov   [ecx+4], ebx
-    mov   [ecx+8], ecx
-    mov   [ecx+0Ch], ebp
-    mov   [ecx+10h], esp
-    mov   [ecx+14h], edi
-    mov   [ecx+18h], esi
-    ret
-
-
-@narch_setjmp@4:
-narch_setjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov  [ecx], ebx
-    mov  [ecx+4], esi
-    mov  [ecx+8], edi
-    mov  [ecx+0Ch], ebp
-    lea  eax, [esp+4]
-    mov  [ecx+10h], eax
-    mov  eax, [esp]
-    mov  [ecx+14h], eax
-    xor  eax, eax
-    ret
-
-
-@narch_longjmp@8:
-narch_longjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov  eax, edx
-    test eax, eax
-    jnz  @F
-    inc  eax
-@@:
-    mov  ebx, [ecx]
-    mov  esi, [ecx+4]
-    mov  edi, [ecx+8]
-    mov  ebp, [ecx+0Ch]
-    mov  esp, [ecx+10h]
-    mov  edx, [ecx+14h]
-    jmp  edx
-
-
-@narch_coroSwitchStack@4:
-narch_coroSwitchStack:
-    pop eax                   ; return address
-    mov edx, esp              ; old esp for saving
-    mov esp, ecx              ; swap stack with one passed to func
-    push edx                  ; store old stack pointer on newly switched stack
-    jmp eax                   ; return
-
-
-@narch_coroRestoreStack@0:
-narch_coroRestoreStack:
-    pop eax                   ; return address
-    pop esp                   ; resture old stack pointer
-    jmp eax                   ; return
diff --git a/lib/arch/ms_amd64.asm b/lib/arch/ms_amd64.asm
deleted file mode 100644
index 0503b31c9..000000000
--- a/lib/arch/ms_amd64.asm
+++ /dev/null
@@ -1,90 +0,0 @@
-;
-;
-;            Nim's Runtime Library
-;        (c) Copyright 2015 Rokas Kupstys
-;
-;    See the file "copying.txt", included in this
-;    distribution, for details about the copyright.
-;
-
-format MS64 COFF
-
-section ".text" executable align 16
-public narch_getRegisters
-public narch_setjmp
-public narch_longjmp
-public narch_coroSwitchStack
-public narch_coroRestoreStack
-
-
-narch_getRegisters:
-    mov   [rcx], rax
-    mov   [rcx+8], rbx
-    mov   [rcx+10h], rcx
-    mov   [rcx+18h], rdx
-    mov   [rcx+20h], rsi
-    mov   [rcx+28h], rdi
-    mov   [rcx+30h], rbp
-    mov   [rcx+38h], rsp
-    mov   rax, [rsp]
-    mov   [rcx+40h], rax      ; rip
-    mov   [rcx+48h], r8
-    mov   [rcx+50h], r9
-    mov   [rcx+58h], r10
-    mov   [rcx+60h], r11
-    mov   [rcx+68h], r12
-    mov   [rcx+70h], r13
-    mov   [rcx+78h], r14
-    mov   [rcx+80h], r15
-    ret
-
-
-narch_setjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov   [rcx], rbx          ; rcx is jmp_buf, move registers onto it
-    mov   [rcx+8], rbp
-    mov   [rcx+10h], r12
-    mov   [rcx+18h], r13
-    mov   [rcx+20h], r14
-    mov   [rcx+28h], r15
-    lea   rdx, [rsp+8]        ; this is our rsp WITHOUT current ret addr
-    mov   [rcx+30h], rdx
-    mov   rdx, [rsp]          ; save return addr ptr for new rip
-    mov   [rcx+38h], rdx
-    mov   [rcx+40h], rsi
-    mov   [rcx+48h], rdi
-    xor   rax, rax            ; always return 0
-    ret
-
-narch_longjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov   rax, rdx            ; val will be longjmp return
-    test  rax, rax
-    jnz   @F
-    inc   rax                 ; if val==0, val=1 per longjmp semantics
-@@:
-    mov   rbx, [rcx]          ; rax is the jmp_buf, restore regs from it
-    mov   rbp, [rcx+8]
-    mov   r12, [rcx+10h]
-    mov   r13, [rcx+18h]
-    mov   r14, [rcx+20h]
-    mov   r15, [rcx+28h]
-    mov   rsp, [rcx+30h]      ; this ends up being the stack pointer
-    mov   rdx, [rcx+38h]      ; this is the instruction pointer
-    jmp   rdx                 ; goto saved address without altering rsp
-
-
-narch_coroSwitchStack:
-    pop rax                   ; return address
-    mov rdx, rsp              ; old rsp for saving
-    mov rsp, rcx              ; swap stack with one passed to func
-    push rdx                  ; store old stack pointer on newly switched stack
-    sub rsp, 28h              ; stack alignment + shadow space
-    jmp rax                   ; return
-
-
-narch_coroRestoreStack:
-    pop rax                   ; return address
-    add rsp, 28h              ; stack alignment + shadow space
-    pop rsp                   ; resture old stack pointer
-    jmp rax                   ; return
diff --git a/lib/arch/ms_i386.asm b/lib/arch/ms_i386.asm
deleted file mode 100644
index a31a698d1..000000000
--- a/lib/arch/ms_i386.asm
+++ /dev/null
@@ -1,12 +0,0 @@
-;
-;
-;            Nim's Runtime Library
-;        (c) Copyright 2015 Rokas Kupstys
-;
-;    See the file "copying.txt", included in this
-;    distribution, for details about the copyright.
-;
-
-format MS COFF
-
-include 'i386.asm'
diff --git a/lib/arch/unix_amd64.asm b/lib/arch/unix_amd64.asm
deleted file mode 100644
index 3005c150c..000000000
--- a/lib/arch/unix_amd64.asm
+++ /dev/null
@@ -1,89 +0,0 @@
-;
-;
-;            Nim's Runtime Library
-;        (c) Copyright 2015 Rokas Kupstys
-;
-;    See the file "copying.txt", included in this
-;    distribution, for details about the copyright.
-;
-
-format ELF64
-
-section ".text" executable align 16
-public narch_getRegisters
-public narch_setjmp
-public narch_longjmp
-public narch_coroSwitchStack
-public narch_coroRestoreStack
-
-
-narch_getRegisters:
-    mov   [rdi], rax
-    mov   [rdi+8], rbx
-    mov   [rdi+10h], rcx
-    mov   [rdi+18h], rdx
-    mov   [rdi+20h], rsi
-    mov   [rdi+28h], rdi
-    mov   [rdi+30h], rbp
-    mov   [rdi+38h], rsp
-    mov   rax, [rsp]
-    mov   [rdi+40h], rax      ; rip
-    mov   [rdi+48h], r8
-    mov   [rdi+50h], r9
-    mov   [rdi+58h], r10
-    mov   [rdi+60h], r11
-    mov   [rdi+68h], r12
-    mov   [rdi+70h], r13
-    mov   [rdi+78h], r14
-    mov   [rdi+80h], r15
-    ret
-
-
-narch_setjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov   [rdi], rbx          ; rdi is jmp_buf, move registers onto it
-    mov   [rdi+8], rbp
-    mov   [rdi+10h], r12
-    mov   [rdi+18h], r13
-    mov   [rdi+20h], r14
-    mov   [rdi+28h], r15
-    lea   rdx, [rsp+8]        ; this is our rsp WITHOUT current ret addr
-    mov   [rdi+30h], rdx
-    mov   rdx, [rsp]          ; save return addr ptr for new rip
-    mov   [rdi+38h], rdx
-    xor   rax, rax            ; always return 0
-    ret
-
-
-narch_longjmp:
-    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
-    mov   rax, rsi            ; val will be longjmp return
-    test  rax, rax
-    jnz   @F
-    inc   rax                 ; if val==0, val=1 per longjmp semantics
-@@:
-    mov   rbx, [rdi]          ; rdi is the jmp_buf, restore regs from it
-    mov   rbp, [rdi+8]
-    mov   r12, [rdi+10h]
-    mov   r13, [rdi+18h]
-    mov   r14, [rdi+20h]
-    mov   r15, [rdi+28h]
-    mov   rsp, [rdi+30h]      ; this ends up being the stack pointer
-    mov   rdx, [rdi+38h]      ; this is the instruction pointer
-    jmp   rdx                 ; goto saved address without altering rsp
-
-
-narch_coroSwitchStack:
-    pop rsi                   ; return address
-    mov rdx, rsp              ; old rsp for saving
-    mov rsp, rdi              ; swap stack with one passed to func
-    push rdx                  ; store old stack pointer on newly switched stack
-    sub rsp, 8h               ; stack alignment
-    jmp rsi                   ; return
-
-
-narch_coroRestoreStack:
-	pop rsi                   ; return address
-	add rsp, 8h               ; stack alignment
-	pop rsp                   ; resture old stack pointer
-	jmp rsi                   ; return
diff --git a/lib/arch/unix_i386.asm b/lib/arch/unix_i386.asm
deleted file mode 100644
index 278679067..000000000
--- a/lib/arch/unix_i386.asm
+++ /dev/null
@@ -1,12 +0,0 @@
-;
-;
-;            Nim's Runtime Library
-;        (c) Copyright 2015 Rokas Kupstys
-;
-;    See the file "copying.txt", included in this
-;    distribution, for details about the copyright.
-;
-
-format ELF
-
-include 'i386.asm'
diff --git a/lib/arch/x86/amd64.S b/lib/arch/x86/amd64.S
new file mode 100644
index 000000000..47a26f627
--- /dev/null
+++ b/lib/arch/x86/amd64.S
@@ -0,0 +1,96 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Rokas Kupstys
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+# Partially based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
+
+.globl narch_coroExecWithStack
+.globl narch_setjmp
+.globl narch_longjmp
+.text
+
+
+# SysV ABI - first argument is rdi.
+# MS ABI   - first argument is rcx.
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  #define REG_ARG1 rcx
+  #define REG_ARG2 rdx
+#else
+  #define REG_ARG1 rdi
+  #define REG_ARG2 rsi
+#endif
+
+
+narch_coroExecWithStack:
+  mov  %REG_ARG2, %rsp        # swap stack with one passed to func
+  sub  $0x30, %rsp            # shadow space (for ms ABI) 0x20 + 0x10 for possible misalignment
+  and  $-0x10, %rsp           # 16-byte stack alignment
+  call *%REG_ARG1
+
+
+narch_setjmp:
+  add   $0x10, %REG_ARG1      # 16-byte alignment
+  and   $-0x10, %REG_ARG1
+  mov   %rbx, 0x00(%REG_ARG1) # jmp_buf, move registers onto it
+  mov   %rbp, 0x08(%REG_ARG1)
+  mov   %r12, 0x10(%REG_ARG1)
+  mov   %r13, 0x18(%REG_ARG1)
+  mov   %r14, 0x20(%REG_ARG1)
+  mov   %r15, 0x28(%REG_ARG1)
+  lea   0x08(%rsp), %rdx      # this is our rsp WITHOUT current ret addr
+  mov   %rdx, 0x30(%REG_ARG1)
+  mov   (%rsp), %rdx          # save return addr ptr for new rip
+  mov   %rdx, 0x38(%REG_ARG1)
+  mov   %rsi, 0x40(%REG_ARG1)
+  mov   %rdi, 0x48(%REG_ARG1)
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  movaps %xmm6,  0x50(%REG_ARG1)
+  movaps %xmm7,  0x60(%REG_ARG1)
+  movaps %xmm8,  0x70(%REG_ARG1)
+  movaps %xmm9,  0x80(%REG_ARG1)
+  movaps %xmm10, 0x90(%REG_ARG1)
+  movaps %xmm11, 0xA0(%REG_ARG1)
+  movaps %xmm12, 0xB0(%REG_ARG1)
+  movaps %xmm13, 0xC0(%REG_ARG1)
+  movaps %xmm14, 0xD0(%REG_ARG1)
+  movaps %xmm15, 0xE0(%REG_ARG1)
+#endif
+  xor   %rax, %rax            # always return 0
+  ret
+
+
+narch_longjmp:
+  add   $0x10, %REG_ARG1      # 16-byte alignment
+  and   $-0x10, %REG_ARG1     #
+  mov   %REG_ARG2, %rax       # val will be longjmp return
+  test  %rax, %rax
+  jnz   narch_longjmp_1
+  inc   %rax                  # if val==0, val=1 per longjmp semantics
+narch_longjmp_1:
+  mov   0x00(%REG_ARG1), %rbx # jmp_buf, restore regs from it
+  mov   0x08(%REG_ARG1), %rbp
+  mov   0x10(%REG_ARG1), %r12
+  mov   0x18(%REG_ARG1), %r13
+  mov   0x20(%REG_ARG1), %r14
+  mov   0x28(%REG_ARG1), %r15
+  mov   0x30(%REG_ARG1), %rsp # this ends up being the stack pointer
+  mov   0x38(%REG_ARG1), %rdx # this is the instruction pointer
+  mov   0x40(%REG_ARG1), %rsi
+  mov   0x48(%REG_ARG1), %rdi
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  movaps 0x50(%REG_ARG1), %xmm6
+  movaps 0x60(%REG_ARG1), %xmm7
+  movaps 0x70(%REG_ARG1), %xmm8
+  movaps 0x80(%REG_ARG1), %xmm9
+  movaps 0x90(%REG_ARG1), %xmm10
+  movaps 0xA0(%REG_ARG1), %xmm11
+  movaps 0xB0(%REG_ARG1), %xmm12
+  movaps 0xC0(%REG_ARG1), %xmm13
+  movaps 0xD0(%REG_ARG1), %xmm14
+  movaps 0xE0(%REG_ARG1), %xmm15
+#endif
+  jmp  *%rdx                  # goto saved address without altering rsp
diff --git a/lib/arch/x86/i386.S b/lib/arch/x86/i386.S
new file mode 100644
index 000000000..d7de4a4c3
--- /dev/null
+++ b/lib/arch/x86/i386.S
@@ -0,0 +1,64 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Rokas Kupstys
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+# Partially based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
+
+.globl narch_coroExecWithStack
+.globl narch_setjmp
+.globl narch_longjmp
+#if defined(__MINGW32__) || defined(__MINGW64__)
+.globl @narch_coroExecWithStack@8
+.globl @narch_setjmp@4
+.globl @narch_longjmp@8
+#endif
+.text
+
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+@narch_coroExecWithStack@8:
+#endif
+narch_coroExecWithStack:
+  mov  %edx, %esp            # swap stack with one passed to func
+  sub  $0x10, %esp           # 16-byte alignment
+  and  $-0x10, %esp          #
+  sub  $4, %esp              # Simulate misalignment caused by return addr
+  jmp *%ecx
+
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+@narch_setjmp@4:
+#endif
+narch_setjmp:
+    mov  %ebx, (%ecx)
+    mov  %esi, 0x04(%ecx)
+    mov  %edi, 0x08(%ecx)
+    mov  %ebp, 0x0C(%ecx)
+    lea  0x04(%esp), %eax
+    mov  %eax, 0x10(%ecx)
+    mov  (%esp), %eax
+    mov  %eax, 0x14(%ecx)
+    xor  %eax, %eax
+    ret
+
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+@narch_longjmp@8:
+#endif
+narch_longjmp:
+    mov  %edx, %eax
+    test %eax, %eax
+    jnz  narch_longjmp_1
+    inc  %eax
+narch_longjmp_1:
+    mov  (%ecx), %ebx
+    mov  0x04(%ecx), %esi
+    mov  0x08(%ecx), %edi
+    mov  0x0C(%ecx), %ebp
+    mov  0x10(%ecx), %esp
+    mov  0x14(%ecx), %edx
+    jmp *%edx