summaryrefslogtreecommitdiff
path: root/backend/src/backend/context.hpp
blob: bbf0dc93051f705c3b1737414573021fa3a088ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* 
 * Copyright © 2012 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Benjamin Segovia <benjamin.segovia@intel.com>
 */

#ifndef __GBE_CONTEXT_HPP__
#define __GBE_CONTEXT_HPP__

#include "ir/instruction.hpp"
#include "backend/program.h"
#include "sys/set.hpp"
#include "sys/map.hpp"
#include "sys/platform.hpp"
#include <string>

namespace gbe {
namespace ir {

  class Unit;        // Contains the complete program
  class Function;    // We compile a function into a kernel
  class Liveness;    // Describes liveness of each ir function register
  class FunctionDAG; // Describes the instruction dependencies

} /* namespace ir */
} /* namespace gbe */

namespace gbe
{
  class Kernel;                 // context creates Kernel
  class RegisterFilePartitioner; // Partition register file for reg allocation

  /*! Context is the helper structure to build the Gen ISA or simulation code
   *  from GenIR
   */
  class Context : public NonCopyable
  {
  public:
    /*! Create a new context. name is the name of the function we want to
     *  compile
     */
    Context(const ir::Unit &unit, const std::string &name);
    /*! Release everything needed */
    virtual ~Context(void);
    /*! Compile the code */
    Kernel *compileKernel(void);
    /*! Tells if the labels is used */
    INLINE bool isLabelUsed(ir::LabelIndex index) const {
      return usedLabels.contains(index);
    }
    /*! Get the function graph */
    INLINE const ir::FunctionDAG &getFunctionDAG(void) const { return *dag; }
    /*! Get the liveness information */
    INLINE const ir::Liveness &getLiveness(void) const { return *liveness; }
    /*! Tells if the register is used */
    bool isRegUsed(const ir::Register &reg) const;
    /*! Indicate if a register is scalar or not */
    bool isScalarReg(const ir::Register &reg) const;
    /*! Get the kernel we are currently compiling */
    INLINE Kernel *getKernel(void) const { return this->kernel; }
    /*! Get the function we are currently compiling */
    INLINE const ir::Function &getFunction(void) const { return this->fn; }
    /*! Get the target label index for the given instruction */
    INLINE ir::LabelIndex getLabelIndex(const ir::Instruction *insn) const {
      GBE_ASSERT(JIPs.find(insn) != JIPs.end());
      return JIPs.find(insn)->second;
    }
    /*! Only GOTO and some LABEL instructions may have JIPs */
    INLINE bool hasJIP(const ir::Instruction *insn) const {
      return JIPs.find(insn) != JIPs.end();
    }
    /*! Allocate some memory in the register file */
    int16_t allocate(int16_t size, int16_t alignment);
    /*! Deallocate previously allocated memory */
    void deallocate(int16_t offset);
  protected:
    /*! Build the instruction stream (to be implemented) */
    virtual void emitCode(void) = 0;
    /*! Allocate a new empty kernel (to be implemented) */
    virtual Kernel *allocateKernel(void) = 0;
    /*! Look if a stack is needed and allocate it */
    void buildStack(void);
    /*! Build the curbe patch list for the given kernel */
    void buildPatchList(void);
    /*! Build the list of arguments to set to launch the kernel */
    void buildArgList(void);
    /*! Build the sets of used labels */
    void buildUsedLabels(void);
    /*! Build JIPs for each branch and possibly labels. Can be different from
     *  the branch target due to unstructured branches
     */
    void buildJIPs(void);
    /*! Insert a new entry with the given size in the Curbe. Return the offset
     *  of the entry
     */
    void newCurbeEntry(gbe_curbe_type value, uint32_t subValue, uint32_t size, uint32_t alignment = 0);
    /*! Provide for each branch and label the label index target */
    typedef map<const ir::Instruction*, ir::LabelIndex> JIPMap;
    const ir::Unit &unit;                 //!< Unit that contains the kernel
    const ir::Function &fn;               //!< Function to compile
    std::string name;                     //!< Name of the kernel to compile
    Kernel *kernel;                       //!< Kernel we are building
    ir::Liveness *liveness;               //!< Liveness info for the variables
    ir::FunctionDAG *dag;                 //!< Graph of values on the function
    RegisterFilePartitioner *partitioner; //!< Handle register file partionning
    set<ir::LabelIndex> usedLabels;       //!< Set of all used labels
    JIPMap JIPs;                          //!< Where to jump all labels/branches
    uint32_t simdWidth;                   //!< Number of lanes per HW threads
    GBE_CLASS(Context);                   //!< Use custom allocators
  };

} /* namespace gbe */

#endif /* __GBE_CONTEXT_HPP__ */