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

Last change on this file since 3327 was 3327, checked in by matszpk, 16 months ago

CLRadeonExtender: AmdCL2BinGen: Change type and fields in reserved Xgprs (setup data).

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