|
| 1 | +#ifndef _INTRIN_HH_ |
| 2 | +#define _INTRIN_HH_ |
| 3 | + |
| 4 | +#include <set> |
| 5 | +#include <cstdio> |
| 6 | +#include <vector> |
| 7 | +#include <cstdlib> |
| 8 | +#include "Resources.h" |
| 9 | +#include "RegAlloc.h" |
| 10 | + |
| 11 | +namespace intr |
| 12 | +{ |
| 13 | +class Intrin; |
| 14 | +class IntrinManager; |
| 15 | + |
| 16 | +/* sub intrin class */ |
| 17 | +/** |
| 18 | + * Intrin type: |
| 19 | + * label: len = 1, LABEL: |
| 20 | + * vreturn: len = 1, return |
| 21 | + * jmp: len = 2, goto LABEL |
| 22 | + * vardef: len = 2, 'var' varmame |
| 23 | + * endfun: len = 2, end funname |
| 24 | + * param: len = 2, param rvar |
| 25 | + * return: len = 2, return rvar |
| 26 | + * funcst: len = 2, fname '['num']' |
| 27 | + * callvfun: len = 2, call funcname |
| 28 | + *--assign: len = 3, lvar = rvar OPTIMIZABLE |
| 29 | + * arrdec: len = 3, 'var' INT varname |
| 30 | + * callfunc: len = 4, lvar = call funcname OPTIMIZABLE |
| 31 | + *--unaryexpr: len = 4, lvar = OP1 rvar OPTIMIZABLE |
| 32 | + *--aassv: len = 4, arr '['num']' = rval |
| 33 | + *--vassa: len = 4, lval = arr '['num']' OPTIMIZABLE |
| 34 | + *--binexpr: len = 5, lvar = rvar OP2 rvar OPTIMIZABLE |
| 35 | + * cjmp: len = 6, 'if' rvar LOP rvar 'goto' LABEL |
| 36 | + */ |
| 37 | +class Ilabel; |
| 38 | +class Ivreturn; |
| 39 | +class Ijmp; |
| 40 | +class Ivardef; |
| 41 | +class Iendfun; |
| 42 | +class Iparam; |
| 43 | +class Ireturn; |
| 44 | +class Ifuncst; |
| 45 | +class Icallvfun; |
| 46 | +class Iassign; |
| 47 | +class Iarrdec; |
| 48 | +class Icallfunc; |
| 49 | +class Iunaryexpr; |
| 50 | +class Iaassv; |
| 51 | +class Ivassa; |
| 52 | +class Ibinexpr; |
| 53 | +class Icjmp; |
| 54 | + |
| 55 | +class Function; |
| 56 | + |
| 57 | + |
| 58 | +class Intrin |
| 59 | +{ |
| 60 | + protected: |
| 61 | + int lineno; |
| 62 | + std::string code; |
| 63 | + std::set<res::EeyoreVariable> def; |
| 64 | + std::set<res::EeyoreVariable> use; |
| 65 | + Function &f; |
| 66 | + |
| 67 | + public: |
| 68 | + Intrin(int line, Function &m) : lineno(line), f(m) {} |
| 69 | + virtual int getline() const {return lineno;} |
| 70 | + virtual std::set<res::EeyoreVariable> &getdef(){return def;} |
| 71 | + virtual std::set<res::EeyoreVariable> &getuse(){return use;} |
| 72 | + virtual std::string gencode(FILE *f) const = 0; |
| 73 | + |
| 74 | + virtual int getPrevLineno() const; |
| 75 | + virtual void dbg_print() const = 0; |
| 76 | + virtual void setcode(const std::string &c) |
| 77 | + {this->code = c;} |
| 78 | + virtual std::string getcode() { return code;} |
| 79 | +}; |
| 80 | + |
| 81 | +class Function |
| 82 | +{ |
| 83 | + private: |
| 84 | + using IntrinSet = std::map<int, Intrin*>; |
| 85 | + IntrinSet intrins; |
| 86 | + res::RegPool tempPool; |
| 87 | + res::StackFrame stk; |
| 88 | + bool inited = false; |
| 89 | + private: |
| 90 | + res::RegAllocer::AllocResult_t allocresult; |
| 91 | + public: |
| 92 | + int paramcnt = -1; |
| 93 | + public: |
| 94 | + Function(); |
| 95 | + void AddIntrin(Intrin *); |
| 96 | + void Initialize(); // call after finishing AddIntrin |
| 97 | + int GetSize(){Initialize(); return this->stk.GetSlots();} |
| 98 | + IntrinSet &getIntrins(){return intrins;} |
| 99 | + bool Optimize(res::Liveness &liveness); |
| 100 | + res::StackFrame &getStack(){return stk;} |
| 101 | + |
| 102 | + private: |
| 103 | + int tempParamCount = 0; |
| 104 | + void _savereg(FILE *f, int rid) |
| 105 | + { |
| 106 | + auto offset = this->stk.GetRegAddr(rid); |
| 107 | + this->stk.gencode_spillin(f, offset, rid); |
| 108 | + //Emit(f," // ^ _savereg\n"); |
| 109 | + } |
| 110 | + void _restorereg(FILE *f, int rid) |
| 111 | + { |
| 112 | + auto offset = this->stk.GetRegAddr(rid); |
| 113 | + this->stk.gencode_spillout(f, offset, rid); |
| 114 | + //Emit(f," // ^ _restore reg\n"); |
| 115 | + } |
| 116 | + public: |
| 117 | + Intrin *getPrevIntrin(const Intrin *in); |
| 118 | + /* ABI for codegen */ |
| 119 | + void gencode(FILE *f, res::Liveness &liveness); |
| 120 | + std::string getReg(FILE *f, res::RightVariable *rvar, int lineno); |
| 121 | + std::string PrepareParam(FILE *f); // return the next free "a?" reg |
| 122 | + void StartFun(FILE *f); // save callee saved regs |
| 123 | + void PrepareCalling(FILE *f); // store the regs into stack |
| 124 | + void EndCalling(FILE *f); // restore the regs from stack |
| 125 | + void EndFun(FILE *f); // restore callee saved regs |
| 126 | + void BackToStack(FILE *f, res::EeyoreVariable *lvar, int reg, int offreg = 0); |
| 127 | + void BackToGlobal(FILE *f, res::EeyoreVariable *gvar, int reg, int offreg = 0); |
| 128 | + void BackToMemory(FILE *f, res::EeyoreVariable *var, int reg, int offreg = 0); |
| 129 | + void LoadVariable(FILE *f, res::EeyoreVariable *var, int reg); |
| 130 | +}; |
| 131 | + |
| 132 | +/** |
| 133 | + * IntrinManager: give a line of input and parse a intrin |
| 134 | + */ |
| 135 | +class IntrinManager |
| 136 | +{ |
| 137 | + private: |
| 138 | + static const std::string GLOBAL_RESMGR_NAME;// = "global"; |
| 139 | + static const std::string GLOBAL_SCOPE_NAME;// = "f__init"; |
| 140 | + private: |
| 141 | + std::vector<std::string> input; //used for debug; |
| 142 | + int lines = 1; |
| 143 | + using IntrinSet = std::map<int, Intrin*>; |
| 144 | + IntrinSet intrins; |
| 145 | + |
| 146 | + /* function management */ |
| 147 | + std::map<std::string, Function*> funcs; |
| 148 | + std::string curr_func; |
| 149 | + |
| 150 | + /* resmgr */ |
| 151 | + /* label searching */ |
| 152 | + std::map<std::string, int> labels; /* lineno of label itself */ |
| 153 | + |
| 154 | + private: |
| 155 | + Intrin *_addintrin(Intrin *in) |
| 156 | + { |
| 157 | + in->setcode(input.back()); |
| 158 | + intrins[this->lines] = in; |
| 159 | + funcs[curr_func]->AddIntrin(in); // insert into function |
| 160 | + ++lines; |
| 161 | + return in; |
| 162 | + } |
| 163 | + public: |
| 164 | + IntrinManager() : lines(1) |
| 165 | + { |
| 166 | + this->lines = 1; |
| 167 | + auto &s = GLOBAL_RESMGR_NAME; |
| 168 | + curr_func = GLOBAL_SCOPE_NAME; |
| 169 | + funcs[curr_func] = new Function(); |
| 170 | + } |
| 171 | + /** |
| 172 | + * add intrin (update labels here) |
| 173 | + * search for label |
| 174 | + * give an intrin's succ |
| 175 | + * set correct ResourceManager |
| 176 | + */ |
| 177 | + std::string getInputLine(int lineno) |
| 178 | + {return input[lineno - 1];} |
| 179 | + void AddIntrin(const std::string &line); |
| 180 | + int SearchLabel(const std::string &label); //param have no ':', return the next intrin |
| 181 | + std::vector<Intrin*> Succ(IntrinSet &, int lineno); |
| 182 | + void NewScope(const std::string &scopename); |
| 183 | + void EndScope(); |
| 184 | + |
| 185 | + void gencode(FILE *f); |
| 186 | + |
| 187 | + std::vector<std::string> getFuncNames() |
| 188 | + { |
| 189 | + std::vector<std::string> ret; |
| 190 | + for(auto func : this->funcs) ret.push_back(func.first); |
| 191 | + return ret; |
| 192 | + } |
| 193 | + Function &getfunc(const std::string &f) { return *this->funcs[f]; } |
| 194 | +}; |
| 195 | + |
| 196 | +/* Functions */ |
| 197 | +using Liveness = res::Liveness; |
| 198 | +Liveness LivenessAnalysis(IntrinManager &m, const std::string &funcname); |
| 199 | +} //namespace intr |
| 200 | + |
| 201 | + |
| 202 | +#endif |
0 commit comments