1 #ifndef HALIDE_MODULE_H 2 #define HALIDE_MODULE_H 3 4 /** \file 5 * 6 * Defines Module, an IR container that fully describes a Halide program. 7 */ 8 9 #include <functional> 10 #include <map> 11 #include <memory> 12 #include <set> 13 #include <string> 14 15 #include "Argument.h" 16 #include "Expr.h" 17 #include "ExternalCode.h" 18 #include "Function.h" // for NameMangling 19 #include "ModulusRemainder.h" 20 #include "Target.h" 21 22 namespace Halide { 23 24 template<typename T> 25 class Buffer; 26 27 /** Enums specifying various kinds of outputs that can be produced from a Halide Pipeline. */ 28 enum class Output { 29 assembly, 30 bitcode, 31 c_header, 32 c_source, 33 compiler_log, 34 cpp_stub, 35 featurization, 36 llvm_assembly, 37 object, 38 python_extension, 39 pytorch_wrapper, 40 registration, 41 schedule, 42 static_library, 43 stmt, 44 stmt_html, 45 }; 46 47 /** Type of linkage a function in a lowered Halide module can have. 48 Also controls whether auxiliary functions and metadata are generated. */ 49 enum class LinkageType { 50 External, ///< Visible externally. 51 ExternalPlusMetadata, ///< Visible externally. Argument metadata and an argv wrapper are also generated. 52 Internal, ///< Not visible externally, similar to 'static' linkage in C. 53 }; 54 55 namespace Internal { 56 57 struct OutputInfo { 58 std::string name, extension; 59 60 // `is_multi` indicates how these outputs are generated 61 // when using the compile_to_multitarget_xxx() APIs (or via the 62 // Generator command-line mode): 63 // 64 // - If `is_multi` is true, then a separate file of this Output type is 65 // generated for each target in the multitarget (e.g. object files, 66 // assembly files, etc). Each of the files will have a suffix appended 67 // that is based on the specific subtarget. 68 // 69 // - If `is_multi` is false, then only one file of this Output type 70 // regardless of how many targets are in the multitarget. No additional 71 // suffix will be appended to the filename. 72 // 73 bool is_multi{false}; 74 }; 75 std::map<Output, const OutputInfo> get_output_info(const Target &target); 76 77 /** Definition of an argument to a LoweredFunc. This is similar to 78 * Argument, except it enables passing extra information useful to 79 * some targets to LoweredFunc. */ 80 struct LoweredArgument : public Argument { 81 /** For scalar arguments, the modulus and remainder of this 82 * argument. */ 83 ModulusRemainder alignment; 84 85 LoweredArgument() = default; LoweredArgumentLoweredArgument86 explicit LoweredArgument(const Argument &arg) 87 : Argument(arg) { 88 } LoweredArgumentLoweredArgument89 LoweredArgument(const std::string &_name, Kind _kind, const Type &_type, uint8_t _dimensions, const ArgumentEstimates &argument_estimates) 90 : Argument(_name, _kind, _type, _dimensions, argument_estimates) { 91 } 92 }; 93 94 /** Definition of a lowered function. This object provides a concrete 95 * mapping between parameters used in the function body and their 96 * declarations in the argument list. */ 97 struct LoweredFunc { 98 std::string name; 99 100 /** Arguments referred to in the body of this function. */ 101 std::vector<LoweredArgument> args; 102 103 /** Body of this function. */ 104 Stmt body; 105 106 /** The linkage of this function. */ 107 LinkageType linkage; 108 109 /** The name-mangling choice for the function. Defaults to using 110 * the Target. */ 111 NameMangling name_mangling; 112 113 LoweredFunc(const std::string &name, 114 const std::vector<LoweredArgument> &args, 115 Stmt body, 116 LinkageType linkage, 117 NameMangling mangling = NameMangling::Default); 118 LoweredFunc(const std::string &name, 119 const std::vector<Argument> &args, 120 Stmt body, 121 LinkageType linkage, 122 NameMangling mangling = NameMangling::Default); 123 }; 124 125 } // namespace Internal 126 127 namespace Internal { 128 struct ModuleContents; 129 class CompilerLogger; 130 } // namespace Internal 131 132 struct AutoSchedulerResults; 133 134 /** A halide module. This represents IR containing lowered function 135 * definitions and buffers. */ 136 class Module { 137 Internal::IntrusivePtr<Internal::ModuleContents> contents; 138 139 public: 140 Module(const std::string &name, const Target &target); 141 142 /** Get the target this module has been lowered for. */ 143 const Target &target() const; 144 145 /** The name of this module. This is used as the default filename 146 * for output operations. */ 147 const std::string &name() const; 148 149 /** If this Module had an auto-generated schedule, return a read-only pointer 150 * to the AutoSchedulerResults. If not, return nullptr. */ 151 const AutoSchedulerResults *get_auto_scheduler_results() const; 152 153 /** Return whether this module uses strict floating-point anywhere. */ 154 bool any_strict_float() const; 155 156 /** The declarations contained in this module. */ 157 // @{ 158 const std::vector<Buffer<void>> &buffers() const; 159 const std::vector<Internal::LoweredFunc> &functions() const; 160 std::vector<Internal::LoweredFunc> &functions(); 161 const std::vector<Module> &submodules() const; 162 const std::vector<ExternalCode> &external_code() const; 163 // @} 164 165 /** Return the function with the given name. If no such function 166 * exists in this module, assert. */ 167 Internal::LoweredFunc get_function_by_name(const std::string &name) const; 168 169 /** Add a declaration to this module. */ 170 // @{ 171 void append(const Buffer<void> &buffer); 172 void append(const Internal::LoweredFunc &function); 173 void append(const Module &module); 174 void append(const ExternalCode &external_code); 175 // @} 176 177 /** Compile a halide Module to variety of outputs, depending on 178 * the fields set in output_files. */ 179 void compile(const std::map<Output, std::string> &output_files) const; 180 181 /** Compile a halide Module to in-memory object code. Currently 182 * only supports LLVM based compilation, but should be extended to 183 * handle source code backends. */ 184 Buffer<uint8_t> compile_to_buffer() const; 185 186 /** Return a new module with all submodules compiled to buffers on 187 * on the result Module. */ 188 Module resolve_submodules() const; 189 190 /** When generating metadata from this module, remap any occurrences 191 * of 'from' into 'to'. */ 192 void remap_metadata_name(const std::string &from, const std::string &to) const; 193 194 /** Retrieve the metadata name map. */ 195 std::map<std::string, std::string> get_metadata_name_map() const; 196 197 /** Set the AutoSchedulerResults for the Module. It is an error to call this 198 * multiple times for a given Module. */ 199 void set_auto_scheduler_results(const AutoSchedulerResults &results); 200 201 /** Set whether this module uses strict floating-point directives anywhere. */ 202 void set_any_strict_float(bool any_strict_float); 203 }; 204 205 /** Link a set of modules together into one module. */ 206 Module link_modules(const std::string &name, const std::vector<Module> &modules); 207 208 /** Create an object file containing the Halide runtime for a given target. For 209 * use with Target::NoRuntime. Standalone runtimes are only compatible with 210 * pipelines compiled by the same build of Halide used to call this function. */ 211 void compile_standalone_runtime(const std::string &object_filename, Target t); 212 213 /** Create an object and/or static library file containing the Halide runtime 214 * for a given target. For use with Target::NoRuntime. Standalone runtimes are 215 * only compatible with pipelines compiled by the same build of Halide used to 216 * call this function. Return a map with just the actual outputs filled in 217 * (typically, Output::object and/or Output::static_library). 218 */ 219 std::map<Output, std::string> compile_standalone_runtime(const std::map<Output, std::string> &output_files, Target t); 220 221 using ModuleFactory = std::function<Module(const std::string &fn_name, const Target &target)>; 222 using CompilerLoggerFactory = std::function<std::unique_ptr<Internal::CompilerLogger>(const std::string &fn_name, const Target &target)>; 223 224 void compile_multitarget(const std::string &fn_name, 225 const std::map<Output, std::string> &output_files, 226 const std::vector<Target> &targets, 227 const std::vector<std::string> &suffixes, 228 const ModuleFactory &module_factory, 229 const CompilerLoggerFactory &compiler_logger_factory = nullptr); 230 231 } // namespace Halide 232 233 #endif 234