diff options
| author | Drahflow <drahflow@gmx.de> | 2013-01-03 22:11:37 +0100 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2013-01-03 22:11:37 +0100 |
| commit | 19d573cf7c6dd729289ef5151f15db51bcc79d91 (patch) | |
| tree | 288980504ab3721cfa7fd0aea59514957c17b45d /compiler | |
| parent | d7d307dc6563fe27bf43cab1e83ac21204fea6c6 (diff) | |
Compiler can now push ints and strings
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/elymasAsm.ey | 277 | ||||
| -rw-r--r-- | compiler/elymasAsmLib.ey | 81 | ||||
| -rw-r--r-- | compiler/elymasGlobal.ey | 93 | ||||
| -rw-r--r-- | compiler/standard.ey | 14 |
4 files changed, 417 insertions, 48 deletions
diff --git a/compiler/elymasAsm.ey b/compiler/elymasAsm.ey index f62f979..f11f950 100644 --- a/compiler/elymasAsm.ey +++ b/compiler/elymasAsm.ey @@ -3,13 +3,6 @@ 16777216 ==STACKSIZE 128 ==STACKSTART - STACKSIZE sys .asm .alloc ==mainStack - - # global stack layout - # 0 - STACKSTART : global variables - # 0 : current stack pointer - # STACKSTART - ...: real stack - # hex decoding { "(.)(.)" regex { } { "not a valid hex-string" die } ? * @@ -25,14 +18,14 @@ { { streq any }_ ==reg [ - [ /al /ax /eax /rax /none ] - [ /cl /cx /ecx /rcx ] - [ /dl /dx /edx /rdx ] - [ /bl /bx /ebx /rbx ] - [ /spl /ah /sp /esp /rsp ] - [ /bpl /ch /bp /ebp /rbp ] - [ /sil /si /esi /rsi ] - [ /dil /di /edi /rdi ] + [ /zero /al /ax /eax /rax /none ] + [ /one /cl /cx /ecx /rcx ] + [ /two /dl /dx /edx /rdx ] + [ /three /bl /bx /ebx /rbx ] + [ /four /spl /ah /sp /esp /rsp ] + [ /five /bpl /ch /bp /ebp /rbp ] + [ /six /sil /si /esi /rsi ] + [ /seven /dil /di /edi /rdi ] [ /r8b /r8w /r8d /r8 ] [ /r9b /r9w /r9d /r9 ] [ /r10b /r10w /r10d /r10 ] @@ -62,26 +55,89 @@ reg regno 8 mul %38 band add } /modrm00 deff - { 8 { _ 256 mod -01 256 div } rep -- } /imm64 deff - { 4 { _ 256 mod -01 256 div } rep -- } /imm32 deff - { 2 { _ 256 mod -01 256 div } rep -- } /imm16 deff - { } /imm8 deff + { =mem =reg + %C0 + mem regno %07 band add + reg regno 8 mul %38 band add + } /modrm11 deff + + { _ 0 ge assert 8 { _ 256 mod -01 256 div } rep -- } /imm64 deff + { _ 0 ge assert 4 { _ 256 mod -01 256 div } rep -- } /imm32 deff + { _ 0 ge assert 2 { _ 256 mod -01 256 div } rep -- } /imm16 deff + { _ 0 ge assert 255 band } /imm8 deff # instructions { ==reg ==i reg bit64 assert + i 256 lt assert + + 1 /none /none reg rex + %83 + /zero reg modrm11 + i imm8 + } /addqImm8Reg deff + + { ==dst ==src + dst bit64 assert + src bit64 assert + + 1 src /none dst rex + %01 + src dst modrm11 + } /addqRegReg deff + + { ==reg + reg bit64 assert + + reg regno %07 gt { 1 /none /none reg rex } rep + %FF + /two reg modrm11 + } /callqReg deff + + { ==dst ==src + dst bit64 assert + src bit64 assert + + 1 src /none dst rex + %39 + src dst modrm11 + } /cmpqRegReg deff + + { ==offset + offset 128 lt assert + + %76 + offset imm8 + } /jbeRel8 deff + + { ==offset + offset 128 lt assert + + %7E + offset imm8 + } /jleRel8 deff + + { ==reg ==i + reg bit64 assert 1 /none /none reg rex %B8 reg regno %07 band add i imm64 } /movqImmReg deff + { ==reg + reg bit64 assert + + 1 /none /none reg rex + %B8 reg regno %07 band add + } /movqImmOOBReg deff + { ==reg ==mem reg bit64 assert mem bit64 assert 1 reg /none mem rex - %89 + %8B reg mem modrm00 } /movqMemReg deff @@ -90,42 +146,195 @@ mem bit64 assert 1 reg /none mem rex - %8B + %89 reg mem modrm00 } /movqRegMem deff - { =reg + { ==dst ==src + src bit64 assert + dst bit64 assert + + 1 src /none dst rex + %89 + src dst modrm11 + } /movqRegReg deff + + { ==mem ==i + mem bit64 assert + i 256 lt assert + + %80 + /one mem modrm00 + i imm8 + } /orbImmMem64 deff + + { ==reg reg regno %07 gt { 1 /none /none reg rex } rep %58 reg regno %07 band add - } /popq deff + } /popqReg deff - { =reg + { ==reg reg regno %07 gt { 1 /none /none reg rex } rep %50 reg regno %07 band add - } /pushq deff + } /pushqReg deff + + { ==imm + %68 + imm imm32 + } /pushqImm32 deff { %C3 } /retn deff + { ==dst ==src + dst bit64 assert + src bit64 assert + + 1 src /none dst rex + %29 + src dst modrm11 + } /subqRegReg deff + + { + %0F %05 + } /syscall deff + + { ==reg ==mem + reg bit64 assert + mem bit64 assert + + 1 reg /none mem rex + %33 + reg mem modrm00 + } /xorqMemReg deff + + { ==mem ==reg + reg bit64 assert + mem bit64 assert + + 1 reg /none mem rex + %31 + reg mem modrm00 + } /xorqRegMem deff + + { ==dst ==src + dst bit64 assert + src bit64 assert + + 1 src /none dst rex + %31 + src dst modrm11 + } /xorqRegReg deff + + # data manipulation functions + { # ==addr + [ -01 8 { _ sys .asm .peek -01 1 add } rep -- ] reverse { -01 256 mul add } fold + } /peekImm64 deff + + { # ==addr + [ -01 4 { _ sys .asm .peek -01 1 add } rep -- ] reverse { -01 256 mul add } fold + } /peekImm32 deff + + # global stack layout + # 0 - STACKSTART : global variables + # %0 : current stack pointer + # %8 : current scope + # %10 : currently quoted + # STACKSTART - ...: real stack + STACKSIZE sys .asm .alloc ==mainStack + < + mainStack .base ==i + [ + mainStack .base STACKSIZE add imm64 + ] { i sys .asm .poke i 1 add =i } each + > -- + + { + [ -01 16 { _ 16 mod -01 16 div } rep -- ] + [ /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /B /C /D /E /F ] * + reverse |cat fold + } /base16encode64 deff + + { + [ -01 8 { _ 16 mod -01 16 div } rep -- ] + [ /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /B /C /D /E /F ] * + reverse |cat fold + } /base16encode32 deff + + < + [ + 32 { "." } rep + " " "!" "\"" "#" "$" "%" "&" "ยด" "(" ")" "*" "+" "," "-" "." "/" + /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 ":" ";" "<" "=" ">" "?" + "@" /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P + /Q /R /S /T /U /V /W /X /Y /Z "[" "\\" "]" "^" "_" + "`" /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p + /q /r /s /t /u /v /w /x /y /z "{" "|" "}" "~" "." + 128 { "." } rep + ] /ASCII defv + + { + mainStack .base STACKSIZE add ==stackEnd + "Stack ------------\n" sys .out .writestr + mainStack .base peekImm64 ==addr + addr stackEnd gt { [ -01 stackEnd ] die } rep # Stack corrupted + + { addr stackEnd lt } { + [ + addr base16encode64 ": " + addr peekImm64 ==value + value base16encode64 + value 105553116266496 ge value 123145302310912 lt and { + value peekImm32 + value 4 add peekImm32 16777215 band 4294967296 mul + add 8 div ==length + 0 length 1 sub range { + 8 mul value add ==heapAddr + "\n " + heapAddr base16encode64 + ": " + # the perl interpreter does not like full 64bit numbers and converts them into floats + heapAddr 4 add peekImm32 _ ==heapValueB base16encode32 + heapAddr peekImm32 _ ==heapValueA base16encode32 + " " + [ [ heapValueA heapValueB ] { 4 { _ 256 mod -01 256 div } rep -- } each ] ASCII * 8 dearray + } each + } rep + "\n" + ] |cat fold sys .out .writestr + addr 8 add =addr + } loop + "^^^^^^^^^^^^^^^^^^\n" sys .out .writestr + } + > -- /stackDump deff + + { ==opcodes + opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv + codearea .base ==i + opcodes { i sys .asm .poke i 1 add =i } each + codearea + } /arrayToCode deff + # take an array of instruction bytes and execute it on the given stack { ==stack ==opcodes [ - /rbx pushq + /rbx pushqReg stack /rbx movqImmReg - /rbx /rsp movqMemReg + /rbx /rsp xorqMemReg + /rsp /rbx xorqRegMem + /rbx /rsp xorqMemReg ] opcodes [ stack /rbx movqImmReg - /rsp /rbx movqRegMem - /rbx popq + /rbx /rsp xorqMemReg + /rsp /rbx xorqRegMem + /rbx /rsp xorqMemReg + /rbx popqReg retn ] cat cat =opcodes - opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv - codearea .base ==i - opcodes { i sys .asm .poke i 1 add =i } each - codearea .base sys .asm .execute - codearea .free + opcodes arrayToCode _ .base sys .asm .execute + .free } /executeOn deff { mainStack .base executeOn } /execute deff diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey new file mode 100644 index 0000000..341c07a --- /dev/null +++ b/compiler/elymasAsmLib.ey @@ -0,0 +1,81 @@ +"elymasAsm.ey" include + +< + { assembler -01 . } ":" deff + "%" _ : -01 deff + + < + 1 ==PROT_READ + 2 ==PROT_WRITE + 4 ==PROT_EXEC + + 2 ==MAP_PRIVATE + 16 ==MAP_FIXED + 32 ==MAP_ANONYMOUS + > ==MMAP + + < + 9 ==mmap + > ==SYSCALL + + { =*def ==struct + struct values |cat fold :arrayToCode .base ==address + struct keys { address -101 def struct -01 . len address add =address } each + } /allocateOffsetStruct deff + + # global data + < + # current end of heap memory (grows upwards) + [ %00 %00 %00 %00 %00 %60 %00 %00 ] ==heapEnd + + # next free byte at end of heap + [ %00 %00 %00 %00 %00 %60 %00 %00 ] ==unusedHeapStart + > { defv }' allocateOffsetStruct + + # internal functions, ABI follows SysV standards + + < + # allocate a chunk of memory + # rdi -> size of chunk in bytes + # 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 + /rax /rcx :movqMemReg + /rcx /rbx :movqRegReg + /rcx /rdx :movqRegReg + /rdi /rcx :addqRegReg + /rcx /rax :movqRegMem + 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 + /rbx /rax :movqRegReg + /rdi :popqReg + /rdi /rax :movqRegMem + /rbx :popqReg + :retn + ] /internalAllocate defv + > { defv }' allocateOffsetStruct +> /assemblerLibrary defv + +# vim: syn=elymas diff --git a/compiler/elymasGlobal.ey b/compiler/elymasGlobal.ey index c339ede..6a92f50 100644 --- a/compiler/elymasGlobal.ey +++ b/compiler/elymasGlobal.ey @@ -1,13 +1,89 @@ -"elymasAsm.ey" include +"elymasAsmLib.ey" include -0 /TOKINT defv -1 /TOKSTR defv -2 /TOKID defv +< + [ /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 ] ==digits + + { 0 ==result + { "(.)(.*)" regex } { + { streq }_ digits -01 index result 10 mul add =result + } loop + result + } +> -- /base10decode deff + +< + { assembler -01 . } ":" deff + { assemblerLibrary -01 . } "::" deff + "%" _ : -01 deff + + { .value base10decode ==v + [ + # allocate int + 16 /rdi :movqImmReg + ::internalAllocate /rax :movqImmReg + /rax :callqReg + + # push int address on program stack + /rax :pushqReg + + # type zero does not need to be changed + + # load value + 8 /rax :addqImm8Reg + v /rdx :movqImmReg + /rdx /rax :movqRegMem + ] :execute + } /TOKINT + + { .value strToUTF8Bytes _ =*v len _ ==exactLength + 1 sub 8 div 4 add 8 mul ==memoryLength + + memoryLength 2147483648 lt assert + + [ + # allocate string + memoryLength /rdi :movqImmReg + ::internalAllocate /rax :movqImmReg + /rax :callqReg + + # push string address on program stack + /rax :pushqReg + + # set type + 7 /rax :addqImm8Reg + %10 /rax :orbImmMem64 + + # clear hash value + 1 /rax :addqImm8Reg + /rdx /rdx :xorqRegReg + /rdx /rax :movqRegMem + + # load exact length + 8 /rax :addqImm8Reg + exactLength /rdx :movqImmReg + /rdx /rax :movqRegMem + + # load string contents + 0 exactLength 8 div range { 8 mul ==i + 8 /rax :addqImm8Reg + /rdx :movqImmOOBReg i _ 7 add range v 8 dearray + /rdx /rax :movqRegMem + } each + ] :execute + } /TOKSTR -1010 deff + + { ==token + # string value + token TOKSTR + # scope resolution + # FIXME + } /TOKID +> -- 3 |defv rep { /f deff -101 /s defv regex { f } { s } ? * } /rxparse deff { " " cat - { < /type defv /value defv > } /token deff + { < /handle deff /value defv > } /token deff [ -01 { _ "" streq not } { 0 /matched defv { /f deff matched { -- } { { 1 =matched f } rxparse } ? * } /parse deff @@ -34,17 +110,12 @@ } loop -- ] } /tokenize deff -{ - dump - [ ] assembler .execute -} /interpretToken deff - { /input defv "" { 4096 input .readstr cat _ "" streq not } { - { _ "([^\\n]*)\\n(.*)" regex } { -102 -- tokenize |interpretToken each } loop + { _ "([^\\n]*)\\n(.*)" regex } { -102 -- tokenize { _ .handle assembler .stackDump } each } loop } loop } /executeFile deff diff --git a/compiler/standard.ey b/compiler/standard.ey index 0d96431..7df61f3 100644 --- a/compiler/standard.ey +++ b/compiler/standard.ey @@ -7,14 +7,18 @@ } quoted { } { * } ? * } "}_" defq -{ ==f _ ==a len ==l +{ =*f _ =*a len ==l l { - 0 a * - 1 l 1 sub range { a * f * } each + 0 a + 1 l 1 sub range { a f } each } { "fold on empty array" die } ? * } /fold deff +{ _ =*a len ==l + [ 1 l range { l -01 sub a } each ] +} /reverse deff + { |or fold } /any deff { |and fold } /all deff @@ -41,4 +45,8 @@ not { "Assertion failure" die } rep } /assert deff +{ ==s + [ s keys { s -01 . } each ] +} /values deff + # vim: syn=elymas |
