Halide
ExternalCode.h
Go to the documentation of this file.
1 #ifndef HALIDE_EXTERNAL_CODE_H
2 #define HALIDE_EXTERNAL_CODE_H
3 
4 #include <vector>
5 
6 #include "Expr.h"
7 #include "Target.h"
8 
9 namespace Halide {
10 
11 class ExternalCode {
12 private:
13  enum Kind {
14  LLVMBitcode,
15  DeviceCode,
16  CPlusPlusSource,
17  } kind;
18 
19  Target llvm_target; // For LLVMBitcode.
20  DeviceAPI device_code_kind;
21 
22  std::vector<uint8_t> code;
23 
24  // Used for debugging and naming the module to llvm.
25  std::string nametag;
26 
27  ExternalCode(Kind kind, const Target &llvm_target, DeviceAPI device_api, const std::vector<uint8_t> &code, const std::string &name)
28  : kind(kind), llvm_target(llvm_target), device_code_kind(device_api), code(code), nametag(name) {
29  }
30 
31 public:
32  /** Construct an ExternalCode container from llvm bitcode. The
33  * result can be passed to Halide::Module::append to have the
34  * contained bitcode linked with that module. The Module's target
35  * must match the target argument here on architecture, bit width,
36  * and operating system. The name is used as a unique identifier
37  * for the external code and duplicates will be reduced to a
38  * single instance. Halide does not do anything other than to
39  * compare names for equality. To guarantee uniqueness in public
40  * code, we suggest using a Java style inverted domain name
41  * followed by organization specific naming. E.g.:
42  * com.initech.y2k.5d2ac80aaf522eec6cb4b40f39fb923f9902bc7e */
43  static ExternalCode bitcode_wrapper(const Target &cpu_type, const std::vector<uint8_t> &code, const std::string &name) {
44  return ExternalCode(LLVMBitcode, cpu_type, DeviceAPI::None, code, name);
45  }
46 
47  /** Construct an ExternalCode container from GPU "source code."
48  * This container can be used to insert its code into the GPU code
49  * generated for a given DeviceAPI. The specific type of code
50  * depends on the device API used as follows:
51  * CUDA: llvm bitcode for PTX
52  * OpenCL: OpenCL source code
53  * GLSL: GLSL source code
54  * OpenGLCompute: GLSL source code
55  * Metal: Metal source code
56  * Hexagon: llvm bitcode for Hexagon
57  *
58  * At present, this API is not fully working. See Issue:
59  * https://github.com/halide/Halide/issues/1971
60  *
61  * The name is used as a unique identifier for the external code
62  * and duplicates will be reduced to a single instance. Halide
63  * does not do anything other than to compare names for
64  * equality. To guarantee uniqueness in public code, we suggest
65  * using a Java style inverted domain name followed by
66  * organization specific naming. E.g.:
67  * com.tyrell.nexus-6.53947db86ba97a9ca5ecd5e60052880945bfeb37 */
68  static ExternalCode device_code_wrapper(DeviceAPI device_api, const std::vector<uint8_t> &code, const std::string &name) {
69  return ExternalCode(DeviceCode, Target(), device_api, code, name);
70  }
71 
72  /** Construct an ExternalCode container from C++ source code. This
73  * container can be used to insert its code into C++ output from
74  * Halide.
75  *
76  * At present, this API is not fully working. See Issue:
77  * https://github.com/halide/Halide/issues/1971
78  *
79  * The name is used as a unique identifier for the external code
80  * and duplicates will be reduced to a single instance. Halide
81  * does not do anything other than to compare names for
82  * equality. To guarantee uniqueness in public code, we suggest
83  * using a Java style inverted domain name followed by
84  * organization specific naming. E.g.:
85  * com.cyberdyne.skynet.78ad6c411d313f050f172cd3d440f23fdd797d0d */
86  static ExternalCode c_plus_plus_code_wrapper(const std::vector<uint8_t> &code, const std::string &name) {
87  return ExternalCode(CPlusPlusSource, Target(), DeviceAPI::None, code, name);
88  }
89 
90  /** Return true if this container holds llvm bitcode linkable with
91  * code generated for the target argument. The matching is done
92  * on the architecture, bit width, and operating system
93  * only. Features are ignored. If the container is for
94  * Target::ArchUnkonwn, it applies to all architectures -- meaning
95  * it is generic llvm bitcode. If the OS is OSUnknown, it applies
96  * to all operationg systems. The bit width must match.
97  *
98  * Ignoring feature flags isn't too important since generally
99  * ExternalCode will be constructed in a Generator which has
100  * access to the feature flags in effect and can select code
101  * appropriately. */
102  bool is_for_cpu_target(const Target &host) const {
103  return kind == LLVMBitcode &&
104  (llvm_target.arch == Target::ArchUnknown || llvm_target.arch == host.arch) &&
105  (llvm_target.os == Target::OSUnknown || llvm_target.os == host.os) &&
106  (llvm_target.bits == host.bits);
107  }
108 
109  /** True if this container holds code linkable with a code generated for a GPU. */
110  bool is_for_device_api(DeviceAPI current_device) const {
111  return kind == DeviceCode && device_code_kind == current_device;
112  }
113 
114  /** True if this container holds C++ source code for inclusion in
115  * generating C++ output. */
116  bool is_c_plus_plus_source() const {
117  return kind == CPlusPlusSource;
118  }
119 
120  /** Retrieve the bytes of external code held by this container. */
121  const std::vector<uint8_t> &contents() const {
122  return code;
123  }
124 
125  /** Retrieve the name of this container. Used to ensure the same
126  * piece of external code is only included once in linkage. */
127  const std::string &name() const {
128  return nametag;
129  }
130 };
131 
132 } // namespace Halide
133 
134 #endif
Halide::ExternalCode::is_for_device_api
bool is_for_device_api(DeviceAPI current_device) const
True if this container holds code linkable with a code generated for a GPU.
Definition: ExternalCode.h:110
Halide::ExternalCode::name
const std::string & name() const
Retrieve the name of this container.
Definition: ExternalCode.h:127
Halide::ExternalCode::is_c_plus_plus_source
bool is_c_plus_plus_source() const
True if this container holds C++ source code for inclusion in generating C++ output.
Definition: ExternalCode.h:116
Target.h
Halide::Target::bits
int bits
The bit-width of the target machine.
Definition: Target.h:51
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AddAtomicMutex.h:21
Halide::Target::os
enum Halide::Target::OS os
Expr.h
Halide::ExternalCode::bitcode_wrapper
static ExternalCode bitcode_wrapper(const Target &cpu_type, const std::vector< uint8_t > &code, const std::string &name)
Construct an ExternalCode container from llvm bitcode.
Definition: ExternalCode.h:43
Halide::DeviceAPI::None
@ None
Halide::ExternalCode
Definition: ExternalCode.h:11
Halide::ExternalCode::contents
const std::vector< uint8_t > & contents() const
Retrieve the bytes of external code held by this container.
Definition: ExternalCode.h:121
Halide::Target::arch
enum Halide::Target::Arch arch
Halide::Target::ArchUnknown
@ ArchUnknown
Definition: Target.h:40
Halide::ExternalCode::device_code_wrapper
static ExternalCode device_code_wrapper(DeviceAPI device_api, const std::vector< uint8_t > &code, const std::string &name)
Construct an ExternalCode container from GPU "source code." This container can be used to insert its ...
Definition: ExternalCode.h:68
Halide::Target::OSUnknown
@ OSUnknown
Definition: Target.h:24
Halide::Target
A struct representing a target machine and os to generate code for.
Definition: Target.h:19
Halide::ExternalCode::is_for_cpu_target
bool is_for_cpu_target(const Target &host) const
Return true if this container holds llvm bitcode linkable with code generated for the target argument...
Definition: ExternalCode.h:102
Halide::ExternalCode::c_plus_plus_code_wrapper
static ExternalCode c_plus_plus_code_wrapper(const std::vector< uint8_t > &code, const std::string &name)
Construct an ExternalCode container from C++ source code.
Definition: ExternalCode.h:86
Halide::DeviceAPI
DeviceAPI
An enum describing a type of device API.
Definition: DeviceAPI.h:15