source: CLRX/CLRadeonExtender/trunk/amdasm/DisasmROCm.cpp @ 2533

Last change on this file since 2533 was 2533, checked in by matszpk, 4 years ago

CLRadeonExtender: Change type of offset and size fields in ROCmRegion.

File size: 21.1 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2016 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstdint>
22#include <cstdio>
23#include <inttypes.h>
24#include <string>
25#include <ostream>
26#include <memory>
27#include <vector>
28#include <utility>
29#include <CLRX/utils/Utilities.h>
30#include <CLRX/utils/MemAccess.h>
31#include <CLRX/amdbin/ROCmBinaries.h>
32#include <CLRX/amdasm/Disassembler.h>
33#include <CLRX/utils/GPUId.h>
34#include "DisasmInternals.h"
35
36using namespace CLRX;
37
38struct AMDGPUArchValues
39{
40    uint32_t major;
41    uint32_t minor;
42    uint32_t stepping;
43    GPUDeviceType deviceType;
44};
45
46static const AMDGPUArchValues amdGpuArchValuesTbl[] =
47{
48    { 0, 0, 0, GPUDeviceType::CAPE_VERDE },
49    { 7, 0, 0, GPUDeviceType::BONAIRE },
50    { 7, 0, 1, GPUDeviceType::HAWAII },
51    { 8, 0, 0, GPUDeviceType::ICELAND },
52    { 8, 0, 1, GPUDeviceType::CARRIZO },
53    { 8, 0, 2, GPUDeviceType::ICELAND },
54    { 8, 0, 3, GPUDeviceType::FIJI },
55    { 8, 0, 4, GPUDeviceType::FIJI },
56    { 8, 1, 0, GPUDeviceType::STONEY }
57};
58
59static const size_t amdGpuArchValuesNum = sizeof(amdGpuArchValuesTbl) /
60                sizeof(AMDGPUArchValues);
61
62ROCmDisasmInput* CLRX::getROCmDisasmInputFromBinary(const ROCmBinary& binary)
63{
64    std::unique_ptr<ROCmDisasmInput> input(new ROCmDisasmInput);
65    uint32_t archMajor = 0;
66    input->archMinor = 0;
67    input->archStepping = 0;
68   
69    {
70        const cxbyte* noteContent = binary.getSectionContent(".note");
71        size_t notesSize = binary.getSectionHeader(".note").sh_size;
72        // find note about AMDGPU
73        for (size_t offset = 0; offset < notesSize; )
74        {
75            const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
76            size_t namesz = ULEV(nhdr->n_namesz);
77            size_t descsz = ULEV(nhdr->n_descsz);
78            if (usumGt(offset, namesz+descsz, notesSize))
79                throw Exception("Note offset+size out of range");
80            if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
81                ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
82            {    // AMDGPU type
83                const uint32_t* content = (const uint32_t*)
84                        (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
85                archMajor = ULEV(content[1]);
86                input->archMinor = ULEV(content[2]);
87                input->archStepping = ULEV(content[3]);
88            }
89            size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
90            offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
91        }
92    }
93    // determine device type
94    input->deviceType = GPUDeviceType::CAPE_VERDE;
95    if (archMajor==0)
96        input->deviceType = GPUDeviceType::CAPE_VERDE;
97    else if (archMajor==7)
98        input->deviceType = GPUDeviceType::BONAIRE;
99    else if (archMajor==8)
100        input->deviceType = GPUDeviceType::ICELAND;
101   
102    for (cxuint i = 0; i < amdGpuArchValuesNum; i++)
103        if (amdGpuArchValuesTbl[i].major==archMajor &&
104            amdGpuArchValuesTbl[i].minor==input->archMinor &&
105            amdGpuArchValuesTbl[i].stepping==input->archStepping)
106        {
107            input->deviceType = amdGpuArchValuesTbl[i].deviceType;
108            break;
109        }
110   
111    const size_t regionsNum = binary.getRegionsNum();
112    input->regions.resize(regionsNum);
113    size_t codeOffset = binary.getCode()-binary.getBinaryCode();
114    for (size_t i = 0; i < regionsNum; i++)
115    {
116        const ROCmRegion& region = binary.getRegion(i);
117        input->regions[i] = { region.regionName, size_t(region.size),
118            size_t(region.offset - codeOffset), region.isKernel };
119    }
120   
121    input->code = binary.getCode();
122    input->codeSize = binary.getCodeSize();
123    return input.release();
124}
125
126static void dumpKernelConfig(std::ostream& output, cxuint maxSgprsNum,
127             GPUArchitecture arch, const ROCmKernelConfig& config)
128{
129    output.write("    .config\n", 12);
130    // convert to native-endian
131    uint32_t amdCodeVersionMajor = ULEV(config.amdCodeVersionMajor);
132    uint32_t amdCodeVersionMinor = ULEV(config.amdCodeVersionMinor);
133    uint16_t amdMachineKind = ULEV(config.amdMachineKind);
134    uint16_t amdMachineMajor = ULEV(config.amdMachineMajor);
135    uint16_t amdMachineMinor = ULEV(config.amdMachineMinor);
136    uint16_t amdMachineStepping = ULEV(config.amdMachineStepping);
137    uint64_t kernelCodeEntryOffset = ULEV(config.kernelCodeEntryOffset);
138    uint64_t kernelCodePrefetchOffset = ULEV(config.kernelCodePrefetchOffset);
139    uint64_t kernelCodePrefetchSize = ULEV(config.kernelCodePrefetchSize);
140    uint64_t maxScrachBackingMemorySize = ULEV(config.maxScrachBackingMemorySize);
141    uint32_t computePgmRsrc1 = ULEV(config.computePgmRsrc1);
142    uint32_t computePgmRsrc2 = ULEV(config.computePgmRsrc2);
143    uint16_t enableSpgrRegisterFlags = ULEV(config.enableSpgrRegisterFlags);
144    uint16_t enableFeatureFlags = ULEV(config.enableFeatureFlags);
145    uint32_t workitemPrivateSegmentSize = ULEV(config.workitemPrivateSegmentSize);
146    uint32_t workgroupGroupSegmentSize = ULEV(config.workgroupGroupSegmentSize);
147    uint32_t gdsSegmentSize = ULEV(config.gdsSegmentSize);
148    uint64_t kernargSegmentSize = ULEV(config.kernargSegmentSize);
149    uint32_t workgroupFbarrierCount = ULEV(config.workgroupFbarrierCount);
150    uint16_t wavefrontSgprCount = ULEV(config.wavefrontSgprCount);
151    uint16_t workitemVgprCount = ULEV(config.workitemVgprCount);
152    uint16_t reservedVgprFirst = ULEV(config.reservedVgprFirst);
153    uint16_t reservedVgprCount = ULEV(config.reservedVgprCount);
154    uint16_t reservedSgprFirst = ULEV(config.reservedSgprFirst);
155    uint16_t reservedSgprCount = ULEV(config.reservedSgprCount);
156    uint16_t debugWavefrontPrivateSegmentOffsetSgpr =
157            ULEV(config.debugWavefrontPrivateSegmentOffsetSgpr);
158    uint16_t debugPrivateSegmentBufferSgpr = ULEV(config.debugPrivateSegmentBufferSgpr);
159    uint32_t callConvention = ULEV(config.callConvention);
160    uint64_t runtimeLoaderKernelSymbol = ULEV(config.runtimeLoaderKernelSymbol);
161   
162    size_t bufSize;
163    char buf[100];
164    const cxuint ldsShift = arch<GPUArchitecture::GCN1_1 ? 8 : 9;
165    const uint32_t pgmRsrc1 = computePgmRsrc1;
166    const uint32_t pgmRsrc2 = computePgmRsrc2;
167   
168    const cxuint dimMask = (pgmRsrc2 >> 7) & 7;
169    strcpy(buf, "        .dims ");
170    bufSize = 14;
171    if ((dimMask & 1) != 0)
172        buf[bufSize++] = 'x';
173    if ((dimMask & 2) != 0)
174        buf[bufSize++] = 'y';
175    if ((dimMask & 4) != 0)
176        buf[bufSize++] = 'z';
177    buf[bufSize++] = '\n';
178    output.write(buf, bufSize);
179   
180    bufSize = snprintf(buf, 100, "        .sgprsnum %u\n",
181              std::min((((pgmRsrc1>>6) & 0xf)<<3)+8, maxSgprsNum));
182    output.write(buf, bufSize);
183    bufSize = snprintf(buf, 100, "        .vgprsnum %u\n", ((pgmRsrc1 & 0x3f)<<2)+4);
184    output.write(buf, bufSize);
185    output.write(buf, bufSize);
186    if ((pgmRsrc1 & (1U<<20)) != 0)
187        output.write("        .privmode\n", 18);
188    if ((pgmRsrc1 & (1U<<22)) != 0)
189        output.write("        .debugmode\n", 19);
190    if ((pgmRsrc1 & (1U<<21)) != 0)
191        output.write("        .dx10clamp\n", 19);
192    if ((pgmRsrc1 & (1U<<23)) != 0)
193        output.write("        .ieeemode\n", 18);
194    if ((pgmRsrc2 & 0x400) != 0)
195        output.write("        .tgsize\n", 16);
196   
197    bufSize = snprintf(buf, 100, "        .floatmode 0x%02x\n", (pgmRsrc1>>12) & 0xff);
198    output.write(buf, bufSize);
199    bufSize = snprintf(buf, 100, "        .priority %u\n", (pgmRsrc1>>10) & 3);
200    output.write(buf, bufSize);
201    if (((pgmRsrc1>>24) & 0x7f) != 0)
202    {
203        bufSize = snprintf(buf, 100, "        .exceptions 0x%02x\n",
204                   (pgmRsrc1>>24) & 0x7f);
205        output.write(buf, bufSize);
206    }
207    const cxuint localSize = ((pgmRsrc2>>15) & 0x1ff) << ldsShift;
208    if (localSize!=0)
209    {
210        bufSize = snprintf(buf, 100, "        .localsize %u\n", localSize);
211        output.write(buf, bufSize);
212    }
213    bufSize = snprintf(buf, 100, "        .userdatanum %u\n", (pgmRsrc2>>1) & 0x1f);
214    output.write(buf, bufSize);
215   
216    bufSize = snprintf(buf, 100, "        .pgmrsrc1 0x%08x\n", pgmRsrc1);
217    output.write(buf, bufSize);
218    bufSize = snprintf(buf, 100, "        .pgmrsrc2 0x%08x\n", pgmRsrc2);
219    output.write(buf, bufSize);
220   
221    bufSize = snprintf(buf, 100, "        .codeversion %u, %u\n",
222                   amdCodeVersionMajor, amdCodeVersionMinor);
223    output.write(buf, bufSize);
224    bufSize = snprintf(buf, 100, "        .machine %hu, %hu, %hu, %hu\n",
225                   amdMachineKind, amdMachineMajor,
226                   amdMachineMinor, amdMachineStepping);
227    output.write(buf, bufSize);
228    bufSize = snprintf(buf, 100, "        .kernel_code_entry_offset 0x%" PRIx64 "\n",
229                       kernelCodeEntryOffset);
230    output.write(buf, bufSize);
231    if (kernelCodePrefetchOffset!=0)
232    {
233        bufSize = snprintf(buf, 100,
234                   "        .kernel_code_prefetch_offset 0x%" PRIx64 "\n",
235                           kernelCodePrefetchOffset);
236        output.write(buf, bufSize);
237    }
238    if (kernelCodePrefetchSize!=0)
239    {
240        bufSize = snprintf(buf, 100, "        .kernel_code_prefetch_size %" PRIu64 "\n",
241                           kernelCodePrefetchSize);
242        output.write(buf, bufSize);
243    }
244    if (maxScrachBackingMemorySize!=0)
245    {
246        bufSize = snprintf(buf, 100, "        .max_scratch_backing_memory %" PRIu64 "\n",
247                           maxScrachBackingMemorySize);
248        output.write(buf, bufSize);
249    }
250   
251    const uint16_t sgprFlags = enableSpgrRegisterFlags;
252    if ((sgprFlags&1) != 0)
253        output.write("        .use_private_segment_buffer\n", 36);
254    if ((sgprFlags&2) != 0)
255        output.write("        .use_dispatch_ptr\n", 26);
256    if ((sgprFlags&4) != 0)
257        output.write("        .use_queue_ptr\n", 24);
258    if ((sgprFlags&8) != 0)
259        output.write("        .use_kernarg_segment_ptr\n", 33);
260    if ((sgprFlags&16) != 0)
261        output.write("        .use_dispatch_id\n", 25);
262    if ((sgprFlags&32) != 0)
263        output.write("        .use_flat_scratch_init\n", 31);
264    if ((sgprFlags&64) != 0)
265        output.write("        .use_private_segment_size\n", 34);
266    if ((sgprFlags&128) != 0)
267        output.write("        .use_grid_workgroup_count_x\n", 36);
268    if ((sgprFlags&256) != 0)
269        output.write("        .use_grid_workgroup_count_y\n", 36);
270    if ((sgprFlags&512) != 0)
271        output.write("        .use_grid_workgroup_count_z\n", 36);
272    const uint16_t featureFlags = enableFeatureFlags;
273    if ((featureFlags&1) != 0)
274        output.write("        .use_ordered_append_gds\n", 32);
275    bufSize = snprintf(buf, 100, "        .private_elem_size %u\n",
276                       2U<<((featureFlags>>1)&3));
277    output.write(buf, bufSize);
278    if ((featureFlags&8) != 0)
279        output.write("        .use_ptr64\n", 19);
280    if ((featureFlags&16) != 0)
281        output.write("        .use_dynamic_call_stack\n", 32);
282    if ((featureFlags&32) != 0)
283        output.write("        .use_debug_enabled\n", 27);
284    if ((featureFlags&64) != 0)
285        output.write("        .use_xnack_enabled\n", 27);
286   
287    if (workitemPrivateSegmentSize!=0)
288    {
289        bufSize = snprintf(buf, 100, "        .workitem_private_segment_size %u\n",
290                         workitemPrivateSegmentSize);
291        output.write(buf, bufSize);
292    }
293    if (workgroupGroupSegmentSize!=0)
294    {
295        bufSize = snprintf(buf, 100, "        .workgroup_group_segment_size %u\n",
296                         workgroupGroupSegmentSize);
297        output.write(buf, bufSize);
298    }
299    if (gdsSegmentSize!=0)
300    {
301        bufSize = snprintf(buf, 100, "        .gds_segment_size %u\n",
302                         gdsSegmentSize);
303        output.write(buf, bufSize);
304    }
305    if (kernargSegmentSize!=0)
306    {
307        bufSize = snprintf(buf, 100, "        .kernarg_segment_size %" PRIu64 "\n",
308                         kernargSegmentSize);
309        output.write(buf, bufSize);
310    }
311    if (workgroupFbarrierCount!=0)
312    {
313        bufSize = snprintf(buf, 100, "        .workgroup_fbarrier_count %u\n",
314                         workgroupFbarrierCount);
315        output.write(buf, bufSize);
316    }
317    if (wavefrontSgprCount!=0)
318    {
319        bufSize = snprintf(buf, 100, "        .wavefront_sgpr_count %hu\n",
320                         wavefrontSgprCount);
321        output.write(buf, bufSize);
322    }
323    if (workitemVgprCount!=0)
324    {
325        bufSize = snprintf(buf, 100, "        .workitem_vgpr_count %hu\n",
326                         workitemVgprCount);
327        output.write(buf, bufSize);
328    }
329    if (reservedVgprFirst!=0)
330    {
331        bufSize = snprintf(buf, 100, "        .reserved_vgpr_first %hu\n",
332                         reservedVgprFirst);
333        output.write(buf, bufSize);
334    }
335    if (reservedVgprCount!=0)
336    {
337        bufSize = snprintf(buf, 100, "        .reserved_vgpr_count %hu\n",
338                         reservedVgprCount);
339        output.write(buf, bufSize);
340    }
341    if (reservedSgprFirst!=0)
342    {
343        bufSize = snprintf(buf, 100, "        .reserved_sgpr_first %hu\n",
344                         reservedSgprFirst);
345        output.write(buf, bufSize);
346    }
347    if (reservedSgprCount!=0)
348    {
349        bufSize = snprintf(buf, 100, "        .reserved_sgpr_count %hu\n",
350                         reservedSgprCount);
351        output.write(buf, bufSize);
352    }
353    if (debugWavefrontPrivateSegmentOffsetSgpr!=0)
354    {
355        bufSize = snprintf(buf, 100, "        "
356                        ".debug_wavefront_private_segment_offset_sgpr %hu\n",
357                         debugWavefrontPrivateSegmentOffsetSgpr);
358        output.write(buf, bufSize);
359    }
360    if (debugPrivateSegmentBufferSgpr!=0)
361    {
362        bufSize = snprintf(buf, 100, "        .debug_private_segment_buffer_sgpr %hu\n",
363                         debugPrivateSegmentBufferSgpr);
364        output.write(buf, bufSize);
365    }
366    bufSize = snprintf(buf, 100, "        .kernarg_segment_align %u\n",
367                     1U<<(config.kernargSegmentAlignment));
368    output.write(buf, bufSize);
369    bufSize = snprintf(buf, 100, "        .group_segment_align %u\n",
370                     1U<<(config.groupSegmentAlignment));
371    output.write(buf, bufSize);
372    bufSize = snprintf(buf, 100, "        .private_segment_align %u\n",
373                     1U<<(config.privateSegmentAlignment));
374    output.write(buf, bufSize);
375    bufSize = snprintf(buf, 100, "        .wavefront_size %u\n",
376                     1U<<(config.wavefrontSize));
377    output.write(buf, bufSize);
378    bufSize = snprintf(buf, 100, "        .call_convention 0x%x\n",
379                     callConvention);
380    output.write(buf, bufSize);
381    if (runtimeLoaderKernelSymbol!=0)
382    {
383        bufSize = snprintf(buf, 100,
384                   "        .runtime_loader_kernel_symbol 0x%" PRIx64 "\n",
385                         runtimeLoaderKernelSymbol);
386        output.write(buf, bufSize);
387    }
388    // new section, control_directive, outside .config
389    output.write("    .control_directive\n", 23);
390    printDisasmData(sizeof config.controlDirective, config.controlDirective, output, true);
391}
392
393void CLRX::disassembleROCm(std::ostream& output, const ROCmDisasmInput* rocmInput,
394           ISADisassembler* isaDisassembler, size_t& sectionCount, Flags flags)
395{
396    const bool doDumpData = ((flags & DISASM_DUMPDATA) != 0);
397    const bool doMetadata = ((flags & (DISASM_METADATA|DISASM_CONFIG)) != 0);
398    const bool doDumpCode = ((flags & DISASM_DUMPCODE) != 0);
399    const bool doDumpConfig = ((flags & DISASM_CONFIG) != 0);
400   
401    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(rocmInput->deviceType);
402    const cxuint maxSgprsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
403   
404    {
405        char buf[40];
406        size_t size = snprintf(buf, 40, ".arch_minor %u\n", rocmInput->archMinor);
407        output.write(buf, size);
408        size = snprintf(buf, 40, ".arch_stepping %u\n", rocmInput->archStepping);
409        output.write(buf, size);
410    }
411   
412    for (const ROCmDisasmRegionInput& rinput: rocmInput->regions)
413        if (rinput.isKernel)
414        {
415            output.write(".kernel ", 8);
416            output.write(rinput.regionName.c_str(), rinput.regionName.size());
417            output.put('\n');
418            if (doMetadata && doDumpConfig)
419                dumpKernelConfig(output, maxSgprsNum, arch,
420                     *reinterpret_cast<const ROCmKernelConfig*>(
421                             rocmInput->code + rinput.offset));
422        }
423   
424    const size_t regionsNum = rocmInput->regions.size();
425    typedef std::pair<size_t, size_t> SortEntry;
426    std::unique_ptr<SortEntry[]> sorted(new SortEntry[regionsNum]);
427    for (size_t i = 0; i < regionsNum; i++)
428        sorted[i] = std::make_pair(rocmInput->regions[i].offset, i);
429    mapSort(sorted.get(), sorted.get() + regionsNum);
430   
431    if (rocmInput->code != nullptr && rocmInput->codeSize != 0)
432    {
433        const cxbyte* code = rocmInput->code;
434        output.write(".text\n", 6);
435        // clear labels
436        isaDisassembler->clearNumberedLabels();
437       
438        /// analyze code with collecting labels
439        for (size_t i = 0; i < regionsNum; i++)
440        {
441            const ROCmDisasmRegionInput& region = rocmInput->regions[sorted[i].second];
442            if (region.isKernel && doDumpCode)
443            {
444                isaDisassembler->setInput(region.size-256, code + region.offset+256,
445                                    region.offset+256);
446                isaDisassembler->analyzeBeforeDisassemble();
447            }
448            isaDisassembler->addNamedLabel(region.offset, region.regionName);
449        }
450        isaDisassembler->prepareLabelsAndRelocations();
451       
452        ISADisassembler::LabelIter curLabel;
453        ISADisassembler::NamedLabelIter curNamedLabel;
454        const auto& labels = isaDisassembler->getLabels();
455        const auto& namedLabels = isaDisassembler->getNamedLabels();
456        // real disassemble
457        size_t prevRegionPos = 0;
458        for (size_t i = 0; i < regionsNum; i++)
459        {
460            const ROCmDisasmRegionInput& region = rocmInput->regions[sorted[i].second];
461            // set labelIters to previous position
462            isaDisassembler->setInput(prevRegionPos, code + region.offset,
463                                    region.offset, prevRegionPos);
464            curLabel = std::lower_bound(labels.begin(), labels.end(), prevRegionPos);
465            curNamedLabel = std::lower_bound(namedLabels.begin(), namedLabels.end(),
466                std::make_pair(prevRegionPos, CString()),
467                  [](const std::pair<size_t,CString>& a,
468                                 const std::pair<size_t, CString>& b)
469                  { return a.first < b.first; });
470            isaDisassembler->writeLabelsToPosition(0, curLabel, curNamedLabel);
471            isaDisassembler->flushOutput();
472           
473            if (region.isKernel)
474            {
475                if (doMetadata)
476                {
477                    if (!doDumpConfig)
478                        printDisasmData(0x100, code + region.offset, output, true);
479                    else    // skip, config was dumped in kernel configuration
480                        output.write(".skip 256\n", 10);
481                }
482               
483                if (doDumpCode)
484                {
485                    isaDisassembler->setInput(region.size-256, code + region.offset+256,
486                                    region.offset+256, region.offset+1);
487                    isaDisassembler->setDontPrintLabels(i+1<regionsNum);
488                    isaDisassembler->disassemble();
489                }
490                /* previous position 1 byte after kernel region
491                 * labels at end will be printed by 'disassemble' */
492                prevRegionPos = region.offset + region.size + 1;
493            }
494            else if (doDumpData)
495            {
496                output.write(".global ", 8);
497                output.write(region.regionName.c_str(), region.regionName.size());
498                output.write("\n", 1);
499                printDisasmData(region.size, code + region.offset, output, true);
500                prevRegionPos = region.offset+1; // previous position byte after region
501            }
502        }
503       
504        if (regionsNum!=0 && !rocmInput->regions[sorted[regionsNum-1].second].isKernel)
505        {   // if last region is kernel, then print labels after last region
506            const ROCmDisasmRegionInput& region =
507                        rocmInput->regions[sorted[regionsNum-1].second];
508            isaDisassembler->writeLabelsToEnd(region.size, curLabel, curNamedLabel);
509            isaDisassembler->flushOutput();
510        }
511    }
512}
Note: See TracBrowser for help on using the repository browser.