File: devprogram.hpp

package info (click to toggle)
rocm-hipamd 6.4.3-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 23,036 kB
  • sloc: cpp: 211,057; ansic: 35,860; sh: 755; python: 623; perl: 275; asm: 166; makefile: 27
file content (507 lines) | stat: -rw-r--r-- 18,537 bytes parent folder | download | duplicates (2)
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
/* Copyright (c) 2008 - 2021 Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#pragma once

#if defined(WITH_COMPILER_LIB)
#include "aclTypes.h"
#endif
#include "platform/context.hpp"
#include "platform/object.hpp"
#include "platform/memory.hpp"

#if defined(USE_COMGR_LIBRARY)
#include "amd_comgr/amd_comgr.h"
#endif  // defined(USE_COMGR_LIBRARY)

namespace amd {
  namespace hsa {
    namespace loader {
      class Symbol;
    }  // loader
    namespace code {
      namespace Kernel {
        class Metadata;
      }  // Kernel
    }  // code
  }  // hsa
}  // amd

namespace amd {

class Device;
class Program;

namespace option {
  class Options;
}  // option
}

namespace amd::device {
class ClBinary;
class Kernel;

struct SymbolInfo {
  int sym_type;
  std::vector<std::string>* var_names;
};

struct SymbolLoweredName {
  const char* name_expression;
  std::string* loweredName;
};

//! A program object for a specific device.
class Program : public amd::HeapObject {
 public:
  typedef std::pair<const void* /* binary_image */, size_t /* binary size */> binary_t;
  typedef std::pair<amd::Os::FileDesc /* file_desc */, size_t /* file_offset */> finfo_t;
  typedef std::unordered_map<std::string, Kernel*> kernels_t;
  // type of the program
  typedef enum {
    TYPE_NONE = 0,     // uncompiled
    TYPE_COMPILED,     // compiled
    TYPE_LIBRARY,      // linked library
    TYPE_EXECUTABLE,   // linked executable
    TYPE_INTERMEDIATE  // intermediate
  } type_t;

  //! type of the input file
  typedef enum {
    FILE_TYPE_DEFAULT         =  0,
    FILE_TYPE_OPENCL          =  1,
    FILE_TYPE_LLVMIR_TEXT     =  2,
    FILE_TYPE_LLVMIR_BINARY   =  3,
    FILE_TYPE_SPIR_TEXT       =  4,
    FILE_TYPE_SPIR_BINARY     =  5,
    FILE_TYPE_AMDIL_TEXT      =  6,
    FILE_TYPE_AMDIL_BINARY    =  7,
    FILE_TYPE_HSAIL_TEXT      =  8,
    FILE_TYPE_HSAIL_BINARY    =  9,
    FILE_TYPE_X86_TEXT        = 10,
    FILE_TYPE_X86_BINARY      = 11,
    FILE_TYPE_CG              = 12,
    FILE_TYPE_SOURCE          = 13,
    FILE_TYPE_ISA             = 14,
    FILE_TYPE_HEADER          = 15,
    FILE_TYPE_RSLLVMIR_BINARY = 16,
    FILE_TYPE_SPIRV_BINARY    = 17,
    FILE_TYPE_ASM_TEXT        = 18,
    FILE_TYPE_LAST            = 19
  } file_type_t;

 private:
  //! The device target for this binary.
  amd::SharedReference<amd::Device> device_;
  amd::Program& owner_; //!< owner of this program

  kernels_t kernels_; //!< The kernel entry points this binary.
  type_t type_;       //!< type of this program

  typedef enum { InitKernel = 0, FiniKernel } kernel_kind_t;  //!< Kernel kind
  bool runInitFiniKernel(kernel_kind_t) const;

#if defined(WITH_COMPILER_LIB)
  static amd::Monitor buildLock_; //!< Global build lock for HSAIL which isn't thread-safe
#endif

 protected:
   union {
     struct {
       uint32_t isNull_ : 1;          //!< Null program no memory allocations
       uint32_t internal_ : 1;        //!< Internal blit program
       uint32_t isLC_ : 1;            //!< LC was used for the program compilation
       uint32_t hasGlobalStores_ : 1; //!< Program has writable program scope variables
       uint32_t isHIP_ : 1;           //!< Determine if the program is for HIP
       uint32_t coLoaded_ : 1;        //!< Has the code objected been loaded
       uint32_t trapHandler_ : 1;     //!< It is a trap handler for debugger
     };
     uint32_t flags_;  //!< Program flags
   };

  ClBinary* clBinary_;                          //!< The CL program binary file
  std::string llvmBinary_;                      //!< LLVM IR binary code
  amd::Elf::ElfSections elfSectionType_;        //!< LLVM IR binary code is in SPIR format
  std::string compileOptions_;                  //!< compile/build options.
  std::string linkOptions_;                     //!< link options.
                                                //!< the option arg passed in to clCompileProgram(), clLinkProgram(),
                                                //! or clBuildProgram(), whichever is called last
#if defined(WITH_COMPILER_LIB)
  aclBinaryOptions binOpts_;        //!< Binary options to create aclBinary
  aclBinary* binaryElf_;            //!< Binary for the new compiler library
#endif

  std::string lastBuildOptionsArg_;
  mutable std::string buildLog_;    //!< build log.
  int32_t buildStatus_;              //!< build status.
  int32_t buildError_;               //!< build error

#if defined(WITH_COMPILER_LIB)
  aclTargetInfo info_;              //!< The info target for this binary.
#endif
  size_t globalVariableTotalSize_;
  amd::option::Options* programOptions_;


#if defined(USE_COMGR_LIBRARY)
  amd_comgr_metadata_node_t metadata_ = {}; //!< COMgr metadata
  uint32_t codeObjectVer_;                  //!< version of code object
  std::map<std::string, amd_comgr_metadata_node_t> kernelMetadataMap_; //!< Map of kernel metadata
#endif
  //! Sanitizer lock - lock when launching init/fini kernels
  static amd::Monitor initFiniLock_;

 public:
  //! Construct a section.
  Program(amd::Device& device, amd::Program& owner);

  //! Destroy this binary image.
  virtual ~Program();

  //! Destroy all the kernels
  void clear();

  amd::Program* owner() const { return &owner_; }

  //! Return the compiler options passed to build this program
  amd::option::Options* getCompilerOptions() const { return programOptions_; }

  //! Compile the device program.
  int32_t compile(const std::string& sourceCode, const std::vector<const std::string*>& headers,
    const char** headerIncludeNames, const char* origOptions,
    amd::option::Options* options);

  //! Link the device program.
  int32_t link(const std::vector<Program*>& inputPrograms, const char* origLinkOptions,
    amd::option::Options* linkOptions);

  //! Build the device program.
  int32_t build(const std::string& sourceCode, const char* origOptions,
                amd::option::Options* options, const std::vector<std::string>& preCompiledHeaders);

  //! Load the device program.
  bool load();

  //! Return the device object, associated with this program.
  const amd::Device& device() const { return device_(); }

  //! Return the compiler options used to build the program.
  const std::string& compileOptions() const { return compileOptions_; }

  const std::string& linkOptions() const { return linkOptions_; }

  //! Return the option arg passed in to clCompileProgram(), clLinkProgram(),
  //! or clBuildProgram(), whichever is called last
  const std::string lastBuildOptionsArg() const { return lastBuildOptionsArg_; }

  //! Return the build log.
  const std::string& buildLog() const { return buildLog_; }

  //! Return the build status.
  cl_build_status buildStatus() const { return buildStatus_; }

  //! Return the build error.
  int32_t buildError() const { return buildError_; }

  //! Return the symbols vector.
  const kernels_t& kernels() const { return kernels_; }
  kernels_t& kernels() { return kernels_; }

  //! Return the binary image.
  inline const binary_t binary() const;
  inline binary_t binary();
  inline finfo_t BinaryFd() const;
  inline std::string BinaryURI() const;

  //! Returns the CL program binary file
  ClBinary* clBinary() { return clBinary_; }
  const ClBinary* clBinary() const { return clBinary_; }

  bool setBinary(const char* binaryIn, size_t size, const device::Program* same_dev_prog = nullptr,
                 amd::Os::FileDesc fdesc = amd::Os::FDescInit(), size_t foffset = 0,
                 std::string uri = std::string());

  type_t type() const { return type_; }

  void setGlobalVariableTotalSize(size_t size) { globalVariableTotalSize_ = size; }

  size_t globalVariableTotalSize() const { return globalVariableTotalSize_; }

#if defined(WITH_COMPILER_LIB)
  //! Returns the aclBinary associated with the program
  aclBinary* binaryElf() const { return static_cast<aclBinary*>(binaryElf_); }
#endif

  //! Returns TRUE if the program just compiled
  bool isNull() const { return isNull_; }

  //! Returns TRUE if the program used internally by runtime
  bool isInternal() const { return internal_; }

  //! Returns TRUE if Lightning compiler was used for this program
  bool isLC() const { return isLC_; }

  //! Global variables are a part of the code segment
  bool hasGlobalStores() const { return hasGlobalStores_; }

  //! Return TRUE if the program has been loaded
  bool isCodeObjectLoaded() const { return coLoaded_; }

  //! Returns TRUE if the program is a trap handler for debugger support
  bool isTrapHandler() const { return trapHandler_; }

#if defined(USE_COMGR_LIBRARY)
  amd_comgr_metadata_node_t metadata() const { return metadata_; }

  //! Get the kernel metadata
  const bool getKernelMetadata(const std::string name, amd_comgr_metadata_node_t* meta) const {
    auto it = kernelMetadataMap_.find(name);
    if (it != kernelMetadataMap_.end()) {
      *meta = it->second;
      return true;
    }
    return false;
  }

  const uint32_t codeObjectVer() const { return codeObjectVer_; }
#endif

  //! Check if program is HIP based
  const bool isHIP() const { return (isHIP_ == 1); }

  //! Get mangled name of a name expresion
  const bool getLoweredNames(std::vector<std::string>* mangledNames) const;

  //! Get demangled names
  bool getDemangledName(const std::string& mangledNames, std::string& demangledNames) const;

  bool getGlobalFuncFromCodeObj(std::vector<std::string>* func_names) const;
  bool getGlobalVarFromCodeObj(std::vector<std::string>* var_names) const;
  bool getUndefinedVarFromCodeObj(std::vector<std::string>* var_names) const;

  virtual bool createGlobalVarObj(amd::Memory** amd_mem_obj, void** dptr,
                                  size_t* bytes, const char* globalName) const {
    ShouldNotReachHere();
    return false;
  }

  //! Run kernels marked with "init" kind metadata
  bool runInitKernels();

  //! Run kernels marked with "fini" kind metadata
  bool runFiniKernels();

 protected:
  //! pre-compile setup
  bool initBuild(amd::option::Options* options);

  //! post-compile cleanup
  bool finiBuild(bool isBuildGood);

  /*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
  *
  *  \return True if we successefully compiled a GPU program
  */
  virtual bool compileImpl(
      const std::string& sourceCode,  //!< the program's source code
      const std::vector<const std::string*>& headers, const char** headerIncludeNames,
      amd::option::Options* options,                      //!< compile options's object
      const std::vector<std::string>& preCompiledHeaders  //!< precompiled headers
  );

  //! Link the device program.
  virtual bool linkImpl(amd::option::Options* options);

  //! Link the device programs.
  virtual bool linkImpl(const std::vector<Program*>& inputPrograms, amd::option::Options* options,
    bool createLibrary);

  virtual bool createBinary(amd::option::Options* options) = 0;

  //! Initialize Binary (used only for clCreateProgramWithBinary()).
  bool initClBinary(const char* binaryIn, size_t size,
                    amd::Os::FileDesc fdesc = amd::Os::FDescInit(),
                    size_t foffset = 0, std::string uri = std::string());

  //! Initialize Binary
  virtual bool initClBinary();

  virtual bool saveBinaryAndSetType(type_t type) = 0;

  //! Release the Binary
  void releaseClBinary();

#if defined(WITH_COMPILER_LIB)
  //! return target info
  virtual const aclTargetInfo& info() = 0;
#endif
  virtual bool createKernels(void* binary, size_t binSize, bool useUniformWorkGroupSize,
                             bool internalKernel) { return true; }

  virtual bool setKernels(
    void* binary, size_t binSize,
    amd::Os::FileDesc fdesc = amd::Os::FDescInit(), size_t foffset = 0,
    std::string uri = std::string()) { return true; }

  //! Returns all the options to be appended while passing to the compiler library
  std::vector<std::string> ProcessOptions(amd::option::Options* options);

  //! Returns all the options to be appended while passing to the compiler library,
  //! flattened into one string.
  std::string ProcessOptionsFlattened(amd::option::Options* options);

  //! At linking time, get the set of compile options to be used from
  //! the set of input program, warn if they have inconsisten compile options.
  bool getCompileOptionsAtLinking(const std::vector<Program*>& inputPrograms,
    const amd::option::Options* linkOptions);

  void setType(type_t newType) { type_ = newType; }

  /* \brief Returns the next stage to compile from, based on sections in binary,
  *  also returns completeStages in a vector, which contains at least ACL_TYPE_DEFAULT,
  *  sets needOptionsCheck to true if options check is needed to decide whether or not to recompile
  */
  file_type_t getCompilationStagesFromBinary(
    std::vector<file_type_t>& completeStages,
    bool& needOptionsCheck);

  /* \brief Returns the next stage to compile from, based on sections and options in binary
  */
  file_type_t getNextCompilationStageFromBinary(amd::option::Options* options);

  //! Finds the total size of all global variables in the program
  bool FindGlobalVarSize(void* binary, size_t binSize);

  bool isElf(const char* bin) const { return amd::Elf::isElfMagic(bin); }

  virtual bool defineGlobalVar(const char* name, void* dptr) {
    ShouldNotReachHere();
    return false;
  }

#if defined(USE_COMGR_LIBRARY)
  bool getSymbolsFromCodeObj(std::vector<std::string>* var_names, amd_comgr_symbol_type_t sym_type) const;
#endif
  bool getUndefinedVarInfo(std::string var_name, void** var_addr, size_t* var_size);
  bool defineUndefinedVars();

 private:

  //! Compile the device program with LC path
  bool compileImplLC(const std::string& sourceCode, const std::vector<const std::string*>& headers,
                     const char** headerIncludeNames, amd::option::Options* options,
                     const std::vector<std::string>& preCompiledHeaders);

  //! Compile the device program with HSAIL path
  bool compileImplHSAIL(const std::string& sourceCode,
    const std::vector<const std::string*>& headers,
    const char** headerIncludeNames, amd::option::Options* options);

  //! Link the device programs with LC path
  bool linkImplLC(const std::vector<Program*>& inputPrograms,
    amd::option::Options* options, bool createLibrary);

  //! Link the device programs with HSAIL path
  bool linkImplHSAIL(const std::vector<Program*>& inputPrograms,
    amd::option::Options* options, bool createLibrary);

  //! Link the device program with LC path
  bool linkImplLC(amd::option::Options* options);

  //! Link the device program with HSAIL path
  bool linkImplHSAIL(amd::option::Options* options);

  //! Load the device program with LC path
  bool loadLC();

  //! Load the device program with HSAIL path
  bool loadHSAIL();

#if defined(USE_COMGR_LIBRARY)
  //! Dump the log data object to the build log, if a log data object is present
  void extractBuildLog(amd_comgr_data_set_t dataSet);
  //! Dump the code object data
  amd_comgr_status_t extractByteCodeBinary(const amd_comgr_data_set_t inDataSet,
    const amd_comgr_data_kind_t dataKind, const std::string& outFileName,
    char* outBinary[] = nullptr, size_t* outSize = nullptr);

  //! Create code object and add it into the data set
  amd_comgr_status_t addCodeObjData(const char *source,
    const size_t size, const amd_comgr_data_kind_t type,
    const char* name, amd_comgr_data_set_t* dataSet);

  //! Add precompiled headers to the data set
  amd_comgr_status_t addPreCompiledHeader(amd_comgr_data_set_t* dataSet,
                                          const std::vector<std::string>& preCompiledHeaders);

  //! Create action for the specified language, target and options
  amd_comgr_status_t createAction(const amd_comgr_language_t oclver,
    const std::vector<std::string>& options, amd_comgr_action_info_t* action,
    bool* hasAction);

  //! Create the bitcode of the linked input dataset
  bool linkLLVMBitcode(const amd_comgr_data_set_t inputs,
    const std::vector<std::string>& options,
    amd::option::Options* amdOptions, amd_comgr_data_set_t* output,
    char* binaryData[] = nullptr, size_t* binarySize = nullptr);

  //! Create the bitcode of the compiled input dataset
  bool compileToLLVMBitcode(const amd_comgr_data_set_t compileInputs,
    const std::vector<std::string>& options, amd::option::Options* amdOptions,
    char* binaryData[], size_t* binarySize,
    const bool link_dev_libs = true);

  //! Compile and create the excutable of the input dataset
  bool compileAndLinkExecutable(const amd_comgr_data_set_t inputs,
    const std::vector<std::string>& options, amd::option::Options* amdOptions, char* executable[],
    size_t* executableSize, file_type_t continueCompileFrom);

  //! Create the map for the kernel name and its metadata for fast access
  bool createKernelMetadataMap(void* binary, size_t binSize);
#endif

  bool trySubstObjFile(const char *SubstCfgFile,
                       const std::string& sourceCode,
                       const amd::option::Options* options);

  //! Disable default copy constructor
  Program(const Program&);

  //! Disable operator=
  Program& operator=(const Program&);
};

#if defined(USE_COMGR_LIBRARY)

class ComgrBinaryData {
 public:
  ComgrBinaryData() : binaryData_({0}), created_(false) {}
  ~ComgrBinaryData();
  bool create(amd_comgr_data_kind_t kind, void* binary, size_t binSize);
  amd_comgr_data_t& data();

 private:
  amd_comgr_data_t binaryData_;
  bool created_;
};

#endif

} // namespace amd::device