1 #ifndef HALIDE_CODEGEN_POSIX_H
2 #define HALIDE_CODEGEN_POSIX_H
3 
4 /** \file
5  * Defines a base-class for code-generators on posixy cpu platforms
6  */
7 
8 #include "CodeGen_LLVM.h"
9 
10 namespace Halide {
11 namespace Internal {
12 
13 /** A code generator that emits posix code from a given Halide stmt. */
14 class CodeGen_Posix : public CodeGen_LLVM {
15 public:
16     /** Create an posix code generator. Processor features can be
17      * enabled using the appropriate arguments */
18     CodeGen_Posix(Target t);
19 
20 protected:
21     using CodeGen_LLVM::visit;
22 
23     /** Posix implementation of Allocate. Small constant-sized allocations go
24      * on the stack. The rest go on the heap by calling "halide_malloc"
25      * and "halide_free" in the standard library. */
26     // @{
27     void visit(const Allocate *) override;
28     void visit(const Free *) override;
29     // @}
30 
31     /** It can be convenient for backends to assume there is extra
32      * padding beyond the end of a buffer to enable faster
33      * loads/stores. This function gets the padding required by the
34      * implementing target. */
35     virtual int allocation_padding(Type type) const;
36 
37     /** A struct describing heap or stack allocations. */
38     struct Allocation {
39         /** The memory */
40         llvm::Value *ptr = nullptr;
41 
42         /** Destructor stack slot for this allocation. */
43         llvm::Value *destructor = nullptr;
44 
45         /** Function to accomplish the destruction. */
46         llvm::Function *destructor_function = nullptr;
47 
48         /** Pseudostack slot for this allocation. Non-null for
49          * allocations of type Stack with dynamic size. */
50         llvm::Value *pseudostack_slot = nullptr;
51 
52         /** The (Halide) type of the allocation. */
53         Type type;
54 
55         /** How many bytes this allocation is, or 0 if not
56          * constant. */
57         int constant_bytes = 0;
58 
59         /** How many bytes of stack space used. 0 implies it was a
60          * heap allocation. */
61         int stack_bytes = 0;
62 
63         /** A unique name for this allocation. May not be equal to the
64          * Allocate node name in cases where we detect multiple
65          * Allocate nodes can share a single allocation. */
66         std::string name;
67     };
68 
69     /** The allocations currently in scope. The stack gets pushed when
70      * we enter a new function. */
71     Scope<Allocation> allocations;
72 
73     std::string get_allocation_name(const std::string &n) override;
74 
75 private:
76     /** Stack allocations that were freed, but haven't gone out of
77      * scope yet.  This allows us to re-use stack allocations when
78      * they aren't being used. */
79     std::vector<Allocation> free_stack_allocs;
80 
81     /** current size of all alloca instances in use; this is tracked only
82      * for debug output purposes. */
83     size_t cur_stack_alloc_total{0};
84 
85     /** Generates code for computing the size of an allocation from a
86      * list of its extents and its size. Fires a runtime assert
87      * (halide_error) if the size overflows 2^31 -1, the maximum
88      * positive number an int32_t can hold. */
89     llvm::Value *codegen_allocation_size(const std::string &name, Type type, const std::vector<Expr> &extents, const Expr &condition);
90 
91     /** Allocates some memory on either the stack or the heap, and
92      * returns an Allocation object describing it. For heap
93      * allocations this calls halide_malloc in the runtime, and for
94      * stack allocations it either reuses an existing block from the
95      * free_stack_blocks list, or it saves the stack pointer and calls
96      * alloca.
97      *
98      * This call returns the allocation, pushes it onto the
99      * 'allocations' map, and adds an entry to the symbol table called
100      * name.host that provides the base pointer.
101      *
102      * When the allocation can be freed call 'free_allocation', and
103      * when it goes out of scope call 'destroy_allocation'. */
104     Allocation create_allocation(const std::string &name, Type type, MemoryType memory_type,
105                                  const std::vector<Expr> &extents,
106                                  const Expr &condition, const Expr &new_expr, std::string free_function);
107 
108     /** Free an allocation previously allocated with
109      * create_allocation */
110     void free_allocation(const std::string &name);
111 };
112 
113 }  // namespace Internal
114 }  // namespace Halide
115 
116 #endif
117