source: CLRX/CLRadeonExtender/trunk/amdasm/AsmGalliumFormat.cpp @ 3294

Last change on this file since 3294 was 3294, checked in by matszpk, 14 months ago

CLRadeonExtender: AsmROCm: Do not print warnings about out of range when values was not parsed in
'.codeversion' and '.machine' pseudo-ops. fix typos. Small formatting in AsmGalliumFormat?.

File size: 86.0 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 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/GPUId.h>
27#include <CLRX/utils/Utilities.h>
28#include <CLRX/amdasm/Assembler.h>
29#include <CLRX/amdasm/AsmFormats.h>
30#include <CLRX/amdbin/GalliumBinaries.h>
31#include "AsmInternals.h"
32
33using namespace CLRX;
34
35static const char* galliumPseudoOpNamesTbl[] =
36{
37    "arch_minor", "arch_stepping",
38    "arg", "args", "call_convention", "codeversion",
39    "config", "control_directive",
40    "debug_private_segment_buffer_sgpr",
41    "debug_wavefront_private_segment_offset_sgpr",
42    "debugmode", "dims", "driver_version", "dx10clamp",
43    "entry", "exceptions", "floatmode", "gds_segment_size",
44    "get_driver_version", "get_llvm_version", "globaldata",
45    "group_segment_align",
46    "hsa_debugmode", "hsa_dims", "hsa_dx10clamp", "hsa_exceptions",
47    "hsa_floatmode", "hsa_ieeemode",
48    "hsa_localsize", "hsa_pgmrsrc1",
49    "hsa_pgmrsrc2", "hsa_priority", "hsa_privmode",
50    "hsa_sgprsnum", "hsa_tgsize", "hsa_userdatanum", "hsa_vgprsnum",
51    "ieeemode", "kcode", "kcodeend",
52    "kernarg_segment_align", "kernarg_segment_size",
53    "kernel_code_entry_offset", "kernel_code_prefetch_offset",
54    "kernel_code_prefetch_size",
55    "llvm_version", "localsize",
56    "machine", "max_scratch_backing_memory",
57    "pgmrsrc1", "pgmrsrc2", "priority",
58    "private_elem_size", "private_segment_align",
59    "privmode", "proginfo", "reserved_sgprs", "reserved_vgprs",
60    "runtime_loader_kernel_symbol",
61    "scratchbuffer", "sgprsnum",
62    "spilledsgprs", "spilledvgprs", "tgsize",
63    "use_debug_enabled", "use_dispatch_id",
64    "use_dispatch_ptr", "use_dynamic_call_stack",
65    "use_flat_scratch_init", "use_grid_workgroup_count",
66    "use_kernarg_segment_ptr",
67    "use_ordered_append_gds", "use_private_segment_buffer",
68    "use_private_segment_size", "use_ptr64",
69    "use_queue_ptr", "use_xnack_enabled",
70    "userdatanum", "vgprsnum",
71    "wavefront_sgpr_count", "wavefront_size",
72    "workgroup_fbarrier_count", "workgroup_group_segment_size",
73    "workitem_private_segment_size", "workitem_vgpr_count"
74};
75
76enum
77{
78    GALLIUMOP_ARCH_MINOR = 0, GALLIUMOP_ARCH_STEPPING,
79    GALLIUMOP_ARG, GALLIUMOP_ARGS, GALLIUMOP_CALL_CONVENTION, GALLIUMOP_CODEVERSION,
80    GALLIUMOP_CONFIG, GALLIUMOP_CONTROL_DIRECTIVE,
81    GALLIUMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR,
82    GALLIUMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR,
83    GALLIUMOP_DEBUGMODE, GALLIUMOP_DIMS, GALLIUMOP_DRIVER_VERSION, GALLIUMOP_DX10CLAMP,
84    GALLIUMOP_ENTRY, GALLIUMOP_EXCEPTIONS, GALLIUMOP_FLOATMODE, GALLIUMOP_GDS_SEGMENT_SIZE,
85    GALLIUMOP_GET_DRIVER_VERSION, GALLIUMOP_GET_LLVM_VERSION, GALLIUMOP_GLOBALDATA,
86    GALLIUMOP_GROUP_SEGMENT_ALIGN,
87    GALLIUMOP_HSA_DEBUGMODE, GALLIUMOP_HSA_DIMS,
88    GALLIUMOP_HSA_DX10CLAMP, GALLIUMOP_HSA_EXCEPTIONS,
89    GALLIUMOP_HSA_FLOATMODE, GALLIUMOP_HSA_IEEEMODE,
90    GALLIUMOP_HSA_LOCALSIZE, GALLIUMOP_HSA_PGMRSRC1,
91    GALLIUMOP_HSA_PGMRSRC2, GALLIUMOP_HSA_PRIORITY, GALLIUMOP_HSA_PRIVMODE,
92    GALLIUMOP_HSA_SGPRSNUM, GALLIUMOP_HSA_TGSIZE,
93    GALLIUMOP_HSA_USERDATANUM, GALLIUMOP_HSA_VGPRSNUM,
94    GALLIUMOP_IEEEMODE, GALLIUMOP_KCODE, GALLIUMOP_KCODEEND,
95    GALLIUMOP_KERNARG_SEGMENT_ALIGN, GALLIUMOP_KERNARG_SEGMENT_SIZE,
96    GALLIUMOP_KERNEL_CODE_ENTRY_OFFSET, GALLIUMOP_KERNEL_CODE_PREFETCH_OFFSET,
97    GALLIUMOP_KERNEL_CODE_PREFETCH_SIZE,
98    GALLIUMOP_LLVM_VERSION, GALLIUMOP_LOCALSIZE,
99    GALLIUMOP_MACHINE, GALLIUMOP_MAX_SCRATCH_BACKING_MEMORY,
100    GALLIUMOP_PGMRSRC1, GALLIUMOP_PGMRSRC2, GALLIUMOP_PRIORITY,
101    GALLIUMOP_PRIVATE_ELEM_SIZE, GALLIUMOP_PRIVATE_SEGMENT_ALIGN,
102    GALLIUMOP_PRIVMODE, GALLIUMOP_PROGINFO,
103    GALLIUMOP_RESERVED_SGPRS, GALLIUMOP_RESERVED_VGPRS,
104    GALLIUMOP_RUNTIME_LOADER_KERNEL_SYMBOL,
105    GALLIUMOP_SCRATCHBUFFER, GALLIUMOP_SGPRSNUM,
106    GALLIUMOP_SPILLEDSGPRS, GALLIUMOP_SPILLEDVGPRS, GALLIUMOP_TGSIZE,
107    GALLIUMOP_USE_DEBUG_ENABLED, GALLIUMOP_USE_DISPATCH_ID,
108    GALLIUMOP_USE_DISPATCH_PTR, GALLIUMOP_USE_DYNAMIC_CALL_STACK,
109    GALLIUMOP_USE_FLAT_SCRATCH_INIT, GALLIUMOP_USE_GRID_WORKGROUP_COUNT,
110    GALLIUMOP_USE_KERNARG_SEGMENT_PTR,
111    GALLIUMOP_USE_ORDERED_APPEND_GDS, GALLIUMOP_USE_PRIVATE_SEGMENT_BUFFER,
112    GALLIUMOP_USE_PRIVATE_SEGMENT_SIZE, GALLIUMOP_USE_PTR64,
113    GALLIUMOP_USE_QUEUE_PTR, GALLIUMOP_USE_XNACK_ENABLED,
114    GALLIUMOP_USERDATANUM, GALLIUMOP_VGPRSNUM,
115    GALLIUMOP_WAVEFRONT_SGPR_COUNT, GALLIUMOP_WAVEFRONT_SIZE,
116    GALLIUMOP_WORKGROUP_FBARRIER_COUNT, GALLIUMOP_WORKGROUP_GROUP_SEGMENT_SIZE,
117    GALLIUMOP_WORKITEM_PRIVATE_SEGMENT_SIZE, GALLIUMOP_WORKITEM_VGPR_COUNT
118};
119
120void AsmGalliumHandler::Kernel::initializeAmdHsaKernelConfig()
121{
122    if (!config)
123    {
124        config.reset(new AsmROCmKernelConfig{});
125        // set default values to kernel config
126        ::memset(config.get(), 0xff, 128);
127        ::memset(config->controlDirective, 0, 128);
128        config->computePgmRsrc1 = config->computePgmRsrc2 = 0;
129        config->enableSgprRegisterFlags = 0;
130        config->enableFeatureFlags = 0;
131        config->reserved1[0] = config->reserved1[1] = config->reserved1[2] = 0;
132        config->dimMask = 0;
133        config->usedVGPRsNum = BINGEN_DEFAULT;
134        config->usedSGPRsNum = BINGEN_DEFAULT;
135        config->userDataNum = BINGEN8_DEFAULT;
136        config->ieeeMode = false;
137        config->floatMode = 0xc0;
138        config->priority = 0;
139        config->exceptions = 0;
140        config->tgSize = false;
141        config->debugMode = false;
142        config->privilegedMode = false;
143        config->dx10Clamp = false;
144    }
145}
146
147/*
148 * GalliumCompute format handler
149 */
150
151AsmGalliumHandler::AsmGalliumHandler(Assembler& assembler): AsmFormatHandler(assembler),
152             output{}, codeSection(0), dataSection(ASMSECT_NONE),
153             commentSection(ASMSECT_NONE), extraSectionCount(0),
154             archMinor(BINGEN_DEFAULT), archStepping(BINGEN_DEFAULT)
155{
156    assembler.currentKernel = ASMKERN_GLOBAL;
157    assembler.currentSection = 0;
158    sections.push_back({ ASMKERN_GLOBAL, AsmSectionType::CODE,
159                ELFSECTID_TEXT, ".text" });
160    inside = Inside::MAINLAYOUT;
161    currentKcodeKernel = ASMKERN_GLOBAL;
162    savedSection = 0;
163    defaultLLVMVersion = detectLLVMCompilerVersion();
164    defaultDriverVersion = detectMesaDriverVersion();
165}
166
167AsmGalliumHandler::~AsmGalliumHandler()
168{
169    for (Kernel* kernel: kernelStates)
170        delete kernel;
171}
172
173cxuint AsmGalliumHandler::determineLLVMVersion() const
174{
175    if (assembler.getLLVMVersion() == 0)
176        return defaultLLVMVersion;
177    else
178        return assembler.getLLVMVersion();
179}
180
181cxuint AsmGalliumHandler::determineDriverVersion() const
182{
183    if (assembler.getDriverVersion() == 0)
184        return defaultDriverVersion;
185    else
186        return assembler.getDriverVersion();
187}
188
189cxuint AsmGalliumHandler::addKernel(const char* kernelName)
190{
191    cxuint thisKernel = output.kernels.size();
192    cxuint thisSection = sections.size();
193    output.addEmptyKernel(kernelName, determineLLVMVersion());
194    /// add kernel config section
195    sections.push_back({ thisKernel, AsmSectionType::CONFIG, ELFSECTID_UNDEF, nullptr });
196    kernelStates.push_back(new Kernel{ thisSection, nullptr, ASMSECT_NONE, false, 0 });
197   
198    if (assembler.currentKernel == ASMKERN_GLOBAL)
199        savedSection = assembler.currentSection;
200   
201    assembler.currentKernel = thisKernel;
202    assembler.currentSection = thisSection;
203    inside = Inside::MAINLAYOUT;
204    return thisKernel;
205}
206
207cxuint AsmGalliumHandler::addSection(const char* sectionName, cxuint kernelId)
208{
209    const cxuint thisSection = sections.size();
210    Section section;
211    section.kernelId = ASMKERN_GLOBAL;  // we ignore input kernelId, we go to main
212   
213    if (::strcmp(sectionName, ".rodata") == 0) // data
214    {
215        if (dataSection!=ASMSECT_NONE)
216            throw AsmFormatException("Only section '.rodata' can be in binary");
217        dataSection = thisSection;
218        section.type = AsmSectionType::DATA;
219        section.elfBinSectId = ELFSECTID_RODATA;
220        section.name = ".rodata"; // set static name (available by whole lifecycle)
221    }
222    else if (::strcmp(sectionName, ".text") == 0) // code
223    {
224        if (codeSection!=ASMSECT_NONE)
225            throw AsmFormatException("Only one section '.text' can be in binary");
226        codeSection = thisSection;
227        section.type = AsmSectionType::CODE;
228        section.elfBinSectId = ELFSECTID_TEXT;
229        section.name = ".text"; // set static name (available by whole lifecycle)
230    }
231    else if (::strcmp(sectionName, ".comment") == 0) // comment
232    {
233        if (commentSection!=ASMSECT_NONE)
234            throw AsmFormatException("Only one section '.comment' can be in binary");
235        commentSection = thisSection;
236        section.type = AsmSectionType::GALLIUM_COMMENT;
237        section.elfBinSectId = ELFSECTID_COMMENT;
238        section.name = ".comment"; // set static name (available by whole lifecycle)
239    }
240    else
241    {
242        auto out = extraSectionMap.insert(std::make_pair(CString(sectionName),
243                    thisSection));
244        if (!out.second)
245            throw AsmFormatException("Section already exists");
246        section.type = AsmSectionType::EXTRA_SECTION;
247        section.elfBinSectId = extraSectionCount++;
248        /// reference entry is available and unchangeable by whole lifecycle of section map
249        section.name = out.first->first.c_str();
250    }
251    sections.push_back(section);
252   
253    assembler.currentKernel = ASMKERN_GLOBAL;
254    assembler.currentSection = thisSection;
255    inside = Inside::MAINLAYOUT;
256    return thisSection;
257}
258
259cxuint AsmGalliumHandler::getSectionId(const char* sectionName) const
260{
261    if (::strcmp(sectionName, ".rodata") == 0) // data
262        return dataSection;
263    else if (::strcmp(sectionName, ".text") == 0) // code
264        return codeSection;
265    else if (::strcmp(sectionName, ".comment") == 0) // comment
266        return commentSection;
267    else
268    {
269        SectionMap::const_iterator it = extraSectionMap.find(sectionName);
270        if (it != extraSectionMap.end())
271            return it->second;
272    }
273    return ASMSECT_NONE;
274}
275
276void AsmGalliumHandler::setCurrentKernel(cxuint kernel)
277{   // set kernel and their default section
278    if (kernel != ASMKERN_GLOBAL && kernel >= kernelStates.size())
279        throw AsmFormatException("KernelId out of range");
280   
281    if (assembler.currentKernel == ASMKERN_GLOBAL)
282        savedSection = assembler.currentSection;
283   
284    assembler.currentKernel = kernel;
285    if (kernel != ASMKERN_GLOBAL)
286        assembler.currentSection = kernelStates[kernel]->defaultSection;
287    else // default main section
288        assembler.currentSection = savedSection;
289    inside = Inside::MAINLAYOUT;
290}
291
292void AsmGalliumHandler::setCurrentSection(cxuint sectionId)
293{
294    if (sectionId >= sections.size())
295        throw AsmFormatException("SectionId out of range");
296   
297    if (assembler.currentKernel == ASMKERN_GLOBAL)
298        savedSection = assembler.currentSection;
299   
300    assembler.currentSection = sectionId;
301    assembler.currentKernel = sections[sectionId].kernelId;
302    inside = Inside::MAINLAYOUT;
303}
304
305AsmFormatHandler::SectionInfo AsmGalliumHandler::getSectionInfo(cxuint sectionId) const
306{
307    if (sectionId >= sections.size())
308        throw AsmFormatException("Section doesn't exists");
309   
310    AsmFormatHandler::SectionInfo info;
311    info.type = sections[sectionId].type;
312    info.flags = 0;
313    if (info.type == AsmSectionType::CODE)
314        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE;
315    else if (info.type != AsmSectionType::CONFIG)
316        info.flags = ASMSECT_ADDRESSABLE | ASMSECT_WRITEABLE | ASMSECT_ABS_ADDRESSABLE;
317   
318    info.name = sections[sectionId].name;
319    return info;
320}
321
322// check whether label is kernel label and restore register allocation to this kernel
323void AsmGalliumHandler::handleLabel(const CString& label)
324{
325    if (assembler.sections[assembler.currentSection].type != AsmSectionType::CODE)
326        return;
327    auto kit = assembler.kernelMap.find(label);
328    if (kit == assembler.kernelMap.end())
329        return;
330    if (!kcodeSelection.empty())
331        return; // do not change if inside kcode
332    // add code start
333    assembler.sections[assembler.currentSection].addCodeFlowEntry({
334                    size_t(assembler.currentOutPos), 0, AsmCodeFlowType::START });
335    // save other state
336    saveKcodeCurrentAllocRegs();
337    if (currentKcodeKernel != ASMKERN_GLOBAL)
338        assembler.kernels[currentKcodeKernel].closeCodeRegion(
339                        assembler.sections[codeSection].content.size());
340    // restore this state
341    currentKcodeKernel = kit->second;
342    restoreKcodeCurrentAllocRegs();
343    if (currentKcodeKernel != ASMKERN_GLOBAL)
344        assembler.kernels[currentKcodeKernel].openCodeRegion(
345                        assembler.sections[codeSection].content.size());
346}
347
348void AsmGalliumHandler::restoreKcodeCurrentAllocRegs()
349{
350    if (currentKcodeKernel != ASMKERN_GLOBAL)
351    {
352        Kernel& newKernel = *kernelStates[currentKcodeKernel];
353        assembler.isaAssembler->setAllocatedRegisters(newKernel.allocRegs,
354                            newKernel.allocRegFlags);
355    }
356}
357
358void AsmGalliumHandler::saveKcodeCurrentAllocRegs()
359{
360    if (currentKcodeKernel != ASMKERN_GLOBAL)
361    {   // save other state
362        size_t regTypesNum;
363        Kernel& oldKernel = *kernelStates[currentKcodeKernel];
364        const cxuint* regs = assembler.isaAssembler->getAllocatedRegisters(
365                            regTypesNum, oldKernel.allocRegFlags);
366        std::copy(regs, regs+regTypesNum, oldKernel.allocRegs);
367    }
368}
369
370namespace CLRX
371{
372
373bool AsmGalliumPseudoOps::checkPseudoOpName(const CString& string)
374{
375    if (string.empty() || string[0] != '.')
376        return false;
377    const size_t pseudoOp = binaryFind(galliumPseudoOpNamesTbl, galliumPseudoOpNamesTbl +
378                sizeof(galliumPseudoOpNamesTbl)/sizeof(char*), string.c_str()+1,
379               CStringLess()) - galliumPseudoOpNamesTbl;
380    return pseudoOp < sizeof(galliumPseudoOpNamesTbl)/sizeof(char*);
381}
382
383void AsmGalliumPseudoOps::setArchMinor(AsmGalliumHandler& handler, const char* linePtr)
384{
385    Assembler& asmr = handler.assembler;
386    const char* end = asmr.line + asmr.lineSize;
387    skipSpacesToEnd(linePtr, end);
388    uint64_t value;
389    const char* valuePlace = linePtr;
390    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
391        return;
392    asmr.printWarningForRange(sizeof(cxuint)<<3, value,
393                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
394    if (!checkGarbagesAtEnd(asmr, linePtr))
395        return;
396    handler.archMinor = value;
397}
398
399void AsmGalliumPseudoOps::setArchStepping(AsmGalliumHandler& handler, const char* linePtr)
400{
401    Assembler& asmr = handler.assembler;
402    const char* end = asmr.line + asmr.lineSize;
403    skipSpacesToEnd(linePtr, end);
404    uint64_t value;
405    const char* valuePlace = linePtr;
406    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
407        return;
408    asmr.printWarningForRange(sizeof(cxuint)<<3, value,
409                 asmr.getSourcePos(valuePlace), WS_UNSIGNED);
410    if (!checkGarbagesAtEnd(asmr, linePtr))
411        return;
412    handler.archStepping = value;
413}
414
415void AsmGalliumPseudoOps::setDriverVersion(AsmGalliumHandler& handler, const char* linePtr)
416{
417    Assembler& asmr = handler.assembler;
418    const char* end = asmr.line + asmr.lineSize;
419    skipSpacesToEnd(linePtr, end);
420    uint64_t value;
421    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
422        return;
423    if (!checkGarbagesAtEnd(asmr, linePtr))
424        return;
425    asmr.driverVersion = value;
426}
427
428void AsmGalliumPseudoOps::setLLVMVersion(AsmGalliumHandler& handler, const char* linePtr)
429{
430    Assembler& asmr = handler.assembler;
431    const char* end = asmr.line + asmr.lineSize;
432    skipSpacesToEnd(linePtr, end);
433    uint64_t value;
434    if (!getAbsoluteValueArg(asmr, value, linePtr, true))
435        return;
436    if (!checkGarbagesAtEnd(asmr, linePtr))
437        return;
438    asmr.llvmVersion = value;
439}
440
441void AsmGalliumPseudoOps::getXXXVersion(AsmGalliumHandler& handler, const char* linePtr,
442            bool getLLVMVersion)
443{
444    Assembler& asmr = handler.assembler;
445    const char* end = asmr.line + asmr.lineSize;
446    skipSpacesToEnd(linePtr, end);
447   
448    const char* symNamePlace = linePtr;
449    const CString symName = extractScopedSymName(linePtr, end, false);
450    if (symName.empty())
451    {
452        asmr.printError(symNamePlace, "Illegal symbol name");
453        return;
454    }
455    size_t symNameLength = symName.size();
456    if (symNameLength >= 3 && symName.compare(symNameLength-3, 3, "::.")==0)
457    {
458        asmr.printError(symNamePlace, "Symbol '.' can be only in global scope");
459        return;
460    }
461    if (!checkGarbagesAtEnd(asmr, linePtr))
462        return;
463   
464    cxuint driverVersion = 0;
465    if (getLLVMVersion)
466        driverVersion = handler.determineLLVMVersion();
467    else
468        driverVersion = handler.determineDriverVersion();
469   
470    std::pair<AsmSymbolEntry*, bool> res = asmr.insertSymbolInScope(symName,
471                AsmSymbol(ASMSECT_ABS, driverVersion));
472    if (!res.second)
473    {   // found
474        if (res.first->second.onceDefined && res.first->second.isDefined()) // if label
475            asmr.printError(symNamePlace, (std::string("Symbol '")+symName.c_str()+
476                        "' is already defined").c_str());
477        else
478            asmr.setSymbol(*res.first, driverVersion, ASMSECT_ABS);
479    }
480}
481
482void AsmGalliumPseudoOps::doConfig(AsmGalliumHandler& handler, const char* pseudoOpPlace,
483                      const char* linePtr)
484{
485    Assembler& asmr = handler.assembler;
486    const char* end = asmr.line + asmr.lineSize;
487    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
488    {
489        asmr.printError(pseudoOpPlace, "Configuration outside kernel definition");
490        return;
491    }
492    if (handler.kernelStates[asmr.currentKernel]->hasProgInfo)
493    {
494        asmr.printError(pseudoOpPlace,
495                "Configuration can't be defined if progInfo was defined");
496        return;
497    }
498    skipSpacesToEnd(linePtr, end);
499    if (!checkGarbagesAtEnd(asmr, linePtr))
500        return;
501   
502    handler.inside = AsmGalliumHandler::Inside::CONFIG;
503    handler.output.kernels[asmr.currentKernel].useConfig = true;
504    if (handler.determineLLVMVersion() >= 40000U) // HSA since LLVM 4.0
505        handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
506}
507
508void AsmGalliumPseudoOps::doControlDirective(AsmGalliumHandler& handler,
509              const char* pseudoOpPlace, const char* linePtr)
510{
511    Assembler& asmr = handler.assembler;
512    if (asmr.currentKernel==ASMKERN_GLOBAL)
513    {
514        asmr.printError(pseudoOpPlace, "Kernel control directive can be defined "
515                    "only inside kernel");
516        return;
517    }
518    if (handler.determineLLVMVersion() < 40000U)
519    {
520        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
521        return;
522    }
523    if (!checkGarbagesAtEnd(asmr, linePtr))
524        return;
525   
526    AsmGalliumHandler::Kernel& kernel = *handler.kernelStates[asmr.currentKernel];
527    if (kernel.ctrlDirSection == ASMSECT_NONE)
528    {
529        cxuint thisSection = handler.sections.size();
530        handler.sections.push_back({ asmr.currentKernel,
531            AsmSectionType::ROCM_CONFIG_CTRL_DIRECTIVE,
532            ELFSECTID_UNDEF, nullptr });
533        kernel.ctrlDirSection = thisSection;
534    }
535    asmr.goToSection(pseudoOpPlace, kernel.ctrlDirSection);
536    handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
537}
538
539void AsmGalliumPseudoOps::doGlobalData(AsmGalliumHandler& handler,
540                   const char* pseudoOpPlace, const char* linePtr)
541{
542    Assembler& asmr = handler.assembler;
543    const char* end = asmr.line + asmr.lineSize;
544    skipSpacesToEnd(linePtr, end);
545    if (!checkGarbagesAtEnd(asmr, linePtr))
546        return;
547   
548    asmr.goToSection(pseudoOpPlace, ".rodata");
549}
550
551void AsmGalliumPseudoOps::setDimensions(AsmGalliumHandler& handler,
552            const char* pseudoOpPlace, const char* linePtr, bool amdHsa)
553{
554    Assembler& asmr = handler.assembler;
555    if (asmr.currentKernel==ASMKERN_GLOBAL ||
556        handler.inside != AsmGalliumHandler::Inside::CONFIG)
557    {
558        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
559        return;
560    }
561    if (amdHsa && handler.determineLLVMVersion() < 40000U)
562    {
563        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
564        return;
565    }
566       
567    cxuint dimMask = 0;
568    if (!parseDimensions(asmr, linePtr, dimMask))
569        return;
570    if (!checkGarbagesAtEnd(asmr, linePtr))
571        return;
572    if (!amdHsa)
573        handler.output.kernels[asmr.currentKernel].config.dimMask = dimMask;
574    else
575    {    // AMD HSA
576        handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
577        AsmAmdHsaKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
578        config.dimMask = dimMask;
579    }
580}
581
582void AsmGalliumPseudoOps::setConfigValue(AsmGalliumHandler& handler,
583         const char* pseudoOpPlace, const char* linePtr, GalliumConfigValueTarget target)
584{
585    Assembler& asmr = handler.assembler;
586    const char* end = asmr.line + asmr.lineSize;
587   
588    if (asmr.currentKernel==ASMKERN_GLOBAL ||
589        handler.inside != AsmGalliumHandler::Inside::CONFIG)
590    {
591        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
592        return;
593    }
594   
595    if (target >= GALLIUMCVAL_HSA_FIRST_PARAM && handler.determineLLVMVersion() < 40000U)
596    {
597        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
598        return;
599    }
600   
601    skipSpacesToEnd(linePtr, end);
602    const char* valuePlace = linePtr;
603    uint64_t value = BINGEN_NOTSUPPLIED;
604    bool good = getAbsoluteValueArg(asmr, value, linePtr, true);
605    /* ranges checking */
606    if (good)
607    {
608        switch(target)
609        {
610            case GALLIUMCVAL_SGPRSNUM:
611            {
612                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
613                            asmr.deviceType);
614                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
615                if (value > maxSGPRsNum)
616                {
617                    char buf[64];
618                    snprintf(buf, 64, "Used SGPRs number out of range (0-%u)", maxSGPRsNum);
619                    asmr.printError(valuePlace, buf);
620                    good = false;
621                }
622                break;
623            }
624            case GALLIUMCVAL_VGPRSNUM:
625            {
626                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
627                            asmr.deviceType);
628                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
629                if (value > maxVGPRsNum)
630                {
631                    char buf[64];
632                    snprintf(buf, 64, "Used VGPRs number out of range (0-%u)", maxVGPRsNum);
633                    asmr.printError(valuePlace, buf);
634                    good = false;
635                }
636                break;
637            }
638            case GALLIUMCVAL_SPILLEDSGPRS:
639            {
640                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
641                            asmr.deviceType);
642                cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
643                if (value > maxSGPRsNum)
644                {
645                    char buf[64];
646                    snprintf(buf, 64, "Spilled SGPRs number out of range (0-%u)",
647                             maxSGPRsNum);
648                    asmr.printError(valuePlace, buf);
649                    good = false;
650                }
651                break;
652            }
653            case GALLIUMCVAL_SPILLEDVGPRS:
654            {
655                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
656                            asmr.deviceType);
657                cxuint maxVGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_VGPR, 0);
658                if (value > maxVGPRsNum)
659                {
660                    char buf[64];
661                    snprintf(buf, 64, "Spilled VGPRs number out of range (0-%u)",
662                             maxVGPRsNum);
663                    asmr.printError(valuePlace, buf);
664                    good = false;
665                }
666                break;
667            }
668            case GALLIUMCVAL_EXCEPTIONS:
669                asmr.printWarningForRange(7, value,
670                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
671                value &= 0x7f;
672                break;
673            case GALLIUMCVAL_FLOATMODE:
674                asmr.printWarningForRange(8, value,
675                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
676                value &= 0xff;
677                break;
678            case GALLIUMCVAL_PRIORITY:
679                asmr.printWarningForRange(2, value,
680                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
681                value &= 3;
682                break;
683            case GALLIUMCVAL_LOCALSIZE:
684            {
685                const GPUArchitecture arch = getGPUArchitectureFromDeviceType(
686                            asmr.deviceType);
687                const cxuint maxLocalSize = getGPUMaxLocalSize(arch);
688                if (value > maxLocalSize)
689                {
690                    char buf[64];
691                    snprintf(buf, 64, "LocalSize out of range (0-%u)", maxLocalSize);
692                    asmr.printError(valuePlace, buf);
693                    good = false;
694                }
695                break;
696            }
697            case GALLIUMCVAL_USERDATANUM:
698                if (value > 16)
699                {
700                    asmr.printError(valuePlace, "UserDataNum out of range (0-16)");
701                    good = false;
702                }
703                break;
704            case GALLIUMCVAL_PGMRSRC1:
705            case GALLIUMCVAL_PGMRSRC2:
706                asmr.printWarningForRange(32, value,
707                                  asmr.getSourcePos(valuePlace), WS_UNSIGNED);
708                break;
709            default:
710                break;
711        }
712       
713        if (good && target >= GALLIUMCVAL_HSA_FIRST_PARAM)
714            good = AsmROCmPseudoOps::checkConfigValue(asmr, valuePlace,
715                ROCmConfigValueTarget(target-GALLIUMCVAL_HSA_FIRST_PARAM), value);
716    }
717   
718    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
719        return;
720   
721    GalliumKernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
722    // set value
723    switch(target)
724    {
725        case GALLIUMCVAL_SGPRSNUM:
726            config.usedSGPRsNum = value;
727            break;
728        case GALLIUMCVAL_VGPRSNUM:
729            config.usedVGPRsNum = value;
730            break;
731        case GALLIUMCVAL_SPILLEDSGPRS:
732            config.spilledSGPRs = value;
733            break;
734        case GALLIUMCVAL_SPILLEDVGPRS:
735            config.spilledVGPRs = value;
736            break;
737        case GALLIUMCVAL_PGMRSRC1:
738            config.pgmRSRC1 = value;
739            break;
740        case GALLIUMCVAL_PGMRSRC2:
741            config.pgmRSRC2 = value;
742            break;
743        case GALLIUMCVAL_FLOATMODE:
744            config.floatMode = value;
745            break;
746        case GALLIUMCVAL_LOCALSIZE:
747            config.localSize = value;
748            break;
749        case GALLIUMCVAL_SCRATCHBUFFER:
750            config.scratchBufferSize = value;
751            break;
752        case GALLIUMCVAL_PRIORITY:
753            config.priority = value;
754            break;
755        case GALLIUMCVAL_USERDATANUM:
756            config.userDataNum = value;
757            break;
758        case GALLIUMCVAL_EXCEPTIONS:
759            config.exceptions = value;
760            break;
761        default:
762            break;
763    }
764   
765    if (target >= GALLIUMCVAL_HSA_FIRST_PARAM)
766    {
767        handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
768        AsmAmdHsaKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
769       
770        AsmROCmPseudoOps::setConfigValueMain(config,
771                ROCmConfigValueTarget(target-GALLIUMCVAL_HSA_FIRST_PARAM), value);
772    }
773}
774
775void AsmGalliumPseudoOps::setConfigBoolValue(AsmGalliumHandler& handler,
776         const char* pseudoOpPlace, const char* linePtr, GalliumConfigValueTarget target)
777{
778    Assembler& asmr = handler.assembler;
779   
780    if (asmr.currentKernel==ASMKERN_GLOBAL ||
781        handler.inside != AsmGalliumHandler::Inside::CONFIG)
782    {
783        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
784        return;
785    }
786   
787    if (target >= GALLIUMCVAL_HSA_FIRST_PARAM && handler.determineLLVMVersion() < 40000U)
788    {
789        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
790        return;
791    }
792   
793    if (!checkGarbagesAtEnd(asmr, linePtr))
794        return;
795    GalliumKernelConfig& config = handler.output.kernels[asmr.currentKernel].config;
796    switch(target)
797    {
798        case GALLIUMCVAL_DEBUGMODE:
799            config.debugMode = true;
800            break;
801        case GALLIUMCVAL_DX10CLAMP:
802            config.dx10Clamp = true;
803            break;
804        case GALLIUMCVAL_IEEEMODE:
805            config.ieeeMode = true;
806            break;
807        case GALLIUMCVAL_PRIVMODE:
808            config.privilegedMode = true;
809            break;
810        case GALLIUMCVAL_TGSIZE:
811            config.tgSize = true;
812            break;
813        default:
814            break;
815    }
816   
817    if (target >= GALLIUMCVAL_HSA_FIRST_PARAM)
818    {
819        handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
820        AsmAmdHsaKernelConfig& config = *(handler.kernelStates[asmr.currentKernel]->config);
821       
822        AsmROCmPseudoOps::setConfigBoolValueMain(config,
823                    ROCmConfigValueTarget(target-GALLIUMCVAL_HSA_FIRST_PARAM));
824    }
825}
826
827void AsmGalliumPseudoOps::setMachine(AsmGalliumHandler& handler, const char* pseudoOpPlace,
828                      const char* linePtr)
829{
830    Assembler& asmr = handler.assembler;
831    if (asmr.currentKernel==ASMKERN_GLOBAL ||
832        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
833    {
834        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
835        return;
836    }
837    if (handler.determineLLVMVersion() < 40000U)
838    {
839        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
840        return;
841    }
842   
843    uint16_t kindValue = 0, majorValue = 0;
844    uint16_t minorValue = 0, steppingValue = 0;
845    if (!AsmROCmPseudoOps::parseMachine(asmr, linePtr, kindValue,
846                    majorValue, minorValue, steppingValue))
847        return;
848   
849    handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
850    AsmAmdHsaKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
851    config->amdMachineKind = kindValue;
852    config->amdMachineMajor = majorValue;
853    config->amdMachineMinor = minorValue;
854    config->amdMachineStepping = steppingValue;
855}
856
857void AsmGalliumPseudoOps::setCodeVersion(AsmGalliumHandler& handler,
858                const char* pseudoOpPlace, const char* linePtr)
859{
860    Assembler& asmr = handler.assembler;
861    if (asmr.currentKernel==ASMKERN_GLOBAL ||
862        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
863    {
864        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
865        return;
866    }
867    if (handler.determineLLVMVersion() < 40000U)
868    {
869        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
870        return;
871    }
872   
873    uint16_t majorValue = 0, minorValue = 0;
874    if (!AsmROCmPseudoOps::parseCodeVersion(asmr, linePtr, majorValue, minorValue))
875        return;
876   
877    handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
878    AsmAmdHsaKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
879    config->amdCodeVersionMajor = majorValue;
880    config->amdCodeVersionMinor = minorValue;
881}
882
883void AsmGalliumPseudoOps::setReservedXgprs(AsmGalliumHandler& handler, const char* pseudoOpPlace,
884                      const char* linePtr, bool inVgpr)
885{
886    Assembler& asmr = handler.assembler;
887    if (asmr.currentKernel==ASMKERN_GLOBAL ||
888        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
889    {
890        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
891        return;
892    }
893    if (handler.determineLLVMVersion() < 40000U)
894    {
895        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
896        return;
897    }
898   
899    uint16_t gprFirst = 0, gprCount = 0;
900    if (!AsmROCmPseudoOps::parseReservedXgprs(asmr, linePtr, inVgpr, gprFirst, gprCount))
901        return;
902   
903    handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
904    AsmAmdHsaKernelConfig* config = handler.kernelStates[asmr.currentKernel]->config.get();
905    if (inVgpr)
906    {
907        config->reservedVgprFirst = gprFirst;
908        config->reservedVgprCount = gprCount;
909    }
910    else
911    {
912        config->reservedSgprFirst = gprFirst;
913        config->reservedSgprCount = gprCount;
914    }
915}
916
917
918void AsmGalliumPseudoOps::setUseGridWorkGroupCount(AsmGalliumHandler& handler,
919                   const char* pseudoOpPlace, const char* linePtr)
920{
921    Assembler& asmr = handler.assembler;
922    if (asmr.currentKernel==ASMKERN_GLOBAL ||
923        asmr.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
924    {
925        asmr.printError(pseudoOpPlace, "Illegal place of configuration pseudo-op");
926        return;
927    }
928    if (handler.determineLLVMVersion() < 40000U)
929    {
930        asmr.printError(pseudoOpPlace, "HSA configuration pseudo-op only for LLVM>=4.0.0");
931        return;
932    }
933   
934    cxuint dimMask = 0;
935    if (!parseDimensions(asmr, linePtr, dimMask))
936        return;
937    if (!checkGarbagesAtEnd(asmr, linePtr))
938        return;
939    handler.kernelStates[asmr.currentKernel]->initializeAmdHsaKernelConfig();
940    uint16_t& flags = handler.kernelStates[asmr.currentKernel]->config->
941                enableSgprRegisterFlags;
942    flags = (flags & ~(7<<ROCMFLAG_USE_GRID_WORKGROUP_COUNT_BIT)) |
943            (dimMask<<ROCMFLAG_USE_GRID_WORKGROUP_COUNT_BIT);
944}
945
946void AsmGalliumPseudoOps::doArgs(AsmGalliumHandler& handler,
947               const char* pseudoOpPlace, const char* linePtr)
948{
949    Assembler& asmr = handler.assembler;
950    const char* end = asmr.line + asmr.lineSize;
951    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
952    {
953        asmr.printError(pseudoOpPlace, "Arguments outside kernel definition");
954        return;
955    }
956    skipSpacesToEnd(linePtr, end);
957    if (!checkGarbagesAtEnd(asmr, linePtr))
958        return;
959   
960    handler.inside = AsmGalliumHandler::Inside::ARGS;
961}
962
963static const std::pair<const char*, GalliumArgType> galliumArgTypesMap[9] =
964{
965    { "constant", GalliumArgType::CONSTANT },
966    { "global", GalliumArgType::GLOBAL },
967    { "image2d_rd", GalliumArgType::IMAGE2D_RDONLY },
968    { "image2d_wr", GalliumArgType::IMAGE2D_WRONLY },
969    { "image3d_rd", GalliumArgType::IMAGE3D_RDONLY },
970    { "image3d_wr", GalliumArgType::IMAGE3D_WRONLY },
971    { "local", GalliumArgType::LOCAL },
972    { "sampler", GalliumArgType::SAMPLER },
973    { "scalar", GalliumArgType::SCALAR }
974};
975
976static const std::pair<const char*, cxuint> galliumArgSemanticsMap[5] =
977{
978    { "general", cxuint(GalliumArgSemantic::GENERAL) },
979    { "griddim", cxuint(GalliumArgSemantic::GRID_DIMENSION) },
980    { "gridoffset", cxuint(GalliumArgSemantic::GRID_OFFSET) },
981    { "imgformat", cxuint(GalliumArgSemantic::IMAGE_FORMAT) },
982    { "imgsize", cxuint(GalliumArgSemantic::IMAGE_SIZE) },
983};
984
985void AsmGalliumPseudoOps::doArg(AsmGalliumHandler& handler, const char* pseudoOpPlace,
986                      const char* linePtr)
987{
988    Assembler& asmr = handler.assembler;
989    const char* end = asmr.line + asmr.lineSize;
990   
991    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
992    {
993        asmr.printError(pseudoOpPlace, "Argument definition outside kernel configuration");
994        return;
995    }
996    if (handler.inside != AsmGalliumHandler::Inside::ARGS)
997    {
998        asmr.printError(pseudoOpPlace, "Argument definition outside arguments list");
999        return;
1000    }
1001   
1002    skipSpacesToEnd(linePtr, end);
1003    char name[20];
1004    bool good = true;
1005    const char* nameStringPlace = linePtr;
1006    GalliumArgType argType = GalliumArgType::GLOBAL;
1007   
1008    GalliumArgSemantic argSemantic = GalliumArgSemantic::GENERAL;
1009    bool semanticDefined = false;
1010    if (getNameArg(asmr, 20, name, linePtr, "argument type"))
1011    {
1012        toLowerString(name);
1013        if (::strcmp(name, "griddim")==0)
1014        {   // shortcur for grid dimension
1015            argSemantic = GalliumArgSemantic::GRID_DIMENSION;
1016            argType = GalliumArgType::SCALAR;
1017            semanticDefined = true;
1018        }
1019        else if (::strcmp(name, "gridoffset")==0)
1020        {   // shortcut for grid dimension
1021            argSemantic = GalliumArgSemantic::GRID_OFFSET;
1022            argType = GalliumArgType::SCALAR;
1023            semanticDefined = true;
1024        }
1025        else
1026        {
1027            cxuint index = binaryMapFind(galliumArgTypesMap, galliumArgTypesMap + 9,
1028                         name, CStringLess()) - galliumArgTypesMap;
1029            if (index != 9) // end of this map
1030                argType = galliumArgTypesMap[index].second;
1031            else
1032            {
1033                asmr.printError(nameStringPlace, "Unknown argument type");
1034                good = false;
1035            }
1036        }
1037    }
1038    else
1039        good = false;
1040   
1041    // parse rest of arguments
1042    if (!skipRequiredComma(asmr, linePtr))
1043        return;
1044    skipSpacesToEnd(linePtr, end);
1045    const char* sizeStrPlace = linePtr;
1046    uint64_t size = 4;
1047    good &= getAbsoluteValueArg(asmr, size, linePtr, true);
1048   
1049    if (size > UINT32_MAX || size == 0)
1050        asmr.printWarning(sizeStrPlace, "Size of argument out of range");
1051   
1052    uint64_t targetSize = (size+3ULL)&~3ULL;
1053    uint64_t targetAlign = (size!=0) ? 1ULL<<(63-CLZ64(targetSize)) : 1;
1054    if (targetSize > targetAlign)
1055        targetAlign <<= 1;
1056    bool sext = false;
1057   
1058    bool haveComma;
1059    if (!skipComma(asmr, haveComma, linePtr))
1060        return;
1061    if (haveComma)
1062    {
1063        skipSpacesToEnd(linePtr, end);
1064        const char* targetSizePlace = linePtr;
1065        if (getAbsoluteValueArg(asmr, targetSize, linePtr, false))
1066        {
1067            if (targetSize > UINT32_MAX || targetSize == 0)
1068                asmr.printWarning(targetSizePlace, "Target size of argument out of range");
1069        }
1070        else
1071            good = false;
1072       
1073        if (!skipComma(asmr, haveComma, linePtr))
1074            return;
1075        if (haveComma)
1076        {
1077            skipSpacesToEnd(linePtr, end);
1078            const char* targetAlignPlace = linePtr;
1079            if (getAbsoluteValueArg(asmr, targetAlign, linePtr, false))
1080            {
1081                if (targetAlign > UINT32_MAX || targetAlign == 0)
1082                    asmr.printWarning(targetAlignPlace,
1083                                      "Target alignment of argument out of range");
1084                if (targetAlign==0 || targetAlign != (1ULL<<(63-CLZ64(targetAlign))))
1085                {
1086                    asmr.printError(targetAlignPlace, "Target alignment is not power of 2");
1087                    good = false;
1088                }
1089            }
1090            else
1091                good = false;
1092           
1093            if (!skipComma(asmr, haveComma, linePtr))
1094                return;
1095            if (haveComma)
1096            {
1097                skipSpacesToEnd(linePtr, end);
1098                const char* numExtPlace = linePtr;
1099                if (getNameArg(asmr, 5, name, linePtr, "numeric extension", false))
1100                {
1101                    toLowerString(name);
1102                    if (::strcmp(name, "sext")==0)
1103                        sext = true;
1104                    else if (::strcmp(name, "zext")!=0 && *name!=0)
1105                    {
1106                        asmr.printError(numExtPlace, "Unknown numeric extension");
1107                        good = false;
1108                    }
1109                }
1110                else
1111                    good = false;
1112               
1113                if (!semanticDefined)
1114                {   /// if semantic has not been defined in the first argument
1115                    if (!skipComma(asmr, haveComma, linePtr))
1116                        return;
1117                    if (haveComma)
1118                    {
1119                        cxuint semantic;
1120                        if (getEnumeration(asmr, linePtr, "argument semantic", 5,
1121                                    galliumArgSemanticsMap, semantic))
1122                            argSemantic = GalliumArgSemantic(semantic);
1123                        else
1124                            good = false;
1125                    }
1126                }
1127            }
1128        }
1129    }
1130   
1131    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
1132        return;
1133   
1134    // put this definition to argument list
1135    handler.output.kernels[asmr.currentKernel].argInfos.push_back(
1136        { argType, sext, argSemantic, uint32_t(size),
1137            uint32_t(targetSize), uint32_t(targetAlign) });
1138}
1139
1140void AsmGalliumPseudoOps::doProgInfo(AsmGalliumHandler& handler,
1141                 const char* pseudoOpPlace, const char* linePtr)
1142{
1143    Assembler& asmr = handler.assembler;
1144    const char* end = asmr.line + asmr.lineSize;
1145    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1146    {
1147        asmr.printError(pseudoOpPlace, "ProgInfo outside kernel definition");
1148        return;
1149    }
1150    if (handler.output.kernels[asmr.currentKernel].useConfig)
1151    {
1152        asmr.printError(pseudoOpPlace,
1153                "ProgInfo can't be defined if configuration was exists");
1154        return;
1155    }
1156    skipSpacesToEnd(linePtr, end);
1157    if (!checkGarbagesAtEnd(asmr, linePtr))
1158        return;
1159   
1160    handler.inside = AsmGalliumHandler::Inside::PROGINFO;
1161    handler.kernelStates[asmr.currentKernel]->hasProgInfo = true;
1162}
1163
1164void AsmGalliumPseudoOps::doEntry(AsmGalliumHandler& handler,
1165                    const char* pseudoOpPlace, const char* linePtr)
1166{
1167    Assembler& asmr = handler.assembler;
1168    const char* end = asmr.line + asmr.lineSize;
1169   
1170    if (handler.sections[asmr.currentSection].type != AsmSectionType::CONFIG)
1171    {
1172        asmr.printError(pseudoOpPlace, "ProgInfo entry outside kernel configuration");
1173        return;
1174    }
1175    if (handler.inside != AsmGalliumHandler::Inside::PROGINFO)
1176    {
1177        asmr.printError(pseudoOpPlace, "ProgInfo entry definition outside ProgInfo");
1178        return;
1179    }
1180   
1181    skipSpacesToEnd(linePtr, end);
1182    const char* addrPlace = linePtr;
1183    uint64_t entryAddr;
1184    bool good = true;
1185    if (getAbsoluteValueArg(asmr, entryAddr, linePtr, true))
1186        asmr.printWarningForRange(32, entryAddr, asmr.getSourcePos(addrPlace),
1187                              WS_UNSIGNED);
1188    else
1189        good = false;
1190    if (!skipRequiredComma(asmr, linePtr))
1191        return;
1192   
1193    skipSpacesToEnd(linePtr, end);
1194    const char* entryValPlace = linePtr;
1195    uint64_t entryVal;
1196    if (getAbsoluteValueArg(asmr, entryVal, linePtr, true))
1197        asmr.printWarningForRange(32, entryVal, asmr.getSourcePos(entryValPlace));
1198    else
1199        good = false;
1200   
1201    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
1202        return;
1203   
1204    // do operation
1205    AsmGalliumHandler::Kernel& kstate = *handler.kernelStates[asmr.currentKernel];
1206    kstate.hasProgInfo = true;
1207    const cxuint llvmVersion = handler.determineLLVMVersion();
1208    if (llvmVersion<30900U && kstate.progInfoEntries == 3)
1209    {
1210        asmr.printError(pseudoOpPlace, "Maximum 3 entries can be in ProgInfo");
1211        return;
1212    }
1213    if (llvmVersion>=30900U && kstate.progInfoEntries == 5)
1214    {
1215        asmr.printError(pseudoOpPlace, "Maximum 5 entries can be in ProgInfo");
1216        return;
1217    }
1218    GalliumProgInfoEntry& pentry = handler.output.kernels[asmr.currentKernel]
1219            .progInfo[kstate.progInfoEntries++];
1220    pentry.address = entryAddr;
1221    pentry.value = entryVal;
1222}
1223
1224/* update kernel code selection, join all regallocation and store to
1225 * current kernel regalloc */
1226void AsmGalliumPseudoOps::updateKCodeSel(AsmGalliumHandler& handler,
1227          const std::vector<cxuint>& oldset)
1228{
1229    Assembler& asmr = handler.assembler;
1230    // old elements - join current regstate with all them
1231    size_t regTypesNum;
1232    for (auto it = oldset.begin(); it != oldset.end(); ++it)
1233    {
1234        Flags curAllocRegFlags;
1235        const cxuint* curAllocRegs = asmr.isaAssembler->getAllocatedRegisters(regTypesNum,
1236                               curAllocRegFlags);
1237        cxuint newAllocRegs[MAX_REGTYPES_NUM];
1238        AsmGalliumHandler::Kernel& kernel = *handler.kernelStates[*it];
1239        for (size_t i = 0; i < regTypesNum; i++)
1240            newAllocRegs[i] = std::max(curAllocRegs[i], kernel.allocRegs[i]);
1241        kernel.allocRegFlags |= curAllocRegFlags;
1242        std::copy(newAllocRegs, newAllocRegs+regTypesNum, kernel.allocRegs);
1243    }
1244    asmr.isaAssembler->setAllocatedRegisters();
1245}
1246
1247void AsmGalliumPseudoOps::doKCode(AsmGalliumHandler& handler, const char* pseudoOpPlace,
1248                      const char* linePtr)
1249{
1250    Assembler& asmr = handler.assembler;
1251    const char* end = asmr.line + asmr.lineSize;
1252    bool good = true;
1253    skipSpacesToEnd(linePtr, end);
1254    if (linePtr==end)
1255        return;
1256    std::unordered_set<cxuint> newSel(handler.kcodeSelection.begin(),
1257                          handler.kcodeSelection.end());
1258    do {
1259        CString kname;
1260        const char* knamePlace = linePtr;
1261        skipSpacesToEnd(linePtr, end);
1262        bool removeKernel = false;
1263        if (linePtr!=end && *linePtr=='-')
1264        {   // '-' - remove this kernel from current kernel selection
1265            removeKernel = true;
1266            linePtr++;
1267        }
1268        else if (linePtr!=end && *linePtr=='+')
1269        {
1270            linePtr++;
1271            skipSpacesToEnd(linePtr, end);
1272            if (linePtr==end)
1273            {   // add all kernels
1274                for (cxuint k = 0; k < handler.kernelStates.size(); k++)
1275                    newSel.insert(k);
1276                break;
1277            }
1278        }
1279       
1280        if (!getNameArg(asmr, kname, linePtr, "kernel"))
1281        { good = false; continue; }
1282        auto kit = asmr.kernelMap.find(kname);
1283        if (kit == asmr.kernelMap.end())
1284        {
1285            asmr.printError(knamePlace, "Kernel not found");
1286            continue;
1287        }
1288        if (!removeKernel)
1289            newSel.insert(kit->second);
1290        else // remove kernel
1291            newSel.erase(kit->second);
1292    } while (skipCommaForMultipleArgs(asmr, linePtr));
1293   
1294    if (!good || !checkGarbagesAtEnd(asmr, linePtr))
1295        return;
1296   
1297    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
1298    {
1299        asmr.printError(pseudoOpPlace, "KCode outside code");
1300        return;
1301    }
1302    if (handler.kcodeSelStack.empty())
1303        handler.saveKcodeCurrentAllocRegs();
1304    // push to stack
1305    handler.kcodeSelStack.push(handler.kcodeSelection);
1306    // set current sel
1307    handler.kcodeSelection.assign(newSel.begin(), newSel.end());
1308    std::sort(handler.kcodeSelection.begin(), handler.kcodeSelection.end());
1309   
1310    const std::vector<cxuint>& oldKCodeSel = handler.kcodeSelStack.top();
1311    if (!oldKCodeSel.empty())
1312        asmr.handleRegionsOnKernels(handler.kcodeSelection, oldKCodeSel,
1313                            handler.codeSection);
1314    else if (handler.currentKcodeKernel != ASMKERN_GLOBAL)
1315    {
1316        std::vector<cxuint> tempKCodeSel;
1317        tempKCodeSel.push_back(handler.currentKcodeKernel);
1318        asmr.handleRegionsOnKernels(handler.kcodeSelection, tempKCodeSel,
1319                            handler.codeSection);
1320    }
1321   
1322    updateKCodeSel(handler, handler.kcodeSelStack.top());
1323}
1324
1325void AsmGalliumPseudoOps::doKCodeEnd(AsmGalliumHandler& handler, const char* pseudoOpPlace,
1326                  const char* linePtr)
1327{
1328    Assembler& asmr = handler.assembler;
1329    if (handler.sections[asmr.currentSection].type != AsmSectionType::CODE)
1330    {
1331        asmr.printError(pseudoOpPlace, "KCodeEnd outside code");
1332        return;
1333    }
1334    if (handler.kcodeSelStack.empty())
1335    {
1336        asmr.printError(pseudoOpPlace, "'.kcodeend' without '.kcode'");
1337        return;
1338    }
1339    updateKCodeSel(handler, handler.kcodeSelection);
1340    std::vector<cxuint> oldKCodeSel = handler.kcodeSelection;
1341    handler.kcodeSelection = handler.kcodeSelStack.top();
1342   
1343    if (!handler.kcodeSelection.empty())
1344        asmr.handleRegionsOnKernels(handler.kcodeSelection, oldKCodeSel,
1345                        handler.codeSection);
1346    else if (handler.currentKcodeKernel != ASMKERN_GLOBAL)
1347    {   // if choosen current kernel
1348        std::vector<cxuint> curKernelSel;
1349        curKernelSel.push_back(handler.currentKcodeKernel);
1350        asmr.handleRegionsOnKernels(curKernelSel, oldKCodeSel, handler.codeSection);
1351    }
1352   
1353    handler.kcodeSelStack.pop();
1354    if (handler.kcodeSelStack.empty())
1355        handler.restoreKcodeCurrentAllocRegs();
1356}
1357
1358}
1359
1360bool AsmGalliumHandler::parsePseudoOp(const CString& firstName,
1361           const char* stmtPlace, const char* linePtr)
1362{
1363    const size_t pseudoOp = binaryFind(galliumPseudoOpNamesTbl, galliumPseudoOpNamesTbl +
1364                    sizeof(galliumPseudoOpNamesTbl)/sizeof(char*), firstName.c_str()+1,
1365                   CStringLess()) - galliumPseudoOpNamesTbl;
1366   
1367    switch(pseudoOp)
1368    {
1369        case GALLIUMOP_ARCH_MINOR:
1370            AsmGalliumPseudoOps::setArchMinor(*this, linePtr);
1371            break;
1372        case GALLIUMOP_ARCH_STEPPING:
1373            AsmGalliumPseudoOps::setArchStepping(*this, linePtr);
1374            break;
1375        case GALLIUMOP_ARG:
1376            AsmGalliumPseudoOps::doArg(*this, stmtPlace, linePtr);
1377            break;
1378        case GALLIUMOP_ARGS:
1379            AsmGalliumPseudoOps::doArgs(*this, stmtPlace, linePtr);
1380            break;
1381        case GALLIUMOP_CALL_CONVENTION:
1382            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1383                             GALLIUMCVAL_CALL_CONVENTION);
1384            break;
1385        case GALLIUMOP_CODEVERSION:
1386            AsmGalliumPseudoOps::setCodeVersion(*this, stmtPlace, linePtr);
1387            break;
1388        case GALLIUMOP_CONFIG:
1389            AsmGalliumPseudoOps::doConfig(*this, stmtPlace, linePtr);
1390            break;
1391        case GALLIUMOP_CONTROL_DIRECTIVE:
1392            AsmGalliumPseudoOps::doControlDirective(*this, stmtPlace, linePtr);
1393            break;
1394        case GALLIUMOP_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR:
1395            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1396                             GALLIUMCVAL_DEBUG_PRIVATE_SEGMENT_BUFFER_SGPR);
1397            break;
1398        case GALLIUMOP_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR:
1399            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1400                         GALLIUMCVAL_DEBUG_WAVEFRONT_PRIVATE_SEGMENT_OFFSET_SGPR);
1401            break;
1402        case GALLIUMOP_DEBUGMODE:
1403            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1404                                GALLIUMCVAL_DEBUGMODE);
1405            break;
1406        case GALLIUMOP_DIMS:
1407            AsmGalliumPseudoOps::setDimensions(*this, stmtPlace, linePtr, false);
1408            break;
1409        case GALLIUMOP_DRIVER_VERSION:
1410            AsmGalliumPseudoOps::setDriverVersion(*this, linePtr);
1411            break;
1412        case GALLIUMOP_DX10CLAMP:
1413            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1414                                GALLIUMCVAL_DX10CLAMP);
1415            break;
1416        case GALLIUMOP_ENTRY:
1417            AsmGalliumPseudoOps::doEntry(*this, stmtPlace, linePtr);
1418            break;
1419        case GALLIUMOP_EXCEPTIONS:
1420            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1421                                    GALLIUMCVAL_EXCEPTIONS);
1422            break;
1423        case GALLIUMOP_FLOATMODE:
1424            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1425                                    GALLIUMCVAL_FLOATMODE);
1426            break;
1427        case GALLIUMOP_GDS_SEGMENT_SIZE:
1428            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1429                             GALLIUMCVAL_GDS_SEGMENT_SIZE);
1430            break;
1431        case GALLIUMOP_GET_DRIVER_VERSION:
1432            AsmGalliumPseudoOps::getXXXVersion(*this, linePtr, false);
1433            break;
1434        case GALLIUMOP_GET_LLVM_VERSION:
1435            AsmGalliumPseudoOps::getXXXVersion(*this, linePtr, true);
1436            break;
1437        case GALLIUMOP_GLOBALDATA:
1438            AsmGalliumPseudoOps::doGlobalData(*this, stmtPlace, linePtr);
1439            break;
1440        case GALLIUMOP_GROUP_SEGMENT_ALIGN:
1441            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1442                             GALLIUMCVAL_GROUP_SEGMENT_ALIGN);
1443            break;
1444        case GALLIUMOP_HSA_DEBUGMODE:
1445            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1446                                GALLIUMCVAL_HSA_DEBUGMODE);
1447            break;
1448        case GALLIUMOP_HSA_DIMS:
1449            AsmGalliumPseudoOps::setDimensions(*this, stmtPlace, linePtr, true);
1450            break;
1451        case GALLIUMOP_HSA_DX10CLAMP:
1452            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1453                                GALLIUMCVAL_HSA_DX10CLAMP);
1454            break;
1455        case GALLIUMOP_HSA_EXCEPTIONS:
1456            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1457                                    GALLIUMCVAL_HSA_EXCEPTIONS);
1458            break;
1459        case GALLIUMOP_HSA_FLOATMODE:
1460            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1461                                    GALLIUMCVAL_HSA_FLOATMODE);
1462            break;
1463        case GALLIUMOP_HSA_IEEEMODE:
1464            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1465                                GALLIUMCVAL_HSA_IEEEMODE);
1466            break;
1467        case GALLIUMOP_HSA_LOCALSIZE:
1468            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1469                             GALLIUMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
1470            break;
1471        case GALLIUMOP_HSA_PGMRSRC1:
1472            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1473                                    GALLIUMCVAL_HSA_PGMRSRC1);
1474            break;
1475        case GALLIUMOP_HSA_PGMRSRC2:
1476            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1477                                    GALLIUMCVAL_HSA_PGMRSRC2);
1478            break;
1479        case GALLIUMOP_HSA_PRIORITY:
1480            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1481                                    GALLIUMCVAL_HSA_PRIORITY);
1482            break;
1483        case GALLIUMOP_HSA_PRIVMODE:
1484            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1485                                GALLIUMCVAL_HSA_PRIVMODE);
1486            break;
1487        case GALLIUMOP_HSA_SGPRSNUM:
1488            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1489                                    GALLIUMCVAL_HSA_SGPRSNUM);
1490            break;
1491        case GALLIUMOP_HSA_TGSIZE:
1492            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1493                                GALLIUMCVAL_HSA_TGSIZE);
1494            break;
1495        case GALLIUMOP_HSA_USERDATANUM:
1496            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1497                                    GALLIUMCVAL_HSA_USERDATANUM);
1498            break;
1499        case GALLIUMOP_HSA_VGPRSNUM:
1500            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1501                                    GALLIUMCVAL_HSA_VGPRSNUM);
1502            break;
1503        case GALLIUMOP_IEEEMODE:
1504            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1505                                    GALLIUMCVAL_IEEEMODE);
1506            break;
1507        case GALLIUMOP_KCODE:
1508            AsmGalliumPseudoOps::doKCode(*this, stmtPlace, linePtr);
1509            break;
1510        case GALLIUMOP_KCODEEND:
1511            AsmGalliumPseudoOps::doKCodeEnd(*this, stmtPlace, linePtr);
1512            break;
1513        case GALLIUMOP_KERNARG_SEGMENT_ALIGN:
1514            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1515                             GALLIUMCVAL_KERNARG_SEGMENT_ALIGN);
1516            break;
1517        case GALLIUMOP_KERNARG_SEGMENT_SIZE:
1518            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1519                             GALLIUMCVAL_KERNARG_SEGMENT_SIZE);
1520            break;
1521        case GALLIUMOP_KERNEL_CODE_ENTRY_OFFSET:
1522            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1523                             GALLIUMCVAL_KERNEL_CODE_ENTRY_OFFSET);
1524            break;
1525        case GALLIUMOP_KERNEL_CODE_PREFETCH_OFFSET:
1526            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1527                             GALLIUMCVAL_KERNEL_CODE_PREFETCH_OFFSET);
1528            break;
1529        case GALLIUMOP_KERNEL_CODE_PREFETCH_SIZE:
1530            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1531                             GALLIUMCVAL_KERNEL_CODE_PREFETCH_SIZE);
1532            break;
1533        case GALLIUMOP_LLVM_VERSION:
1534            AsmGalliumPseudoOps::setLLVMVersion(*this, linePtr);
1535            break;
1536        case GALLIUMOP_LOCALSIZE:
1537            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1538                                    GALLIUMCVAL_LOCALSIZE);
1539            break;
1540        case GALLIUMOP_MACHINE:
1541            AsmGalliumPseudoOps::setMachine(*this, stmtPlace, linePtr);
1542            break;
1543        case GALLIUMOP_MAX_SCRATCH_BACKING_MEMORY:
1544            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1545                             GALLIUMCVAL_MAX_SCRATCH_BACKING_MEMORY);
1546            break;
1547        case GALLIUMOP_PRIORITY:
1548            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1549                                    GALLIUMCVAL_PRIORITY);
1550            break;
1551        case GALLIUMOP_PRIVATE_ELEM_SIZE:
1552            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1553                             GALLIUMCVAL_PRIVATE_ELEM_SIZE);
1554            break;
1555        case GALLIUMOP_PRIVATE_SEGMENT_ALIGN:
1556            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1557                             GALLIUMCVAL_PRIVATE_SEGMENT_ALIGN);
1558            break;
1559        case GALLIUMOP_PRIVMODE:
1560            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1561                                GALLIUMCVAL_PRIVMODE);
1562            break;
1563        case GALLIUMOP_PGMRSRC1:
1564            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1565                                    GALLIUMCVAL_PGMRSRC1);
1566            break;
1567        case GALLIUMOP_PGMRSRC2:
1568            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1569                                    GALLIUMCVAL_PGMRSRC2);
1570            break;
1571        case GALLIUMOP_PROGINFO:
1572            AsmGalliumPseudoOps::doProgInfo(*this, stmtPlace, linePtr);
1573            break;
1574        case GALLIUMOP_RESERVED_SGPRS:
1575            AsmGalliumPseudoOps::setReservedXgprs(*this, stmtPlace, linePtr, false);
1576            break;
1577        case GALLIUMOP_RESERVED_VGPRS:
1578            AsmGalliumPseudoOps::setReservedXgprs(*this, stmtPlace, linePtr, true);
1579            break;
1580        case GALLIUMOP_RUNTIME_LOADER_KERNEL_SYMBOL:
1581            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1582                             GALLIUMCVAL_RUNTIME_LOADER_KERNEL_SYMBOL);
1583            break;
1584        case GALLIUMOP_SCRATCHBUFFER:
1585            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1586                                    GALLIUMCVAL_SCRATCHBUFFER);
1587            break;
1588        case GALLIUMOP_SGPRSNUM:
1589            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1590                                    GALLIUMCVAL_SGPRSNUM);
1591            break;
1592        case GALLIUMOP_SPILLEDSGPRS:
1593            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1594                                    GALLIUMCVAL_SPILLEDSGPRS);
1595            break;
1596        case GALLIUMOP_SPILLEDVGPRS:
1597            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1598                                    GALLIUMCVAL_SPILLEDVGPRS);
1599            break;
1600        case GALLIUMOP_USE_DEBUG_ENABLED:
1601            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1602                             GALLIUMCVAL_USE_DEBUG_ENABLED);
1603            break;
1604        case GALLIUMOP_USE_DISPATCH_ID:
1605            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1606                             GALLIUMCVAL_USE_DISPATCH_ID);
1607            break;
1608        case GALLIUMOP_USE_DISPATCH_PTR:
1609            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1610                             GALLIUMCVAL_USE_DISPATCH_PTR);
1611            break;
1612        case GALLIUMOP_USE_DYNAMIC_CALL_STACK:
1613            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1614                             GALLIUMCVAL_USE_DYNAMIC_CALL_STACK);
1615            break;
1616        case GALLIUMOP_USE_FLAT_SCRATCH_INIT:
1617            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1618                             GALLIUMCVAL_USE_FLAT_SCRATCH_INIT);
1619            break;
1620        case GALLIUMOP_USE_GRID_WORKGROUP_COUNT:
1621            AsmGalliumPseudoOps::setUseGridWorkGroupCount(*this, stmtPlace, linePtr);
1622            break;
1623        case GALLIUMOP_USE_KERNARG_SEGMENT_PTR:
1624            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1625                             GALLIUMCVAL_USE_KERNARG_SEGMENT_PTR);
1626            break;
1627        case GALLIUMOP_USE_ORDERED_APPEND_GDS:
1628            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1629                             GALLIUMCVAL_USE_ORDERED_APPEND_GDS);
1630            break;
1631        case GALLIUMOP_USE_PRIVATE_SEGMENT_SIZE:
1632            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1633                             GALLIUMCVAL_USE_PRIVATE_SEGMENT_SIZE);
1634            break;
1635        case GALLIUMOP_USE_PTR64:
1636            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1637                             GALLIUMCVAL_USE_PTR64);
1638            break;
1639        case GALLIUMOP_USE_QUEUE_PTR:
1640            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1641                             GALLIUMCVAL_USE_QUEUE_PTR);
1642            break;
1643        case GALLIUMOP_USE_PRIVATE_SEGMENT_BUFFER:
1644            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1645                             GALLIUMCVAL_USE_PRIVATE_SEGMENT_BUFFER);
1646            break;
1647        case GALLIUMOP_USE_XNACK_ENABLED:
1648            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1649                             GALLIUMCVAL_USE_XNACK_ENABLED);
1650            break;
1651        case GALLIUMOP_TGSIZE:
1652            AsmGalliumPseudoOps::setConfigBoolValue(*this, stmtPlace, linePtr,
1653                                GALLIUMCVAL_TGSIZE);
1654            break;
1655        case GALLIUMOP_USERDATANUM:
1656            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1657                                    GALLIUMCVAL_USERDATANUM);
1658            break;
1659        case GALLIUMOP_VGPRSNUM:
1660            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1661                                    GALLIUMCVAL_VGPRSNUM);
1662            break;
1663        case GALLIUMOP_WAVEFRONT_SGPR_COUNT:
1664            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1665                             GALLIUMCVAL_WAVEFRONT_SGPR_COUNT);
1666            break;
1667        case GALLIUMOP_WAVEFRONT_SIZE:
1668            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1669                             GALLIUMCVAL_WAVEFRONT_SIZE);
1670            break;
1671        case GALLIUMOP_WORKITEM_VGPR_COUNT:
1672            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1673                             GALLIUMCVAL_WORKITEM_VGPR_COUNT);
1674            break;
1675        case GALLIUMOP_WORKGROUP_FBARRIER_COUNT:
1676            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1677                             GALLIUMCVAL_WORKGROUP_FBARRIER_COUNT);
1678            break;
1679        case GALLIUMOP_WORKGROUP_GROUP_SEGMENT_SIZE:
1680            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1681                             GALLIUMCVAL_WORKGROUP_GROUP_SEGMENT_SIZE);
1682            break;
1683        case GALLIUMOP_WORKITEM_PRIVATE_SEGMENT_SIZE:
1684            AsmGalliumPseudoOps::setConfigValue(*this, stmtPlace, linePtr,
1685                             GALLIUMCVAL_WORKITEM_PRIVATE_SEGMENT_SIZE);
1686            break;
1687        default:
1688            return false;
1689    }
1690    return true;
1691}
1692
1693static const AMDGPUArchValues galliumAmdGpuArchValuesTbl[] =
1694{
1695    { 0, 0, 0 }, // GPUDeviceType::CAPE_VERDE
1696    { 0, 0, 0 }, // GPUDeviceType::PITCAIRN
1697    { 0, 0, 0 }, // GPUDeviceType::TAHITI
1698    { 0, 0, 0 }, // GPUDeviceType::OLAND
1699    { 7, 0, 0 }, // GPUDeviceType::BONAIRE
1700    { 7, 0, 0 }, // GPUDeviceType::SPECTRE
1701    { 7, 0, 0 }, // GPUDeviceType::SPOOKY
1702    { 7, 0, 0 }, // GPUDeviceType::KALINDI
1703    { 0, 0, 0 }, // GPUDeviceType::HAINAN
1704    { 7, 0, 1 }, // GPUDeviceType::HAWAII
1705    { 8, 0, 0 }, // GPUDeviceType::ICELAND
1706    { 8, 0, 0 }, // GPUDeviceType::TONGA
1707    { 7, 0, 0 }, // GPUDeviceType::MULLINS
1708    { 8, 0, 3 }, // GPUDeviceType::FIJI
1709    { 8, 0, 1 }, // GPUDeviceType::CARRIZO
1710    { 0, 0, 0 }, // GPUDeviceType::DUMMY
1711    { 0, 0, 0 }, // GPUDeviceType::GOOSE
1712    { 0, 0, 0 }, // GPUDeviceType::HORSE
1713    { 8, 0, 1 }, // GPUDeviceType::STONEY
1714    { 8, 0, 4 }, // GPUDeviceType::ELLESMERE
1715    { 8, 0, 4 }, // GPUDeviceType::BAFFIN
1716    { 8, 0, 4 }, // GPUDeviceType::GFX804
1717    { 9, 0, 0 } // GPUDeviceType::GFX900
1718};
1719
1720bool AsmGalliumHandler::prepareBinary()
1721{   // before call we initialize pointers and datas
1722    bool good = true;
1723   
1724    output.is64BitElf = assembler.is64Bit();
1725    size_t sectionsNum = sections.size();
1726    size_t kernelsNum = kernelStates.size();
1727    output.deviceType = assembler.getDeviceType();
1728    if (assembler.isaAssembler!=nullptr)
1729    {   // make last kernel registers pool updates
1730        if (kcodeSelStack.empty())
1731            saveKcodeCurrentAllocRegs();
1732        else
1733            while (!kcodeSelStack.empty())
1734            {   // pop from kcode stack and apply changes
1735                AsmGalliumPseudoOps::updateKCodeSel(*this, kcodeSelection);
1736                kcodeSelection = kcodeSelStack.top();
1737                kcodeSelStack.pop();
1738            }
1739    }
1740   
1741    for (size_t i = 0; i < sectionsNum; i++)
1742    {
1743        const AsmSection& asmSection = assembler.sections[i];
1744        const Section& section = sections[i];
1745        const size_t sectionSize = asmSection.getSize();
1746        const cxbyte* sectionData = (!asmSection.content.empty()) ?
1747                asmSection.content.data() : (const cxbyte*)"";
1748        switch(asmSection.type)
1749        {
1750            case AsmSectionType::CODE:
1751                output.codeSize = sectionSize;
1752                output.code = sectionData;
1753                break;
1754            case AsmSectionType::DATA:
1755                output.globalDataSize = sectionSize;
1756                output.globalData = sectionData;
1757                break;
1758            case AsmSectionType::EXTRA_PROGBITS:
1759            case AsmSectionType::EXTRA_NOTE:
1760            case AsmSectionType::EXTRA_NOBITS:
1761            case AsmSectionType::EXTRA_SECTION:
1762            {
1763                uint32_t elfSectType =
1764                       (asmSection.type==AsmSectionType::EXTRA_NOTE) ? SHT_NOTE :
1765                       (asmSection.type==AsmSectionType::EXTRA_NOBITS) ? SHT_NOBITS :
1766                             SHT_PROGBITS;
1767                uint32_t elfSectFlags = 
1768                    ((asmSection.flags&ASMELFSECT_ALLOCATABLE) ? SHF_ALLOC : 0) |
1769                    ((asmSection.flags&ASMELFSECT_WRITEABLE) ? SHF_WRITE : 0) |
1770                    ((asmSection.flags&ASMELFSECT_EXECUTABLE) ? SHF_EXECINSTR : 0);
1771                output.extraSections.push_back({section.name, sectionSize, sectionData,
1772                    asmSection.alignment!=0?asmSection.alignment:1, elfSectType,
1773                    elfSectFlags, ELFSECTID_NULL, 0, 0 });
1774                break;
1775            }
1776            case AsmSectionType::GALLIUM_COMMENT:
1777                output.commentSize = sectionSize;
1778                output.comment = (const char*)sectionData;
1779                break;
1780            case AsmSectionType::GALLIUM_CONFIG_CTRL_DIRECTIVE:
1781                if (sectionSize != 128)
1782                    assembler.printError(AsmSourcePos(),
1783                         (std::string("Section '.control_directive' for kernel '")+
1784                          assembler.kernels[section.kernelId].name+
1785                          "' have wrong size").c_str());
1786                break;
1787            default: // ignore other sections
1788                break;
1789        }
1790    }
1791   
1792    GPUArchitecture arch = getGPUArchitectureFromDeviceType(assembler.deviceType);
1793    // set up number of the allocated SGPRs and VGPRs for kernel
1794    cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
1795   
1796    for (size_t i = 0; i < kernelsNum; i++)
1797    {
1798        if (!output.kernels[i].useConfig)
1799            continue;
1800        GalliumKernelConfig& config = output.kernels[i].config;
1801        cxuint userSGPRsNum = config.userDataNum;
1802        /* include userData sgprs */
1803        cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1804                ((config.pgmRSRC2>>7)&7);
1805        // extra sgprs for dimensions
1806        cxuint minRegsNum[2];
1807        getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1808                   ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1809                   ((config.scratchBufferSize!=0) ? GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1810       
1811        if (config.usedSGPRsNum!=BINGEN_DEFAULT && maxSGPRsNum < config.usedSGPRsNum)
1812        {   // check only if sgprsnum set explicitly
1813            char numBuf[64];
1814            snprintf(numBuf, 64, "(max %u)", maxSGPRsNum);
1815            assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1816                    "Number of total SGPRs for kernel '")+
1817                    output.kernels[i].kernelName.c_str()+"' is too high "+numBuf).c_str());
1818            good = false;
1819        }
1820       
1821        if (config.usedSGPRsNum==BINGEN_DEFAULT)
1822        {
1823            config.usedSGPRsNum = std::min(
1824                std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]) +
1825                    getGPUExtraRegsNum(arch, REGTYPE_SGPR,
1826                        kernelStates[i]->allocRegFlags|GCN_VCC),
1827                    maxSGPRsNum); // include all extra sgprs
1828        }
1829        if (config.usedVGPRsNum==BINGEN_DEFAULT)
1830            config.usedVGPRsNum = std::max(minRegsNum[1], kernelStates[i]->allocRegs[1]);
1831    }
1832   
1833    // if set adds symbols to binary
1834    if (assembler.getFlags() & ASM_FORCE_ADD_SYMBOLS)
1835        for (const AsmSymbolEntry& symEntry: assembler.globalScope.symbolMap)
1836        {
1837            if (!symEntry.second.hasValue)
1838                continue; // unresolved
1839            if (ELF32_ST_BIND(symEntry.second.info) == STB_LOCAL)
1840                continue; // local
1841            if (ELF32_ST_BIND(symEntry.second.info) == STB_GLOBAL)
1842            {
1843                assembler.printError(AsmSourcePos(), (std::string("Added symbol '")+
1844                    symEntry.first.c_str()+"' must not be a global").c_str());
1845                good = false;
1846                continue; // local
1847            }
1848            if (assembler.kernelMap.find(symEntry.first.c_str())!=assembler.kernelMap.end())
1849                continue; // if kernel name
1850            cxuint binSectId = (symEntry.second.sectionId != ASMSECT_ABS) ?
1851                    sections[symEntry.second.sectionId].elfBinSectId : ELFSECTID_ABS;
1852            if (binSectId==ELFSECTID_UNDEF)
1853                continue; // no section
1854           
1855            output.extraSymbols.push_back({ symEntry.first, symEntry.second.value,
1856                    symEntry.second.size, binSectId, false, symEntry.second.info,
1857                    symEntry.second.other });
1858        }
1859    // setup amd GPU arch values (for LLVM 4.0 HSA config)
1860    AMDGPUArchValues amdGpuArchValues = galliumAmdGpuArchValuesTbl[
1861                    cxuint(assembler.deviceType)];
1862    if (archMinor != BINGEN_DEFAULT)
1863        amdGpuArchValues.minor = archMinor;
1864    if (archStepping != BINGEN_DEFAULT)
1865        amdGpuArchValues.stepping = archStepping;
1866    /// checking symbols and set offset for kernels
1867    AsmSection& asmCSection = assembler.sections[codeSection];
1868    const AsmSymbolMap& symbolMap = assembler.getSymbolMap();
1869   
1870    cxuint llvmVersion = assembler.llvmVersion;
1871    if (llvmVersion == 0 && (assembler.flags&ASM_TESTRUN)==0)
1872        llvmVersion = defaultLLVMVersion;
1873   
1874    const cxuint ldsShift = arch<GPUArchitecture::GCN1_1 ? 8 : 9;
1875    const uint32_t ldsMask = (1U<<ldsShift)-1U;
1876   
1877    for (size_t ki = 0; ki < output.kernels.size(); ki++)
1878    {
1879        GalliumKernelInput& kinput = output.kernels[ki];
1880        auto it = symbolMap.find(kinput.kernelName);
1881        if (it == symbolMap.end() || !it->second.isDefined())
1882        {   // error, undefined
1883            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1884                        "Symbol for kernel '")+kinput.kernelName.c_str()+
1885                        "' is undefined").c_str());
1886            good = false;
1887            continue;
1888        }
1889        const AsmSymbol& symbol = it->second;
1890        if (!symbol.hasValue)
1891        {   // error, unresolved
1892            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1893                    "Symbol for kernel '") + kinput.kernelName.c_str() +
1894                    "' is not resolved").c_str());
1895            good = false;
1896            continue;
1897        }
1898        if (symbol.sectionId != codeSection)
1899        {   /// error, wrong section
1900            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1901                    "Symbol for kernel '")+kinput.kernelName.c_str()+
1902                    "' is defined for section other than '.text'").c_str());
1903            good = false;
1904            continue;
1905        }
1906        kinput.offset = symbol.value;
1907        if (llvmVersion >= 40000U && output.kernels[ki].useConfig)
1908        {   // requires amdhsa-gcn (with HSA header)
1909            // hotfix
1910            GalliumKernelConfig config = output.kernels[ki].config;
1911            AmdHsaKernelConfig outConfig;
1912            ::memset(&outConfig, 0xff, 128); // fill by defaults
1913            outConfig.enableSgprRegisterFlags =
1914                    uint16_t(AMDHSAFLAG_USE_PRIVATE_SEGMENT_BUFFER|
1915                        AMDHSAFLAG_USE_DISPATCH_PTR|AMDHSAFLAG_USE_KERNARG_SEGMENT_PTR);
1916            outConfig.enableFeatureFlags = uint16_t(AMDHSAFLAG_USE_PTR64|2);
1917           
1918            const Kernel& kernel = *kernelStates[ki];
1919            if (kernel.config != nullptr)
1920            {   // replace by HSA config
1921                ::memcpy(&outConfig, kernel.config.get(), sizeof(AmdHsaKernelConfig));
1922                // set config from HSA config
1923                const AsmAmdHsaKernelConfig& hsaConfig = *kernel.config.get();
1924                if (hsaConfig.usedSGPRsNum != BINGEN_DEFAULT)
1925                    config.usedSGPRsNum = hsaConfig.usedSGPRsNum;
1926                if (hsaConfig.usedVGPRsNum != BINGEN_DEFAULT)
1927                    config.usedVGPRsNum = hsaConfig.usedVGPRsNum;
1928                if (hsaConfig.userDataNum != BINGEN8_DEFAULT)
1929                    config.userDataNum = hsaConfig.userDataNum;
1930                config.dimMask |= hsaConfig.dimMask;
1931                config.pgmRSRC1 |= hsaConfig.computePgmRsrc1;
1932                config.pgmRSRC2 |= hsaConfig.computePgmRsrc2;
1933                config.ieeeMode |= hsaConfig.ieeeMode;
1934                config.floatMode |= hsaConfig.floatMode;
1935                config.priority = std::max(hsaConfig.priority, config.priority);
1936                config.exceptions |= hsaConfig.exceptions;
1937                config.tgSize |= hsaConfig.tgSize;
1938                config.debugMode |= hsaConfig.debugMode;
1939                config.privilegedMode |= hsaConfig.privilegedMode;
1940                config.dx10Clamp |= hsaConfig.dx10Clamp;
1941                if (hsaConfig.workgroupGroupSegmentSize != BINGEN_DEFAULT) // local size
1942                    config.localSize = hsaConfig.workgroupGroupSegmentSize;
1943                if (hsaConfig.workitemPrivateSegmentSize != BINGEN_DEFAULT) // scratch buffer
1944                    config.scratchBufferSize = hsaConfig.workitemPrivateSegmentSize;
1945               
1946                if (outConfig.enableSgprRegisterFlags == 0)
1947                    outConfig.enableSgprRegisterFlags =
1948                        uint16_t(AMDHSAFLAG_USE_PRIVATE_SEGMENT_BUFFER|
1949                            AMDHSAFLAG_USE_DISPATCH_PTR|AMDHSAFLAG_USE_KERNARG_SEGMENT_PTR);
1950                if (outConfig.enableFeatureFlags == 0)
1951                    outConfig.enableFeatureFlags = uint16_t(AMDHSAFLAG_USE_PTR64|2);
1952            }
1953           
1954            uint32_t dimValues = 0;
1955            if (config.dimMask != BINGEN_DEFAULT)
1956                dimValues = ((config.dimMask&7)<<7) |
1957                        (((config.dimMask&4) ? 2 : (config.dimMask&2) ? 1 : 0)<<11);
1958            else
1959                dimValues |= (config.pgmRSRC2 & 0x1b80U);
1960            cxuint sgprsNum = std::max(config.usedSGPRsNum, 1U);
1961            cxuint vgprsNum = std::max(config.usedVGPRsNum, 1U);
1962            uint32_t pgmRSRC1 =  (config.pgmRSRC1) | ((vgprsNum-1)>>2) |
1963                (((sgprsNum-1)>>3)<<6) | ((uint32_t(config.floatMode)&0xff)<<12) |
1964                (config.ieeeMode?1U<<23:0) | (uint32_t(config.priority&3)<<10) |
1965                (config.privilegedMode?1U<<20:0) | (config.dx10Clamp?1U<<21:0) |
1966                (config.debugMode?1U<<22:0);
1967           
1968            uint32_t pgmRSRC2 = (config.pgmRSRC2 & 0xffffe440U) |
1969                        (config.userDataNum<<1) | ((config.tgSize) ? 0x400 : 0) |
1970                        ((config.scratchBufferSize)?1:0) | dimValues |
1971                        (((config.localSize+ldsMask)>>ldsShift)<<15) |
1972                        ((uint32_t(config.exceptions)&0x7f)<<24);
1973           
1974            size_t argSegmentSize = 0;
1975            for (GalliumArgInfo& argInfo: output.kernels[ki].argInfos)
1976            {
1977                if (argInfo.semantic == GalliumArgSemantic::GRID_DIMENSION ||
1978                        argInfo.semantic == GalliumArgSemantic::GRID_OFFSET)
1979                    continue; // skip
1980                if (argInfo.targetAlign != 0)
1981                    argSegmentSize = (argSegmentSize + argInfo.targetAlign-1) &
1982                            ~size_t(argInfo.targetAlign-1);
1983                argSegmentSize += argInfo.targetSize;
1984            }
1985            argSegmentSize += 16; // gridOffset and gridDim
1986           
1987            if (outConfig.amdCodeVersionMajor == BINGEN_DEFAULT)
1988                outConfig.amdCodeVersionMajor = 1;
1989            if (outConfig.amdCodeVersionMinor == BINGEN_DEFAULT)
1990                outConfig.amdCodeVersionMinor = 0;
1991            if (outConfig.amdMachineKind == BINGEN16_DEFAULT)
1992                outConfig.amdMachineKind = 1;
1993            if (outConfig.amdMachineMajor == BINGEN16_DEFAULT)
1994                outConfig.amdMachineMajor = amdGpuArchValues.major;
1995            if (outConfig.amdMachineMinor == BINGEN16_DEFAULT)
1996                outConfig.amdMachineMinor = amdGpuArchValues.minor;
1997            if (outConfig.amdMachineStepping == BINGEN16_DEFAULT)
1998                outConfig.amdMachineStepping = amdGpuArchValues.stepping;
1999            if (outConfig.kernelCodeEntryOffset == BINGEN64_DEFAULT)
2000                outConfig.kernelCodeEntryOffset = 256;
2001            if (outConfig.kernelCodePrefetchOffset == BINGEN64_DEFAULT)
2002                outConfig.kernelCodePrefetchOffset = 0;
2003            if (outConfig.kernelCodePrefetchSize == BINGEN64_DEFAULT)
2004                outConfig.kernelCodePrefetchSize = 0;
2005            if (outConfig.maxScrachBackingMemorySize == BINGEN64_DEFAULT) // ??
2006                outConfig.maxScrachBackingMemorySize = 0;
2007            outConfig.computePgmRsrc1 = pgmRSRC1;
2008            outConfig.computePgmRsrc2 = pgmRSRC2;
2009            if (outConfig.workitemPrivateSegmentSize == BINGEN_DEFAULT) // scratch buffer
2010                outConfig.workitemPrivateSegmentSize = config.scratchBufferSize;
2011            if (outConfig.workgroupGroupSegmentSize == BINGEN_DEFAULT)
2012                outConfig.workgroupGroupSegmentSize = config.localSize;
2013            if (outConfig.gdsSegmentSize == BINGEN_DEFAULT)
2014                outConfig.gdsSegmentSize = 0;
2015            if (outConfig.kernargSegmentSize == BINGEN64_DEFAULT)
2016                outConfig.kernargSegmentSize = argSegmentSize;
2017            if (outConfig.workgroupFbarrierCount == BINGEN_DEFAULT)
2018                outConfig.workgroupFbarrierCount = 0;
2019            if (outConfig.wavefrontSgprCount == BINGEN16_DEFAULT)
2020                outConfig.wavefrontSgprCount = config.usedSGPRsNum;
2021            if (outConfig.workitemVgprCount == BINGEN16_DEFAULT)
2022                outConfig.workitemVgprCount = config.usedVGPRsNum;
2023            if (outConfig.reservedVgprFirst == BINGEN16_DEFAULT)
2024                outConfig.reservedVgprFirst = 0;
2025            if (outConfig.reservedVgprCount == BINGEN16_DEFAULT)
2026                outConfig.reservedVgprCount = 0;
2027            if (outConfig.reservedSgprFirst == BINGEN16_DEFAULT)
2028                outConfig.reservedSgprFirst = 0;
2029            if (outConfig.reservedSgprCount == BINGEN16_DEFAULT)
2030                outConfig.reservedSgprCount = 0;
2031            if (outConfig.debugWavefrontPrivateSegmentOffsetSgpr == BINGEN16_DEFAULT)
2032                outConfig.debugWavefrontPrivateSegmentOffsetSgpr = 0;
2033            if (outConfig.debugPrivateSegmentBufferSgpr == BINGEN16_DEFAULT)
2034                outConfig.debugPrivateSegmentBufferSgpr = 0;
2035            if (outConfig.kernargSegmentAlignment == BINGEN8_DEFAULT)
2036                outConfig.kernargSegmentAlignment = 4;
2037            if (outConfig.groupSegmentAlignment == BINGEN8_DEFAULT)
2038                outConfig.groupSegmentAlignment = 4;
2039            if (outConfig.privateSegmentAlignment == BINGEN8_DEFAULT)
2040                outConfig.privateSegmentAlignment = 4;
2041            if (outConfig.wavefrontSize == BINGEN8_DEFAULT)
2042                outConfig.wavefrontSize = 6;
2043            if (outConfig.callConvention == BINGEN_DEFAULT)
2044                outConfig.callConvention = 0;
2045            outConfig.reserved1[0] = 0;
2046            outConfig.reserved1[1] = 0;
2047            outConfig.reserved1[2] = 0;
2048            if (outConfig.runtimeLoaderKernelSymbol == BINGEN64_DEFAULT)
2049                outConfig.runtimeLoaderKernelSymbol = 0;
2050           
2051            // to little endian
2052            SLEV(outConfig.amdCodeVersionMajor, outConfig.amdCodeVersionMajor);
2053            SLEV(outConfig.amdCodeVersionMinor, outConfig.amdCodeVersionMinor);
2054            SLEV(outConfig.amdMachineKind, outConfig.amdMachineKind);
2055            SLEV(outConfig.amdMachineMajor, outConfig.amdMachineMajor);
2056            SLEV(outConfig.amdMachineMinor, outConfig.amdMachineMinor);
2057            SLEV(outConfig.amdMachineStepping, outConfig.amdMachineStepping);
2058            SLEV(outConfig.kernelCodeEntryOffset, outConfig.kernelCodeEntryOffset);
2059            SLEV(outConfig.kernelCodePrefetchOffset, outConfig.kernelCodePrefetchOffset);
2060            SLEV(outConfig.kernelCodePrefetchSize, outConfig.kernelCodePrefetchSize);
2061            SLEV(outConfig.maxScrachBackingMemorySize,
2062                 outConfig.maxScrachBackingMemorySize);
2063            SLEV(outConfig.computePgmRsrc1, outConfig.computePgmRsrc1);
2064            SLEV(outConfig.computePgmRsrc2, outConfig.computePgmRsrc2);
2065            SLEV(outConfig.enableSgprRegisterFlags, outConfig.enableSgprRegisterFlags);
2066            SLEV(outConfig.enableFeatureFlags, outConfig.enableFeatureFlags);
2067            SLEV(outConfig.workitemPrivateSegmentSize,
2068                 outConfig.workitemPrivateSegmentSize);
2069            SLEV(outConfig.workgroupGroupSegmentSize,
2070                 outConfig.workgroupGroupSegmentSize);
2071            SLEV(outConfig.gdsSegmentSize, outConfig.gdsSegmentSize);
2072            SLEV(outConfig.kernargSegmentSize, outConfig.kernargSegmentSize);
2073            SLEV(outConfig.workgroupFbarrierCount, outConfig.workgroupFbarrierCount);
2074            SLEV(outConfig.wavefrontSgprCount, outConfig.wavefrontSgprCount);
2075            SLEV(outConfig.workitemVgprCount, outConfig.workitemVgprCount);
2076            SLEV(outConfig.reservedVgprFirst, outConfig.reservedVgprFirst);
2077            SLEV(outConfig.reservedVgprCount, outConfig.reservedVgprCount);
2078            SLEV(outConfig.reservedSgprFirst, outConfig.reservedSgprFirst);
2079            SLEV(outConfig.reservedSgprCount, outConfig.reservedSgprCount);
2080            SLEV(outConfig.debugWavefrontPrivateSegmentOffsetSgpr,
2081                outConfig.debugWavefrontPrivateSegmentOffsetSgpr);
2082            SLEV(outConfig.debugPrivateSegmentBufferSgpr,
2083                 outConfig.debugPrivateSegmentBufferSgpr);
2084            SLEV(outConfig.callConvention, outConfig.callConvention);
2085            SLEV(outConfig.runtimeLoaderKernelSymbol,
2086                 outConfig.runtimeLoaderKernelSymbol);
2087            // put control directive section to config
2088            if (kernel.ctrlDirSection!=ASMSECT_NONE &&
2089                assembler.sections[kernel.ctrlDirSection].content.size()==128)
2090                ::memcpy(outConfig.controlDirective, 
2091                    assembler.sections[kernel.ctrlDirSection].content.data(), 128);
2092            else
2093                ::memset(outConfig.controlDirective, 0, 128);
2094           
2095            if (asmCSection.content.size() >= symbol.value+256)
2096                ::memcpy(asmCSection.content.data() + symbol.value,
2097                        &outConfig, sizeof(AmdHsaKernelConfig));
2098            else
2099                assembler.printError(AsmSourcePos(), (
2100                    std::string("HSA configuration for kernel'")+
2101                    kinput.kernelName.c_str()+"' out of content").c_str());
2102        }
2103    }
2104    // set versions
2105    if (assembler.driverVersion == 0 && (assembler.flags&ASM_TESTRUN)==0) // auto detection
2106        output.isMesa170 = defaultDriverVersion >= 170000U;
2107    else
2108        output.isMesa170 = assembler.driverVersion >= 170000U;
2109    output.isLLVM390 = llvmVersion >= 30900U;
2110    return good;
2111}
2112
2113void AsmGalliumHandler::writeBinary(std::ostream& os) const
2114{
2115    GalliumBinGenerator binGenerator(&output);
2116    binGenerator.generate(os);
2117}
2118
2119void AsmGalliumHandler::writeBinary(Array<cxbyte>& array) const
2120{
2121    GalliumBinGenerator binGenerator(&output);
2122    binGenerator.generate(array);
2123}
Note: See TracBrowser for help on using the repository browser.