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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
* This file is part of tela the Tensor Language.
* Copyright (c) 1994-2001 Pekka Janhunen
*/
#ifdef __GNUC__
# pragma interface
#endif
#include "machine.H"
#include "common.H"
#define COMPTYPE Toperand
#define DEFAULT_COMPVALUE Toperand()
#define LINEARLIST TInstructionList1
#include "templ/tLL.H"
#undef LINEARLIST
#undef DEFAULT_COMPVALUE
#undef COMPTYPE
class TInstructionList : public TInstructionList1 {
private:
int maxNops; // Maximum number of operands in any instruction
public:
TInstructionList() : TInstructionList1(0), maxNops(0) {}
void add(Tcode code) {append(Toperand(code));}
void add(Tcode code, const Toperand& op1);
void add(Tcode code, const Toperand& op1, const Toperand& op2);
void add(Tcode code, const Toperand& op1, const Toperand& op2, const Toperand& op3);
void add(Tcode code, const Toperand& op1, const Toperand& op2, const Toperand& op3, const Toperand& op4);
void add(Tcode code, int Noperands);
int MaxNops() const {return maxNops;}
void set_maxNops(int i) {maxNops = i;}
void clear() {TInstructionList1::operator=(0);}
friend ostream& operator<<(ostream& o, const TInstructionList& il);
};
#define MAX_NOPERANDS 200
class TObjectStack { // Runtime stack, common for all functions
private:
TObjectLL LL; // Implemented as a linear list of TObjectPtrs
public:
TObjectStack() : LL(0) {} // Initially, the stack is empty
void push(TObjectPtr ptr) {LL.append(ptr);} // stack.push(&obj) works
void push(Tobject& obj) {LL.append(&obj);} // stack.push(obj) also works
void push(int N) {int L=LL.length(); LL=L+N;} // push N null pointers
Tobject& top() const {return *LL[LL.length()-1];} // stack.top() gives ref to last object pushed
void pop(int N); // shorten the stack by N objects
int length() const {return LL.length();} // stack.length() == number of objects in the stack
TObjectPtr& operator[](int i) {return LL[LL.length()-1-i];} // stack[0] == &stack.top(), etc.
friend inline ostream& operator<<(ostream& o, const TObjectStack& stack);
~TObjectStack();
};
inline ostream& operator<<(ostream& o, const TObjectStack& stack) {return o << stack.LL;}
extern TObjectStack theStack; // General runtime stack
extern void optimize(TInstructionList& il, TIntLL& linenums, const Tsymbol *symptr);
//extern void Call(const Tobject& fn,
// const TConstObjectPtr inputs[], const int Ninputs,
// const TObjectPtr outputs[], const int Noutputs,
// const Tsymbol* symptr=0, bool check_that_first_output_not_obligatory=false);
class Tprg { // flatcode sequence with static objects
private:
TInstructionList il; // the sequence of flatcode words
TObjectLL ol; // list of static objects
TObjectLL* old_olptr; // ptr to previous list of static objects
TIntLL linenums; // source line number information
int nargin; // (Maximum) number of input objects
int nargout; // (Maximum) number of output objects
int nargin_min; // Minimum number of input objects
int nargout_min; // Minimum number of output objects
int nlocal; // Number of local non-temporary objects
int ntemp; // Number of local temporary objects (introduced by codegen)
int nstack; // Stack frame size
int inputellipsis; // Nonzero if input arglist ends with ellipsis (...)
int outputellipsis; // Nonzero if output arglist ends with ellipsis
Tchar *filename; // source file name from this Tprg was compiled
const Tsymbol* symptr; // pointer to symbol whose value this Tprg is
void CalcStack();
void executeInstructionSequence();
void MakeCurrent()
{old_olptr=Toperand::objLLptr; Toperand::objLLptr = &ol;} // Activate this Tprg to receive static objects into its ol
void checkreadonlyoperand(const Toperand&, int) const;
Tprg(const Tprg&); // do not implement
Tprg& operator=(const Tprg&); // do not implement
friend void Call(const Tobject& fn,
const TConstObjectPtr inputs[], const int Ninputs,
const TObjectPtr outputs[], const int Noutputs,
const Tsymbol* symptr=0, bool check_that_first_output_not_obligatory=false);
public:
Tprg(const Tchar *fn);
Tprg(const Tchar *fn, int in, int out);
Tprg(const Tchar *fn, int in, int out, int loc);
Tprg(const Tchar *fn, int in, int out, int minin, int minout, int loc, const Tsymbol* sympointer=0);
void SetInputEllipsisFlag() {inputellipsis=1; CalcStack();}
void SetOutputEllipsisFlag() {outputellipsis=1; CalcStack();}
int HasInputEllipsis() const {return inputellipsis;}
int HasOutputEllipsis() const {return outputellipsis;}
void JustMakeCurrent()
{Toperand::objLLptr = &ol;} // Same as MakeCurrent but do not modify old_oldptr
int FindLineNumber(int startPC=0) const; // find line number after error
// --- add functions, add new instructions to program
void add(Tcode code) {il.add(code); linenums.append(global::lineno);}
void add(Tcode code, const Toperand& op1) {il.add(code,op1); linenums.append(global::lineno);}
void add(Tcode code, const Toperand& op1, const Toperand& op2) {il.add(code,op1,op2); linenums.append(global::lineno);}
void add(Tcode code, const Toperand& op1, const Toperand& op2, const Toperand& op3)
{il.add(code,op1,op2,op3); linenums.append(global::lineno);}
void add(Tcode code, const Toperand& op1, const Toperand& op2, const Toperand& op3, const Toperand& op4)
{il.add(code,op1,op2,op3,op4); linenums.append(global::lineno);}
// --- another form of add function: first use add(code,N), then call append() exactly N times
// --- this can be used to form instructions with arbitrary number of operands
void add(Tcode code, int Noperands) {il.add(code,Noperands); linenums.append(global::lineno);}
void append(const Toperand& op) {il.append(op);}
// --- execution functions
void execute(const TConstObjectPtr[],int, const TObjectPtr[],int, const Tsymbol*fnsymptr=0);
// --- function to add (possibly) more temporaries
void AllocTemporaries(int N) {if (N>ntemp) {ntemp=N; CalcStack();}}
// --- inquiry functions
int length() const {return il.length();} // prg.length() returns number of flatcode words in prg
Toperand& operator[](int i) const {return il[i];} // prg[i] returns the ith flatcode word in prg
int Nstatic() const {return ol.length();} // prg.Nstatic() is the number of static objects
TObjectPtr nthobject(int n) {return ol[n];} // prg.nthobject(n) returns the nth static object in prg
int Nargin() const {return nargin;} // prg.Nargin() returns the maximum number of input objects for prg
int Nargout() const {return nargout;} // prg.Nargout() returns the maximum number of output objects for prg
int NMinArgin() const {return nargin_min;} // prg.NMinArgin() returns the minimum number of input objects for prg
int NMinArgout() const {return nargout_min;} // prg.NMinArgout() returns the minimum number of output objects for prg
int Nlocal() const {return nlocal;} // prg.Nlocal() returns the number of local objects in prg
int Ntemp() const {return ntemp;} // prg.Ntemp() returns the number of temporary local objects
int StackFrameSize() const {return nstack;} // prg.StackFrameSize() returns the number of objects in stack frame
int PermanentFrameSize() const {return 1+nargin+nargout+nlocal+(inputellipsis!=0)+(outputellipsis!=0);} // same as StackFrameSize but without temporaries
const Tchar *FileName() const {return filename;}
const Tsymbol& Symbol() const {return *symptr;}
int MaxNops() const {return il.MaxNops();}
Tcode LastOpcode() const; // prg.LastOpcode() is the last opcode appended, or Klit if none is found
// --- function to check that input args are not modified
void checkreadonlyvars() const;
// --- function to optimize flatcode
void optimize() {::optimize(il,linenums,symptr);}
// --- outputting
friend ostream& operator<<(ostream& o, Tprg& prg);
// --- destructor
~Tprg();
};
class TCodeStack {
private:
struct TCodeStackNode {
Tprg *prgptr;
TCodeStackNode *next;
};
TCodeStackNode *p;
TCodeStack(const TCodeStack&); // do not implement
TCodeStack& operator=(const TCodeStack&); // do not implement
public:
TCodeStack() : p(0) {}
int isempty() const {return p==0;}
void push(Tprg* ptr);
Tprg* top() const;
Tprg* pop();
};
extern TCodeStack theCodeStack; // General stack of pointer to Tprgs
extern void PerformanceReport(int longflag=0);
|