source: CLRX/CLRadeonExtender/trunk/CLRX/amdbin/GalliumBinaries.h @ 3150

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

CLRadeonExtender: CLRX: small typos. GalliumBinary/GalliumDisasm?: Add support new LLVM 3.9.0 (spilledGPR info) and new Mesa3D 17.0.

File size: 15.3 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19/*! \file GalliumBinaries.h
20 * \brief GalliumCompute binaries handling (only with LLVM 3.6)
21 */
22
23#ifndef __CLRX_GALLIUMBINARIES_H__
24#define __CLRX_GALLIUMBINARIES_H__
25
26#include <CLRX/Config.h>
27#include <cstdint>
28#include <string>
29#include <vector>
30#include <ostream>
31#include <utility>
32#include <memory>
33#include <CLRX/amdbin/Elf.h>
34#include <CLRX/amdbin/ElfBinaries.h>
35#include <CLRX/utils/MemAccess.h>
36#include <CLRX/utils/Utilities.h>
37#include <CLRX/utils/GPUId.h>
38#include <CLRX/utils/Containers.h>
39#include <CLRX/utils/InputOutput.h>
40
41/// main namespace
42namespace CLRX
43{
44
45enum : Flags {
46    GALLIUM_INNER_CREATE_SECTIONMAP = 0x10, ///< create map of sections for inner binaries
47    GALLIUM_INNER_CREATE_SYMBOLMAP = 0x20,  ///< create map of kernels for inner binaries
48    /** create map of dynamic kernels for inner binaries */
49    GALLIUM_INNER_CREATE_DYNSYMMAP = 0x40,
50    GALLIUM_INNER_CREATE_PROGINFOMAP = 0x100, ///< create prinfomap for inner binaries
51   
52    GALLIUM_ELF_CREATE_PROGINFOMAP = 0x10,  ///< create elf proginfomap
53   
54    GALLIUM_CREATE_ALL = ELF_CREATE_ALL | 0xfff0, ///< all Gallium binaries flags
55    GALLIUM_INNER_SHIFT = 4 ///< shift for convert inner binary flags into elf binary flags
56};
57
58/// GalliumCompute Kernel Arg type
59enum class GalliumArgType: cxbyte
60{
61    SCALAR = 0, ///< scalar type
62    CONSTANT,   ///< constant pointer
63    GLOBAL,     ///< global pointer
64    LOCAL,      ///< local pointer
65    IMAGE2D_RDONLY, ///< read-only 2d image
66    IMAGE2D_WRONLY, ///< write-only 2d image
67    IMAGE3D_RDONLY, ///< read-only 3d image
68    IMAGE3D_WRONLY, ///< write-only 3d image
69    SAMPLER,    ///< sampler
70    MAX_VALUE = SAMPLER ///< last value
71};
72
73/// Gallium semantic field type
74enum class GalliumArgSemantic: cxbyte
75{
76    GENERAL = 0,    ///< general
77    GRID_DIMENSION,     ///< ???
78    GRID_OFFSET,    ///< ???
79    IMAGE_SIZE,     ///< image size
80    IMAGE_FORMAT,   ///< image format
81    MAX_VALUE = IMAGE_FORMAT ///< last value
82};
83
84/// kernel program info entry for Gallium binaries
85struct GalliumProgInfoEntry
86{
87    uint32_t address;   ///< address
88    uint32_t value;     ///< value
89};
90
91/// kernel argument (Gallium binaries)
92struct GalliumArgInfo
93{
94    GalliumArgType type;    ///< type of argument
95    bool signExtended;  ///< is signed extended
96    GalliumArgSemantic semantic;    ///< semantic of array
97    uint32_t size;  ///< size of argument
98    uint32_t targetSize;    ///< target size
99    uint32_t targetAlign;   ///< target alignment
100};
101
102/// kernel info structure (Gallium binaries)
103struct GalliumKernel
104{
105    CString kernelName;   ///< kernel's name
106    uint32_t sectionId; ///< section id
107    uint32_t offset;    ///< offset in ElfBinary
108    Array<GalliumArgInfo> argInfos;   ///< arguments
109};
110
111/// Gallium format section type
112enum class GalliumSectionType: cxbyte
113{
114    TEXT = 0,   ///< section for text (binary code)
115    DATA_CONSTANT,  ///< constant data (???)
116    DATA_GLOBAL,    ///< global data (???)
117    DATA_LOCAL,     ///< local data (???)
118    DATA_PRIVATE,   ///< private data (???)
119    TEXT_INTERMEDIATE_170 = 0,
120    TEXT_LIBRARY_170,
121    TEXT_EXECUTABLE_170,
122    DATA_CONSTANT_170,
123    DATA_GLOBAL_170,
124    DATA_LOCAL_170,
125    DATA_PRIVATE_170,
126    MAX_VALUE = DATA_PRIVATE_170    ///< last value
127};
128
129/// Gallium binarie's Section
130struct GalliumSection
131{
132    uint32_t sectionId; ///< section id
133    GalliumSectionType type;    ///< type of section
134    uint32_t offset;    ///< offset in binary
135    uint32_t size;      ///< size of section
136};
137
138/// Gallium elf binary base (for 32-bit and 64-bit)
139class GalliumElfBinaryBase
140{
141public:
142    /// program info entry index map
143    typedef Array<std::pair<const char*, size_t> > ProgInfoEntryIndexMap;
144protected:
145    uint32_t progInfosNum;  ///< program info entries number
146    GalliumProgInfoEntry* progInfoEntries;  ///< program info entries
147    ProgInfoEntryIndexMap progInfoEntryMap; ///< program info map
148    size_t disasmSize;  ///< disassembly size
149    size_t disasmOffset;    ///< disassembly offset
150    bool llvm390;
151   
152    /// routine to load binary fro internal ELF
153    template<typename ElfBinary>
154    void loadFromElf(ElfBinary& elfBinary, size_t kernelsNum);
155public:
156    /// empty constructor
157    GalliumElfBinaryBase();
158    /// destructor
159    virtual ~GalliumElfBinaryBase();
160   
161    /// returns program infos number
162    uint32_t getProgramInfosNum() const
163    { return progInfosNum; }
164   
165    /// returns number of program info entries for program info
166    uint32_t getProgramInfoEntriesNum(uint32_t index) const;
167   
168    /// returns index for programinfo entries index for specified kernel name
169    uint32_t getProgramInfoEntryIndex(const char* name) const;
170   
171    /// returns program info entries for specified kernel name
172    const GalliumProgInfoEntry* getProgramInfo(const char* name) const
173    { return reinterpret_cast<GalliumProgInfoEntry*>(progInfoEntries) +
174        getProgramInfoEntryIndex(name); }
175   
176    /// returns program info entries for specified kernel name
177    GalliumProgInfoEntry* getProgramInfo(const char* name)
178    { return reinterpret_cast<GalliumProgInfoEntry*>(progInfoEntries) +
179        getProgramInfoEntryIndex(name); }
180   
181    /// returns program info entries for specified kernel index
182    const GalliumProgInfoEntry* getProgramInfo(uint32_t index) const;
183    /// returns program info entries for specified kernel index
184    GalliumProgInfoEntry* getProgramInfo(uint32_t index);
185   
186    /// returns true if disassembly available
187    bool hasDisassembly() const
188    { return disasmOffset != 0; }
189   
190    /// returns size of disassembly
191    size_t getDisassemblySize() const
192    { return disasmSize; }
193   
194    bool isLLVM390() const
195    { return llvm390; }
196};
197
198/* INFO: in this file is used ULEV function for conversion
199 * from LittleEndian and unaligned access to other memory access policy and endianness
200 * Please use this function whenever you want to get or set word in ELF binary,
201 * because ELF binaries can be unaligned in memory (as inner binaries).
202 */
203/// 32-bit Gallium ELF binary
204/** ULEV function is required to access programInfoEntry fields */
205class GalliumElfBinary32: public GalliumElfBinaryBase, public ElfBinary32
206{
207public:
208    /// empty constructor
209    GalliumElfBinary32();
210    /// constructor
211    GalliumElfBinary32(size_t binaryCodeSize, cxbyte* binaryCode, Flags creationFlags,
212            size_t kernelsNum);
213    /// destructor
214    virtual ~GalliumElfBinary32();
215   
216    /// return true if binary has program info map
217    bool hasProgInfoMap() const
218    { return (creationFlags & GALLIUM_ELF_CREATE_PROGINFOMAP) != 0; }
219   
220    /// return disassembly content (without null-character)
221    const char* getDisassembly() const
222    { return reinterpret_cast<const char*>(binaryCode + disasmOffset); }
223};
224
225/// 64-bit Gallium ELF binary
226class GalliumElfBinary64: public GalliumElfBinaryBase, public ElfBinary64
227{
228public:
229    /// empty constructor
230    GalliumElfBinary64();
231    /// constructor
232    GalliumElfBinary64(size_t binaryCodeSize, cxbyte* binaryCode, Flags creationFlags,
233            size_t kernelsNum);
234    /// destructor
235    virtual ~GalliumElfBinary64();
236   
237    /// return true if binary has program info map
238    bool hasProgInfoMap() const
239    { return (creationFlags & GALLIUM_ELF_CREATE_PROGINFOMAP) != 0; }
240   
241    /// return disassembly content (without null-character)
242    const char* getDisassembly() const
243    { return reinterpret_cast<const char*>(binaryCode + disasmOffset); }
244};
245
246/** GalliumBinary object. This object converts to host-endian fields and
247  * ULEV is not needed to access to fields of kernels and sections */
248class GalliumBinary: public NonCopyableAndNonMovable
249{
250private:
251    Flags creationFlags;
252    size_t binaryCodeSize;
253    cxbyte* binaryCode;
254    uint32_t kernelsNum;
255    uint32_t sectionsNum;
256    std::unique_ptr<GalliumKernel[]> kernels;
257    std::unique_ptr<GalliumSection[]> sections;
258   
259    bool elf64BitBinary;
260    std::unique_ptr<GalliumElfBinaryBase> elfBinary;
261    bool mesa170;
262   
263public:
264    /// constructor
265    GalliumBinary(size_t binaryCodeSize, cxbyte* binaryCode, Flags creationFlags);
266    /// destructor
267    ~GalliumBinary() = default;
268   
269    /// get creation flags
270    Flags getCreationFlags()
271    { return creationFlags; }
272   
273    /// get size of binaries
274    size_t getSize() const
275    { return binaryCodeSize; }
276   
277    /// returns true if object is initialized
278    operator bool() const
279    { return binaryCode!=nullptr; }
280   
281    /// returns true if object is uninitialized
282    bool operator!() const
283    { return binaryCode==nullptr; }
284   
285    /// returns binary code data
286    const cxbyte* getBinaryCode() const
287    { return binaryCode; }
288   
289    /// returns binary code data
290    cxbyte* getBinaryCode()
291    { return binaryCode; }
292    /// return true if inner binary is 64-bit
293    bool is64BitElfBinary() const
294    { return elf64BitBinary; }
295   
296    /// returns Gallium inner ELF 32-bit binary
297    GalliumElfBinary32& getElfBinary32()
298    { return *static_cast<GalliumElfBinary32*>(elfBinary.get()); }
299   
300    /// returns Gallium inner ELF 32-bit binary
301    const GalliumElfBinary32& getElfBinary32() const
302    { return *static_cast<const GalliumElfBinary32*>(elfBinary.get()); }
303   
304    /// returns Gallium inner ELF 64-bit binary
305    GalliumElfBinary64& getElfBinary64()
306    { return *static_cast<GalliumElfBinary64*>(elfBinary.get()); }
307   
308    /// returns Gallium inner ELF 64-bit binary
309    const GalliumElfBinary64& getElfBinary64() const
310    { return *static_cast<const GalliumElfBinary64*>(elfBinary.get()); }
311   
312    /// get sections number
313    uint32_t getSectionsNum() const
314    { return sectionsNum; }
315   
316    /// get size of section with specified index
317    uint32_t getSectionSize(uint32_t index) const
318    { return sections[index].size; }
319   
320    /// get content for section with specified index
321    const cxbyte* getSectionContent(uint32_t index) const
322    { return binaryCode + sections[index].offset; }
323   
324    /// get content for section with specified index
325    cxbyte* getSectionContent(uint32_t index)
326    { return binaryCode + sections[index].offset; }
327   
328    /// get section with specified index
329    const GalliumSection& getSection(uint32_t index) const
330    { return sections[index]; }
331   
332    /// returns kernels number
333    uint32_t getKernelsNum() const
334    { return kernelsNum;; }
335   
336    /// returns kernel index
337    uint32_t getKernelIndex(const char* name) const;
338   
339    /// get kernel by index
340    const GalliumKernel& getKernel(uint32_t index) const
341    { return kernels[index]; }
342   
343    /// get kernel with speciified name
344    const GalliumKernel& getKernel(const char* name) const
345    { return kernels[getKernelIndex(name)]; }
346   
347    bool isMesa170() const
348    { return mesa170; };
349};
350
351enum: cxuint {
352    GALLIUMSECTID_GPUCONFIG = ELFSECTID_OTHER_BUILTIN,
353    GALLIUMSECTID_NOTEGNUSTACK,
354    GALLIUMSECTID_MAX = GALLIUMSECTID_NOTEGNUSTACK
355};
356
357/*
358 * Gallium Binary generator
359 */
360
361/// kernel config
362struct GalliumKernelConfig
363{
364    cxuint dimMask;    ///< mask of dimension (bits: 0 - X, 1 - Y, 2 - Z)
365    cxuint usedVGPRsNum;  ///< number of used VGPRs
366    cxuint usedSGPRsNum;  ///< number of used SGPRs
367    uint32_t pgmRSRC1;      ///< pgmRSRC1 register value
368    uint32_t pgmRSRC2;      ///< pgmRSRC2 register value
369    cxbyte userDataNum;   ///< number of user data
370    bool ieeeMode;  ///< IEEE mode
371    cxbyte floatMode; ///< float mode
372    cxbyte priority;    ///< priority
373    cxbyte exceptions;      ///< enabled exceptions
374    bool tgSize;        ///< enable TG_SIZE_EN bit
375    bool debugMode;     ///< debug mode
376    bool privilegedMode;   ///< prvileged mode
377    bool dx10Clamp;     ///< DX10 CLAMP mode
378    size_t localSize; ///< used local size (not local defined in kernel arguments)
379    uint32_t scratchBufferSize; ///< size of scratch buffer
380    cxuint spilledVGPRs;
381    cxuint spilledSGPRs;
382};
383
384/// kernel info structure (Gallium binaries)
385struct GalliumKernelInput
386{
387    CString kernelName;   ///< kernel's name
388    GalliumProgInfoEntry progInfo[3];   ///< program info for kernel
389    bool useConfig;         ///< true if configuration has been used to generate binary
390    GalliumKernelConfig config; ///< kernel's configuration
391    uint32_t offset;    ///< offset of kernel code
392    std::vector<GalliumArgInfo> argInfos;   ///< arguments
393};
394
395/// Gallium input
396struct GalliumInput
397{
398    bool is64BitElf;   ///< is 64-bit elf binary
399    GPUDeviceType deviceType;   ///< GPU device type
400    size_t globalDataSize;  ///< global constant data size
401    const cxbyte* globalData;   ///< global constant data
402    std::vector<GalliumKernelInput> kernels;    ///< input kernel list
403    size_t codeSize;        ///< code size
404    const cxbyte* code;     ///< code
405    size_t commentSize; ///< comment size (can be null)
406    const char* comment; ///< comment
407    std::vector<BinSection> extraSections;  ///< extra sections
408    std::vector<BinSymbol> extraSymbols;    ///< extra symbols
409   
410    /// add empty kernel with default values
411    void addEmptyKernel(const char* kernelName);
412};
413
414/// gallium code binary generator
415class GalliumBinGenerator: public NonCopyableAndNonMovable
416{
417private:
418    bool manageable;
419    const GalliumInput* input;
420   
421    void generateInternal(std::ostream* osPtr, std::vector<char>* vPtr,
422             Array<cxbyte>* aPtr) const;
423public:
424    GalliumBinGenerator();
425    /// constructor with gallium input
426    GalliumBinGenerator(const GalliumInput* galliumInput);
427   
428    /// constructor
429    /**
430     * \param _64bitMode 64-bit elf binary
431     * \param deviceType device type
432     * \param codeSize size of code
433     * \param code code pointer
434     * \param globalDataSize global data size
435     * \param globalData global data pointer
436     * \param kernels vector of kernels
437     */
438    GalliumBinGenerator(bool _64bitMode, GPUDeviceType deviceType, size_t codeSize,
439            const cxbyte* code, size_t globalDataSize, const cxbyte* globalData,
440            const std::vector<GalliumKernelInput>& kernels);
441    /// constructor
442    GalliumBinGenerator(bool _64bitMode, GPUDeviceType deviceType, size_t codeSize,
443            const cxbyte* code, size_t globalDataSize, const cxbyte* globalData,
444            std::vector<GalliumKernelInput>&& kernels);
445    ~GalliumBinGenerator();
446   
447    /// get input
448    const GalliumInput* getInput() const
449    { return input; }
450   
451    /// set input
452    void setInput(const GalliumInput* input);
453   
454    /// generates binary to array of bytes
455    void generate(Array<cxbyte>& array) const;
456   
457    /// generates binary to output stream
458    void generate(std::ostream& os) const;
459   
460    /// generates binary to vector of char
461    void generate(std::vector<char>& vector) const;
462};
463
464};
465
466#endif
Note: See TracBrowser for help on using the repository browser.