| 106 | } |
| 107 | |
| 108 | std::shared_ptr<device_function> host_program::get_function(const std::string_view& func_name) const { |
| 109 | if (has_device_binary) { |
| 110 | return device_program::get_function(func_name); |
| 111 | } |
| 112 | |
| 113 | const auto iter = find_if(cbegin(dynamic_function_names), cend(dynamic_function_names), [&func_name](const auto& name) { |
| 114 | return (*name == func_name); |
| 115 | }); |
| 116 | if (iter != cend(dynamic_function_names)) { |
| 117 | return dynamic_functions[(size_t)distance(cbegin(dynamic_function_names), iter)]; |
| 118 | } |
| 119 | |
| 120 | #if !defined(__WINDOWS__) |
| 121 | FLOOR_PUSH_WARNINGS() |
| 122 | FLOOR_IGNORE_WARNING(zero-as-null-pointer-constant) // RTLD_DEFAULT is implementation-defined, but cast from int to void* |
| 123 | auto func_ptr = dlsym(RTLD_DEFAULT, func_name.data()); |
| 124 | FLOOR_POP_WARNINGS() |
| 125 | #else |
| 126 | // get a handle to the main program / exe if it hasn't been created yet |
| 127 | if(exe_module == nullptr) { |
| 128 | exe_module = GetModuleHandle(nullptr); |
| 129 | } |
| 130 | // failed to get a handle |
| 131 | if(exe_module == nullptr) { |
| 132 | log_error("failed to get a module handle of the main program exe"); |
| 133 | return {}; |
| 134 | } |
| 135 | |
| 136 | auto func_ptr = (void*)GetProcAddress(exe_module, func_name.data()); |
| 137 | #endif |
| 138 | if(func_ptr == nullptr) { |
| 139 | #if !defined(__WINDOWS__) |
| 140 | log_error("failed to retrieve function pointer to \"$\": $", func_name, dlerror()); |
| 141 | #else |
| 142 | log_error("failed to retrieve function pointer to \"$\": $", func_name, GetLastError()); |
| 143 | #endif |
| 144 | return {}; |
| 145 | } |
| 146 | |
| 147 | host_function::host_function_entry entry; |
| 148 | entry.max_total_local_size = dev.max_total_local_size; |
| 149 | entry.max_local_size = dev.max_local_size; |
| 150 | entry.host_function_info = { |
| 151 | .name = std::string(func_name), |
| 152 | .type = toolchain::FUNCTION_TYPE::KERNEL, |
| 153 | .flags = toolchain::FUNCTION_FLAGS::KERNEL_3D, |
| 154 | // NOTE: this must always be false, even when we're pretending to load a function from a FUBAR, |
| 155 | // since this way we have the possibility to detect that this is just dummy function info |
| 156 | .is_fubar = false, |
| 157 | }; |
| 158 | |
| 159 | auto dyn_function_name = std::make_unique<std::string>(func_name); // needs to be owned by us |
| 160 | std::string_view dyn_function_name_sv(*dyn_function_name); |
| 161 | dynamic_function_names.emplace_back(std::move(dyn_function_name)); |
| 162 | auto function = std::make_shared<host_function>(dyn_function_name_sv, (const void*)func_ptr, std::move(entry)); |
| 163 | dynamic_functions.emplace_back(function); |
| 164 | |
| 165 | return function; |