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

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

CLRadeonExtender: Commenting AsmAmdFormat? and AsmGalliumFormat?.

File size: 85.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
1637// AMD GPU architecture for Gallium
1638static const AMDGPUArchValues galliumAmdGpuArchValuesTbl[] =
1639{
1640    { 0, 0, 0 }, // GPUDeviceType::CAPE_VERDE
1641    { 0, 0, 0 }, // GPUDeviceType::PITCAIRN
1642    { 0, 0, 0 }, // GPUDeviceType::TAHITI
1643    { 0, 0, 0 }, // GPUDeviceType::OLAND
1644    { 7, 0, 0 }, // GPUDeviceType::BONAIRE
1645    { 7, 0, 0 }, // GPUDeviceType::SPECTRE
1646    { 7, 0, 0 }, // GPUDeviceType::SPOOKY
1647    { 7, 0, 0 }, // GPUDeviceType::KALINDI
1648    { 0, 0, 0 }, // GPUDeviceType::HAINAN
1649    { 7, 0, 1 }, // GPUDeviceType::HAWAII
1650    { 8, 0, 0 }, // GPUDeviceType::ICELAND
1651    { 8, 0, 0 }, // GPUDeviceType::TONGA
1652    { 7, 0, 0 }, // GPUDeviceType::MULLINS
1653    { 8, 0, 3 }, // GPUDeviceType::FIJI
1654    { 8, 0, 1 }, // GPUDeviceType::CARRIZO
1655    { 0, 0, 0 }, // GPUDeviceType::DUMMY
1656    { 0, 0, 0 }, // GPUDeviceType::GOOSE
1657    { 0, 0, 0 }, // GPUDeviceType::HORSE
1658    { 8, 0, 1 }, // GPUDeviceType::STONEY
1659    { 8, 0, 4 }, // GPUDeviceType::ELLESMERE
1660    { 8, 0, 4 }, // GPUDeviceType::BAFFIN
1661    { 8, 0, 4 }, // GPUDeviceType::GFX804
1662    { 9, 0, 0 }, // GPUDeviceType::GFX900
1663    { 9, 0, 1 }  // GPUDeviceType::GFX901
1664};
1665
1666bool AsmGalliumHandler::prepareBinary()
1667{
1668    // before call we initialize pointers and datas
1669    bool good = true;
1670   
1671    output.is64BitElf = assembler.is64Bit();
1672    size_t sectionsNum = sections.size();
1673    size_t kernelsNum = kernelStates.size();
1674    output.deviceType = assembler.getDeviceType();
1675    if (assembler.isaAssembler!=nullptr)
1676    {
1677        // make last kernel registers pool updates
1678        if (kcodeSelStack.empty())
1679            saveKcodeCurrentAllocRegs();
1680        else
1681            while (!kcodeSelStack.empty())
1682            {
1683                // pop from kcode stack and apply changes
1684                AsmGalliumPseudoOps::updateKCodeSel(*this, kcodeSelection);
1685                kcodeSelection = kcodeSelStack.top();
1686                kcodeSelStack.pop();
1687            }
1688    }
1689   
1690    // set sections as outputs
1691    for (size_t i = 0; i < sectionsNum; i++)
1692    {
1693        const AsmSection& asmSection = assembler.sections[i];
1694        const Section& section = sections[i];
1695        const size_t sectionSize = asmSection.getSize();
1696        const cxbyte* sectionData = (!asmSection.content.empty()) ?
1697                asmSection.content.data() : (const cxbyte*)"";
1698        switch(asmSection.type)
1699        {
1700            case AsmSectionType::CODE:
1701                output.codeSize = sectionSize;
1702                output.code = sectionData;
1703                break;
1704            case AsmSectionType::DATA:
1705                output.globalDataSize = sectionSize;
1706                output.globalData = sectionData;
1707                break;
1708            case AsmSectionType::EXTRA_PROGBITS:
1709            case AsmSectionType::EXTRA_NOTE:
1710            case AsmSectionType::EXTRA_NOBITS:
1711            case AsmSectionType::EXTRA_SECTION:
1712            {
1713                // handle extra (user) section, set section type and its flags
1714                uint32_t elfSectType =
1715                       (asmSection.type==AsmSectionType::EXTRA_NOTE) ? SHT_NOTE :
1716                       (asmSection.type==AsmSectionType::EXTRA_NOBITS) ? SHT_NOBITS :
1717                             SHT_PROGBITS;
1718                uint32_t elfSectFlags = 
1719                    ((asmSection.flags&ASMELFSECT_ALLOCATABLE) ? SHF_ALLOC : 0) |
1720                    ((asmSection.flags&ASMELFSECT_WRITEABLE) ? SHF_WRITE : 0) |
1721                    ((asmSection.flags&ASMELFSECT_EXECUTABLE) ? SHF_EXECINSTR : 0);
1722                output.extraSections.push_back({section.name, sectionSize, sectionData,
1723                    asmSection.alignment!=0?asmSection.alignment:1, elfSectType,
1724                    elfSectFlags, ELFSECTID_NULL, 0, 0 });
1725                break;
1726            }
1727            case AsmSectionType::GALLIUM_COMMENT:
1728                output.commentSize = sectionSize;
1729                output.comment = (const char*)sectionData;
1730                break;
1731            case AsmSectionType::GALLIUM_CONFIG_CTRL_DIRECTIVE:
1732                if (sectionSize != 128)
1733                    // control directive accepts only 128-byte size
1734                    assembler.printError(AsmSourcePos(),
1735                         (std::string("Section '.control_directive' for kernel '")+
1736                          assembler.kernels[section.kernelId].name+
1737                          "' have wrong size").c_str());
1738                break;
1739            default: // ignore other sections
1740                break;
1741        }
1742    }
1743   
1744    // get current llvm version (if not TESTRUN)
1745    cxuint llvmVersion = assembler.llvmVersion;
1746    if (llvmVersion == 0 && (assembler.flags&ASM_TESTRUN)==0)
1747        llvmVersion = detectedLLVMVersion;
1748   
1749    GPUArchitecture arch = getGPUArchitectureFromDeviceType(assembler.deviceType);
1750    // set up number of the allocated SGPRs and VGPRs for kernel
1751    cxuint maxSGPRsNum = getGPUMaxRegistersNum(arch, REGTYPE_SGPR, 0);
1752   
1753    for (size_t i = 0; i < kernelsNum; i++)
1754    {
1755        if (!output.kernels[i].useConfig)
1756            continue;
1757        GalliumKernelConfig& config = output.kernels[i].config;
1758        cxuint userSGPRsNum = config.userDataNum;
1759       
1760        if (llvmVersion >= 40000U && config.userDataNum == BINGEN8_DEFAULT)
1761        {
1762            // fixed userdatanum for LLVM 4.0
1763            const AmdHsaKernelConfig& hsaConfig  = *kernelStates[i]->hsaConfig.get();
1764            // calculate userSGPRs
1765            const uint16_t sgprFlags = hsaConfig.enableSgprRegisterFlags;
1766            userSGPRsNum =
1767                ((sgprFlags&ROCMFLAG_USE_PRIVATE_SEGMENT_BUFFER)!=0 ? 4 : 0) +
1768                ((sgprFlags&ROCMFLAG_USE_DISPATCH_PTR)!=0 ? 2 : 0) +
1769                ((sgprFlags&ROCMFLAG_USE_QUEUE_PTR)!=0 ? 2 : 0) +
1770                ((sgprFlags&ROCMFLAG_USE_KERNARG_SEGMENT_PTR)!=0 ? 2 : 0) +
1771                ((sgprFlags&ROCMFLAG_USE_DISPATCH_ID)!=0 ? 2 : 0) +
1772                ((sgprFlags&ROCMFLAG_USE_FLAT_SCRATCH_INIT)!=0 ? 2 : 0) +
1773                ((sgprFlags&ROCMFLAG_USE_PRIVATE_SEGMENT_SIZE)!=0) +
1774                /* use_grid_workgroup_count */
1775                ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_X)!=0) +
1776                ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_Y)!=0) +
1777                ((sgprFlags&ROCMFLAG_USE_GRID_WORKGROUP_COUNT_Z)!=0);
1778            userSGPRsNum = std::min(16U, userSGPRsNum);
1779            config.userDataNum = userSGPRsNum;
1780        }
1781       
1782        /* include userData sgprs */
1783        cxuint dimMask = (config.dimMask!=BINGEN_DEFAULT) ? config.dimMask :
1784                ((config.pgmRSRC2>>7)&7);
1785        // extra sgprs for dimensions
1786        cxuint minRegsNum[2];
1787        getGPUSetupMinRegistersNum(arch, dimMask, userSGPRsNum,
1788                   ((config.tgSize) ? GPUSETUP_TGSIZE_EN : 0) |
1789                   ((config.scratchBufferSize!=0) ? GPUSETUP_SCRATCH_EN : 0), minRegsNum);
1790       
1791        if (config.usedSGPRsNum!=BINGEN_DEFAULT && maxSGPRsNum < config.usedSGPRsNum)
1792        {
1793            // check only if sgprsnum set explicitly
1794            char numBuf[64];
1795            snprintf(numBuf, 64, "(max %u)", maxSGPRsNum);
1796            assembler.printError(assembler.kernels[i].sourcePos, (std::string(
1797                    "Number of total SGPRs for kernel '")+
1798                    output.kernels[i].kernelName.c_str()+"' is too high "+numBuf).c_str());
1799            good = false;
1800        }
1801       
1802        if (config.usedSGPRsNum==BINGEN_DEFAULT)
1803        {
1804            cxuint allocFlags = kernelStates[i]->allocRegFlags;
1805            if (llvmVersion >= 40000U)
1806            {
1807                // fix alloc reg flags for AMD HSA (such as ROCm)
1808                const AmdHsaKernelConfig& hsaConfig  = *kernelStates[i]->hsaConfig.get();
1809                allocFlags = kernelStates[i]->allocRegFlags |
1810                    // flat_scratch_init
1811                    ((hsaConfig.enableSgprRegisterFlags&
1812                            AMDHSAFLAG_USE_FLAT_SCRATCH_INIT)!=0? GCN_FLAT : 0) |
1813                    // enable_xnack
1814                    ((hsaConfig.enableFeatureFlags&AMDHSAFLAG_USE_XNACK_ENABLED)!=0 ?
1815                                GCN_XNACK : 0);
1816            }
1817           
1818            config.usedSGPRsNum = std::min(
1819                std::max(minRegsNum[0], kernelStates[i]->allocRegs[0]) +
1820                    getGPUExtraRegsNum(arch, REGTYPE_SGPR, allocFlags|GCN_VCC),
1821                    maxSGPRsNum); // include all extra sgprs
1822        }
1823        if (config.usedVGPRsNum==BINGEN_DEFAULT)
1824            config.usedVGPRsNum = std::max(minRegsNum[1], kernelStates[i]->allocRegs[1]);
1825    }
1826   
1827    // if set adds symbols to binary
1828    if (assembler.getFlags() & ASM_FORCE_ADD_SYMBOLS)
1829        for (const AsmSymbolEntry& symEntry: assembler.globalScope.symbolMap)
1830        {
1831            if (!symEntry.second.hasValue)
1832                continue; // unresolved
1833            if (ELF32_ST_BIND(symEntry.second.info) == STB_LOCAL)
1834                continue; // local
1835            if (ELF32_ST_BIND(symEntry.second.info) == STB_GLOBAL)
1836            {
1837                assembler.printError(AsmSourcePos(), (std::string("Added symbol '")+
1838                    symEntry.first.c_str()+"' must not be a global").c_str());
1839                good = false;
1840                continue; // local
1841            }
1842            if (assembler.kernelMap.find(symEntry.first.c_str())!=assembler.kernelMap.end())
1843                continue; // if kernel name
1844            cxuint binSectId = (symEntry.second.sectionId != ASMSECT_ABS) ?
1845                    sections[symEntry.second.sectionId].elfBinSectId : ELFSECTID_ABS;
1846            if (binSectId==ELFSECTID_UNDEF)
1847                continue; // no section
1848           
1849            output.extraSymbols.push_back({ symEntry.first, symEntry.second.value,
1850                    symEntry.second.size, binSectId, false, symEntry.second.info,
1851                    symEntry.second.other });
1852        }
1853   
1854    // setup amd GPU arch values (for LLVM 4.0 HSA config)
1855    AMDGPUArchValues amdGpuArchValues = galliumAmdGpuArchValuesTbl[
1856                    cxuint(assembler.deviceType)];
1857    // replace arch minor and stepping by user defined values (if set)
1858    if (archMinor != BINGEN_DEFAULT)
1859        amdGpuArchValues.minor = archMinor;
1860    if (archStepping != BINGEN_DEFAULT)
1861        amdGpuArchValues.stepping = archStepping;
1862    /// checking symbols and set offset for kernels
1863    AsmSection& asmCSection = assembler.sections[codeSection];
1864    const AsmSymbolMap& symbolMap = assembler.getSymbolMap();
1865   
1866    for (size_t ki = 0; ki < output.kernels.size(); ki++)
1867    {
1868        GalliumKernelInput& kinput = output.kernels[ki];
1869        auto it = symbolMap.find(kinput.kernelName);
1870        if (it == symbolMap.end() || !it->second.isDefined())
1871        {
1872            // error, undefined
1873            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1874                        "Symbol for kernel '")+kinput.kernelName.c_str()+
1875                        "' is undefined").c_str());
1876            good = false;
1877            continue;
1878        }
1879        const AsmSymbol& symbol = it->second;
1880        if (!symbol.hasValue)
1881        {
1882            // error, unresolved
1883            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1884                    "Symbol for kernel '") + kinput.kernelName.c_str() +
1885                    "' is not resolved").c_str());
1886            good = false;
1887            continue;
1888        }
1889        if (symbol.sectionId != codeSection)
1890        {
1891            /// error, wrong section
1892            assembler.printError(assembler.kernels[ki].sourcePos, (std::string(
1893                    "Symbol for kernel '")+kinput.kernelName.c_str()+
1894                    "' is defined for section other than '.text'").c_str());
1895            good = false;
1896            continue;
1897        }
1898        kinput.offset = symbol.value;
1899        // set up AMD HSA configuration in kernel code
1900        if (llvmVersion >= 40000U && output.kernels[ki].useConfig)
1901        {
1902            // requires amdhsa-gcn (with HSA header)
1903            // hotfix
1904            GalliumKernelConfig config = output.kernels[ki].config;
1905            // outConfig is final HSA config
1906            AmdHsaKernelConfig outConfig;
1907            ::memset(&outConfig, 0xff, 128); // fill by defaults
1908           
1909            const Kernel& kernel = *kernelStates[ki];
1910            if (kernel.hsaConfig != nullptr)
1911            {
1912                // replace Gallium config by HSA config
1913                ::memcpy(&outConfig, kernel.hsaConfig.get(), sizeof(AmdHsaKernelConfig));
1914                // set config from HSA config
1915                const AsmAmdHsaKernelConfig& hsaConfig = *kernel.hsaConfig.get();
1916                if (hsaConfig.usedSGPRsNum != BINGEN_DEFAULT)
1917                    config.usedSGPRsNum = hsaConfig.usedSGPRsNum;
1918                if (hsaConfig.usedVGPRsNum != BINGEN_DEFAULT)
1919                    config.usedVGPRsNum = hsaConfig.usedVGPRsNum;
1920                if (hsaConfig.userDataNum != BINGEN8_DEFAULT)
1921                    config.userDataNum = hsaConfig.userDataNum;
1922                config.dimMask |= hsaConfig.dimMask;
1923                config.pgmRSRC1 |= hsaConfig.computePgmRsrc1;
1924                config.pgmRSRC2 |= hsaConfig.computePgmRsrc2;
1925                config.ieeeMode |= hsaConfig.ieeeMode;
1926                config.floatMode |= hsaConfig.floatMode;
1927                config.priority = std::max(hsaConfig.priority, config.priority);
1928                config.exceptions |= hsaConfig.exceptions;
1929                config.tgSize |= hsaConfig.tgSize;
1930                config.debugMode |= hsaConfig.debugMode;
1931                config.privilegedMode |= hsaConfig.privilegedMode;
1932                config.dx10Clamp |= hsaConfig.dx10Clamp;
1933                if (hsaConfig.workgroupGroupSegmentSize != BINGEN_DEFAULT) // local size
1934                    config.localSize = hsaConfig.workgroupGroupSegmentSize;
1935                if (hsaConfig.workitemPrivateSegmentSize != BINGEN_DEFAULT)
1936                    // scratch buffer
1937                    config.scratchBufferSize = hsaConfig.workitemPrivateSegmentSize;
1938            }
1939            // calculate pgmrsrcs
1940            cxuint sgprsNum = std::max(config.usedSGPRsNum, 1U);
1941            cxuint vgprsNum = std::max(config.usedVGPRsNum, 1U);
1942            uint32_t pgmRSRC1 =  (config.pgmRSRC1) |
1943                    calculatePgmRSrc1(arch, vgprsNum, sgprsNum,
1944                        config.priority, config.floatMode, config.privilegedMode,
1945                        config.dx10Clamp, config.debugMode, config.ieeeMode);
1946           
1947            uint32_t pgmRSRC2 = (config.pgmRSRC2 & 0xffffe440U) |
1948                    calculatePgmRSrc2(arch, (config.scratchBufferSize != 0),
1949                            config.userDataNum, false, config.dimMask,
1950                            (config.pgmRSRC2 & 0x1b80U), config.tgSize,
1951                            config.localSize, config.exceptions);
1952           
1953            // calculating kernel argument segment size
1954            size_t argSegmentSize = 0;
1955            for (GalliumArgInfo& argInfo: output.kernels[ki].argInfos)
1956            {
1957                if (argInfo.semantic == GalliumArgSemantic::GRID_DIMENSION ||
1958                        argInfo.semantic == GalliumArgSemantic::GRID_OFFSET)
1959                    continue; // skip
1960                if (argInfo.targetAlign != 0)
1961                    argSegmentSize = (argSegmentSize + argInfo.targetAlign-1) &
1962                            ~size_t(argInfo.targetAlign-1);
1963                argSegmentSize += argInfo.targetSize;
1964            }
1965            argSegmentSize += 16; // gridOffset and gridDim
1966           
1967            if (outConfig.amdCodeVersionMajor == BINGEN_DEFAULT)
1968                outConfig.amdCodeVersionMajor = 1;
1969            if (outConfig.amdCodeVersionMinor == BINGEN_DEFAULT)
1970                outConfig.amdCodeVersionMinor = 0;
1971            if (outConfig.amdMachineKind == BINGEN16_DEFAULT)
1972                outConfig.amdMachineKind = 1;
1973            if (outConfig.amdMachineMajor == BINGEN16_DEFAULT)
1974                outConfig.amdMachineMajor = amdGpuArchValues.major;
1975            if (outConfig.amdMachineMinor == BINGEN16_DEFAULT)
1976                outConfig.amdMachineMinor = amdGpuArchValues.minor;
1977            if (outConfig.amdMachineStepping == BINGEN16_DEFAULT)
1978                outConfig.amdMachineStepping = amdGpuArchValues.stepping;
1979            if (outConfig.kernelCodeEntryOffset == BINGEN64_DEFAULT)
1980                outConfig.kernelCodeEntryOffset = 256;
1981            if (outConfig.kernelCodePrefetchOffset == BINGEN64_DEFAULT)
1982                outConfig.kernelCodePrefetchOffset = 0;
1983            if (outConfig.kernelCodePrefetchSize == BINGEN64_DEFAULT)
1984                outConfig.kernelCodePrefetchSize = 0;
1985            if (outConfig.maxScrachBackingMemorySize == BINGEN64_DEFAULT) // ??
1986                outConfig.maxScrachBackingMemorySize = 0;
1987            outConfig.computePgmRsrc1 = pgmRSRC1;
1988            outConfig.computePgmRsrc2 = pgmRSRC2;
1989            if (outConfig.workitemPrivateSegmentSize == BINGEN_DEFAULT) // scratch buffer
1990                outConfig.workitemPrivateSegmentSize = config.scratchBufferSize;
1991            if (outConfig.workgroupGroupSegmentSize == BINGEN_DEFAULT)
1992                outConfig.workgroupGroupSegmentSize = config.localSize;
1993            if (outConfig.gdsSegmentSize == BINGEN_DEFAULT)
1994                outConfig.gdsSegmentSize = 0;
1995            if (outConfig.kernargSegmentSize == BINGEN64_DEFAULT)
1996                outConfig.kernargSegmentSize = argSegmentSize;
1997            if (outConfig.workgroupFbarrierCount == BINGEN_DEFAULT)
1998                outConfig.workgroupFbarrierCount = 0;
1999            if (outConfig.wavefrontSgprCount == BINGEN16_DEFAULT)
2000                outConfig.wavefrontSgprCount = config.usedSGPRsNum;
2001            if (outConfig.workitemVgprCount == BINGEN16_DEFAULT)
2002                outConfig.workitemVgprCount = config.usedVGPRsNum;
2003            if (outConfig.reservedVgprFirst == BINGEN16_DEFAULT)
2004                outConfig.reservedVgprFirst = 0;
2005            if (outConfig.reservedVgprCount == BINGEN16_DEFAULT)
2006                outConfig.reservedVgprCount = 0;
2007            if (outConfig.reservedSgprFirst == BINGEN16_DEFAULT)
2008                outConfig.reservedSgprFirst = 0;
2009            if (outConfig.reservedSgprCount == BINGEN16_DEFAULT)
2010                outConfig.reservedSgprCount = 0;
2011            if (outConfig.debugWavefrontPrivateSegmentOffsetSgpr == BINGEN16_DEFAULT)
2012                outConfig.debugWavefrontPrivateSegmentOffsetSgpr = 0;
2013            if (outConfig.debugPrivateSegmentBufferSgpr == BINGEN16_DEFAULT)
2014                outConfig.debugPrivateSegmentBufferSgpr = 0;
2015            if (outConfig.kernargSegmentAlignment == BINGEN8_DEFAULT)
2016                outConfig.kernargSegmentAlignment = 4;
2017            if (outConfig.groupSegmentAlignment == BINGEN8_DEFAULT)
2018                outConfig.groupSegmentAlignment = 4;
2019            if (outConfig.privateSegmentAlignment == BINGEN8_DEFAULT)
2020                outConfig.privateSegmentAlignment = 4;
2021            if (outConfig.wavefrontSize == BINGEN8_DEFAULT)
2022                outConfig.wavefrontSize = 6;
2023            if (outConfig.callConvention == BINGEN_DEFAULT)
2024                outConfig.callConvention = 0;
2025            outConfig.reserved1[0] = 0;
2026            outConfig.reserved1[1] = 0;
2027            outConfig.reserved1[2] = 0;
2028            if (outConfig.runtimeLoaderKernelSymbol == BINGEN64_DEFAULT)
2029                outConfig.runtimeLoaderKernelSymbol = 0;
2030           
2031            // to little endian
2032            outConfig.toLE(); // to little-endian
2033            // put control directive section to config
2034            if (kernel.ctrlDirSection!=ASMSECT_NONE &&
2035                assembler.sections[kernel.ctrlDirSection].content.size()==128)
2036                ::memcpy(outConfig.controlDirective, 
2037                    assembler.sections[kernel.ctrlDirSection].content.data(), 128);
2038            else
2039                ::memset(outConfig.controlDirective, 0, 128);
2040           
2041            if (asmCSection.content.size() >= symbol.value+256)
2042                // and store it to asm section in kernel place
2043                ::memcpy(asmCSection.content.data() + symbol.value,
2044                        &outConfig, sizeof(AmdHsaKernelConfig));
2045            else // if wrong size
2046                assembler.printError(AsmSourcePos(), (
2047                    std::string("HSA configuration for kernel '")+
2048                    kinput.kernelName.c_str()+"' out of content").c_str());
2049        }
2050    }
2051    // set versions
2052    if (assembler.driverVersion == 0 && (assembler.flags&ASM_TESTRUN)==0) // auto detection
2053        output.isMesa170 = detectedDriverVersion >= 170000U;
2054    else
2055        output.isMesa170 = assembler.driverVersion >= 170000U;
2056    output.isLLVM390 = llvmVersion >= 30900U;
2057    return good;
2058}
2059
2060void AsmGalliumHandler::writeBinary(std::ostream& os) const
2061{
2062    GalliumBinGenerator binGenerator(&output);
2063    binGenerator.generate(os);
2064}
2065
2066void AsmGalliumHandler::writeBinary(Array<cxbyte>& array) const
2067{
2068    GalliumBinGenerator binGenerator(&output);
2069    binGenerator.generate(array);
2070}
Note: See TracBrowser for help on using the repository browser.