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

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

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

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