diff options
| author | Drahflow <drahflow@gmx.de> | 2013-02-06 00:02:28 +0100 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2013-02-06 00:02:28 +0100 |
| commit | 4f9ab0adc677045612c3199f3be04cdcfd32a42a (patch) | |
| tree | ad210bc95f17e167797f968ff8992241fa1fcf44 /compiler | |
| parent | 199c2079370634675f9d3d7f366ea258c0cae890 (diff) | |
Typed functions now executing (a little)
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/elymasAsm.ey | 41 | ||||
| -rw-r--r-- | compiler/elymasAsmLib.ey | 16 | ||||
| -rw-r--r-- | compiler/elymasGlobal.ey | 280 |
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 |
