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

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

CLRadeonExtender: Commenting AmdCL2BinGen and ROCmBinaries.

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