aboutsummaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-01-03 22:11:37 +0100
committerDrahflow <drahflow@gmx.de>2013-01-03 22:11:37 +0100
commit19d573cf7c6dd729289ef5151f15db51bcc79d91 (patch)
tree288980504ab3721cfa7fd0aea59514957c17b45d /compiler
parentd7d307dc6563fe27bf43cab1e83ac21204fea6c6 (diff)
Compiler can now push ints and strings
Diffstat (limited to 'compiler')
-rw-r--r--compiler/elymasAsm.ey277
-rw-r--r--compiler/elymasAsmLib.ey81
-rw-r--r--compiler/elymasGlobal.ey93
-rw-r--r--compiler/standard.ey14
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