source: CLRX/CLRadeonExtender/trunk/amdasm/AsmROCmFormat.cpp @ 2597

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

CLRadeonExtender: AsmROCm: Some part of code for prepareBinary.

File size: 49.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 <cstdio>
22#include <cstring>
23#include <string>
24#include <vector>
25#include <utility>
26#include <algorithm>
27#include <CLRX/utils/Utilities.h>
28#include <CLRX/amdasm/Assembler.h>
29#include "AsmInternals.h"
30
31using namespace CLRX;
32
33static const char* rocmPseudoOpNamesTbl[] =
34{
35    "call_convention", "codeversion", "config",
36    "control_directive", "debug_private_segment_buffer_sgpr",
37    "debug_wavefront_private_segment_offset_sgpr",
38    "debugmode", "dims", "dx10clamp",
39    "exceptions", "floatmode", "gds_segment_size",
40    "group_segment_align", "ieeemode", "kcode",
41    "kcodeend", "kernarg_segment_align",
42    "kernarg_segment_size", "kernel_code_entry_offset",
43    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
44    "localsize", "machine", "max_scratch_backing_memory",
45    "pgmrsrc1", "pgmrsrc2", "priority", "private_segment_align",
46    "privmode", "reserved_sgpr_count", "reserved_sgpr_first",
47    "reserved_vgpr_count", "reserved_vgpr_first",
48    "runtime_loader_kernel_symbol",
49    "scratchbuffer", "sgprsnum", "tgsize",
50    "use_debug_enabled", "use_dispatch_id",
51    "use_dispatch_ptr", "use_dynamic_call_stack",
52    "use_flat_scratch_init", "use_grid_workgroup_count",
53    "use_kernarg_segment_ptr", "use_ordered_append_gds",
54    "use_private_segment_size", "use_ptr64", "use_queue_ptr",
55    "use_private_segment_buffer", "use_xnack_enabled",
56    "userdatanum", "vgprsnum", "wavefront_sgpr_count",
57    "wavefront_size", "workitem_vgpr_count",
58    "workgroup_fbarrier_count", "workgroup_group_segment_size",
59    "workitem_private_segment_size"
60};
61
62enum
63{
64    ROCMOP_CALL_CONVENTION, ROCMOP_CODEVERSION, ROCMOP_CONFIG,
65    ROCMOP_CONTROL_DIRECTIVE, ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
66    ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
67    ROCMOP_DEBUGMODE, ROCMOP_DIMS, ROCMOP_DX10CLAMP,
68    ROCMOP_EXCEPTIONS, ROCMOP_FLOATMODE, ROCMOP_GDS_SEGMENT_SIZE,
69    ROCMOP_GROUP_SEGMENT_ALIGN, ROCMOP_IEEEMODE, ROCMOP_KCODE,
70    ROCMOP_KCODEEND, ROCMOP_KERNARG_SEGMENT_ALIGN,
71    ROCMOP_KERNARG_SEGMENT_SIZE, ROCMOP_KERNEL_CODE_ENTRY_OFFSET,
72    ROCMOP_KERNEL_CODE_PREFETCH_OFFSET, ROCMOP_KERNEL_CODE_PREFETCH_SIZE,
73    ROCMOP_LOCALSIZE, ROCMOP_MACHINE, ROCMOP_MAX_SCRATCH_BACKING_MEMORY,
74    ROCMOP_PGMRSRC1, ROCMOP_PGMRSRC2, ROCMOP_PRIORITY, ROCMOP_PRIVATE_SEGMENT_ALIGN,
75    ROCMOP_PRIVMODE, ROCMOP_RESERVED_SGPR_COUNT, ROCMOP_RESERVED_SGPR_FIRST,
76    ROCMOP_RESERVED_VGPR_COUNT, ROCMOP_RESERVED_VGPR_FIRST,
77    ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
78    ROCMOP_SCRATCHBUFFER, ROCMOP_SGPRSNUM, ROCMOP_TGSIZE,
79    ROCMOP_USE_DEBUG_ENABLED, ROCMOP_USE_DISPATCH_ID,
80    ROCMOP_USE_DISPATCH_PTR, ROCMOP_USE_DYNAMIC_CALL_STACK,
81    ROCMOP_USE_FLAT_SCRATCH_INIT, ROCMOP_USE_GRID_WORKGROUP_COUNT,
82    ROCMOP_USE_KERNARG_SEGMENT_PTR, ROCMOP_USE_ORDERED_APPEND_GDS,
83    ROCMOP_USE_PRIVATE_SEGMENT_SIZE, ROCMOP_USE_PTR64, ROCMOP_USE_QUEUE_PTR,
84    ROCMOP_USE_PRIVATE_SEGMENT_BUFFER, ROCMOP_USE_XNACK_ENABLED,
85    ROCMOP_USERDATANUM, ROCMOP_VGPRSNUM, ROCMOP_WAVEFRONT_SGPR_COUNT,
86    ROCMOP_WAVEFRONT_SIZE, ROCMOP_WORKITEM_VGPR_COUNT,
87    ROCMOP_WORKGROUP_FBARRIER_COUNT, ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
88    ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE
89};
90
91/*
92 * ROCm format handler
93 */
94
95AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
96             output{}, codeSection(0), commentSection(ASMSECT_NONE),
97             extraSectionCount(0)
98{
99    assembler.currentKernel = ASMKERN_GLOBAL;
100    assembler.currentSection = 0;
101    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
102                ELFSECTID_TEXT, ".text" });
103    currentKcodeKernel = ASMKERN_GLOBAL;
104    savedSection = 0;
105}
106
107AsmROCmHandler::~AsmROCmHandler()
108{
109    for (Kernel* kernel: kernelStates)
110        delete kernel;
111}
112
113cxuint AsmROCmHandler::addKernel(const char* kernelName)
114{
115    cxuint thisKernel = output.symbols.size();
116    cxuint thisSection = sections.size();
117    output.addEmptyKernel(kernelName);
118    /// add kernel config section
119    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
120    kernelStates.push_back(new Kernel{ thisSection, nullptr, ASMSECT_NONE, thisSection });
121   
122    if (assembler.currentKernel == ASMKERN_GLOBAL)
123        savedSection = assembler.currentSection;
124   
125    assembler.currentKernel = thisKernel;
126    assembler.currentSection = thisSection;
127    return thisKernel;
128}
129
130cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
131{
132    const cxuint thisSection = sections.size();
133    Section section;
134    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
135       
136    if (::strcmp(sectionName, ".text") == 0) // code
137    {
138        if (codeSection!=ASMSECT_NONE)
139            throw AsmFormatException("Only one section '.text' can be in binary");
140        codeSection = thisSection;
141        section.type = AsmSectionType::CODE;
142        section.elfBinSectId = ELFSECTID_TEXT;
143        section.name = ".text"; // set static name (available by whole lifecycle)
144    }
145    else if (::strcmp(sectionName, ".comment") == 0) // comment
146    {
147        if (commentSection!=ASMSECT_NONE)
148            throw AsmFormatException("Only one section '.comment' can be in binary");
149        commentSection = thisSection;
150        section.type = AsmSectionType::GALLIUM_COMMENT;
151        section.elfBinSectId = ELFSECTID_COMMENT;
152        section.name = ".comment"; // set static name (available by whole lifecycle)
153    }
154    else
155    {
156        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
157                    thisSection));
158        if (!out.second)
159            throw AsmFormatException("Section already exists");
160        section.type = AsmSectionType::EXTRA_SECTION;
161        section.elfBinSectId = extraSectionCount++;
162        /// reference entry is available and unchangeable by whole lifecycle of section map
163        section.name = out.first->first.c_str();
164    }
165    sections.push_back(section);
166   
167    assembler.currentKernel = ASMKERN_GLOBAL;
168    assembler.currentSection = thisSection;
169    return thisSection;
170}
171
172cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
173{
174    if (::strcmp(sectionName, ".text") == 0) // code
175        return codeSection;
176    else if (::strcmp(sectionName, ".comment") == 0) // comment
177        return commentSection;
178    else
179    {
180        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
181        if (it != extraSectionMap.end())
182            return it->second;
183    }
184    return ASMSECT_NONE;
185}
186
187void AsmROCmHandler::setCurrentKernel(cxuint kernel)
188{
189    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
190        throw AsmFormatException("KernelId out of range");
191   
192    if (assembler.currentKernel == ASMKERN_GLOBAL)
193        savedSection = assembler.currentSection;
194    else // if kernel
195        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
196   
197    assembler.currentKernel = kernel;
198    if (kernel != ASMKERN_GLOBAL)
199        assembler.currentSection = kernelStates[kernel]->savedSection;
200    else // default main section
201        assembler.currentSection = savedSection;
202}
203
204void AsmROCmHandler::setCurrentSection(cxuint sectionId)
205{
206    if (sectionId >= sections.size())
207        throw AsmFormatException("SectionId out of range");
208   
209    if (assembler.currentKernel == ASMKERN_GLOBAL)
210        savedSection = assembler.currentSection;
211    else // if kernel
212        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
213   
214    assembler.currentSection = sectionId;
215    assembler.currentKernel = sections[sectionId].kernelId;
216}
217
218
219AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
220{
221    if (sectionId >= sections.size())
222        throw AsmFormatException("Section doesn't exists");
223   
224    AsmFormatHandler::SectionInfo info;
225    info.type = sections[sectionId].type;
226    info.flags = 0;
227    if (info.type == AsmSectionType::CODE)
228        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
229    else if (info.type != AsmSectionType::CONFIG)
230        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
231   
232    info.name = sections[sectionId].name;
233    return info;
234}
235
236void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
237{
238    if (currentKcodeKernel != ASMKERN_GLOBAL)
239    {
240        Kernel& newKernel = *kernelStates[currentKcodeKernel];
241        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
242                            newKernel.allocRegFlags);
243    }
244}
245
246void AsmROCmHandler::saveKcodeCurrentAllocRegs()
247{
248    if (currentKcodeKernel != ASMKERN_GLOBAL)
249    {   // save other state
250        size_t regTypesNum;
251        Kernel& oldKernel = *kernelStates[currentKcodeKernel];
252        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
253                            regTypesNum, oldKernel.allocRegFlags);
254        std::copy(regs, regs+2, oldKernel.allocRegs);
255    }
256}
257
258
259void AsmROCmHandler::handleLabel(const CString& label)
260{
261    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
262        return;
263    auto kit = assembler.kernelMap.find(label);
264    if (kit == assembler.kernelMap.end())
265        return;
266    if (!kcodeSelection.empty())
267        return; // do not change if inside kcode
268    // save other state
269    saveKcodeCurrentAllocRegs();
270    // restore this state
271    currentKcodeKernel = kit->second;
272    restoreKcodeCurrentAllocRegs();
273}
274
275void AsmROCmHandler::Kernel::initializeKernelConfig()
276{
277    if (!config)
278    {
279        config.reset(new AsmROCmKernelConfig{});
280        ::memset(config.get(), 0, sizeof(AsmROCmKernelConfig));
281    }
282}
283
284namespace CLRX
285{
286
287bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
288{
289    if (string.empty() || string[0] != '.')
290        return false;
291    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
292                sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
293               CStringLess()) - rocmPseudoOpNamesTbl;
294    return pseudoOp < sizeof(rocmPseudoOpNamesTbl)/sizeof(char*);
295}
296   
297void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
298                  const char* linePtr)
299{
300    Assembler& asmr = handler.assembler;
301    const char* end = asmr.line + asmr.lineSize;
302    if (asmr.currentKernel==ASMKERN_GLOBAL)
303    {
304        asmr.printError(pseudoOpPlace, "Kernel config can be defined only inside kernel");
305        return;
306    }
307   
308    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
309    {
310        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
311        return;
312    }
313    skipSpacesToEnd(linePtr, end);
314    if (!checkGarbagesAtEnd(asmr, linePtr))
315        return;
316    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
317}
318
319void AsmROCmPseudoOps::doControlDirective(AsmROCmHandler& handler,
320              const char* pseudoOpPlace, const char* linePtr)
321{
322    Assembler& asmr = handler.assembler;
323    const char* end = asmr.line + asmr.lineSize;
324    if (asmr.currentKernel==ASMKERN_GLOBAL)
325    {
326        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
327                    "only inside kernel");
328        return;
329    }
330    skipSpacesToEnd(linePtr, end);
331    if (!checkGarbagesAtEnd(asmr, linePtr))
332        return;
333   
334    AsmROCmHandler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
335    if (kernel.ctrlDirSection == ASMSECT_NONE)
336    {
337        cxuint thisSection = handler.sections.size();
338        handler.sections.push_back({ asmr.currentKernel,
339            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
340            ELFSECTID_UNDEF, nullptr });
341        kernel.ctrlDirSection = thisSection;
342    }
343    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
344    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
345}
346
347void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
348                  const char* linePtr, ROCmConfigValueTarget target)
349{
350    Assembler& asmr = handler.assembler;
351    const char* end = asmr.line + asmr.lineSize;
352   
353    if (asmr.currentKernel==ASMKERN_GLOBAL ||
354        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
355    {
356        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
357        return;
358    }
359   
360    skipSpacesToEnd(linePtr, end);
361    const char* valuePlace = linePtr;
362    uint64_t value = BINGEN64_NOTSUPPLIED;
363    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
364    /* ranges checking */
365    if (good)
366    {
367        switch(target)
368        {
369            case ROCMCVAL_SGPRSNUM:
370            {
371                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
372                            asmr.deviceType);
373                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
374                if (value > maxSGPRsNum)
375                {
376                    char buf[64];
377                    snprintf(buf, 64, "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
378                    asmr.printError(valuePlace, buf);
379                    good = false;
380                }
381                break;
382            }
383            case ROCMCVAL_VGPRSNUM:
384            {
385                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
386                            asmr.deviceType);
387                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
388                if (value > maxVGPRsNum)
389                {
390                    char buf[64];
391                    snprintf(buf, 64, "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
392                    asmr.printError(valuePlace, buf);
393                    good = false;
394                }
395                break;
396            }
397            case ROCMCVAL_EXCEPTIONS:
398                asmr.printWarningForRange(7, value,
399                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
400                value &= 0x7f;
401                break;
402            case ROCMCVAL_FLOATMODE:
403                asmr.printWarningForRange(8, value,
404                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
405                value &= 0xff;
406                break;
407            case ROCMCVAL_PRIORITY:
408                asmr.printWarningForRange(2, value,
409                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
410                value &= 3;
411                break;
412            case ROCMCVAL_LOCALSIZE:
413            {
414                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
415                            asmr.deviceType);
416                const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
417                if (value > maxLocalSize)
418                {
419                    char buf[64];
420                    snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
421                    asmr.printError(valuePlace, buf);
422                    good = false;
423                }
424                break;
425            }
426            case ROCMCVAL_USERDATANUM:
427                if (value > 16)
428                {
429                    asmr.printError(valuePlace, "UserDataNum out of range (0-16)");
430                    good = false;
431                }
432                break;
433            default:
434                break;
435        }
436    }
437    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
438        return;
439   
440    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
441    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
442    // set value
443    switch(target)
444    {
445        case ROCMCVAL_SGPRSNUM:
446            config.usedSGPRsNum = value;
447            break;
448        case ROCMCVAL_VGPRSNUM:
449            config.usedVGPRsNum = value;
450            break;
451        case ROCMCVAL_PGMRSRC1:
452            config.computePgmRsrc1 = value;
453            break;
454        case ROCMCVAL_PGMRSRC2:
455            config.computePgmRsrc2 = value;
456            break;
457        case ROCMCVAL_FLOATMODE:
458            config.floatMode = value;
459            break;
460        case ROCMCVAL_LOCALSIZE:
461            config.localSize = value;
462            break;
463        case ROCMCVAL_SCRATCHBUFFER:
464            config.scratchBufferSize = value;
465            break;
466        case ROCMCVAL_PRIORITY:
467            config.priority = value;
468            break;
469        case ROCMCVAL_USERDATANUM:
470            config.userDataNum = value;
471            break;
472        case ROCMCVAL_EXCEPTIONS:
473            config.exceptions = value;
474            break;
475        case ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET:
476            config.kernelCodeEntryOffset = value;
477            break;
478        case ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET:
479            config.kernelCodePrefetchOffset = value;
480            break;
481        case ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE:
482            config.kernelCodePrefetchSize = value;
483            break;
484        case ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY:
485            config.maxScrachBackingMemorySize = value;
486            break;
487        case ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE:
488            config.workitemPrivateSegmentSize = value;
489            break;
490        case ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE:
491            config.workgroupGroupSegmentSize = value;
492            break;
493        case ROCMCVAL_GDS_SEGMENT_SIZE:
494            config.gdsSegmentSize = value;
495            break;
496        case ROCMCVAL_KERNARG_SEGMENT_SIZE:
497            config.kernargSegmentSize = value;
498            break;
499        case ROCMCVAL_WORKGROUP_FBARRIER_COUNT:
500            config.workgroupFbarrierCount = value;
501            break;
502        case ROCMCVAL_WAVEFRONT_SGPR_COUNT:
503            config.wavefrontSgprCount = value;
504            break;
505        case ROCMCVAL_WORKITEM_VGPR_COUNT:
506            config.workitemVgprCount = value;
507            break;
508        case ROCMCVAL_RESERVED_VGPR_FIRST:
509            config.reservedVgprFirst = value;
510            break;
511        case ROCMCVAL_RESERVED_VGPR_COUNT:
512            config.reservedVgprCount = value;
513            break;
514        case ROCMCVAL_RESERVED_SGPR_FIRST:
515            config.reservedSgprFirst = value;
516            break;
517        case ROCMCVAL_RESERVED_SGPR_COUNT:
518            config.reservedSgprCount = value;
519            break;
520        case ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
521            config.debugWavefrontPrivateSegmentOffsetSgpr = value;
522            break;
523        case ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
524            config.debugPrivateSegmentBufferSgpr = value;
525            break;
526        case ROCMCVAL_KERNARG_SEGMENT_ALIGN:
527            config.kernargSegmentAlignment = value;
528            break;
529        case ROCMCVAL_GROUP_SEGMENT_ALIGN:
530            config.groupSegmentAlignment = value;
531            break;
532        case ROCMCVAL_PRIVATE_SEGMENT_ALIGN:
533            config.privateSegmentAlignment = value;
534            break;
535        case ROCMCVAL_WAVEFRONT_SIZE:
536            config.wavefrontSize = value;
537            break;
538        case ROCMCVAL_CALL_CONVENTION:
539            config.callConvention = value;
540            break;
541        case ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL:
542            config.runtimeLoaderKernelSymbol = value;
543            break;
544        default:
545            break;
546    }
547}
548
549void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
550          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
551{
552    Assembler& asmr = handler.assembler;
553    const char* end = asmr.line + asmr.lineSize;
554   
555    if (asmr.currentKernel==ASMKERN_GLOBAL ||
556        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
557    {
558        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
559        return;
560    }
561   
562    skipSpacesToEnd(linePtr, end);
563    if (!checkGarbagesAtEnd(asmr, linePtr))
564        return;
565   
566    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
567    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
568   
569    switch(target)
570    {
571        case ROCMCVAL_PRIVMODE:
572            config.privilegedMode = true;
573            break;
574        case ROCMCVAL_DEBUGMODE:
575            config.debugMode = true;
576            break;
577        case ROCMCVAL_DX10CLAMP:
578            config.dx10Clamp = true;
579            break;
580        case ROCMCVAL_IEEEMODE:
581            config.ieeeMode = true;
582            break;
583        case ROCMCVAL_TGSIZE:
584            config.tgSize = true;
585            break;
586        case ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER:
587            config.enableSpgrRegisterFlags |= 1;
588            break;
589        case ROCMCVAL_USE_DISPATCH_PTR:
590            config.enableSpgrRegisterFlags |= 2;
591            break;
592        case ROCMCVAL_USE_QUEUE_PTR:
593            config.enableSpgrRegisterFlags |= 4;
594            break;
595        case ROCMCVAL_USE_KERNARG_SEGMENT_PTR:
596            config.enableSpgrRegisterFlags |= 8;
597            break;
598        case ROCMCVAL_USE_DISPATCH_ID:
599            config.enableSpgrRegisterFlags |= 16;
600            break;
601        case ROCMCVAL_USE_FLAT_SCRATCH_INIT:
602            config.enableSpgrRegisterFlags |= 32;
603            break;
604        case ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE:
605            config.enableSpgrRegisterFlags |= 64;
606            break;
607        case ROCMCVAL_USE_ORDERED_APPEND_GDS:
608            config.enableFeatureFlags |= 1;
609            break;
610        case ROCMCVAL_USE_PTR64:
611            config.enableFeatureFlags |= 8;
612            break;
613        case ROCMCVAL_USE_DYNAMIC_CALL_STACK:
614            config.enableFeatureFlags |= 16;
615            break;
616        case ROCMCVAL_USE_DEBUG_ENABLED:
617            config.enableFeatureFlags |= 32;
618            break;
619        case ROCMCVAL_USE_XNACK_ENABLED:
620            config.enableFeatureFlags |= 64;
621            break;
622        default:
623            break;
624    }
625}
626
627void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
628                  const char* linePtr)
629{
630    Assembler& asmr = handler.assembler;
631    if (asmr.currentKernel==ASMKERN_GLOBAL ||
632        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
633    {
634        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
635        return;
636    }
637    cxuint dimMask = 0;
638    if (!parseDimensions(asmr, linePtr, dimMask))
639        return;
640    if (!checkGarbagesAtEnd(asmr, linePtr))
641        return;
642    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
643    handler.kernelStates[asmr.currentKernel]->config->dimMask = dimMask;
644}
645
646void AsmROCmPseudoOps::setMachine(AsmROCmHandler& handler, const char* pseudoOpPlace,
647                      const char* linePtr)
648{
649    Assembler& asmr = handler.assembler;
650    const char* end = asmr.line + asmr.lineSize;
651    if (asmr.currentKernel==ASMKERN_GLOBAL ||
652        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
653    {
654        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
655        return;
656    }
657   
658    skipSpacesToEnd(linePtr, end);
659    uint64_t kindValue = BINGEN_NOTSUPPLIED;
660    uint64_t majorValue = BINGEN_NOTSUPPLIED;
661    uint64_t minorValue = BINGEN_NOTSUPPLIED;
662    uint64_t steppingValue = BINGEN_NOTSUPPLIED;
663    bool good = getAbsoluteValueArg(asmr, kindValue, linePtr, true);
664    if (!skipRequiredComma(asmr, linePtr))
665        return;
666    good &= getAbsoluteValueArg(asmr, majorValue, linePtr, true);
667    if (!skipRequiredComma(asmr, linePtr))
668        return;
669    good &= getAbsoluteValueArg(asmr, minorValue, linePtr, true);
670    if (!skipRequiredComma(asmr, linePtr))
671        return;
672    good &= getAbsoluteValueArg(asmr, steppingValue, linePtr, true);
673   
674    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
675        return;
676   
677    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
678    AsmROCmKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
679    config->amdMachineKind = kindValue;
680    config->amdMachineMajor = majorValue;
681    config->amdMachineMinor = minorValue;
682    config->amdMachineStepping = steppingValue;
683}
684
685void AsmROCmPseudoOps::setCodeVersion(AsmROCmHandler& handler, const char* pseudoOpPlace,
686                  const char* linePtr)
687{
688    Assembler& asmr = handler.assembler;
689    const char* end = asmr.line + asmr.lineSize;
690    if (asmr.currentKernel==ASMKERN_GLOBAL ||
691        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
692    {
693        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
694        return;
695    }
696   
697    skipSpacesToEnd(linePtr, end);
698    uint64_t majorValue = BINGEN_NOTSUPPLIED;
699    uint64_t minorValue = BINGEN_NOTSUPPLIED;
700    bool good = getAbsoluteValueArg(asmr, majorValue, linePtr, true);
701    if (!skipRequiredComma(asmr, linePtr))
702        return;
703    good &= getAbsoluteValueArg(asmr, minorValue, linePtr, true);
704   
705    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
706        return;
707   
708    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
709    AsmROCmKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
710    config->amdCodeVersionMajor = majorValue;
711    config->amdCodeVersionMinor = minorValue;
712}
713
714void AsmROCmPseudoOps::setUseGridWorkGroupCount(AsmROCmHandler& handler,
715                   const char* pseudoOpPlace, const char* linePtr)
716{
717    Assembler& asmr = handler.assembler;
718    if (asmr.currentKernel==ASMKERN_GLOBAL ||
719        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
720    {
721        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
722        return;
723    }
724    cxuint dimMask = 0;
725    if (!parseDimensions(asmr, linePtr, dimMask))
726        return;
727    if (!checkGarbagesAtEnd(asmr, linePtr))
728        return;
729    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
730    uint16_t& flags = handler.kernelStates[asmr.currentKernel]->config->
731                enableSpgrRegisterFlags;
732    flags = (flags & ~(7<<7)) | dimMask<<7;
733}
734
735void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
736                  const std::vector<cxuint>& oldset)
737{
738    Assembler& asmr = handler.assembler;
739    // old elements - join current regstate with all them
740    size_t regTypesNum;
741    for (auto it = oldset.begin(); it != oldset.end(); ++it)
742    {
743        Flags curAllocRegFlags;
744        const cxuint* curAllocRegs = asmr.isaAssembler->getAllocatedRegisters(regTypesNum,
745                               curAllocRegFlags);
746        cxuint newAllocRegs[2];
747        AsmROCmHandler::Kernel& kernel = *(handler.kernelStates[*it]);
748        newAllocRegs[0] = std::max(curAllocRegs[0], kernel.allocRegs[0]);
749        newAllocRegs[1] = std::max(curAllocRegs[1], kernel.allocRegs[1]);
750        kernel.allocRegFlags |= curAllocRegFlags;
751        std::copy(newAllocRegs, newAllocRegs+2, kernel.allocRegs);
752    }
753    asmr.isaAssembler->setAllocatedRegisters();
754}
755
756void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
757                  const char* linePtr)
758{
759    Assembler& asmr = handler.assembler;
760    const char* end = asmr.line + asmr.lineSize;
761    bool good = true;
762    skipSpacesToEnd(linePtr, end);
763    if (linePtr==end)
764        return;
765    std::unordered_set<cxuint> newSel(handler.kcodeSelection.begin(),
766                          handler.kcodeSelection.end());
767    do {
768        CString kname;
769        const char* knamePlace = linePtr;
770        skipSpacesToEnd(linePtr, end);
771        bool removeKernel = false;
772        if (linePtr!=end && *linePtr=='-')
773        {   // '-' - remove this kernel from current kernel selection
774            removeKernel = true;
775            linePtr++;
776        }
777        else if (linePtr!=end && *linePtr=='+')
778        {
779            linePtr++;
780            skipSpacesToEnd(linePtr, end);
781            if (linePtr==end)
782            {   // add all kernels
783                for (cxuint k = 0; k < handler.kernelStates.size(); k++)
784                    newSel.insert(k);
785                break;
786            }
787        }
788       
789        if (!getNameArg(asmr, kname, linePtr, "kernel"))
790        { good = false; continue; }
791        auto kit = asmr.kernelMap.find(kname);
792        if (kit == asmr.kernelMap.end())
793        {
794            asmr.printError(knamePlace, "Kernel not found");
795            continue;
796        }
797        if (!removeKernel)
798            newSel.insert(kit->second);
799        else // remove kernel
800            newSel.erase(kit->second);
801    } while (skipCommaForMultipleArgs(asmr, linePtr));
802   
803    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
804        return;
805   
806    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
807    {
808        asmr.printError(pseudoOpPlace, "KCode outside code");
809        return;
810    }
811    if (handler.kcodeSelStack.empty())
812        handler.saveKcodeCurrentAllocRegs();
813    // push to stack
814    handler.kcodeSelStack.push(handler.kcodeSelection);
815    // set current sel
816    handler.kcodeSelection.assign(newSel.begin(), newSel.end());
817   
818    std::sort(handler.kcodeSelection.begin(), handler.kcodeSelection.end());
819    updateKCodeSel(handler, handler.kcodeSelStack.top());
820}
821
822void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
823                  const char* linePtr)
824{
825    Assembler& asmr = handler.assembler;
826    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
827    {
828        asmr.printError(pseudoOpPlace, "KCodeEnd outside code");
829        return;
830    }
831    if (handler.kcodeSelStack.empty())
832    {
833        asmr.printError(pseudoOpPlace, "'.kcodeend' without '.kcode'");
834        return;
835    }
836    updateKCodeSel(handler, handler.kcodeSelection);
837    handler.kcodeSelection = handler.kcodeSelStack.top();
838    handler.kcodeSelStack.pop();
839    if (handler.kcodeSelStack.empty())
840        handler.restoreKcodeCurrentAllocRegs();
841}
842
843}
844
845bool AsmROCmHandler::parsePseudoOp(const CString& firstName, const char* stmtPlace,
846               const char* linePtr)
847{
848    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
849                    sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
850                   CStringLess()) - rocmPseudoOpNamesTbl;
851   
852    switch(pseudoOp)
853    {
854        case ROCMOP_CALL_CONVENTION:
855            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
856                             ROCMCVAL_CALL_CONVENTION);
857            break;
858        case ROCMOP_CODEVERSION:
859            AsmROCmPseudoOps::setCodeVersion(*this, stmtPlace, linePtr);
860            break;
861        case ROCMOP_CONFIG:
862            AsmROCmPseudoOps::doConfig(*this, stmtPlace, linePtr);
863            break;
864        case ROCMOP_CONTROL_DIRECTIVE:
865            AsmROCmPseudoOps::doControlDirective(*this, stmtPlace, linePtr);
866            break;
867        case ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
868            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
869                             ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
870            break;
871        case ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
872            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
873                         ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
874            break;
875        case ROCMOP_DEBUGMODE:
876            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
877                             ROCMCVAL_DEBUGMODE);
878            break;
879        case ROCMOP_DIMS:
880            AsmROCmPseudoOps::setDimensions(*this, stmtPlace, linePtr);
881            break;
882        case ROCMOP_DX10CLAMP:
883            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
884                             ROCMCVAL_DX10CLAMP);
885            break;
886        case ROCMOP_EXCEPTIONS:
887            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
888                             ROCMCVAL_EXCEPTIONS);
889            break;
890        case ROCMOP_FLOATMODE:
891            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
892                             ROCMCVAL_FLOATMODE);
893            break;
894        case ROCMOP_GDS_SEGMENT_SIZE:
895            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
896                             ROCMCVAL_GDS_SEGMENT_SIZE);
897            break;
898        case ROCMOP_GROUP_SEGMENT_ALIGN:
899            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
900                             ROCMCVAL_GROUP_SEGMENT_ALIGN);
901            break;
902        case ROCMOP_IEEEMODE:
903            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
904                             ROCMCVAL_IEEEMODE);
905            break;
906        case ROCMOP_KCODE:
907            AsmROCmPseudoOps::doKCode(*this, stmtPlace, linePtr);
908            break;
909        case ROCMOP_KCODEEND:
910            AsmROCmPseudoOps::doKCodeEnd(*this, stmtPlace, linePtr);
911            break;
912        case ROCMOP_KERNARG_SEGMENT_ALIGN:
913            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
914                             ROCMCVAL_KERNARG_SEGMENT_ALIGN);
915            break;
916        case ROCMOP_KERNARG_SEGMENT_SIZE:
917            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
918                             ROCMCVAL_KERNARG_SEGMENT_SIZE);
919            break;
920        case ROCMOP_KERNEL_CODE_ENTRY_OFFSET:
921            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
922                             ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET);
923            break;
924        case ROCMOP_KERNEL_CODE_PREFETCH_OFFSET:
925            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
926                             ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET);
927            break;
928        case ROCMOP_KERNEL_CODE_PREFETCH_SIZE:
929            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
930                             ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE);
931            break;
932        case ROCMOP_LOCALSIZE:
933            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
934                             ROCMCVAL_LOCALSIZE);
935            break;
936        case ROCMOP_MACHINE:
937            AsmROCmPseudoOps::setMachine(*this, stmtPlace, linePtr);
938            break;
939        case ROCMOP_MAX_SCRATCH_BACKING_MEMORY:
940            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
941                             ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY);
942            break;
943        case ROCMOP_PGMRSRC1:
944            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC1);
945            break;
946        case ROCMOP_PGMRSRC2:
947            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC2);
948            break;
949        case ROCMOP_PRIORITY:
950            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PRIORITY);
951            break;
952        case ROCMOP_PRIVATE_SEGMENT_ALIGN:
953            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
954                             ROCMCVAL_PRIVATE_SEGMENT_ALIGN);
955            break;
956        case ROCMOP_PRIVMODE:
957            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
958                             ROCMCVAL_PRIVMODE);
959            break;
960        case ROCMOP_RESERVED_SGPR_COUNT:
961            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
962                             ROCMCVAL_RESERVED_SGPR_COUNT);
963            break;
964        case ROCMOP_RESERVED_SGPR_FIRST:
965            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
966                             ROCMCVAL_RESERVED_SGPR_FIRST);
967            break;
968        case ROCMOP_RESERVED_VGPR_COUNT:
969            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
970                             ROCMCVAL_RESERVED_VGPR_COUNT);
971            break;
972        case ROCMOP_RESERVED_VGPR_FIRST:
973            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
974                             ROCMCVAL_RESERVED_VGPR_FIRST);
975            break;
976        case ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
977            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
978                             ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
979            break;
980        case ROCMOP_SCRATCHBUFFER:
981            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
982                             ROCMCVAL_SCRATCHBUFFER);
983            break;
984        case ROCMOP_SGPRSNUM:
985            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
986                             ROCMCVAL_SGPRSNUM);
987            break;
988        case ROCMOP_TGSIZE:
989            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
990                             ROCMCVAL_TGSIZE);
991            break;
992        case ROCMOP_USE_DEBUG_ENABLED:
993            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
994                             ROCMCVAL_USE_DEBUG_ENABLED);
995            break;
996        case ROCMOP_USE_DISPATCH_ID:
997            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
998                             ROCMCVAL_USE_DISPATCH_ID);
999            break;
1000        case ROCMOP_USE_DISPATCH_PTR:
1001            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1002                             ROCMCVAL_USE_DISPATCH_PTR);
1003            break;
1004        case ROCMOP_USE_DYNAMIC_CALL_STACK:
1005            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1006                             ROCMCVAL_USE_DYNAMIC_CALL_STACK);
1007            break;
1008        case ROCMOP_USE_FLAT_SCRATCH_INIT:
1009            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1010                             ROCMCVAL_USE_FLAT_SCRATCH_INIT);
1011            break;
1012        case ROCMOP_USE_GRID_WORKGROUP_COUNT:
1013            AsmROCmPseudoOps::setUseGridWorkGroupCount(*this, stmtPlace, linePtr);
1014            break;
1015        case ROCMOP_USE_KERNARG_SEGMENT_PTR:
1016            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1017                             ROCMCVAL_USE_KERNARG_SEGMENT_PTR);
1018            break;
1019        case ROCMOP_USE_ORDERED_APPEND_GDS:
1020            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1021                             ROCMCVAL_USE_ORDERED_APPEND_GDS);
1022            break;
1023        case ROCMOP_USE_PRIVATE_SEGMENT_SIZE:
1024            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1025                             ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE);
1026            break;
1027        case ROCMOP_USE_PTR64:
1028            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1029                             ROCMCVAL_USE_PTR64);
1030            break;
1031        case ROCMOP_USE_QUEUE_PTR:
1032            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1033                             ROCMCVAL_USE_QUEUE_PTR);
1034            break;
1035        case ROCMOP_USE_PRIVATE_SEGMENT_BUFFER:
1036            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1037                             ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER);
1038            break;
1039        case ROCMOP_USE_XNACK_ENABLED:
1040            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1041                             ROCMCVAL_USE_XNACK_ENABLED);
1042            break;
1043        case ROCMOP_USERDATANUM:
1044            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1045                             ROCMCVAL_USERDATANUM);
1046            break;
1047        case ROCMOP_VGPRSNUM:
1048            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_VGPRSNUM);
1049            break;
1050        case ROCMOP_WAVEFRONT_SGPR_COUNT:
1051            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1052                             ROCMCVAL_WAVEFRONT_SGPR_COUNT);
1053            break;
1054        case ROCMOP_WAVEFRONT_SIZE:
1055            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1056                             ROCMCVAL_WAVEFRONT_SIZE);
1057            break;
1058        case ROCMOP_WORKITEM_VGPR_COUNT:
1059            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1060                             ROCMCVAL_WORKITEM_VGPR_COUNT);
1061            break;
1062        case ROCMOP_WORKGROUP_FBARRIER_COUNT:
1063            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1064                             ROCMCVAL_WORKGROUP_FBARRIER_COUNT);
1065            break;
1066        case ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
1067            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1068                             ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
1069            break;
1070        case ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
1071            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1072                             ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
1073            break;
1074        default:
1075            return false;
1076    }
1077    return true;
1078}
1079
1080bool AsmROCmHandler::prepareBinary()
1081{
1082    bool good = true;
1083    size_t sectionsNum = sections.size();
1084    size_t kernelsNum = kernelStates.size();
1085    output.deviceType = assembler.getDeviceType();
1086   
1087    if (assembler.isaAssembler!=nullptr)
1088    {   // make last kernel registers pool updates
1089        if (kcodeSelStack.empty())
1090            saveKcodeCurrentAllocRegs();
1091        else
1092            while (!kcodeSelStack.empty())
1093            {   // pop from kcode stack and apply changes
1094                AsmROCmPseudoOps::updateKCodeSel(*this, kcodeSelection);
1095                kcodeSelection = kcodeSelStack.top();
1096                kcodeSelStack.pop();
1097            }
1098    }
1099   
1100    for (size_t i = 0; i < sectionsNum; i++)
1101    {
1102        const AsmSection& asmSection = assembler.sections[i];
1103        const Section& section = sections[i];
1104        const size_t sectionSize = asmSection.getSize();
1105        const cxbyte* sectionData = (!asmSection.content.empty()) ?
1106                asmSection.content.data() : (const cxbyte*)"";
1107        switch(asmSection.type)
1108        {
1109            case AsmSectionType::CODE:
1110                output.codeSize = sectionSize;
1111                output.code = sectionData;
1112                break;
1113            case AsmSectionType::EXTRA_PROGBITS:
1114            case AsmSectionType::EXTRA_NOTE:
1115            case AsmSectionType::EXTRA_NOBITS:
1116            case AsmSectionType::EXTRA_SECTION:
1117            {
1118                uint32_t elfSectType =
1119                       (asmSection.type==AsmSectionType::EXTRA_NOTE) ? SHT_NOTE :
1120                       (asmSection.type==AsmSectionType::EXTRA_NOBITS) ? SHT_NOBITS :
1121                             SHT_PROGBITS;
1122                uint32_t elfSectFlags = 
1123                    ((asmSection.flags&ASMELFSECT_ALLOCATABLE) ? SHF_ALLOC : 0) |
1124                    ((asmSection.flags&ASMELFSECT_WRITEABLE) ? SHF_WRITE : 0) |
1125                    ((asmSection.flags&ASMELFSECT_EXECUTABLE) ? SHF_EXECINSTR : 0);
1126                output.extraSections.push_back({section.name, sectionSize, sectionData,
1127                    asmSection.alignment!=0?asmSection.alignment:1, elfSectType,
1128                    elfSectFlags, ELFSECTID_NULL, 0, 0 });
1129                break;
1130            }
1131            case AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE:
1132                if (sectionSize != 128)
1133                    assembler.printError(AsmSourcePos(),
1134                         (std::string("Section '.control_directive' for kernel '")+
1135                          assembler.kernels[section.kernelId].name+
1136                          "' have wrong size").c_str());
1137                break;
1138            case AsmSectionType::ROCM_COMMENT:
1139                output.commentSize = sectionSize;
1140                output.comment = (const char*)sectionData;
1141                break;
1142            default:
1143                break;
1144        }
1145    }
1146   
1147    GPUArchitecture arch = getGPUArchitectureFromDeviceType(assembler.deviceType);
1148    // set up number of the allocated SGPRs and VGPRs for kernel
1149    cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
1150    // prepare kernels configuration
1151    for (size_t i = 0; i < kernelStates.size(); i++)
1152    {
1153        const Kernel* kernel = kernelStates[i];
1154        if (kernel->config.get() == nullptr)
1155            continue;
1156        const CString& kernelName = assembler.kernels[i].name;
1157        AsmROCmKernelConfig& config = *kernel->config.get();
1158        // setup config
1159        cxuint userSGPRsNum = 4;
1160        /* include userData sgprs */
1161        cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1162                ((config.computePgmRsrc2>>7)&7);
1163        // extra sgprs for dimensions
1164        cxuint minRegsNum[2];
1165        getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1166                   ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1167                   ((config.scratchBufferSize!=0) ? GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1168       
1169        if (config.usedSGPRsNum!=BINGEN_DEFAULT && maxSGPRsNum < config.usedSGPRsNum)
1170        {   // check only if sgprsnum set explicitly
1171            char numBuf[64];
1172            snprintf(numBuf, 64, "(max %u)", maxSGPRsNum);
1173            assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1174                    "Number of total SGPRs for kernel '")+
1175                    kernelName.c_str()+"' is too high "+numBuf).c_str());
1176            good = false;
1177        }
1178       
1179        if (config.usedSGPRsNum==BINGEN_DEFAULT)
1180        {
1181            config.usedSGPRsNum = std::min(
1182                std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]) +
1183                    getGPUExtraRegsNum(arch, REGTYPE_SGPR, kernelStates[i]->allocRegFlags),
1184                    maxSGPRsNum); // include all extra sgprs
1185        }
1186        if (config.usedVGPRsNum==BINGEN_DEFAULT)
1187            config.usedVGPRsNum = std::max(minRegsNum[1], kernelStates[i]->allocRegs[1]);
1188        // to little endian
1189        SLEV(config.amdCodeVersionMajor, config.amdCodeVersionMajor);
1190        SLEV(config.amdCodeVersionMinor, config.amdCodeVersionMinor);
1191        SLEV(config.amdMachineKind, config.amdMachineKind);
1192        SLEV(config.amdMachineMajor, config.amdMachineMajor);
1193        SLEV(config.amdMachineMinor, config.amdMachineMinor);
1194        SLEV(config.amdMachineStepping, config.amdMachineStepping);
1195        SLEV(config.kernelCodeEntryOffset, config.kernelCodeEntryOffset);
1196        SLEV(config.kernelCodePrefetchOffset, config.kernelCodePrefetchOffset);
1197        SLEV(config.kernelCodePrefetchSize, config.kernelCodePrefetchSize);
1198        SLEV(config.maxScrachBackingMemorySize, config.maxScrachBackingMemorySize);
1199        SLEV(config.computePgmRsrc1, config.computePgmRsrc1);
1200        SLEV(config.computePgmRsrc2, config.computePgmRsrc2);
1201        SLEV(config.enableSpgrRegisterFlags, config.enableSpgrRegisterFlags);
1202        SLEV(config.enableFeatureFlags, config.enableFeatureFlags);
1203        SLEV(config.workitemPrivateSegmentSize, config.workitemPrivateSegmentSize);
1204        SLEV(config.workgroupGroupSegmentSize, config.workgroupGroupSegmentSize);
1205        SLEV(config.gdsSegmentSize, config.gdsSegmentSize);
1206        SLEV(config.kernargSegmentSize, config.kernargSegmentSize);
1207        SLEV(config.workgroupFbarrierCount, config.workgroupFbarrierCount);
1208        SLEV(config.wavefrontSgprCount, config.wavefrontSgprCount);
1209        SLEV(config.workitemVgprCount, config.workitemVgprCount);
1210        SLEV(config.reservedVgprFirst, config.reservedVgprFirst);
1211        SLEV(config.reservedVgprCount, config.reservedVgprCount);
1212        SLEV(config.reservedSgprFirst, config.reservedSgprFirst);
1213        SLEV(config.reservedSgprCount, config.reservedSgprCount);
1214        SLEV(config.debugWavefrontPrivateSegmentOffsetSgpr,
1215             config.debugWavefrontPrivateSegmentOffsetSgpr);
1216        SLEV(config.debugPrivateSegmentBufferSgpr, config.debugPrivateSegmentBufferSgpr);
1217        SLEV(config.callConvention, config.callConvention);
1218        SLEV(config.runtimeLoaderKernelSymbol, config.runtimeLoaderKernelSymbol);
1219    }
1220   
1221    const AsmSymbolMap& symbolMap = assembler.getSymbolMap();
1222    for (size_t ki = 0; ki < output.symbols.size(); ki++)
1223    {
1224        ROCmSymbolInput& kinput = output.symbols[ki];
1225        auto it = symbolMap.find(kinput.symbolName);
1226        if (it == symbolMap.end() || !it->second.isDefined())
1227        {   // error, undefined
1228            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1229                        "Symbol for kernel '")+kinput.symbolName.c_str()+
1230                        "' is undefined").c_str());
1231            good = false;
1232            continue;
1233        }
1234        const AsmSymbol& symbol = it->second;
1235        if (!symbol.hasValue)
1236        {   // error, unresolved
1237            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1238                    "Symbol for kernel '") + kinput.symbolName.c_str() +
1239                    "' is not resolved").c_str());
1240            good = false;
1241            continue;
1242        }
1243        if (symbol.sectionId != codeSection)
1244        {   /// error, wrong section
1245            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1246                    "Symbol for kernel '")+kinput.symbolName.c_str()+
1247                    "' is defined for section other than '.text'").c_str());
1248            good = false;
1249            continue;
1250        }
1251        kinput.offset = symbol.value;
1252    }
1253    return good;
1254}
1255
1256void AsmROCmHandler::writeBinary(std::ostream& os) const
1257{
1258    ROCmBinGenerator binGenerator(&output);
1259    binGenerator.generate(os);
1260}
1261
1262void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
1263{
1264    ROCmBinGenerator binGenerator(&output);
1265    binGenerator.generate(array);
1266}
Note: See TracBrowser for help on using the repository browser.