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

Last change on this file since 3443 was 3443, checked in by matszpk, 18 months ago

CLRadeonExtender: Move tables with arch values (arch versions) to GPUId.

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