1/* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16namespace panda::intrinsics { 17 18// Autogenerated file -- DO NOT EDIT! 19% Runtime::intrinsics.select(&:has_impl?).uniq { |intrn| intrn.impl + ", " + intrn.impl_signature.args.count.to_s + ";;" + intrn.private.to_s}.each do |intrinsic| 20% params = intrinsic.impl_signature.args.each_with_index.map {|cpp_type, index| cpp_type + " " + "arg#{index}" } 21% params = params.unshift("[[maybe_unused]] Method* /* unused */") 22% implementation = intrinsic.impl.rpartition("::").last 23% if intrinsic.private 24#ifndef PANDA_PRODUCT_BUILD 25% end 26extern "C" <%= intrinsic.impl_signature.ret %> <%= implementation %>BridgeSelectorEntryPoint(<%= params.join(", ") %>); 27// NOLINTNEXTLINE(misc-definitions-in-headers) 28extern "C" <%= intrinsic.impl_signature.ret %> <%= implementation %>CompiledAbi(<%= params.join(", ") %>) { // NOLINT 29% nargs = intrinsic.impl_signature.args.size 30% arg_list = (0...nargs).map { |i| "arg#{i}" }.join(", ") 31% ret_type = intrinsic.impl_signature.ret 32% if ret_type == 'void' 33 <%= intrinsic.impl %>(<%= arg_list %>); 34% else 35 return <%= intrinsic.impl %>(<%= arg_list %>); 36% end 37} 38% if intrinsic.private 39#endif // PANDA_PRODUCT_BUILD 40% end 41 42% end 43 44// NOLINTNEXTLINE(readability-function-size,misc-definitions-in-headers) 45bool Initialize(panda::panda_file::SourceLang vm_lang) { 46 Runtime *runtime = Runtime::GetCurrent(); 47 ClassLinker *class_linker = runtime->GetClassLinker(); 48 const auto& runtime_options = Runtime::GetOptions(); 49 50 if (!runtime_options.ShouldInitializeIntrinsics()) { 51 return true; 52 } 53 54 if (!class_linker->HasExtension(vm_lang)) { 55 // No extension here. 56 return true; 57 } 58 59 ClassLinkerExtension *cle = class_linker->GetExtension(vm_lang); 60 61 auto spaces = runtime_options.GetBootIntrinsicSpaces(); 62 63#ifndef PANDA_PRODUCT_BUILD 64 auto blacklist = runtime_options.GetIntrinsicsBlacklist(); 65#endif // PANDA_PRODUCT_BUILD 66 67 std::string_view space; 68 for (const auto &space_arg : spaces) { 69 if (runtime->GetLanguageContext(space_arg).GetLanguage() == vm_lang) { 70 space = space_arg; 71 break; 72 } 73 } 74 75 if (space.empty()) { 76 // Current space was disabled in options. 77 return true; 78 } 79 80% Runtime::intrinsics.select(&:has_impl?).each do |intrinsic| 81% if intrinsic.private 82#ifndef PANDA_PRODUCT_BUILD 83% end 84 // Init intrinsics only for current vm. 85 if (space == "<%= intrinsic.space %>") { 86 auto mutf8_name = reinterpret_cast<const uint8_t *>("<%= get_object_descriptor(intrinsic.class_name) %>"); 87 auto klass = cle->GetClass(mutf8_name); 88 if (klass == nullptr) { 89 LOG(ERROR, RUNTIME) << "Cannot find class '" << mutf8_name << "'"; 90 return false; 91 } 92 mutf8_name = reinterpret_cast<const uint8_t *>("<%= intrinsic.method_name %>"); 93 94 Method::Proto proto; 95 auto &shorty = proto.GetShorty(); 96 97% types = [intrinsic.signature.ret] + intrinsic.signature.args 98% types.each do |t| 99 shorty.emplace_back(panda_file::Type::TypeId::<%= get_shorty_type(t) %>); 100% if object_type?(t) 101 proto.GetRefTypes().emplace_back("<%= get_object_descriptor(t) %>"); 102% end 103% end 104 105 auto method = klass->GetDirectMethod(mutf8_name, proto); 106 if (method == nullptr) { 107 LOG(ERROR, RUNTIME) << "Cannot find method '<%= intrinsic.class_name %>.<%= intrinsic.method_name %>' in space '<%= intrinsic.space %>'"; 108 return false; 109 } 110 111% method_full_name = intrinsic.class_name + "::" + intrinsic.method_name 112#ifndef PANDA_PRODUCT_BUILD 113 if (!blacklist.empty() && std::find(blacklist.begin(), blacklist.end(), static_cast<const char *>("<%= method_full_name %>")) != blacklist.end()) { 114 LOG(DEBUG, RUNTIME) << "Skipping intrinsic linkage for blacklisted method <%= method_full_name %>"; 115 } else { 116#endif // PANDA_PRODUCT_BUILD 117 method->SetIntrinsic(Intrinsic::<%= intrinsic.enum_name %>); 118% if intrinsic.static 119 method->SetCompiledEntryPoint(reinterpret_cast<const void *>(<%= intrinsic.impl.rpartition("::").last + "CompiledAbi" %>)); 120% else 121 method->SetCompiledEntryPoint(reinterpret_cast<const void *>(<%= intrinsic.impl.rpartition("::").last + "BridgeSelectorEntryPoint" %>)); 122% end 123#ifndef PANDA_PRODUCT_BUILD 124 } 125#endif // PANDA_PRODUCT_BUILD 126 } 127% if intrinsic.private 128#endif // PANDA_PRODUCT_BUILD 129% end 130% end 131 return true; 132} 133 134} // namespace panda::intrinsics 135 136% Runtime::intrinsics.select(&:has_impl?).uniq { |i| i.impl }.each do |intrinsic| 137% next if !intrinsic.need_abi_wrapper? 138% namespace, _, funcname = intrinsic.impl.rpartition('::') 139namespace <%= namespace %> { 140% params = intrinsic.impl_signature.args.each_with_index.map {|cpp_type, index| cpp_type + " " + "arg#{index}" } 141<%= intrinsic.impl_signature.ret %> <%= funcname %>(<%= params.join(", ") %>) { // NOLINT 142% nargs = intrinsic.impl_signature.args.size 143% arg_list = (0...nargs).map do |i| 144% if intrinsic.impl_signature.args[i] == intrinsic.orig_impl_signature.args[i] 145% "arg#{i}" 146% else 147% "static_cast<#{intrinsic.orig_impl_signature.args[i]}>(arg#{i})" 148% end 149% end 150% arg_list = arg_list.join(", ") 151% ret_type = intrinsic.orig_impl_signature.ret 152% if ret_type == 'void' 153 <%= intrinsic.orig_impl %>(<%= arg_list %>); 154% else 155 return <%= intrinsic.orig_impl %>(<%= arg_list %>); 156% end 157} 158} // namespace <%= namespace %> 159 160% end 161