aboutsummaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-02-06 00:02:28 +0100
committerDrahflow <drahflow@gmx.de>2013-02-06 00:02:28 +0100
commit4f9ab0adc677045612c3199f3be04cdcfd32a42a (patch)
treead210bc95f17e167797f968ff8992241fa1fcf44 /compiler
parent199c2079370634675f9d3d7f366ea258c0cae890 (diff)
Typed functions now executing (a little)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/elymasAsm.ey41
-rw-r--r--compiler/elymasAsmLib.ey16
-rw-r--r--compiler/elymasGlobal.ey280
3 files changed, 245 insertions, 92 deletions
diff --git a/compiler/elymasAsm.ey b/compiler/elymasAsm.ey
index bf55a51..974f1ce 100644
--- a/compiler/elymasAsm.ey
+++ b/compiler/elymasAsm.ey
@@ -29,7 +29,7 @@
[ /two /dl /dx /edx /rdx ] { 2 -01 defv }' each
[ /three /bl /bx /ebx /rbx ] { 3 -01 defv }' each
[ /four /sib /spl /ah /sp /esp /rsp ] { 4 -01 defv }' each
- [ /five /bpl /ch /bp /ebp /rbp ] { 5 -01 defv }' each
+ [ /five /bpl /bp /ebp /rbp ] { 5 -01 defv }' each
[ /six /sil /si /esi /rsi ] { 6 -01 defv }' each
[ /seven /dil /di /edi /rdi ] { 7 -01 defv }' each
[ /r8b /r8w /r8d /r8 ] { 8 -01 defv }' each
@@ -44,6 +44,14 @@
{ regnoTable -01 . } /regno deff
+ <
+ [ /al /cl /dl /bl ] { 0 -01 defv }' each
+ [ /spl /bpl /sil /dil ] { 1 -01 defv }' each
+ [ /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each
+ > ==rexreqbyteTable
+
+ { rexreqbyteTable -01 . } /rexreqbyte deff
+
# encoding a REX prefix
{ # ==b ==x ==r ==w
%40
@@ -160,8 +168,8 @@
opcode
lbl labelRel8
- _ 128 neg ge assert
- _ 128 lt assert
+ _ 128 neg ge not { lbl " out of Lbl8 reach" cat die } rep
+ _ 128 lt not { lbl " out of Lbl8 reach" cat die } rep
} name "Lbl8" cat
> -- 2 |deff rep
}' /defJmpRel8 deff
@@ -231,7 +239,7 @@
reg bit8assert
i 256 lt assert
- reg regno %07 gt { 0 /none /none reg rex } rep
+ reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep
%80
/four reg modrm11
i imm8
@@ -372,12 +380,21 @@
reg bit8assert
i 256 lt assert
- reg regno %07 gt { 0 /none /none reg rex } rep
+ reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep
%80
/seven reg modrm11
i imm8
} /cmpbImmReg deff
+ { ==dst ==src
+ src bit8assert
+ dst bit8assert
+
+ src regno %07 gt dst regno %07 gt src rexreqbyte dst rexreqbyte or or or { 0 src /none dst rex } rep
+ %38
+ src dst modrm11
+ } /cmpbRegReg deff
+
{ ==mem ==reg
reg bit32assert
mem bit64assert
@@ -590,7 +607,7 @@
mem bit64assert
disp 128 lt assert
- reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep
+ reg regno %07 gt reg rexreqbyte mem regno %07 gt or or { 0 reg /none mem rex } rep
%8A
reg mem modrm01
disp imm8
@@ -600,7 +617,7 @@
reg bit8assert
mem bit64assert
- reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep
+ reg regno %07 gt reg rexreqbyte mem regno %07 gt or or { 0 reg /none mem rex } rep
%88
reg mem modrm00
} /movbRegMem deff
@@ -987,6 +1004,16 @@
%0F %05
} /syscall deff
+ { ==reg =i
+ reg bit8assert
+ i 256 lt assert
+
+ reg regno %07 gt { 0 /none /none reg rex } rep
+ %F6
+ /zero reg modrm11
+ i imm8
+ } /testbImmReg deff
+
{ ==dst ==src
dst bit64assert
src bit64assert
diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey
index f1f64a8..6a95ee6 100644
--- a/compiler/elymasAsmLib.ey
+++ b/compiler/elymasAsmLib.ey
@@ -57,6 +57,22 @@
opcodes
} /stringResolve deff
+ [ ] ==linkHoles
+
+ { ==what ==where
+ ] _ len ==offset
+ linkHoles [ { =*resolve
+ [ what resolve :imm64 ] =*bytesToPatch
+ 0 7 range { _ bytesToPatch -01 where resolve offset add add sys .asm .poke } each
+ } ] cat =linkHoles
+ [ -011 len dearray %00 %00 %00 %00 %00 %00 %00 %00
+ } /linkAbs64 deff
+
+ { ==resolve
+ linkHoles { resolve -01 * } each
+ [ ] =linkHoles
+ } /linkResolve deff
+
<
# current end of heap memory (grows upwards)
[ %00 %00 %00 %00 %00 %60 %00 %00 ] ==heapEnd
diff --git a/compiler/elymasGlobal.ey b/compiler/elymasGlobal.ey
index 25b423f..bffa08a 100644
--- a/compiler/elymasGlobal.ey
+++ b/compiler/elymasGlobal.ey
@@ -85,85 +85,6 @@
:retn
]] /ey| defv
- # arithmetic functions on ints
- [ /rcx /rdx :addqRegReg ] makeArith /eyadd defv
- [ /rcx /rdx :subqRegReg ] makeArith /eysub defv
- [ /rcx /rdx :andqRegReg ] makeArith /eyband defv
- [ /rcx /rdx :orqRegReg ] makeArith /eybor defv
- [ /rcx /rdx :xorqRegReg ] makeArith /eybxor defv
-
- [
- /rdi /rdi :xorqRegReg
- 1 /rsi :movqImmReg
- /rdx /rcx :cmpqRegReg
- /rsi /rdx :movqRegReg
- /rdi /rdx :cmovnzqRegReg
- ] makeArith /eyeq defv
- [
- /rdi /rdi :xorqRegReg
- 1 /rsi :movqImmReg
- /rdx /rcx :cmpqRegReg
- /rsi /rdx :movqRegReg
- /rdi /rdx :cmovgeqRegReg
- ] makeArith /eygt defv
- [
- /rdi /rdi :xorqRegReg
- 1 /rsi :movqImmReg
- /rdx /rcx :cmpqRegReg
- /rsi /rdx :movqRegReg
- /rdi /rdx :cmovgqRegReg
- ] makeArith /eyge defv
- [
- /rdi /rdi :xorqRegReg
- 1 /rsi :movqImmReg
- /rdx /rcx :cmpqRegReg
- /rsi /rdx :movqRegReg
- /rdi /rdx :cmovngqRegReg
- ] makeArith /eylt defv
- [
- /rdi /rdi :xorqRegReg
- 1 /rsi :movqImmReg
- /rdx /rcx :cmpqRegReg
- /rsi /rdx :movqRegReg
- /rdi /rdx :cmovngeqRegReg
- ] makeArith /eyle defv
-
- [
- /rax :pushqReg
- /rcx /rax :movqRegReg
- /rdx :mulqReg
- /rax /rdx :movqRegReg
- /rax :popqReg
- ] makeArith /eymul defv
- [
- /rax :pushqReg
- /rdx /rax :movqRegReg
- /rdx /rdx :xorqRegReg
- /rcx :divqReg
- /rax :popqReg
- ] makeArith /eymod defv
- [
- /rax :pushqReg
- /rdx /rax :movqRegReg
- /rdx /rdx :xorqRegReg
- /rcx :divqReg
- /rax /rdx :movqRegReg
- /rax :popqReg
- ] makeArith /eydiv defv
-
- [[
- /rcx /rcx :testqRegReg
- /no :jzLbl8
- /rdx /rdx :testqRegReg
- /no :jzLbl8
- 1 /rdx :movqImmReg
- /done :jmpLbl8
-
- @no
- /rdx /rdx :xorqRegReg
- @done
- ]] makeArith /eyand defv
-
# 0 -> integer
# 0 <- the negated integer
[
@@ -400,8 +321,10 @@
%50 /cl :cmpbImmReg
/normalFunction :jeLbl8
%70 /cl :cmpbImmReg
- /arrayFunction :jeLbl8
+ /unexecutable :jneLbl8
+ /arrayFunction :jmpLbl32
+ @unexecutable
"not an executable thing" ::outputError
:ud2
@@ -422,8 +345,10 @@
# handle typed function
16 /rdx /rcx :movqMemDisp8Reg
/rcx /rcx :testqRegReg
- /typed :jnzLbl8
+ /untyped :jzLbl8
+ /typed :jmpLbl32
+ @untyped
24 /rdx /rax :movqMemDisp8Reg
8 /rax :addqImm8Reg
/rax :callqReg
@@ -437,6 +362,11 @@
:retn
@unscoped
+ # handle typed unscoped function
+ 16 /rdx /rcx :movqMemDisp8Reg
+ /rcx /rcx :testqRegReg
+ /typedUnscoped :jnzLbl8
+
24 /rdx /rax :movqMemDisp8Reg
8 /rax :addqImm8Reg
/rax :callqReg
@@ -445,9 +375,13 @@
8 /r15 :addqImm8Reg
:retn
- @unscopedTyped
- # TODO think about whether this should be allowed to happen
- :ud2
+ @typedUnscoped
+ # save current scope
+ ::currentScope /rax :movqImmReg
+ /rax /rsi :movqMemReg
+ 8 /r15 :subqImm8Reg
+ /rsi /r15 :movqRegMem
+ /typed :jmpLbl32
@arrayFunction
# rdx == array on heap
@@ -480,7 +414,62 @@
:retn
@typed
- :ud2 # TODO handle typed functions and autolooping
+ # quick check for the common case (and to avoid infinite recursion)
+ 16 /rdx /rbx :movqMemDisp8Reg
+ 8 /rbx /rcx :movqMemDisp8Reg # rcx == number of input stack elements
+ 16 /rbx /rbx :leaqMemDisp8Reg # rbx == first input stack element
+
+ /rsp /rdi :movqRegReg
+
+ @typedCommonCheck
+ /rbx /rsi :movqMemReg # rsi == address of abstract argument
+ 7 /rsi /al :movbMemDisp8Reg # al == type of abstract argument
+ %F0 /al :andbImmReg
+ /rdi /rsi :movqMemReg # rsi == address of concrete argument
+ 7 /rsi /sil :movbMemDisp8Reg # sil = type of concrete argument
+ %F0 /sil :andbImmReg
+
+ /al /sil :cmpbRegReg
+ /typedNonCommon :jnzLbl8 # non-equal types
+ %E0 /al :testbImmReg
+ /typedNonCommon :jnzLbl8 # non-trivial types
+
+ 8 /rdi :addqImm8Reg
+ 8 /rbx :addqImm8Reg
+ /typedCommonCheck :loopLbl8
+
+ 24 /rdx /rax :movqMemDisp8Reg
+ 8 /rax :addqImm8Reg
+ /rax :callqReg
+
+ /r15 /rcx :movqMemReg
+ ::currentScope /rax :movqImmReg
+ /rcx /rax :movqRegMem
+ 8 /r15 :addqImm8Reg
+ /r15 :pushqMem
+ 8 /r15 :addqImm8Reg
+ :retn
+
+ @typedNonCommon
+ :ud2 # TRACE, this path is unchecked
+ # escape this to compiled high-level code
+ /rdx :pushqReg
+
+ /rax :movqImmOOBReg "sys" ::string
+ /rax :pushqReg
+ /rax :movqImmOOBReg "ey*" "ey." ::linkAbs64
+ /rax :callqReg
+
+ /rax :movqImmOOBReg "typed" ::string
+ /rax :pushqReg
+ /rax :movqImmOOBReg "ey*" "ey." ::linkAbs64
+ /rax :callqReg
+
+ /rax :movqImmOOBReg "execute" ::string
+ /rax :pushqReg
+ /rax :movqImmOOBReg "ey*" "ey." ::linkAbs64
+ /rax :callqReg
+ :retn
]] /ey* defv
# dump top stack element (actually drop it for now)
@@ -1617,6 +1606,105 @@
::unscopingFunctionHeader ::unscopingFunctionFooter -102* /ey}' defv
> _ ==globalMacros { defv }' ::allocateOffsetStruct
+ <
+ [
+ %10 %00 %00 %00 %00 %00 %00 %00
+ %01 %00 %00 %00 %00 %00 %00 %00
+ ] /t1 defv
+
+ [
+ %28 %00 %00 %00 %00 %00 %00 %80
+ %02 %00 %00 %00 %00 %00 %00 %00
+ /t11t1 /t1 ::linkAbs64
+ /t11t1 /t1 ::linkAbs64
+ %01 %00 %00 %00 %00 %00 %00 %00
+ /t11t1 /t1 ::linkAbs64
+ ] /t11t1 defv
+ > _ =globalTypes { defv }' ::allocateOffsetStruct
+
+ <
+ # arithmetic functions on ints
+ [ /rcx /rdx :addqRegReg ] makeArith /eyadd defv
+ [ /rcx /rdx :subqRegReg ] makeArith /eysub defv
+ [ /rcx /rdx :andqRegReg ] makeArith /eyband defv
+ [ /rcx /rdx :orqRegReg ] makeArith /eybor defv
+ [ /rcx /rdx :xorqRegReg ] makeArith /eybxor defv
+
+ [
+ /rdi /rdi :xorqRegReg
+ 1 /rsi :movqImmReg
+ /rdx /rcx :cmpqRegReg
+ /rsi /rdx :movqRegReg
+ /rdi /rdx :cmovnzqRegReg
+ ] makeArith /eyeq defv
+ [
+ /rdi /rdi :xorqRegReg
+ 1 /rsi :movqImmReg
+ /rdx /rcx :cmpqRegReg
+ /rsi /rdx :movqRegReg
+ /rdi /rdx :cmovgeqRegReg
+ ] makeArith /eygt defv
+ [
+ /rdi /rdi :xorqRegReg
+ 1 /rsi :movqImmReg
+ /rdx /rcx :cmpqRegReg
+ /rsi /rdx :movqRegReg
+ /rdi /rdx :cmovgqRegReg
+ ] makeArith /eyge defv
+ [
+ /rdi /rdi :xorqRegReg
+ 1 /rsi :movqImmReg
+ /rdx /rcx :cmpqRegReg
+ /rsi /rdx :movqRegReg
+ /rdi /rdx :cmovngqRegReg
+ ] makeArith /eylt defv
+ [
+ /rdi /rdi :xorqRegReg
+ 1 /rsi :movqImmReg
+ /rdx /rcx :cmpqRegReg
+ /rsi /rdx :movqRegReg
+ /rdi /rdx :cmovngeqRegReg
+ ] makeArith /eyle defv
+
+ [
+ /rax :pushqReg
+ /rcx /rax :movqRegReg
+ /rdx :mulqReg
+ /rax /rdx :movqRegReg
+ /rax :popqReg
+ ] makeArith /eymul defv
+ [
+ /rax :pushqReg
+ /rdx /rax :movqRegReg
+ /rdx /rdx :xorqRegReg
+ /rcx :divqReg
+ /rax :popqReg
+ ] makeArith /eymod defv
+ [
+ /rax :pushqReg
+ /rdx /rax :movqRegReg
+ /rdx /rdx :xorqRegReg
+ /rcx :divqReg
+ /rax /rdx :movqRegReg
+ /rax :popqReg
+ ] makeArith /eydiv defv
+
+ [[
+ /rcx /rcx :testqRegReg
+ /no :jzLbl8
+ /rdx /rdx :testqRegReg
+ /no :jzLbl8
+ 1 /rdx :movqImmReg
+ /done :jmpLbl8
+
+ @no
+ /rdx /rdx :xorqRegReg
+ @done
+ ]] makeArith /eyand defv
+ > _ =globalT11t1Functions { defv }' ::allocateOffsetStruct
+
+ { | }' ::linkResolve
+
{ =*resolve ==createScopeEntry
{ ==name
# create function
@@ -1638,6 +1726,26 @@
} each
} /createScopeEntries deff
+ { =*resolve ==typeToUse ==createScopeEntry
+ { ==name
+ # create function
+ name resolve 8 sub /rdi :movqImmReg # adjust for expected (but non-existent) code block header size
+ /rsi /rsi :xorqRegReg # library functions don't have a captured scope
+ typeToUse /rdx :movqImmReg
+
+ ::internalAllocateFunction /rax :movqImmReg
+ /rax :callqReg
+ /rax :pushqReg
+
+ # create string
+ name "ey(.*)" regex assert ::constStringCode _ len dearray
+
+ # enter into current (i.e. global) scope
+ createScopeEntry /rax :movqImmReg
+ /rax :callqReg
+ } each
+ } /createTypedScopeEntries deff
+
{
[ /eydefv /eydeff /eydefq ] { ==name
# create function
@@ -1664,6 +1772,7 @@
globalFunctions2 keys len add
globalFunctions3 keys len add
globalMacros keys len add
+ globalT11t1Functions keys len add
/rdi :movqImmReg
/rsi /rsi :xorqRegReg
::internalAllocateScope /rax :movqImmReg
@@ -1676,6 +1785,7 @@
globalFunctions2 keys eydeff { | }' createScopeEntries
globalFunctions3 keys eydeff { | }' createScopeEntries
globalMacros keys eydefq { | }' createScopeEntries
+ globalT11t1Functions keys eydeff t11t1 { | }' createTypedScopeEntries
] :execute
{ ==name