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

Last change on this file since 3575 was 3575, checked in by matszpk, 2 years ago

CLRadeonExtender: Change Copyright dates.

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