aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/elymasAsm.ey67
-rw-r--r--compiler/elymasAsmLib.ey55
-rw-r--r--compiler/elymasGlobalSysAsm.ey123
-rw-r--r--compiler/standardClient.ey175
-rw-r--r--examples/working-compiler/freeze.test1
5 files changed, 333 insertions, 88 deletions
diff --git a/compiler/elymasAsm.ey b/compiler/elymasAsm.ey
index 3c6944e..f768e0b 100644
--- a/compiler/elymasAsm.ey
+++ b/compiler/elymasAsm.ey
@@ -1,6 +1,7 @@
<
4096 ==PAGESIZE
16777216 ==STACKSIZE
+ 65536 ==GLOBALALLOCSSIZE
128 ==STACKSTART
# hex decoding
@@ -215,6 +216,15 @@
i imm8
} /addqImm8Reg deff
+ { ==reg ==mem
+ reg bit64assert
+ mem bit64assert
+
+ 1 reg /none mem rex
+ %03
+ reg mem modrm00
+ } /addqMemReg deff
+
{ ==reg ==mem ==disp
reg bit64assert
mem bit64assert
@@ -728,6 +738,18 @@
1 idx mem sib
} /movqMemIndexReg deff
+ { ==reg ==mem ==idx ==scale ==disp
+ reg bit64assert
+ mem bit64assert
+ idx bit64assert
+
+ 1 reg idx mem rex
+ %8B
+ reg /sib modrm01
+ scale idx mem sib
+ disp imm8
+ } /movqMemIndexScaleDisp8Reg deff
+
{ ==reg ==mem
reg bit64assert
mem bit64assert
@@ -1122,14 +1144,52 @@
src dst modrm11
} /xorqRegReg deff
+ # global alloc list layout
+ # %0 : next unused byte of global alloc list as an offset from beginning of list
+ # %8 : <unused>
+ # %10 : base of this very alloc
+ # %18 : size of this very alloc
+ # %20... : <base> <size> of next allocs
+ <
+ { # ==addr
+ [ -01 7 add 8 { _ sys .asm .peek -01 1 sub } rep -- ] { -01 256 mul add } fold
+ } /peekImm64 deff
+
+ { ==addr ==value
+ [ value imm64 ] { addr sys .asm .poke addr 1 add =addr } each
+ } /pokeImm64 deff
+
+ GLOBALALLOCSSIZE sys .asm .alloc ==allocs
+ allocs .base ==i
+ [
+ %20 imm64
+ 0 imm64
+ allocs .base imm64
+ allocs .size imm64
+ ] { i sys .asm .poke i 1 add =i } each
+
+ { ==block
+ allocs .base peekImm64 ==nextOffset
+ nextOffset 16 add _
+ GLOBALALLOCSSIZE gt { "Global allocation list full." die } rep
+ allocs .base pokeImm64
+ allocs .base nextOffset add =nextOffset
+
+ block .base nextOffset pokeImm64
+ block .size nextOffset 8 add pokeImm64
+ } /register deff
+
+ { allocs .base } /base deff
+ > ==globalAllocations
+
# global stack layout
# 0 - STACKSTART : global variables
# %0 : current stack pointer
# STACKSTART - ...: real stack
[ /mainStack /mainCallStack ] {
<
- STACKSIZE sys .asm .alloc ==stack
-
+ STACKSIZE sys .asm .alloc _ globalAllocations .register
+ ==stack
stack .base ==i
[
stack .base STACKSIZE add imm64
@@ -1139,7 +1199,8 @@
> -12 ==
}' each
- STACKSIZE sys .asm .alloc .base ==quoteEncodingBuffer
+ STACKSIZE sys .asm .alloc _ globalAllocations .register
+ .base ==quoteEncodingBuffer
{ ==opcodes
opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv
diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey
index 40b83c8..5ae42f2 100644
--- a/compiler/elymasAsmLib.ey
+++ b/compiler/elymasAsmLib.ey
@@ -20,7 +20,8 @@
> ==SYSCALL
{ =*def ==struct
- struct values |cat fold :arrayToCode .base ==address
+ struct values |cat fold :arrayToCode _ :globalAllocations .register
+ .base ==address
struct keys { address -101 def struct -01 . len address add =address } each
} /allocateOffsetStruct deff
@@ -88,6 +89,9 @@
# current parser quote state
[ %00 %00 %00 %00 %00 %00 %00 %00 ] ==currentQuoted
+
+ # global allocation list
+ [ :globalAllocations .base :imm64 ] ==globalAllocationList
> { defv }' allocateOffsetStruct
{ _ =*array len _ 4 div ==largeMoves
@@ -142,7 +146,7 @@
# rax <- address of allocated chunk
# chunk will have GC length header initialized correctly
# FIXME put a real allocator here
- [
+ [[
/rbx :pushqReg
/rdi :pushqReg
unusedHeapStart /rax :movqImmReg
@@ -154,29 +158,40 @@
heapEnd /rax :movqImmReg
/rax /rdi :movqMemReg
/rdi /rcx :cmpqRegReg
- [
- 4096 4096 mul /rsi :movqImmReg
- /rsi /rdi :addqRegReg
- /rdi /rax :movqRegMem
- /rsi /rdi :subqRegReg
-
- SYSCALL .mmap /rax :movqImmReg
- # /rdi already fine
- # /rsi already fine
- < { MMAP -01 . } "!" deff
- !PROT_READ !PROT_WRITE !PROT_EXEC bor bor /rdx :movqImmReg
- !MAP_PRIVATE !MAP_FIXED !MAP_ANONYMOUS bor bor /r10 :movqImmReg
- > --
- /r8 :movqImmOOBReg %FF %FF %FF %FF %FF %FF %FF %FF
- 0 /r9 :movqImmReg
- :syscall
- ] |len { :jbeRel8 } -21*0*221* dearray # FIXME move to labelResolve
+ /memAvailable :jbeLbl8
+
+ 4096 4096 mul /rsi :movqImmReg # size of new block
+ /rsi /rdi :addqRegReg
+ /rdi /rax :movqRegMem
+ /rsi /rdi :subqRegReg
+
+ # record new block in global allocation list
+ globalAllocationList /rax :movqImmReg
+ /rax /rax :movqMemReg
+ 16 /rax :addqImm8Mem
+ /rax /rax :addqMemReg
+ 16 /rax :subqImm8Reg
+ /rdi /rax :movqRegMem
+ /rsi 8 /rax :movqRegMemDisp8
+
+ SYSCALL .mmap /rax :movqImmReg
+ # /rdi already fine
+ # /rsi already fine
+ < { MMAP -01 . } "!" deff
+ !PROT_READ !PROT_WRITE !PROT_EXEC bor bor /rdx :movqImmReg
+ !MAP_PRIVATE !MAP_FIXED !MAP_ANONYMOUS bor bor /r10 :movqImmReg
+ > --
+ /r8 :movqImmOOBReg %FF %FF %FF %FF %FF %FF %FF %FF
+ 0 /r9 :movqImmReg
+ :syscall
+
+ @memAvailable
/rbx /rax :movqRegReg
/rdi :popqReg
/rdi /rax :movqRegMem
/rbx :popqReg
:retn
- ] /internalAllocate defv
+ ]] /internalAllocate defv
# compare two strings
# rdi -> address of first string
diff --git a/compiler/elymasGlobalSysAsm.ey b/compiler/elymasGlobalSysAsm.ey
index c24ef5e..cc1ec43 100644
--- a/compiler/elymasGlobalSysAsm.ey
+++ b/compiler/elymasGlobalSysAsm.ey
@@ -110,12 +110,135 @@
8 /r15 :addqImm8Reg
:retn
]] /eysyscall defv
+
+ # returns the number of allocations in the global allocation list
+ # 0 <- number of allocations registered
+ [[
+ /rbx :popqReg
+ # allocate return integer
+ 16 /rdi :movqImmReg
+ ::internalAllocate /rax :movqImmReg
+ /rax :callqReg
+ /rax :pushqReg
+
+ ::globalAllocationList /rdx :movqImmReg
+ /rdx /rdx :movqMemReg
+ /rdx /rdx :movqMemReg
+ 4 /rdx :shrqImm8Reg
+ /rdx :decqReg
+ /rdx 8 /rax :movqRegMemDisp8
+
+ /rbx :pushqReg
+ :retn
+ ]] /eyglobalAllocCount defv
+
+ # returns the base address of a global allocation
+ # 0 -> number of allocation
+ # 0 <- allocation base address
+ [[
+ /rbx :popqReg
+
+ # allocate return integer
+ 16 /rdi :movqImmReg
+ ::internalAllocate /rax :movqImmReg
+ /rax :callqReg
+
+ /rcx :popqReg
+ /rax :pushqReg
+
+ 8 /rcx /rcx :movqMemDisp8Reg
+
+ ::globalAllocationList /rdx :movqImmReg
+ /rdx /rdx :movqMemReg
+ /rcx :incqReg
+ 4 /rcx :shlqImm8Reg
+
+ /rcx /rdx /rdx :movqMemIndexReg
+ /rdx 8 /rax :movqRegMemDisp8
+
+ /rbx :pushqReg
+ :retn
+ ]] /eyglobalAllocBase defv
+
+ # returns the size of a global allocation
+ # 0 -> number of allocation
+ # 0 <- allocation size
+ [[
+ /rbx :popqReg
+
+ # allocate return integer
+ 16 /rdi :movqImmReg
+ ::internalAllocate /rax :movqImmReg
+ /rax :callqReg
+
+ /rcx :popqReg
+ /rax :pushqReg
+
+ 8 /rcx /rcx :movqMemDisp8Reg
+
+ ::globalAllocationList /rdx :movqImmReg
+ /rdx /rdx :movqMemReg
+ /rcx :incqReg
+ 4 /rcx :shlqImm8Reg
+
+ 8 1 /rcx /rdx /rdx :movqMemIndexScaleDisp8Reg
+ /rdx 8 /rax :movqRegMemDisp8
+
+ /rbx :pushqReg
+ :retn
+ ]] /eyglobalAllocSize defv
+
+ # get raw code execution address from function object
+ # 0 -> function object
+ # 0 <- address of first instruction
+ [[
+ /rbx :popqReg
+
+ # allocate return integer
+ 16 /rdi :movqImmReg
+ ::internalAllocate /rax :movqImmReg
+ /rax :callqReg
+
+ /rdx :popqReg
+ 24 /rdx /rdx :movqMemDisp8Reg
+ 8 /rdx :addqImm8Reg
+ /rdx 8 /rax :movqRegMemDisp8
+
+ /rax :pushqReg
+ /rbx :pushqReg
+ :retn
+ ]] /eyrawCodeAddress defv
+
+ # (template) program boot sequence after freeze
+ [[
+ /rsp :movqImmOOBReg %EE %EE %EE %EE %EE %EE %EE %EE
+ /r15 :movqImmOOBReg %EE %EE %EE %EE %EE %EE %EE %EE
+
+ |ey* /rax :movqImmReg
+ /rax :callqReg
+ :ud2
+ ]] /eyprogramStart defv
> _ ==globalFunctions { defv }' ::allocateOffsetStruct
+ <
+ # patch programStart to current program state
+ [[
+ /rbx :popqReg
+
+ eyprogramStart /rax :movqImmReg
+ /rsp 2 /rax :movqRegMemDisp8
+ /r15 12 /rax :movqRegMemDisp8
+
+ /rbx :pushqReg
+ :retn
+ ]] /eypatchProgramStart defv
+ > _ ==globalFunctions2 { defv }' ::allocateOffsetStruct
+
"asm" enterSubScope
[
globalFunctions keys eydeff { | }' createScopeEntries
+ globalFunctions2 keys eydeff { | }' createScopeEntries
createScopeExtensionEntries
] :execute
diff --git a/compiler/standardClient.ey b/compiler/standardClient.ey
index ca40c00..01d04a5 100644
--- a/compiler/standardClient.ey
+++ b/compiler/standardClient.ey
@@ -23,6 +23,12 @@
9 ==MMAP
11 ==MUNMAP
+ 60 ==EXIT
+
+ { ==code
+ code 0 0 0 0 0 0 EXIT sys .asm .syscall
+ "exit failed" die
+ } /exit sys .deff
{ < ==mode ==flags ==fd <
{ flags RWMASK bnot band RDONLY bor =flags } /readonly deff
@@ -711,7 +717,9 @@
#
# { enregex * } /regex deff
-{ ==filename ==f
+{ ==filename # ==f (left on the stack and executed from sys .asm .programStart)
+ sys .asm .patchProgramStart
+
# hex decoding
{ ==strNumber
strNumber len 2 neq { "not a valid hex-string" die } rep
@@ -723,6 +731,10 @@
{ _ 0 lt { 65536 add } rep 65535 band 2 { _ 256 mod -01 256 div } rep -- } /uint16 deff
{ _ 0 lt { 256 add } rep 255 band } /uint8 deff
+ { ==align ==value
+ align value align mod sub align mod
+ } /alignUpto deff
+
sys .file ==out
filename out _ .creating _ .writeonly .open
@@ -737,6 +749,7 @@
0 ==link # no associated section
0 ==entsize # no entries
[ ] ==data
+ 0 ==dataSize
> <
".strtab" ==name
0 ==nameOffset { =nameOffset } /setNameOffset deff
@@ -747,38 +760,59 @@
0 ==link # no associated section
0 ==entsize # no entries
[ ] ==data # to be filled later
- { =data } /setData deff
+ 0 ==dataSize # to be filled later
+ { _ =data len =dataSize } /setData deff
> _ ==stringTable
- ] ==sections
+ ] ==metaSections
- {
- ### program header
- # Elf64_Word p_type; /* Type of segment */
- # Elf64_Word p_flags; /* Segment attributes */
- # Elf64_Off p_offset; /* Offset in file */
- # Elf64_Addr p_vaddr; /* Virtual address in memory */
- # Elf64_Addr p_paddr; /* Reserved */
- # Elf64_Xword p_filesz; /* Size of segment in file */
- # Elf64_Xword p_memsz; /* Size of segment in memory */
- # Elf64_Xword p_align; /* Alignment of segment */
-
- # p_type
- %01 %00 %00 %00 # loadable segment
- # p_flags
- %07 %00 %00 %00 # read | write | execute
- # p_offset
- %EE %EE %EE %EE %EE %EE %EE %EE # offset in file
- # p_vaddr
- %EE %EE %EE %EE %EE %EE %EE %EE # virtual addr in memory
- # p_paddr
- %00 %00 %00 %00 %00 %00 %00 %00 # reserved
- # p_filesz
- %EE %EE %EE %EE %EE %EE %EE %EE # size of segment in file
- # p_memsz
- %EE %EE %EE %EE %EE %EE %EE %EE # size of segment in memory
- # p_align
- %10 %00 %00 %00 %00 %00 %00 %00 # alignment
- } /programHeader deff
+ [
+ 0 sys .asm .globalAllocCount 1 sub range { ==i
+ <
+ ".-=#=-" ==name
+ 0 ==nameOffset { =nameOffset } /setNameOffset deff
+ 0 ==dataOffset { =dataOffset } /setDataOffset deff
+ 1 ==type # program data
+ 7 ==flags # writable, allocated, executable
+ 0 ==addr # FIXME
+ 0 ==link # no associated section
+ 0 ==entsize # no entries
+ i sys .asm .globalAllocBase ==dataBase
+ i sys .asm .globalAllocSize ==dataSize
+ >
+ } each
+ ] ==allocSections
+
+ 4096 ==PAGESIZE
+
+ < 1 ==nameOffset
+ [
+ %00 # initial zero byte of string table
+ ### section names
+
+ [ metaSections allocSections ] { { ==s
+ s .name ==n
+ 0 n len 1 sub range { n * } each %00
+ nameOffset s .setNameOffset
+ nameOffset n len add 1 add =nameOffset
+ } each } each
+ ] stringTable .setData
+ > -- <
+ # %40 == section header size, %38 == program header size
+ metaSections len allocSections len add %40 mul
+ allocSections len %38 mul add
+ %40 add ==dataOffset
+ metaSections { ==s
+ dataOffset s .setDataOffset
+ dataOffset s .dataSize add =dataOffset
+ } each
+
+ dataOffset _ 4096 alignUpto add =dataOffset
+
+ allocSections { ==s
+ dataOffset s .setDataOffset
+ dataOffset s .dataSize add _ PAGESIZE alignUpto add =dataOffset
+ } each
+ > --
[
### elf header
@@ -796,48 +830,28 @@
# Elf64_Word e_version; /* Object file version */
%01 %00 %00 %00 # always 1
# Elf64_Addr e_entry; /* Entry point address */
- %EE %EE %EE %EE %EE %EE %EE %EE # virtual address entry point
+ sys .asm .|programStart sys .asm .rawCodeAddress uint64
# Elf64_Off e_phoff; /* Program header offset */
- sections len %40 mul %40 add uint64
+ metaSections len allocSections len add %40 mul
+ %40 add uint64
# Elf64_Off e_shoff; /* Section header offset */
%40 uint64
# Elf64_Word e_flags; /* Processor-specific flags */
- %00 %00 %00 %00 # processor specific flags (from /bin/ls)
+ %00 %00 %00 %00 # taken from from /bin/ls
# Elf64_Half e_ehsize; /* ELF header size */
- %40 %00 # header size
+ %40 %00
# Elf64_Half e_phentsize; /* Size of program header entry */
- %38 %00 # program header entry size
+ %38 %00
# Elf64_Half e_phnum; /* Number of program header entries */
- %01 %00 # program header entry count
+ allocSections len uint16
# Elf64_Half e_shentsize; /* Size of section header entry */
- %40 %00 # section header entry size
+ %40 %00
# Elf64_Half e_shnum; /* Number of section header entries */
- %02 %00 # section header count
+ metaSections len allocSections len add uint16
# Elf64_Half e_shstrndx; /* Section name string table index */
%01 %00 # section header name table index in section headers table
- < 1 ==nameOffset
- [
- %00 # initial zero byte of string table
- ### section names
-
- sections { ==s
- s .name ==n
- 0 n len 1 sub range { n * } each %00
- nameOffset s .setNameOffset
- nameOffset n len add 1 add =nameOffset
- } each
- ] stringTable .setData
- > -- <
- # %40 == section header size, %38 == program header size
- sections len %40 mul %78 add ==dataOffset
- sections { ==s
- dataOffset s .setDataOffset
- dataOffset s .data len add =dataOffset
- } each
- > --
-
- sections { ==s
+ [ metaSections allocSections ] { { ==s
### section header
# Elf64_Word sh_name; /* Section name */
s .nameOffset uint32
@@ -850,7 +864,7 @@
# Elf64_Off sh_offset; /* Offset in file */
s .dataOffset uint64
# Elf64_Xword sh_size; /* Size of section */
- s .data len uint64
+ s .dataSize uint64
# Elf64_Word sh_link; /* Link to other section */
s .link uint32
# Elf64_Word sh_info; /* Miscellaneous information */
@@ -859,15 +873,46 @@
1 uint64
# Elf64_Xword sh_entsize; /* Size of entries, if section has table */
0 uint64
+ } each } each
+
+ allocSections { ==s
+ ### program header
+ # Elf64_Word p_type; /* Type of segment */
+ %01 %00 %00 %00 # loadable segment
+ # Elf64_Word p_flags; /* Segment attributes */
+ %07 %00 %00 %00 # read | write | execute
+ # Elf64_Off p_offset; /* Offset in file */
+ s .dataOffset uint64
+ # Elf64_Addr p_vaddr; /* Virtual address in memory */
+ s .dataBase uint64
+ # Elf64_Addr p_paddr; /* Reserved */
+ %00 %00 %00 %00 %00 %00 %00 %00
+ # Elf64_Xword p_filesz; /* Size of segment in file */
+ s .dataSize uint64
+ # Elf64_Xword p_memsz; /* Size of segment in memory */
+ s .dataSize uint64
+ # Elf64_Xword p_align; /* Alignment of segment */
+ %01 %00 %00 %00 %00 %00 %00 %00 # alignment
} each
-
- programHeader
- ] sections { .data cat } each ==fileData
+ ] metaSections { .data cat } each ==fileData
fileData len str .alloc ==buffer
0 fileData len 1 sub range { ==i i fileData * i buffer =[] } each
buffer out .writeall
+
+ 1 ==WRITE
+
+ buffer len ==fileOffset
+
+ allocSections { ==section
+ section .dataOffset fileOffset sub str .alloc out .writeall
+ section .dataOffset section .dataSize add =fileOffset
+
+ out .fd section .dataBase section .dataSize 0 0 0 WRITE sys .asm .syscall --
+ section .dataSize neq { "write failed" die } rep
+ } each
+
out .close
} /freeze sys .deff
diff --git a/examples/working-compiler/freeze.test b/examples/working-compiler/freeze.test
new file mode 100644
index 0000000..580e0d6
--- /dev/null
+++ b/examples/working-compiler/freeze.test
@@ -0,0 +1 @@
+{ "Hallo Welt" dump 0 sys .exit } "frozen" sys .freeze