source: CLRX/CLRadeonExtender/trunk/amdbin/AmdCL2BinGen.cpp @ 3348

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

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

File size: 97.9 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstring>
22#include <cstdint>
23#include <cassert>
24#include <bitset>
25#include <fstream>
26#include <algorithm>
27#include <string>
28#include <vector>
29#include <memory>
30#include <CLRX/utils/Containers.h>
31#include <CLRX/utils/InputOutput.h>
32#include <CLRX/amdbin/AmdCL2Binaries.h>
33#include <CLRX/amdbin/AmdCL2BinGen.h>
34
35using namespace CLRX;
36
37static const cxuint innerBinSectonTableLen = AMDCL2SECTID_MAX+1-ELFSECTID_START;
38
39void AmdCL2Input::addEmptyKernel(const char* kernelName)
40{
41    AmdCL2KernelInput kernel{};
42    kernel.kernelName = kernelName;
43   
44    kernel.config.usedSGPRsNum = kernel.config.usedVGPRsNum = BINGEN_DEFAULT;
45    kernel.config.floatMode = 0xc0;
46    kernel.config.dimMask = BINGEN_DEFAULT;
47    kernels.push_back(std::move(kernel));
48}
49
50AmdCL2GPUBinGenerator::AmdCL2GPUBinGenerator() : manageable(false), input(nullptr)
51{ }
52
53AmdCL2GPUBinGenerator::AmdCL2GPUBinGenerator(const AmdCL2Input* amdInput)
54        : manageable(false), input(amdInput)
55{ }
56
57AmdCL2GPUBinGenerator::AmdCL2GPUBinGenerator(bool _64bitMode,
58       GPUDeviceType deviceType, uint32_t archMinor, uint32_t archStepping,
59       uint32_t driverVersion, size_t globalDataSize, const cxbyte* globalData,
60       size_t rwDataSize, const cxbyte* rwData, 
61       const std::vector<AmdCL2KernelInput>& kernelInputs)
62        : manageable(true), input(nullptr)
63{
64    input = new AmdCL2Input{_64bitMode, deviceType, archMinor, archStepping,
65                globalDataSize, globalData, rwDataSize, rwData, 0, 0, 0,
66                nullptr, false, { }, { }, driverVersion, "", "", kernelInputs };
67}
68
69AmdCL2GPUBinGenerator::AmdCL2GPUBinGenerator(bool _64bitMode,
70       GPUDeviceType deviceType, uint32_t archMinor, uint32_t archStepping,
71       uint32_t driverVersion, size_t globalDataSize, const cxbyte* globalData,
72       size_t rwDataSize, const cxbyte* rwData,
73       std::vector<AmdCL2KernelInput>&& kernelInputs)
74        : manageable(true), input(nullptr)
75{
76    input = new AmdCL2Input{_64bitMode, deviceType, archMinor, archStepping,
77                globalDataSize, globalData, rwDataSize, rwData, 0, 0, 0,
78                nullptr, false, { }, { }, driverVersion, "", "",
79                std::move(kernelInputs) };
80}
81
82AmdCL2GPUBinGenerator::~AmdCL2GPUBinGenerator()
83{
84    if (manageable)
85        delete input;
86}
87
88void AmdCL2GPUBinGenerator::setInput(const AmdCL2Input* input)
89{
90    if (manageable)
91        delete input;
92    manageable = false;
93    this->input = input;
94}
95
96struct CLRX_INTERNAL TempAmdCL2KernelData
97{
98    size_t metadataSize;
99    size_t isaMetadataSize;
100    size_t stubSize;
101    size_t setupSize;
102    size_t codeSize;
103    bool useLocals;
104    uint32_t pipesUsed;
105    Array<uint16_t> argResIds;
106};
107
108struct CLRX_INTERNAL ArgTypeSizes
109{
110    cxbyte type;
111    cxbyte elemSize;
112    cxbyte vectorSize;
113};
114
115static const ArgTypeSizes argTypeSizesTable[] =
116{
117    { 6, 1, 1 /*void */ },
118    { 6, 1, 1 /*uchar*/ }, { 6, 1, 1, /*char*/ },
119    { 7, 2, 1, /*ushort*/ }, { 7, 2, 1, /*short*/ },
120    { 8, 4, 1, /*uint*/ }, { 8, 4, 1, /*int*/ },
121    { 9, 8, 1, /*ulong*/ }, { 9, 8, 1, /*long*/ },
122    { 11, 4, 1, /*float*/ }, { 12, 8, 1, /*double*/ },
123    { 7, 8, 1, /*pointer*/ },
124    { 0, 32, 1, /*image*/ }, { 0, 32, 1, /*image1d*/ }, { 0, 32, 1, /*image1da */ },
125    { 0, 32, 1, /*image1db*/ }, { 0, 32, 1, /*image2d*/ }, { 0, 32, 1, /*image2da*/ },
126    { 0, 32, 1, /*image3d*/ },
127    { 6, 1, 2, /*uchar2*/ }, { 6, 1, 3, /*uchar3*/ }, { 6, 1, 4, /*uchar4*/ },
128    { 6, 1, 8, /*uchar8*/ }, { 6, 1, 16, /*uchar16*/ },
129    { 6, 1, 2, /*char2*/ }, { 6, 1, 3, /*char3*/ }, { 6, 1, 4, /*char4*/ },
130    { 6, 1, 8, /*char8*/ }, { 6, 1, 16, /*char16*/ },
131    { 7, 2, 2, /*ushort2*/ }, { 7, 2, 3, /*ushort3*/ }, { 7, 2, 4, /*ushort4*/ },
132    { 7, 2, 8, /*ushort8*/ }, { 7, 2, 16, /*ushort16*/ },
133    { 7, 2, 2, /*short2*/ }, { 7, 2, 3, /*short3*/ }, { 7, 2, 4, /*short4*/ },
134    { 7, 2, 8, /*short8*/ }, { 7, 2, 16, /*short16*/ },
135    { 8, 4, 2, /*uint2*/ }, { 8, 4, 3, /*uint3*/ }, { 8, 4, 4, /*uint4*/ },
136    { 8, 4, 8, /*uint8*/ }, { 8, 4, 16, /*uint16*/ },
137    { 8, 4, 2, /*int2*/ }, { 8, 4, 3, /*int3*/ }, { 8, 4, 4, /*int4*/ },
138    { 8, 4, 8, /*int8*/ }, { 8, 4, 16, /*int16*/ },
139    { 9, 8, 2, /*ulong2*/ }, { 9, 8, 3, /*ulong3*/ }, { 9, 8, 4, /*ulong4*/ },
140    { 9, 8, 8, /*ulong8*/ }, { 9, 8, 16, /*ulong16*/ },
141    { 9, 8, 2, /*long2*/ }, { 9, 8, 3, /*long3*/ }, { 9, 8, 4, /*long4*/ },
142    { 9, 8, 8, /*long8*/ }, { 9, 8, 16, /*long16*/ },
143    { 11, 4, 2, /*float2*/ }, { 11, 4, 3, /*float3*/ }, { 11, 4, 4, /*float4*/ },
144    { 11, 4, 8, /*float8*/ }, { 11, 4, 16, /*float16*/ },
145    { 12, 8, 2, /*double2*/ }, { 12, 8, 3, /*double3*/ }, { 12, 8, 4, /*double4*/ },
146    { 12, 8, 8, /*double8*/ }, { 12, 8, 16, /*double16*/ },
147    { 0, 16, 1, /* sampler*/ }, { 15, 0, 0, /*structure*/ }, { 0, 0, 0, /*counter*/ },
148    { 0, 0, 0, /*counter64*/ }, { 7, 16, 1, /* pipe*/ }, { 18, 16, 1, /*cmdqueue*/ },
149    { 7, 8, 1, /*clkevent*/ }
150};
151
152static const uint32_t gpuDeviceCodeTable[24] =
153{
154    UINT_MAX, // GPUDeviceType::CAPE_VERDE
155    UINT_MAX, // GPUDeviceType::PITCAIRN
156    UINT_MAX, // GPUDeviceType::TAHITI
157    UINT_MAX, // GPUDeviceType::OLAND
158    6, // GPUDeviceType::BONAIRE
159    1, // GPUDeviceType::SPECTRE
160    2, // GPUDeviceType::SPOOKY
161    3, // GPUDeviceType::KALINDI
162    UINT_MAX, // GPUDeviceType::HAINAN
163    7, // GPUDeviceType::HAWAII
164    8, // GPUDeviceType::ICELAND
165    9, // GPUDeviceType::TONGA
166    4, // GPUDeviceType::MULLINS
167    17, // GPUDeviceType::FIJI
168    16, // GPUDeviceType::CARRIZO
169    15, // GPUDeviceType::DUMMY
170    UINT_MAX, // GPUDeviceType::GOOSE
171    UINT_MAX, // GPUDeviceType::HORSE
172    UINT_MAX, // GPUDeviceType::STONEY
173    UINT_MAX, // GPUDeviceType::ELLESMERE
174    UINT_MAX, // GPUDeviceType::BAFFIN
175    UINT_MAX, // GPUDeviceType::GFX804
176    UINT_MAX, // GPUDeviceType::GFX900
177    UINT_MAX  // GPUDeviceType::GFX901
178};
179
180static const uint32_t gpuDeviceCodeTable15_7[24] =
181{
182    UINT_MAX, // GPUDeviceType::CAPE_VERDE
183    UINT_MAX, // GPUDeviceType::PITCAIRN
184    UINT_MAX, // GPUDeviceType::TAHITI
185    UINT_MAX, // GPUDeviceType::OLAND
186    6, // GPUDeviceType::BONAIRE
187    1, // GPUDeviceType::SPECTRE
188    2, // GPUDeviceType::SPOOKY
189    3, // GPUDeviceType::KALINDI
190    UINT_MAX, // GPUDeviceType::HAINAN
191    7, // GPUDeviceType::HAWAII
192    8, // GPUDeviceType::ICELAND
193    9, // GPUDeviceType::TONGA
194    4, // GPUDeviceType::MULLINS
195    16, // GPUDeviceType::FIJI
196    15, // GPUDeviceType::CARRIZO
197    UINT_MAX, // GPUDeviceType::DUMMY
198    UINT_MAX, // GPUDeviceType::GOOSE
199    UINT_MAX, // GPUDeviceType::HORSE
200    UINT_MAX, // GPUDeviceType::STONEY
201    UINT_MAX, // GPUDeviceType::ELLESMERE
202    UINT_MAX, // GPUDeviceType::BAFFIN
203    UINT_MAX, // GPUDeviceType::GFX804
204    UINT_MAX, // GPUDeviceType::GFX900
205    UINT_MAX  // GPUDeviceType::GFX901
206};
207
208static const uint32_t gpuDeviceCodeTable16_3[24] =
209{
210    UINT_MAX, // GPUDeviceType::CAPE_VERDE
211    UINT_MAX, // GPUDeviceType::PITCAIRN
212    UINT_MAX, // GPUDeviceType::TAHITI
213    UINT_MAX, // GPUDeviceType::OLAND
214    6, // GPUDeviceType::BONAIRE
215    1, // GPUDeviceType::SPECTRE
216    2, // GPUDeviceType::SPOOKY
217    3, // GPUDeviceType::KALINDI
218    UINT_MAX, // GPUDeviceType::HAINAN
219    7, // GPUDeviceType::HAWAII
220    8, // GPUDeviceType::ICELAND
221    9, // GPUDeviceType::TONGA
222    4, // GPUDeviceType::MULLINS
223    16, // GPUDeviceType::FIJI
224    15, // GPUDeviceType::CARRIZO
225    17, // GPUDeviceType::DUMMY
226    13, // GPUDeviceType::GOOSE
227    12, // GPUDeviceType::HORSE
228    17, // GPUDeviceType::STONEY
229    12, // GPUDeviceType::ELLESMERE
230    13,  // GPUDeviceType::BAFFIN
231    UINT_MAX, // GPUDeviceType::GFX804
232    UINT_MAX, // GPUDeviceType::GFX900
233    UINT_MAX  // GPUDeviceType::GFX901
234};
235
236static const uint32_t gpuDeviceCodeTableGPUPRO[24] =
237{
238    UINT_MAX, // GPUDeviceType::CAPE_VERDE
239    UINT_MAX, // GPUDeviceType::PITCAIRN
240    UINT_MAX, // GPUDeviceType::TAHITI
241    UINT_MAX, // GPUDeviceType::OLAND
242    6, // GPUDeviceType::BONAIRE
243    1, // GPUDeviceType::SPECTRE
244    2, // GPUDeviceType::SPOOKY
245    3, // GPUDeviceType::KALINDI
246    UINT_MAX, // GPUDeviceType::HAINAN
247    7, // GPUDeviceType::HAWAII
248    8, // GPUDeviceType::ICELAND
249    9, // GPUDeviceType::TONGA
250    4, // GPUDeviceType::MULLINS
251    14, // GPUDeviceType::FIJI
252    13, // GPUDeviceType::CARRIZO
253    15, // GPUDeviceType::DUMMY
254    16, // GPUDeviceType::GOOSE
255    17, // GPUDeviceType::HORSE
256    15, // GPUDeviceType::STONEY
257    17, // GPUDeviceType::ELLESMERE
258    16,// GPUDeviceType::BAFFIN
259    UINT_MAX, // GPUDeviceType::GFX804
260    UINT_MAX, // GPUDeviceType::GFX900
261    UINT_MAX  // GPUDeviceType::GFX901
262};
263
264static const uint32_t gpuDeviceCodeTable2236[24] =
265{
266    UINT_MAX, // GPUDeviceType::CAPE_VERDE
267    UINT_MAX, // GPUDeviceType::PITCAIRN
268    UINT_MAX, // GPUDeviceType::TAHITI
269    UINT_MAX, // GPUDeviceType::OLAND
270    6, // GPUDeviceType::BONAIRE
271    1, // GPUDeviceType::SPECTRE
272    2, // GPUDeviceType::SPOOKY
273    3, // GPUDeviceType::KALINDI
274    UINT_MAX, // GPUDeviceType::HAINAN
275    7, // GPUDeviceType::HAWAII
276    8, // GPUDeviceType::ICELAND
277    9, // GPUDeviceType::TONGA
278    4, // GPUDeviceType::MULLINS
279    13, // GPUDeviceType::FIJI
280    12, // GPUDeviceType::CARRIZO
281    14, // GPUDeviceType::DUMMY
282    15, // GPUDeviceType::GOOSE
283    16, // GPUDeviceType::HORSE
284    14, // GPUDeviceType::STONEY
285    16, // GPUDeviceType::ELLESMERE
286    15, // GPUDeviceType::BAFFIN
287    18, // GPUDeviceType::GFX804
288    17, // GPUDeviceType::GFX900
289    UINT_MAX  // GPUDeviceType::GFX901
290};
291
292static const uint32_t gpuDeviceCodeTable2264[24] =
293{
294    UINT_MAX, // GPUDeviceType::CAPE_VERDE
295    UINT_MAX, // GPUDeviceType::PITCAIRN
296    UINT_MAX, // GPUDeviceType::TAHITI
297    UINT_MAX, // GPUDeviceType::OLAND
298    6, // GPUDeviceType::BONAIRE
299    1, // GPUDeviceType::SPECTRE
300    2, // GPUDeviceType::SPOOKY
301    3, // GPUDeviceType::KALINDI
302    UINT_MAX, // GPUDeviceType::HAINAN
303    7, // GPUDeviceType::HAWAII
304    8, // GPUDeviceType::ICELAND
305    9, // GPUDeviceType::TONGA
306    4, // GPUDeviceType::MULLINS
307    14, // GPUDeviceType::FIJI
308    13, // GPUDeviceType::CARRIZO
309    15, // GPUDeviceType::DUMMY
310    16, // GPUDeviceType::GOOSE
311    17, // GPUDeviceType::HORSE
312    15, // GPUDeviceType::STONEY
313    17, // GPUDeviceType::ELLESMERE
314    16, // GPUDeviceType::BAFFIN
315    18, // GPUDeviceType::GFX804
316    19, // GPUDeviceType::GFX900
317    20  // GPUDeviceType::GFX901
318};
319
320static const uint32_t gpuDeviceCodeTable2348[24] =
321{
322    UINT_MAX, // GPUDeviceType::CAPE_VERDE
323    UINT_MAX, // GPUDeviceType::PITCAIRN
324    UINT_MAX, // GPUDeviceType::TAHITI
325    UINT_MAX, // GPUDeviceType::OLAND
326    6, // GPUDeviceType::BONAIRE
327    1, // GPUDeviceType::SPECTRE
328    2, // GPUDeviceType::SPOOKY
329    3, // GPUDeviceType::KALINDI
330    UINT_MAX, // GPUDeviceType::HAINAN
331    7, // GPUDeviceType::HAWAII
332    8, // GPUDeviceType::ICELAND
333    9, // GPUDeviceType::TONGA
334    4, // GPUDeviceType::MULLINS
335    15, // GPUDeviceType::FIJI
336    14, // GPUDeviceType::CARRIZO
337    16, // GPUDeviceType::DUMMY
338    17, // GPUDeviceType::GOOSE
339    18, // GPUDeviceType::HORSE
340    16, // GPUDeviceType::STONEY
341    18, // GPUDeviceType::ELLESMERE
342    17, // GPUDeviceType::BAFFIN
343    19, // GPUDeviceType::GFX804
344    20, // GPUDeviceType::GFX900
345    21  // GPUDeviceType::GFX901
346};
347
348struct CLRX_INTERNAL CL2GPUGenCodeTable
349{
350    cxuint toDriverVersion;   // to driver version
351    const uint32_t* table;
352};
353
354static const CL2GPUGenCodeTable cl2GenCodeTables[] =
355{
356    { 191205U, gpuDeviceCodeTable15_7 },
357    { 200406U, gpuDeviceCodeTable },
358    { 203603U, gpuDeviceCodeTable16_3 },
359    { 223600U, gpuDeviceCodeTableGPUPRO },
360    { 226400U, gpuDeviceCodeTable2236 },
361    { 234800U, gpuDeviceCodeTable2264 },
362    { UINT_MAX, gpuDeviceCodeTable2348 }
363};
364
365static const uint16_t mainBuiltinSectionTable[] =
366{
367    1, // ELFSECTID_SHSTRTAB
368    2, // ELFSECTID_STRTAB
369    3, // ELFSECTID_SYMTAB
370    SHN_UNDEF, // ELFSECTID_DYNSTR
371    SHN_UNDEF, // ELFSECTID_DYNSYM
372    6, // ELFSECTID_TEXT
373    5, // ELFSECTID_RODATA
374    SHN_UNDEF, // ELFSECTID_DATA
375    SHN_UNDEF, // ELFSECTID_BSS
376    4 // ELFSECTID_COMMENT
377};
378
379static const uint16_t mainBuiltinSectionTable2[] =
380{
381    1, // ELFSECTID_SHSTRTAB
382    2, // ELFSECTID_STRTAB
383    3, // ELFSECTID_SYMTAB
384    SHN_UNDEF, // ELFSECTID_DYNSTR
385    SHN_UNDEF, // ELFSECTID_DYNSYM
386    SHN_UNDEF, // ELFSECTID_TEXT
387    5, // ELFSECTID_RODATA
388    SHN_UNDEF, // ELFSECTID_DATA
389    SHN_UNDEF, // ELFSECTID_BSS
390    4 // ELFSECTID_COMMENT
391};
392
393static const cxbyte kernelIsaMetadata[] =
394{
395    0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
396    0x00, 0x00, 0x00, 0x08, 0x42, 0x09, 0x00, 0x00,
397    0x00, 0x00, 0x00, 0x00
398};
399
400static const char* amdcl2GPUArchNameWordTable[] =
401{
402    "GFX6", "GFX7", "GFX8", "GFX9"
403};
404
405static void prepareKernelTempData(const AmdCL2Input* input,
406          Array<TempAmdCL2KernelData>& tempDatas)
407{
408    const bool newBinaries = input->driverVersion >= 191205;
409    const bool is16_3Ver = input->driverVersion >= 200406;
410    const size_t kernelsNum = input->kernels.size();
411    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
412   
413    const size_t samplersNum = (input->samplerConfig) ?
414                input->samplers.size() : (input->samplerInitSize>>3);
415   
416    for (size_t i = 0; i < kernelsNum; i++)
417    {
418        const AmdCL2KernelInput& kernel = input->kernels[i];
419        TempAmdCL2KernelData& tempData = tempDatas[i];
420        if (newBinaries && (kernel.isaMetadataSize!=0 || kernel.isaMetadata!=nullptr))
421            throw Exception("ISA metadata allowed for old driver binaries");
422        if (newBinaries && (kernel.stubSize!=0 || kernel.stub!=nullptr))
423            throw Exception("Kernel stub allowed for old driver binaries");
424        /* check relocations */
425        if (newBinaries)
426            for (const AmdCL2RelInput& rel: kernel.relocations)
427            {
428                if (rel.type > RELTYPE_HIGH_32BIT || rel.symbol > 2)
429                    throw Exception("Wrong relocation symbol or type");
430                if (rel.offset+4 > kernel.codeSize)
431                    throw Exception("Relocation offset outside code size");
432            }
433       
434        if (!kernel.useConfig)
435        {   // if no kernel configuration
436            tempData.metadataSize = kernel.metadataSize;
437            tempData.isaMetadataSize = (kernel.isaMetadata!=nullptr) ?
438                        kernel.isaMetadataSize : sizeof(kernelIsaMetadata);
439            tempData.setupSize = kernel.setupSize;
440            tempData.stubSize = kernel.stubSize;
441        }
442        else
443        {   // if kernel configuration present
444            const cxuint argsNum = kernel.config.args.size();
445            size_t out;
446            if (input->is64Bit)
447            {
448                out = ((newBinaries) ? ((is16_3Ver) ? 303 : 254) : 246) +
449                            (argsNum + 1)*sizeof(AmdCL2GPUKernelArgEntry64);
450                for (const AmdKernelArgInput& arg: kernel.config.args)
451                    out += arg.argName.size() + arg.typeName.size() + 2;
452                out += 48;
453            }
454            else
455            {
456                out = ((newBinaries) ? ((is16_3Ver) ? 195 : 174) : 166) +
457                            (argsNum + 1)*sizeof(AmdCL2GPUKernelArgEntry32);
458                for (const AmdKernelArgInput& arg: kernel.config.args)
459                    out += arg.argName.size() + arg.typeName.size() + 2;
460                out += 24;
461            }
462            // fix for new word (GFX?)
463            if (input->driverVersion >= 223600U)
464                out += ::strlen(amdcl2GPUArchNameWordTable[cxuint(arch)]) - 7;
465           
466            /// if kernels uses locals
467            tempData.pipesUsed = 0;
468            tempData.useLocals = (kernel.config.localSize != 0);
469            if (!tempData.useLocals)
470                for (const AmdKernelArgInput& inarg: kernel.config.args)
471                    if (inarg.argType == KernelArgType::POINTER &&
472                                inarg.ptrSpace == KernelPtrSpace::LOCAL)
473                    {
474                        tempData.useLocals = true;
475                        break;
476                    }
477            for (const AmdKernelArgInput& inarg: kernel.config.args)
478                if (inarg.argType == KernelArgType::PIPE && inarg.used)
479                    tempData.pipesUsed++;
480           
481            std::bitset<128> imgRoMask;
482            std::bitset<64> imgWoMask;
483            std::bitset<64> imgRWMask;
484            std::bitset<16> samplerMask;
485            tempData.argResIds.resize(argsNum);
486            // collect set bit to masks
487            for (cxuint k = 0; k < argsNum; k++)
488            {
489                const AmdKernelArgInput& inarg = kernel.config.args[k];
490                if (inarg.resId != BINGEN_DEFAULT)
491                {
492                    if (inarg.argType == KernelArgType::SAMPLER)
493                    {
494                        if (inarg.resId >= 16)
495                            throw Exception("SamplerId out of range!");
496                        if (samplerMask[inarg.resId])
497                            throw Exception("SamplerId already used!");
498                        samplerMask.set(inarg.resId);
499                        tempData.argResIds[k] = inarg.resId;
500                    }
501                    else if (isKernelArgImage(inarg.argType))
502                    {
503                        uint32_t imgAccess = inarg.ptrAccess & KARG_PTR_ACCESS_MASK;
504                        if (imgAccess == KARG_PTR_READ_ONLY)
505                        {
506                            if (inarg.resId >= 128)
507                                throw Exception("RdOnlyImgId out of range!");
508                            if (imgRoMask[inarg.resId])
509                                throw Exception("RdOnlyImgId already used!");
510                            imgRoMask.set(inarg.resId);
511                            tempData.argResIds[k] = inarg.resId;
512                        }
513                        else if (imgAccess == KARG_PTR_WRITE_ONLY)
514                        {
515                            if (inarg.resId >= 64)
516                                throw Exception("WrOnlyImgId out of range!");
517                            if (imgWoMask[inarg.resId])
518                                throw Exception("WrOnlyImgId already used!");
519                            imgWoMask.set(inarg.resId);
520                            tempData.argResIds[k] = inarg.resId;
521                        }
522                        else // read-write images
523                        {
524                            if (inarg.resId >= 64)
525                                throw Exception("RdWrImgId out of range!");
526                            if (imgRWMask[inarg.resId])
527                                throw Exception("RdWrImgId already used!");
528                            imgRWMask.set(inarg.resId);
529                            tempData.argResIds[k] = inarg.resId;
530                        }
531                    }
532                }
533            }
534           
535            cxuint imgRoCount = 0;
536            cxuint imgWoCount = 0;
537            cxuint imgRWCount = 0;
538            cxuint samplerCount = 0;
539            // now, we can set resId for argument that have no resid
540            for (cxuint k = 0; k < argsNum; k++)
541            {
542                const AmdKernelArgInput& inarg = kernel.config.args[k];
543                if (inarg.resId == BINGEN_DEFAULT)
544                {
545                    if (inarg.argType == KernelArgType::SAMPLER)
546                    {
547                        for (; samplerCount < 16 && samplerMask[samplerCount];
548                             samplerCount++);
549                        if (samplerCount == 16)
550                            throw Exception("SamplerId out of range!");
551                        tempData.argResIds[k] = samplerCount++;
552                    }
553                    else if (isKernelArgImage(inarg.argType))
554                    {
555                        uint32_t imgAccess = inarg.ptrAccess & KARG_PTR_ACCESS_MASK;
556                        if (imgAccess == KARG_PTR_READ_ONLY)
557                        {
558                            for (; imgRoCount < 128 && imgRoMask[imgRoCount]; imgRoCount++);
559                            if (imgRoCount == 128)
560                                throw Exception("RdOnlyImgId out of range!");
561                            tempData.argResIds[k] = imgRoCount++;
562                        }
563                        else if (imgAccess == KARG_PTR_WRITE_ONLY)
564                        {
565                            for (; imgWoCount < 64 && imgWoMask[imgWoCount]; imgWoCount++);
566                            if (imgWoCount == 64)
567                                throw Exception("WrOnlyImgId out of range!");
568                            tempData.argResIds[k] = imgWoCount++;
569                        }
570                        else // read-write images
571                        {
572                            for (; imgRWCount < 64 && imgRWMask[imgRWCount]; imgRWCount++);
573                            if (imgRWCount == 128)
574                                throw Exception("RdWrImgId out of range!");
575                            tempData.argResIds[k] = imgRWCount++;
576                        }
577                    }
578                }
579            }
580           
581            // check sampler list
582            for (cxuint sampler: kernel.config.samplers)
583                if (sampler >= samplersNum)
584                    throw Exception("SamplerId out of range");
585           
586            tempData.metadataSize = out;
587            tempData.setupSize = 256;
588            tempData.stubSize = tempData.isaMetadataSize = 0;
589            if (!newBinaries)
590            {
591                tempData.stubSize = 0xa60;
592                tempData.isaMetadataSize = sizeof(kernelIsaMetadata);
593            }
594        }
595        tempData.codeSize = kernel.codeSize;
596    }
597}
598
599// fast and memory efficient String table generator for main binary
600class CLRX_INTERNAL CL2MainStrTabGen: public ElfRegionContent
601{
602private:
603    const AmdCL2Input* input;
604    bool withBrig;
605public:
606    explicit CL2MainStrTabGen(const AmdCL2Input* _input) : input(_input), withBrig(false)
607    {
608        for (const BinSection& section: input->extraSections)
609            if (section.name==".brig")
610            {
611                withBrig = true;
612                break;
613            }
614    }
615   
616    size_t size() const
617    {
618        const bool newBinaries = input->driverVersion >= 191205;
619        size_t size = 1;
620        if (!input->compileOptions.empty())
621            size += 26;
622        if (withBrig)
623            size += 9; // __BRIG__
624        //size +=
625        if (newBinaries)
626            for (const AmdCL2KernelInput& kernel: input->kernels)
627                size += kernel.kernelName.size() + 19 + 17;
628        else // old binaries
629            for (const AmdCL2KernelInput& kernel: input->kernels)
630                size += kernel.kernelName.size()*3 + 19 + 17 + 16*2 + 17 + 15;
631        size += 19; // acl version string
632        /// extra symbols
633        for (const BinSymbol& symbol: input->extraSymbols)
634            size += symbol.name.size()+1;
635        return size;
636    }
637   
638    void operator()(FastOutputBuffer& fob) const
639    {
640        const bool newBinaries = input->driverVersion >= 191205;
641        fob.put(0);
642        if (!input->compileOptions.empty())
643            fob.write(26, "__OpenCL_compiler_options");
644       
645        for (const AmdCL2KernelInput& kernel: input->kernels)
646        {   // put kernel metadata symbol names
647            fob.write(19, "__OpenCL_&__OpenCL_");
648            fob.write(kernel.kernelName.size(), kernel.kernelName.c_str());
649            fob.write(17, "_kernel_metadata");
650        }
651        if (withBrig)
652            fob.write(9, "__BRIG__");
653        if (!newBinaries)
654            for (const AmdCL2KernelInput& kernel: input->kernels)
655            {   // put kernel ISA/binary symbol names
656                fob.write(16, "__ISA_&__OpenCL_");
657                fob.write(kernel.kernelName.size(), kernel.kernelName.c_str());
658                fob.write(31, "_kernel_binary\000__ISA_&__OpenCL_");
659                fob.write(kernel.kernelName.size(), kernel.kernelName.c_str());
660                fob.write(17, "_kernel_metadata");
661            }
662        fob.write(19, "acl_version_string");
663        /// extra symbols
664        for (const BinSymbol& symbol: input->extraSymbols)
665            fob.write(symbol.name.size()+1, symbol.name.c_str());
666    }
667};
668
669// fast and memory efficient symbol table generator for main binary
670template<typename Types>
671class CLRX_INTERNAL CL2MainSymTabGen: public ElfRegionContent
672{
673private:
674    const AmdCL2Input* input;
675    bool withBrig;
676    uint16_t brigIndex;
677    const Array<TempAmdCL2KernelData>& tempDatas;
678    const CString& aclVersion;
679    const uint16_t* mainSectTable;
680    cxuint extraSectionIndex;
681public:
682    CL2MainSymTabGen(const AmdCL2Input* _input,
683             const Array<TempAmdCL2KernelData>& _tempDatas,
684             const CString& _aclVersion, const uint16_t* _mainSectTable,
685             cxuint _extraSectionIndex)
686             : input(_input), withBrig(false), tempDatas(_tempDatas),
687               aclVersion(_aclVersion), mainSectTable(_mainSectTable),
688               extraSectionIndex(_extraSectionIndex)
689    {
690        for (brigIndex = 0; brigIndex < input->extraSections.size(); brigIndex++)
691        {
692            const BinSection& section = input->extraSections[brigIndex];
693            if (section.name==".brig")
694            {
695                withBrig = true;
696                break;
697            }
698        }
699    }
700   
701    size_t size() const
702    {
703        const bool newBinaries = input->driverVersion >= 191205;
704        return sizeof(typename Types::Sym)*(1 + (!input->compileOptions.empty()) +
705            input->kernels.size()*(newBinaries ? 1 : 3) +
706            (withBrig) + 1 /* acl_version */ + input->extraSymbols.size());
707    }
708   
709    void operator()(FastOutputBuffer& fob) const
710    {
711        const bool newBinaries = input->driverVersion >= 191205;
712        fob.fill(sizeof(typename Types::Sym), 0);
713        typename Types::Sym sym;
714        size_t nameOffset = 1;
715        if (!input->compileOptions.empty())
716        {
717            SLEV(sym.st_name, nameOffset);
718            SLEV(sym.st_shndx, 4);
719            SLEV(sym.st_value, 0);
720            SLEV(sym.st_size, input->compileOptions.size());
721            sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
722            sym.st_other = 0;
723            nameOffset += 26;
724            fob.writeObject(sym);
725        }
726        size_t rodataPos = 0;
727        size_t textPos = 0;
728        for (size_t i = 0; i < input->kernels.size(); i++)
729        {
730            const AmdCL2KernelInput& kernel = input->kernels[i];
731            const TempAmdCL2KernelData& tempData = tempDatas[i];
732            SLEV(sym.st_name, nameOffset);
733            SLEV(sym.st_shndx, 5);
734            SLEV(sym.st_value, rodataPos);
735            SLEV(sym.st_size, tempData.metadataSize);
736            sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
737            sym.st_other = 0;
738            nameOffset += kernel.kernelName.size() + 19 + 17;
739            rodataPos += tempData.metadataSize;
740            fob.writeObject(sym);
741        }
742        if (withBrig)
743        {   // put __BRIG__ symbol
744            SLEV(sym.st_name, nameOffset);
745            SLEV(sym.st_shndx, 7 + brigIndex);
746            SLEV(sym.st_value, 0);
747            SLEV(sym.st_size, input->extraSections[brigIndex].size);
748            sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
749            sym.st_other = 0;
750            nameOffset += 9;
751            fob.writeObject(sym);
752        }
753       
754        if (!newBinaries)
755        { // put binary and ISA metadata symbols
756            for (size_t i = 0; i < input->kernels.size(); i++)
757            {
758                const AmdCL2KernelInput& kernel = input->kernels[i];
759                const TempAmdCL2KernelData& tempData = tempDatas[i];
760                // put kernel binary symbol
761                SLEV(sym.st_name, nameOffset);
762                SLEV(sym.st_shndx, 6);
763                SLEV(sym.st_value, textPos);
764                SLEV(sym.st_size, tempData.stubSize+tempData.setupSize+tempData.codeSize);
765                sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_FUNC);
766                sym.st_other = 0;
767                nameOffset += 16 + kernel.kernelName.size() + 15;
768                textPos += tempData.stubSize+tempData.setupSize+tempData.codeSize;
769                fob.writeObject(sym);
770                // put ISA metadata symbol
771                SLEV(sym.st_name, nameOffset);
772                SLEV(sym.st_shndx, 5);
773                SLEV(sym.st_value, rodataPos);
774                SLEV(sym.st_size, tempData.isaMetadataSize);
775                sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
776                sym.st_other = 0;
777                nameOffset += 16 + kernel.kernelName.size() + 17;
778                rodataPos += tempData.isaMetadataSize;
779                fob.writeObject(sym);
780            }
781        }
782        // acl_version_string
783        SLEV(sym.st_name, nameOffset);
784        SLEV(sym.st_shndx, 4);
785        SLEV(sym.st_value, input->compileOptions.size());
786        SLEV(sym.st_size, aclVersion.size());
787        sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
788        sym.st_other = 0;
789        fob.writeObject(sym);
790        nameOffset += 19;
791       
792        for (const BinSymbol& symbol: input->extraSymbols)
793        {
794            SLEV(sym.st_name, nameOffset);
795            SLEV(sym.st_shndx, convertSectionId(symbol.sectionId, mainSectTable,
796                            ELFSECTID_STD_MAX, extraSectionIndex));
797            SLEV(sym.st_size, symbol.size);
798            SLEV(sym.st_value, symbol.value);
799            sym.st_info = symbol.info;
800            sym.st_other = symbol.other;
801            nameOffset += symbol.name.size()+1;
802            fob.writeObject(sym);
803        }
804    }
805};
806
807class CLRX_INTERNAL CL2MainCommentGen: public ElfRegionContent
808{
809private:
810    const AmdCL2Input* input;
811    const CString& aclVersion;
812public:
813    explicit CL2MainCommentGen(const AmdCL2Input* _input, const CString& _aclVersion) :
814            input(_input), aclVersion(_aclVersion)
815    { }
816   
817    void operator()(FastOutputBuffer& fob) const
818    {
819        fob.write(input->compileOptions.size(), input->compileOptions.c_str());
820        fob.write(aclVersion.size(), aclVersion.c_str());
821    }
822};
823
824struct CLRX_INTERNAL TypeNameVecSize
825{
826    cxbyte elemSize;
827    cxbyte vecSize;
828};
829
830static const uint32_t ptrSpacesTable[4] = { 0, 3, 5, 4 };
831
832struct CLRX_INTERNAL AmdCL2Types32
833{
834    typedef AmdCL2GPUMetadataHeader32 MetadataHeader;
835    typedef AmdCL2GPUKernelArgEntry32 KernelArgEntry;
836    static const size_t headerSize16_3Ver = 0xa4;
837    static const size_t headerSizeNewBinaries = 0x90;
838    static const size_t headerSizeOldBinaries = 0x88;
839    static const size_t endSize = 24;
840    static const size_t headerEndSize = 20;
841    static const size_t middleHeaderSize = 16;
842};
843
844struct CLRX_INTERNAL AmdCL2Types64
845{
846    typedef AmdCL2GPUMetadataHeader64 MetadataHeader;
847    typedef AmdCL2GPUKernelArgEntry64 KernelArgEntry;
848    static const size_t headerSize16_3Ver = 0x110;
849    static const size_t headerSizeNewBinaries = 0xe0;
850    static const size_t headerSizeOldBinaries = 0xd8;
851    static const size_t endSize = 48;
852    static const size_t headerEndSize = 44;
853    static const size_t middleHeaderSize = 40;
854};
855
856template<typename Types>
857class CLRX_INTERNAL CL2MainRodataGen: public ElfRegionContent
858{
859private:
860    const AmdCL2Input* input;
861    const Array<TempAmdCL2KernelData>& tempDatas;
862public:
863    explicit CL2MainRodataGen(const AmdCL2Input* _input,
864              const Array<TempAmdCL2KernelData>& _tempDatas) : input(_input),
865              tempDatas(_tempDatas)
866    { }
867   
868    size_t size() const
869    {
870        const bool newBinaries = input->driverVersion >= 191205;
871        size_t out = 0;
872        for (const TempAmdCL2KernelData& tempData: tempDatas)
873            out += tempData.metadataSize;
874           
875        if (!newBinaries)
876            for (const TempAmdCL2KernelData& tempData: tempDatas)
877                out += tempData.isaMetadataSize;
878        return out;
879    }
880   
881    void writeMetadata(cxuint kernelId, const TempAmdCL2KernelData& tempData,
882               const AmdCL2KernelConfig& config, FastOutputBuffer& fob) const
883    {
884        const bool newBinaries = input->driverVersion >= 191205;
885        const bool is16_3Ver = input->driverVersion >= 200406;
886        const GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
887       
888        typename Types::MetadataHeader header;
889        cxuint argsNum = config.args.size();
890       
891        SLEV(header.size, (newBinaries) ? (is16_3Ver ? Types::headerSize16_3Ver :
892                Types::headerSizeNewBinaries) : Types::headerSizeOldBinaries);
893        SLEV(header.metadataSize, tempData.metadataSize);
894        SLEV(header.unknown1[0], 0x3);
895        SLEV(header.unknown1[1], 0x1);
896        SLEV(header.unknown1[2], 0x68);
897        uint32_t options = config.reqdWorkGroupSize[0]!=0 ? 0x04 : 0x00;
898        options |= input->is64Bit ? 0x20 : 0x00;
899        if (((config.useEnqueue || config.localSize!=0 || tempData.pipesUsed!=0 ||
900                config.scratchBufferSize!=0) && !newBinaries))
901            options |= 0x100U;
902        SLEV(header.options, options);
903        SLEV(header.kernelId, kernelId+1024);
904        header.unknownx = 0;
905        header.unknowny = 0;
906        SLEV(header.unknown2[0], 0x0100000008ULL);
907        SLEV(header.unknown2[1], 0x0200000001ULL);
908        SLEV(header.reqdWorkGroupSize[0], config.reqdWorkGroupSize[0]);
909        SLEV(header.reqdWorkGroupSize[1], config.reqdWorkGroupSize[1]);
910        SLEV(header.reqdWorkGroupSize[2], config.reqdWorkGroupSize[2]);
911        ::memset(header.unknown3, 0, sizeof header.unknown3);
912        SLEV(header.firstNameLength, 0x15);
913        if (input->driverVersion < 223600U)
914            SLEV(header.secondNameLength, 0x7); // generic word
915        else  // GFX? word
916            SLEV(header.secondNameLength,
917                        ::strlen(amdcl2GPUArchNameWordTable[cxuint(arch)]));
918        for (cxuint i = 0; i < 3; i++)
919            header.unknown4[i] = 0;
920        if (!newBinaries)
921            SLEV(header.pipesUsage, (config.scratchBufferSize!=0) ?
922                    config.scratchBufferSize : (tempData.pipesUsed<<4));
923        else // new binaries
924            header.pipesUsage = 0;
925        header.unknown5[0] = header.unknown5[1] = 0;
926        SLEV(header.argsNum, argsNum);
927        fob.writeObject(header);
928        fob.fill(Types::middleHeaderSize, 0); // fill up
929        fob.writeObject(LEV(uint32_t(config.useEnqueue?1:0)));
930        fob.writeObject(LEV(uint32_t(kernelId)));
931        if (newBinaries) // additional data
932        {
933            fob.writeObject(LEV(uint32_t(0x00000006U)));
934            if (is16_3Ver && input->is64Bit)
935                fob.writeObject(uint32_t(0));
936            fob.writeObject(LEV(uint32_t(
937                        tempData.pipesUsed==0 && !config.useEnqueue ? 0xffffffffU : 0)));
938        }
939        if (is16_3Ver)
940            fob.fill(Types::headerEndSize, 0);
941        // two null terminated strings
942        fob.writeArray(22, "__OpenCL_dummy_kernel");
943        if (input->driverVersion < 223600U)
944            fob.writeArray(8, "generic");
945        else    // GFX?
946            fob.writeArray(::strlen(amdcl2GPUArchNameWordTable[cxuint(arch)])+1,
947                           amdcl2GPUArchNameWordTable[cxuint(arch)]);
948        if (is16_3Ver)
949            fob.writeObject<cxbyte>(0);
950       
951        // put argument entries
952        cxuint argOffset = 0;
953        for (cxuint i = 0; i < argsNum; i++)
954        {   //
955            const AmdKernelArgInput& arg = config.args[i];
956            typename Types::KernelArgEntry argEntry;
957            SLEV(argEntry.size, sizeof(typename Types::KernelArgEntry));
958            SLEV(argEntry.argNameSize, arg.argName.size());
959            SLEV(argEntry.typeNameSize, arg.typeName.size());
960            argEntry.unknown1 = 0;
961            argEntry.unknown2 = 0;
962           
963            const bool isImage = isKernelArgImage(arg.argType);
964           
965            ArgTypeSizes argTypeSizes = argTypeSizesTable[cxuint(arg.argType)];
966            if (!input->is64Bit && arg.argType==KernelArgType::POINTER)
967                argTypeSizes.elemSize = 4; // fix for 32-bit for pointer
968            cxuint vectorLength = argTypeSizes.vectorSize;
969            if (newBinaries && vectorLength==3)
970                vectorLength = 4;
971            if (isImage || arg.argType==KernelArgType::SAMPLER)
972                // image/sampler resid
973                SLEV(argEntry.resId, tempData.argResIds[i]);
974            else if (arg.argType == KernelArgType::STRUCTURE)
975                SLEV(argEntry.structSize, arg.structSize);
976            else
977                SLEV(argEntry.vectorLength, vectorLength);
978            size_t argSize = (arg.argType==KernelArgType::STRUCTURE) ? arg.structSize :
979                    // argSize for argOffset: clamp elem size to 4 bytes
980                    std::max(cxbyte(4), argTypeSizes.elemSize)*vectorLength;
981           
982            SLEV(argEntry.unknown3, (arg.argType!=KernelArgType::SAMPLER));
983            SLEV(argEntry.argOffset, argOffset);
984            argOffset += (argSize + 15) & ~15U; // align to 16 bytes
985           
986            uint32_t argType = 0;
987            if (isImage)
988            {   // if image
989                cxuint ptrAccMask = arg.ptrAccess & KARG_PTR_ACCESS_MASK;
990                argType = ptrAccMask==KARG_PTR_READ_ONLY ? 1 :
991                        ptrAccMask==KARG_PTR_WRITE_ONLY ? 2 : 3 /* read-write */;
992            }
993            else // otherwise
994            {
995                argType = argTypeSizes.type;
996                if (is16_3Ver && (arg.argType==KernelArgType::CHAR ||
997                     arg.argType==KernelArgType::SHORT ||
998                     arg.argType==KernelArgType::INT||
999                     arg.argType==KernelArgType::LONG))
1000                    argType -= 4; // fix for crimson 16.4/gpupro
1001            }
1002            SLEV(argEntry.argType, argType);
1003           
1004            uint32_t ptrAlignment = 0;
1005            if (arg.argType == KernelArgType::CMDQUEUE)
1006                ptrAlignment = newBinaries ? 4 : 2;
1007            else if (arg.argType == KernelArgType::PIPE)
1008                ptrAlignment = 256;
1009            else if (arg.argType == KernelArgType::CLKEVENT)
1010                ptrAlignment = 4;
1011            else if (isImage)
1012                ptrAlignment = 1;
1013            else if (arg.argType == KernelArgType::POINTER) // otherwise
1014            {
1015                cxuint vectorLength = argTypeSizesTable[cxuint(arg.pointerType)].vectorSize;
1016                if (newBinaries && vectorLength==3)
1017                vectorLength = 4;
1018                size_t ptrTypeSize = (arg.pointerType==KernelArgType::STRUCTURE) ?
1019                    arg.structSize :argTypeSizesTable[cxuint(arg.pointerType)].elemSize *
1020                    vectorLength;
1021                ptrAlignment = 1U<<(31-CLZ32(ptrTypeSize));
1022                if (ptrAlignment != ptrTypeSize)
1023                    ptrAlignment <<= 1;
1024            }
1025           
1026            SLEV(argEntry.ptrAlignment, ptrAlignment);
1027           
1028            if (arg.argType == KernelArgType::CLKEVENT)
1029            {
1030                SLEV(argEntry.ptrType, 18);
1031                SLEV(argEntry.ptrSpace, 4);
1032            }
1033            else if (arg.argType == KernelArgType::POINTER)
1034            {
1035                SLEV(argEntry.ptrType, argTypeSizesTable[cxuint(arg.pointerType)].type);
1036                SLEV(argEntry.ptrSpace, ptrSpacesTable[cxuint(arg.ptrSpace)]);
1037            }
1038            else if (arg.argType == KernelArgType::PIPE)
1039            {
1040                SLEV(argEntry.ptrType, 15);
1041                SLEV(argEntry.ptrSpace, 4);
1042            }
1043            else
1044            {
1045                argEntry.ptrType = 0;
1046                argEntry.ptrSpace = 0;
1047            }
1048            cxuint isPointerOrPipe = 0;
1049            if (arg.argType==KernelArgType::PIPE)
1050                isPointerOrPipe = (arg.used) ? 3 : 1;
1051            else if (arg.argType==KernelArgType::POINTER ||
1052                    arg.argType==KernelArgType::CLKEVENT)
1053            {
1054                if (newBinaries)
1055                    isPointerOrPipe = (arg.used!=0) ? arg.used : 1;
1056                else // ???
1057                    isPointerOrPipe = 3;
1058            }
1059            SLEV(argEntry.isPointerOrPipe, isPointerOrPipe);
1060           
1061            SLEV(argEntry.isConst, (arg.ptrAccess & KARG_PTR_CONST) != 0);
1062            argEntry.isVolatile = ((arg.ptrAccess & KARG_PTR_VOLATILE) != 0);
1063            argEntry.isRestrict = ((arg.ptrAccess & KARG_PTR_RESTRICT) != 0);
1064            argEntry.unknown4 = 0;
1065            argEntry.isPipe = (arg.argType==KernelArgType::PIPE);
1066           
1067            uint32_t kindOfType;
1068            if (arg.argType==KernelArgType::SAMPLER)
1069                kindOfType = 1;
1070            else if (isImage)
1071                kindOfType = 2;
1072            else if (isPointerOrPipe)
1073                kindOfType = 5;
1074            else if (arg.argType==KernelArgType::CMDQUEUE)
1075                kindOfType = 7;
1076            else // otherwise
1077                kindOfType = 4;
1078            SLEV(argEntry.kindOfType, kindOfType);
1079            fob.writeObject(argEntry);
1080        }
1081        fob.fill(sizeof(typename Types::KernelArgEntry), 0); // NULL arg
1082       
1083        // arg names and type names
1084        for (const AmdKernelArgInput& arg: config.args)
1085        {
1086            fob.writeArray(arg.argName.size()+1, arg.argName.c_str());
1087            fob.writeArray(arg.typeName.size()+1, arg.typeName.c_str());
1088        }
1089        fob.fill(Types::endSize, 0);
1090    }
1091   
1092    void operator()(FastOutputBuffer& fob) const
1093    {
1094        const bool newBinaries = input->driverVersion >= 191205;
1095        for (size_t i = 0; i < input->kernels.size(); i++)
1096        {
1097            const AmdCL2KernelInput& kernel = input->kernels[i];
1098            if (kernel.useConfig)
1099                writeMetadata(i, tempDatas[i], kernel.config, fob);
1100            else
1101                fob.writeArray(kernel.metadataSize, kernel.metadata);
1102        }
1103        if (!newBinaries)
1104            for (const AmdCL2KernelInput& kernel: input->kernels)
1105            {
1106                if (kernel.isaMetadata!=nullptr)
1107                    fob.writeArray(kernel.isaMetadataSize, kernel.isaMetadata);
1108                else // default values
1109                    fob.writeArray(sizeof(kernelIsaMetadata), kernelIsaMetadata);
1110            }
1111    }
1112};
1113
1114static const cxbyte kernelSetupBytesAfter8[40] =
1115{
1116    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1118    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1119    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1121};
1122
1123struct CLRX_INTERNAL IntAmdCL2SetupData
1124{
1125    uint32_t pgmRSRC1;
1126    uint32_t pgmRSRC2;
1127    uint16_t setup1;
1128    uint16_t archInd;
1129    uint32_t scratchBufferSize;
1130    uint32_t localSize; // in bytes
1131    uint32_t gdsSize;
1132    uint32_t kernelArgsSize;
1133    uint32_t zeroes[2];
1134    uint16_t sgprsNumAll;
1135    uint16_t vgprsNum16;
1136    uint16_t vgprReserved;
1137    uint16_t vgprReservedCount;
1138    uint16_t sgprReserved;
1139    uint16_t sgprReservedCount;
1140    uint32_t zero3;
1141    uint32_t setup2; // ??
1142};
1143
1144static uint32_t calculatePgmRSRC2(const AmdCL2KernelConfig& config,
1145                GPUArchitecture arch, bool storeLocalSize = false)
1146{
1147    uint32_t dimValues = 0;
1148    if (config.dimMask != BINGEN_DEFAULT)
1149    {
1150        dimValues = ((config.dimMask&7)<<7);
1151        if (!config.useEnqueue)
1152            // useenqueue in GFX9 is enabled by default ???
1153            dimValues |= (((config.dimMask&4) ? 2 : (config.dimMask&2) ? 1 : 0)<<11);
1154        else // enqueue needs TIDIG_COMP_CNT=2 ????
1155            dimValues |= (2U<<11);
1156    }
1157    else
1158        dimValues |= (config.pgmRSRC2 & 0x1b80U);
1159   
1160    const bool isGCN14 = arch >= GPUArchitecture::GCN1_4;
1161    cxuint userDatasNum = isGCN14 ? 6 : 4;
1162    if (config.useGeneric)
1163        userDatasNum = 12;
1164    else if (config.useEnqueue)
1165        userDatasNum = 10;
1166    else if (config.useSetup)
1167        userDatasNum = isGCN14 ? 10 : 8;
1168    else if (config.useArgs)
1169        userDatasNum = isGCN14 ? 8 : 6;
1170   
1171    return (config.pgmRSRC2 & 0xffffe440U) |
1172            calculatePgmRSrc2(arch, (config.scratchBufferSize != 0),
1173                    userDatasNum, false, BINGEN_DEFAULT, dimValues, config.tgSize,
1174                    storeLocalSize ? config.localSize : 0, config.exceptions);
1175}
1176
1177size_t AmdCL2KernelConfig::calculateKernelArgSize(bool is64Bit, bool newBinaries) const
1178{
1179    cxuint kernelArgSize = 0;
1180    for (const AmdKernelArgInput arg: args)
1181    {
1182        if (arg.argType == KernelArgType::POINTER ||
1183            arg.argType == KernelArgType::PIPE ||
1184            arg.argType == KernelArgType::CLKEVENT ||
1185            arg.argType == KernelArgType::STRUCTURE ||
1186            arg.argType == KernelArgType::CMDQUEUE ||
1187            arg.argType == KernelArgType::SAMPLER || isKernelArgImage(arg.argType))
1188        {
1189            cxuint size = (is64Bit) ? 8 : 4;
1190            if ((kernelArgSize&(size-1))!=0)    // alignment
1191                kernelArgSize += size-(kernelArgSize&(size-1));
1192            kernelArgSize += size;
1193        }
1194        else
1195        {   // scalar
1196            const ArgTypeSizes& argTypeSizes = argTypeSizesTable[cxuint(arg.argType)];
1197            cxuint vectorLength = argTypeSizes.vectorSize;
1198            if (newBinaries && vectorLength==3)
1199                vectorLength = 4;
1200            if ((kernelArgSize & (argTypeSizes.elemSize-1))!=0)
1201                kernelArgSize += argTypeSizes.elemSize -
1202                        (kernelArgSize & (argTypeSizes.elemSize-1));
1203            kernelArgSize += vectorLength * argTypeSizes.elemSize;
1204        }
1205    }
1206    if (newBinaries)
1207        kernelArgSize = (kernelArgSize+15)&~15U;
1208    return kernelArgSize;
1209}
1210
1211static void generateKernelSetup(GPUArchitecture arch, const AmdCL2KernelConfig& config,
1212                FastOutputBuffer& fob, bool newBinaries, bool useLocals, bool usePipes,
1213                bool is64Bit, cxuint driverVersion)
1214{
1215    fob.writeObject<uint64_t>(LEV(uint64_t(newBinaries ? 0x100000001ULL : 1ULL)));
1216    fob.writeArray(40, kernelSetupBytesAfter8);
1217    IntAmdCL2SetupData setupData;
1218    const cxuint neededExtraSGPRsNum = arch>=GPUArchitecture::GCN1_2 ? 4 : 2;
1219    const cxuint extraSGPRsNum = (config.useEnqueue || config.useGeneric) ?
1220                neededExtraSGPRsNum : 0;
1221    cxuint sgprsNum = std::max(config.usedSGPRsNum + extraSGPRsNum + 2, 1U);
1222    cxuint vgprsNum = std::max(config.usedVGPRsNum, 1U);
1223    // pgmrsrc1
1224    SLEV(setupData.pgmRSRC1, config.pgmRSRC1 |
1225            calculatePgmRSrc1(arch, vgprsNum, sgprsNum, config.priority, config.floatMode,
1226                    config.privilegedMode, config.dx10Clamp | newBinaries,
1227                    config.debugMode, config.ieeeMode));
1228    // pgmrsrc2 - without ldssize
1229    uint16_t setup1 = 0x1;
1230    if (config.useGeneric)
1231        setup1 = 0x2f;
1232    else if (config.useEnqueue)
1233        setup1 = 0x2b;
1234    else if (config.useSetup)
1235        setup1 = 0xb;
1236    else if (config.useArgs)
1237        setup1 = 0x9;
1238    if (arch==GPUArchitecture::GCN1_4)
1239        setup1 |= 0x20;
1240   
1241    SLEV(setupData.pgmRSRC2, calculatePgmRSRC2(config, arch));
1242   
1243    SLEV(setupData.setup1, setup1);
1244    uint16_t archInd = (is64Bit) ? 0xa : 0x2;
1245    SLEV(setupData.archInd, (arch>=GPUArchitecture::GCN1_2 && newBinaries &&
1246                driverVersion <= 191205) ? (0x40|archInd) : archInd);
1247    SLEV(setupData.scratchBufferSize, config.scratchBufferSize);
1248    SLEV(setupData.localSize, config.localSize);
1249    SLEV(setupData.gdsSize, config.gdsSize);
1250    setupData.zeroes[0] = setupData.zeroes[1] = 0;
1251    setupData.zero3 = 0;
1252   
1253    const cxuint kernelArgSize = config.calculateKernelArgSize(is64Bit, newBinaries);
1254    SLEV(setupData.kernelArgsSize, kernelArgSize);
1255    SLEV(setupData.sgprsNumAll, sgprsNum);
1256    SLEV(setupData.vgprsNum16, config.usedVGPRsNum);
1257    SLEV(setupData.vgprReserved, config.usedVGPRsNum);
1258    SLEV(setupData.vgprReservedCount, 0);
1259    SLEV(setupData.sgprReserved, config.usedSGPRsNum);
1260    SLEV(setupData.sgprReservedCount, 0);
1261    if (newBinaries)
1262        SLEV(setupData.setup2, 0x06040404U);
1263    else // old binaries
1264    {
1265        uint32_t extraBits = (config.useEnqueue) ? 0x30000U : 0;
1266        extraBits |= (!config.useEnqueue && config.scratchBufferSize!=0) ? 0x40000U : 0;
1267        extraBits |= (config.localSize!=0) ? 0x200U : 0;
1268        extraBits |= (usePipes && (extraBits&0x40000U)==0) ? 0x30000U : 0;
1269        SLEV(setupData.setup2, 0x06000003U | extraBits);
1270    }
1271   
1272    fob.writeObject(setupData);
1273    fob.fill(256 - sizeof(IntAmdCL2SetupData) - 48, 0);
1274}
1275
1276struct CLRX_INTERNAL IntAmdCL2StubHeader
1277{
1278    uint32_t hsaTextOffset;
1279    uint32_t instrsNum;
1280    uint32_t vgprsNum;
1281    uint32_t zeroes[6];
1282    uint32_t sizeProgVal; // 0x24
1283    uint32_t globalMemOps;
1284    uint32_t localMemOps;
1285    uint32_t zero2;
1286    uint32_t programRegSize; // sum??
1287    uint32_t zero3;
1288    uint32_t sgprsNumAll;
1289};
1290
1291static const bool gcnSize11Table[16] =
1292{
1293    false, // GCNENC_SMRD, // 0000
1294    false, // GCNENC_SMRD, // 0001
1295    false, // GCNENC_VINTRP, // 0010
1296    false, // GCNENC_NONE, // 0011 - illegal
1297    true,  // GCNENC_VOP3A, // 0100
1298    false, // GCNENC_NONE, // 0101 - illegal
1299    true,  // GCNENC_DS,   // 0110
1300    true,  // GCNENC_FLAT, // 0111
1301    true,  // GCNENC_MUBUF, // 1000
1302    false, // GCNENC_NONE,  // 1001 - illegal
1303    true,  // GCNENC_MTBUF, // 1010
1304    false, // GCNENC_NONE,  // 1011 - illegal
1305    true,  // GCNENC_MIMG,  // 1100
1306    false, // GCNENC_NONE,  // 1101 - illegal
1307    true,  // GCNENC_EXP,   // 1110
1308    false  // GCNENC_NONE   // 1111 - illegal
1309};
1310
1311static const bool gcnSize12Table[16] =
1312{
1313    true,  // GCNENC_SMEM, // 0000
1314    true,  // GCNENC_EXP, // 0001
1315    false, // GCNENC_NONE, // 0010 - illegal
1316    false, // GCNENC_NONE, // 0011 - illegal
1317    true,  // GCNENC_VOP3A, // 0100
1318    false, // GCNENC_VINTRP, // 0101
1319    true,  // GCNENC_DS,   // 0110
1320    true,  // GCNENC_FLAT, // 0111
1321    true,  // GCNENC_MUBUF, // 1000
1322    false, // GCNENC_NONE,  // 1001 - illegal
1323    true,  // GCNENC_MTBUF, // 1010
1324    false, // GCNENC_NONE,  // 1011 - illegal
1325    true,  // GCNENC_MIMG,  // 1100
1326    false, // GCNENC_NONE,  // 1101 - illegal
1327    false, // GCNENC_NONE,  // 1110 - illegal
1328    false  // GCNENC_NONE   // 1111 - illegal
1329};
1330
1331enum : cxbyte
1332{
1333    INSTRTYPE_OTHER = 0,
1334    INSTRTYPE_GLOBAL,
1335    INSTRTYPE_LOCAL,
1336};
1337
1338static const cxbyte gcnEncInstrTable[16] =
1339{
1340    INSTRTYPE_OTHER, // 0000
1341    INSTRTYPE_OTHER, // 0001
1342    INSTRTYPE_OTHER, // 0010
1343    INSTRTYPE_OTHER, // 0011 - illegal
1344    INSTRTYPE_OTHER, // 0100
1345    INSTRTYPE_OTHER, // 0101 - illegal
1346    INSTRTYPE_LOCAL,  // 0110
1347    INSTRTYPE_GLOBAL, // 0111
1348    INSTRTYPE_GLOBAL, // 1000
1349    INSTRTYPE_OTHER,  // 1001 - illegal
1350    INSTRTYPE_GLOBAL, // 1010
1351    INSTRTYPE_OTHER,  // 1011 - illegal
1352    INSTRTYPE_GLOBAL, // 1100
1353    INSTRTYPE_OTHER,  // 1101 - illegal
1354    INSTRTYPE_OTHER,  // 1110
1355    INSTRTYPE_OTHER // 1111 - illegal
1356};
1357
1358/* count number of instructions, local memory operations and global memory operations */
1359
1360static void analyzeCode(GPUArchitecture arch, size_t codeSize, const cxbyte* code,
1361            IntAmdCL2StubHeader& stubHdr)
1362{
1363    uint32_t instrsNum = 0;
1364    uint32_t globalMemOps = 0;
1365    uint32_t localMemOps = 0;
1366    const size_t codeWordsNum = codeSize>>2;
1367    const uint32_t* codeWords = reinterpret_cast<const uint32_t*>(code);
1368    bool isGCN12 = (arch >= GPUArchitecture::GCN1_2);
1369    bool isGCN11 = (arch == GPUArchitecture::GCN1_1);
1370   
1371    /* main analyzing code loop, parse and determine instr encoding, and counts
1372     * global/local memory ops */
1373    for (size_t pos = 0; pos < codeWordsNum; instrsNum++)
1374    {
1375        uint32_t insnCode = ULEV(codeWords[pos++]);
1376       
1377        if ((insnCode & 0x80000000U) != 0)
1378        {
1379            if ((insnCode & 0x40000000U) == 0)
1380            {   // SOP???
1381                if  ((insnCode & 0x30000000U) == 0x30000000U)
1382                {   // SOP1/SOPK/SOPC/SOPP
1383                    const uint32_t encPart = (insnCode & 0x0f800000U);
1384                    if (encPart == 0x0e800000U)
1385                    {   // SOP1
1386                        if ((insnCode&0xff) == 0xff) // literal
1387                        {
1388                            if (pos < codeWordsNum) pos++;
1389                        }
1390                    }
1391                    else if (encPart == 0x0f000000U)
1392                    {   // SOPC
1393                        if ((insnCode&0xff) == 0xff ||
1394                            (insnCode&0xff00) == 0xff00) // literal
1395                            if (pos < codeWordsNum) pos++;
1396                    }
1397                    else if (encPart != 0x0f800000U) // no SOPP
1398                    {
1399                        const uint32_t opcode = ((insnCode>>23)&0x1f);
1400                        if ((!isGCN12 && opcode == 21) ||
1401                            (isGCN12 && opcode == 20))
1402                            if (pos < codeWordsNum) pos++;
1403                    }
1404                }
1405                else
1406                {   // SOP2
1407                    if ((insnCode&0xff) == 0xff || (insnCode&0xff00) == 0xff00)
1408                        // literal
1409                        if (pos < codeWordsNum) pos++;
1410                }
1411            }
1412            else
1413            {   // SMRD and others
1414                const uint32_t encPart = (insnCode&0x3c000000U)>>26;
1415                if ((!isGCN12 && gcnSize11Table[encPart] && (encPart != 7 || isGCN11)) ||
1416                    (isGCN12 && gcnSize12Table[encPart]))
1417                {
1418                    if (pos < codeWordsNum) pos++;
1419                }
1420                cxbyte instrType = gcnEncInstrTable[encPart];
1421                if (instrType == INSTRTYPE_LOCAL)
1422                    localMemOps++;
1423                if (instrType == INSTRTYPE_GLOBAL)
1424                    globalMemOps++;
1425            }
1426        }
1427        else
1428        {   // some vector instructions
1429            if ((insnCode & 0x7e000000U) == 0x7c000000U)
1430            {   // VOPC
1431                if ((insnCode&0x1ff) == 0xff || // literal
1432                    // SDWA, DDP
1433                    (isGCN12 && ((insnCode&0x1ff) == 0xf9 || (insnCode&0x1ff) == 0xfa)))
1434                {
1435                    if (pos < codeWordsNum) pos++;
1436                }
1437            }
1438            else if ((insnCode & 0x7e000000U) == 0x7e000000U)
1439            {   // VOP1
1440                if ((insnCode&0x1ff) == 0xff || // literal
1441                    // SDWA, DDP
1442                    (isGCN12 && ((insnCode&0x1ff) == 0xf9 || (insnCode&0x1ff) == 0xfa)))
1443                    if (pos < codeWordsNum) pos++;
1444            }
1445            else
1446            {   // VOP2
1447                const cxuint opcode = (insnCode >> 25)&0x3f;
1448                if ((!isGCN12 && (opcode == 32 || opcode == 33)) ||
1449                    (isGCN12 && (opcode == 23 || opcode == 24 ||
1450                    opcode == 36 || opcode == 37))) // V_MADMK and V_MADAK
1451                {
1452                    if (pos < codeWordsNum) pos++;
1453                }
1454                else if ((insnCode&0x1ff) == 0xff || // literal
1455                    // SDWA, DDP
1456                    (isGCN12 && ((insnCode&0x1ff) == 0xf9 || (insnCode&0x1ff) == 0xfa)))
1457                    if (pos < codeWordsNum) pos++; 
1458            }
1459        }
1460    }
1461   
1462    SLEV(stubHdr.instrsNum, instrsNum);
1463    SLEV(stubHdr.localMemOps, localMemOps);
1464    SLEV(stubHdr.globalMemOps, globalMemOps);
1465}
1466
1467struct CLRX_INTERNAL IntAmdCL2StubEnd
1468{
1469    uint64_t hsaTextOffset;
1470    uint32_t endSize;
1471    uint32_t hsaTextSize;
1472    uint32_t zeroes[2];
1473    uint32_t unknown1; // value - 0x200
1474    uint32_t unknown2;
1475    uint64_t kernelSize;    // 0x20
1476    uint32_t zeroesx[2];
1477    uint64_t kernelSize2;
1478    uint32_t vgprsNum;      // 0x30
1479    uint32_t sgprsNumAll;
1480    uint32_t zeroes2[2];
1481    uint32_t vgprsNum2;
1482    uint32_t sgprsNum;
1483    uint32_t floatMode; // 0x50
1484    uint32_t unknown3;
1485    uint32_t one; //??
1486    uint32_t zeroes3[3];   
1487    uint32_t scratchBufferSize; // 0x68
1488    uint32_t localSize;
1489    uint32_t allOnes;// 0x70
1490    uint32_t unknownlast; // 0x74 (alignment)
1491};
1492
1493static void generateKernelStub(GPUArchitecture arch, const AmdCL2KernelConfig& config,
1494        FastOutputBuffer& fob, size_t codeSize, const cxbyte* code, bool useLocals,
1495        bool usePipes)
1496{
1497    const cxuint neededExtraSGPRsNum = arch>=GPUArchitecture::GCN1_2 ? 4 : 2;
1498    const cxuint extraSGPRsNum = (config.useEnqueue) ? neededExtraSGPRsNum : 0;
1499    cxuint sgprsNumAll = config.usedSGPRsNum+2 + extraSGPRsNum;
1500    {
1501        IntAmdCL2StubHeader stubHdr;
1502        SLEV(stubHdr.hsaTextOffset, 0xa60);
1503        SLEV(stubHdr.instrsNum, 0xa60);
1504        SLEV(stubHdr.sgprsNumAll, sgprsNumAll);
1505        SLEV(stubHdr.vgprsNum, config.usedVGPRsNum);
1506        analyzeCode(arch, codeSize, code, stubHdr);
1507        std::fill(stubHdr.zeroes, stubHdr.zeroes+6, uint32_t(0));
1508        stubHdr.zero2 = 0;
1509        stubHdr.zero3 = 0;
1510        stubHdr.sizeProgVal = stubHdr.instrsNum; // this same? enough reliable?
1511        SLEV(stubHdr.programRegSize, config.usedSGPRsNum + config.usedVGPRsNum);
1512        fob.writeObject(stubHdr);
1513    }
1514    // next bytes
1515    fob.fill(0xb8 - sizeof(IntAmdCL2StubHeader), 0); // fill up
1516    fob.writeObject(LEV(0xa60));
1517    fob.fill(0x164-0xbc, 0); // fill up
1518    // 0x164
1519    fob.writeObject(LEV(3)); //?
1520    fob.writeObject(LEV(config.localSize!=0 ? 13 : 12)); //?
1521    fob.fill(0x9a0-0x16c, 0); // fill up
1522    { // end of stub - kernel config?
1523        IntAmdCL2StubEnd stubEnd;
1524        SLEV(stubEnd.hsaTextOffset, 0xa60);
1525        SLEV(stubEnd.endSize, 0x100);
1526        SLEV(stubEnd.hsaTextSize, codeSize + 0x100);
1527        stubEnd.zeroes[0] = stubEnd.zeroes[1] = 0;
1528        SLEV(stubEnd.unknown1, 0x200);
1529        stubEnd.unknown2 = 0;
1530        SLEV(stubEnd.kernelSize, codeSize + 0xb60);
1531        stubEnd.zeroesx[0] = stubEnd.zeroesx[1] = 0;
1532        SLEV(stubEnd.kernelSize2, codeSize + 0xb60);
1533        SLEV(stubEnd.vgprsNum, config.usedVGPRsNum);
1534        SLEV(stubEnd.sgprsNumAll, sgprsNumAll);
1535        SLEV(stubEnd.vgprsNum2, config.usedVGPRsNum);
1536        stubEnd.zeroes2[0] = stubEnd.zeroes2[1] = 0;
1537        SLEV(stubEnd.sgprsNum, config.usedSGPRsNum);
1538        SLEV(stubEnd.floatMode, config.floatMode&0xff);
1539        stubEnd.unknown3 = 0;
1540        SLEV(stubEnd.one, 1);
1541        stubEnd.zeroes3[0] = stubEnd.zeroes3[1] = stubEnd.zeroes3[2] = 0;
1542        SLEV(stubEnd.scratchBufferSize, (config.scratchBufferSize+3)>>2);
1543        SLEV(stubEnd.localSize, config.localSize);
1544        SLEV(stubEnd.allOnes, 0xffffffffU);
1545        SLEV(stubEnd.unknownlast, 0);
1546        fob.writeObject(stubEnd);
1547    }
1548    fob.fill(0xa8-sizeof(IntAmdCL2StubEnd), 0);
1549    fob.writeObject(LEV(calculatePgmRSRC2(config, arch, true)));
1550    fob.fill(0xc0-0xac, 0);
1551}
1552
1553class CLRX_INTERNAL CL2MainTextGen: public ElfRegionContent
1554{
1555private:
1556    const AmdCL2Input* input;
1557    const Array<TempAmdCL2KernelData>& tempDatas;
1558    ElfBinaryGen64* innerBinGen;
1559public:
1560    explicit CL2MainTextGen(const AmdCL2Input* _input,
1561            const Array<TempAmdCL2KernelData>& _tempDatas,
1562            ElfBinaryGen64* _innerBinGen) : input(_input), tempDatas(_tempDatas),
1563            innerBinGen(_innerBinGen)
1564    { }
1565   
1566    size_t size() const
1567    {
1568        if (innerBinGen)
1569            return innerBinGen->countSize();
1570        size_t out = 0;
1571        for (const TempAmdCL2KernelData tempData: tempDatas)
1572            out += tempData.stubSize + tempData.setupSize + tempData.codeSize;
1573        return out;
1574    }
1575   
1576    void operator()(FastOutputBuffer& fob) const
1577    {
1578        if (innerBinGen!=nullptr)
1579            innerBinGen->generate(fob);
1580        else // otherwise (old binaries)
1581        {
1582            GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
1583            for (size_t i = 0; i < input->kernels.size(); i++)
1584            {
1585                const AmdCL2KernelInput& kernel = input->kernels[i];
1586                const TempAmdCL2KernelData& tempData = tempDatas[i];
1587                if (!kernel.useConfig)
1588                    // no configuration, get from kernel data
1589                    fob.writeArray(tempData.stubSize, kernel.stub);
1590                else // generate stub, from kernel config
1591                    generateKernelStub(arch, kernel.config, fob, tempData.codeSize,
1592                               kernel.code, tempData.useLocals, tempData.pipesUsed!=0);
1593               
1594                if (!kernel.useConfig || kernel.hsaConfig)
1595                    // no configuration, get from kernel data
1596                    fob.writeArray(tempData.setupSize, kernel.setup);
1597                else // generate stub, setup from kernel config
1598                    generateKernelSetup(arch, kernel.config, fob, false,
1599                                tempData.useLocals, tempData.pipesUsed!=0, input->is64Bit,
1600                                input->driverVersion);
1601                fob.writeArray(kernel.codeSize, kernel.code);
1602            }
1603        }
1604    }
1605};
1606
1607class CLRX_INTERNAL CL2InnerTextGen: public ElfRegionContent
1608{
1609private:
1610    const AmdCL2Input* input;
1611    const Array<TempAmdCL2KernelData>& tempDatas;
1612public:
1613    explicit CL2InnerTextGen(const AmdCL2Input* _input,
1614                const Array<TempAmdCL2KernelData>& _tempDatas) : input(_input),
1615                tempDatas(_tempDatas)
1616    { }
1617   
1618    size_t size() const
1619    {
1620        size_t out = 0;
1621        for (const TempAmdCL2KernelData& tempData: tempDatas)
1622        {
1623            if ((out & 255) != 0)
1624                out += 256-(out&255);
1625            out += tempData.setupSize + tempData.codeSize;
1626        }
1627        return out;
1628    }
1629   
1630    void operator()(FastOutputBuffer& fob) const
1631    {
1632        GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
1633        size_t outSize = 0;
1634        for (size_t i = 0; i < input->kernels.size(); i++)
1635        {
1636            const AmdCL2KernelInput& kernel = input->kernels[i];
1637            const TempAmdCL2KernelData& tempData = tempDatas[i];
1638            if ((outSize & 255) != 0)
1639            {
1640                size_t toFill = 256-(outSize&255);
1641                fob.fill(toFill, 0);
1642                outSize += toFill;
1643            }
1644            if (!kernel.useConfig || kernel.hsaConfig)
1645                fob.writeArray(tempData.setupSize, kernel.setup);
1646            else
1647                generateKernelSetup(arch, kernel.config, fob, true, tempData.useLocals,
1648                            tempData.pipesUsed!=0, input->is64Bit, input->driverVersion);
1649            fob.writeArray(tempData.codeSize, kernel.code);
1650            outSize += tempData.setupSize + tempData.codeSize;
1651        }
1652    }
1653};
1654
1655class CLRX_INTERNAL CL2InnerSamplerInitGen: public ElfRegionContent
1656{
1657private:
1658    const AmdCL2Input* input;
1659public:
1660    explicit CL2InnerSamplerInitGen(const AmdCL2Input* _input) : input(_input)
1661    { }
1662   
1663    void operator()(FastOutputBuffer& fob) const
1664    {
1665        if (input->samplerConfig)
1666        {
1667            uint32_t sampDef[2];
1668            for (uint32_t sampler: input->samplers)
1669            {
1670                SLEV(sampDef[0], 0x10008);
1671                SLEV(sampDef[1], sampler);
1672                fob.writeArray(2, sampDef);
1673            }
1674        }
1675        else
1676            fob.writeArray(input->samplerInitSize, input->samplerInit);
1677    }
1678};
1679
1680class CLRX_INTERNAL CL2InnerGlobalDataGen: public ElfRegionContent
1681{
1682private:
1683    const AmdCL2Input* input;
1684public:
1685    explicit CL2InnerGlobalDataGen(const AmdCL2Input* _input) : input(_input)
1686    { }
1687   
1688    size_t size() const
1689    {
1690        if (input->driverVersion >= 200406)
1691            return input->globalDataSize;
1692        size_t rwDataSize = (input->rwData!=nullptr) ? input->rwDataSize : 0;
1693        size_t allSize = (input->globalDataSize + input->bssSize +
1694                rwDataSize + 255) & ~size_t(255);
1695        return allSize - rwDataSize - input->bssSize;
1696    }
1697   
1698    void operator()(FastOutputBuffer& fob) const
1699    {
1700        size_t gdataSize = size();
1701        fob.writeArray(input->globalDataSize, input->globalData);
1702        if (gdataSize > input->globalDataSize)
1703            fob.fill(gdataSize - input->globalDataSize, 0);
1704    }
1705};
1706
1707class CLRX_INTERNAL CL2InnerGlobalDataRelsGen: public ElfRegionContent
1708{
1709private:
1710    const AmdCL2Input* input;
1711    size_t dataSymbolsNum;
1712public:
1713    explicit CL2InnerGlobalDataRelsGen(const AmdCL2Input* _input, size_t _dataSymNum)
1714            : input(_input), dataSymbolsNum(_dataSymNum)
1715    { }
1716   
1717    size_t size() const
1718    {
1719        size_t out = (input->samplerConfig) ? input->samplers.size() :
1720                (input->samplerInitSize>>3);
1721        return out*sizeof(Elf64_Rela);
1722    }
1723   
1724    void operator()(FastOutputBuffer& fob) const
1725    {
1726        Elf64_Rela rela;
1727        rela.r_addend = 0;
1728        const size_t samplersNum = (input->samplerConfig) ?
1729                input->samplers.size() : (input->samplerInitSize>>3);
1730        /* calculate first symbol for samplers (last symbols) */
1731        uint32_t symIndex = input->kernels.size() + samplersNum + dataSymbolsNum + 2 +
1732                (input->rwDataSize!=0 && input->rwData!=nullptr) /* globaldata symbol */ +
1733                (input->bssSize!=0) /* bss data symbol */ +
1734                (input->driverVersion>=200406);
1735        if (!input->samplerOffsets.empty())
1736            for (size_t sampOffset: input->samplerOffsets)
1737            {
1738                SLEV(rela.r_offset, sampOffset);
1739                SLEV(rela.r_info, ELF64_R_INFO(symIndex, 4U));
1740                fob.writeObject(rela);
1741                symIndex++;
1742            }
1743        else // default in last bytes
1744        {
1745            size_t globalOffset = input->globalDataSize - (samplersNum<<3);
1746            globalOffset &= ~size_t(7); // alignment
1747            for (size_t i = 0; i < samplersNum; i++)
1748            {
1749                SLEV(rela.r_offset, globalOffset + 8*i);
1750                SLEV(rela.r_info, ELF64_R_INFO(symIndex+i, 4U));
1751                fob.writeObject(rela);
1752            }
1753        }
1754    }
1755};
1756
1757class CLRX_INTERNAL CL2InnerTextRelsGen: public ElfRegionContent
1758{
1759private:
1760    const AmdCL2Input* input;
1761    const Array<TempAmdCL2KernelData>& tempDatas;
1762    size_t dataSymbolsNum;
1763public:
1764    explicit CL2InnerTextRelsGen(const AmdCL2Input* _input,
1765            const Array<TempAmdCL2KernelData>& _tempDatas, size_t _dataSymNum) :
1766            input(_input), tempDatas(_tempDatas), dataSymbolsNum(_dataSymNum)
1767    { }
1768   
1769    size_t size() const
1770    {
1771        size_t out = 0;
1772        for (const AmdCL2KernelInput& kernel: input->kernels)
1773            out += kernel.relocations.size()*sizeof(Elf64_Rela);
1774        return out;
1775    }
1776   
1777    void operator()(FastOutputBuffer& fob) const
1778    {
1779        Elf64_Rela rela;
1780        size_t codeOffset = 0;
1781        uint32_t adataSymIndex = 0;
1782        cxuint samplersNum = (input->samplerConfig) ?
1783                input->samplers.size() : (input->samplerInitSize>>3);
1784        uint32_t gdataSymIndex = input->kernels.size() + samplersNum + dataSymbolsNum +
1785            (input->driverVersion>=200406);
1786        uint32_t bssSymIndex = input->kernels.size() + samplersNum + dataSymbolsNum +
1787            (input->driverVersion>=200406);
1788        if (input->rwDataSize!=0 && input->rwData!=nullptr)
1789        {   // atomic data available
1790            adataSymIndex = gdataSymIndex; // first is atomic data symbol index
1791            gdataSymIndex++;
1792        }
1793        if (input->bssSize!=0)
1794        {   // bss section available
1795            bssSymIndex = gdataSymIndex; // first is bss data symbol index
1796            gdataSymIndex++;
1797        }
1798        for (size_t i = 0; i < input->kernels.size(); i++)
1799        {
1800            const AmdCL2KernelInput& kernel = input->kernels[i];
1801            const TempAmdCL2KernelData& tempData = tempDatas[i];
1802           
1803            codeOffset += tempData.setupSize;
1804            for (const AmdCL2RelInput inRel: kernel.relocations)
1805            {
1806                SLEV(rela.r_offset, inRel.offset + codeOffset);
1807                uint32_t type = (inRel.type==RELTYPE_LOW_32BIT) ? 1 : 2;
1808                uint32_t symIndex = (inRel.symbol==1) ? adataSymIndex : 
1809                    ((inRel.symbol==2) ? bssSymIndex: gdataSymIndex);
1810                SLEV(rela.r_info, ELF64_R_INFO(symIndex, type));
1811                SLEV(rela.r_addend, inRel.addend);
1812                fob.writeObject(rela);
1813            }
1814            codeOffset += (kernel.codeSize+255)&~size_t(255);
1815        }
1816    }
1817};
1818
1819static const cxbyte noteDescType1[8] = { 1, 0, 0, 0, 0, 0, 0, 0 };
1820static const cxbyte noteDescType2[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0 };
1821static const cxbyte noteDescType2_32[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 };
1822static const cxbyte noteDescType3[30] =
1823{ 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1824  'A', 'M', 'D', 0, 'A', 'M', 'D', 'G', 'P', 'U', 0, 0, 0, 0  };
1825static const cxbyte noteDescType4[8] =
1826{ 0xf0, 0x83, 0x17, 0xfb, 0xfc, 0x7f, 0x00, 0x00 };
1827static const cxbyte noteDescType4_32bit[4] =
1828{ 0xb0, 0xa6, 0xf2, 0x00 };
1829static const cxbyte noteDescType4_16_3[0x29] =
1830{ 0x19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'A', 'M', 'D', ' ', 'H', 'S', 'A', ' ',
1831  'R', 'u', 'n', 't', 'i', 'm', 'e', ' ',
1832  'F', 'i', 'n', 'a', 'l', 'i', 'z', 'e', 'r', 0, 0, 0, 0  };
1833static const cxbyte noteDescType5[25] =
1834{ 0x16, 0, '-', 'h', 's', 'a', '_', 'c', 'a', 'l', 'l', '_',
1835    'c', 'o', 'n', 'v', 'e', 'n', 't', 'i', 'o', 'n', '=', 0, 0 };
1836static const cxbyte noteDescType5_16_3[26] =
1837{ 0x16, 0, '-', 'h', 's', 'a', '_', 'c', 'a', 'l', 'l', '_',
1838    'c', 'o', 'n', 'v', 'e', 'n', 't', 'i', 'o', 'n', '=', '0', 0, 0 };
1839static const cxbyte noteDescType5_gpupro[26] =
1840{ 0x16, 0, '-', 'h', 's', 'a', '_', 'c', 'a', 'l', 'l', '_',
1841    'c', 'o', 'n', 'v', 'e', 'n', 't', 'i', 'o', 'n', '=', '0', 0, 't' };
1842static const cxbyte noteDescType5_16_3_32bit[54] =
1843{ 0x32, 0, '-', 'h', 's', 'a', '_', 'c', 'a', 'l', 'l', '_',
1844    'c', 'o', 'n', 'v', 'e', 'n', 't', 'i', 'o', 'n', '=', '0', ' ',
1845    '-', 'u', 's', 'e', '-', 'b', 'u', 'f', 'f', 'e', 'r', '-', 'f', 'o', 'r',
1846    '-', 'h', 's', 'a', '-', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 0, 'R' };
1847static const cxbyte noteDescType5_32bit[52] =
1848{ 0x31, 0, '-', 'h', 's', 'a', '_', 'c', 'a', 'l', 'l', '_',
1849    'c', 'o', 'n', 'v', 'e', 'n', 't', 'i', 'o', 'n', '=',  '0', ' ',
1850    '-', 'u', 's', 'e', '-', 'b', 'u', 'f', 'f', 'e', 'r', '-', 'f', 'o', 'r',
1851    '-', 'h', 's', 'a', '-', 'g', 'l', 'o', 'b', 'a' };
1852
1853static const AMDGPUArchValues amdGpuArchValuesTbl[] =
1854{
1855    { 0, 0, 0 }, // GPUDeviceType::CAPE_VERDE
1856    { 0, 0, 0 }, // GPUDeviceType::PITCAIRN
1857    { 0, 0, 0 }, // GPUDeviceType::TAHITI
1858    { 0, 0, 0 }, // GPUDeviceType::OLAND
1859    { 7, 0, 0 }, // GPUDeviceType::BONAIRE
1860    { 7, 0, 0 }, // GPUDeviceType::SPECTRE
1861    { 7, 0, 0 }, // GPUDeviceType::SPOOKY
1862    { 7, 0, 0 }, // GPUDeviceType::KALINDI
1863    { 0, 0, 0 }, // GPUDeviceType::HAINAN
1864    { 7, 0, 1 }, // GPUDeviceType::HAWAII
1865    { 8, 0, 0 }, // GPUDeviceType::ICELAND
1866    { 8, 0, 0 }, // GPUDeviceType::TONGA
1867    { 7, 0, 0 }, // GPUDeviceType::MULLINS
1868    { 8, 0, 4 }, // GPUDeviceType::FIJI
1869    { 8, 0, 1 }, // GPUDeviceType::CARRIZO
1870    { 8, 0, 1 }, // GPUDeviceType::DUMMY
1871    { 8, 0, 4 }, // GPUDeviceType::GOOSE
1872    { 8, 0, 4 }, // GPUDeviceType::HORSE
1873    { 8, 1, 0 }, // GPUDeviceType::STONEY
1874    { 8, 0, 4 }, // GPUDeviceType::ELLESMERE
1875    { 8, 0, 4 }, // GPUDeviceType::BAFFIN
1876    { 8, 0, 4 }, // GPUDeviceType::GFX804
1877    { 9, 0, 0 }, // GPUDeviceType::GFX900
1878    { 9, 0, 1 }  // GPUDeviceType::GFX901
1879};
1880
1881static CString constructName(size_t prefixSize, const char* prefix, const CString& name,
1882                 size_t suffixSize, const char* suffix)
1883{
1884    const size_t nameLen = name.size();
1885    CString out(prefixSize + suffixSize + nameLen);
1886    char* outPtr = out.begin();
1887    std::copy(prefix, prefix+prefixSize, outPtr);
1888    std::copy(name.begin(), name.begin()+nameLen, outPtr+prefixSize);
1889    std::copy(suffix, suffix+suffixSize, outPtr+prefixSize+nameLen);
1890    return out;
1891}
1892
1893static void putInnerSymbols(ElfBinaryGen64& innerBinGen, const AmdCL2Input* input,
1894        const Array<TempAmdCL2KernelData>& tempDatas, const uint16_t* builtinSectionTable,
1895        cxuint extraSeciontIndex, std::vector<CString>& stringPool, size_t dataSymbolsNum)
1896{
1897    const size_t samplersNum = (input->samplerConfig) ? input->samplers.size() :
1898                (input->samplerInitSize>>3);
1899    // put kernel symbols
1900    std::vector<bool> samplerMask(samplersNum);
1901    size_t samplerOffset = input->globalDataSize - samplersNum;
1902    size_t codePos = 0;
1903    const uint16_t textSectId = builtinSectionTable[ELFSECTID_TEXT-ELFSECTID_START];
1904    const uint16_t globalSectId = builtinSectionTable[ELFSECTID_RODATA-ELFSECTID_START];
1905    const uint16_t atomicSectId = builtinSectionTable[
1906                ELFSECTID_DATA-ELFSECTID_START];
1907    const uint16_t sampInitSectId = builtinSectionTable[
1908                AMDCL2SECTID_SAMPLERINIT-ELFSECTID_START];
1909    const uint16_t bssSectId = builtinSectionTable[ELFSECTID_BSS-ELFSECTID_START];
1910    stringPool.resize(input->kernels.size() + samplersNum + dataSymbolsNum);
1911    size_t nameIdx = 0;
1912   
1913    /* put data symbols */
1914    for (const BinSymbol& symbol: input->innerExtraSymbols)
1915        if (symbol.sectionId==ELFSECTID_RODATA || symbol.sectionId==ELFSECTID_DATA ||
1916                   symbol.sectionId==ELFSECTID_BSS)
1917        {
1918            stringPool[nameIdx] = constructName(12, "&input_bc::&", symbol.name,
1919                        0, nullptr);
1920            innerBinGen.addSymbol(ElfSymbol64(stringPool[nameIdx].c_str(),
1921                  convertSectionId(symbol.sectionId, builtinSectionTable, AMDCL2SECTID_MAX,
1922                           extraSeciontIndex),
1923                  ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), 0, false, symbol.value, 
1924                  symbol.size));
1925            nameIdx++;
1926        }
1927    for (size_t i = 0; i < input->kernels.size(); i++)
1928    {   // first, we put sampler objects
1929        const AmdCL2KernelInput& kernel = input->kernels[i];
1930        const TempAmdCL2KernelData& tempData = tempDatas[i];
1931        if ((codePos & 255) != 0)
1932            codePos += 256-(codePos&255);
1933       
1934        if (kernel.useConfig)
1935            for (cxuint samp: kernel.config.samplers)
1936            {
1937                if (samplerMask[samp])
1938                    continue; // if added to symbol table
1939                const uint64_t value = !input->samplerOffsets.empty() ?
1940                        input->samplerOffsets[samp] : samplerOffset + samp*8;
1941                char sampName[64];
1942                memcpy(sampName, "&input_bc::&_.Samp", 18);
1943                itocstrCStyle<cxuint>(samp, sampName+18, 64-18);
1944                stringPool[nameIdx] = sampName;
1945                innerBinGen.addSymbol(ElfSymbol64(stringPool[nameIdx].c_str(), globalSectId,
1946                          ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), 0, false, value, 8));
1947                nameIdx++;
1948                samplerMask[samp] = true;
1949            }
1950        // put kernel symbol
1951        stringPool[nameIdx] = constructName(10, "&__OpenCL_", kernel.kernelName,
1952                        7, "_kernel");
1953       
1954        innerBinGen.addSymbol(ElfSymbol64(stringPool[nameIdx].c_str(), textSectId,
1955                  ELF64_ST_INFO(STB_GLOBAL, 10), 0, false, codePos, 
1956                  kernel.codeSize + tempData.setupSize));
1957        nameIdx++;
1958        codePos += kernel.codeSize + tempData.setupSize;
1959    }
1960   
1961    for (size_t i = 0; i < samplersNum; i++)
1962        if (!samplerMask[i])
1963        {
1964            const uint64_t value = !input->samplerOffsets.empty() ?
1965                    input->samplerOffsets[i] : samplerOffset + i*8;
1966            char sampName[64];
1967            memcpy(sampName, "&input_bc::&_.Samp", 18);
1968            itocstrCStyle<cxuint>(i, sampName+18, 64-18);
1969            stringPool[nameIdx] = sampName;
1970            innerBinGen.addSymbol(ElfSymbol64(stringPool[nameIdx].c_str(), globalSectId,
1971                      ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), 0, false, value, 8));
1972            nameIdx++;
1973            samplerMask[i] = true;
1974        }
1975   
1976    if (input->rwDataSize!=0 && input->rwData!=nullptr)
1977        innerBinGen.addSymbol(ElfSymbol64("__hsa_section.hsadata_global_agent",
1978              atomicSectId, ELF64_ST_INFO(STB_LOCAL, STT_SECTION), 0, false, 0, 0));
1979    if (input->bssSize!=0)
1980        innerBinGen.addSymbol(ElfSymbol64("__hsa_section.hsabss_global_agent",
1981              bssSectId, ELF64_ST_INFO(STB_LOCAL, STT_SECTION), 0, false, 0, 0));
1982    if (input->globalDataSize!=0 && input->globalData!=nullptr)
1983        innerBinGen.addSymbol(ElfSymbol64("__hsa_section.hsadata_readonly_agent",
1984              globalSectId, ELF64_ST_INFO(STB_LOCAL, STT_SECTION), 0, false, 0, 0));
1985    innerBinGen.addSymbol(ElfSymbol64("__hsa_section.hsatext", textSectId,
1986              ELF64_ST_INFO(STB_LOCAL, STT_SECTION), 0, false, 0, 0));
1987   
1988    for (size_t i = 0; i < samplersNum; i++)
1989        innerBinGen.addSymbol(ElfSymbol64("", sampInitSectId, ELF64_ST_INFO(STB_LOCAL, 12),
1990                      0, false, i*8, 0));
1991    /// add extra inner symbols
1992    for (const BinSymbol& extraSym: input->innerExtraSymbols)
1993        innerBinGen.addSymbol(ElfSymbol64(extraSym, builtinSectionTable, AMDCL2SECTID_MAX,
1994                                  extraSeciontIndex));
1995}
1996
1997/// main routine to generate OpenCL 2.0 binary
1998void AmdCL2GPUBinGenerator::generateInternal(std::ostream* osPtr, std::vector<char>* vPtr,
1999             Array<cxbyte>* aPtr) const
2000{
2001    const size_t kernelsNum = input->kernels.size();
2002    const bool newBinaries = input->driverVersion >= 191205;
2003    const bool hasSamplers = !input->samplerOffsets.empty() ||
2004                (!input->samplerConfig && input->samplerInitSize!=0 &&
2005                    input->samplerInit!=nullptr) ||
2006                (input->samplerConfig && !input->samplers.empty());
2007    const bool hasGlobalData = input->globalDataSize!=0 && input->globalData!=nullptr;
2008    const bool hasRWData = input->rwDataSize!=0 && input->rwData!=nullptr;
2009   
2010    const GPUArchitecture arch = getGPUArchitectureFromDeviceType(input->deviceType);
2011    if (arch == GPUArchitecture::GCN1_0)
2012        throw Exception("OpenCL 2.0 supported only for GCN1.1 or later");
2013   
2014    const bool is16_3Ver = (input->driverVersion>=200406);
2015    AMDGPUArchValues amdGpuArchValues = amdGpuArchValuesTbl[cxuint(input->deviceType)];
2016    // fix for old drivers (1912.05)
2017    if (!is16_3Ver && input->deviceType==GPUDeviceType::FIJI)
2018        amdGpuArchValues.stepping = 1;
2019    if (input->archMinor!=UINT32_MAX)
2020        amdGpuArchValues.minor = input->archMinor;
2021    if (input->archStepping!=UINT32_MAX)
2022        amdGpuArchValues.stepping = input->archStepping;
2023   
2024    if ((hasGlobalData || hasRWData || hasSamplers) && !newBinaries)
2025        throw Exception("Old driver binaries doesn't support "
2026                        "global/atomic data or samplers");
2027   
2028    if (newBinaries)
2029    {
2030        if (!hasGlobalData && hasSamplers)
2031            throw Exception("Global data must be defined if samplers present");
2032        // check sampler offset range
2033        for (size_t sampOffset: input->samplerOffsets)
2034            if (sampOffset+8 > input->globalDataSize)
2035                throw Exception("Sampler offset outside global data");
2036    }
2037    /* check samplers */
2038    const cxuint samplersNum = (input->samplerConfig) ? input->samplers.size() :
2039                (input->samplerInitSize>>3);
2040    if (!input->samplerOffsets.empty() && input->samplerOffsets.size() != samplersNum)
2041        throw Exception("SamplerOffset number doesn't match to samplers number");
2042   
2043    for (size_t sampOffset: input->samplerOffsets)
2044        if ((sampOffset&7) != 0 && sampOffset >= input->globalDataSize)
2045            throw Exception("Wrong sampler offset (out of range of unaligned)");
2046   
2047    const bool gpuProDriver = (input->driverVersion == 203603 ||
2048            input->driverVersion == 207903);
2049    /* determine correct flags for device type */
2050    const uint32_t* deviceCodeTable;
2051    const size_t codeTablesNum = sizeof(cl2GenCodeTables)/sizeof(CL2GPUGenCodeTable);
2052    auto ctit = std::upper_bound(cl2GenCodeTables, cl2GenCodeTables+codeTablesNum,
2053                CL2GPUGenCodeTable{ input->driverVersion },
2054                [](const CL2GPUGenCodeTable& a, const CL2GPUGenCodeTable& b)
2055                { return a.toDriverVersion < b.toDriverVersion; });
2056    if (ctit == cl2GenCodeTables+codeTablesNum)
2057        ctit--; // to previous table
2058    deviceCodeTable = ctit->table;
2059   
2060    // if GPU type is not supported by driver version
2061    if (deviceCodeTable[cxuint(input->deviceType)] == UINT_MAX)
2062        throw Exception("Unsupported GPU device type by driver version");
2063   
2064    std::unique_ptr<ElfBinaryGen32> elfBinGen32;
2065    std::unique_ptr<ElfBinaryGen64> elfBinGen64;
2066   
2067    if (input->is64Bit)
2068        elfBinGen64.reset(new ElfBinaryGen64({ 0, 0, ELFOSABI_SYSV, 0, ET_EXEC, 0xaf5b,
2069                EV_CURRENT, UINT_MAX, 0, deviceCodeTable[cxuint(input->deviceType)] }));
2070    else
2071        elfBinGen32.reset(new ElfBinaryGen32({ 0, 0, ELFOSABI_SYSV, 0, ET_EXEC, 0xaf5a,
2072                EV_CURRENT, UINT_MAX, 0, deviceCodeTable[cxuint(input->deviceType)] }));
2073   
2074    CString aclVersion = input->aclVersion;
2075    if (aclVersion.empty())
2076    {
2077        if (newBinaries)
2078            aclVersion = "AMD-COMP-LIB-v0.8 (0.0.SC_BUILD_NUMBER)";
2079        else // old binaries
2080            aclVersion = "AMD-COMP-LIB-v0.8 (0.0.326)";
2081    }
2082   
2083    Array<TempAmdCL2KernelData> tempDatas(kernelsNum);
2084    prepareKernelTempData(input, tempDatas);
2085   
2086    const size_t dataSymbolsNum = std::count_if(input->innerExtraSymbols.begin(),
2087        input->innerExtraSymbols.end(), [](const BinSymbol& symbol)
2088        { return symbol.sectionId==ELFSECTID_RODATA || symbol.sectionId==ELFSECTID_DATA ||
2089                   symbol.sectionId==ELFSECTID_BSS; });
2090   
2091    cxuint mainExtraSectionIndex = 6 + (kernelsNum != 0 || newBinaries);
2092    const uint16_t* mainSectTable = (kernelsNum != 0 || newBinaries) ?
2093            mainBuiltinSectionTable : mainBuiltinSectionTable2;
2094    CL2MainStrTabGen mainStrTabGen(input);
2095    CL2MainSymTabGen<Elf32Types> mainSymTabGen32(input, tempDatas, aclVersion,
2096                     mainSectTable, mainExtraSectionIndex);
2097    CL2MainSymTabGen<Elf64Types> mainSymTabGen64(input, tempDatas, aclVersion,
2098                     mainSectTable, mainExtraSectionIndex);
2099    CL2MainCommentGen mainCommentGen(input, aclVersion);
2100    CL2MainRodataGen<AmdCL2Types32> mainRodataGen32(input, tempDatas);
2101    CL2MainRodataGen<AmdCL2Types64> mainRodataGen64(input, tempDatas);
2102    CL2InnerTextGen innerTextGen(input, tempDatas);
2103    CL2InnerGlobalDataGen innerGDataGen(input);
2104    CL2InnerSamplerInitGen innerSamplerInitGen(input);
2105    CL2InnerTextRelsGen innerTextRelsGen(input, tempDatas, dataSymbolsNum);
2106    CL2InnerGlobalDataRelsGen innerGDataRels(input, dataSymbolsNum);
2107   
2108    // main section of main binary
2109    if (input->is64Bit)
2110    {
2111        elfBinGen64->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 1, ".shstrtab",
2112                        SHT_STRTAB, SHF_STRINGS));
2113        elfBinGen64->addRegion(ElfRegion64(mainStrTabGen.size(), &mainStrTabGen,
2114                      1, ".strtab", SHT_STRTAB, SHF_STRINGS));
2115        elfBinGen64->addRegion(ElfRegion64(mainSymTabGen64.size(), &mainSymTabGen64,
2116                      8, ".symtab", SHT_SYMTAB, 0));
2117        elfBinGen64->addRegion(ElfRegion64(input->compileOptions.size()+aclVersion.size(),
2118                        &mainCommentGen, 1, ".comment", SHT_PROGBITS, 0));
2119        if (kernelsNum != 0)
2120            elfBinGen64->addRegion(ElfRegion64(mainRodataGen64.size(), &mainRodataGen64,
2121                        1, ".rodata", SHT_PROGBITS, SHF_ALLOC));
2122    }
2123    else
2124    {
2125        elfBinGen32->addRegion(ElfRegion32(0, (const cxbyte*)nullptr, 1, ".shstrtab",
2126                        SHT_STRTAB, SHF_STRINGS));
2127        elfBinGen32->addRegion(ElfRegion32(mainStrTabGen.size(), &mainStrTabGen,
2128                      1, ".strtab", SHT_STRTAB, SHF_STRINGS));
2129        elfBinGen32->addRegion(ElfRegion32(mainSymTabGen32.size(), &mainSymTabGen32,
2130                      8, ".symtab", SHT_SYMTAB, 0));
2131        elfBinGen32->addRegion(ElfRegion32(input->compileOptions.size()+aclVersion.size(),
2132                        &mainCommentGen, 1, ".comment", SHT_PROGBITS, 0));
2133        if (kernelsNum != 0)
2134            elfBinGen32->addRegion(ElfRegion32(mainRodataGen32.size(), &mainRodataGen32,
2135                        1, ".rodata", SHT_PROGBITS, SHF_ALLOC));
2136    }
2137   
2138    std::unique_ptr<ElfBinaryGen64> innerBinGen;
2139    std::vector<CString> symbolNamePool;
2140    std::unique_ptr<cxbyte[]> noteBuf;
2141    if (newBinaries)
2142    {   // new binaries - .text holds inner ELF binaries
2143        uint16_t innerBinSectionTable[innerBinSectonTableLen];
2144        cxuint extraSectionIndex = 1;
2145        /* check kernel text relocations */
2146        for (const AmdCL2KernelInput& kernel: input->kernels)
2147            for (const AmdCL2RelInput& rel: kernel.relocations)
2148                if (rel.offset >= kernel.codeSize)
2149                    throw Exception("Kernel text relocation offset outside kernel code");
2150       
2151        std::fill(innerBinSectionTable,
2152                  innerBinSectionTable+innerBinSectonTableLen, SHN_UNDEF);
2153       
2154        cxuint symtabId, globalDataId, textId;
2155        if (!is16_3Ver)
2156        {
2157            symtabId = 4 + (hasSamplers?2:0) /* samplerinit&rela.global */ +
2158                    (hasRWData) + (hasGlobalData) +
2159                    (input->bssSize!=0) +
2160                    (hasRWData || hasGlobalData || input->bssSize!=0) /* rela.hsatext */;
2161            globalDataId = 1 + (hasRWData) + (input->bssSize!=0);
2162            textId = 1 + (hasRWData) + (hasGlobalData) + (input->bssSize!=0);
2163        }
2164        else
2165        {
2166            textId = 4 + (hasRWData) + (hasGlobalData) + (input->bssSize!=0);
2167            symtabId = 5 + (hasRWData) + (hasGlobalData) + (input->bssSize!=0);
2168            globalDataId = 4 + (hasRWData) + (input->bssSize!=0);
2169        }
2170        /* in innerbin we do not add null symbol, we count address for program headers
2171         * and section from first section */
2172        innerBinGen.reset(new ElfBinaryGen64({ 0, 0, 0x40, 0, ET_REL, 0xe0, EV_CURRENT,
2173                        UINT_MAX, 0, 0 }, (input->driverVersion>=200406), true, true, 
2174                        /* globaldata sectionid: for 200406 - 4, for older - 1 */
2175                        (!is16_3Ver) ? 1 : 4));
2176        innerBinGen->addRegion(ElfRegion64::programHeaderTable());
2177       
2178        if (is16_3Ver)
2179        {   /* first is shstrab and strtab */
2180            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8, ".shstrtab",
2181                                  SHT_STRTAB, SHF_STRINGS, 0, 0));
2182            innerBinSectionTable[ELFSECTID_SHSTRTAB-ELFSECTID_START] = extraSectionIndex++;
2183            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8, ".strtab",
2184                                  SHT_STRTAB, SHF_STRINGS, 0, 0));
2185            innerBinSectionTable[ELFSECTID_STRTAB-ELFSECTID_START] = extraSectionIndex++;
2186           
2187            // set AMDGPU type
2188            /*
2189             * AMD - 1 - 00000001 00000000
2190             * AMD - 2 - 00000001 00000000 00010101
2191             * AMD - 3 - size=0x1a, 00070004 major minor stepping AMD\0 AMDGPU\0
2192             * AMD - 4 - size=0x29 00000019 00000001 00000000
2193             *      "AMD HSA Runtime Finalizer" 00000000
2194             * AMD - 5 - size=0x19 \x16\000-hsa_call_convention=\0\0
2195             */
2196            innerBinGen->addNote({"AMD", sizeof noteDescType1, noteDescType1, 1U});
2197            innerBinGen->addNote({"AMD", sizeof noteDescType2,
2198                        (input->is64Bit) ? noteDescType2 : noteDescType2_32, 2U});
2199            noteBuf.reset(new cxbyte[0x1a]);
2200            ::memcpy(noteBuf.get(), noteDescType3, 0x1a);
2201            SULEV(*(uint32_t*)(noteBuf.get()+4), amdGpuArchValues.major);
2202            SULEV(*(uint32_t*)(noteBuf.get()+8), amdGpuArchValues.minor);
2203            SULEV(*(uint32_t*)(noteBuf.get()+12), amdGpuArchValues.stepping);
2204            innerBinGen->addNote({"AMD", 0x1a, noteBuf.get(), 3U});
2205            innerBinGen->addNote({"AMD",
2206                         sizeof noteDescType4_16_3, noteDescType4_16_3, 4U});
2207            if (!gpuProDriver)
2208            {
2209                if (input->is64Bit)
2210                    innerBinGen->addNote({"AMD",
2211                                 sizeof noteDescType5_16_3, noteDescType5_16_3, 5U});
2212                else // 32-bit
2213                    innerBinGen->addNote({"AMD", sizeof noteDescType5_16_3_32bit,
2214                                 noteDescType5_16_3_32bit, 5U});
2215            }
2216            else
2217                innerBinGen->addNote({"AMD",
2218                             sizeof noteDescType5_gpupro, noteDescType5_gpupro, 5U});
2219           
2220            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8,
2221                             ".note", SHT_NOTE, 0));
2222            innerBinSectionTable[AMDCL2SECTID_NOTE-ELFSECTID_START] = extraSectionIndex++;
2223        }
2224        if (hasRWData)
2225        {   // rw data section
2226            innerBinGen->addRegion(ElfRegion64(input->rwDataSize, input->rwData,
2227                      8, ".hsadata_global_agent", SHT_PROGBITS, 0x900003, 0, 0,
2228                      Elf64Types::nobase));
2229            innerBinSectionTable[ELFSECTID_DATA-ELFSECTID_START] =
2230                    extraSectionIndex++;
2231        }
2232        if (input->bssSize!=0)
2233        {
2234            innerBinGen->addRegion(ElfRegion64(input->bssSize, (const cxbyte*)nullptr,
2235                      input->bssAlignment!=0 ? input->bssAlignment : 8,
2236                      ".hsabss_global_agent", SHT_NOBITS, 0x900003,
2237                      0, 0, Elf64Types::nobase, 0, true));
2238            innerBinSectionTable[ELFSECTID_BSS-ELFSECTID_START] = extraSectionIndex++;
2239        }
2240        if (hasGlobalData)
2241        {// global data section
2242            innerBinGen->addRegion(ElfRegion64(innerGDataGen.size(), &innerGDataGen,
2243                      8, ".hsadata_readonly_agent", SHT_PROGBITS, 0xa00003, 0, 0,
2244                      Elf64Types::nobase));
2245            innerBinSectionTable[ELFSECTID_RODATA-ELFSECTID_START] = extraSectionIndex++;
2246        }
2247        if (kernelsNum != 0)
2248        {
2249            innerBinGen->addRegion(ElfRegion64(innerTextGen.size(), &innerTextGen, 256,
2250                      ".hsatext", SHT_PROGBITS, 0xc00007, 0, 0, 
2251                      Elf64Types::nobase, 0));
2252            innerBinSectionTable[ELFSECTID_TEXT-ELFSECTID_START] = extraSectionIndex++;
2253        }
2254       
2255        if (is16_3Ver)
2256        {   /* new driver version */
2257            innerBinGen->addRegion(ElfRegion64::symtabSection());
2258            innerBinSectionTable[ELFSECTID_SYMTAB-ELFSECTID_START] = extraSectionIndex++;
2259        }
2260       
2261        if (hasSamplers)
2262        {
2263            innerBinGen->addRegion(ElfRegion64(input->samplerConfig ?
2264                    input->samplers.size()*8 : input->samplerInitSize,
2265                    &innerSamplerInitGen, (is16_3Ver) ? 8 : 1,
2266                    ".hsaimage_samplerinit", SHT_PROGBITS, SHF_MERGE, 0, 0, 0, 8));
2267            innerBinSectionTable[AMDCL2SECTID_SAMPLERINIT-ELFSECTID_START] =
2268                        extraSectionIndex++;
2269            innerBinGen->addRegion(ElfRegion64(innerGDataRels.size(), &innerGDataRels,
2270                    8, ".rela.hsadata_readonly_agent", SHT_RELA, 0, symtabId,
2271                    globalDataId, 0, sizeof(Elf64_Rela)));
2272            innerBinSectionTable[AMDCL2SECTID_RODATARELA-ELFSECTID_START] =
2273                        extraSectionIndex++;
2274        }
2275        size_t textRelSize = innerTextRelsGen.size();
2276        if (textRelSize!=0) // if some relocations
2277        {
2278            innerBinGen->addRegion(ElfRegion64(textRelSize, &innerTextRelsGen, 8,
2279                    ".rela.hsatext", SHT_RELA, 0, symtabId, textId,  0,
2280                    sizeof(Elf64_Rela)));
2281            innerBinSectionTable[AMDCL2SECTID_TEXTRELA-ELFSECTID_START] =
2282                    extraSectionIndex++;
2283        }
2284       
2285        if (!is16_3Ver)
2286        {   /* this order of section for 1912.05 driver version */
2287            /* AMD - 1 - 00000001 00000000
2288             * AMD - 2 - 00000001 00000000 00010101
2289             * AMD - 5 - size=0x19 \x16\000-hsa_call_convention=\0\0
2290             * AMD - 3 - size=0x1e, 00070004 major minor stepping AMD\0 AMDGPU\0 00000000
2291             * AMD - 4 - size=8 random values 0x7ffXXXXXXXX
2292             */
2293            innerBinGen->addNote({"AMD", sizeof noteDescType1, noteDescType1, 1U});
2294            innerBinGen->addNote({"AMD", sizeof noteDescType2,
2295                        (input->is64Bit) ? noteDescType2 : noteDescType2_32, 2U});
2296            if (input->is64Bit)
2297                innerBinGen->addNote({"AMD", sizeof noteDescType5, noteDescType5, 5U});
2298            else // 32bit
2299                innerBinGen->addNote({"AMD", sizeof noteDescType5_32bit,
2300                            noteDescType5_32bit, 5U});
2301           
2302            noteBuf.reset(new cxbyte[0x1e]);
2303            ::memcpy(noteBuf.get(), noteDescType3, 0x1e);
2304            SULEV(*(uint32_t*)(noteBuf.get()+4), amdGpuArchValues.major);
2305            SULEV(*(uint32_t*)(noteBuf.get()+8), amdGpuArchValues.minor);
2306            SULEV(*(uint32_t*)(noteBuf.get()+12), amdGpuArchValues.stepping);
2307            innerBinGen->addNote({"AMD", 0x1e, noteBuf.get(), 3U});
2308            if (input->is64Bit)
2309                innerBinGen->addNote({"AMD", sizeof noteDescType4, noteDescType4, 4U});
2310            else // 32-bit
2311                innerBinGen->addNote({"AMD", sizeof noteDescType4_32bit,
2312                            noteDescType4_32bit, 4U});
2313           
2314            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8,
2315                                   ".note", SHT_NOTE, 0));
2316           
2317            innerBinSectionTable[AMDCL2SECTID_NOTE-ELFSECTID_START] = extraSectionIndex++;
2318            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 1, ".strtab",
2319                                  SHT_STRTAB, SHF_STRINGS, 0, 0));
2320            innerBinSectionTable[ELFSECTID_STRTAB-ELFSECTID_START] = extraSectionIndex++;
2321            innerBinGen->addRegion(ElfRegion64::symtabSection());
2322            innerBinSectionTable[ELFSECTID_SYMTAB-ELFSECTID_START] = extraSectionIndex++;
2323            innerBinGen->addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 1, ".shstrtab",
2324                                  SHT_STRTAB, SHF_STRINGS, 0, 0));
2325            innerBinSectionTable[ELFSECTID_SHSTRTAB-ELFSECTID_START] = extraSectionIndex++;
2326        }
2327       
2328        if (kernelsNum != 0)
2329            putInnerSymbols(*innerBinGen, input, tempDatas, innerBinSectionTable,
2330                        extraSectionIndex, symbolNamePool, dataSymbolsNum);
2331       
2332        for (const BinSection& section: input->innerExtraSections)
2333            innerBinGen->addRegion(ElfRegion64(section, innerBinSectionTable,
2334                         AMDCL2SECTID_MAX, extraSectionIndex));
2335        // section table
2336        innerBinGen->addRegion(ElfRegion64::sectionHeaderTable());
2337        /// program headers
2338        if (kernelsNum != 0)
2339        {
2340            cxuint textSectionReg = (is16_3Ver) ? 4 : 1;
2341            if (hasRWData && input->bssSize!=0)
2342            {
2343                innerBinGen->addProgramHeader({ PT_LOOS+1, PF_W|PF_R, textSectionReg, 2,
2344                                true, 0, 0, 0 });
2345                textSectionReg += 2;
2346            }
2347            else if (hasRWData)
2348            {
2349                innerBinGen->addProgramHeader({ PT_LOOS+1, PF_W|PF_R, textSectionReg, 1,
2350                                true, 0, 0, 0 });
2351                textSectionReg++;
2352            }
2353            else if (input->bssSize!=0)
2354            {
2355                innerBinGen->addProgramHeader({ PT_LOOS+1, PF_W|PF_R, textSectionReg, 1,
2356                                true, 0, 0, 0 });
2357                textSectionReg++;
2358            }
2359            if (hasGlobalData)
2360            {   // textSectionReg - now is global data section
2361                innerBinGen->addProgramHeader({ PT_LOOS+2, PF_W|PF_R, textSectionReg, 1,
2362                        true, 0, Elf64Types::nobase
2363                        /*(hasRWData || input->bssSize!=0) ? -0xe8ULL+ : 0*/, 0 });
2364                textSectionReg++; // now is text section index
2365            }
2366            uint32_t phFlags = (is16_3Ver) ? (PF_X|PF_R) : (PF_R|PF_W);
2367            innerBinGen->addProgramHeader({ PT_LOOS+3, phFlags, textSectionReg, 1,
2368                    true, 0, Elf64Types::nobase, 0 });
2369        }
2370    }
2371   
2372    CL2MainTextGen mainTextGen(input, tempDatas, innerBinGen.get());
2373    uint64_t binarySize;
2374    if (input->is64Bit)
2375    {
2376        if (kernelsNum != 0 || newBinaries)
2377            elfBinGen64->addRegion(ElfRegion64(mainTextGen.size(), &mainTextGen,
2378                       1, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR));
2379       
2380        for (const BinSection& section: input->extraSections)
2381            elfBinGen64->addRegion(ElfRegion64(section, mainSectTable,
2382                         ELFSECTID_STD_MAX, mainExtraSectionIndex));
2383        elfBinGen64->addRegion(ElfRegion64::sectionHeaderTable());
2384        binarySize = elfBinGen64->countSize();
2385    }
2386    else
2387    {
2388        if (kernelsNum != 0 || newBinaries)
2389            elfBinGen32->addRegion(ElfRegion32(mainTextGen.size(), &mainTextGen,
2390                       1, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR));
2391       
2392        for (const BinSection& section: input->extraSections)
2393            elfBinGen32->addRegion(ElfRegion32(section, mainSectTable,
2394                         ELFSECTID_STD_MAX, mainExtraSectionIndex));
2395        elfBinGen32->addRegion(ElfRegion32::sectionHeaderTable());
2396        binarySize = elfBinGen32->countSize();
2397    }
2398   
2399    if (
2400#ifdef HAVE_64BIT
2401        !input->is64Bit &&
2402#endif
2403        binarySize > UINT32_MAX)
2404        throw Exception("Binary size is too big!");
2405    /****
2406     * prepare for write binary to output
2407     ****/
2408    std::unique_ptr<std::ostream> outStreamHolder;
2409    std::ostream* os = nullptr;
2410    if (aPtr != nullptr)
2411    {
2412        aPtr->resize(binarySize);
2413        outStreamHolder.reset(
2414            new ArrayOStream(binarySize, reinterpret_cast<char*>(aPtr->data())));
2415        os = outStreamHolder.get();
2416    }
2417    else if (vPtr != nullptr)
2418    {
2419        vPtr->resize(binarySize);
2420        outStreamHolder.reset(new VectorOStream(*vPtr));
2421        os = outStreamHolder.get();
2422    }
2423    else // from argument
2424        os = osPtr;
2425   
2426    const std::ios::iostate oldExceptions = os->exceptions();
2427    FastOutputBuffer fob(256, *os);
2428    try
2429    {
2430        os->exceptions(std::ios::failbit | std::ios::badbit);
2431        if (input->is64Bit)
2432            elfBinGen64->generate(fob);
2433        else
2434            elfBinGen32->generate(fob);
2435    }
2436    catch(...)
2437    {
2438        os->exceptions(oldExceptions);
2439        throw;
2440    }
2441    os->exceptions(oldExceptions);
2442    assert(fob.getWritten() == binarySize);
2443}
2444
2445void AmdCL2GPUBinGenerator::generate(Array<cxbyte>& array) const
2446{
2447    generateInternal(nullptr, nullptr, &array);
2448}
2449
2450void AmdCL2GPUBinGenerator::generate(std::ostream& os) const
2451{
2452    generateInternal(&os, nullptr, nullptr);
2453}
2454
2455void AmdCL2GPUBinGenerator::generate(std::vector<char>& vector) const
2456{
2457    generateInternal(nullptr, &vector, nullptr);
2458}
Note: See TracBrowser for help on using the repository browser.