1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2020-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include <vector>
12 #include <ZEELFObjectBuilder.hpp>
13 #include "sp_g8.h"
14 #include "llvm/BinaryFormat/ELF.h"
15 #include "CLElfLib/ElfReader.h"
16 
17 namespace IGC
18 {
19     struct SOpenCLKernelInfo;
20     struct SOpenCLProgramInfo;
21     class CBTILayout;
22     class OpenCLProgramContext;
23 }
24 
25 namespace vISA
26 {
27     struct ZESymEntry;
28 }
29 
30 namespace iOpenCL
31 {
32 
33 /// ZEBinaryBuilder - Provides services to create a ZE Binary from given
34 /// SProgramOutput information
35 class ZEBinaryBuilder : DisallowCopy
36 {
37 public:
38     // Setup ZEBin platform, and ELF header information. The program scope information
39     // is also be parsed from SOpenCLProgramInfo in the constructor
40     ZEBinaryBuilder(const PLATFORM plat, bool is64BitPointer,
41         const IGC::SOpenCLProgramInfo& programInfo, const uint8_t* spvData, uint32_t spvSize);
42 
43     // Set the ProductFamily as the specified value.
44     void setProductFamily(PRODUCT_FAMILY value);
45 
46     // Set the GfxCoreFamily as the specified value.
47     void setGfxCoreFamily(GFXCORE_FAMILY value);
48 
49     /// add kernel information. Also create kernel metadata information for .ze_info
50     /// This function can be called several times for adding different kernel information
51     /// into this ZEObject
52     /// The given rawIsaBinary must be lived through the entire ZEBinaryBuilder life
53     void createKernel(
54         const char*  rawIsaBinary,
55         unsigned int rawIsaBinarySize,
56         const IGC::SOpenCLKernelInfo& annotations,
57         const uint32_t grfSize,
58         const IGC::CBTILayout& layout,
59         const std::string& visaasm,
60         bool isProgramDebuggable);
61 
62     // getElfSymbol - find a symbol name in ELF binary and return a symbol entry
63     // that will later be transformed to ZE binary format
64     void getElfSymbol(CLElfLib::CElfReader* elfReader, const unsigned int symtabIdx, llvm::ELF::Elf64_Sym& symtabEntry,
65         char*& symName);
66 
67     /// addElfSections - copy every section of ELF file (a buffer in memory) to zeBinary
68     void addElfSections(void* elfBin, size_t elfSize);
69 
70     /// getBinaryObject - get the final ze object
71     void getBinaryObject(llvm::raw_pwrite_stream& os);
72 
73     // getBinaryObject - write the final object into given Util::BinaryStream
74     // Avoid using this function, which has extra buffer copy
75     void getBinaryObject(Util::BinaryStream& outputStream);
76 
77     void printBinaryObject(const std::string& filename);
78 
79 private:
80     /// ------------ program scope helper functions ------------
81     /// add program scope information. This function will be called in the ctor.
82     /// The program scope information include global buffers (data sections for
83     /// globals and global constants)
84     /// ProgramScopeInfo must be prepared before kernel information. For example,
85     /// Symbols are per-kernel information but they could possible refering to
86     /// program-scope sections such as global buffer.
87     void addProgramScopeInfo(const IGC::SOpenCLProgramInfo& programInfo);
88 
89     /// add data section for global constants
90     void addGlobalConstants(const IGC::SOpenCLProgramInfo& annotations);
91 
92     /// add data section for globals
93     void addGlobals(const IGC::SOpenCLProgramInfo& annotations);
94 
95     /// add spir-v section
96     void addSPIRV(const uint8_t* data, uint32_t size);
97 
98     /// add program scope symbols (e.g. symbols defined in global/const buffer)
99     void addProgramSymbols(const IGC::SOpenCLProgramInfo& annotations);
100 
101     /// add program scope relocations (e.g. relocations for global/const buffer)
102     void addProgramRelocations(const IGC::SOpenCLProgramInfo& annotations);
103 
104     /// ------------ kernel scope helper functions ------------
105     /// add gen binary
106     zebin::ZEELFObjectBuilder::SectionID addKernelBinary(
107         const std::string& kernelName, const char* kernelBinary,
108         unsigned int kernelBinarySize);
109 
110     /// add execution environment
111     void addKernelExecEnv(const IGC::SOpenCLKernelInfo& annotations,
112                           zebin::zeInfoKernel& zeinfoKernel);
113 
114     /// add experimental properties
115     void addKernelExperimentalProperties(const IGC::SOpenCLKernelInfo& annotations,
116         zebin::zeInfoKernel& zeinfoKernel);
117 
118     /// add symbols of this kernel corresponding to kernel binary
119     /// added by addKernelBinary
120     void addKernelSymbols(
121         zebin::ZEELFObjectBuilder::SectionID kernelSectId,
122         const IGC::SOpenCLKernelInfo& annotations);
123 
124     /// get symbol type and binding
125     /// FIXME: this should be decided when symbol being created
126     uint8_t getSymbolElfType(const vISA::ZESymEntry& sym);
127     uint8_t getSymbolElfBinding(const vISA::ZESymEntry& sym);
128 
129     /// addSymbol - a helper function to add a symbol which is defined in targetSect
130     void addSymbol(const vISA::ZESymEntry& sym, zebin::ZEELFObjectBuilder::SectionID targetSect);
131 
132     /// add relocations of this kernel corresponding to binary added by
133     /// addKernelBinary.
134     void addKernelRelocations(
135         zebin::ZEELFObjectBuilder::SectionID targetId,
136         const IGC::SOpenCLKernelInfo& annotations);
137 
138     /// add local ids as per-thread payload argument
139     void addLocalIds(uint32_t simdSize, uint32_t grfSize,
140         bool has_local_id_x, bool has_local_id_y, bool has_local_id_z,
141         zebin::zeInfoKernel& zeinfoKernel);
142 
143     /// add payload arguments and BTI info from IGC::SOpenCLKernelInfo
144     /// payload arguments and BTI info have been added at
145     /// COpenCLKernel::CreateZEPayloadArguments
146     void addPayloadArgsAndBTI(
147         const IGC::SOpenCLKernelInfo& annotations,
148         zebin::zeInfoKernel& zeinfoKernel);
149 
150     /// add Memory buffer information
151     void addMemoryBuffer(
152         const IGC::SOpenCLKernelInfo& annotations,
153         zebin::zeInfoKernel& zeinfoKernel);
154 
155     /// add gtpin_info section
156     /// Add everything used to be in patch token iOpenCL::PATCH_TOKEN_GTPIN_INFO
157     /// into gtpin_info section
158     void addGTPinInfo(const IGC::SOpenCLKernelInfo& annotations);
159 
160     /// ------------ Verifier sub-functions ------------
161     bool hasSystemKernel(
162         const IGC::OpenCLProgramContext* clContext,
163         const USC::SSystemThreadKernelOutput* pSystemThreadKernelOutput);
164 
165     bool hasSystemThreadSurface(const IGC::OpenCLProgramContext* clContext);
166 
167     /// Calculate correct (pure) size of ELF binary, because m_debugDataSize in kernel output
168     /// contains something else.
169     size_t calcElfSize(void* elfBin, size_t elfSize);
170 
171     /// add debug environment
172     void addKernelDebugEnv(const IGC::SOpenCLKernelInfo& annotations,
173                            const IGC::CBTILayout& layout,
174                            zebin::zeInfoKernel& zeinfoKernel);
175 
176     /// add visasm of the kernel
177     void addKernelVISAAsm(const std::string& kernel, const std::string& visaasm);
178 private:
179     // mBuilder - Builder of a ZE ELF object
180     zebin::ZEELFObjectBuilder mBuilder;
181 
182     // mZEInfoBuilder - Builder and holder of a zeInfoContainer, which will
183     // be added into ZEELFObjectBuilder as .ze_info section
184     zebin::ZEInfoBuilder mZEInfoBuilder;
185 
186     const PLATFORM mPlatform;
187     G6HWC::SMediaHardwareCapabilities mHWCaps;
188 
189     /// sectionID holder for program scope sections
190     /// There should be only one global, global constant buffer per program
191     zebin::ZEELFObjectBuilder::SectionID mGlobalConstSectID = -1;
192     zebin::ZEELFObjectBuilder::SectionID mConstStringSectID = -1;
193     zebin::ZEELFObjectBuilder::SectionID mGlobalSectID = -1;
194 };
195 
196 } //namespace iOpenCL
197