/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace panda::intrinsics { // Autogenerated file -- DO NOT EDIT! % Runtime::intrinsics.select(&:has_impl?).uniq { |intrn| intrn.impl + ", " + intrn.impl_signature.args.count.to_s + ";;" + intrn.private.to_s}.each do |intrinsic| % params = intrinsic.impl_signature.args.each_with_index.map {|cpp_type, index| cpp_type + " " + "arg#{index}" } % params = params.unshift("[[maybe_unused]] Method* /* unused */") % implementation = intrinsic.impl.rpartition("::").last % if intrinsic.private #ifndef PANDA_PRODUCT_BUILD % end extern "C" <%= intrinsic.impl_signature.ret %> <%= implementation %>BridgeSelectorEntryPoint(<%= params.join(", ") %>); // NOLINTNEXTLINE(misc-definitions-in-headers) extern "C" <%= intrinsic.impl_signature.ret %> <%= implementation %>CompiledAbi(<%= params.join(", ") %>) { // NOLINT % nargs = intrinsic.impl_signature.args.size % arg_list = (0...nargs).map { |i| "arg#{i}" }.join(", ") % ret_type = intrinsic.impl_signature.ret % if ret_type == 'void' <%= intrinsic.impl %>(<%= arg_list %>); % else return <%= intrinsic.impl %>(<%= arg_list %>); % end } % if intrinsic.private #endif // PANDA_PRODUCT_BUILD % end % end // NOLINTNEXTLINE(readability-function-size,misc-definitions-in-headers) bool Initialize(panda::panda_file::SourceLang vm_lang) { Runtime *runtime = Runtime::GetCurrent(); ClassLinker *class_linker = runtime->GetClassLinker(); const auto& runtime_options = Runtime::GetOptions(); if (!runtime_options.ShouldInitializeIntrinsics()) { return true; } if (!class_linker->HasExtension(vm_lang)) { // No extension here. return true; } ClassLinkerExtension *cle = class_linker->GetExtension(vm_lang); auto spaces = runtime_options.GetBootIntrinsicSpaces(); #ifndef PANDA_PRODUCT_BUILD auto blacklist = runtime_options.GetIntrinsicsBlacklist(); #endif // PANDA_PRODUCT_BUILD std::string_view space; for (const auto &space_arg : spaces) { if (runtime->GetLanguageContext(space_arg).GetLanguage() == vm_lang) { space = space_arg; break; } } if (space.empty()) { // Current space was disabled in options. return true; } % Runtime::intrinsics.select(&:has_impl?).each do |intrinsic| % if intrinsic.private #ifndef PANDA_PRODUCT_BUILD % end // Init intrinsics only for current vm. if (space == "<%= intrinsic.space %>") { auto mutf8_name = reinterpret_cast("<%= get_object_descriptor(intrinsic.class_name) %>"); auto klass = cle->GetClass(mutf8_name); if (klass == nullptr) { LOG(ERROR, RUNTIME) << "Cannot find class '" << mutf8_name << "'"; return false; } mutf8_name = reinterpret_cast("<%= intrinsic.method_name %>"); Method::Proto proto; auto &shorty = proto.GetShorty(); % types = [intrinsic.signature.ret] + intrinsic.signature.args % types.each do |t| shorty.emplace_back(panda_file::Type::TypeId::<%= get_shorty_type(t) %>); % if object_type?(t) proto.GetRefTypes().emplace_back("<%= get_object_descriptor(t) %>"); % end % end auto method = klass->GetDirectMethod(mutf8_name, proto); if (method == nullptr) { LOG(ERROR, RUNTIME) << "Cannot find method '<%= intrinsic.class_name %>.<%= intrinsic.method_name %>' in space '<%= intrinsic.space %>'"; return false; } % method_full_name = intrinsic.class_name + "::" + intrinsic.method_name #ifndef PANDA_PRODUCT_BUILD if (!blacklist.empty() && std::find(blacklist.begin(), blacklist.end(), static_cast("<%= method_full_name %>")) != blacklist.end()) { LOG(DEBUG, RUNTIME) << "Skipping intrinsic linkage for blacklisted method <%= method_full_name %>"; } else { #endif // PANDA_PRODUCT_BUILD method->SetIntrinsic(Intrinsic::<%= intrinsic.enum_name %>); % if intrinsic.static method->SetCompiledEntryPoint(reinterpret_cast(<%= intrinsic.impl.rpartition("::").last + "CompiledAbi" %>)); % else method->SetCompiledEntryPoint(reinterpret_cast(<%= intrinsic.impl.rpartition("::").last + "BridgeSelectorEntryPoint" %>)); % end #ifndef PANDA_PRODUCT_BUILD } #endif // PANDA_PRODUCT_BUILD } % if intrinsic.private #endif // PANDA_PRODUCT_BUILD % end % end return true; } } // namespace panda::intrinsics % Runtime::intrinsics.select(&:has_impl?).uniq { |i| i.impl }.each do |intrinsic| % next if !intrinsic.need_abi_wrapper? % namespace, _, funcname = intrinsic.impl.rpartition('::') namespace <%= namespace %> { % params = intrinsic.impl_signature.args.each_with_index.map {|cpp_type, index| cpp_type + " " + "arg#{index}" } <%= intrinsic.impl_signature.ret %> <%= funcname %>(<%= params.join(", ") %>) { // NOLINT % nargs = intrinsic.impl_signature.args.size % arg_list = (0...nargs).map do |i| % if intrinsic.impl_signature.args[i] == intrinsic.orig_impl_signature.args[i] % "arg#{i}" % else % "static_cast<#{intrinsic.orig_impl_signature.args[i]}>(arg#{i})" % end % end % arg_list = arg_list.join(", ") % ret_type = intrinsic.orig_impl_signature.ret % if ret_type == 'void' <%= intrinsic.orig_impl %>(<%= arg_list %>); % else return <%= intrinsic.orig_impl %>(<%= arg_list %>); % end } } // namespace <%= namespace %> % end