101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2018 Red Hat. 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 237ec681f3Smrg#include "radv_llvm_helper.h" 2401e04c3fSmrg#include "ac_llvm_util.h" 2501e04c3fSmrg 2601e04c3fSmrg#include <list> 2701e04c3fSmrgclass radv_llvm_per_thread_info { 287ec681f3Smrg public: 297ec681f3Smrg radv_llvm_per_thread_info(enum radeon_family arg_family, 307ec681f3Smrg enum ac_target_machine_options arg_tm_options, unsigned arg_wave_size) 317ec681f3Smrg : family(arg_family), tm_options(arg_tm_options), wave_size(arg_wave_size), passes(NULL) 327ec681f3Smrg { 337ec681f3Smrg } 347ec681f3Smrg 357ec681f3Smrg ~radv_llvm_per_thread_info() 367ec681f3Smrg { 377ec681f3Smrg ac_destroy_llvm_compiler(&llvm_info); 387ec681f3Smrg } 397ec681f3Smrg 407ec681f3Smrg bool init(void) 417ec681f3Smrg { 427ec681f3Smrg if (!ac_init_llvm_compiler(&llvm_info, family, tm_options)) 437ec681f3Smrg return false; 447ec681f3Smrg 457ec681f3Smrg passes = ac_create_llvm_passes(llvm_info.tm); 467ec681f3Smrg if (!passes) 477ec681f3Smrg return false; 487ec681f3Smrg 497ec681f3Smrg return true; 507ec681f3Smrg } 517ec681f3Smrg 527ec681f3Smrg bool compile_to_memory_buffer(LLVMModuleRef module, char **pelf_buffer, size_t *pelf_size) 537ec681f3Smrg { 547ec681f3Smrg return ac_compile_module_to_elf(passes, module, pelf_buffer, pelf_size); 557ec681f3Smrg } 567ec681f3Smrg 577ec681f3Smrg bool is_same(enum radeon_family arg_family, enum ac_target_machine_options arg_tm_options, 587ec681f3Smrg unsigned arg_wave_size) 597ec681f3Smrg { 607ec681f3Smrg if (arg_family == family && arg_tm_options == tm_options && arg_wave_size == wave_size) 617ec681f3Smrg return true; 627ec681f3Smrg return false; 637ec681f3Smrg } 647ec681f3Smrg struct ac_llvm_compiler llvm_info; 657ec681f3Smrg 667ec681f3Smrg private: 677ec681f3Smrg enum radeon_family family; 687ec681f3Smrg enum ac_target_machine_options tm_options; 697ec681f3Smrg unsigned wave_size; 707ec681f3Smrg struct ac_compiler_passes *passes; 7101e04c3fSmrg}; 7201e04c3fSmrg 7301e04c3fSmrg/* we have to store a linked list per thread due to the possiblity of multiple gpus being required */ 7401e04c3fSmrgstatic thread_local std::list<radv_llvm_per_thread_info> radv_llvm_per_thread_list; 7501e04c3fSmrg 767ec681f3Smrgbool 777ec681f3Smrgradv_compile_to_elf(struct ac_llvm_compiler *info, LLVMModuleRef module, char **pelf_buffer, 787ec681f3Smrg size_t *pelf_size) 7901e04c3fSmrg{ 807ec681f3Smrg radv_llvm_per_thread_info *thread_info = nullptr; 817ec681f3Smrg 827ec681f3Smrg for (auto &I : radv_llvm_per_thread_list) { 837ec681f3Smrg if (I.llvm_info.tm == info->tm) { 847ec681f3Smrg thread_info = &I; 857ec681f3Smrg break; 867ec681f3Smrg } 877ec681f3Smrg } 887ec681f3Smrg 897ec681f3Smrg if (!thread_info) { 907ec681f3Smrg struct ac_compiler_passes *passes = ac_create_llvm_passes(info->tm); 917ec681f3Smrg bool ret = ac_compile_module_to_elf(passes, module, pelf_buffer, pelf_size); 927ec681f3Smrg ac_destroy_llvm_passes(passes); 937ec681f3Smrg return ret; 947ec681f3Smrg } 957ec681f3Smrg 967ec681f3Smrg return thread_info->compile_to_memory_buffer(module, pelf_buffer, pelf_size); 9701e04c3fSmrg} 9801e04c3fSmrg 997ec681f3Smrgbool 1007ec681f3Smrgradv_init_llvm_compiler(struct ac_llvm_compiler *info, enum radeon_family family, 1017ec681f3Smrg enum ac_target_machine_options tm_options, unsigned wave_size) 10201e04c3fSmrg{ 1037ec681f3Smrg for (auto &I : radv_llvm_per_thread_list) { 1047ec681f3Smrg if (I.is_same(family, tm_options, wave_size)) { 1057ec681f3Smrg *info = I.llvm_info; 1067ec681f3Smrg return true; 1077ec681f3Smrg } 1087ec681f3Smrg } 1097ec681f3Smrg 1107ec681f3Smrg radv_llvm_per_thread_list.emplace_back(family, tm_options, wave_size); 1117ec681f3Smrg radv_llvm_per_thread_info &tinfo = radv_llvm_per_thread_list.back(); 1127ec681f3Smrg 1137ec681f3Smrg if (!tinfo.init()) { 1147ec681f3Smrg radv_llvm_per_thread_list.pop_back(); 1157ec681f3Smrg return false; 1167ec681f3Smrg } 1177ec681f3Smrg 1187ec681f3Smrg *info = tinfo.llvm_info; 1197ec681f3Smrg return true; 12001e04c3fSmrg} 121