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

Last change on this file since 3348 was 3348, checked in by matszpk, 10 months ago

CLRadeonExtender: Move routines to calculate PGMRSRC1 and PGMRSRC2 to GPUId code. Apply these function in code.

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