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