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

Last change on this file since 2593 was 2593, checked in by matszpk, 3 years ago

CLRadeonExtender: Asm: Move parsring of dimensions to AsmParseUtils?.

File size: 36.9 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 <cstring>
22#include <string>
23#include <vector>
24#include <utility>
25#include <algorithm>
26#include <CLRX/utils/Utilities.h>
27#include <CLRX/amdasm/Assembler.h>
28#include "AsmInternals.h"
29
30using namespace CLRX;
31
32static const char* rocmPseudoOpNamesTbl[] =
33{
34    "call_convention", "codeversion", "config",
35    "control_directive", "debug_private_segment_buffer_sgpr",
36    "debug_wavefront_private_segment_offset_sgpr",
37    "debugmode", "dims", "dx10clamp",
38    "exceptions", "floatmode", "gds_segment_size",
39    "group_segment_align", "ieeemode", "kcode",
40    "kcodeend", "kernarg_segment_align",
41    "kernarg_segment_size", "kernel_code_entry_offset",
42    "kernel_code_prefetch_offset", "kernel_code_prefetch_size",
43    "localsize", "machine", "max_scratch_backing_memory",
44    "pgmrsrc1", "pgmrsrc2", "priority", "private_segment_align",
45    "privmode", "reserved_sgpr_count", "reserved_sgpr_first",
46    "reserved_vgpr_count", "reserved_vgpr_first",
47    "runtime_loader_kernel_symbol",
48    "scratchbuffer", "sgprsnum", "tgsize",
49    "use_debug_enabled", "use_dispatch_id",
50    "use_dispatch_ptr", "use_dynamic_call_stack",
51    "use_flat_scratch_init", "use_grid_workgroup_count",
52    "use_kernarg_segment_ptr", "use_ordered_append_gds",
53    "use_private_segment_size", "use_ptr64", "use_queue_ptr",
54    "use_private_segment_buffer", "use_xnack_enabled",
55    "userdatanum", "vgprsnum", "wavefront_sgpr_count",
56    "wavefront_size", "workitem_vgpr_count",
57    "workgroup_fbarrier_count", "workgroup_group_segment_size",
58    "workitem_private_segment_size"
59};
60
61enum
62{
63    ROCMOP_CALL_CONVENTION, ROCMOP_CODEVERSION, ROCMOP_CONFIG,
64    ROCMOP_CONTROL_DIRECTIVE, ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
65    ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
66    ROCMOP_DEBUGMODE, ROCMOP_DIMS, ROCMOP_DX10CLAMP,
67    ROCMOP_EXCEPTIONS, ROCMOP_FLOATMODE, ROCMOP_GDS_SEGMENT_SIZE,
68    ROCMOP_GROUP_SEGMENT_ALIGN, ROCMOP_IEEEMODE, ROCMOP_KCODE,
69    ROCMOP_KCODEEND, ROCMOP_KERNARG_SEGMENT_ALIGN,
70    ROCMOP_KERNARG_SEGMENT_SIZE, ROCMOP_KERNEL_CODE_ENTRY_OFFSET,
71    ROCMOP_KERNEL_CODE_PREFETCH_OFFSET, ROCMOP_KERNEL_CODE_PREFETCH_SIZE,
72    ROCMOP_LOCALSIZE, ROCMOP_MACHINE, ROCMOP_MAX_SCRATCH_BACKING_MEMORY,
73    ROCMOP_PGMRSRC1, ROCMOP_PGMRSRC2, ROCMOP_PRIORITY, ROCMOP_PRIVATE_SEGMENT_ALIGN,
74    ROCMOP_PRIVMODE, ROCMOP_RESERVED_SGPR_COUNT, ROCMOP_RESERVED_SGPR_FIRST,
75    ROCMOP_RESERVED_VGPR_COUNT, ROCMOP_RESERVED_VGPR_FIRST,
76    ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
77    ROCMOP_SCRATCHBUFFER, ROCMOP_SGPRSNUM, ROCMOP_TGSIZE,
78    ROCMOP_USE_DEBUG_ENABLED, ROCMOP_USE_DISPATCH_ID,
79    ROCMOP_USE_DISPATCH_PTR, ROCMOP_USE_DYNAMIC_CALL_STACK,
80    ROCMOP_USE_FLAT_SCRATCH_INIT, ROCMOP_USE_GRID_WORKGROUP_COUNT,
81    ROCMOP_USE_KERNARG_SEGMENT_PTR, ROCMOP_USE_ORDERED_APPEND_GDS,
82    ROCMOP_USE_PRIVATE_SEGMENT_SIZE, ROCMOP_USE_PTR64, ROCMOP_USE_QUEUE_PTR,
83    ROCMOP_USE_PRIVATE_SEGMENT_BUFFER, ROCMOP_USE_XNACK_ENABLED,
84    ROCMOP_USERDATANUM, ROCMOP_VGPRSNUM, ROCMOP_WAVEFRONT_SGPR_COUNT,
85    ROCMOP_WAVEFRONT_SIZE, ROCMOP_WORKITEM_VGPR_COUNT,
86    ROCMOP_WORKGROUP_FBARRIER_COUNT, ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
87    ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE
88};
89
90/*
91 * ROCm format handler
92 */
93
94AsmROCmHandler::AsmROCmHandler(Assembler& assembler): AsmFormatHandler(assembler),
95             output{}, codeSection(0), commentSection(ASMSECT_NONE),
96             extraSectionCount(0)
97{
98    assembler.currentKernel = ASMKERN_GLOBAL;
99    assembler.currentSection = 0;
100    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
101                ELFSECTID_TEXT, ".text" });
102    currentKcodeKernel = ASMKERN_GLOBAL;
103    savedSection = 0;
104}
105
106AsmROCmHandler::~AsmROCmHandler()
107{
108    for (Kernel* kernel: kernelStates)
109        delete kernel;
110}
111
112cxuint AsmROCmHandler::addKernel(const char* kernelName)
113{
114    cxuint thisKernel = output.symbols.size();
115    cxuint thisSection = sections.size();
116    output.addEmptyKernel(kernelName);
117    /// add kernel config section
118    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
119    kernelStates.push_back(new Kernel{ thisSection, nullptr, ASMSECT_NONE, thisSection });
120   
121    if (assembler.currentKernel == ASMKERN_GLOBAL)
122        savedSection = assembler.currentSection;
123   
124    assembler.currentKernel = thisKernel;
125    assembler.currentSection = thisSection;
126    return thisKernel;
127}
128
129cxuint AsmROCmHandler::addSection(const char* sectionName, cxuint kernelId)
130{
131    const cxuint thisSection = sections.size();
132    Section section;
133    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
134       
135    if (::strcmp(sectionName, ".text") == 0) // code
136    {
137        if (codeSection!=ASMSECT_NONE)
138            throw AsmFormatException("Only one section '.text' can be in binary");
139        codeSection = thisSection;
140        section.type = AsmSectionType::CODE;
141        section.elfBinSectId = ELFSECTID_TEXT;
142        section.name = ".text"; // set static name (available by whole lifecycle)
143    }
144    else if (::strcmp(sectionName, ".comment") == 0) // comment
145    {
146        if (commentSection!=ASMSECT_NONE)
147            throw AsmFormatException("Only one section '.comment' can be in binary");
148        commentSection = thisSection;
149        section.type = AsmSectionType::GALLIUM_COMMENT;
150        section.elfBinSectId = ELFSECTID_COMMENT;
151        section.name = ".comment"; // set static name (available by whole lifecycle)
152    }
153    else
154    {
155        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
156                    thisSection));
157        if (!out.second)
158            throw AsmFormatException("Section already exists");
159        section.type = AsmSectionType::EXTRA_SECTION;
160        section.elfBinSectId = extraSectionCount++;
161        /// reference entry is available and unchangeable by whole lifecycle of section map
162        section.name = out.first->first.c_str();
163    }
164    sections.push_back(section);
165   
166    assembler.currentKernel = ASMKERN_GLOBAL;
167    assembler.currentSection = thisSection;
168    return thisSection;
169}
170
171cxuint AsmROCmHandler::getSectionId(const char* sectionName) const
172{
173    if (::strcmp(sectionName, ".text") == 0) // code
174        return codeSection;
175    else if (::strcmp(sectionName, ".comment") == 0) // comment
176        return commentSection;
177    else
178    {
179        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
180        if (it != extraSectionMap.end())
181            return it->second;
182    }
183    return ASMSECT_NONE;
184}
185
186void AsmROCmHandler::setCurrentKernel(cxuint kernel)
187{
188    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
189        throw AsmFormatException("KernelId out of range");
190   
191    if (assembler.currentKernel == ASMKERN_GLOBAL)
192        savedSection = assembler.currentSection;
193    else // if kernel
194        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
195   
196    assembler.currentKernel = kernel;
197    if (kernel != ASMKERN_GLOBAL)
198        assembler.currentSection = kernelStates[kernel]->savedSection;
199    else // default main section
200        assembler.currentSection = savedSection;
201}
202
203void AsmROCmHandler::setCurrentSection(cxuint sectionId)
204{
205    if (sectionId >= sections.size())
206        throw AsmFormatException("SectionId out of range");
207   
208    if (assembler.currentKernel == ASMKERN_GLOBAL)
209        savedSection = assembler.currentSection;
210    else // if kernel
211        kernelStates[assembler.currentKernel]->savedSection = assembler.currentSection;
212   
213    assembler.currentSection = sectionId;
214    assembler.currentKernel = sections[sectionId].kernelId;
215}
216
217
218AsmFormatHandler::SectionInfo AsmROCmHandler::getSectionInfo(cxuint sectionId) const
219{
220    if (sectionId >= sections.size())
221        throw AsmFormatException("Section doesn't exists");
222   
223    AsmFormatHandler::SectionInfo info;
224    info.type = sections[sectionId].type;
225    info.flags = 0;
226    if (info.type == AsmSectionType::CODE)
227        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
228    else if (info.type != AsmSectionType::CONFIG)
229        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
230   
231    info.name = sections[sectionId].name;
232    return info;
233}
234
235void AsmROCmHandler::restoreKcodeCurrentAllocRegs()
236{
237    if (currentKcodeKernel != ASMKERN_GLOBAL)
238    {
239        Kernel& newKernel = *kernelStates[currentKcodeKernel];
240        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
241                            newKernel.allocRegFlags);
242    }
243}
244
245void AsmROCmHandler::saveKcodeCurrentAllocRegs()
246{
247    if (currentKcodeKernel != ASMKERN_GLOBAL)
248    {   // save other state
249        size_t regTypesNum;
250        Kernel& oldKernel = *kernelStates[currentKcodeKernel];
251        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
252                            regTypesNum, oldKernel.allocRegFlags);
253        std::copy(regs, regs+2, oldKernel.allocRegs);
254    }
255}
256
257
258void AsmROCmHandler::handleLabel(const CString& label)
259{
260    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
261        return;
262    auto kit = assembler.kernelMap.find(label);
263    if (kit == assembler.kernelMap.end())
264        return;
265    if (!kcodeSelection.empty())
266        return; // do not change if inside kcode
267    // save other state
268    saveKcodeCurrentAllocRegs();
269    // restore this state
270    currentKcodeKernel = kit->second;
271    restoreKcodeCurrentAllocRegs();
272}
273
274void AsmROCmHandler::Kernel::initializeKernelConfig()
275{
276    if (!config)
277    {
278        config.reset(new AsmROCmKernelConfig{});
279        ::memset(config.get(), 0, sizeof(AsmROCmKernelConfig));
280    }
281}
282
283namespace CLRX
284{
285
286bool AsmROCmPseudoOps::checkPseudoOpName(const CString& string)
287{
288    if (string.empty() || string[0] != '.')
289        return false;
290    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
291                sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
292               CStringLess()) - rocmPseudoOpNamesTbl;
293    return pseudoOp < sizeof(rocmPseudoOpNamesTbl)/sizeof(char*);
294}
295   
296void AsmROCmPseudoOps::doConfig(AsmROCmHandler& handler, const char* pseudoOpPlace,
297                  const char* linePtr)
298{
299    Assembler& asmr = handler.assembler;
300    const char* end = asmr.line + asmr.lineSize;
301    if (asmr.currentKernel==ASMKERN_GLOBAL)
302    {
303        asmr.printError(pseudoOpPlace, "Kernel config can be defined only inside kernel");
304        return;
305    }
306   
307    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
308    {
309        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
310        return;
311    }
312    skipSpacesToEnd(linePtr, end);
313    if (!checkGarbagesAtEnd(asmr, linePtr))
314        return;
315    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
316}
317
318void AsmROCmPseudoOps::doControlDirective(AsmROCmHandler& handler,
319              const char* pseudoOpPlace, const char* linePtr)
320{
321    Assembler& asmr = handler.assembler;
322    const char* end = asmr.line + asmr.lineSize;
323    if (asmr.currentKernel==ASMKERN_GLOBAL)
324    {
325        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
326                    "only inside kernel");
327        return;
328    }
329    skipSpacesToEnd(linePtr, end);
330    if (!checkGarbagesAtEnd(asmr, linePtr))
331        return;
332   
333    AsmROCmHandler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
334    if (kernel.ctrlDirSection == ASMSECT_NONE)
335    {
336        cxuint thisSection = handler.sections.size();
337        handler.sections.push_back({ asmr.currentKernel,
338            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
339            ELFSECTID_UNDEF, nullptr });
340        kernel.ctrlDirSection = thisSection;
341    }
342    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
343    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
344}
345
346void AsmROCmPseudoOps::setConfigValue(AsmROCmHandler& handler, const char* pseudoOpPlace,
347                  const char* linePtr, ROCmConfigValueTarget target)
348{
349    Assembler& asmr = handler.assembler;
350    const char* end = asmr.line + asmr.lineSize;
351   
352    if (asmr.currentKernel==ASMKERN_GLOBAL ||
353        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
354    {
355        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
356        return;
357    }
358   
359    skipSpacesToEnd(linePtr, end);
360    const char* valuePlace = linePtr;
361    uint64_t value = BINGEN64_NOTSUPPLIED;
362    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
363    /* ranges checking */
364    if (good)
365    {
366        switch(target)
367        {
368            case ROCMCVAL_SGPRSNUM:
369            {
370                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
371                            asmr.deviceType);
372                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
373                if (value > maxSGPRsNum)
374                {
375                    char buf[64];
376                    snprintf(buf, 64, "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
377                    asmr.printError(valuePlace, buf);
378                    good = false;
379                }
380                break;
381            }
382            case ROCMCVAL_VGPRSNUM:
383            {
384                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
385                            asmr.deviceType);
386                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
387                if (value > maxVGPRsNum)
388                {
389                    char buf[64];
390                    snprintf(buf, 64, "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
391                    asmr.printError(valuePlace, buf);
392                    good = false;
393                }
394                break;
395            }
396            case ROCMCVAL_EXCEPTIONS:
397                asmr.printWarningForRange(7, value,
398                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
399                value &= 0x7f;
400                break;
401            case ROCMCVAL_FLOATMODE:
402                asmr.printWarningForRange(8, value,
403                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
404                value &= 0xff;
405                break;
406            case ROCMCVAL_PRIORITY:
407                asmr.printWarningForRange(2, value,
408                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
409                value &= 3;
410                break;
411            case ROCMCVAL_LOCALSIZE:
412            {
413                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
414                            asmr.deviceType);
415                const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
416                if (value > maxLocalSize)
417                {
418                    char buf[64];
419                    snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
420                    asmr.printError(valuePlace, buf);
421                    good = false;
422                }
423                break;
424            }
425            case ROCMCVAL_USERDATANUM:
426                if (value > 16)
427                {
428                    asmr.printError(valuePlace, "UserDataNum out of range (0-16)");
429                    good = false;
430                }
431                break;
432            default:
433                break;
434        }
435    }
436    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
437        return;
438   
439    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
440    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
441    // set value
442    switch(target)
443    {
444        case ROCMCVAL_SGPRSNUM:
445            config.usedSGPRsNum = value;
446            break;
447        case ROCMCVAL_VGPRSNUM:
448            config.usedVGPRsNum = value;
449            break;
450        case ROCMCVAL_PGMRSRC1:
451            config.computePgmRsrc1 = value;
452            break;
453        case ROCMCVAL_PGMRSRC2:
454            config.computePgmRsrc2 = value;
455            break;
456        case ROCMCVAL_FLOATMODE:
457            config.floatMode = value;
458            break;
459        case ROCMCVAL_LOCALSIZE:
460            config.localSize = value;
461            break;
462        case ROCMCVAL_SCRATCHBUFFER:
463            config.scratchBufferSize = value;
464            break;
465        case ROCMCVAL_PRIORITY:
466            config.priority = value;
467            break;
468        case ROCMCVAL_USERDATANUM:
469            config.userDataNum = value;
470            break;
471        case ROCMCVAL_EXCEPTIONS:
472            config.exceptions = value;
473            break;
474        case ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET:
475            config.kernelCodeEntryOffset = value;
476            break;
477        case ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET:
478            config.kernelCodePrefetchOffset = value;
479            break;
480        case ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE:
481            config.kernelCodePrefetchSize = value;
482            break;
483        case ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY:
484            config.maxScrachBackingMemorySize = value;
485            break;
486        case ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE:
487            config.workitemPrivateSegmentSize = value;
488            break;
489        case ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE:
490            config.workgroupGroupSegmentSize = value;
491            break;
492        case ROCMCVAL_GDS_SEGMENT_SIZE:
493            config.gdsSegmentSize = value;
494            break;
495        case ROCMCVAL_KERNARG_SEGMENT_SIZE:
496            config.kernargSegmentSize = value;
497            break;
498        case ROCMCVAL_WORKGROUP_FBARRIER_COUNT:
499            config.workgroupFbarrierCount = value;
500            break;
501        case ROCMCVAL_WAVEFRONT_SGPR_COUNT:
502            config.wavefrontSgprCount = value;
503            break;
504        case ROCMCVAL_WORKITEM_VGPR_COUNT:
505            config.workitemVgprCount = value;
506            break;
507        case ROCMCVAL_RESERVED_VGPR_FIRST:
508            config.reservedVgprFirst = value;
509            break;
510        case ROCMCVAL_RESERVED_VGPR_COUNT:
511            config.reservedVgprCount = value;
512            break;
513        case ROCMCVAL_RESERVED_SGPR_FIRST:
514            config.reservedSgprFirst = value;
515            break;
516        case ROCMCVAL_RESERVED_SGPR_COUNT:
517            config.reservedSgprCount = value;
518            break;
519        case ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
520            config.debugWavefrontPrivateSegmentOffsetSgpr = value;
521            break;
522        case ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
523            config.debugPrivateSegmentBufferSgpr = value;
524            break;
525        case ROCMCVAL_KERNARG_SEGMENT_ALIGN:
526            config.kernargSegmentAlignment = value;
527            break;
528        case ROCMCVAL_GROUP_SEGMENT_ALIGN:
529            config.groupSegmentAlignment = value;
530            break;
531        case ROCMCVAL_PRIVATE_SEGMENT_ALIGN:
532            config.privateSegmentAlignment = value;
533            break;
534        case ROCMCVAL_WAVEFRONT_SIZE:
535            config.wavefrontSize = value;
536            break;
537        case ROCMCVAL_CALL_CONVENTION:
538            config.callConvention = value;
539            break;
540        case ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL:
541            config.runtimeLoaderKernelSymbol = value;
542            break;
543        default:
544            break;
545    }
546}
547
548void AsmROCmPseudoOps::setConfigBoolValue(AsmROCmHandler& handler,
549          const char* pseudoOpPlace, const char* linePtr, ROCmConfigValueTarget target)
550{
551    Assembler& asmr = handler.assembler;
552    const char* end = asmr.line + asmr.lineSize;
553   
554    if (asmr.currentKernel==ASMKERN_GLOBAL ||
555        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
556    {
557        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
558        return;
559    }
560   
561    skipSpacesToEnd(linePtr, end);
562    if (!checkGarbagesAtEnd(asmr, linePtr))
563        return;
564   
565    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
566    AsmROCmKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
567   
568    switch(target)
569    {
570        case ROCMCVAL_PRIVMODE:
571            config.privilegedMode = true;
572            break;
573        case ROCMCVAL_DEBUGMODE:
574            config.debugMode = true;
575            break;
576        case ROCMCVAL_DX10CLAMP:
577            config.dx10Clamp = true;
578            break;
579        case ROCMCVAL_IEEEMODE:
580            config.ieeeMode = true;
581            break;
582        case ROCMCVAL_TGSIZE:
583            config.tgSize = true;
584            break;
585        case ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER:
586            config.enableSpgrRegisterFlags |= 1;
587            break;
588        case ROCMCVAL_USE_DISPATCH_PTR:
589            config.enableSpgrRegisterFlags |= 2;
590            break;
591        case ROCMCVAL_USE_QUEUE_PTR:
592            config.enableSpgrRegisterFlags |= 4;
593            break;
594        case ROCMCVAL_USE_KERNARG_SEGMENT_PTR:
595            config.enableSpgrRegisterFlags |= 8;
596            break;
597        case ROCMCVAL_USE_DISPATCH_ID:
598            config.enableSpgrRegisterFlags |= 16;
599            break;
600        case ROCMCVAL_USE_FLAT_SCRATCH_INIT:
601            config.enableSpgrRegisterFlags |= 32;
602            break;
603        case ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE:
604            config.enableSpgrRegisterFlags |= 64;
605            break;
606        case ROCMCVAL_USE_ORDERED_APPEND_GDS:
607            config.enableFeatureFlags |= 1;
608            break;
609        case ROCMCVAL_USE_PTR64:
610            config.enableFeatureFlags |= 8;
611            break;
612        case ROCMCVAL_USE_DYNAMIC_CALL_STACK:
613            config.enableFeatureFlags |= 16;
614            break;
615        case ROCMCVAL_USE_DEBUG_ENABLED:
616            config.enableFeatureFlags |= 32;
617            break;
618        case ROCMCVAL_USE_XNACK_ENABLED:
619            config.enableFeatureFlags |= 64;
620            break;
621        default:
622            break;
623    }
624}
625
626void AsmROCmPseudoOps::setDimensions(AsmROCmHandler& handler, const char* pseudoOpPlace,
627                  const char* linePtr)
628{
629    Assembler& asmr = handler.assembler;
630    if (asmr.currentKernel==ASMKERN_GLOBAL ||
631        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
632    {
633        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
634        return;
635    }
636    cxuint dimMask = 0;
637    if (!parseDimensions(asmr, linePtr, dimMask))
638        return;
639    if (!checkGarbagesAtEnd(asmr, linePtr))
640        return;
641    handler.kernelStates[asmr.currentKernel]->initializeKernelConfig();
642    handler.kernelStates[asmr.currentKernel]->config->dimMask = dimMask;
643}
644
645void AsmROCmPseudoOps::updateKCodeSel(AsmROCmHandler& handler,
646                  const std::vector<cxuint>& oldset)
647{
648    Assembler& asmr = handler.assembler;
649    // old elements - join current regstate with all them
650    size_t regTypesNum;
651    for (auto it = oldset.begin(); it != oldset.end(); ++it)
652    {
653        Flags curAllocRegFlags;
654        const cxuint* curAllocRegs = asmr.isaAssembler->getAllocatedRegisters(regTypesNum,
655                               curAllocRegFlags);
656        cxuint newAllocRegs[2];
657        AsmROCmHandler::Kernel& kernel = *(handler.kernelStates[*it]);
658        newAllocRegs[0] = std::max(curAllocRegs[0], kernel.allocRegs[0]);
659        newAllocRegs[1] = std::max(curAllocRegs[1], kernel.allocRegs[1]);
660        kernel.allocRegFlags |= curAllocRegFlags;
661        std::copy(newAllocRegs, newAllocRegs+2, kernel.allocRegs);
662    }
663    asmr.isaAssembler->setAllocatedRegisters();
664}
665
666void AsmROCmPseudoOps::doKCode(AsmROCmHandler& handler, const char* pseudoOpPlace,
667                  const char* linePtr)
668{
669    Assembler& asmr = handler.assembler;
670    const char* end = asmr.line + asmr.lineSize;
671    bool good = true;
672    skipSpacesToEnd(linePtr, end);
673    if (linePtr==end)
674        return;
675    std::unordered_set<cxuint> newSel(handler.kcodeSelection.begin(),
676                          handler.kcodeSelection.end());
677    do {
678        CString kname;
679        const char* knamePlace = linePtr;
680        skipSpacesToEnd(linePtr, end);
681        bool removeKernel = false;
682        if (linePtr!=end && *linePtr=='-')
683        {   // '-' - remove this kernel from current kernel selection
684            removeKernel = true;
685            linePtr++;
686        }
687        else if (linePtr!=end && *linePtr=='+')
688        {
689            linePtr++;
690            skipSpacesToEnd(linePtr, end);
691            if (linePtr==end)
692            {   // add all kernels
693                for (cxuint k = 0; k < handler.kernelStates.size(); k++)
694                    newSel.insert(k);
695                break;
696            }
697        }
698       
699        if (!getNameArg(asmr, kname, linePtr, "kernel"))
700        { good = false; continue; }
701        auto kit = asmr.kernelMap.find(kname);
702        if (kit == asmr.kernelMap.end())
703        {
704            asmr.printError(knamePlace, "Kernel not found");
705            continue;
706        }
707        if (!removeKernel)
708            newSel.insert(kit->second);
709        else // remove kernel
710            newSel.erase(kit->second);
711    } while (skipCommaForMultipleArgs(asmr, linePtr));
712   
713    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
714        return;
715   
716    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
717    {
718        asmr.printError(pseudoOpPlace, "KCode outside code");
719        return;
720    }
721    if (handler.kcodeSelStack.empty())
722        handler.saveKcodeCurrentAllocRegs();
723    // push to stack
724    handler.kcodeSelStack.push(handler.kcodeSelection);
725    // set current sel
726    handler.kcodeSelection.assign(newSel.begin(), newSel.end());
727   
728    std::sort(handler.kcodeSelection.begin(), handler.kcodeSelection.end());
729    updateKCodeSel(handler, handler.kcodeSelStack.top());
730}
731
732void AsmROCmPseudoOps::doKCodeEnd(AsmROCmHandler& handler, const char* pseudoOpPlace,
733                  const char* linePtr)
734{
735    Assembler& asmr = handler.assembler;
736    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
737    {
738        asmr.printError(pseudoOpPlace, "KCodeEnd outside code");
739        return;
740    }
741    if (handler.kcodeSelStack.empty())
742    {
743        asmr.printError(pseudoOpPlace, "'.kcodeend' without '.kcode'");
744        return;
745    }
746    updateKCodeSel(handler, handler.kcodeSelection);
747    handler.kcodeSelection = handler.kcodeSelStack.top();
748    handler.kcodeSelStack.pop();
749    if (handler.kcodeSelStack.empty())
750        handler.restoreKcodeCurrentAllocRegs();
751}
752
753}
754
755bool AsmROCmHandler::parsePseudoOp(const CString& firstName, const char* stmtPlace,
756               const char* linePtr)
757{
758    const size_t pseudoOp = binaryFind(rocmPseudoOpNamesTbl, rocmPseudoOpNamesTbl +
759                    sizeof(rocmPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
760                   CStringLess()) - rocmPseudoOpNamesTbl;
761   
762    switch(pseudoOp)
763    {
764        case ROCMOP_CALL_CONVENTION:
765            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
766                             ROCMCVAL_CALL_CONVENTION);
767            break;
768        case ROCMOP_CODEVERSION:
769            break;
770        case ROCMOP_CONFIG:
771            break;
772        case ROCMOP_CONTROL_DIRECTIVE:
773            break;
774        case ROCMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
775            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
776                             ROCMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
777            break;
778        case ROCMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
779            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
780                         ROCMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
781            break;
782        case ROCMOP_DEBUGMODE:
783            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
784                             ROCMCVAL_DEBUGMODE);
785            break;
786        case ROCMOP_DIMS:
787            break;
788        case ROCMOP_DX10CLAMP:
789            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
790                             ROCMCVAL_DX10CLAMP);
791            break;
792        case ROCMOP_EXCEPTIONS:
793            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
794                             ROCMCVAL_EXCEPTIONS);
795            break;
796        case ROCMOP_FLOATMODE:
797            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
798                             ROCMCVAL_FLOATMODE);
799            break;
800        case ROCMOP_GDS_SEGMENT_SIZE:
801            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
802                             ROCMCVAL_GDS_SEGMENT_SIZE);
803            break;
804        case ROCMOP_GROUP_SEGMENT_ALIGN:
805            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
806                             ROCMCVAL_GROUP_SEGMENT_ALIGN);
807            break;
808        case ROCMOP_IEEEMODE:
809            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
810                             ROCMCVAL_IEEEMODE);
811            break;
812        case ROCMOP_KCODE:
813            break;
814        case ROCMOP_KCODEEND:
815            break;
816        case ROCMOP_KERNARG_SEGMENT_ALIGN:
817            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
818                             ROCMCVAL_KERNARG_SEGMENT_ALIGN);
819            break;
820        case ROCMOP_KERNARG_SEGMENT_SIZE:
821            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
822                             ROCMCVAL_KERNARG_SEGMENT_SIZE);
823            break;
824        case ROCMOP_KERNEL_CODE_ENTRY_OFFSET:
825            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
826                             ROCMCVAL_KERNEL_CODE_ENTRY_OFFSET);
827            break;
828        case ROCMOP_KERNEL_CODE_PREFETCH_OFFSET:
829            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
830                             ROCMCVAL_KERNEL_CODE_PREFETCH_OFFSET);
831            break;
832        case ROCMOP_KERNEL_CODE_PREFETCH_SIZE:
833            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
834                             ROCMCVAL_KERNEL_CODE_PREFETCH_SIZE);
835            break;
836        case ROCMOP_LOCALSIZE:
837            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
838                             ROCMCVAL_LOCALSIZE);
839            break;
840        case ROCMOP_MACHINE:
841            break;
842        case ROCMOP_MAX_SCRATCH_BACKING_MEMORY:
843            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
844                             ROCMCVAL_MAX_SCRATCH_BACKING_MEMORY);
845            break;
846        case ROCMOP_PGMRSRC1:
847            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC1);
848            break;
849        case ROCMOP_PGMRSRC2:
850            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PGMRSRC2);
851            break;
852        case ROCMOP_PRIORITY:
853            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_PRIORITY);
854            break;
855        case ROCMOP_PRIVATE_SEGMENT_ALIGN:
856            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
857                             ROCMCVAL_PRIVATE_SEGMENT_ALIGN);
858            break;
859        case ROCMOP_PRIVMODE:
860            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
861                             ROCMCVAL_PRIVMODE);
862            break;
863        case ROCMOP_RESERVED_SGPR_COUNT:
864            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
865                             ROCMCVAL_RESERVED_SGPR_COUNT);
866            break;
867        case ROCMOP_RESERVED_SGPR_FIRST:
868            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
869                             ROCMCVAL_RESERVED_SGPR_FIRST);
870            break;
871        case ROCMOP_RESERVED_VGPR_COUNT:
872            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
873                             ROCMCVAL_RESERVED_VGPR_COUNT);
874            break;
875        case ROCMOP_RESERVED_VGPR_FIRST:
876            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
877                             ROCMCVAL_RESERVED_VGPR_FIRST);
878            break;
879        case ROCMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
880            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
881                             ROCMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
882            break;
883        case ROCMOP_SCRATCHBUFFER:
884            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
885                             ROCMCVAL_SCRATCHBUFFER);
886            break;
887        case ROCMOP_SGPRSNUM:
888            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
889                             ROCMCVAL_SGPRSNUM);
890            break;
891        case ROCMOP_TGSIZE:
892            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
893                             ROCMCVAL_TGSIZE);
894            break;
895        case ROCMOP_USE_DEBUG_ENABLED:
896            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
897                             ROCMCVAL_USE_DEBUG_ENABLED);
898            break;
899        case ROCMOP_USE_DISPATCH_ID:
900            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
901                             ROCMCVAL_USE_DISPATCH_ID);
902            break;
903        case ROCMOP_USE_DISPATCH_PTR:
904            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
905                             ROCMCVAL_USE_DISPATCH_PTR);
906            break;
907        case ROCMOP_USE_DYNAMIC_CALL_STACK:
908            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
909                             ROCMCVAL_USE_DYNAMIC_CALL_STACK);
910            break;
911        case ROCMOP_USE_FLAT_SCRATCH_INIT:
912            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
913                             ROCMCVAL_USE_FLAT_SCRATCH_INIT);
914            break;
915        case ROCMOP_USE_GRID_WORKGROUP_COUNT:
916            break;
917        case ROCMOP_USE_KERNARG_SEGMENT_PTR:
918            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
919                             ROCMCVAL_USE_KERNARG_SEGMENT_PTR);
920            break;
921        case ROCMOP_USE_ORDERED_APPEND_GDS:
922            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
923                             ROCMCVAL_USE_ORDERED_APPEND_GDS);
924            break;
925        case ROCMOP_USE_PRIVATE_SEGMENT_SIZE:
926            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
927                             ROCMCVAL_USE_PRIVATE_SEGMENT_SIZE);
928            break;
929        case ROCMOP_USE_PTR64:
930            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
931                             ROCMCVAL_USE_PTR64);
932            break;
933        case ROCMOP_USE_QUEUE_PTR:
934            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
935                             ROCMCVAL_USE_QUEUE_PTR);
936            break;
937        case ROCMOP_USE_PRIVATE_SEGMENT_BUFFER:
938            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
939                             ROCMCVAL_USE_PRIVATE_SEGMENT_BUFFER);
940            break;
941        case ROCMOP_USE_XNACK_ENABLED:
942            AsmROCmPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
943                             ROCMCVAL_USE_XNACK_ENABLED);
944            break;
945        case ROCMOP_USERDATANUM:
946            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
947                             ROCMCVAL_USERDATANUM);
948            break;
949        case ROCMOP_VGPRSNUM:
950            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr, ROCMCVAL_VGPRSNUM);
951            break;
952        case ROCMOP_WAVEFRONT_SGPR_COUNT:
953            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
954                             ROCMCVAL_WAVEFRONT_SGPR_COUNT);
955            break;
956        case ROCMOP_WAVEFRONT_SIZE:
957            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
958                             ROCMCVAL_WAVEFRONT_SIZE);
959            break;
960        case ROCMOP_WORKITEM_VGPR_COUNT:
961            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
962                             ROCMCVAL_WORKITEM_VGPR_COUNT);
963            break;
964        case ROCMOP_WORKGROUP_FBARRIER_COUNT:
965            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
966                             ROCMCVAL_WORKGROUP_FBARRIER_COUNT);
967            break;
968        case ROCMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
969            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
970                             ROCMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
971            break;
972        case ROCMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
973            AsmROCmPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
974                             ROCMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
975            break;
976        default:
977            return false;
978    }
979    return true;
980}
981
982bool AsmROCmHandler::prepareBinary()
983{
984    return false;
985}
986
987void AsmROCmHandler::writeBinary(std::ostream& os) const
988{
989}
990
991void AsmROCmHandler::writeBinary(Array<cxbyte>& array) const
992{
993}
Note: See TracBrowser for help on using the repository browser.