diff options
| -rw-r--r-- | compiler/elymasAsm.ey | 67 | ||||
| -rw-r--r-- | compiler/elymasAsmLib.ey | 55 | ||||
| -rw-r--r-- | compiler/elymasGlobalSysAsm.ey | 123 | ||||
| -rw-r--r-- | compiler/standardClient.ey | 175 | ||||
| -rw-r--r-- | examples/working-compiler/freeze.test | 1 |
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 + < + ".[1;31m-[33m=[32m#[34m=[35m-[0m" ==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 |
