#ifndef HALIDE_CODEGEN_POSIX_H #define HALIDE_CODEGEN_POSIX_H /** \file * Defines a base-class for code-generators on posixy cpu platforms */ #include "CodeGen_LLVM.h" namespace Halide { namespace Internal { /** A code generator that emits posix code from a given Halide stmt. */ class CodeGen_Posix : public CodeGen_LLVM { public: /** Create an posix code generator. Processor features can be * enabled using the appropriate arguments */ CodeGen_Posix(const Target &t); protected: using CodeGen_LLVM::visit; /** Posix implementation of Allocate. Small constant-sized allocations go * on the stack. The rest go on the heap by calling "halide_malloc" * and "halide_free" in the standard library. */ // @{ void visit(const Allocate *) override; void visit(const Free *) override; // @} /** It can be convenient for backends to assume there is extra * padding beyond the end of a buffer to enable faster * loads/stores. This function gets the padding required by the * implementing target. */ virtual int allocation_padding(Type type) const; /** A struct describing heap or stack allocations. */ struct Allocation { /** The memory */ llvm::Value *ptr = nullptr; /** Destructor stack slot for this allocation. */ llvm::Value *destructor = nullptr; /** Function to accomplish the destruction. */ llvm::Function *destructor_function = nullptr; /** Pseudostack slot for this allocation. Non-null for * allocations of type Stack with dynamic size. */ llvm::Value *pseudostack_slot = nullptr; /** The (Halide) type of the allocation. */ Type type; /** How many bytes this allocation is, or 0 if not * constant. */ int constant_bytes = 0; /** How many bytes of stack space used. 0 implies it was a * heap allocation. */ int stack_bytes = 0; /** A unique name for this allocation. May not be equal to the * Allocate node name in cases where we detect multiple * Allocate nodes can share a single allocation. */ std::string name; }; /** The allocations currently in scope. The stack gets pushed when * we enter a new function. */ Scope allocations; std::string get_allocation_name(const std::string &n) override; private: /** Stack allocations that were freed, but haven't gone out of * scope yet. This allows us to re-use stack allocations when * they aren't being used. */ std::vector free_stack_allocs; /** current size of all alloca instances in use; this is tracked only * for debug output purposes. */ size_t cur_stack_alloc_total{0}; /** Generates code for computing the size of an allocation from a * list of its extents and its size. Fires a runtime assert * (halide_error) if the size overflows 2^31 -1, the maximum * positive number an int32_t can hold. */ llvm::Value *codegen_allocation_size(const std::string &name, Type type, const std::vector &extents, const Expr &condition); /** Allocates some memory on either the stack or the heap, and * returns an Allocation object describing it. For heap * allocations this calls halide_malloc in the runtime, and for * stack allocations it either reuses an existing block from the * free_stack_blocks list, or it saves the stack pointer and calls * alloca. * * This call returns the allocation, pushes it onto the * 'allocations' map, and adds an entry to the symbol table called * name.host that provides the base pointer. * * When the allocation can be freed call 'free_allocation', and * when it goes out of scope call 'destroy_allocation'. */ Allocation create_allocation(const std::string &name, Type type, MemoryType memory_type, const std::vector &extents, const Expr &condition, const Expr &new_expr, std::string free_function); /** Free an allocation previously allocated with * create_allocation */ void free_allocation(const std::string &name); }; } // namespace Internal } // namespace Halide #endif