| LEFT | RIGHT | 
|    1 /* |    1 /* | 
|    2  * This file is part of Adblock Plus <https://adblockplus.org/>, |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|    3  * Copyright (C) 2006-2017 eyeo GmbH |    3  * Copyright (C) 2006-2017 eyeo GmbH | 
|    4  * |    4  * | 
|    5  * Adblock Plus is free software: you can redistribute it and/or modify |    5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|    6  * it under the terms of the GNU General Public License version 3 as |    6  * it under the terms of the GNU General Public License version 3 as | 
|    7  * published by the Free Software Foundation. |    7  * published by the Free Software Foundation. | 
|    8  * |    8  * | 
|    9  * Adblock Plus is distributed in the hope that it will be useful, |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
|   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   38 { |   38 { | 
|   39   typedef void* TYPEID; |   39   typedef void* TYPEID; | 
|   40  |   40  | 
|   41   enum class TypeCategory |   41   enum class TypeCategory | 
|   42   { |   42   { | 
|   43     UNKNOWN, |   43     UNKNOWN, | 
|   44     VOID, |   44     VOID, | 
|   45     INT, |   45     INT, | 
|   46     INT64, |   46     INT64, | 
|   47     FLOAT, |   47     FLOAT, | 
 |   48     DOUBLE, | 
|   48     DEPENDENT_STRING, |   49     DEPENDENT_STRING, | 
|   49     OWNED_STRING, |   50     OWNED_STRING, | 
|   50     STRING_REF, |   51     STRING_REF, | 
|   51     CLASS_PTR |   52     CLASS_PTR | 
|   52   }; |   53   }; | 
|   53  |   54  | 
|   54   template<typename T> |   55   template<typename T> | 
|   55   struct TypeInfo |   56   struct TypeInfo | 
|   56   { |   57   { | 
|   57     /* |   58     /* | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|   72     { |   73     { | 
|   73       if (std::is_void<T>()) |   74       if (std::is_void<T>()) | 
|   74         return TypeCategory::VOID; |   75         return TypeCategory::VOID; | 
|   75  |   76  | 
|   76       if (std::is_same<T, uint64_t>()) |   77       if (std::is_same<T, uint64_t>()) | 
|   77         return TypeCategory::INT64; |   78         return TypeCategory::INT64; | 
|   78  |   79  | 
|   79       if (std::is_integral<T>() || std::is_enum<T>()) |   80       if (std::is_integral<T>() || std::is_enum<T>()) | 
|   80         return TypeCategory::INT; |   81         return TypeCategory::INT; | 
|   81  |   82  | 
|   82       if (std::is_floating_point<T>()) |   83       if (std::is_same<T, float>()) | 
|   83         return TypeCategory::FLOAT; |   84         return TypeCategory::FLOAT; | 
 |   85  | 
 |   86       if (std::is_same<T, double>()) | 
 |   87         return TypeCategory::DOUBLE; | 
|   84  |   88  | 
|   85       if (std::is_same<DependentString, T>() || std::is_same<const DependentStri
     ng, T>()) |   89       if (std::is_same<DependentString, T>() || std::is_same<const DependentStri
     ng, T>()) | 
|   86         return TypeCategory::DEPENDENT_STRING; |   90         return TypeCategory::DEPENDENT_STRING; | 
|   87  |   91  | 
|   88       if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>()
     ) |   92       if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>()
     ) | 
|   89         return TypeCategory::OWNED_STRING; |   93         return TypeCategory::OWNED_STRING; | 
|   90  |   94  | 
|   91       if (std::is_same<String&, T>() || std::is_same<const String&, T>() || |   95       if (std::is_same<String&, T>() || std::is_same<const String&, T>() || | 
|   92         std::is_same<DependentString&, T>()) |   96         std::is_same<DependentString&, T>()) | 
|   93       { |   97       { | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  135     { |  139     { | 
|  136       name[0] = '\0'; |  140       name[0] = '\0'; | 
|  137  |  141  | 
|  138       // The function parameter is a pointer to the function pointer. |  142       // The function parameter is a pointer to the function pointer. | 
|  139       // Emscripten's "function pointers" are actually integers indicating the |  143       // Emscripten's "function pointers" are actually integers indicating the | 
|  140       // position in the call table. 0 represents nullptr. |  144       // position in the call table. 0 represents nullptr. | 
|  141       if (!*reinterpret_cast<int*>(function)) |  145       if (!*reinterpret_cast<int*>(function)) | 
|  142         return; |  146         return; | 
|  143  |  147  | 
|  144       std::string signature; |  148       std::string signature; | 
|  145       if (returnType == TypeCategory::DEPENDENT_STRING || |  149  | 
|  146           returnType == TypeCategory::OWNED_STRING) |  150       // Add return type to the signature. Similar logic in Emscripten: | 
|  147       { |  151       // https://github.com/kripken/emscripten/blob/1.37.3/src/modules.js#L46 | 
|  148         // Objects aren't really returned but passed as parameter. Note that |  152       switch (returnType) | 
|  149         // this pointer might come before it but we don't care because both |  153       { | 
|  150         // are integers (pointers) as far as Emscripten is concerned. |  154         case TypeCategory::DEPENDENT_STRING: | 
|  151         signature += "vi"; |  155         case TypeCategory::OWNED_STRING: | 
|  152       } |  156           // Technically, objects aren't really returned with clang. The caller | 
|  153       else if (returnType == TypeCategory::VOID) |  157           // instead adds the reference to the resulting object as an implicit | 
|  154         signature += 'v'; |  158           // parameter. | 
|  155       else if (returnType == TypeCategory::FLOAT) |  159           signature += "vi"; | 
|  156         signature += 'd'; |  160           break; | 
|  157       else if (returnType == TypeCategory::INT || |  161         case TypeCategory::VOID: | 
|  158           returnType == TypeCategory::INT64 || |  162           signature += 'v'; | 
|  159           returnType == TypeCategory::STRING_REF || |  163           break; | 
|  160           returnType == TypeCategory::CLASS_PTR) |  164         case TypeCategory::FLOAT: | 
|  161       { |  165           signature += 'f'; | 
 |  166           break; | 
 |  167         case TypeCategory::DOUBLE: | 
 |  168           signature += 'd'; | 
 |  169           break; | 
 |  170         case TypeCategory::INT: | 
 |  171         case TypeCategory::INT64: | 
 |  172         case TypeCategory::STRING_REF: | 
 |  173         case TypeCategory::CLASS_PTR: | 
 |  174           signature += 'i'; | 
 |  175           break; | 
 |  176         default: | 
 |  177           throw std::runtime_error("Unexpected function return type"); | 
 |  178       } | 
 |  179  | 
 |  180       // `this` pointer is an implicit parameter with clang and should be added | 
 |  181       // to the signature. | 
 |  182       if (instance_function) | 
|  162         signature += 'i'; |  183         signature += 'i'; | 
|  163       } |  184  | 
|  164       else |  185       // Add explicit parameters to the signature, Similar logic in Emscripten: | 
|  165         throw std::runtime_error("Unexpected function return type"); |  186       // https://github.com/kripken/emscripten/blob/1.37.3/src/modules.js#L67 | 
|  166  |  187       for (const auto& type : argTypes) | 
|  167       if (instance_function) |  188       { | 
|  168       { |  189         switch (type) | 
|  169         // this pointer is an implicit parameter |  190         { | 
|  170         signature += 'i'; |  191           case TypeCategory::INT: | 
|  171       } |  192           case TypeCategory::STRING_REF: | 
|  172  |  193           case TypeCategory::CLASS_PTR: | 
|  173       for (const auto& item : argTypes) |  194             signature += 'i'; | 
|  174       { |  195             break; | 
|  175         if (item == TypeCategory::INT || item == TypeCategory::STRING_REF || |  196           case TypeCategory::INT64: | 
|  176             item == TypeCategory::CLASS_PTR) |  197             // See https://github.com/kripken/emscripten/blob/1.37.3/src/modules
     .js#L73, | 
|  177         { |  198             // numerical types larger than 32-bit are split into multiple | 
|  178           signature += 'i'; |  199             // 32-bit parameters. | 
 |  200             signature += "ii"; | 
 |  201             break; | 
 |  202           case TypeCategory::FLOAT: | 
 |  203             signature += 'f'; | 
 |  204             break; | 
 |  205           case TypeCategory::DOUBLE: | 
 |  206             signature += 'd'; | 
 |  207             break; | 
 |  208           default: | 
 |  209             throw std::runtime_error("Unexpected function argument type"); | 
|  179         } |  210         } | 
|  180         else if (item == TypeCategory::INT64) |  211         args.push_back(type); | 
|  181           signature += "ii"; |  | 
|  182         else if (item == TypeCategory::FLOAT) |  | 
|  183           signature += 'd'; |  | 
|  184         else |  | 
|  185           throw std::runtime_error("Unexpected function argument type"); |  | 
|  186         args.push_back(item); |  | 
|  187       } |  212       } | 
|  188  |  213  | 
|  189       get_function_name(function, signature.c_str()); |  214       get_function_name(function, signature.c_str()); | 
|  190     } |  215     } | 
|  191  |  216  | 
|  192     template<typename ReturnType, typename... Args> |  217     template<typename ReturnType, typename... Args> | 
|  193     FunctionInfo(ReturnType (*function)(Args...)) |  218     FunctionInfo(ReturnType (*function)(Args...)) | 
|  194         : FunctionInfo(TypeInfo<ReturnType>(), |  219         : FunctionInfo(TypeInfo<ReturnType>(), | 
|  195           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, |  220           TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, | 
|  196           &function) |  221           &function) | 
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  402     std::string call_str(call.name); |  427     std::string call_str(call.name); | 
|  403     call_str += "("; |  428     call_str += "("; | 
|  404     for (int i = 0; i < params.size(); i++) |  429     for (int i = 0; i < params.size(); i++) | 
|  405     { |  430     { | 
|  406       if (i > 0) |  431       if (i > 0) | 
|  407         call_str += ", "; |  432         call_str += ", "; | 
|  408       call_str += params[i]; |  433       call_str += params[i]; | 
|  409     } |  434     } | 
|  410     call_str += ")"; |  435     call_str += ")"; | 
|  411  |  436  | 
|  412     if (call.returnType == TypeCategory::VOID) |  437     switch (call.returnType) | 
|  413       return "  " + call_str + ";\n"; |  438     { | 
|  414     else if (call.returnType == TypeCategory::INT || |  439       case TypeCategory::VOID: | 
|  415           call.returnType == TypeCategory::FLOAT) |  440         return "  " + call_str + ";\n"; | 
|  416     { |  441       case TypeCategory::INT: | 
|  417       return "  var result = " + call_str + ";\n"; |  442       case TypeCategory::FLOAT: | 
|  418     } |  443       case TypeCategory::DOUBLE: | 
|  419     else if (call.returnType == TypeCategory::INT64) |  444         return "  var result = " + call_str + ";\n"; | 
|  420     { |  445       case TypeCategory::INT64: | 
|  421       // Emscripten saves the high bits of a 64-bit return value in a special |  446         return "  var result = Runtime.makeBigInt(" + call_str + ", " + | 
|  422       // variable called tempRet0. We cannot use bit operators to combine the |  447                                                   "Runtime.getTempRet0(), " + | 
|  423       // values because JavaScript operates on 32-bit integers. |  448                                                   "true);\n"; | 
|  424       return "  var result = (" + call_str + " >>> 0)" + |  449       case TypeCategory::DEPENDENT_STRING: | 
|  425              "             + (Runtime.getTempRet0() >>> 0) * 0x100000000;\n"; |  450       case TypeCategory::OWNED_STRING: | 
|  426     } |  451       { | 
|  427     else if (call.returnType == TypeCategory::DEPENDENT_STRING || |  452         std::string result; | 
|  428         call.returnType == TypeCategory::OWNED_STRING) |  453         result += "  var string = createString();\n"; | 
|  429     { |  454         result += "  " + call_str + ";\n"; | 
|  430       std::string result; |  455         result += "  var result = readString(string);\n"; | 
|  431       result += "  var string = createString();\n"; |  456         if (call.returnType == TypeCategory::OWNED_STRING) | 
|  432       result += "  " + call_str + ";\n"; |  457           result += "  Module._DestroyString(string);\n"; | 
|  433       result += "  var result = readString(string);\n"; |  458         return result; | 
|  434       if (call.returnType == TypeCategory::OWNED_STRING) |  459       } | 
|  435         result += "  Module._DestroyString(string);\n"; |  460       case TypeCategory::STRING_REF: | 
|  436       return result; |  461         return "  var result = readString(" + call_str + ");\n"; | 
|  437     } |  462       case TypeCategory::CLASS_PTR: | 
|  438     else if (call.returnType == TypeCategory::STRING_REF) |  463       { | 
|  439     { |  464         std::string result; | 
|  440       return "  var result = readString(" + call_str + ");\n"; |  465         result += "  var result = " + call_str + ";\n"; | 
|  441     } |  466         result += "  if (result)\n"; | 
|  442     else if (call.returnType == TypeCategory::CLASS_PTR) |  467         result += "  {\n"; | 
|  443     { |  468  | 
|  444       std::string result; |  469         auto it = classes.find(call.pointerType); | 
|  445       result += "  var result = " + call_str + ";\n"; |  470         if (it == classes.end()) | 
|  446       result += "  if (result)\n"; |  471           throw std::runtime_error("Function " + std::string(call.name) + " retu
     rns pointer to unknown class"); | 
|  447       result += "  {\n"; |  472  | 
|  448  |  473         const ClassInfo& cls = it->second; | 
|  449       auto it = classes.find(call.pointerType); |  474         auto offset = cls.subclass_differentiator.offset; | 
|  450       if (it == classes.end()) |  475         if (offset == SIZE_MAX) | 
|  451         throw std::runtime_error("Function " + std::string(call.name) + " return
     s pointer to unknown class"); |  476           result += "    result = " + cls.name + "(result);\n"; | 
|  452  |  477         else | 
|  453       const ClassInfo& cls = it->second; |  478         { | 
|  454       auto offset = cls.subclass_differentiator.offset; |  479           result += "    var type = HEAP32[result + " + std::to_string(offset)+ 
     " >> 2];\n"; | 
|  455       if (offset == SIZE_MAX) |  480           result += "    if (type in " + cls.name + "_mapping)\n"; | 
|  456         result += "    result = " + cls.name + "(result);\n"; |  481           result += "      result = new (exports[" + cls.name + "_mapping[type]]
     )(result);\n"; | 
|  457       else |  482           result += "    else\n"; | 
|  458       { |  483           result += "      throw new Error('Unexpected " + cls.name + " type: ' 
     + type);\n"; | 
|  459         result += "    var type = HEAP32[result + " + std::to_string(offset)+ " 
     >> 2];\n"; |  484         } | 
|  460         result += "    if (type in " + cls.name + "_mapping)\n"; |  485  | 
|  461         result += "      result = new (exports[" + cls.name + "_mapping[type]])(
     result);\n"; |  486         result += "  }\n"; | 
|  462         result += "    else\n"; |  487         result += "  else\n"; | 
|  463         result += "      throw new Error('Unexpected " + cls.name + " type: ' + 
     type);\n"; |  488         result += "    result = null;\n"; | 
|  464       } |  489         return result; | 
|  465  |  490       } | 
|  466       result += "  }\n"; |  491       default: | 
|  467       result += "  else\n"; |  492         throw std::runtime_error("Unexpected return type for " + std::string(cal
     l.name)); | 
|  468       result += "    result = null;\n"; |  493     } | 
|  469       return result; |  | 
|  470     } |  | 
|  471     else |  | 
|  472       throw std::runtime_error("Unexpected return type for " + std::string(call.
     name)); |  | 
|  473   } |  494   } | 
|  474  |  495  | 
|  475   const std::string wrapCall(const FunctionInfo& call) |  496   const std::string wrapCall(const FunctionInfo& call) | 
|  476   { |  497   { | 
|  477     bool hasStringArgs = false; |  498     bool hasStringArgs = false; | 
|  478     std::vector<std::string> params; |  499     std::vector<std::string> params; | 
|  479     std::string prefix = "function("; |  500     std::string prefix = "function("; | 
|  480     for (int i = 0; i < call.args.size(); i++) |  501     for (int i = 0; i < call.args.size(); i++) | 
|  481     { |  502     { | 
|  482       std::string argName("arg" + std::to_string(i)); |  503       std::string argName("arg" + std::to_string(i)); | 
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  765     bindings_internal::register_differentiator( |  786     bindings_internal::register_differentiator( | 
|  766         bindings_internal::TypeInfo<ClassType>(), offset, mapping); |  787         bindings_internal::TypeInfo<ClassType>(), offset, mapping); | 
|  767     return *this; |  788     return *this; | 
|  768   } |  789   } | 
|  769 }; |  790 }; | 
|  770  |  791  | 
|  771 void custom_generator(bindings_internal::CustomGenerator generator) |  792 void custom_generator(bindings_internal::CustomGenerator generator) | 
|  772 { |  793 { | 
|  773   bindings_internal::customGenerators.push_back(generator); |  794   bindings_internal::customGenerators.push_back(generator); | 
|  774 } |  795 } | 
| LEFT | RIGHT |