CE Func List.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. //#define SUPPORT_SCRIPTS
  4. namespace EE{
  5. namespace Edit{
  6. /******************************************************************************/
  7. struct FuncCall
  8. {
  9. CChar8 *name;
  10. Call::Func func;
  11. };
  12. struct GlobalVar
  13. {
  14. CChar8 *name;
  15. CPtr addr;
  16. };
  17. /******************************************************************************/
  18. static Str SymbolToCppName(C Str &s)
  19. {
  20. Str n='$';
  21. FREPA(s)
  22. {
  23. Char c=s[i];
  24. if(c>='a' && c<='z'
  25. || c>='A' && c<='Z'
  26. || c>='0' && c<='9'
  27. || c=='_')n+=c;else n+=S+'$'+TextHex(UInt(c), 2);
  28. }
  29. return n;
  30. }
  31. Str CppStyle(C Str &s) {return Replace(s, '.', "::");} // "EE.Str" -> "EE::Str"
  32. Str ModifName(Symbol::Modif &m, Bool spaces=true, Bool include_const=true, Bool include_ref=true, Bool invalid_array_as_1=false, Bool template_space=false) // this function replaces basic types "Int" -> "int"
  33. {
  34. //if(m && m->var_type!=VAR_NONE && m->var_type!=VAR_ENUM){Symbol::Modif temp=m; temp.proceedToFinal(&temp.templates); return temp.modifName(spaces, include_const, include_ref);}
  35. return m.modifName(spaces, include_const, include_ref, invalid_array_as_1, template_space);
  36. }
  37. Str FuncName(Symbol &func)
  38. {
  39. if(!func.value)return S;
  40. Str n=ModifName(func.value, false)+' '+func.fullCppName()+'(';
  41. FREPA(func.params){if(i)n+=',';
  42. Symbol *param=func.params[i]();
  43. if(!param || !param->value)return S; n+=ModifName(param->value, false);}
  44. n+=')';
  45. if(func.modifiers&Symbol::MODIF_FUNC_CONST )n +="const";
  46. //if(func.modifiers&Symbol::MODIF_FUNC_FINAL )n.space()+="final";
  47. //if(func.modifiers&Symbol::MODIF_FUNC_OVERRIDE)n.space()+="override";
  48. return n;
  49. }
  50. Str DtorName(Symbol &Class)
  51. {
  52. return S+"void "+Class.fullCppName()+".~"+Class+"()";
  53. }
  54. Str NativeOperatorName(C Str &op, Symbol::Modif &result, Symbol::Modif &a)
  55. {
  56. return result.modifName(false, false, false)+" operator"+op+'('+a.modifName(false, false, false)+')';
  57. }
  58. Str NativeOperatorName(C Str &op, Symbol::Modif &result, Symbol::Modif &a, Symbol::Modif &b)
  59. {
  60. return result.modifName(false, false, false)+" operator"+op+'('+a.modifName(false, false, false)+','+b.modifName(false, false, false)+')';
  61. }
  62. /******************************************************************************/
  63. static CChar8 *op_change []={"=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "|=", "^="},
  64. *op_compare[]={"==", "===", "!=", "!!=", "<", ">", "<=", ">=", "&&", "^^", "||"},
  65. *op_binary []={"*", "/", "%", "+", "-", "<<", ">>", "&", "^", "|"},
  66. *op_inc_dec[]={"++", "--"};
  67. static Mems<FuncCall*> FC2; // 'FC' sorted by FuncCall::func
  68. /******************************************************************************/
  69. void CodeEditor::createFuncList()
  70. {
  71. FileText ft; ft.writeMem(UTF_8); // xcode had problems with utf-16
  72. Memc<Str> funcs, vars;
  73. CodeEnvironment::SetupChildren(); // needed for some functions
  74. // create call's
  75. {
  76. Str name;
  77. name="nop"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos+=Call::Size(0); }");
  78. }
  79. // create call's
  80. {
  81. Str name; // use 'getInstructP' and 'getInstructI' for param 0 because they're always stored in INSTRUCT (adjust code positions before making the call, so thread.call will store new positions and will return to them later)
  82. name="call func" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos+=Call::Size(1); thread.call(*(CodeEnvironment::FuncBody*)call.param(0).getInstructP(), call.param(0).getInstructI2(), null, null); }");
  83. name="call func result" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos+=Call::Size(2); thread.call(*(CodeEnvironment::FuncBody*)call.param(0).getInstructP(), call.param(0).getInstructI2(), null, call.param(1).address(thread)); }");
  84. name="call method" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos+=Call::Size(2); thread.call(*(CodeEnvironment::FuncBody*)call.param(0).getInstructP(), call.param(0).getInstructI2(), call.param(1).address(thread), null); }");
  85. name="call method result"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos+=Call::Size(3); thread.call(*(CodeEnvironment::FuncBody*)call.param(0).getInstructP(), call.param(0).getInstructI2(), call.param(1).address(thread), call.param(2).address(thread)); }");
  86. }
  87. // create set const's
  88. {
  89. Str name; // use 'getInstructI' and 'raw' for params 0 and 1 because they're always stored in INSTRUCT
  90. name="set const 1" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(byte *)(thread.func_stack+call.param(0).getInstructI()) = (byte &)call.param(1).raw; thread.func_code_pos+=Call::Size(2); }");
  91. name="set const 2" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(short*)(thread.func_stack+call.param(0).getInstructI()) = (short&)call.param(1).raw; thread.func_code_pos+=Call::Size(2); }");
  92. name="set const 4" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(int *)(thread.func_stack+call.param(0).getInstructI()) = (int &)call.param(1).raw; thread.func_code_pos+=Call::Size(2); }");
  93. name="set const 8" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(long *)(thread.func_stack+call.param(0).getInstructI()) = (long &)call.param(1).raw; thread.func_code_pos+=Call::Size(2); }");
  94. name="set const heap 1"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(byte *)(thread.func_stack+call.param(0).getInstructI()) = PARAM(1,byte ); thread.func_code_pos+=Call::Size(2); }");
  95. name="set const heap 2"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(short*)(thread.func_stack+call.param(0).getInstructI()) = PARAM(1,short); thread.func_code_pos+=Call::Size(2); }");
  96. name="set const heap 4"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(int *)(thread.func_stack+call.param(0).getInstructI()) = PARAM(1,int ); thread.func_code_pos+=Call::Size(2); }");
  97. name="set const heap 8"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(long *)(thread.func_stack+call.param(0).getInstructI()) = PARAM(1,long ); thread.func_code_pos+=Call::Size(2); }");
  98. }
  99. // create set addr
  100. {
  101. Str name; // use 'getInstructI' for param 0 because it's always stored in INSTRUCT
  102. name="set addr heap" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(ptr*)(thread.heap +call.param(0).getInstructI()) = call.param(1).address(thread); thread.func_code_pos+=Call::Size(2); }");
  103. name="set addr stack" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(ptr*)(thread.func_stack+call.param(0).getInstructI()) = call.param(1).address(thread); thread.func_code_pos+=Call::Size(2); }");
  104. name="set addr result"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(ptr*)(thread.func_result ) = call.param(0).address(thread); thread.func_code_pos+=Call::Size(1); }");
  105. }
  106. // create indirection + addressOf
  107. {
  108. Str name;
  109. name="indirection"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { *(ptr*)(thread.func_stack+call.param(0).getInstructI()) = PARAM(1,ptr); thread.func_code_pos+=Call::Size(2); }"); // we can't use "PARAM(0,ptr)" because it's always STACK_REF and by using it we would access the value of the address not set yet
  110. name="address of" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = call.param(1).address(thread); thread.func_code_pos+=Call::Size(2); }");
  111. name="offset 1s" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,sbyte ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  112. name="offset 1u" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,byte ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  113. name="offset 2s" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,short ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  114. name="offset 2u" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,ushort) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  115. name="offset 4s" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,int ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  116. name="offset 4u" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,uint ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  117. name="offset 8s" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,long ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  118. name="offset 8u" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM_REF(0) = (byte*)call.param(1).address(thread) + PARAM(2,ulong ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  119. }
  120. // create inc/dec ptr's
  121. {
  122. Str name;
  123. name="inc ptr 2"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { ++PARAM(0,short*); thread.func_code_pos+=Call::Size(1); }");
  124. name="dec ptr 2"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { --PARAM(0,short*); thread.func_code_pos+=Call::Size(1); }");
  125. name="inc ptr 4"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { ++PARAM(0,int *); thread.func_code_pos+=Call::Size(1); }");
  126. name="dec ptr 4"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { --PARAM(0,int *); thread.func_code_pos+=Call::Size(1); }");
  127. name="inc ptr 8"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { ++PARAM(0,long *); thread.func_code_pos+=Call::Size(1); }");
  128. name="dec ptr 8"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { --PARAM(0,long *); thread.func_code_pos+=Call::Size(1); }");
  129. name="inc ptr n"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte *) += call.param(1).getInstructI(); thread.func_code_pos+=Call::Size(2); }"); // use 'getInstructI' for param 1 because it's always stored in INSTRUCT
  130. name="dec ptr n"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte *) -= call.param(1).getInstructI(); thread.func_code_pos+=Call::Size(2); }"); // use 'getInstructI' for param 1 because it's always stored in INSTRUCT
  131. name="add ptr 1s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,sbyte ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  132. name="add ptr 1u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,byte ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  133. name="add ptr 2s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,short ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  134. name="add ptr 2u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,ushort) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  135. name="add ptr 4s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,int ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  136. name="add ptr 4u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,uint ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  137. name="add ptr 8s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,long ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  138. name="add ptr 8u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,byte*) += PARAM(1,ulong ) * call.param(2).getInstructI(); thread.func_code_pos+=Call::Size(3); }");
  139. name="ptr add 1s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,sbyte ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  140. name="ptr add 1u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,byte ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  141. name="ptr add 2s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,short ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  142. name="ptr add 2u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,ushort) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  143. name="ptr add 4s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,int ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  144. name="ptr add 4u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,uint ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  145. name="ptr add 8s"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,long ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  146. name="ptr add 8u"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,ptr) = PARAM(1,byte*) + PARAM(2,ulong ) * call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  147. name="ptr diff"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,uintptr) = (PARAM(1,byte*) - PARAM(2,byte*)) / call.param(3).getInstructI(); thread.func_code_pos+=Call::Size(4); }");
  148. }
  149. // create goto's
  150. {
  151. Str name; // use 'getInstructP' because goto's are always stored in INSTRUCT
  152. name="goto" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { thread.func_code_pos = (byte*)call.param(0).getInstructP(); }");
  153. name="goto cond 1" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,byte )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  154. name="goto cond 2" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,short)) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  155. name="goto cond 4" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,int )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  156. name="goto cond 8" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,long )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  157. name="goto cond f" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,flt )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  158. name="goto cond d" ; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if( PARAM(1,dbl )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  159. name="goto cond n 1"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,byte )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  160. name="goto cond n 2"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,short)) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  161. name="goto cond n 4"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,int )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  162. name="goto cond n 8"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,long )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  163. name="goto cond n f"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,flt )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  164. name="goto cond n d"; funcs.add(name); ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { if(!PARAM(1,dbl )) thread.func_code_pos = (byte*)call.param(0).getInstructP(); else thread.func_code_pos+=Call::Size(2); }");
  165. }
  166. ft.endLine();
  167. ft.putLine("#ifdef SUPPORT_SCRIPTS");
  168. ft.endLine();
  169. // create basic operators
  170. // binary change
  171. FREPAD(o, op_change)
  172. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  173. for(VAR_TYPE b=VAR_FROM; b<=VAR_TO; b=VAR_TYPE(b+1))
  174. if(!((op_change[o]=="%=" || op_change[o]=="<<=" || op_change[o]==">>=" || op_change[o]=="&=" || op_change[o]=="|=" || op_change[o]=="^=") && (RealType(a) || RealType(b)))) // disallow modulo and binary operators if at least one param is real
  175. if(SameSizeSignBoolType(a)==a && ((a==VAR_BOOL && op_change[o]=="=") ? SameSizeSignBoolType(b)==b : SameSizeSignType(b)==b)) // keep bool for left side because C++ forces the result to bool (for bool=bool keep bool on the right side as well)
  176. {
  177. Symbol::Modif result, pa, pb;
  178. result=TypeSymbol(VAR_VOID);
  179. pa =TypeSymbol(a);
  180. pb =TypeSymbol(b);
  181. Str name=NativeOperatorName(op_change[o], result, pa, pb); funcs.add(name);
  182. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*pa+") "+op_change[o]+" PARAM(1,"+*pb+"); thread.func_code_pos+=Call::Size(2); }"); // A OP B;
  183. }
  184. // binary compare
  185. FREPAD(o, op_compare)
  186. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  187. for(VAR_TYPE b=VAR_FROM; b<=VAR_TO; b=VAR_TYPE(b+1))
  188. if(op_compare[o]!="===" && op_compare[o]!="!!=" && op_compare[o]!="^^") // temporarily skip extra operators
  189. if((op_compare[o]=="&&" || op_compare[o]=="^^" || op_compare[o]=="||") ? (SameSizeType(a)==a && SameSizeType(b)==b) : (SameSizeSignType(a)==a && SameSizeSignType(b)==b))
  190. {
  191. Symbol::Modif result, pa, pb;
  192. result=TypeSymbol(VAR_BOOL);
  193. pa =TypeSymbol(a);
  194. pb =TypeSymbol(b);
  195. Str name=NativeOperatorName(op_compare[o], result, pa, pb); funcs.add(name);
  196. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*result+") = (PARAM(1,"+*pa+") "+op_compare[o]+" PARAM(2,"+*pb+")); thread.func_code_pos+=Call::Size(3); }"); // RESULT = (A OP B);
  197. }
  198. // binary
  199. FREPAD(o, op_binary)
  200. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  201. for(VAR_TYPE b=VAR_FROM; b<=VAR_TO; b=VAR_TYPE(b+1))
  202. {
  203. VAR_TYPE type=VAR_NONE, ta=SameSizeSignType(a), tb=SameSizeSignType(b);
  204. if(ta==a && tb==b)
  205. {
  206. if(op_binary[o]=="*" )type= MulResult(ta, tb);else
  207. if(op_binary[o]=="/" )type= DivResult(ta, tb);else
  208. if(op_binary[o]=="%" )type= ModResult(ta, tb);else
  209. if(op_binary[o]=="+" )type= AddResult(ta, tb);else
  210. if(op_binary[o]=="-" )type= SubResult(ta, tb);else
  211. if(op_binary[o]=="<<" )type= ShiftLeftResult(ta, tb);else
  212. if(op_binary[o]==">>" )type=ShiftRightResult(ta, tb);else
  213. if(op_binary[o]=="&" || op_binary[o]=="^" || op_binary[o]=="|")type= BitResult(ta, tb);
  214. if(type)
  215. {
  216. Symbol::Modif result, pa, pb;
  217. result=TypeSymbol(type);
  218. pa =TypeSymbol(ta);
  219. pb =TypeSymbol(tb);
  220. Str name=NativeOperatorName(op_binary[o], result, pa, pb); funcs.add(name);
  221. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*result+") = (PARAM(1,"+*pa+") "+op_binary[o]+" PARAM(2,"+*pb+")); thread.func_code_pos+=Call::Size(3); }"); // RESULT = (A OP B);
  222. }
  223. }
  224. }
  225. // unary !
  226. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  227. if(SameSizeType(a)==a)
  228. {
  229. Symbol::Modif result, pa;
  230. result=TypeSymbol(VAR_BOOL);
  231. pa =TypeSymbol(a);
  232. Str name=NativeOperatorName("!", result, pa); funcs.add(name);
  233. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*result+") = !PARAM(1,"+*pa+"); thread.func_code_pos+=Call::Size(2); }"); // RESULT = !A;
  234. }
  235. // unary ~
  236. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))if(!RealType(a))
  237. if(SameSizeSignType(a)==a)
  238. {
  239. Symbol::Modif result, pa;
  240. result=TypeSymbol(ComplementResult(a));
  241. pa =TypeSymbol(a);
  242. Str name=NativeOperatorName("~", result, pa); funcs.add(name);
  243. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*result+") = ~PARAM(1,"+*pa+"); thread.func_code_pos+=Call::Size(2); }"); // RESULT = ~A;
  244. }
  245. // unary -
  246. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  247. if(SameSizeSignType(a)==a)
  248. {
  249. Symbol::Modif result, pa;
  250. result=TypeSymbol(NegativeResult(a));
  251. pa =TypeSymbol(a);
  252. Str name=NativeOperatorName("-", result, pa); funcs.add(name);
  253. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { PARAM(0,"+*result+") = -PARAM(1,"+*pa+"); thread.func_code_pos+=Call::Size(2); }"); // RESULT = -A;
  254. }
  255. // unary ++ --
  256. FREPAD(o, op_inc_dec)
  257. for(VAR_TYPE a=VAR_FROM; a<=VAR_TO; a=VAR_TYPE(a+1))
  258. if(!(a==VAR_BOOL && op_inc_dec[o]=="--")) // C++ doesn't allow "--bool"
  259. if(SameSizeType(a)==a)
  260. {
  261. Symbol::Modif result, pa;
  262. result=TypeSymbol(VAR_VOID);
  263. pa =TypeSymbol(a);
  264. Str name=NativeOperatorName(op_inc_dec[o], result, pa); funcs.add(name);
  265. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { "+op_inc_dec[o]+"PARAM(0,"+*pa+"); thread.func_code_pos+=Call::Size(1); }"); // ++A;
  266. }
  267. // create EE functions (as first, so binarySearch can be used without sorting native operators, and faster because of fewer functions at this stage)
  268. // TODO: process virtuals twice (as virtual and as not)
  269. FREPA(Symbols)
  270. {
  271. Symbol &func=Symbols.lockedData(i);
  272. if(func.isFunc() // functions
  273. && !(func.modifiers&Symbol::MODIF_FUNC_PARAM) // which are not function parameters "Mems& Mems::sort(Int Compare(C TYPE &a, C TYPE &b));"
  274. && !func.isTemplateFunc() // skip templates
  275. && func.fullyPublic() // this and all parents are public, skip "class Parent { private class Child { void func(); } }"
  276. && func.source && func.source->ee_header) // only stuff from EE headers
  277. {
  278. // TODO: skip functions which accept pointers to functions as parameters
  279. Bool has_func_param=false; REPA(func.params)if(func.params[i]->type==Symbol::FUNC){has_func_param=true; break;} if(has_func_param)continue;
  280. Str short_name=func.fullCppName();
  281. if(Equal (short_name, "InitPre", true) || Equal(short_name, "Init", true) || Equal(short_name, "Shut", true) || Equal(short_name, "Update", true) || Equal(short_name, "Draw", true) // skip user provided functions
  282. || Equal (short_name, "SupportScripts", true) // skip enabling scripts since it's already a script
  283. || Contains(short_name, "PVRTC" , true))continue; // skip anything PVRTC related so that the EXE is not bigger due to PVRTC compression libraries
  284. Int index;
  285. Str name=FuncName(func);
  286. if(!funcs.binarySearch(name, index, CompareCS))
  287. {
  288. Symbol::Modif &result =func.value, result_final=result; result_final.proceedToFinal(null, true);
  289. Symbol *Class =func.Class();
  290. Str func_name=func.cppName(), op_name;
  291. Bool has_result =func.hasResult(),
  292. has_this =func.isClassNonStaticFunc(),
  293. is_virtual =func.isVirtualFunc(),
  294. is_operator=Starts(func_name, "operator", true, true); if(is_operator)op_name=SkipWhiteChars(SkipStart(func_name, "operator"));
  295. if(has_result && !result
  296. || has_this && !Class
  297. || is_operator && (op_name=="new" || op_name=="delete")
  298. || (func.modifiers&Symbol::MODIF_CTOR) && Class->isAbstractClass() // can't call constructor using placement new for abstract classes
  299. )continue; // quietly skip incorrect data
  300. funcs.NewAt(index)=name;
  301. Str body=S+"thread.func_code_pos+=Call::Size("+(has_result + has_this + func.realParams())+"); ";
  302. Int params=0;
  303. if(has_result)
  304. if(result.modifiers&Symbol::MODIF_REF)body+=S+ "PARAM_REF("+(params++)+ ") = &(";else // PARAM_REF(0 ) = &(
  305. if(result_final.basicType() )body+=S+ "PARAM(" +(params++)+", "+CppStyle(ModifName(result, false, true, false, false, true))+") = (" ;else // PARAM (0, type) = (
  306. body+=S+"new(&PARAM(" +(params++)+", "+CppStyle(ModifName(result, false, true, false, false, true))+"))"+CppStyle(ModifName(result, false, false, false, false, true))+'('; // new(&PARAM (0, type))Class(
  307. if(has_this)
  308. {
  309. if(func.modifiers&Symbol::MODIF_CTOR)body+="new(&"; // new(&
  310. body+=S+"PARAM("+(params++)+", "+CppStyle(Class->fullCppName())+")"; // PARAM(1, type)
  311. if(func.modifiers&Symbol::MODIF_CTOR)body+=S+')'+CppStyle(ModifName(result, false, false, false, false, true));else // )Class
  312. if(func.modifiers&Symbol::MODIF_DTOR)body+=S+'.'+*Class+"::";else // ctors/dtors need to have class "XX::" added, sample: "Str::Str()"
  313. body+= '.';
  314. }
  315. if(!(func.modifiers&Symbol::MODIF_CTOR))
  316. {
  317. if(is_operator) // operator[], operator+, operator CChar*
  318. {
  319. body+="operator ";
  320. if(op_name=="cast")body+=CppStyle(ModifName(result, false, true, true));else body+=op_name;
  321. }else
  322. {
  323. body+=(has_this ? func_name : CppStyle(func.fullCppName())); // func
  324. }
  325. }
  326. body+='(';
  327. FREPA(func.params)
  328. {
  329. if(i)body+=", ";
  330. if(InRange(i, func.realParams()))body+=S+"PARAM("+(params++)+", "+CppStyle(ModifName(func.params[i]->value, false, true, false, true, true))+')'; // skip references but keep const in case there are "func(const int x)" and "func(int x)"
  331. else body+='0'; // 0 for dummy operator++(int)
  332. }
  333. body+=')'; // func(|)
  334. if(has_result)body+=')'; // x = (|)
  335. body+=';';
  336. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { "+body+" }");
  337. //if(funcs.elms()>=128)break;
  338. }
  339. }
  340. }
  341. // setup default destructors
  342. FREPA(Symbols)
  343. {
  344. Symbol &Class=Symbols.lockedData(i);
  345. if( Class.type==Symbol::CLASS // classes
  346. && !Class.isTemplateClass() // skip templates
  347. && !(Class.modifiers&Symbol::MODIF_NAMELESS) // skip nameless classes
  348. && Class.fullyPublic() // this and all parents are public, skip "class Parent { private class Child { void func(); } }"
  349. && Class.source && Class.source->ee_header) // only stuff from EE headers
  350. {
  351. if(Class.hasDestructor() && !FindChild(S+'~'+Class, &Class, null, false)) // should have destructor but doesn't
  352. {
  353. Str name=DtorName(Class);
  354. if(funcs.binaryInclude(name, CompareCS))
  355. {
  356. Str body ="thread.func_code_pos+=Call::Size(1); ";
  357. body+=S+"PARAM(0, "+CppStyle(Class.fullCppName())+").";
  358. body+=Class+"::~"+Class+"();";
  359. ft.putLine(S+"static void "+SymbolToCppName(name)+"(PARAMS) { "+body+" }");
  360. }
  361. }
  362. }
  363. }
  364. ft.endLine();
  365. // put list of functions
  366. funcs.sort(CompareCS); // compare before writing to enable binary search later
  367. ft.putLine("#ifdef _MSC_VER");
  368. ft.putLine(" #pragma optimize(\"\", off) // because this file compiles so slow!");
  369. ft.putLine("#endif");
  370. ft.endLine();
  371. #if 0
  372. ft.putLine("static FuncCall FC[]=");
  373. ft.putLine("{"); ft.depth++;
  374. FREPA(funcs)
  375. {
  376. Bool shader_compile=(Contains(funcs[i], "EE.ShaderCompile", true, true) || Contains(funcs[i], "EE.ShaderCompileTry", true, true));
  377. if(shader_compile){ft.depth--; ft.putLine("#if !MAC // disable this on Mac, because compiling shaders on Mac requires CG framework installed and thus all EE based applications would not run without CG"); ft.depth++;}
  378. ft.putLine(S+"{\""+funcs[i]+"\", "+SymbolToCppName(funcs[i])+"},");
  379. if(shader_compile){ft.depth--; ft.putLine("#endif"); ft.depth++;}
  380. }
  381. ft.depth--; ft.putLine("};");
  382. ft.putLine("static Int ElmsFC=Elms(FC);");
  383. ft.putLine("static void InitFC() {}");
  384. #else
  385. ft.putLine(S+"static FuncCall FC["+funcs.elms()+"];");
  386. ft.putLine("static Int ElmsFC;");
  387. ft.putLine("static void InitFC()");
  388. ft.putLine("{"); ft.depth++;
  389. ft.putLine("if(ElmsFC)return;");
  390. #if 1 // makes .exe files smallest
  391. ft.putLine("static FuncCall FC2[]=");
  392. ft.putLine("{"); ft.depth++;
  393. FREPA(funcs)
  394. {
  395. Bool shader_compile=(Contains(funcs[i], "EE.ShaderCompile", true, true) || Contains(funcs[i], "EE.ShaderCompileTry", true, true));
  396. if(shader_compile){ft.depth--; ft.putLine("#if !MAC // disable this on Mac, because compiling shaders on Mac requires CG framework installed and thus all EE based applications would not run without CG"); ft.depth++;}
  397. ft.putLine(S+"{\""+funcs[i]+"\", "+SymbolToCppName(funcs[i])+"},");
  398. if(shader_compile){ft.depth--; ft.putLine("#endif"); ft.depth++;}
  399. }
  400. ft.depth--; ft.putLine("};");
  401. ft.putLine("CopyN(FC, FC2, ElmsFC=Elms(FC2));");
  402. #else
  403. ft.putLine("int i=0;");
  404. FREPA(funcs)
  405. {
  406. Bool shader_compile=(Contains(funcs[i], "EE.ShaderCompile", true, true) || Contains(funcs[i], "EE.ShaderCompileTry", true, true));
  407. if(shader_compile){ft.depth--; ft.putLine("#if !MAC // disable this on Mac, because compiling shaders on Mac requires CG framework installed and thus all EE based applications would not run without CG"); ft.depth++;}
  408. ft.putLine(S+"FC[i].name=\""+funcs[i]+"\"; FC[i].func="+SymbolToCppName(funcs[i])+"; i++;");
  409. if(shader_compile){ft.depth--; ft.putLine("#endif"); ft.depth++;}
  410. }
  411. ft.putLine("ElmsFC=i;");
  412. #endif
  413. ft.depth--; ft.putLine("}");
  414. #endif
  415. // put list of variables
  416. FREPA(Symbols)
  417. {
  418. Symbol &var=Symbols.lockedData(i);
  419. if(var.isVar() // variables
  420. && var.isGlobalOrStatic()
  421. && var.fullyPublic()
  422. && var.source && var.source->ee_header) // only stuff from EE headers
  423. {
  424. Str short_name=var.fullCppName();
  425. if(Contains(short_name, "PVRTC", true))continue; // skip anything PVRTC related so that the EXE is not bigger due to PVRTC compression libraries
  426. vars.add(short_name);
  427. }
  428. }
  429. vars.sort(CompareCS); // compare before writing to enable binary search later
  430. ft.endLine();
  431. ft.putLine("static GlobalVar GV[]=");
  432. ft.putLine("{"); ft.depth++;
  433. FREPA(vars)ft.putLine(S+"{\""+vars[i]+"\", &"+CppStyle(vars[i])+"},");
  434. ft.depth--; ft.putLine("};");
  435. ft.endLine(); ft.depth++;
  436. ft.putLine("#ifdef _MSC_VER");
  437. ft.putLine(" #pragma optimize(\"\", on) // because this file compiles so slow!");
  438. ft.putLine("#endif"); ft.depth--;
  439. ft.putLine("#endif // SUPPORT_SCRIPTS");
  440. if(!OverwriteOnChange(ft, "C:\\Projects\\EsenthelEngine\\Src\\Code\\Compile\\CE Func List.h"))Exit("Can't create FuncList");
  441. }
  442. /******************************************************************************/
  443. // FUNCTION LIST
  444. /******************************************************************************/
  445. void Call::Param::set(Expr &expr, Compiler &compiler, Bool auto_map)
  446. {
  447. switch(expr.mem.type)
  448. {
  449. case Expr::Memory::GLOBAL:
  450. {
  451. if(expr.mem.index>=0) {setHeap (expr.mem.index+expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF)); return;} // set successfully
  452. if(expr.mem.symbol)if(CPtr addr=FindGlobalVar(expr.mem.symbol->fullCppName())){setGlobal((Byte*)addr +expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF)); return;} // set successfully
  453. }break;
  454. case Expr::Memory::LOCAL:
  455. {
  456. if(InRange(expr.mem.index, compiler.locals))
  457. {
  458. Local &local=compiler.locals[expr.mem.index];
  459. if(local.stack_offset< 0 && auto_map)compiler.mapLocalInStack(expr.mem); // auto map only if allowed
  460. if(local.stack_offset>=0)
  461. {
  462. if(local.force_heap)setHeap (local.stack_offset+expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF));
  463. else setStack(local.stack_offset+expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF));
  464. return; // set successfully
  465. }
  466. }
  467. }break;
  468. case Expr::Memory::PARAM:
  469. {
  470. if(expr.mem.index>=0){setParamStack(expr.mem.index+expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF)); return;} // set successfully
  471. }break;
  472. case Expr::Memory::THIS:
  473. {
  474. setThis(expr.mem.offset, expr.mem.offset2, FlagTest(expr.symbol.modifiers, Symbol::MODIF_REF)); return; // set successfully
  475. }break;
  476. case Expr::Memory::RESULT:
  477. {
  478. if(expr.mem.offset==0 && expr.mem.offset2==0){setResult(); return;} // set successfully
  479. }break;
  480. case Expr::Memory::KNOWN:
  481. {
  482. if(expr.mem.offset==0 && expr.mem.offset2==0)
  483. {
  484. Int size=expr.symbol.rawSize(false);
  485. U64 raw =expr.asRaw(compiler);
  486. if(ValueFitsInInstruction(size) || expr.symbol.isPtr() && !raw)setInstruct(raw);else setHeap(compiler.heapConstant(&raw, size, expr.symbol.firstMemberSize()), 0, false);
  487. return;
  488. }
  489. }break;
  490. case Expr::Memory::NONE:
  491. {
  492. if(expr.instance && expr.symbol.isArray() && expr.symbol && (expr.symbol->var_type==VAR_CHAR8 || expr.symbol->var_type==VAR_CHAR16)) // "text"
  493. if(expr[0]=='"' || (expr[1]=='"' && (expr[0]=='8' || expr[0]=='u' || expr[0]=='U' || expr[0]=='L'))) // "", 8"", u"", U"", L""
  494. {
  495. Int heap;
  496. Memc<Char> text=expr.asText(compiler);
  497. if(expr.symbol->var_type==VAR_CHAR16)heap=compiler.heapConstant(text.data(), text.elms()*SIZE(Char), 2);else
  498. {
  499. Mems<Char8> text8; text8.setNum(text.elms()); FREPAO(text8)=Char16To8Fast(text[i]); // convert Str to Str8, we can assume that Str was already initialized
  500. heap=compiler.heapConstant(text8.data(), text8.elms(), 1);
  501. }
  502. setHeap(heap, 0, false);
  503. return;
  504. }
  505. }break;
  506. }
  507. compiler.msgs.New().error("Unknown memory address of expression", expr.origin);
  508. }
  509. void Call::Param::setRef(Expr &expr, Compiler &compiler)
  510. {
  511. set(expr, compiler);
  512. switch(type)
  513. {
  514. default : return; // don't check after switch
  515. case ADDR_GLOBAL_REF: type=ADDR_GLOBAL; break;
  516. case ADDR_HEAP_REF : type=ADDR_HEAP ; break;
  517. case ADDR_STACK_REF : type=ADDR_STACK ; break;
  518. case ADDR_THIS_REF : type=ADDR_THIS ; break;
  519. }
  520. if(offset2!=0)compiler.msgs.New().error("Invalid reference address", expr.origin);
  521. }
  522. void Call::Param::setGlobal (Ptr addr , Int offset2, Bool ref) {type=(ref ? ADDR_GLOBAL_REF : ADDR_GLOBAL ); T.addr =addr ; T.offset2=offset2;}
  523. void Call::Param::setHeap (Int offset, Int offset2, Bool ref) {type=(ref ? ADDR_HEAP_REF : ADDR_HEAP ); T.offset=offset; T.offset2=offset2;}
  524. void Call::Param::setStack (Int offset, Int offset2, Bool ref) {type=(ref ? ADDR_STACK_REF : ADDR_STACK ); T.offset=offset; T.offset2=offset2;}
  525. void Call::Param::setParamStack (Int offset, Int offset2, Bool ref) {type=(ref ? ADDR_PARAM_STACK_REF : ADDR_PARAM_STACK); T.offset=offset; T.offset2=offset2;}
  526. void Call::Param::setThis (Int offset, Int offset2, Bool ref) {type=(ref ? ADDR_THIS_REF : ADDR_THIS ); T.offset=offset; T.offset2=offset2;}
  527. void Call::Param::setResult ( ) {type= ADDR_RESULT ; T.offset= 0; T.offset2= 0;}
  528. void Call::Param::setInstruct (U64 raw ) {type= ADDR_INSTRUCT ; T.raw =raw ; }
  529. void Call::Param::setInstructI (Int raw ) {type= ADDR_INSTRUCT ; T.offset=raw ; T.offset2= 0;}
  530. void Call::Param::setInstructP (Ptr addr ) {type= ADDR_INSTRUCT ; T.addr =addr ; T.offset2= 0;}
  531. void Call::Param::setInstructPI2(Ptr addr , Int i ) {type= ADDR_INSTRUCT ; T.addr =addr ; T.offset2= i;}
  532. #if WINDOWS
  533. #pragma warning(push)
  534. #pragma warning(disable:4715) // not all control paths return a value
  535. #endif
  536. #if 0
  537. Ptr Call::Param::address(CodeEnvironment::Thread &thread)
  538. {
  539. switch(type)
  540. {
  541. case ADDR_STACK : return (thread.func_stack +offset);
  542. case ADDR_STACK_REF : return (*(Byte**)(thread.func_stack +offset)) + offset2;
  543. case ADDR_PARAM_STACK : return (thread.func_param_stack+offset);
  544. case ADDR_PARAM_STACK_REF: return (*(Byte**)(thread.func_param_stack+offset)) + offset2;
  545. case ADDR_THIS : return (thread.func_this +offset);
  546. case ADDR_THIS_REF : return (*(Byte**)(thread.func_this +offset)) + offset2;
  547. case ADDR_RESULT : return (thread.func_result );
  548. case ADDR_HEAP : return (thread.heap +offset);
  549. case ADDR_HEAP_REF : return (*(Byte**)(thread.heap +offset)) + offset2;
  550. case ADDR_GLOBAL : return ( addr);
  551. case ADDR_GLOBAL_REF : return (*(Byte**)( addr)) + offset2;
  552. case ADDR_INSTRUCT : return &( raw);
  553. }
  554. }
  555. #else
  556. // TODO: make all _REF with _REF_OFS and only there apply 'offset2'?
  557. T1(TYPE) TYPE& Call::Param::value(CodeEnvironment::Thread &thread)
  558. {
  559. switch(type)
  560. {
  561. case ADDR_STACK : return *(TYPE*) (thread.func_stack +offset);
  562. case ADDR_STACK_REF : return *(TYPE*)((*(Byte**)(thread.func_stack +offset)) + offset2);
  563. case ADDR_PARAM_STACK : return *(TYPE*) (thread.func_param_stack+offset);
  564. case ADDR_PARAM_STACK_REF: return *(TYPE*)((*(Byte**)(thread.func_param_stack+offset)) + offset2);
  565. case ADDR_THIS : return *(TYPE*) (thread.func_this +offset);
  566. case ADDR_THIS_REF : return *(TYPE*)((*(Byte**)(thread.func_this +offset)) + offset2);
  567. case ADDR_RESULT : return *(TYPE*) (thread.func_result );
  568. case ADDR_HEAP : return *(TYPE*) (thread.heap +offset);
  569. case ADDR_HEAP_REF : return *(TYPE*)((*(Byte**)(thread.heap +offset)) + offset2);
  570. case ADDR_GLOBAL : return *(TYPE*) ( addr);
  571. case ADDR_GLOBAL_REF : return *(TYPE*)((*(Byte**)( addr)) + offset2);
  572. case ADDR_INSTRUCT : return reinterpret_cast<TYPE&>( raw); // use 'reinterpret_cast' instead of (TYPE&) because 'TYPE' can be const and "(const TYPE&)(raw)" could create new temporary var
  573. }
  574. }
  575. INLINE Ptr Call::Param::address(CodeEnvironment::Thread &thread) {return &value<Byte>(thread);} // use Byte because void can't be used
  576. #endif
  577. CPtr& Call::Param::ref(CodeEnvironment::Thread &thread)
  578. {
  579. switch(type)
  580. {
  581. case ADDR_STACK_REF : return *(CPtr*)(thread.func_stack +offset);
  582. case ADDR_PARAM_STACK_REF: return *(CPtr*)(thread.func_param_stack+offset);
  583. case ADDR_THIS_REF : return *(CPtr*)(thread.func_this +offset);
  584. case ADDR_HEAP_REF : return *(CPtr*)(thread.heap +offset);
  585. case ADDR_GLOBAL_REF : return *(CPtr*)( addr);
  586. }
  587. return *(CPtr*)null; // on purpose return null based pointer so it will trigger exception
  588. }
  589. #if WINDOWS
  590. #pragma warning(pop)
  591. #endif
  592. /******************************************************************************/
  593. #define PARAMS Call &call, CodeEnvironment::Thread &thread
  594. #define PARAM(i, type) call.param(i).value<type>(thread)
  595. #define PARAM_REF(i ) call.param(i).ref (thread)
  596. #define bool Bool // boolean value (8-bit)
  597. #define char8 Char8 // 8-bit character
  598. #define char Char // 16-bit character
  599. #define sbyte I8 // 8-bit signed integer
  600. #define byte U8 // 8-bit unsigned integer
  601. #define short I16 // 16-bit signed integer
  602. #define ushort U16 // 16-bit unsigned integer
  603. #define int I32 // 32-bit signed integer
  604. #define uint U32 // 32-bit unsigned integer
  605. #define long I64 // 64-bit signed integer
  606. #define ulong U64 // 64-bit unsigned integer
  607. #define flt Flt // 32-bit floating point
  608. #define dbl Dbl // 64-bit floating point
  609. #define ptr Ptr // universal pointer
  610. #define cptr CPtr // universal pointer to const data
  611. #define cchar8 CChar8 // const Char8
  612. #define cchar CChar // const Char16
  613. #define intptr IntPtr // signed integer capable of storing full memory address
  614. #define uintptr UIntPtr // unsigned integer capable of storing full memory address
  615. #if WINDOWS
  616. #pragma warning(push)
  617. #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
  618. #pragma warning(disable:4804) // unsafe use of type 'bool' in operation
  619. #pragma warning(disable:4805) // unsafe mix of type A and type B in operation
  620. #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
  621. #endif
  622. #include "CE Func List.h"
  623. #if WINDOWS
  624. #pragma warning(pop)
  625. #endif
  626. #undef bool
  627. #undef char8
  628. #undef char
  629. #undef sbyte
  630. #undef byte
  631. #undef short
  632. #undef ushort
  633. #undef int
  634. #undef uint
  635. #undef long
  636. #undef ulong
  637. #undef flt
  638. #undef dbl
  639. #undef ptr
  640. #undef cptr
  641. #undef cchar8
  642. #undef cchar
  643. #undef intptr
  644. #undef uintptr
  645. #undef PARAMS
  646. #undef PARAM
  647. #undef PARAM_REF
  648. /******************************************************************************/
  649. static Int CompareFC(C FuncCall &fc, C Str &func_name ) {return CompareCS(fc.name, func_name);}
  650. static Int CompareGV(C GlobalVar &gv, C Str & var_name ) {return CompareCS(gv.name, var_name);}
  651. static Int CompareFC( FuncCall*C &a , FuncCall*C &b ) {if(a->func < b->func)return -1; if(a->func > b->func)return +1; return 0;}
  652. static Int CompareFC( FuncCall*C &a , C Call::Func &func) {if(a->func < func)return -1; if(a->func > func)return +1; return 0;}
  653. #ifdef SUPPORT_SCRIPTS
  654. CChar8* FindFuncCall(Call::Func func)
  655. {
  656. if(!FC2.elms()){FC2.setNum(ElmsFC); FREPAO(FC2)=&FC[i]; FC2.sort(CompareFC);} // create array of functions sorted by their 'func' address
  657. Int index; return FC2.binarySearch(func, index, CompareFC) ? FC2[index]->name : null;
  658. }
  659. Call::Func FindFuncCall(C Str &func_name)
  660. {
  661. Int index; return BinarySearch(FC, ElmsFC, func_name, index, CompareFC) ? FC[index].func : null;
  662. }
  663. CPtr FindGlobalVar(C Str &var_name)
  664. {
  665. Int index; return BinarySearch(GV, Elms(GV), var_name, index, CompareGV) ? GV[index].addr : null;
  666. }
  667. #else
  668. CChar8* FindFuncCall (Call::Func func) {return null;}
  669. Call::Func FindFuncCall (C Str &func_name) {return null;}
  670. CPtr FindGlobalVar(C Str & var_name) {return null;}
  671. #endif
  672. Call::Func GetFuncCall(C Str &func_name)
  673. {
  674. Call::Func func=FindFuncCall(func_name); if(!func)Exit(S+"Can't find \""+func_name+"\" function.");
  675. return func;
  676. }
  677. Call::Func GetIgnoreCall() {return $nop;}
  678. Call::Func GetCallFunc(Bool has_this, Bool has_result)
  679. {
  680. if(has_this)return has_result ? $call$20method$20result : $call$20method;
  681. return has_result ? $call$20func$20result : $call$20func;
  682. }
  683. Call::Func GetIndirectionCall() {return $indirection ;}
  684. Call::Func GetAddressOfCall () {return $address$20of;}
  685. Call::Func GetOffsetCall (Symbol::Modif &offset)
  686. {
  687. if(offset)switch(offset.rawSize(false))
  688. {
  689. case 1: return SignedType(offset->var_type) ? $offset$201s : $offset$201u;
  690. case 2: return SignedType(offset->var_type) ? $offset$202s : $offset$202u;
  691. case 4: return SignedType(offset->var_type) ? $offset$204s : $offset$204u;
  692. case 8: return SignedType(offset->var_type) ? $offset$208s : $offset$208u;
  693. }
  694. return null;
  695. }
  696. Call::Func GetAddPtrCall(Symbol::Modif &offset)
  697. {
  698. if(offset)switch(offset.rawSize(false))
  699. {
  700. case 1: return SignedType(offset->var_type) ? $add$20ptr$201s : $add$20ptr$201u;
  701. case 2: return SignedType(offset->var_type) ? $add$20ptr$202s : $add$20ptr$202u;
  702. case 4: return SignedType(offset->var_type) ? $add$20ptr$204s : $add$20ptr$204u;
  703. case 8: return SignedType(offset->var_type) ? $add$20ptr$208s : $add$20ptr$208u;
  704. }
  705. return null;
  706. }
  707. Call::Func GetPtrAddCall(Symbol::Modif &offset)
  708. {
  709. if(offset)switch(offset.rawSize(false))
  710. {
  711. case 1: return SignedType(offset->var_type) ? $ptr$20add$201s : $ptr$20add$201u;
  712. case 2: return SignedType(offset->var_type) ? $ptr$20add$202s : $ptr$20add$202u;
  713. case 4: return SignedType(offset->var_type) ? $ptr$20add$204s : $ptr$20add$204u;
  714. case 8: return SignedType(offset->var_type) ? $ptr$20add$208s : $ptr$20add$208u;
  715. }
  716. return null;
  717. }
  718. Call::Func GetPtrDiffCall() {return $ptr$20diff;}
  719. Call::Func GetGotoCall() {return $goto;}
  720. Call::Func GetGotoCondCall(Symbol::Modif &cond)
  721. {
  722. if(cond.isPtr())
  723. {
  724. if(PtrSize==4)return $goto$20cond$204;
  725. if(PtrSize==8)return $goto$20cond$208;
  726. }else
  727. if(cond.isObj() && cond)switch(cond->var_type)
  728. {
  729. case VAR_CHAR8 :
  730. case VAR_BOOL :
  731. case VAR_BYTE :
  732. case VAR_SBYTE : return $goto$20cond$201;
  733. case VAR_CHAR16:
  734. case VAR_SHORT :
  735. case VAR_USHORT: return $goto$20cond$202;
  736. case VAR_ENUM :
  737. case VAR_INT :
  738. case VAR_UINT : return $goto$20cond$204;
  739. case VAR_LONG :
  740. case VAR_ULONG : return $goto$20cond$208;
  741. case VAR_FLT : return $goto$20cond$20f;
  742. case VAR_DBL : return $goto$20cond$20d;
  743. }
  744. return null;
  745. }
  746. Call::Func GetGotoCondNCall(Symbol::Modif &cond)
  747. {
  748. if(cond.isPtr())
  749. {
  750. if(PtrSize==4)return $goto$20cond$20n$204;
  751. if(PtrSize==8)return $goto$20cond$20n$208;
  752. }else
  753. if(cond.isObj() && cond)switch(cond->var_type)
  754. {
  755. case VAR_CHAR8 :
  756. case VAR_BOOL :
  757. case VAR_BYTE :
  758. case VAR_SBYTE : return $goto$20cond$20n$201;
  759. case VAR_CHAR16:
  760. case VAR_SHORT :
  761. case VAR_USHORT: return $goto$20cond$20n$202;
  762. case VAR_ENUM :
  763. case VAR_INT :
  764. case VAR_UINT : return $goto$20cond$20n$204;
  765. case VAR_LONG :
  766. case VAR_ULONG : return $goto$20cond$20n$208;
  767. case VAR_FLT : return $goto$20cond$20n$20f;
  768. case VAR_DBL : return $goto$20cond$20n$20d;
  769. }
  770. return null;
  771. }
  772. Call::Func GetSetConstCall(Int size, Bool heap)
  773. {
  774. switch(size)
  775. {
  776. case 1: return heap ? $set$20const$20heap$201 : $set$20const$201;
  777. case 2: return heap ? $set$20const$20heap$202 : $set$20const$202;
  778. case 4: return heap ? $set$20const$20heap$204 : $set$20const$204;
  779. case 8: return heap ? $set$20const$20heap$208 : $set$20const$208;
  780. default: return null;
  781. }
  782. }
  783. Call::Func GetSetAddrHeapCall () {return $set$20addr$20heap ;}
  784. Call::Func GetSetAddrStackCall () {return $set$20addr$20stack ;}
  785. Call::Func GetSetAddrResultCall() {return $set$20addr$20result;}
  786. /******************************************************************************/
  787. } // namespace Edit
  788. /******************************************************************************/
  789. void SupportScripts()
  790. {
  791. #ifdef SUPPORT_SCRIPTS
  792. Edit::InitFC();
  793. #endif
  794. }
  795. Bool ScriptsSupported()
  796. {
  797. #ifdef SUPPORT_SCRIPTS
  798. return Edit::ElmsFC>0;
  799. #else
  800. return false;
  801. #endif
  802. }
  803. /******************************************************************************/
  804. } // namespace EE
  805. /******************************************************************************/