Halide 14.0.0
Halide compiler and libraries
CodeGen_C.h
Go to the documentation of this file.
1#ifndef HALIDE_CODEGEN_C_H
2#define HALIDE_CODEGEN_C_H
3
4/** \file
5 *
6 * Defines an IRPrinter that emits C++ code equivalent to a halide stmt
7 */
8
9#include "IRPrinter.h"
10#include "Scope.h"
11#include "Target.h"
12
13namespace Halide {
14
15struct Argument;
16class Module;
17
18namespace Internal {
19
20struct LoweredFunc;
21
22/** This class emits C++ code equivalent to a halide Stmt. It's
23 * mostly the same as an IRPrinter, but it's wrapped in a function
24 * definition, and some things are handled differently to be valid
25 * C++.
26 */
27class CodeGen_C : public IRPrinter {
28public:
36 };
37
38 /** Initialize a C code generator pointing at a particular output
39 * stream (e.g. a file, or std::cout) */
40 CodeGen_C(std::ostream &dest,
41 const Target &target,
43 const std::string &include_guard = "");
44 ~CodeGen_C() override;
45
46 /** Emit the declarations contained in the module as C code. */
47 void compile(const Module &module);
48
49 /** The target we're generating code for */
50 const Target &get_target() const {
51 return target;
52 }
53
54 static void test();
55
56protected:
57 enum class IntegerSuffixStyle {
58 PlainC = 0,
59 OpenCL = 1,
60 HLSL = 2
61 };
62
63 /** How to emit 64-bit integer constants */
65
66 /** Emit a declaration. */
67 // @{
68 virtual void compile(const LoweredFunc &func, const std::map<std::string, std::string> &metadata_name_map);
69 virtual void compile(const Buffer<> &buffer);
70 // @}
71
72 /** An ID for the most recently generated ssa variable */
73 std::string id;
74
75 /** The target being generated for. */
77
78 /** Controls whether this instance is generating declarations or
79 * definitions and whether the interface us extern "C" or C++. */
81
82 /** A cache of generated values in scope */
83 std::map<std::string, std::string> cache;
84
85 /** Emit an expression as an assignment, then return the id of the
86 * resulting var */
87 std::string print_expr(const Expr &);
88
89 /** Like print_expr, but cast the Expr to the given Type */
90 std::string print_cast_expr(const Type &, const Expr &);
91
92 /** Emit a statement */
93 void print_stmt(const Stmt &);
94
95 void create_assertion(const std::string &id_cond, const Expr &message);
96 void create_assertion(const Expr &cond, const Expr &message);
97
102 };
103
104 /** Emit the C name for a halide type. If space_option is AppendSpace,
105 * and there should be a space between the type and the next token,
106 * one is appended. (This allows both "int foo" and "Foo *foo" to be
107 * formatted correctly. Otherwise the latter is "Foo * foo".)
108 */
109 virtual std::string print_type(Type, AppendSpaceIfNeeded space_option = DoNotAppendSpace);
110
111 /** Emit a statement to reinterpret an expression as another type */
112 virtual std::string print_reinterpret(Type, const Expr &);
113
114 /** Emit a version of a string that is a valid identifier in C (. is replaced with _) */
115 virtual std::string print_name(const std::string &);
116
117 /** Add typedefs for vector types. Not needed for OpenCL, might
118 * use different syntax for other C-like languages. */
119 virtual void add_vector_typedefs(const std::set<Type> &vector_types);
120
121 /** Bottleneck to allow customization of calls to generic Extern/PureExtern calls. */
122 virtual std::string print_extern_call(const Call *op);
123
124 /** Convert a vector Expr into a series of scalar Exprs, then reassemble into vector of original type. */
125 std::string print_scalarized_expr(const Expr &e);
126
127 /** Emit an SSA-style assignment, and set id to the freshly generated name. Return id. */
128 virtual std::string print_assignment(Type t, const std::string &rhs);
129
130 /** Emit free for the heap allocation. **/
131 void print_heap_free(const std::string &alloc_name);
132
133 /** Return true if only generating an interface, which may be extern "C" or C++ */
134 bool is_header() {
135 return output_kind == CHeader ||
137 }
138
139 /** Return true if only generating an interface, which may be extern "C" or C++ */
141 return output_kind == CExternDecl ||
143 }
144
145 /** Return true if only generating an interface, which may be extern "C" or C++ */
147 return is_header() || is_extern_decl();
148 }
149
150 /** Return true if generating C++ linkage. */
152 return output_kind == CPlusPlusHeader ||
155 }
156
157 /** Open a new C scope (i.e. throw in a brace, increase the indent) */
159
160 /** Close a C scope (i.e. throw in an end brace, decrease the indent) */
161 void close_scope(const std::string &comment);
162
163 struct Allocation {
165 };
166
167 /** Track the types of allocations to avoid unnecessary casts. */
169
170 /** Track which allocations actually went on the heap. */
172
173 /** True if there is a void * __user_context parameter in the arguments. */
175
176 /** Track current calling convention scope. */
178
179 /** True if at least one gpu-based for loop is used. */
181
182 /** Track which handle types have been forward-declared already. */
183 std::set<const halide_handle_cplusplus_type *> forward_declared;
184
185 /** If the Type is a handle type, emit a forward-declaration for it
186 * if we haven't already. */
188
190
191 using IRPrinter::visit;
192
193 void visit(const Variable *) override;
194 void visit(const IntImm *) override;
195 void visit(const UIntImm *) override;
196 void visit(const StringImm *) override;
197 void visit(const FloatImm *) override;
198 void visit(const Cast *) override;
199 void visit(const Add *) override;
200 void visit(const Sub *) override;
201 void visit(const Mul *) override;
202 void visit(const Div *) override;
203 void visit(const Mod *) override;
204 void visit(const Max *) override;
205 void visit(const Min *) override;
206 void visit(const EQ *) override;
207 void visit(const NE *) override;
208 void visit(const LT *) override;
209 void visit(const LE *) override;
210 void visit(const GT *) override;
211 void visit(const GE *) override;
212 void visit(const And *) override;
213 void visit(const Or *) override;
214 void visit(const Not *) override;
215 void visit(const Call *) override;
216 void visit(const Select *) override;
217 void visit(const Load *) override;
218 void visit(const Store *) override;
219 void visit(const Let *) override;
220 void visit(const LetStmt *) override;
221 void visit(const AssertStmt *) override;
222 void visit(const ProducerConsumer *) override;
223 void visit(const For *) override;
224 void visit(const Ramp *) override;
225 void visit(const Broadcast *) override;
226 void visit(const Provide *) override;
227 void visit(const Allocate *) override;
228 void visit(const Free *) override;
229 void visit(const Realize *) override;
230 void visit(const IfThenElse *) override;
231 void visit(const Evaluate *) override;
232 void visit(const Shuffle *) override;
233 void visit(const Prefetch *) override;
234 void visit(const Fork *) override;
235 void visit(const Acquire *) override;
236 void visit(const Atomic *) override;
237 void visit(const VectorReduce *) override;
238
239 void visit_binop(Type t, const Expr &a, const Expr &b, const char *op);
240 void visit_relop(Type t, const Expr &a, const Expr &b, const char *scalar_op, const char *vector_op);
241
242 template<typename T>
243 static std::string with_sep(const std::vector<T> &v, const std::string &sep) {
244 std::ostringstream o;
245 for (size_t i = 0; i < v.size(); ++i) {
246 if (i > 0) {
247 o << sep;
248 }
249 o << v[i];
250 }
251 return o.str();
252 }
253
254 template<typename T>
255 static std::string with_commas(const std::vector<T> &v) {
256 return with_sep<T>(v, ", ");
257 }
258
259 /** Are we inside an atomic node that uses mutex locks?
260 This is used for detecting deadlocks from nested atomics. */
262
263 /** Emit atomic store instructions? */
265
266 /** true if add_vector_typedefs() has been called. */
268
269 void emit_argv_wrapper(const std::string &function_name,
270 const std::vector<LoweredArgument> &args);
271 void emit_metadata_getter(const std::string &function_name,
272 const std::vector<LoweredArgument> &args,
273 const std::map<std::string, std::string> &metadata_name_map);
274};
275
276} // namespace Internal
277} // namespace Halide
278
279#endif
This header file defines operators that let you dump a Halide expression, statement,...
Defines the Scope class, which is used for keeping track of names in a scope while traversing IR.
Defines the structure that describes a Halide target.
This class emits C++ code equivalent to a halide Stmt.
Definition: CodeGen_C.h:27
void visit(const GE *) override
bool is_extern_decl()
Return true if only generating an interface, which may be extern "C" or C++.
Definition: CodeGen_C.h:140
void visit(const Provide *) override
void visit(const Evaluate *) override
virtual std::string print_type(Type, AppendSpaceIfNeeded space_option=DoNotAppendSpace)
Emit the C name for a halide type.
void print_heap_free(const std::string &alloc_name)
Emit free for the heap allocation.
void visit(const NE *) override
void visit(const Realize *) override
CodeGen_C(std::ostream &dest, const Target &target, OutputKind output_kind=CImplementation, const std::string &include_guard="")
Initialize a C code generator pointing at a particular output stream (e.g.
void visit(const Call *) override
void visit(const UIntImm *) override
void close_scope(const std::string &comment)
Close a C scope (i.e.
void visit(const Or *) override
void visit(const Sub *) override
void create_assertion(const std::string &id_cond, const Expr &message)
void open_scope()
Open a new C scope (i.e.
OutputKind output_kind
Controls whether this instance is generating declarations or definitions and whether the interface us...
Definition: CodeGen_C.h:80
bool is_header()
Return true if only generating an interface, which may be extern "C" or C++.
Definition: CodeGen_C.h:134
bool using_vector_typedefs
true if add_vector_typedefs() has been called.
Definition: CodeGen_C.h:267
void visit(const Max *) override
void visit(const Select *) override
void visit(const Load *) override
void visit(const FloatImm *) override
void forward_declare_type_if_needed(const Type &t)
If the Type is a handle type, emit a forward-declaration for it if we haven't already.
void visit(const LE *) override
void visit(const Div *) override
Expr scalarize_vector_reduce(const VectorReduce *op)
void visit(const Let *) override
void visit(const And *) override
void visit(const Atomic *) override
std::set< const halide_handle_cplusplus_type * > forward_declared
Track which handle types have been forward-declared already.
Definition: CodeGen_C.h:183
bool is_header_or_extern_decl()
Return true if only generating an interface, which may be extern "C" or C++.
Definition: CodeGen_C.h:146
virtual void add_vector_typedefs(const std::set< Type > &vector_types)
Add typedefs for vector types.
void visit(const For *) override
void print_stmt(const Stmt &)
Emit a statement.
Scope< Allocation > allocations
Track the types of allocations to avoid unnecessary casts.
Definition: CodeGen_C.h:168
virtual std::string print_name(const std::string &)
Emit a version of a string that is a valid identifier in C (.
void visit(const GT *) override
void visit(const Free *) override
void visit(const Store *) override
bool emit_atomic_stores
Emit atomic store instructions?
Definition: CodeGen_C.h:264
void visit(const Prefetch *) override
void emit_metadata_getter(const std::string &function_name, const std::vector< LoweredArgument > &args, const std::map< std::string, std::string > &metadata_name_map)
void visit(const Add *) override
Scope heap_allocations
Track which allocations actually went on the heap.
Definition: CodeGen_C.h:171
Target target
The target being generated for.
Definition: CodeGen_C.h:76
virtual std::string print_extern_call(const Call *op)
Bottleneck to allow customization of calls to generic Extern/PureExtern calls.
virtual std::string print_reinterpret(Type, const Expr &)
Emit a statement to reinterpret an expression as another type.
void visit(const AssertStmt *) override
void visit(const EQ *) override
const Target & get_target() const
The target we're generating code for.
Definition: CodeGen_C.h:50
void create_assertion(const Expr &cond, const Expr &message)
void visit(const VectorReduce *) override
void visit(const Ramp *) override
void emit_argv_wrapper(const std::string &function_name, const std::vector< LoweredArgument > &args)
bool is_c_plus_plus_interface()
Return true if generating C++ linkage.
Definition: CodeGen_C.h:151
void visit(const Not *) override
std::string id
An ID for the most recently generated ssa variable.
Definition: CodeGen_C.h:73
void visit_relop(Type t, const Expr &a, const Expr &b, const char *scalar_op, const char *vector_op)
static std::string with_commas(const std::vector< T > &v)
Definition: CodeGen_C.h:255
void visit(const Min *) override
void visit(const Variable *) override
void set_name_mangling_mode(NameMangling mode)
virtual void compile(const LoweredFunc &func, const std::map< std::string, std::string > &metadata_name_map)
Emit a declaration.
void visit(const Mul *) override
void visit(const Mod *) override
void visit(const Allocate *) override
bool have_user_context
True if there is a void * __user_context parameter in the arguments.
Definition: CodeGen_C.h:174
static std::string with_sep(const std::vector< T > &v, const std::string &sep)
Definition: CodeGen_C.h:243
virtual void compile(const Buffer<> &buffer)
void visit(const Cast *) override
virtual std::string print_assignment(Type t, const std::string &rhs)
Emit an SSA-style assignment, and set id to the freshly generated name.
bool extern_c_open
Track current calling convention scope.
Definition: CodeGen_C.h:177
bool inside_atomic_mutex_node
Are we inside an atomic node that uses mutex locks? This is used for detecting deadlocks from nested ...
Definition: CodeGen_C.h:261
void visit(const IfThenElse *) override
void visit(const Broadcast *) override
void visit(const StringImm *) override
void compile(const Module &module)
Emit the declarations contained in the module as C code.
void visit(const Shuffle *) override
std::string print_expr(const Expr &)
Emit an expression as an assignment, then return the id of the resulting var.
void visit(const LT *) override
std::string print_scalarized_expr(const Expr &e)
Convert a vector Expr into a series of scalar Exprs, then reassemble into vector of original type.
void visit(const LetStmt *) override
bool uses_gpu_for_loops
True if at least one gpu-based for loop is used.
Definition: CodeGen_C.h:180
void visit(const Fork *) override
void visit(const ProducerConsumer *) override
void visit(const Acquire *) override
std::map< std::string, std::string > cache
A cache of generated values in scope.
Definition: CodeGen_C.h:83
IntegerSuffixStyle integer_suffix_style
How to emit 64-bit integer constants.
Definition: CodeGen_C.h:64
void visit(const IntImm *) override
void visit_binop(Type t, const Expr &a, const Expr &b, const char *op)
std::string print_cast_expr(const Type &, const Expr &)
Like print_expr, but cast the Expr to the given Type.
An IRVisitor that emits IR to the given output stream in a human readable form.
Definition: IRPrinter.h:102
void visit(const IntImm *) override
A common pattern when traversing Halide IR is that you need to keep track of stuff when you find a Le...
Definition: Scope.h:94
A halide module.
Definition: Module.h:172
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
NameMangling
An enum to specify calling convention for extern stages.
Definition: Function.h:24
A fragment of Halide syntax.
Definition: Expr.h:256
The sum of two expressions.
Definition: IR.h:38
Allocate a scratch area called with the given name, type, and size.
Definition: IR.h:353
Logical and - are both expressions true.
Definition: IR.h:157
If the 'condition' is false, then evaluate and return the message, which should be a call to an error...
Definition: IR.h:276
Lock all the Store nodes in the body statement.
Definition: IR.h:870
A vector with 'lanes' elements, in which every element is 'value'.
Definition: IR.h:241
A function call.
Definition: IR.h:466
The actual IR nodes begin here.
Definition: IR.h:29
The ratio of two expressions.
Definition: IR.h:65
Is the first expression equal to the second.
Definition: IR.h:103
Evaluate and discard an expression, presumably because it has some side-effect.
Definition: IR.h:452
Floating point constants.
Definition: Expr.h:234
A for loop.
Definition: IR.h:747
A pair of statements executed concurrently.
Definition: IR.h:433
Free the resources associated with the given buffer.
Definition: IR.h:389
Is the first expression greater than or equal to the second.
Definition: IR.h:148
Is the first expression greater than the second.
Definition: IR.h:139
An if-then-else block.
Definition: IR.h:442
Integer constants.
Definition: Expr.h:216
Is the first expression less than or equal to the second.
Definition: IR.h:130
Is the first expression less than the second.
Definition: IR.h:121
A let expression, like you might find in a functional language.
Definition: IR.h:253
The statement form of a let node.
Definition: IR.h:264
Load a value from a named symbol if predicate is true.
Definition: IR.h:199
Definition of a lowered function.
Definition: Module.h:133
The greater of two values.
Definition: IR.h:94
The lesser of two values.
Definition: IR.h:85
The remainder of a / b.
Definition: IR.h:76
The product of two expressions.
Definition: IR.h:56
Is the first expression not equal to the second.
Definition: IR.h:112
Logical not - true if the expression false.
Definition: IR.h:175
Logical or - is at least one of the expression true.
Definition: IR.h:166
Represent a multi-dimensional region of a Func or an ImageParam that needs to be prefetched.
Definition: IR.h:847
This node is a helpful annotation to do with permissions.
Definition: IR.h:297
This defines the value of a function at a multi-dimensional location.
Definition: IR.h:336
A linear ramp vector node.
Definition: IR.h:229
Allocate a multi-dimensional buffer of the given type and size.
Definition: IR.h:403
A ternary operator.
Definition: IR.h:186
Construct a new vector by taking elements from another sequence of vectors.
Definition: IR.h:778
A reference-counted handle to a statement node.
Definition: Expr.h:417
Store a 'value' to the buffer called 'name' at a given 'index' if 'predicate' is true.
Definition: IR.h:315
String constants.
Definition: Expr.h:243
The difference of two expressions.
Definition: IR.h:47
Unsigned integer constants.
Definition: Expr.h:225
A named variable.
Definition: IR.h:700
Horizontally reduce a vector to a scalar or narrower vector using the given commutative and associati...
Definition: IR.h:888
A struct representing a target machine and os to generate code for.
Definition: Target.h:19
Types in the halide type system.
Definition: Type.h:266