1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2018 Google 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "aco_interface.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "aco_ir.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "vulkan/radv_shader_args.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "util/memstream.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include <array> 34bf215546Sopenharmony_ci#include <iostream> 35bf215546Sopenharmony_ci#include <vector> 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic const std::array<aco_compiler_statistic_info, aco::num_statistics> statistic_infos = []() 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci std::array<aco_compiler_statistic_info, aco::num_statistics> ret{}; 40bf215546Sopenharmony_ci ret[aco::statistic_hash] = 41bf215546Sopenharmony_ci aco_compiler_statistic_info{"Hash", "CRC32 hash of code and constant data"}; 42bf215546Sopenharmony_ci ret[aco::statistic_instructions] = 43bf215546Sopenharmony_ci aco_compiler_statistic_info{"Instructions", "Instruction count"}; 44bf215546Sopenharmony_ci ret[aco::statistic_copies] = 45bf215546Sopenharmony_ci aco_compiler_statistic_info{"Copies", "Copy instructions created for pseudo-instructions"}; 46bf215546Sopenharmony_ci ret[aco::statistic_branches] = aco_compiler_statistic_info{"Branches", "Branch instructions"}; 47bf215546Sopenharmony_ci ret[aco::statistic_latency] = 48bf215546Sopenharmony_ci aco_compiler_statistic_info{"Latency", "Issue cycles plus stall cycles"}; 49bf215546Sopenharmony_ci ret[aco::statistic_inv_throughput] = aco_compiler_statistic_info{ 50bf215546Sopenharmony_ci "Inverse Throughput", "Estimated busy cycles to execute one wave"}; 51bf215546Sopenharmony_ci ret[aco::statistic_vmem_clauses] = aco_compiler_statistic_info{ 52bf215546Sopenharmony_ci "VMEM Clause", "Number of VMEM clauses (includes 1-sized clauses)"}; 53bf215546Sopenharmony_ci ret[aco::statistic_smem_clauses] = aco_compiler_statistic_info{ 54bf215546Sopenharmony_ci "SMEM Clause", "Number of SMEM clauses (includes 1-sized clauses)"}; 55bf215546Sopenharmony_ci ret[aco::statistic_sgpr_presched] = 56bf215546Sopenharmony_ci aco_compiler_statistic_info{"Pre-Sched SGPRs", "SGPR usage before scheduling"}; 57bf215546Sopenharmony_ci ret[aco::statistic_vgpr_presched] = 58bf215546Sopenharmony_ci aco_compiler_statistic_info{"Pre-Sched VGPRs", "VGPR usage before scheduling"}; 59bf215546Sopenharmony_ci return ret; 60bf215546Sopenharmony_ci}(); 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ciconst unsigned aco_num_statistics = aco::num_statistics; 63bf215546Sopenharmony_ciconst aco_compiler_statistic_info* aco_statistic_infos = statistic_infos.data(); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ciuint64_t 66bf215546Sopenharmony_ciaco_get_codegen_flags() 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci aco::init(); 69bf215546Sopenharmony_ci /* Exclude flags which don't affect code generation. */ 70bf215546Sopenharmony_ci uint64_t exclude = aco::DEBUG_VALIDATE_IR | aco::DEBUG_VALIDATE_RA | aco::DEBUG_PERFWARN | 71bf215546Sopenharmony_ci aco::DEBUG_PERF_INFO | aco::DEBUG_LIVE_INFO; 72bf215546Sopenharmony_ci return aco::debug_flags & ~exclude; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_cistatic void 76bf215546Sopenharmony_civalidate(aco::Program* program) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci if (!(aco::debug_flags & aco::DEBUG_VALIDATE_IR)) 79bf215546Sopenharmony_ci return; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci ASSERTED bool is_valid = aco::validate_ir(program); 82bf215546Sopenharmony_ci assert(is_valid); 83bf215546Sopenharmony_ci} 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cistatic std::string 86bf215546Sopenharmony_ciget_disasm_string(aco::Program* program, std::vector<uint32_t>& code, 87bf215546Sopenharmony_ci unsigned exec_size) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci std::string disasm; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci if (check_print_asm_support(program)) { 92bf215546Sopenharmony_ci char* data = NULL; 93bf215546Sopenharmony_ci size_t disasm_size = 0; 94bf215546Sopenharmony_ci struct u_memstream mem; 95bf215546Sopenharmony_ci if (u_memstream_open(&mem, &data, &disasm_size)) { 96bf215546Sopenharmony_ci FILE* const memf = u_memstream_get(&mem); 97bf215546Sopenharmony_ci aco::print_asm(program, code, exec_size / 4u, memf); 98bf215546Sopenharmony_ci fputc(0, memf); 99bf215546Sopenharmony_ci u_memstream_close(&mem); 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci disasm = std::string(data, data + disasm_size); 103bf215546Sopenharmony_ci free(data); 104bf215546Sopenharmony_ci } else { 105bf215546Sopenharmony_ci disasm = "Shader disassembly is not supported in the current configuration" 106bf215546Sopenharmony_ci#ifndef LLVM_AVAILABLE 107bf215546Sopenharmony_ci " (LLVM not available)" 108bf215546Sopenharmony_ci#endif 109bf215546Sopenharmony_ci ".\n"; 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci return disasm; 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_cistatic std::string 116bf215546Sopenharmony_ciaco_postprocess_shader(const struct aco_compiler_options* options, 117bf215546Sopenharmony_ci const struct radv_shader_args *args, 118bf215546Sopenharmony_ci std::unique_ptr<aco::Program>& program) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci std::string llvm_ir; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci if (options->dump_preoptir) 123bf215546Sopenharmony_ci aco_print_program(program.get(), stderr); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci aco::live live_vars; 126bf215546Sopenharmony_ci if (!args->is_trap_handler_shader) { 127bf215546Sopenharmony_ci /* Phi lowering */ 128bf215546Sopenharmony_ci aco::lower_phis(program.get()); 129bf215546Sopenharmony_ci aco::dominator_tree(program.get()); 130bf215546Sopenharmony_ci validate(program.get()); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci /* Optimization */ 133bf215546Sopenharmony_ci if (!options->key.optimisations_disabled) { 134bf215546Sopenharmony_ci if (!(aco::debug_flags & aco::DEBUG_NO_VN)) 135bf215546Sopenharmony_ci aco::value_numbering(program.get()); 136bf215546Sopenharmony_ci if (!(aco::debug_flags & aco::DEBUG_NO_OPT)) 137bf215546Sopenharmony_ci aco::optimize(program.get()); 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci /* cleanup and exec mask handling */ 141bf215546Sopenharmony_ci aco::setup_reduce_temp(program.get()); 142bf215546Sopenharmony_ci aco::insert_exec_mask(program.get()); 143bf215546Sopenharmony_ci validate(program.get()); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci /* spilling and scheduling */ 146bf215546Sopenharmony_ci live_vars = aco::live_var_analysis(program.get()); 147bf215546Sopenharmony_ci aco::spill(program.get(), live_vars); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci if (options->record_ir) { 151bf215546Sopenharmony_ci char* data = NULL; 152bf215546Sopenharmony_ci size_t size = 0; 153bf215546Sopenharmony_ci u_memstream mem; 154bf215546Sopenharmony_ci if (u_memstream_open(&mem, &data, &size)) { 155bf215546Sopenharmony_ci FILE* const memf = u_memstream_get(&mem); 156bf215546Sopenharmony_ci aco_print_program(program.get(), memf); 157bf215546Sopenharmony_ci fputc(0, memf); 158bf215546Sopenharmony_ci u_memstream_close(&mem); 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci llvm_ir = std::string(data, data + size); 162bf215546Sopenharmony_ci free(data); 163bf215546Sopenharmony_ci } 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci if (program->collect_statistics) 166bf215546Sopenharmony_ci aco::collect_presched_stats(program.get()); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if ((aco::debug_flags & aco::DEBUG_LIVE_INFO) && options->dump_shader) 169bf215546Sopenharmony_ci aco_print_program(program.get(), stderr, live_vars, aco::print_live_vars | aco::print_kill); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci if (!args->is_trap_handler_shader) { 172bf215546Sopenharmony_ci if (!options->key.optimisations_disabled && !(aco::debug_flags & aco::DEBUG_NO_SCHED)) 173bf215546Sopenharmony_ci aco::schedule_program(program.get(), live_vars); 174bf215546Sopenharmony_ci validate(program.get()); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* Register Allocation */ 177bf215546Sopenharmony_ci aco::register_allocation(program.get(), live_vars.live_out); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci if (aco::validate_ra(program.get())) { 180bf215546Sopenharmony_ci aco_print_program(program.get(), stderr); 181bf215546Sopenharmony_ci abort(); 182bf215546Sopenharmony_ci } else if (options->dump_shader) { 183bf215546Sopenharmony_ci aco_print_program(program.get(), stderr); 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci validate(program.get()); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci /* Optimization */ 189bf215546Sopenharmony_ci if (!options->key.optimisations_disabled && !(aco::debug_flags & aco::DEBUG_NO_OPT)) { 190bf215546Sopenharmony_ci aco::optimize_postRA(program.get()); 191bf215546Sopenharmony_ci validate(program.get()); 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci aco::ssa_elimination(program.get()); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci /* Lower to HW Instructions */ 198bf215546Sopenharmony_ci aco::lower_to_hw_instr(program.get()); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci /* Insert Waitcnt */ 201bf215546Sopenharmony_ci aco::insert_wait_states(program.get()); 202bf215546Sopenharmony_ci aco::insert_NOPs(program.get()); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci if (program->gfx_level >= GFX10) 205bf215546Sopenharmony_ci aco::form_hard_clauses(program.get()); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (program->collect_statistics || (aco::debug_flags & aco::DEBUG_PERF_INFO)) 208bf215546Sopenharmony_ci aco::collect_preasm_stats(program.get()); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci return llvm_ir; 211bf215546Sopenharmony_ci} 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_civoid 214bf215546Sopenharmony_ciaco_compile_shader(const struct aco_compiler_options* options, 215bf215546Sopenharmony_ci const struct aco_shader_info* info, 216bf215546Sopenharmony_ci unsigned shader_count, struct nir_shader* const* shaders, 217bf215546Sopenharmony_ci const struct radv_shader_args *args, 218bf215546Sopenharmony_ci aco_callback *build_binary, 219bf215546Sopenharmony_ci void **binary) 220bf215546Sopenharmony_ci{ 221bf215546Sopenharmony_ci aco::init(); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci ac_shader_config config = {0}; 224bf215546Sopenharmony_ci std::unique_ptr<aco::Program> program{new aco::Program}; 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci program->collect_statistics = options->record_stats; 227bf215546Sopenharmony_ci if (program->collect_statistics) 228bf215546Sopenharmony_ci memset(program->statistics, 0, sizeof(program->statistics)); 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci program->debug.func = options->debug.func; 231bf215546Sopenharmony_ci program->debug.private_data = options->debug.private_data; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* Instruction Selection */ 234bf215546Sopenharmony_ci if (args->is_gs_copy_shader) 235bf215546Sopenharmony_ci aco::select_gs_copy_shader(program.get(), shaders[0], &config, options, info, args); 236bf215546Sopenharmony_ci else if (args->is_trap_handler_shader) 237bf215546Sopenharmony_ci aco::select_trap_handler_shader(program.get(), shaders[0], &config, options, info, args); 238bf215546Sopenharmony_ci else 239bf215546Sopenharmony_ci aco::select_program(program.get(), shader_count, shaders, &config, options, info, args); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci std::string llvm_ir = aco_postprocess_shader(options, args, program); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci /* assembly */ 244bf215546Sopenharmony_ci std::vector<uint32_t> code; 245bf215546Sopenharmony_ci unsigned exec_size = aco::emit_program(program.get(), code); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (program->collect_statistics) 248bf215546Sopenharmony_ci aco::collect_postasm_stats(program.get(), code); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci bool get_disasm = options->dump_shader || options->record_ir; 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci std::string disasm; 253bf215546Sopenharmony_ci if (get_disasm) 254bf215546Sopenharmony_ci disasm = get_disasm_string(program.get(), code, exec_size); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci size_t stats_size = 0; 257bf215546Sopenharmony_ci if (program->collect_statistics) 258bf215546Sopenharmony_ci stats_size = aco::num_statistics * sizeof(uint32_t); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci (*build_binary)(binary, 261bf215546Sopenharmony_ci shaders[shader_count - 1]->info.stage, 262bf215546Sopenharmony_ci args->is_gs_copy_shader, 263bf215546Sopenharmony_ci &config, 264bf215546Sopenharmony_ci llvm_ir.c_str(), 265bf215546Sopenharmony_ci llvm_ir.size(), 266bf215546Sopenharmony_ci disasm.c_str(), 267bf215546Sopenharmony_ci disasm.size(), 268bf215546Sopenharmony_ci program->statistics, 269bf215546Sopenharmony_ci stats_size, 270bf215546Sopenharmony_ci exec_size, 271bf215546Sopenharmony_ci code.data(), 272bf215546Sopenharmony_ci code.size()); 273bf215546Sopenharmony_ci} 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_civoid 276bf215546Sopenharmony_ciaco_compile_vs_prolog(const struct aco_compiler_options* options, 277bf215546Sopenharmony_ci const struct aco_shader_info* info, 278bf215546Sopenharmony_ci const struct aco_vs_prolog_key* key, 279bf215546Sopenharmony_ci const struct radv_shader_args* args, 280bf215546Sopenharmony_ci aco_shader_part_callback *build_prolog, 281bf215546Sopenharmony_ci void **binary) 282bf215546Sopenharmony_ci{ 283bf215546Sopenharmony_ci aco::init(); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci /* create program */ 286bf215546Sopenharmony_ci ac_shader_config config = {0}; 287bf215546Sopenharmony_ci std::unique_ptr<aco::Program> program{new aco::Program}; 288bf215546Sopenharmony_ci program->collect_statistics = false; 289bf215546Sopenharmony_ci program->debug.func = NULL; 290bf215546Sopenharmony_ci program->debug.private_data = NULL; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci /* create IR */ 293bf215546Sopenharmony_ci unsigned num_preserved_sgprs; 294bf215546Sopenharmony_ci aco::select_vs_prolog(program.get(), key, &config, options, info, args, &num_preserved_sgprs); 295bf215546Sopenharmony_ci aco::insert_NOPs(program.get()); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (options->dump_shader) 298bf215546Sopenharmony_ci aco_print_program(program.get(), stderr); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci /* assembly */ 301bf215546Sopenharmony_ci std::vector<uint32_t> code; 302bf215546Sopenharmony_ci code.reserve(align(program->blocks[0].instructions.size() * 2, 16)); 303bf215546Sopenharmony_ci unsigned exec_size = aco::emit_program(program.get(), code); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci bool get_disasm = options->dump_shader || options->record_ir; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci std::string disasm; 308bf215546Sopenharmony_ci if (get_disasm) 309bf215546Sopenharmony_ci disasm = get_disasm_string(program.get(), code, exec_size); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci (*build_prolog)(binary, 312bf215546Sopenharmony_ci config.num_sgprs, 313bf215546Sopenharmony_ci config.num_vgprs, 314bf215546Sopenharmony_ci num_preserved_sgprs, 315bf215546Sopenharmony_ci code.data(), 316bf215546Sopenharmony_ci code.size(), 317bf215546Sopenharmony_ci disasm.data(), 318bf215546Sopenharmony_ci disasm.size()); 319bf215546Sopenharmony_ci} 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_civoid 322bf215546Sopenharmony_ciaco_compile_ps_epilog(const struct aco_compiler_options* options, 323bf215546Sopenharmony_ci const struct aco_shader_info* info, 324bf215546Sopenharmony_ci const struct aco_ps_epilog_key* key, 325bf215546Sopenharmony_ci const struct radv_shader_args* args, 326bf215546Sopenharmony_ci aco_shader_part_callback* build_epilog, 327bf215546Sopenharmony_ci void** binary) 328bf215546Sopenharmony_ci{ 329bf215546Sopenharmony_ci aco::init(); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci ac_shader_config config = {0}; 332bf215546Sopenharmony_ci std::unique_ptr<aco::Program> program{new aco::Program}; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci program->collect_statistics = options->record_stats; 335bf215546Sopenharmony_ci if (program->collect_statistics) 336bf215546Sopenharmony_ci memset(program->statistics, 0, sizeof(program->statistics)); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci program->debug.func = options->debug.func; 339bf215546Sopenharmony_ci program->debug.private_data = options->debug.private_data; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci /* Instruction selection */ 342bf215546Sopenharmony_ci aco::select_ps_epilog(program.get(), key, &config, options, info, args); 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci aco_postprocess_shader(options, args, program); 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci /* assembly */ 347bf215546Sopenharmony_ci std::vector<uint32_t> code; 348bf215546Sopenharmony_ci unsigned exec_size = aco::emit_program(program.get(), code); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci bool get_disasm = options->dump_shader || options->record_ir; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci std::string disasm; 353bf215546Sopenharmony_ci if (get_disasm) 354bf215546Sopenharmony_ci disasm = get_disasm_string(program.get(), code, exec_size); 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci (*build_epilog)(binary, 357bf215546Sopenharmony_ci config.num_sgprs, 358bf215546Sopenharmony_ci config.num_vgprs, 359bf215546Sopenharmony_ci 0, 360bf215546Sopenharmony_ci code.data(), 361bf215546Sopenharmony_ci code.size(), 362bf215546Sopenharmony_ci disasm.data(), 363bf215546Sopenharmony_ci disasm.size()); 364bf215546Sopenharmony_ci} 365