< txt .consume .|hu "%" deffd < "../compiler/elymasAsmOps.ey" include > /ops sys .asm .defv sys .asm .ops ==:sysasmops { quoted { _ sys .typed .type 1 eq { sysasmops -01 .| } { "sysasmops" "|" | -102 "." | } ? * } { sysasmops -01 . } ? * } ":" defq sys .asm "::" via sys .asm .|peek ==:peek { [ -01 _ 4 add range peek each ] 256 math .unbase } =*:peeku32 { [ -01 _ 8 add range peek each ] 256 math .unbase } =*:peeku64 [ 8 /r15 :subqImm8Reg /r15 :popqMem ] ==:generalHeaderPattern [ 8 /r15 :subqImm8Reg /r14 /r15 :movqRegMem /r14 /rsi :movqRegReg 0 /rdi :movqImmReg # this should match arbitrary INITIALSCOPESIZE, hence 0 0 /rax :movqImmReg /rax :callqReg /rax /r14 :movqRegReg ] ==:scopingHeaderPattern [ 0 /rax :movqImmReg /rax :pushqReg ] ==:pushConstantPattern [ 0 /rax :movqImmReg /rax :callqReg ] ==:callConstantPattern [ 0 :callqRel32 ] ==:footerPattern [ /rbx :popqReg 0 /rax :movqImmReg /rax :pushqReg /rbx :pushqReg 0 /rax :movqImmReg /rax :jmpqReg ] ==:constantActiveGeneralPattern [ 16 /r15 :subqImm8Reg 8 /r15 :popqMemDisp8 /r14 /r15 :movqRegMem 0 /r14 :movqImmReg 0 /rdi :movqImmReg /rdi :callqReg /r15 /r14 :movqMemReg 8 /r15 :pushqMemDisp8 16 /r15 :addqImm8Reg :retn ] ==:constantNormalFunctionScopedUntypedPattern [ 0 /rax :movqImmReg /rax :jmpqReg ] ==:constantNormalFunctionUnscopedUntypedPattern [ /rbx :popqReg 0 /rax :movqImmReg /rax :pushqReg /rbx :jmpqReg ] ==:constantPassivePattern [ /r14 /rax :movqRegReg ] ==:staticLoadPattern [ 16 /rax /rax :movqMemDisp8Reg ] ==:staticLoadParentPattern [ /rbx :popqReg 0 /rax /rax :movqMemDisp32Reg ] ==:staticLoadFromScopePattern [ 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer /rax /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction /rbx :popqReg 0 1 /rdx /rcx /rax :movqMemIndexScaleDisp32Reg # load entry ] ==:staticLoadFromExtensionPattern [ /rax :pushqReg 0 /rcx :movqImmReg /rax /rcx :movqRegMem /rbx :jmpqReg ] ==:staticLoadPassivePattern [ /rax :pushqReg 0 /rcx :movqImmReg /rax /rcx :movqRegMem /rbx :pushqReg 0 /rax :movqImmReg /rax :jmpqReg ] ==:staticLoadActivePattern [ 8 /r15 :subqImm8Reg /r15 :popqMem 0 /rax :movqImmReg /rax :pushqReg /r15 :pushqMem 8 /r15 :addqImm8Reg :retn ] ==:customFunctionConstantPassivePattern [ 8 /r15 :subqImm8Reg /r15 :popqMem ] ==:customFunctionHeaderPattern /NOP ==:NOP /PUSH ==:PUSH /CALL ==:CALL /CALLSCOPED ==:CALLSCOPED /STATIC ==:STATIC /STATICTYPED ==:STATICTYPED /STATICWRITE ==:STATICWRITE /STATICDOT ==:STATICDOT /NATIVE ==:NATIVE /NATIVENOSCOPE ==:NATIVENOSCOPE /ARRAYSTAR ==:ARRAYSTAR /UNTYPEDSCOPEDSTAR ==:UNTYPEDSCOPEDSTAR /UNTYPEDUNSCOPEDSTAR ==:UNTYPEDUNSCOPEDSTAR /STRINGSTAR ==:STRINGSTAR { =*f ==t t { f } { 0 } ? * } /andif deffd { ==e [ 0 e * STATICTYPED eq { 4 e * sys .typed .type 0 eq }' andif 0 e * PUSH eq { 1 e * sys .typed .type 0 eq }' andif 0 e * STRINGSTAR eq ] any } /holdsInt deffd [ "|" "=" "/" "?" "[" "]" /cat /dearray /def /die /len /quoted /range "''" ".?" ".?'" ".|" ";" /defv /deff /defq /defm /defvs /deffs /defms /defvt /defft /defmt /defvst /deffst /defmst /defvc /deffc /defmc /defvd /deffd /defmd /keys /dom /add /and /band /bor /bxor /div /eq /ge /gt /le /lt /mod /mul /neq /or /sub /udiv /umod /xor /bnot /neg /not ] { | ::rawCodeAddress } [ 0 ] [ 0 ] '' * ==:SCOPETIGHTFUNCTIONS [ /defvs /deffs /defms /defvst /deffst /defmst ] { | ::rawCodeAddress } [ 0 ] [ 0 ] '' * ==:STATICDEFININGFUNCTIONS { ==o ==executingScope 0 ==containsScopeModifications { _ ==logic logic { ==entry 0 entry * ==action [ { action CALL eq { 1 entry * "<" | ::rawCodeAddress eq }' andif }' { 1 =containsScopeModifications } { action CALL eq { 1 entry * ">" | ::rawCodeAddress eq }' andif }' { 1 =containsScopeModifications } { action CALL eq { 1 entry * ">'" | ::rawCodeAddress eq }' andif }' { 1 =containsScopeModifications } ] conds } each } /testScopeModifications deffst 0 ==allocatedScopeMightEscape { _ ==logic logic { ==entry 0 entry * ==action [ { action NOP eq }' { } { action PUSH eq }' { } { action CALLSCOPED eq }' { } { action STATIC eq }' { } { action STATICTYPED eq }' { } { action STATICWRITE eq }' { } { action STATICDOT eq }' { } { action ARRAYSTAR eq }' { } { action UNTYPEDSCOPEDSTAR eq }' { } { action STRINGSTAR eq }' { } { action NATIVENOSCOPE eq }' { } { action CALL eq { 1 entry * SCOPETIGHTFUNCTIONS eq any } andif }' { } # TODO handle more known-harmless unscoped global functions { 1 }' { 1 =allocatedScopeMightEscape } ] conds } each } /testAllocatedScopeEscape deffst 0 ==templateNametable { 1 ==templatable executingScope ::rawAddress 8 add peeku64 ==nameTableAddress nameTableAddress { nameTableAddress peeku32 ==nameTableLength 0 nameTableLength 16 sub 16 div range 16 mul nameTableAddress 16 add add { ==entryAddr entryAddr peeku64 ==keyAddr keyAddr { entryAddr 8 add peeku32 %10 band not { 0 =templatable "NOT templatable because" dump nameTableAddress dump keyAddr ::rawObject dump } rep } { } ? * } each } { 0 =templatable } ? * templatable { nameTableAddress =templateNametable "Setting template bit on " dump nameTableAddress dump nameTableAddress 7 add _ sys .asm .peek %04 bor -01 sys .asm .poke # set template bit } rep } /testNametableTemplatability deffst { ==logic [ logic { ==entry 0 entry * ==action action CALL eq { 1 entry * "/" | ::rawCodeAddress eq }' andif { "dropped call to /" dump # drop call to / } { entry } ? * } each ] } /rewriteSlash deffst { ==logic [ NOP ] ==last [ logic { ==entry 0 entry * ==action [ { action CALL eq { 1 entry * "|" | ::rawCodeAddress eq }' andif { 0 last * PUSH eq }' andif }' { 1 last * ::rawObject ==constant constant executingScope sys .resolveInfo { ==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea inExtensionArea { offsetInScope 8 add =offsetInScope } rep mode 16 div 1 band { [ STATIC offsetInScope parentCount inExtensionArea ] =last [ NOP ] =entry } { } ? * } { executingScope dump executingScope keys dump constant dump "resolution failed" die } ? * } ] conds last entry =last } each last ] } /rewriteConstantPipe deffst { ==logic [ NOP ] ==last [ logic { ==entry 0 entry * ==action [ { action CALL eq { 1 entry * "=" | ::rawCodeAddress eq }' andif { 0 last * PUSH eq }' andif }' { 1 last * ::rawObject ==constant constant executingScope sys .resolveInfo { ==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea inExtensionArea { offsetInScope 8 add =offsetInScope } rep mode 16 div 1 band { [ STATICWRITE offsetInScope parentCount inExtensionArea ] =last [ NOP ] =entry } { } ? * } { executingScope dump executingScope keys dump constant dump "resolution failed" die } ? * } { templateNametable { action CALL eq }' andif { 1 entry * STATICDEFININGFUNCTIONS eq any }' andif { 0 last * PUSH eq }' andif }' { 1 last * ::rawObject ==constant constant executingScope sys .resolveInfo { ==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea inExtensionArea { offsetInScope 8 add =offsetInScope } rep inExtensionArea not { # FIXME: implement the extension area case mode 16 div 1 band { [ STATICWRITE offsetInScope parentCount inExtensionArea ] =last [ NOP ] =entry } { } ? * "Rewrote def* of " dump constant dump } rep } { executingScope dump executingScope keys dump constant dump "resolution failed" die } ? * } ] conds last entry =last } each last ] } /rewriteConstantAssignment deffst { _ ==logic 2 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last i 2 sub logic * ==secondLast [ { action CALL eq { 1 entry * "." | ::rawCodeAddress eq }' andif { 0 last * PUSH eq }' andif { 0 secondLast * STATICTYPED eq }' andif }' { 1 last * ::rawObject ==constant 4 secondLast * ==relevantScope constant relevantScope sys .resolveInfo { ==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea inExtensionArea { offsetInScope 8 add =offsetInScope } rep mode 16 div 1 band { [ STATICDOT offsetInScope parentCount inExtensionArea ] i 1 sub logic =[] [ { mode 16 mod 0 eq }' { [ NOP ] i logic =[] } { mode 16 mod 1 eq }' { [ CALL "*" | ::rawCodeAddress ] i logic =[] } { 1 }' { # TODO this might conceivably be legal though... "Scope keys: " dump relevantScope keys dump "Constant: " dump constant dump "Mode: " dump mode dump "static . resolution resulted in execution mode neither 0 nor 1" die } ] conds } { } ? * } { relevantScope dump relevantScope keys dump constant dump "resolution failed" die } ? * } ] conds } each } /rewriteConstantDot deffst { _ ==logic 3 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last i 2 sub logic * ==secondLast i 3 sub logic * ==thirdLast action CALL eq { 1 entry * "*" | ::rawCodeAddress eq }' andif { 0 last * PUSH eq }' andif { secondLast holdsInt }' andif { thirdLast holdsInt }' andif { [ { 1 last * |add ::rawAddress eq { 0 secondLast * PUSH eq }' andif { 1 secondLast * 128 lt }' andif }' { 1 secondLast * ==value [ NATIVENOSCOPE [ /rdx :popqReg 63 /rdx :btrqImm8Reg [ 8 /rdx /rdx :movqMemDisp8Reg ] len :jcRel8 8 /rdx /rdx :movqMemDisp8Reg value /rdx :addqImm8Reg /rdx /rax :movqRegReg 32 /rax :shrqImm8Reg [ 63 /rdx :btsqImm8Reg /rdx :pushqReg 0 :jmpRel8 ] len :jnzRel8 63 /rdx :btsqImm8Reg /rdx :pushqReg [ /rdx :pushqReg ::internalAllocateInteger /rax :movqImmReg /rax :callqReg 8 /rax :popqMemDisp8 /rax :pushqReg ] len :jmpRel8 /rdx :pushqReg ::internalAllocateInteger /rax :movqImmReg /rax :callqReg 8 /rax :popqMemDisp8 /rax :pushqReg ] ] i logic =[] [ NOP ] i 1 sub logic =[] [ NOP ] i 2 sub logic =[] } { 1 last * |add ::rawAddress eq }' { [ NATIVENOSCOPE [ /rcx :popqReg 63 /rcx :btrqImm8Reg [ 8 /rcx /rcx :movqMemDisp8Reg ] len :jcRel8 8 /rcx /rcx :movqMemDisp8Reg /rdx :popqReg 63 /rdx :btrqImm8Reg [ 8 /rdx /rdx :movqMemDisp8Reg ] len :jcRel8 8 /rdx /rdx :movqMemDisp8Reg /rcx /rdx :addqRegReg /rdx /rax :movqRegReg 32 /rax :shrqImm8Reg [ 63 /rdx :btsqImm8Reg /rdx :pushqReg 0 :jmpRel8 ] len :jnzRel8 63 /rdx :btsqImm8Reg /rdx :pushqReg [ /rdx :pushqReg ::internalAllocateInteger /rax :movqImmReg /rax :callqReg 8 /rax :popqMemDisp8 /rax :pushqReg ] len :jmpRel8 /rdx :pushqReg ::internalAllocateInteger /rax :movqImmReg /rax :callqReg 8 /rax :popqMemDisp8 /rax :pushqReg ] ] i logic =[] [ NOP ] i 1 sub logic =[] } { ==negatedOpcodeName ==functionName { 1 last * functionName | ::rawAddress eq }' { [ NATIVENOSCOPE [ /rcx :popqReg 63 /rcx :btrqImm8Reg [ 8 /rcx /rcx :movqMemDisp8Reg ] len :jcRel8 8 /rcx /rcx :movqMemDisp8Reg /rdx :popqReg 63 /rdx :btrqImm8Reg [ 8 /rdx /rdx :movqMemDisp8Reg ] len :jcRel8 8 /rdx /rdx :movqMemDisp8Reg /rsi /rsi :xorqRegReg /rcx /rdx :cmpqRegReg [ /rsi :incqReg ] len negatedOpcodeName : /rsi :incqReg 63 /rsi :btsqImm8Reg /rsi :pushqReg ] ] i logic =[] [ NOP ] i 1 sub logic =[] } } /logicalOperator deffst /eq /jnzRel8 logicalOperator /neq /jzRel8 logicalOperator /le /jnleRel8 logicalOperator /lt /jnlRel8 logicalOperator /ge /jngeRel8 logicalOperator /gt /jngRel8 logicalOperator ] conds } rep } each } /rewriteArithmetics deffst { _ ==logic 1 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last [ { action CALL eq { 1 entry * "*" | ::rawCodeAddress eq }' andif { 0 last * STATICTYPED eq }' andif }' { 4 last * ==executedObject executedObject sys .typed .type ==type type [ { "failed to optimize 'execution' of integer typed object" die } { [ STRINGSTAR ] i logic =[] } { "failed to optimize 'execution' of float typed object" die } { "objects of type 3 should not appear" die } { "failed to optimize 'execution' of extension area" die } { # TODO think about handling typed functions executedObject sys .typed .inputs len { } { # handle untyped function executedObject sys .capturedScope { -- # ignore concrete scope [ UNTYPEDSCOPEDSTAR ] i logic =[] } { [ UNTYPEDUNSCOPEDSTAR ] i logic =[] } ? * } ? * } { "failed to optimize 'execution' of raw function opcodes object" die } { [ ARRAYSTAR ] i logic =[] } { "failed to optimize 'execution' of function type descriptor" die } { } # TODO optimize scope execution one day { "failed to optimize 'execution' of name table" die } { "objects of type 11 should not appear" die } { } # TODO optimize coroutine execution one day { "objects of type 13 should not appear" die } { "objects of type 14 should not appear" die } { "objects of type 15 should not appear" die } ] * * } ] conds } each } /rewriteConstantStar deffst { _ ==logic 3 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last i 2 sub logic * ==secondLast i 3 sub logic * ==thirdLast [ { action CALL eq { 1 entry * "*" | ::rawCodeAddress eq }' andif { 0 last * CALL eq }' andif { 1 last * "?" | ::rawCodeAddress eq }' andif { 0 secondLast * PUSH eq }' andif { 0 thirdLast * PUSH eq }' andif { 1 secondLast * ::rawObject sys .typed .type 5 eq }' andif { 1 thirdLast * ::rawObject sys .typed .type 5 eq }' andif { 1 secondLast * ::rawObject sys .typed .inputs len not }' andif # TODO: think about typed functions { 1 thirdLast * ::rawObject sys .typed .inputs len not }' andif # TODO: think about typed functions }' { 1 secondLast * ::rawObject sys .capturedScope _ { -01 -- } { } ? * ==hasScope 1 thirdLast * ::rawObject sys .capturedScope _ { -01 -- } { } ? * hasScope or =hasScope hasScope { [ UNTYPEDSCOPEDSTAR ] i logic =[] } { [ UNTYPEDUNSCOPEDSTAR ] i logic =[] } ? * } ] conds } each } /rewriteConstantQuestionStar deffst { ==logic [ NOP ] ==last [ logic { ==entry 0 entry * ==action [ { action CALL eq { 1 entry * "?" | ::rawCodeAddress eq }' andif }' { [ NATIVENOSCOPE [ /rcx :popqReg /rdx :popqReg /rax :popqReg 63 /rax :btrqImm8Reg [ 8 /rax /rax :movqMemDisp8Reg ] len :jcRel8 8 /rax /rax :movqMemDisp8Reg /rax /rax :testqRegReg /rcx /rdx :cmovzqRegReg /rdx :pushqReg ] ] =entry } { action CALL eq { 1 entry * "_" | ::rawCodeAddress eq }' andif }' { [ NATIVENOSCOPE [ 0 /rsp :pushqMemDisp8 ] ] =entry } { action CALL eq { 1 entry * "--" | ::rawCodeAddress eq }' andif }' { [ NATIVENOSCOPE [ 8 /rsp :addqImm8Reg ] ] =entry } { action CALL eq { 1 entry * "-" | ::rawCodeAddress eq }' andif { 0 last * PUSH eq }' andif }' { 1 last * ::rawObject ==constant 0 ==largestNumber 0 ==starUsed constant { _ 0 "*" * eq { 1 =starUsed } rep 0 "0" * sub largestNumber max =largestNumber } each [ /rax /rcx /rdx /rbx /rbp /rsi /rdi ] =*:availableRegisters starUsed { # TODO maybe implement this one day } { largestNumber |availableRegisters len gt { # TODO maybe implement this one day } { [ NATIVENOSCOPE [ 0 largestNumber 1 add range { availableRegisters :popqReg } each constant { 0 "0" * sub availableRegisters :pushqReg } each ] ] =entry [ NOP ] =last } ? * } ? * } ] conds last entry =last } each last ] } /rewriteSimpleFunctions deffst o ::rawAddress ==addr [ addr _ 4 add range peek each ] 256 math .unbase ==totalLength [ addr 8 add _ 4 add range peek each ] 256 math .unbase ==codeLength addr 16 add ==i { =*ops =*set =*get ==pattern 1 ==found get ==j pattern { _ j ops -01 { eq not { 0 =found }' rep }" { -- -- }" ? * j 1 add =j }' each found _ { j set }' { }" ? * } /generalMatch deffst { { i }' { =i }' peek generalMatch }' /match deffst generalHeaderPattern match not { "failure while matching generalHeaderPattern" die }" rep scopingHeaderPattern match ==isScoping 1 ==continueParsing [ ] ==newLogic { newLogic [ -102 ] cat =newLogic }' /emitLogic deffst { continueParsing }' { i ==s [ { footerPattern match }' { 0 =continueParsing } { pushConstantPattern match }' { [ s 2 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant [ PUSH pushedConstant ] emitLogic } { callConstantPattern match }' { [ s 2 add _ 8 add range peek each ] 256 math .unbase ==calledAddress calledAddress ==j { { j }' { =j }' peek generalMatch }' /callTargetMatch deffst [ { calledAddress 105553116266496 lt }' { # HEAPBASE # FIXME: should use global constant [ CALL calledAddress ] emitLogic } { constantActiveGeneralPattern callTargetMatch }' { [ calledAddress 3 add _ 8 add range peek each ] 256 math .unbase ==calledConstant [ PUSH calledConstant ] emitLogic [ CALL "*" | ::rawCodeAddress ] emitLogic } { constantNormalFunctionScopedUntypedPattern callTargetMatch }' { [ calledAddress 13 add _ 8 add range peek each ] 256 math .unbase ==functionScope [ calledAddress 23 add _ 8 add range peek each ] 256 math .unbase ==finalAddress [ CALLSCOPED finalAddress functionScope ] emitLogic } { constantNormalFunctionUnscopedUntypedPattern callTargetMatch }' { [ calledAddress 2 add _ 8 add range peek each ] 256 math .unbase ==finalAddress [ CALL finalAddress ] emitLogic } { constantPassivePattern callTargetMatch }' { [ calledAddress 3 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant [ PUSH pushedConstant ] emitLogic } { staticLoadPattern callTargetMatch }' { 0 ==parentCount { staticLoadParentPattern callTargetMatch }' { parentCount 1 add =parentCount } loop j ==loadStart [ { staticLoadFromScopePattern callTargetMatch }' { [ loadStart 4 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope [ calledAddress 8 sub _ 8 add range peek each ] 256 math .unbase ==exampleObjectOffset [ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ::rawObject ==exampleObject [ STATICTYPED offsetInScope parentCount 0 exampleObject ] emitLogic } { staticLoadFromExtensionPattern callTargetMatch }' { [ loadStart 14 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope [ calledAddress 8 sub _ 8 add range peek each ] 256 math .unbase ==exampleObjectOffset [ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ::rawObject ==exampleObject [ STATICTYPED offsetInScope parentCount 1 exampleObject ] emitLogic } { 1 }' { [ j j 16 add range peek each ] dump o dump j dump "unparsed static load opcodes in sys .opt .hook (optimizing version)" die } ] conds [ { staticLoadActivePattern callTargetMatch }' { [ CALL "*" | ::rawCodeAddress ] emitLogic } { staticLoadPassivePattern callTargetMatch }' { # nothing to emit } { 1 }' { [ j j 16 add range peek each ] dump o dump j dump "unparsed static load opcodes in sys .opt .hook (optimizing version)" die } ] conds } { customFunctionConstantPassivePattern callTargetMatch }' { [ calledAddress 9 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant [ PUSH pushedConstant ] emitLogic } { customFunctionHeaderPattern callTargetMatch }' { [ CALL calledAddress ] emitLogic } { 1 }' { [ j j 16 add range peek each ] dump o dump j dump "unparsed call target opcodes in sys .opt .hook (optimizing version)" die } ] conds } { 1 }' { [ i i 16 add range peek each ] dump o dump i dump "unparsed opcodes in sys .opt .hook (optimizing version)" die } ] conds } loop [ ] ==newOpcodes { newOpcodes -01 cat =newOpcodes }' /emitOpcodes deffst [ ] ==newReferences { ==ref [ { ref 105553116266496 lt } { } # HEAPBASE # FIXME: use a global constant { ref 123145302310912 ge } { } # %700000000000 { 1 } { newReferences [ ref ] cat =newReferences } ] conds }' /emitReference deffst # [ :ud2 ] emitOpcodes # enable for further development newLogic testNametableTemplatability testScopeModifications rewriteSlash containsScopeModifications not { rewriteConstantPipe rewriteConstantAssignment } rep rewriteConstantDot rewriteConstantStar rewriteConstantQuestionStar rewriteArithmetics rewriteSimpleFunctions testAllocatedScopeEscape isScoping { allocatedScopeMightEscape { [ 8 /r15 :subqImm8Reg /r15 :popqMem 8 /r15 :subqImm8Reg /r14 /r15 :movqRegMem /r14 /rsi :movqRegReg 2 /rdi :movqImmReg # FIXME: this should use INITIALSCOPESIZE ::internalAllocateScope /rax :movqImmReg /rax :callqReg /rax /r14 :movqRegReg ] emitOpcodes }" { # allocate scope directly on the call stack # this works even though we cannot GC the scope object anymore, because # the stack contents are tracked anyway [ 8 /r15 :subqImm8Reg /r15 :popqMem 8 /r15 :subqImm8Reg /r14 /r15 :movqRegMem 48 /r15 :subqImm8Reg # FIXME: this should use INITIALSCOPESIZE /rax /rax :xorqRegReg /rax 0 /r15 :andqRegMemDisp8 /rax 8 /r15 :andqRegMemDisp8 /r14 16 /r15 :movqRegMemDisp8 # save parent scope /rax 24 /r15 :andqRegMemDisp8 /rax 32 /r15 :andqRegMemDisp8 # FIXME also use INITIALSCOPESIZE /rax 40 /r15 :andqRegMemDisp8 48 /r15 :orbImmMem # set length %96 7 /r15 :orbImmMemDisp8 # set type and existence of all pointers /r15 /r14 :movqRegReg ] emitOpcodes }" ? * templateNametable { [ templateNametable /rax :movqImmReg /rax 8 /r14 :movqRegMemDisp8 ] emitOpcodes templateNametable emitReference } { } ? * }" { [ 8 /r15 :subqImm8Reg /r15 :popqMem ] emitOpcodes }" ? * { =*entry 0 entry ==action [ { action PUSH eq }' { [ 1 entry /rax :movqImmReg /rax :pushqReg ] emitOpcodes 1 entry emitReference } { action CALL eq }' { [ 1 entry /rax :movqImmReg /rax :callqReg ] emitOpcodes 1 entry 16 sub emitReference } { action CALLSCOPED eq }' { [ 8 /r15 :subqImm8Reg /r14 /r15 :movqRegMem 2 entry /r14 :movqImmReg 1 entry /rdi :movqImmReg /rdi :callqReg /r15 /r14 :movqMemReg 8 /r15 :addqImm8Reg ] emitOpcodes 1 entry 16 sub emitReference 2 entry emitReference } { action [ STATIC STATICTYPED ] eq any }' { [ 2 entry { 16 /r14 /rax :movqMemDisp8Reg 2 entry 1 sub { 16 /rax /rax :movqMemDisp8Reg } rep 3 entry { 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer /rax /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction # TODO the length calculation could be done beforehand 1 entry 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack } { 1 entry /rax :pushqMemDisp32 } ? * } { 3 entry { 24 /r14 /rcx :movqMemDisp8Reg # load extension area pointer /r14 /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction # TODO the length calculation could be done beforehand 1 entry 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack } { 1 entry /r14 :pushqMemDisp32 } ? * } ? * ] emitOpcodes } { action STATICWRITE eq }' { [ 2 entry { 16 /r14 /rax :movqMemDisp8Reg 2 entry 1 sub { 16 /rax /rax :movqMemDisp8Reg } rep 3 entry { 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer /rax /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction 1 entry 1 /rdx /rcx :popqMemIndexScaleDisp32 # load entry from stack } { 1 entry /rax :popqMemDisp32 } ? * } { 3 entry { 24 /r14 /rcx :movqMemDisp8Reg # load extension area pointer /r14 /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction 1 entry 1 /rdx /rcx :popqMemIndexScaleDisp32 # load entry from stack } { 1 entry /r14 :popqMemDisp32 } ? * } ? * ] emitOpcodes } { action STATICDOT eq }' { [ /rax :popqReg 2 entry { 16 /rax /rax :movqMemDisp8Reg } rep 3 entry { 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer /rax /edx :movlMemReg # load scope length /rdx :negqReg # prepare for substraction 1 entry 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack } { 1 entry /rax :pushqMemDisp32 } ? * ] emitOpcodes } { action UNTYPEDSCOPEDSTAR eq }' { [ /rax :popqReg 8 /r15 :subqImm8Reg /r14 /r15 :movqRegMem 8 /rax /r14 :movqMemDisp8Reg 24 /rax /rax :movqMemDisp8Reg 16 /rax :addqImm8Reg /rax :callqReg /r15 /r14 :movqMemReg 8 /r15 :addqImm8Reg ] emitOpcodes } { action UNTYPEDUNSCOPEDSTAR eq }' { [ /rax :popqReg 24 /rax /rax :movqMemDisp8Reg 16 /rax :addqImm8Reg /rax :callqReg ] emitOpcodes } { action ARRAYSTAR eq }' { [ /rsi :popqReg /rax :popqReg 63 /rax :btrqImm8Reg [ 8 /rax /rax :movqMemDisp8Reg ] len :jcRel8 8 /rax /rax :movqMemDisp8Reg /rsi /ecx :movlMemReg 3 /rcx :shrqImm8Reg /rcx :decqReg :cqo /rcx :idivqReg 0 /rdx :cmpqImm8Reg [ /rcx /rdx :addqRegReg ] len :jgeRel8 /rcx /rdx :addqRegReg 8 8 /rdx /rsi :pushqMemIndexScaleDisp8 ] emitOpcodes } { action STRINGSTAR eq }' { [ /rsi :popqReg /rax :popqReg 63 /rax :btrqImm8Reg [ 8 /rax /rax :movqMemDisp8Reg ] len :jcRel8 8 /rax /rax :movqMemDisp8Reg 16 /rsi /rcx :movqMemDisp8Reg :cqo /rcx :idivqReg 0 /rdx :cmpqImm8Reg [ /rcx /rdx :addqRegReg ] len :jgeRel8 /rcx /rdx :addqRegReg 24 1 /rdx /rsi /rbx :movzxMem8IndexScaleDisp8Reg64 63 /rbx :btsqImm8Reg /rbx :pushqReg ] emitOpcodes } { action [ NATIVE NATIVENOSCOPE ] eq any }' { 1 entry emitOpcodes } { action NOP eq }' { } { 1 }' { entry dump "invalid intermediate code during optimize" die } ] conds } each isScoping { allocatedScopeMightEscape { [ /r15 /r14 :movqMemReg 16 /r15 :addqImm8Reg 8 neg /r15 :jmpqMemDisp8 ] emitOpcodes }" { [ 48 /r15 /r14 :movqMemDisp8Reg 64 /r15 :addqImm8Reg # FIXME also use INITIALSCOPESIZE 8 neg /r15 :jmpqMemDisp8 ] emitOpcodes }" ? * }" { [ /r15 :pushqMem 8 /r15 :addqImm8Reg :retn ] emitOpcodes }" ? * newOpcodes newReferences o ::replace 1 executingScope # return something different from o to signal successful optimization [ ] _ =newOpcodes _ =newReferences =newLogic } /optimize deffd 0 ==recursionDepth { recursionDepth 1 add =recursionDepth recursionDepth 3 lt { optimize } { } ? * recursionDepth 1 sub =recursionDepth } /hook sys .opt .deff > -- # ensure that the optimizer is run often enough to finish optimize itself # while in practice this is also achieved by the next freeze, it should be done explicitely 100 { scope ==s "{" s sys .executeIdentifier =s 1 1 "add" s sys .executeIdentifier =s "--" s sys .executeIdentifier =s "}" s sys .executeIdentifier =s * } rep # vim: syn=elymas