Logo Search packages:      
Sourcecode: tela version File versions  Download package

Ctgen.C

/*
 * This file is part of tela the Tensor Language.
 * Copyright (c) 1994-2000 Pekka Janhunen
 */

#include "prg.H"

static int avoid_ctors = 0;
static char *star = "";             // This MUST be set to "*" if avoid_ctors is nonzero!!!

//#define UNIQ "__tela_"
#define UNIQ ""
#define VARBODY UNIQ "var"
#define CONSTBODY UNIQ "cnst"
#define GLOBBODY UNIQ "glob"
#define INPUTS UNIQ "inputs"
#define OUTPUTS UNIQ "outputs"
#define INDICES UNIQ "aux_index_vector"
#define FNAME_APPENDIX "function" /* Must be same as in ctpp.C */
#define MAXSYMBOLS 1000 /* maximum number of different symbols referenced in a function */
//#ifdef AVOID_CTORS
//#  define STAR "*"
//#else
//#  define STAR ""
//#endif

extern char *VersionString;

extern void SetAvoidCtorsFlag(int flag)
// Call this function from the outside to alter the avoid_ctors flag
{
      if (flag) {
            avoid_ctors = 1;
            star = "*";
      } else {
            avoid_ctors = 0;
            star = "";
      }
}

static char*barename(const Tstring& S) {
      // Remove a leading package selector from symbol name
      char *ptr = strchr((char*)S,':');
      return ptr ? ptr+1 : (char*)S;
}

static char*barename(const Tchar*s) {
      char *ptr = strchr((char*)s,':');
      return ptr ? ptr+1 : (char*)s;
}

struct VarRef {Toperand op; VarRef(Toperand op1) : op(op1) {}};

static Tprg *ThePrgptr;

ostream& operator<<(ostream& o, const VarRef& v) {
      const Toperand& op = v.op;
      switch (op.kind()) {    
      case Ksym:
            o << "(*(" << barename(op.symbol().name()) << GLOBBODY << "->value()))";
            break;
      case Kpar:
            o << '(' << (0<op.offset() && op.offset() <= ThePrgptr->Nargin()+ThePrgptr->Nargout() ? "" : star) << VARBODY << op.offset() << ')';
            break;
      case Kobj:
            o << '(' << star << CONSTBODY << op.offset() << ')';
            break;
      case Klit:
            if (op.literal()==1)
                  o << '(' << star << UNIQ << "UnitObject" << ')';
            else {
                  cerr << "Ctgen warning: Literal which is not equal to 1\n";
                  o << op.literal();
            }
            break;
      case Kallrange:
            o << '(' << star << UNIQ << "VoidObject" << ')';
            break;
      default:
            o << instrinfo[op.opcode()].mnemonic;
            break;
      }
      return o;
}

// Class TCForm is a wrapper class, when outputted, it prints an object in C-compilable form

class TCForm {
 private:
      const Tobject* ptr;

        TCForm(const TCForm&); // do not implement
        TCForm& operator=(const TCForm&); // do not implement

 public:
      TCForm(const Tobject& obj) : ptr(&obj) {}
      friend ostream& operator<<(ostream& o, const TCForm& cf);
};

ostream& operator<<(ostream& o, const TCForm& cf) {
      const Tobject& obj = *cf.ptr;
      switch (obj.kind()) {
      case Kcomplex:
            o << "Tcomplex(" << real(obj.ComplexValue()) << ',' << imag(obj.ComplexValue()) << ')';
            break;
      default:
            o << obj;
      }
      return o;
}

static void F1arb(ostream& o, const char*opname, const Toperand& arg1) {
      o << opname << "(" << VarRef(arg1) << ");\n";
}

static void F2arb(ostream& o, const char*opname, const Toperand& arg1, const Toperand& arg2) {
      o << opname << "(" << VarRef(arg1) << "," << VarRef(arg2) << ");\n";
}

static void F3arb(ostream& o, const char*opname, const Toperand& arg1, const Toperand& arg2, const Toperand& arg3) {
      o << opname << "(" << VarRef(arg1) << "," << VarRef(arg2) << "," << VarRef(arg3) << ");\n";
}

#define F1(opname) F1arb(o,opname,d[0])
#define F2(opname) F2arb(o,opname,d[0],d[1])
#define F3(opname) F3arb(o,opname,d[0],d[1],d[2])

static void AddToSet(TIntLL& L, Tint x) {
      for (int i=0; i<L.length(); i++) if (L[i]==x) return;
      L.append(x);
}

static int MemberQ(const TIntLL& L, Tint x) {
      for (int i=0; i<L.length(); i++) if (L[i]==x) return 1;
      return 0;
}

static void DoExternalDeclarations(ostream& o, Tprg& prg)
{
      int Nop;
      for (int PC=0; PC<prg.length(); ) {
            Toperand *f = &prg[PC++];
            if (!f->IsOpcode()) {err << "Internal in DoExternalDeclarations: " << *f << " is not an opcode\n"; error();}
            Nop = f->Noperands();
            Toperand *d = &prg[PC];
            PC+= Nop;
            if ((f->rawcode() == EncodeOpcode(Fcall,0) || f->rawcode() == EncodeOpcode(Fcall,0)) && d[0].kind()==Ksym) {
                  o << "extern \"C\" int " << barename(d[0].symbol().name()) << FNAME_APPENDIX
                    << "(const TConstObjectPtr[], const int, const TObjectPtr[], const int);\n";
            }
      }
      o << '\n';
}

static void DoSymbolReferences(ostream& o, Tprg& prg, int InInitialization=0)
{
      Tsymbol *syms[MAXSYMBOLS];
      Tint Nsyms = 0;
      for (int PC=0; PC<prg.length(); PC++) {
            Toperand *f = &prg[PC];
            if (f->kind() == Ksym && prg[PC-1].opcode() != Fcall && prg[PC-1].opcode() != Fscall) {
                  int found = 0;
                  for (int i=0; i<Nsyms; i++)
                        if (syms[i] == &(f->symbol())) {found=1; break;}
                  if (!found) {
                        if (Nsyms >= MAXSYMBOLS) {
                              cerr << "*** Too many (more than " << MAXSYMBOLS << ") global symbols in one function.\n";
                              cerr << "    You can increase MAXSYMBOLS in Ctgen.C.\n";
                              return;
                        }
                        syms[Nsyms++] = &(f->symbol());
                        if (InInitialization)
                              o << "\t\t" << barename(f->symbol().name()) << GLOBBODY << " = theHT.add((Tchar*)\"" << f->symbol().name() << "\");\n";
                        else
                              o << "\tstatic Tsymbol *" << barename(f->symbol().name()) << GLOBBODY << ";\n";
                  }
            }
      }
}

static void FindJumpAddresses(Tprg& prg, TIntLL& L)
{
      int Nop,pcaddr;
      for (int PC=0; PC<prg.length(); ) {
            Toperand *f = &prg[PC++];
            if (!f->IsOpcode()) {err << "Internal in FindJumpAddresses: " << *f << " is not an opcode\n"; error();}
            Nop = f->Noperands();
            Toperand *d = &prg[PC];
            PC+= Nop;
#           define pair(opcode,Nargs) EncodeOpcode(opcode,Nargs)
            int c = f->rawcode();
//          if (c==pair(Fbra,1)) {
//                pcaddr = PC + d[0].literal() - 1;
//                AddToSet(L,pcaddr);
//          } else
            if (c==pair(Fjmp,1)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
//          } else if (c==pair(Fbif,2)) {
//                pcaddr = PC + d[0].literal()-1;
//                AddToSet(L,pcaddr);
//          } else if (c==pair(Fbifn,2)) {
//                pcaddr = PC + d[0].literal()-1;
//                AddToSet(L,pcaddr);
            } else if (c==pair(Fjif,2)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fjifn,2)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fjngt,3)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fjnlt,3)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fjnge,3)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fjnle,3)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            } else if (c==pair(Fincjmp,2)) {
                  pcaddr = d[0].literal();
                  AddToSet(L,pcaddr);
            }
#           undef pair
      }
}

static int LastLabelUsed = 0;

static ostream& GotoInstruction(ostream& o, int pcaddr, const Tprg& prg) {
      o << "goto L";
      if (pcaddr < prg.length())
            o << pcaddr;
      else {
            o << "AST_LABEL";
            LastLabelUsed = 1;
      }
      return o << ";\n";
}
      
void Ctgen(ostream& o, Tprg& prg)
{
      ThePrgptr = &prg;
      TObjectLL *old_objLLptr = Toperand::objLLptr;
      prg.JustMakeCurrent();
      Tchar *FunctionName = &(prg.Symbol()) ? (Tchar*)(prg.Symbol().name()) : (Tchar*)"main";
      Tchar *ptr = strchr(FunctionName,':');
      int IsStatic = 0;
      if (ptr) {FunctionName=ptr+1; IsStatic=1;}

      LastLabelUsed = 0;
      
      //cerr << "compiling " << FunctionName << "...\n";

      // We need to access gather/scatter functions
      o << "\n// ct-translation of t-function " << FunctionName << ".\n";
      o << "// Produced by Tela " << VersionString << ".\n",
//    o << "\n#include \"gatscat.H\"\n";

      // Find out external functions and declare them
      //o << "// External functions for " << FunctionName << "\n";
      DoExternalDeclarations(o,prg);
      
      // Output function header
//    if (IsStatic) o << "static\n";
      o << '[';
    int argc;
      for (argc=prg.Nargin()+1; argc<=prg.Nargin()+prg.Nargout(); argc++) {
            o << VARBODY << argc;
            if (argc < prg.Nargin()+prg.Nargout()) o << ',';
      }
      o << "] = " << barename(FunctionName) << "(";
      for (argc=1; argc<=prg.Nargin(); argc++) {
            o << VARBODY << argc;
            if (argc<prg.Nargin()) o << ',';
      }
      o << ")\n{\n";

      // Standard arrays for argument passing etc. The maximum length is obtained from prg.MaxNops()
      if (!avoid_ctors) {
            o << '\t' << "Tobject " << UNIQ << "DummyObject;\n\n";
      }
      o << "\t// Standard arrays for argument passing\n";
      o << "\tTConstObjectPtr " << INPUTS << '[' << max(1,prg.MaxNops()) << "];\n";
      o << "\tTObjectPtr " << OUTPUTS << '[' << max(20/*4*/,prg.MaxNops()) << "];\n";     // Range uses 4 args
      if (!avoid_ctors) {
            o << "\tfor (int " << UNIQ << "_i=0; " << UNIQ << "_i<20; " << UNIQ << "_i++) " << OUTPUTS << '[' << UNIQ << "_i] = &" << UNIQ << "DummyObject;\n";
      }
      o << "\tTint " INDICES << '[' << MAXRANK << "];\n";
      
      // Output declarations of local objects
      o << "\t// Local objects\n";
      if (avoid_ctors) {
            o << "\tTobject *" << VARBODY << "0 = new Tobject;\n";
            for (argc=prg.Nargin()+prg.Nargout()+1; argc<prg.StackFrameSize(); argc++)
                  o << "\tTobject *" << VARBODY << argc << " = new Tobject;\n";
      } else {
            o << "\tTobject " << VARBODY << "0;\n";
            for (argc=prg.Nargin()+prg.Nargout()+1; argc<prg.StackFrameSize(); argc++)
                  o << "\tTobject " << VARBODY << argc << ";\n";
      }
      // Initialize var0 to VOID. If we don't do this, it will remain UNDEFINED.
      // When other ct-functions that have no output args get called, PRI $0 instructions
      // will be added, and these will write "<Undefined>" on cout if $0 is UNDEFINED.
      if (avoid_ctors) {
            o << '\t' << VARBODY << "0->SetToVoid();\n";
      } else {
            o << '\t' << VARBODY << "0.SetToVoid();\n";
      }
      
      // Output definitions of constant objects
      o << "\n\t// \"Constant\" objects\n";
      for (argc=0; argc<prg.Nstatic(); argc++) {
            if (avoid_ctors) {
                  o << "\tstatic Tobject *" << CONSTBODY << argc << ";\n";
            } else {
                  o << "\tstatic Tobject " << CONSTBODY << argc << ";\n";
            }
      }
      // We may also need a unit object
      // And we may need a VOID object
      if (avoid_ctors) {
            o << "\tstatic Tobject *" << UNIQ << "UnitObject;\n";
            o << "\tstatic Tobject *" << UNIQ << "VoidObject;\n";
      } else {
            o << "\tstatic Tobject " << UNIQ << "UnitObject;\n";
            o << "\tstatic Tobject " << UNIQ << "VoidObject;\n";
      }
      /*
        Notice the UnitObject is quite a hack. It is (probably) only needed in
        RANGE, which generates literal objects with value unity as the default
        step. It is passed as a modifiable object pointer to Range() so we cannot
        make it const here, however Range() does not modify it.
    */

      // Initialize find symbol pointers to all symbols (global vars)
      o << "\n\t// Global variables\n";
      DoSymbolReferences(o,prg);

      // Generate code to do first-time-only initialization of 'const' etc objects
      // DLD apparently fails to do static initialization properly! therefore choose
      // zero as first value of the static flag (it presumably clears the memory space).
      o << "\n\tstatic int InitializationDone = 0;\n\tif (!InitializationDone) {\n";
      // Const object values
      if (avoid_ctors) {
            for (argc=0; argc<prg.Nstatic(); argc++)
                  o << "\t\t" << CONSTBODY << argc << " = new Tobject(" << TCForm(*prg.nthobject(argc)) << ");\n";
      } else {
            for (argc=0; argc<prg.Nstatic(); argc++)
                  o << "\t\t" << CONSTBODY << argc << " = " << TCForm(*prg.nthobject(argc)) << ";\n";
      }
      // UnitObject
      if (avoid_ctors) {
            o << "\t\t" << UNIQ << "UnitObject = new Tobject(1);\n";
            o << "\t\t" << UNIQ << "VoidObject = new Tobject;\n";
            o << "\t\t" << UNIQ << "VoidObject->SetToVoid();\n";
      } else {
            o << "\t\t" << star << UNIQ << "UnitObject = 1;\n";
            o << "\t\t" << UNIQ << "VoidObject.SetToVoid();\n";
      }
      DoSymbolReferences(o,prg,1);
      o << "\t\tInitializationDone = 1;\n\t}\n";
      
      o << "\n\t// Code\n";
      
      // Find set of possible jump targets
      TIntLL jumplines(0);
      FindJumpAddresses(prg,jumplines);
      
      int i,oldPC,Nop;
      Toperand *f;
      for (int PC=0; PC<prg.length(); ) {

            if (MemberQ(jumplines,PC)) o << 'L' << PC << ":\n";
            
            oldPC = PC;
            f = &prg[PC++];
            if (!f->IsOpcode()) {err << "Internal: " << *f << " is not an opcode\n"; error();}
            Nop = f->Noperands();
            Toperand *d = &prg[PC];
            PC+= Nop;

            o << '\t';
            
#           define pair(opcode,Nargs) EncodeOpcode(opcode,Nargs)
#           define CASE(opcode,Nargs) } else if (c==pair(opcode,Nargs)) {
#           define CASE2(opcode1,opcode2,Nargs) } else if (c==pair(opcode1,Nargs) || c==pair(opcode2,Nargs)) {
#           define CASE3(opcode1,opcode2,opcode3,Nargs) \
            } else if (c==pair(opcode1,Nargs) || c==pair(opcode2,Nargs) || c==pair(opcode3,Nargs)) {

          int c = f->rawcode();

            if (c==pair(Fadd,2)) {
                  F2("Add");
            CASE(Fadd,3)
                  F3("Add");
                  
            CASE(Finc,1)
                  F1("Inc");
                  
            CASE(Fsub,2)
                  F2("Sub");
            CASE(Fsub,3)
                  F3("Sub");
                  
            CASE(Fdec,1)
                  F1("Dec");
                  
            CASE(Fmul,2)
                  F2("Mul");
            CASE(Fmul,3)
                  F3("Mul");
                  
            CASE(Fdiv,2)
                  F2("Div");
            CASE(Fdiv,3)
                  F3("Div");

            CASE(Fmod,3)
                  F3("Mod");
                  
            CASE(Fpow,2)
                  F2("Pow");
            CASE(Fpow,3)
                  F3("Pow");
                  
            CASE(Fneg,1)
                  F1("Neg");
            CASE(Fneg,2)
                  F2("Neg");
            CASE(Fabs,1)
                  F1("Abs");
            CASE(Fabs,2)
                  F2("Abs");
                  
            CASE(Fmove,2)
                  o << VarRef(d[0]) << " = " << VarRef(d[1]) << ";\n";
                  
            CASE(Fgt,3)
                  F3("Gt");
            CASE(Flt,3)
                  F3("Lt");
            CASE(Fge,3)
                  F3("Ge");
            CASE(Fle,3)
                  F3("Le");
            CASE(Feq,3)
                  F3("Eq");
            CASE(Fne,3)
                  F3("Ne");
                  
            CASE(Fand,3)
                  F3("And");
            CASE(Fand,2)
                  F3arb(o,"And",d[0],d[0],d[1]);
            CASE(For,3)
                  F3("Or");
            CASE(For,2)
                  F3arb(o,"Or",d[0],d[0],d[1]);
            CASE(Fnot,2)
                  F2("Not");
            CASE(Fnot,1)
                  F2arb(o,"Not",d[0],d[0]);

            CASE(Fmin,3)
                  F3("Min");
            CASE(Fmax,3)
                  F3("Max");
            CASE(Fmin,2)
                  F2("Min");
            CASE(Fmax,2)
                  F2("Max");

            CASE(Fnin,1)
                  o << VarRef(d[0]) << " = Nargin;\n";
            CASE(Fnout,1)
                  o << VarRef(d[0]) << " = Nargout;\n";
            CASE(Fmmpos,1)
                  o << VarRef(d[0]) << " = MinMaxPosition();\n";
            CASE(Fgetin,2)
                  o << VarRef(d[0]) << " = *(argin[" << VarRef(d[1]) << ".IntValue()]);\n";
            CASE(Fgetout,2)
                  o << VarRef(d[0]) << " = *(argout[" << VarRef(d[1]) << ".IntValue()]);\n";
            CASE(Fsetout,2)
                  o << "*(argout[" << VarRef(d[0]) << ".IntValue()]) = " << VarRef(d[1]) << ";\n";

            CASE(Fvloop,0)
                  ;
            CASE(Fendv,1)
                  ;
            
//          CASE(Fbra,1)
//                GotoInstruction(o,PC+d[0].literal()-1,prg);
            CASE(Fjmp,1)
                  GotoInstruction(o,d[0].literal(),prg);
            CASE(Fincjmp,2)
                  o << "Inc(" << VarRef(d[1]) << "); ";
                  GotoInstruction(o,d[0].literal(),prg);
//          CASE(Fbif,2)
//                o << "if (" << VarRef(d[1]) << ".IsNonzero()) ";
//                GotoInstruction(o,PC+d[0].literal()-1,prg);
//          CASE(Fbifn,2)
//                o << "if (!(" << VarRef(d[1]) << ".IsNonzero())) ";
//                GotoInstruction(o,PC+d[0].literal()-1,prg);
            CASE(Fjif,2)
                  o << "if (" << VarRef(d[1]) << ".IsNonzero()) ";
                  GotoInstruction(o,d[0].literal(),prg);
            CASE(Fjifn,2)
                  o << "if (!(" << VarRef(d[1]) << ".IsNonzero())) ";
                  GotoInstruction(o,d[0].literal(),prg);

            CASE(Fjngt,3)
                  o << "if (!TestGt(" << VarRef(d[1]) << "," << VarRef(d[2]) << ")) ";
                  GotoInstruction(o,d[0].literal(),prg);
            CASE(Fjnlt,3)
                  o << "if (!TestLt(" << VarRef(d[1]) << "," << VarRef(d[2]) << ")) ";
                  GotoInstruction(o,d[0].literal(),prg);
            CASE(Fjnge,3)
                  o << "if (!TestGe(" << VarRef(d[1]) << "," << VarRef(d[2]) << ")) ";
                  GotoInstruction(o,d[0].literal(),prg);
            CASE(Fjnle,3)
                  o << "if (!TestLe(" << VarRef(d[1]) << "," << VarRef(d[2]) << ")) ";
                  GotoInstruction(o,d[0].literal(),prg);
                  
            CASE(Fpri,1)
                  o << "if (" << VarRef(d[0]) << ".kind()!=Kvoid) cout << " << VarRef(d[0]) << " << '\\n';\n";
            CASE(Fnop,0)
                  ;

        } else if (c==pair(Fcall,0) || c==pair(Fscall,0)) {       // CALL fn, Noutputs, out1,out2,...outN, in1,in2,...,inM
                  int Noutputs = d[1].literal();
                  int Ninputs = Nop - Noutputs - 2;
                  for (i=0; i<Ninputs; i++)
                        o << INPUTS << '[' << i << "] = &" << VarRef(d[2+Noutputs+i]) << ";\n\t";
                  if (Noutputs == 1 && d[2].kind()==Kpar && d[2].offset()==0)
                        if (avoid_ctors) {
                              o << VARBODY << "0->SetToVoid();\n\t";
                        } else {
                              o << VARBODY << "0.SetToVoid();\n\t";
                        }
                  for (i=0; i<Noutputs; i++)
                        o << OUTPUTS << '[' << i << "] = &" << VarRef(d[2+i]) << ";\n\t";
//                if (d[0].kind() != Ksym) cerr << "*** Ctgen: calling non-symbol, not yet implemented\n";
                  if (d[0].kind() == Kpar) {
                        o << "Call(" << VarRef(d[0])
                          << "," << INPUTS << "," << Ninputs << "," << OUTPUTS << "," << Noutputs << ",0);\n";
                  } else if (d[0].kind() == Ksym) {
//                      if (d[0].symbol().value()->kind()!=Kfunction)
//                            cerr << "*** Ctgen: CALL instruction for non-function\n";
//                      else {
//                            for (i=Noutputs; i<10 /*d[0].symbol().value()->FunctionValue()->Nargout()*/; i++)
//                                  o << OUTPUTS << '[' << i << "] = &Dummy;\n\t";
                              o << barename(d[0].symbol().name()) << FNAME_APPENDIX
                                    << "(" << INPUTS << "," << Ninputs << "," << OUTPUTS << "," << Noutputs << ");\n";
//                      }
                  } else
                        cerr << "*** Ctgen: CALL instruction for non-symbol, non-par\n";
            CASE2(Fgath,Fscat,0)
                  for (i=2; i<Nop; i++)
                        o << INPUTS << "[" << i-2 << "] = &" << VarRef(d[i]) << ";\n\t";
                  o << (f->opcode()==Fgath ? "Gather" : "Scatter");
                  o << "(" << VarRef(d[0]) << ',' << VarRef(d[1]) << "," << INPUTS << "," << Nop-2 << ");\n";
            CASE2(Farray,Fappend,0)       // ARRAY result,arg1,arg2,...,argN
                                          // APPEND result,arg1,arg2,...,argN
                  for (i=1; i<Nop; i++)
                        o << INPUTS << '[' << i-1 << "] = &" << VarRef(d[i]) << ";\n\t";
                  o << (f->opcode()==Farray ? "BuildArray" : "PasteArrays");
                  o << "(" << VarRef(d[0]) << "," << INPUTS << "," << Nop-1 << ");\n";
            CASE2(Fmgath,Fmscat,0)
                  for (i=2; i<Nop; i++)
                        o << INPUTS << "[" << i-2 << "] = &" << VarRef(d[i]) << ";\n\t";
                  o << "MGatScat(" << VarRef(d[0]) << "," << VarRef(d[1])
                    << "," << INPUTS << "," << Nop-2 << "," << (f->opcode()==Fmscat) << ");\n";
            CASE(Frange,0)
                  for (i=0; i<4; i++)
                        o << OUTPUTS << "[" << i << "] = (Tobject*)&" << VarRef(d[i]) << ";\n\t";
                  o << "Range(" << OUTPUTS << ");\n";
            CASE3(Fizeros,Frzeros,Fczeros,0)
                  if (Nop <= 3) {
                        o << VarRef(d[0]) << ".";
                        if (f->opcode()==Fizeros) o << 'i'; else if (f->opcode()==Frzeros) o << 'r'; else o << 'c';
                        o << "zeros(TDimPack(";
                        for (i=1; i<Nop; i++) {
                              o << VarRef(d[i]) << ".IntValue()";
                              if (i < Nop-1) o << ',';
                        }
                        o << "));\n";
                  } else {
                        for (i=1; i<Nop; i++)
                              o << INDICES << "[" << i-1 << "] = " << VarRef(d[i]) << ".IntValue();\n\t";
                        o << VarRef(d[0]) << ".";
                        if (f->opcode()==Fizeros) o << 'i'; else if (f->opcode()==Frzeros) o << 'r'; else o << 'c';
                        o << "zeros(TDimPack(" << INDICES << "," << Nop-1 << "));\n";
                  }

            } else {
                  cerr << "Internal: illegal instruction " << instrinfo[f->kind()].mnemonic << "(" << Nop << ") in Ctgen()\n";
                  o << "ILLEGAL INSTRUCTION\n";
                  //error();
            }
            
#           undef pair  

      }     // end of the big for loop

      if (LastLabelUsed) o << "LAST_LABEL:\n";
      if (avoid_ctors) {
            o << "\t// Deallocate locally created objects\n";
            o << "\tdelete " << VARBODY << "0;\n";
            for (argc=prg.Nargin()+prg.Nargout()+1; argc<prg.StackFrameSize(); argc++)
                  o << "\tdelete " << VARBODY << argc << ";\n";
      
      }
      o << "\treturn 0;\n}\t// " << FunctionName << "\n";

      Toperand::objLLptr = old_objLLptr;
      
}

Generated by  Doxygen 1.6.0   Back to index