File: ZEELFObjectBuilder.hpp

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (541 lines) | stat: -rw-r--r-- 22,484 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
/*========================== begin_copyright_notice ============================

Copyright (C) 2020-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

//===- ZEELFObjectBuilder.hpp -----------------------------------*- C++ -*-===//
// ZE Binary Utilities
//
// \file
// This file declares ZEELFObjectBuilder for building an ZE Binary object
//===----------------------------------------------------------------------===//

#ifndef ZE_ELF_OBJECT_BUILDER_HPP
#define ZE_ELF_OBJECT_BUILDER_HPP

#include <ZEELF.h>
#include <ZEInfo.hpp>
#include "inc/common/igfxfmid.h"

#ifndef ZEBinStandAloneBuild
#include "common/LLVMWarningsPush.hpp"
#endif

#include "llvm/BinaryFormat/ELF.h"

#ifndef ZEBinStandAloneBuild
#include "common/LLVMWarningsPop.hpp"
#endif

#include <map>
#include <memory>
#include <string>
#include <vector>

namespace llvm {
    class raw_pwrite_stream;
}

namespace zebin {

/// ZEELFObjectBuilder - Build an ELF Object for ZE binary format
class ZEELFObjectBuilder {
    friend class ELFWriter;
public:
    // The valid SectionID must be 0 or positive value
    typedef int32_t SectionID;

public:
    ZEELFObjectBuilder(bool is64Bit) : m_is64Bit(is64Bit)
    {
        m_metadata.packed = 0;
    }

    ~ZEELFObjectBuilder() {}

    void setProductFamily(PRODUCT_FAMILY family) { m_productFamily = family; }
    PRODUCT_FAMILY getProductFamily() const { return m_productFamily; }

    void setGfxCoreFamily(GFXCORE_FAMILY family) { m_gfxCoreFamily = family; }
    GFXCORE_FAMILY getGfxCoreFamily() const { return m_gfxCoreFamily; }

    void setTargetMetadata(TargetMetadata metadata) { m_metadata = metadata; }
    TargetMetadata getTargetMetadata() const { return m_metadata; }

    // add a text section contains gen binary
    // - name: section name. This is usually the kernel or function name of
    //         this text section. Do not includes leading .text in given
    //         name. For example, giving "kernel", the section name will be
    //         .text.kernel
    // - data: memory buffer of the section contents. This buffer must be live
    //         through this ZEELFObjectBuilder
    // - size: input buffer size in byte
    // - padding: required padding at the end
    // - align: alignment requirement in byte
    // - return a unique id for referencing in addSymbol
    // Currently we assume there is only one text section that'll be added
    SectionID addSectionText(
        std::string name, const uint8_t* data, uint64_t size, uint32_t padding, uint32_t align);

    // add a data section contains raw data, such as constant or global buffer.
    // - name: section name. Do not includes leading .data in given
    //         name. For example, giving "const", the section name will be
    //         .data.const
    // - data: memory buffer of the section contents. This buffer must be live through
    //         this ZEELFObjectBuilder
    // - size: input buffer size in byte
    // - padding: required padding at the end
    // - align: alignment requirement in byte
    // - return a unique id for referencing in addSymbol
    SectionID addSectionData(
        std::string name, const uint8_t* data, uint64_t size, uint32_t padding = 0, uint32_t align = 0, bool rodata = false);

    // add a bss section which occupies no space in the ELF, but with size and other section information
    // The bss sections could be used for zero-initialized variables.
    // - name: section name. Do not includes leading .bss in given name.
    //         For example, giving "const", the section name will be .bss.const
    // - size: input buffer size in byte
    // - padding: required padding at the end
    // - align: alignment requirement in byte
    // - return a unique id for referencing in addSymbol
    SectionID addSectionBss(
        std::string name, uint64_t size, uint32_t padding = 0, uint32_t align = 0);

    // add a spv section contains the spv source. This section will be set to SHT_ZEBIN_SPIRV type
    // - name: section name. The default name is .spv
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through
    //   ZEELFObjectBuilder
    void addSectionSpirv(std::string name, const uint8_t* data, uint64_t size);

    // add .gtpin_info section
    // - name: section name. Do not includes leading .gtpin_info in the given
    //         name. For example, giving "func", the section name will be
    //         ".gtpin_info.func". The default name is .gtpin_fino. It'll be apply
    //         if the given name is empty.
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through
    //   ZEELFObjectBuilder
    void addSectionGTPinInfo(std::string name, const uint8_t* data, uint64_t size);

    // add .visaasm section
    // - name: section name. Do not includes leading .visaasm in the given
    //         name. For example, giving "func", the section name will be
    //         ".visaasm.func". The default name is .visaasm. It'll be apply
    //         if the given name is empty.
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through ZEELFObjectBuilder
    void addSectionVISAAsm(std::string name, const uint8_t* data, uint64_t size);

    // add .misc section
    // - name: section name. Do not includes leading .misc in the given
    //         name. For example, giving "func", the section name will be
    //         ".misc.func". The default name is .misc. It'll be apply
    //         if the given name is empty.
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through ZEELFObjectBuilder
    void addSectionMisc(std::string name, const uint8_t* data, uint64_t size);

    // add .note.intelgt.metrics section
    // - name: .note.intelgt.metrics. Do not includes leading .note.intelgt.metrics
    //         in the given name. For example, giving "func", the section name will be
    //         ".note.intelgt.metrics.func". The default name is .note.intelgt.metrics.
    //         It'll be applied if the given name is empty.
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through ZEELFObjectBuilder
    void addSectionMetrics(std::string name, const uint8_t* data, uint64_t size);

    // .debug_info section in DWARF format
    // - name: section name. The default name is .debug_info
    // - size in byte
    // - Note that the alignment requirement of the section should be satisfied
    //   by the given data and size
    // - Note that the given data buffer have to be alive through
    //   ZEELFObjectBuilder
    // - return a unique id for referencing in addSymbol
    SectionID addSectionDebug(std::string name, const uint8_t* data, uint64_t size);

    // add ze_info section
    void addSectionZEInfo(zeInfoContainer& zeInfo);

    // add a symbol
    // - name    : symbol's name
    // - addr    : symbol's address. The binary offset of where this symbol is
    //             defined in the section
    // - size    : symbol size
    // - binding : symbol binding. The value is defined in ELF standard ST_BIND
    // - type    : symbol type. The value is defined in ELF standard ST_TYPE
    // - sectionId : the section id of which this symbol is defined in. Giving
    //               -1 if this is an UNDEFINED symbol
    void addSymbol(std::string name, uint64_t addr, uint64_t size,
        uint8_t binding, uint8_t type, SectionID sectionId);

    // add a relocation with rel format
    // This function will create a corresponding .rel.{targetSectionName} section if
    // not exist
    // - offset    : the binary offset of the section where the relocation
    //               will apply to. The section is denoted by sectionId
    // - symName   : the target symbol's name
    // - type      : the relocation name
    // - sectionId : the section id where the relocation is apply to
    void addRelRelocation(
        uint64_t offset, std::string symName, R_TYPE_ZEBIN type, SectionID sectionId);

    // add a relocation with rela format
    // This function will create a corresponding .rela.{targetSectionName} section if
    // not exist
    // - offset    : the binary offset of the section where the relocation
    //               will apply to. The section is denoted by sectionId
    // - symName   : the target symbol's name
    // - type      : the relocation name
    // - addend    : the addend value
    // - sectionId : the section id where the relocation is apply to
    void addRelaRelocation(
        uint64_t offset, std::string symName, R_TYPE_ZEBIN type, uint64_t addend, SectionID sectionId);

    // finalize - Finalize the ELF Object, write ELF file into given os
    // return number of written bytes
    uint64_t finalize(llvm::raw_pwrite_stream& os);

    // get an ID of a section
    // - name  : section name
    SectionID getSectionIDBySectionName(const char* name);

private:
    class Section {
    public:
        enum Kind {STANDARD, RELOC, ZEINFO};
        virtual Kind getKind() const = 0;

        SectionID id() const { return m_id; }

    protected:
        Section(uint32_t id) : m_id(id) {}
        virtual ~Section() {}
        Section(const Section&) = default;
        Section& operator=(const Section&) = default;

    protected:
        SectionID m_id;
    };

    class StandardSection : public Section {
    public:
        StandardSection(std::string sectName, const uint8_t* data, uint64_t size,
            unsigned type, unsigned flags, uint32_t padding, uint32_t id)
            : Section(id), m_sectName(sectName), m_data(data), m_size(size), m_type(type),
              m_flags(flags), m_padding(padding)
        {}

        Kind getKind() const { return STANDARD; }

        // m_sectName - the final name presented in ELF section header
        // This field is required as the place holder for StringTable construction
        std::string m_sectName;
        const uint8_t* m_data;
        uint64_t m_size;
        // section type
        unsigned m_type;
        unsigned m_flags = 0;
        uint32_t m_padding;
    };

    class ZEInfoSection : public Section {
    public:
        ZEInfoSection(zeInfoContainer& zeinfo, uint32_t id)
            : Section(id), m_zeinfo(zeinfo)
        {}

        Kind getKind() const { return ZEINFO; }

        zeInfoContainer& getZeInfo()
        { return m_zeinfo; }

    private:
        zeInfoContainer& m_zeinfo;
    };

    class Symbol {
    public:
        Symbol(std::string name, uint64_t addr, uint64_t size, uint8_t binding,
            uint8_t type, SectionID sectionId)
            : m_name(name), m_addr(addr), m_size(size), m_binding(binding),
            m_type(type), m_sectionId(sectionId)
        {}

        std::string& name()            { return m_name;      }
        uint64_t     addr()      const { return m_addr;      }
        uint64_t     size()      const { return m_size;      }
        uint8_t      binding()   const { return m_binding;   }
        uint8_t      type()      const { return m_type;      }
        SectionID    sectionId() const { return m_sectionId; }

    private:
        std::string m_name;
        uint64_t m_addr;
        uint64_t m_size;
        uint8_t m_binding;
        uint8_t m_type;
        SectionID m_sectionId;
    };

    /// Relocation - present the relocation information of each entry.
    /// The relocation itself doesn't know if it's in rel or rela format.
    /// It's rel or rela depends on it's in RelocSection or RelaRelocSection
    class Relocation {
    public:
        Relocation(uint64_t offset, std::string symName, R_TYPE_ZEBIN type, uint64_t addend = 0)
            : m_offset(offset), m_symName(symName), m_type(type), m_addend(addend)
        {}

        uint64_t            offset()  const { return m_offset;  }
        const std::string&  symName() const { return m_symName; }
        R_TYPE_ZEBIN        type()    const { return m_type;    }
        uint64_t            addend()  const { return m_addend;  }

    private:
        uint64_t m_offset;
        std::string m_symName;
        R_TYPE_ZEBIN m_type;
        uint64_t m_addend;
    };

    typedef std::vector<StandardSection> StandardSectionListTy;
    typedef std::vector<Symbol> SymbolListTy;
    typedef std::vector<Relocation> RelocationListTy;

    class RelocSection : public Section {
    public:
        RelocSection(SectionID myID, SectionID targetID, std::string sectName, bool isRelFormat) :
            Section(myID), m_TargetID(targetID), m_sectName(sectName), m_isRelFormat (isRelFormat)
        {}

        Kind getKind() const { return RELOC; }
        bool isRelFormat() const { return m_isRelFormat; }

    public:
        // target section's id that this relocation section apply to
        SectionID m_TargetID;
        std::string m_sectName;
        RelocationListTy m_Relocations;

        // This is a rel or rela relocation format
        bool m_isRelFormat;
    };
    typedef std::vector<RelocSection> RelocSectionListTy;

private:
    Section& addStandardSection(
        std::string sectName, const uint8_t* data, uint64_t size, unsigned type,
        unsigned flags, uint32_t padding, uint32_t align, StandardSectionListTy& sections);

    // isRelFormat - rel or rela relocation format
    RelocSection& getOrCreateRelocSection(SectionID targetSectId, bool isRelFormat);

    std::string getSectionNameBySectionID(SectionID id);

private:
    // place holder for section default name
    const std::string m_TextName        = ".text";
    const std::string m_DataName        = ".data";
    const std::string m_BssName         = ".bss";
    const std::string m_SymTabName      = ".symtab";
    const std::string m_RelName         = ".rel";
    const std::string m_RelaName        = ".rela";
    const std::string m_SpvName         = ".spv";
    const std::string m_VISAAsmName     = ".visaasm";
    const std::string m_DebugName       = ".debug_info";
    const std::string m_ZEInfoName      = ".ze_info";
    const std::string m_GTPinInfoName   = ".gtpin_info";
    const std::string m_MiscName        = ".misc";
    const std::string m_CompatNoteName  = ".note.intelgt.compat";
    const std::string m_MetricsNoteName = ".note.intelgt.metrics";
    const std::string m_StrTabName      = ".strtab";

private:
    // 32 or 64 bit object
    bool m_is64Bit;

    // information used to generate .note.intelgt.compat
    PRODUCT_FAMILY m_productFamily = IGFX_UNKNOWN;
    GFXCORE_FAMILY m_gfxCoreFamily = IGFX_UNKNOWN_CORE;
    TargetMetadata m_metadata;

    StandardSectionListTy m_textSections;
    StandardSectionListTy m_dataAndbssSections; // data and bss sections
    StandardSectionListTy m_otherStdSections;
    RelocSectionListTy    m_relocSections; // rel and rela reloc sections

    // current section id
    SectionID m_sectionIdCount = 0;

    // every ze object contains at most one ze_info section
    std::unique_ptr<ZEInfoSection> m_zeInfoSection;
    SymbolListTy m_localSymbols;
    SymbolListTy m_globalSymbols;

};

/// ZEInfoBuilder - Build a zeInfoContainer for .ze_info section
class ZEInfoBuilder {
public:
    ZEInfoBuilder()
    {
        mContainer.version = PreDefinedAttrGetter::getVersionNumber();
    }

    zeInfoContainer& getZEInfoContainer()             { return mContainer; }
    const zeInfoContainer& getZEInfoContainer() const { return mContainer; }

    // empty - return true if there is no kernel/function info in it
    bool empty() const;

    /// --------- Helper functions for setup zeinfo contents -------------- ///
    // createKernel - create a zeInfoKernel and add it into zeInfoContainer
    zeInfoKernel& createKernel(const std::string& name);

    // createFunction - create a zeInfoFunction and add it into zeInfoContainer
    zeInfoFunction& createFunction(const std::string& name);

    // createKernelMiscInfo - create a zeKernelMiscInfo and add it into zeInfoContainer
    zeInfoKernelMiscInfo& createKernelMiscInfo(const std::string& name);

    // addGlobalHostAccessSymbol - create a zeInfo global_host_access_table section
    // which is used by Runtime to identify a global variable based on host name
    void addGlobalHostAccessSymbol(const std::string& device_name, const std::string& host_name);

    // addPayloadArgumentByPointer - add explicit kernel argument with pointer
    // type into given arg_list
    static zeInfoPayloadArgument& addPayloadArgumentByPointer(
        PayloadArgumentsTy& arg_list,
        int32_t offset,
        int32_t size,
        int32_t arg_index,
        PreDefinedAttrGetter::ArgAddrMode addrmode,
        PreDefinedAttrGetter::ArgAddrSpace addrspace,
        PreDefinedAttrGetter::ArgAccessType access_type,
        int32_t alignment = 0);

    // addPayloadArgumentByValue - add explicit kernel argument with pass by
    // value type into given arg_list
    static zeInfoPayloadArgument& addPayloadArgumentByValue(
        PayloadArgumentsTy& arg_list,
        int32_t offset,
        int32_t size,
        int32_t arg_index,
        int32_t source_offset);

    // addPayloadArgumentImage - add explicit kernel argument for image
    // into given arg_list
    // The argument type will be set to by_pointer, and addr_space will be set to image
    static zeInfoPayloadArgument& addPayloadArgumentImage(
        PayloadArgumentsTy& arg_list,
        int32_t offset,
        int32_t size,
        int32_t arg_index,
        PreDefinedAttrGetter::ArgAddrMode addrmode,
        PreDefinedAttrGetter::ArgAccessType access_type,
        PreDefinedAttrGetter::ArgImageType image_type);

    // addPayloadArgumentSampler - add explicit kernel argument for sampler
    // into given arg_list
    // The argument type will be set to by_pointer, and addr_space will be set to sampler
    static zeInfoPayloadArgument& addPayloadArgumentSampler(
        PayloadArgumentsTy& arg_list,
        int32_t offset,
        int32_t size,
        int32_t arg_index,
        int32_t sampler_index,
        PreDefinedAttrGetter::ArgAddrMode addrmode,
        PreDefinedAttrGetter::ArgAccessType access_type,
        PreDefinedAttrGetter::ArgSamplerType sampler_type);

    // addInlineSampler - add inline sampler into given inline_sampler_list.
    static zeInfoInlineSampler& addInlineSampler(
        InlineSamplersTy& inline_sampler_list,
        int32_t sampler_index,
        PreDefinedAttrGetter::ArgSamplerAddrMode addr_mode,
        PreDefinedAttrGetter::ArgSamplerFilterMode filter_mode,
        bool normalized);

    // addPayloadArgumentImplicit - add non-user argument (implicit argument)
    // into given arg_list. The type must be local_size, group_size,
    // global_id_offset or private_base_stateless
    static zeInfoPayloadArgument& addPayloadArgumentImplicit(
        PayloadArgumentsTy& arg_list,
        PreDefinedAttrGetter::ArgType type,
        int32_t offset,
        int32_t size);

    // addPerThreadPayloadArgument - add a per-thread payload argument into
    // arg_list. Currently we only support local id as per-thread argument.
    // The given type must be packed_local_ids or local_id
    static zeInfoPerThreadPayloadArgument& addPerThreadPayloadArgument(
        PerThreadPayloadArgumentsTy& arg_list,
        PreDefinedAttrGetter::ArgType type,
        int32_t offset,
        int32_t size);

    // addBindingTableIndex - add a binding table index into given bti_list, with
    // corresponding kernel argument index
    static zeInfoBindingTableIndex& addBindingTableIndex(
        BindingTableIndicesTy& bti_list,
        int32_t bti_value,
        int32_t arg_index);

    // addPerThreadMemoryBuffer - add a memory buffer info with global or slm type
    // If adding buffer with "global" type, this API assume it is allocated per-hardware-thread
    // Use below addPerSIMTThreadGlobalMemoryBuffer API if attempting to add per-simt-thread global buffer
    static zeInfoPerThreadMemoryBuffer& addPerThreadMemoryBuffer(
        PerThreadMemoryBuffersTy& mem_buff_list,
        PreDefinedAttrGetter::MemBufferType type,
        PreDefinedAttrGetter::MemBufferUsage usage,
        int32_t size);

    // addScratchPerThreadMemoryBuffer - add a memory buffer info for scratch buffer
    // per_thread_memory_buffers::type set to scratch
    static zeInfoPerThreadMemoryBuffer& addScratchPerThreadMemoryBuffer(
        PerThreadMemoryBuffersTy& mem_buff_list,
        PreDefinedAttrGetter::MemBufferUsage usage,
        int32_t slot_id,
        int32_t size);

    // addPerSIMTThreadGlobalMemoryBuffer - add a memory buffer info
    // for global memory buffer with
    // per_thread_memory_buffers::type set to global
    // per_thread_memory_buffers::is_simt_thread set to true
    // Use addPerThreadMemoryBuffer if adding per-hardware-thread global memory buffer
    static zeInfoPerThreadMemoryBuffer& addPerSIMTThreadGlobalMemoryBuffer(
        PerThreadMemoryBuffersTy& mem_buff_list,
        PreDefinedAttrGetter::MemBufferUsage usage,
        int32_t size);

    // addExpPropertiesHasNonKernelArgLdSt - add experimental_properties for has-non-kernel-arg-load-store analysis
    // add experimental_properties::has_non_kernel_arg_load, experimental_properties::has_non_kernel_arg_store
    // and experimental_properties::has_non_kernel_arg_atomic
    // Note that zeInfoExperimentalProperties is made as a vector under kernel in the spec, because we want it only
    // present when needed. If it's not a vector, the attribute name will always present in final output even if
    // all of its sub-attributes are default and are not shown.
    static void addExpPropertiesHasNonKernelArgLdSt(zeInfoKernel& zekernel,
        bool hasNonKernelArgLoad, bool hasNonKernelArgStore, bool hasNonKernelArgAtomic);

private:
    zeInfoContainer mContainer;
};

} // end namespace zebin

#endif // ZE_ELF_OBJECT_BUILDER_HPP