home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / BlitzSrc / gen.cc < prev    next >
C/C++ Source or Header  |  2007-09-19  |  132KB  |  4,066 lines

  1. // gen.cc  --  Routines related to IR code generation
  2. //
  3. // KPL Compiler
  4. //
  5. // Copyright 2002-2007, Harry H. Porter III
  6. //
  7. // This file may be freely copied, modified and compiled, on the sole
  8. // condition that if you modify it...
  9. //   (1) Your name and the date of modification is added to this comment
  10. //       under "Modifications by", and
  11. //   (2) Your name and the date of modification is added to the printHelp()
  12. //       routine in file "main.cc" under "Modifications by".
  13. //
  14. // Original Author:
  15. //   05/24/03 - Harry H. Porter III
  16. //
  17. // Modifcations by:
  18. //   03/15/06 - Harry H. Porter III
  19. //
  20. //
  21.  
  22. #include "main.h"
  23.  
  24.  
  25. // generateIR ()
  26. //
  27. // This routine walks the AST and generates intermediate (IR) code.
  28. //
  29. void generateIR () {
  30.   Header * hdr;
  31.   ErrorDecl * errorDecl;
  32.   ClassDef * cl;
  33.   Interface * inter;
  34.   Global * glob;
  35.   int i;
  36.   Function * fun;
  37.   FunctionProto * funProto;
  38.   Method * meth;
  39.   DoubleConst * doubleConst;
  40.   StringConst * stringConst;
  41.   char * sanitizedPackName, * s, * lab1, * lab2;
  42.   int sawMain = 0;
  43.  
  44.   IRComment (appendStrings ("Name of package being compiled: ",
  45.              mainHeader->packageName->chars, ""));
  46.   IRComment ("");
  47.  
  48.   IRComment ("Symbols from runtime.s");
  49.   IRImport ("_putString");
  50.   // IRImport ("_flush");   No longer used
  51.   IRImport ("_heapInitialize");
  52.   IRImport ("_heapAlloc");
  53.   IRImport ("_heapFree");
  54.   IRImport ("_IsKindOf");
  55.   IRImport ("_RestoreCatchStack");
  56.   IRImport ("_PerformThrow");
  57.   IRImport ("_runtimeErrorOverflow");
  58.   IRImport ("_runtimeErrorZeroDivide");
  59.   IRImport ("_runtimeErrorNullPointer");
  60.   IRImport ("_runtimeErrorUninitializedObject");
  61.   IRImport ("_runtimeErrorWrongObject");
  62.   IRImport ("_runtimeErrorWrongObject2");
  63.   IRImport ("_runtimeErrorWrongObject3");
  64.   IRImport ("_runtimeErrorBadObjectSize");
  65.   IRImport ("_runtimeErrorDifferentArraySizes");
  66.   IRImport ("_runtimeErrorWrongArraySize");
  67.   IRImport ("_runtimeErrorUninitializedArray");
  68.   IRImport ("_runtimeErrorBadArrayIndex");
  69.   IRImport ("_runtimeErrorNullPointerDuringCall");
  70.   IRImport ("_runtimeErrorArrayCountNotPositive");
  71.   IRImport ("_runtimeErrorRestoreCatchStackError");
  72.   //  IRImport ("_runtimeErrorThrowHandlerHasReturned");  // Called from runtime.s only
  73.   //  IRImport ("_runtimeErrorFatalThrowError");          // Called from runtime.s only
  74.  
  75.   // Go through all ErrorDecls and give them new names...
  76.   IRText ();
  77.   IRComment ("ErrorDecls");
  78.   for (hdr = headerList; hdr; hdr = hdr->next) {
  79.     sanitizedPackName = sanitizedPackageName (hdr->packageName);
  80.     for (errorDecl = hdr->errors; errorDecl; errorDecl = errorDecl->next) {
  81.       errorDecl->newName = appendStrings (
  82.                                   "_Error",
  83.                                   sanitizedPackName,
  84.                                   errorDecl->id->chars);
  85.       if (hdr == mainHeader) {
  86.         IRExport (errorDecl->newName);
  87.         IRLabel (errorDecl->newName);
  88.         IRAscii0 (errorDecl->newName);
  89.       } else {
  90.         IRImport (errorDecl->newName);
  91.       }
  92.     }
  93.   }
  94.   IRAlign ();
  95.  
  96.   // Go through all function protos in used packages and generate IMPORTs...
  97.   IRComment ("Functions imported from other packages");
  98.   for (hdr = headerList; hdr; hdr = hdr->next) {
  99.     if (hdr == mainHeader) continue;
  100.     sanitizedPackName = sanitizedPackageName (hdr->packageName);
  101.     for (funProto = hdr->functionProtos; funProto; funProto = funProto->next) {
  102.       if (funProto->isExternal) {
  103.         funProto->newName = funProto->id->chars;
  104.       } else {
  105.         funProto->newName = appendStrings (
  106.                                   sanitizedPackName,
  107.                                   funProto->id->chars,
  108.                                   "");
  109.       }
  110.       IRImport (funProto->newName);
  111.     }
  112.   }
  113.  
  114.   // Go through functions in this package and give them new names and
  115.   // Generate EXPORT statements.  For externals, generate IMPORTs...
  116.   IRComment ("Externally visible functions in this package");
  117.   sanitizedPackName = sanitizedPackageName (mainHeader->packageName);
  118.   for (funProto = mainHeader->functionProtos; funProto; funProto = funProto->next) {
  119.     if ((funProto->myFunction == NULL) != (funProto->isExternal)) {
  120.       programLogicError ("funProto->myFunction should be NULL iff function is external");
  121.     }
  122.     if (funProto->id == stringMain) {
  123.       if (funProto->isExternal) {
  124.         programLogicError ("The main function must not be external");
  125.       }
  126.       funProto->newName = funProto->id->chars;
  127.       // printf ("funProto->newName (MAIN) = %s\n", funProto->newName);
  128.       funProto->myFunction->newName = funProto->newName;
  129.       IRExport ("_mainEntry");
  130.       IRExport (funProto->newName);
  131.       sawMain = 1;
  132.     } else if (funProto->isPrivate) {
  133.       funProto->newName = appendStrings (newName ("function"), "_", funProto->id->chars);
  134.       funProto->myFunction->newName = funProto->newName;
  135.       // printf ("Private function %s    newName = %s\n",
  136.       //         funProto->id->chars,
  137.       //         funProto->newName);
  138.     } else {
  139.       funProto->newName = funProto->id->chars;
  140.       // printf ("funProto->newName = %s\n", funProto->newName);
  141.       if (funProto->isExternal) {
  142.         IRImport (funProto->newName);
  143.       } else {
  144.         funProto->newName = appendStrings (
  145.                                 sanitizedPackName,
  146.                                 funProto->id->chars,
  147.                                 "");
  148.         funProto->myFunction->newName = funProto->newName;
  149.         // printf ("funProto->newName = %s\n", funProto->newName);
  150.         IRExport (funProto->newName);
  151.       }
  152.     }
  153.   }
  154.  
  155.   // Go through nameless functions and give them new names...
  156.   for (fun = mainHeader->closures; fun; fun = fun->next) {
  157.     fun->newName = newName ("NamelessFunction");
  158.     // printf ("Closure newName = %s\n", fun->newName);
  159.   }
  160.  
  161.   // Go through all classes in other packages.  Give them new names and
  162.   // generate import statements...
  163.   for (hdr = headerList; hdr; hdr = hdr->next) {
  164.     if (hdr == mainHeader) continue;
  165.     sanitizedPackName = sanitizedPackageName (hdr->packageName);
  166.     for (cl = hdr->classes; cl; cl = cl->next) {
  167.       cl->newName = appendStrings (sanitizedPackName,
  168.                                    cl->id->chars,
  169.                                    "");
  170.       IRComment ("The following class and its methods are from other packages");
  171.       IRImport (cl->newName);
  172.       // Go through all methods.  Give them new names and import them...
  173.       i = 1;
  174.       for (meth = cl->methods; meth; meth = meth->next) {
  175.         meth->newName = newMethodName (cl->newName, i);
  176.         IRImport (meth->newName);
  177.         i++;
  178.       }
  179.     }
  180.   }
  181.  
  182.   // Go through classes in this package.  Give them new names and
  183.   // generate export statements...
  184.   sanitizedPackName = sanitizedPackageName (mainHeader->packageName);
  185.   for (cl = mainHeader->classes; cl; cl = cl->next) {
  186.     cl->newName = appendStrings (sanitizedPackName,
  187.                                  cl->id->chars,
  188.                                  "");
  189.     IRComment ("The following class and its methods are from this package");
  190.     IRExport (cl->newName);
  191.     // Go through all methods.  Give them new names and export them...
  192.     i = 1;
  193.     for (meth = cl->methods; meth; meth = meth->next) {
  194.       meth->newName = newMethodName (cl->newName, i);
  195.       IRExport (meth->newName);
  196.       i++;
  197.     }
  198.   }
  199.  
  200.   // Go through all interfaces in other packages.  Give them new names and
  201.   // generate import statements...
  202.   IRComment ("The following interfaces are from other packages");
  203.   for (hdr = headerList; hdr; hdr = hdr->next) {
  204.     if (hdr == mainHeader) continue;
  205.     sanitizedPackName = sanitizedPackageName (hdr->packageName);
  206.     for (inter = hdr->interfaces; inter; inter = inter->next) {
  207.       inter->newName = appendStrings (sanitizedPackName,
  208.                                       inter->id->chars,
  209.                                       "");
  210.       IRImport (inter->newName);
  211.     }
  212.   }
  213.  
  214.   // Go through interfaces in this package.  Give them new names and
  215.   // generate export statements...
  216.   sanitizedPackName = sanitizedPackageName (mainHeader->packageName);
  217.   IRComment ("The following interfaces are from this package");
  218.   for (inter = mainHeader->interfaces; inter; inter = inter->next) {
  219.     inter->newName = appendStrings (sanitizedPackName,
  220.                                     inter->id->chars,
  221.                                     "");
  222.     IRExport (inter->newName);
  223.   }
  224.  
  225.   // Go through all headers (except mainHeader) and import globals...
  226.   IRComment ("Globals imported from other packages");
  227.   for (hdr = headerList; hdr; hdr = hdr->next) {
  228.     if (hdr == mainHeader) continue;
  229.     sanitizedPackName = sanitizedPackageName (hdr->packageName);
  230.     for (glob = hdr->globals; glob; glob = (Global *) glob->next) {
  231.       // Rename the global...
  232.       glob->id = lookupAndAdd (appendStrings (sanitizedPackName,
  233.                                               glob->id->chars,
  234.                                               ""),
  235.                                ID);
  236.       IRImport (glob->id->chars);
  237.     }
  238.   }
  239.  
  240.   // Go through all the globals in this package...
  241.   IRComment ("Global variables in this package");
  242.   IRData ();
  243.   sanitizedPackName = sanitizedPackageName (mainHeader->packageName);
  244.   for (glob = mainHeader->globals; glob; glob = (Global *) glob->next) {
  245.     if (glob->isPrivate) {
  246.       // Rename each private global by pre-pending "_Gloabl_"...
  247.       glob->id = lookupAndAdd (appendStrings ("_Global_",
  248.                                               glob->id->chars,
  249.                                               ""),
  250.                                ID);
  251.     } else {
  252.       // Rename each public global by pre-pending the package name,
  253.       // e.g., "_P_MyPackage_".  Also generate an export...
  254.       glob->id = lookupAndAdd (appendStrings (sanitizedPackName,
  255.                                               glob->id->chars,
  256.                                               ""),
  257.                                ID);
  258.       IRExport (glob->id->chars);
  259.     }
  260.   }
  261.  
  262.   // Generate the code for all aligned global variables...
  263.   for (glob = mainHeader->globals; glob; glob = (Global *) glob->next) {
  264.     if (glob->sizeInBytes >= 4) {
  265.       IRLabel (glob->id->chars);
  266.       if (glob->initExpr) {
  267.         genStaticData (glob->initExpr);
  268.       } else {
  269.         IRSkip (glob->sizeInBytes);
  270.       }
  271.     }
  272.   }
  273.  
  274.   // Generate the code for all byte (unaligned) global variables...
  275.   for (glob = mainHeader->globals; glob; glob = (Global *) glob->next) {
  276.     if (glob->sizeInBytes < 4) {
  277.       IRLabel (glob->id->chars);
  278.       if (glob->initExpr) {
  279.         genStaticData (glob->initExpr);
  280.       } else {
  281.         IRSkip (glob->sizeInBytes);
  282.       }
  283.     }
  284.   }
  285.   IRAlign ();
  286.  
  287.   // Generate all String Constants...
  288.   if (stringList) {
  289.     IRComment ("String constants");
  290.     for (stringConst = stringList; stringConst; stringConst = stringConst->next) {
  291.       IRLabel (stringConst->nameOfConstant);
  292.       IRAscii2 (stringConst->svalue);
  293.       IRAlign ();
  294.     }
  295.   }
  296.  
  297.   IRText ();
  298.  
  299.   // Generate all Double Constants...
  300.   if (floatList) {
  301.     IRComment ("Floating point constants");
  302.     for (doubleConst = floatList; doubleConst; doubleConst = doubleConst->next) {
  303.       IRLabel (doubleConst->nameOfConstant);
  304.       IRDouble (doubleConst->rvalue);
  305.     }
  306.   }
  307.  
  308.   // If we have a main function, generate the "_mainEntry" code...
  309.   if (sawMain) {
  310.     IRComment ("");
  311.     IRComment ("=====  MAIN ENTRY POINT  =====");
  312.     IRComment ("");
  313.     IRLabel ("_mainEntry");
  314.     lab2 = newLabel ();
  315.     IRStartCheckVersion (sanitizedPackageName (mainHeader->packageName),
  316.                          mainHeader->hashVal,
  317.                          lab2);
  318.     IRCall ("_heapInitialize");
  319.     IRGoto ("main");
  320.   }
  321.  
  322.   IRComment ("");
  323.   IRComment ("Source Filename and Package Name");
  324.   IRComment ("");
  325.   IRLabel ("_sourceFileName");
  326.   s = inputFileNames [0];
  327.   if (s) {
  328.     IRAscii0 (s);
  329.   } else {
  330.     programLogicError ("inputFileNames [0] is NULL");
  331.   }
  332.   IRLabel ("_packageName");
  333.   IRAscii0 (mainHeader->packageName->chars);
  334.   IRAlign ();
  335.  
  336.   // Generate the CheckVersion routine
  337.   lab1 = newLabel ();
  338.   lab2 = newLabel ();
  339.   IRCheckVersion (sanitizedPackName, mainHeader->hashVal, lab1);
  340.   for (hdr = headerList; hdr; hdr = hdr->next) {
  341.     if (hdr == mainHeader) continue;
  342.     IRCallCheckVersion (sanitizedPackageName (hdr->packageName), hdr->hashVal, lab2);
  343.   }
  344.   IREndCheckVersion (lab2);
  345.  
  346.   // Go through functions in this package and generate code for them...
  347.   for (fun = mainHeader->functions; fun; fun = fun->next) {
  348.     genMethOrFunction (fun);
  349.   }
  350.  
  351.   // Go through nameless functions in this package and generate code for them...
  352.   for (fun = mainHeader->closures; fun; fun = fun->next) {
  353.     genMethOrFunction (fun);
  354.   }
  355.  
  356.   // Go through the interfaces in this package and generate descriptors for each...
  357.   for (inter = mainHeader->interfaces; inter; inter = inter->next) {
  358.     genInterface (inter);
  359.   }
  360.  
  361.   // Go through the classes in this package and generate code for each...
  362.   for (cl = mainHeader->classes; cl; cl = cl->next) {
  363.     genClass (cl);
  364.   }
  365.  
  366. }
  367.  
  368.  
  369.  
  370. // genInterface (inter)
  371. //
  372. // This routine generates the "Interface Descriptor" for an interface.
  373. //
  374. void genInterface (Interface * inter) {
  375.   char * interfaceNamePtr;
  376.   Interface * otherInter;
  377.   Mapping<Abstract, Abstract > * setOfSupers
  378.                = new Mapping<Abstract, Abstract > (10, NULL);
  379.   Abstract * super;
  380.  
  381.   IRComment ("");
  382.   IRComment2 ("===============  INTERFACE ", inter->id->chars ,"  ===============");
  383.   IRComment ("");
  384.   IRComment ("Interface descriptor:");
  385.   IRComment ("");
  386.  
  387.   IRLabel (inter->newName);
  388.  
  389.   // Write out magic number, ptr to interface name, ptr to source filename,
  390.   // and line number...
  391.   IRWord3 (0x494e5446, "Magic number 0x494e5446 == 'INTF'");
  392.   interfaceNamePtr = newLabel ();
  393.   IRWord2 (interfaceNamePtr);
  394.   IRWord2 ("_sourceFileName");
  395.   IRWord3 (extractLineNumber (inter->tokn), "line number");
  396.  
  397.   // Identify all interfaces that this interfaces extends...
  398.   addAllSupers (inter, setOfSupers);
  399.  
  400.   // For each, generate a pointer to its interface descriptor...
  401.   super = setOfSupers->getFirst ();
  402.   while (super) {
  403.     otherInter = (Interface *) super;
  404.     if (otherInter == NULL || otherInter->op != INTERFACE) {
  405.       programLogicError ("Within genInterface - This was checked in check() - 2");
  406.     }
  407.     IRWord2 (otherInter->newName);
  408.     super = setOfSupers->getNext ();
  409.   }
  410.   IRWord (0);
  411.  
  412.   IRLabel (interfaceNamePtr);
  413.   IRAscii0 (inter->id->chars);
  414.   IRAlign ();
  415.  
  416. }
  417.  
  418.  
  419.  
  420. // genClass (cl)
  421. //
  422. // This routine generates the code for a class.
  423. //
  424. void genClass (ClassDef * cl) {
  425.   MethodProto * methProto;
  426.   Method * meth;
  427.   char * lab, * classNamePtr;
  428.   Offset * offset;
  429.   String * sel;
  430.   TypeArg * typeArg;
  431.   NamedType * namedType;
  432.   Interface * otherInter;
  433.   Mapping<Abstract, Abstract > * setOfSupers
  434.                = new Mapping<Abstract, Abstract > (10, NULL);
  435.   Abstract * otherAbs;
  436.  
  437.   IRComment ("");
  438.   IRComment2 ("===============  CLASS ", cl->id->chars ,"  ===============");
  439.   IRComment ("");
  440.   IRComment ("Dispatch Table:");
  441.   IRComment ("");
  442.  
  443.   IRLabel (cl->newName);
  444.  
  445.   // Gen ptr to class descriptor...
  446.   lab = newLabel ();
  447.   IRWord2 (lab);
  448.  
  449.   // Go through the offsets and write a line for each...
  450.   offset = firstDispatchOffset;
  451.   while (1) {
  452.     sel = cl->offsetToSelector->findInTopScope (offset);
  453.     if (sel == NULL) break;
  454.     methProto = cl->selectorMapping->findInTopScope (sel);
  455.     if (methProto == NULL) {
  456.       programLogicError ("Should find a method proto for every offset");
  457.     }
  458.     meth = methProto->myMethod;
  459.     if (meth == NULL) {
  460. //qqqqq -- This program logic error occurs -- See example in folder "Art-error"
  461.       printf ("class = %s\n", cl->id->chars);
  462.       printf ("methProto selector = %s\n", methProto->selector->chars);
  463.       programLogicError ("Should find a method for every method proto");
  464.     }
  465.     IRGoto2 (meth->newName, offset->ivalue, meth->selector->chars);
  466.     offset = nextDispatchOffset (offset);
  467.   }
  468.   IRWord (0);
  469.  
  470.   // Generate the class descriptor...
  471.   IRComment ("");
  472.   IRComment ("Class descriptor:");
  473.   IRComment ("");
  474.   IRLabel (lab);
  475.   IRWord3 (0x434c4153, "Magic number 0x434c4153 == 'CLAS'");
  476.   classNamePtr = newLabel ();
  477.   IRWord2 (classNamePtr);
  478.   IRWord2 ("_sourceFileName");
  479.   IRWord3 (extractLineNumber (cl->tokn), "line number");
  480.   IRWord3 (cl->sizeInBytes, "size of instances, in bytes");
  481.  
  482.   // Generate pointers to super-classes and super-interfaces...
  483.   addAllSupers (cl, setOfSupers);
  484.   otherAbs = setOfSupers->getFirst ();
  485.   while (otherAbs) {
  486.     IRWord2 (otherAbs->newName);
  487.     otherAbs = setOfSupers->getNext ();
  488.   }
  489.   IRWord (0);
  490.  
  491.   IRLabel (classNamePtr);
  492.   IRAscii0 (cl->id->chars);
  493.   IRAlign ();
  494.  
  495.   // Go through the methods and generate code for each...
  496.   for (meth = cl->methods; meth; meth = meth->next) {
  497.     genMethOrFunction (meth);
  498.   }
  499.  
  500. }
  501.  
  502.  
  503.  
  504. // addAllSupers (abs, setOfSupers)
  505. //
  506. // This routine is passed an abstract "abs".  It visits each of its superclasses
  507. // superInterfaces and adds each of them to the set "setOfSupers".
  508. //
  509. void addAllSupers (Abstract * abs, Mapping <Abstract, Abstract> * setOfSupers) {
  510.   ClassDef * cl, * supercl;
  511.   Interface * inter, * superInter;
  512.   TypeArg * typeArg;
  513.   NamedType * nType;
  514.  
  515.   //    printf ("    %s: CALLED\n", abs->id->chars);
  516.  
  517.   // Put this abstract into the set if it is not already there...
  518.   if (! setOfSupers->alreadyDefined (abs)) {
  519.     //    printf ("    %s: Adding to setOfSupers\n", abs->id->chars);
  520.     setOfSupers->enter (abs, abs);
  521.   }
  522.  
  523.   // If this routine is called on a class...
  524.   if (abs->op == CLASS_DEF) {
  525.     cl = (ClassDef *) abs;
  526.  
  527.     // Identify the superclass, if any...
  528.     //    printf ("    %s:   Looking at the superclass...\n", abs->id->chars);
  529.     nType = cl->superclass;
  530.     if (nType &&
  531.         nType->myDef &&
  532.         nType->myDef->op == CLASS_DEF) {
  533.       supercl = (ClassDef *) nType->myDef;
  534.       // Recursively consider adding it to the set...
  535.       addAllSupers (supercl, setOfSupers);
  536.     }
  537.  
  538.     // Run through all the interfaces this class implements...
  539.     for (typeArg = cl->implements; typeArg; typeArg = typeArg->next) {
  540.       //    printf ("    %s:   Considering next interface in the implements clause...\n",
  541.       //            abs->id->chars);
  542.       nType = (NamedType *) typeArg->type;
  543.       if (nType &&
  544.           nType->op == NAMED_TYPE &&
  545.           nType->myDef &&
  546.           nType->myDef->op == INTERFACE) {
  547.         superInter = (Interface *) nType->myDef;
  548.         //    printf ("    %s:     ... and calling recursively for interface %s...\n",
  549.         //           abs->id->chars, nType->id->chars);
  550.         // Recursively consider adding it to the set...
  551.         addAllSupers (superInter, setOfSupers);
  552.       }
  553.     }
  554.  
  555.   // Else, if this routine is called on an interface...
  556.   } else if (abs->op == INTERFACE) {
  557.     inter = (Interface *) abs;
  558.  
  559.     // Run through all the interfaces this interface extends...
  560.     for (typeArg = inter->extends; typeArg; typeArg = typeArg->next) {
  561.       //    printf ("    %s:   Considering next interface in the extends clause...\n",
  562.       //            abs->id->chars);
  563.       nType = (NamedType *) typeArg->type;
  564.       if (nType &&
  565.           nType->op == NAMED_TYPE &&
  566.           nType->myDef &&
  567.           nType->myDef->op == INTERFACE) {
  568.         superInter = (Interface *) nType->myDef;
  569.         //    printf ("    %s:     ... and calling recursively for %s...\n",
  570.         //            abs->id->chars, nType->id->chars);
  571.         // Recursively consider adding it to the set...
  572.         addAllSupers (superInter, setOfSupers);
  573.       }
  574.     }
  575.  
  576.   // Else, if this routine is called on something else...
  577.   } else {
  578.     programLogicError ("Unexpected node in addAllSupers");
  579.   }
  580.   //    printf ("    %s: DONE\n", abs->id->chars);
  581. }
  582.  
  583.  
  584.  
  585. // genMethOrFunction (methOrFunction)
  586. //
  587. // This routine is passed a method, function, or closure.
  588. // It generates the code for it.
  589. //
  590. void genMethOrFunction (MethOrFunction * methOrFunction) {
  591.   Local * local;
  592.   AstNode * x;
  593.   char * methOrFunName, * labelForSelf;
  594.   char kind;
  595.   Parameter * parm;
  596.   char * nameOfNamelessFunction;
  597.   Function * fun;
  598.   Method * meth;
  599.   Catch * cat;
  600.  
  601.   currentFunOrMeth = methOrFunction;   // This is where new temps will be added
  602.   IRComment ("");
  603.  
  604.   if (methOrFunction->op == FUNCTION) {
  605.     fun = (Function *) methOrFunction;
  606.     if (fun->myProto == NULL) {
  607.       nameOfNamelessFunction = (char *) calloc (1,
  608.                                     strlen (extractFilename (fun->tokn)) + 40);
  609.       if (nameOfNamelessFunction == 0) {
  610.         programLogicError ("Calloc failed in genMethOrFunction; out of memory perhaps???");
  611.       }
  612.       sprintf (nameOfNamelessFunction, "Function (%s:%d)",
  613.                                 extractFilename (fun->tokn),
  614.                                 extractLineNumber (fun->tokn));
  615.       IRComment2 ("===============  Nameless ", nameOfNamelessFunction,
  616.                                                            "  ===============");
  617.     } else {
  618.       IRComment2 ("===============  FUNCTION ", fun->id->chars, "  ===============");
  619.     }
  620.     IRComment ("");
  621.     IRLabel (fun->newName);
  622.     // printf ("PROCESSING FUNCTION %s\n", fun->newName);
  623.     IRFunctionEntry (fun);
  624.     genLineNumber (methOrFunction, "FU");
  625.  
  626.   } else {
  627.     meth = (Method *) methOrFunction;
  628.     // printf ("PROCESSING METHOD %s\n", meth->newName);
  629.     IRComment2 ("===============  METHOD ", meth->selector->chars, "  ===============");
  630.     IRComment ("");
  631.     IRLabel (meth->newName);
  632.     IRMethodEntry (meth);
  633.     genLineNumber (methOrFunction, "ME");
  634.   }
  635.  
  636.   if (methOrFunction->containsTry) {
  637.     methOrFunction->catchStackSave = newTemp (4);
  638.     IRSaveCatchStack (methOrFunction->catchStackSave);
  639.   }
  640.  
  641.   // Run through the locals...
  642.   IRComment ("VARIABLE INITIALIZATION...");
  643.   for (local = methOrFunction->locals; local; local = (Local *) local->next) {
  644.     //     printf ("LOCAL INIT ");
  645.     //     pretty (local);
  646.     if (local == methOrFunction->catchStackSave) {
  647.       // Do not initialize the temp that we just saved CATCH STACK into.
  648.     } else if (local->initExpr) {
  649.       IRComment (local->id->chars);
  650.       genExprInto (local, local->initExpr, NULL, NULL);
  651.     //  The frame will be initialized to zero, so don't bother with this:
  652.     //      } else {
  653.     //        IRComment (local->id->chars);
  654.     //        IRZeroLocal (local);
  655.     }
  656.   }
  657.  
  658.   // Run through the stmts and generate code for them...
  659.   genStmts (methOrFunction->stmts);
  660.  
  661.   // Generate the Routine Descriptor...
  662.   IRComment ("");
  663.   IRComment ("Routine Descriptor");
  664.   IRComment ("");
  665.   IRLabel (appendStrings ("_RoutineDescriptor_",methOrFunction->newName,""));
  666.   IRWord2 ("_sourceFileName");
  667.   methOrFunName = newLabel ();
  668.   IRWord2 (methOrFunName);
  669.   IRWord3 (methOrFunction->totalParmSize, "total size of parameters");
  670.   IRFrameSize (methOrFunction);           // Don't know frameSize until later
  671.  
  672.   // If this is a method, generate the descriptor for "self"...
  673.   if (methOrFunction->op == METHOD) {
  674.     labelForSelf = newLabel ();
  675.     IRWord2 (labelForSelf);
  676.     IRWord3 (4, "size of self");
  677.     IRWord3 (8, "offset of self");
  678.   }
  679.  
  680.   // Run through the parameters and generate var descriptors...
  681.   for (parm = methOrFunction->parmList; parm; parm = (Parameter *) parm->next) {
  682.     parm->varDescLabel = newLabel ();
  683.     IRVarDesc1 (parm->varDescLabel, parm, parm->sizeInBytes);
  684.   }
  685.  
  686.   // Run through the locals and generate var descriptors...
  687.   for (local = methOrFunction->locals; local; local = (Local *) local->next) {
  688.     // if (local->type != NULL) {    // Don't include info for temp variables.
  689.       local->varDescLabel = newLabel ();
  690.       IRVarDesc1 (local->varDescLabel, local, local->sizeInBytes);
  691.     // }
  692.   }
  693.  
  694.   // Run through the parameters for all catch clauses and generate var descriptors...
  695.   for (cat = methOrFunction->catchList; cat; cat = cat->nextInMethOrFunction) {
  696.     for (parm = cat->parmList; parm; parm = (Parameter *) parm->next) {
  697.       parm->varDescLabel = newLabel ();
  698.       IRVarDesc1 (parm->varDescLabel, parm, parm->sizeInBytes);
  699.     }
  700.   }
  701.  
  702.   IRWord (0);
  703.  
  704.   // Generate the ASCII characters for the function or method name...
  705.   IRLabel (methOrFunName);
  706.   if (methOrFunction->op == FUNCTION) {
  707.     if (fun->id) {
  708.       IRAscii0 (fun->id->chars);
  709.     } else {   // if closure...
  710.       IRAscii0 (nameOfNamelessFunction);
  711.     }
  712.   } else {
  713.     IRAscii (meth->myClass->id->chars);
  714.     IRAscii ("::");
  715.     IRAscii0 (meth->selector->chars);
  716.     IRAlign ();
  717.     IRLabel (labelForSelf);
  718.     IRAscii0 ("Pself");
  719.   }
  720.   IRAlign ();
  721.  
  722.   // Run through the parameters and generate var descriptors...
  723.   for (parm = methOrFunction->parmList; parm; parm = (Parameter *) parm->next) {
  724.     genVarDescriptor (parm);
  725.   }
  726.  
  727.   // Run through the locals and generate var descriptors...
  728.   for (local = methOrFunction->locals; local; local = (Local *) local->next) {
  729.     // if (local->type != NULL) {    // Don't include info for temp variables.
  730.       genVarDescriptor (local);
  731.     // }
  732.   }
  733.  
  734.   // Run through the parameters for all catch clauses and generate var descriptors...
  735.   for (cat = methOrFunction->catchList; cat; cat = cat->nextInMethOrFunction) {
  736.     for (parm = cat->parmList; parm; parm = (Parameter *) parm->next) {
  737.       genVarDescriptor (parm);
  738.     }
  739.   }
  740. }
  741.  
  742.  
  743.  
  744. // genVarDescriptor (varDecl)
  745. //
  746. // This routine is passed a local or a catch parameter.  It generates the
  747. // appropriate "IRVarDesc2" instruction.
  748. //
  749. void genVarDescriptor (VarDecl * varDecl) {
  750.   char kind;
  751.  
  752.   if (varDecl->type == NULL) {
  753.     if (varDecl->sizeInBytes == 1) {
  754.       kind = 'C';
  755.     } else {
  756.       kind = '?';
  757.     }
  758.   } else if (isCharType (varDecl->type)) {
  759.     kind = 'C';
  760.   } else if (isIntType (varDecl->type)) {
  761.     kind = 'I';
  762.   } else if (isBoolType (varDecl->type)) {
  763.     kind = 'B';
  764.   } else if (isDoubleType (varDecl->type)) {
  765.     kind = 'D';
  766.   } else if (isPtrType (varDecl->type) || isTypeOfNullType (varDecl->type)) {
  767.     kind = 'P';
  768.   } else if (isArrayType (varDecl->type)) {
  769.     kind = 'A';
  770.   } else if (isRecordType (varDecl->type)) {
  771.     kind = 'R';
  772.   } else if (isObjectType (varDecl->type)) {
  773.     kind = 'O';
  774.   } else {
  775.     programLogicError ("Unexpected type in genVarDescriptor");
  776.   }
  777.  
  778.   IRVarDesc2 (varDecl->varDescLabel, kind, varDecl->id->chars);
  779. }
  780.  
  781.  
  782.  
  783. // genStaticData (expr)
  784. //
  785. // This routine generates IR code for a static constant, e.g., for a global var.
  786. // It handles these cases:
  787. //    intConst, doubleConst, charConst, boolConst
  788. //    null ptr
  789. //    & glob
  790. //    function
  791. //    new Object
  792. //    new Record
  793. //    new Array
  794. //
  795. void genStaticData (Expression * expr) {
  796.   SendExpr * sendExpr;
  797.   VariableExpr * var;
  798.   Global * glob;
  799.   FunctionProto * funProto;
  800.   Constructor * constructor;
  801.   CountValue * countValue;
  802.   IntConst * intConst;
  803.   int i, n, nextOff;
  804.   FieldInit * f;
  805.  
  806.   switch (expr->op) {
  807.  
  808.     case INT_CONST:                                       // in genStaticData
  809.  
  810.       IRWord (((IntConst *) expr)->ivalue);
  811.       return;
  812.  
  813.     case DOUBLE_CONST:                                    // in genStaticData
  814.  
  815.       IRDouble (((DoubleConst *) expr)->rvalue);
  816.       return;
  817.  
  818.     case CHAR_CONST:                                      // in genStaticData
  819.  
  820.       IRByte (((CharConst *) expr)->ivalue);
  821.       return;
  822.  
  823.     case BOOL_CONST:                                      // in genStaticData
  824.  
  825.       IRByte (((BoolConst *) expr)->ivalue);
  826.       return;
  827.  
  828.     case NULL_CONST:                                      // in genStaticData
  829.  
  830.       IRWord (0);
  831.       return;
  832.  
  833.     case CLOSURE_EXPR:                                    // in genStaticData
  834.  
  835.       IRWord2 (((ClosureExpr *) expr)->function->newName);
  836.       return;
  837.  
  838.     case DYNAMIC_CHECK:                                   // in genStaticData
  839.  
  840.       genStaticData (((DynamicCheck *) expr)->expr);
  841.       return;
  842.  
  843.     case CONSTRUCTOR:                                     // in genStaticData
  844.  
  845.       constructor = (Constructor *) expr;
  846.       if (constructor->allocKind != NEW) {
  847.         programLogicError ("We should have eliminated ALLOC during check");
  848.       }
  849.  
  850.       // If this is "NEW ARRAY"...
  851.       if (constructor->kind == ARRAY) {
  852.         n = 0;
  853.         for (countValue = constructor->countValueList;
  854.              countValue;
  855.              countValue = countValue->next) {
  856.           if (countValue->count == NULL) {
  857.             i = 1;
  858.           } else {
  859.             intConst = (IntConst *) countValue->count;
  860.             if (intConst->op != INT_CONST) {
  861.               programLogicError ("We should have checked this in checkStaticData (5)");
  862.             }
  863.             i = intConst->ivalue;
  864.           }
  865.           n += i;
  866.         }
  867.         IRComment ("Static array");
  868.         IRWord3 (n, "number of elements");
  869.         for (countValue = constructor->countValueList;
  870.              countValue;
  871.              countValue = countValue->next) {
  872.           if (countValue->count == NULL) {
  873.             i = 1;
  874.           } else {
  875.             intConst = (IntConst *) countValue->count;
  876.             i = intConst->ivalue;
  877.           }
  878.           for (; i > 0; i--) {
  879.             genStaticData (countValue->value);
  880.           }
  881.         }
  882.         IRAlign ();
  883.  
  884.       // Else, if this is "NEW RECORD" or "NEW CLASS"...
  885.       } else if (constructor->kind == RECORD ||
  886.                  constructor->kind == CLASS) {
  887.         if (constructor->kind == RECORD) {
  888.           IRComment ("Static record");
  889.         } else {
  890.           IRComment ("Static object");
  891.           IRWord2 (constructor->myClass->newName);
  892.         }
  893.  
  894.         // If this is an object initialization with missing field inits...
  895.         if ((constructor->kind == CLASS) &&
  896.             (constructor->fieldInits == NULL)) {
  897.           for (i = constructor->sizeInBytes; i>4; i = i-4) {
  898.             IRWord (0);
  899.           }
  900.         }
  901.  
  902.         constructor->fieldInits = sortFieldInits (constructor->fieldInits);
  903.         nextOff = 4;
  904.         for (f = constructor->fieldInits; f; f = f->next) {
  905.           // Add padding zeros if necessary...
  906.           if (f->sizeInBytes >= 4) {
  907.             while (nextOff % 4 != 0) {
  908.               IRByte (0);
  909.               nextOff++;
  910.             }
  911.           }
  912.           genStaticData (f->expr);
  913.           nextOff += f->sizeInBytes;
  914.         }
  915.         // Add padding zeros if necessary...
  916.         while (nextOff % 4 != 0) {
  917.           IRByte (0);
  918.           nextOff++;
  919.         }
  920.       } else {
  921.         programLogicError ("Bad constructor->kind in genStaticData");
  922.       }
  923.       return;
  924.  
  925.     case VARIABLE_EXPR:                                   // in genStaticData
  926.  
  927.       var = (VariableExpr *) expr;
  928.       funProto = (FunctionProto *) var->myDef;
  929.       if (funProto->op != FUNCTION_PROTO) {
  930.         programLogicError ("We should have checked this in checkStaticData (1)");
  931.       }
  932.       IRWord2 (funProto->newName);
  933.       return;
  934.  
  935.     case SEND_EXPR:                                       // in genStaticData
  936.  
  937.       sendExpr = (SendExpr *) expr;
  938.       if (sendExpr->primitiveSymbol == PRIMITIVE_ADDRESS_OF) {
  939.         var = (VariableExpr *) sendExpr->receiver;
  940.         if (var->op != VARIABLE_EXPR) {
  941.           programLogicError ("We should have checked this in checkStaticData (2)");
  942.         }
  943.         glob = (Global *) var->myDef;
  944.         if (glob->op != GLOBAL) {
  945.           programLogicError ("We should have checked this in checkStaticData (3)");
  946.         }
  947.         IRWord2 (glob->id->chars);
  948.         return;
  949.       } else {
  950.         programLogicError ("We should have checked this in checkStaticData (4)");
  951.       }
  952.       break;
  953.  
  954.   }
  955.  
  956.   printf ("node->op = %s\n", symbolName (expr->op));
  957.   pretty (expr);
  958.   programLogicError ("Unexpected node in genStaticData");
  959. }
  960.  
  961.  
  962.  
  963. // sortFieldInits (fieldList) -> fieldList
  964. //
  965. // This routine is passed a list of FieldInit nodes.  It sorts them,
  966. // based on their offsets.  (This uses insertion sort, but this shouldn't
  967. // be too time-consuming since record and class sizes should be small.)
  968. //
  969. FieldInit * sortFieldInits (FieldInit * f) {
  970.   FieldInit * oldList, * newList, * g, * newF;
  971.  
  972.   // printf ("=====SORTING FIELD INITS=====\n");
  973.  
  974.   if (f == NULL) return NULL;
  975.   oldList = f->next;
  976.   newList = f;
  977.   f->next = NULL;
  978.  
  979.   //    printf ("oldList = ");
  980.   //    for (f = oldList; f; f = f->next) {
  981.   //      printf ("%s ", f->id->chars);
  982.   //    }
  983.   //    printf ("\n");
  984.  
  985.   f = oldList;
  986.   while (f) {
  987.     newF = f->next;
  988.     oldList = f->next;
  989.     f->next = NULL;
  990.     //    printf ("=====  EXAMINING f = %s...  =====\n", f->id->chars);
  991.     if (f->offset < newList->offset) {
  992.       f->next = newList;
  993.       newList = f;
  994.       //    printf ("  inserting at front\n");
  995.     } else {
  996.       //    printf ("  searching...\n");
  997.       for (g = newList; ; g = g->next) {
  998.         //    printf ("    considering g = %s...\n", g->id->chars);
  999.         if (g->next == NULL) break;
  1000.         if (f->offset < g->next->offset) break;
  1001.       }
  1002.       //    printf ("    inserting after g = %s...\n", g->id->chars);
  1003.       f->next = g->next;
  1004.       g->next = f;
  1005.     }
  1006.  
  1007.     //    printf ("oldList = ");
  1008.     //    for (f = oldList; f; f = f->next) {
  1009.     //      printf ("%s ", f->id->chars);
  1010.     //    }
  1011.     //    printf ("\n");
  1012.  
  1013.     //    printf ("newList = ");
  1014.     //    for (f = newList; f; f = f->next) {
  1015.     //      printf ("%s ", f->id->chars);
  1016.     //    }
  1017.     //    printf ("\n");
  1018.  
  1019.     f = newF;
  1020.   }
  1021.  
  1022.   //    printf ("========================== DONE: newList = ");
  1023.   //    for (f = newList; f; f = f->next) {
  1024.   //      printf ("%s ", f->id->chars);
  1025.   //    }
  1026.   //    printf ("\n");
  1027.  
  1028.   return newList;
  1029.  
  1030. }
  1031.  
  1032.  
  1033.  
  1034. // genStmts (stmtList)
  1035. //
  1036. // This routine generates IR code for a list of statements.
  1037. //
  1038. void genStmts (Statement * stmt) {
  1039.   while (stmt) {
  1040.     // printf ("PROCESSING %s\n", symbolName (stmt->op));
  1041.     switch (stmt->op) {
  1042.       case IF_STMT:
  1043.         IRComment ("IF STATEMENT...");
  1044.         genLineNumber (stmt, "IF");
  1045.         genIfStmt ((IfStmt *) stmt);
  1046.         break;
  1047.       case ASSIGN_STMT:
  1048.         IRComment ("ASSIGNMENT STATEMENT...");
  1049.         genLineNumber (stmt, "AS");
  1050.         genAssignStmt ((AssignStmt *) stmt);
  1051.         break;
  1052.       case CALL_STMT:
  1053.         IRComment ("CALL STATEMENT...");
  1054.         // genLineNumber (stmt, "CA");
  1055.         genCallStmt ((CallStmt *) stmt);
  1056.         break;
  1057.       case SEND_STMT:
  1058.         IRComment ("SEND STATEMENT...");
  1059.         // genLineNumber (stmt, "SE");
  1060.         genSendStmt ((SendStmt *) stmt);
  1061.         break;
  1062.       case WHILE_STMT:
  1063.         IRComment ("WHILE STATEMENT...");
  1064.         // genLineNumber (stmt, "WH");
  1065.         genWhileStmt ((WhileStmt *) stmt);
  1066.         break;
  1067.       case DO_STMT:
  1068.         IRComment ("DO STATEMENT...");
  1069.         // genLineNumber (stmt, "DO");
  1070.         genDoStmt ((DoStmt *) stmt);
  1071.         break;
  1072.       case BREAK_STMT:
  1073.         IRComment ("BREAK STATEMENT...");
  1074.         genLineNumber (stmt, "BR");
  1075.         genBreakStmt ((BreakStmt *) stmt);
  1076.         break;
  1077.       case CONTINUE_STMT:
  1078.         IRComment ("CONTINUE STATEMENT...");
  1079.         genLineNumber (stmt, "CO");
  1080.         genContinueStmt ((ContinueStmt *) stmt);
  1081.         break;
  1082.       case RETURN_STMT:
  1083.         IRComment ("RETURN STATEMENT...");
  1084.         genLineNumber (stmt, "RE");
  1085.         genReturnStmt ((ReturnStmt *) stmt);
  1086.         break;
  1087.       case FOR_STMT:
  1088.         IRComment ("FOR STATEMENT...");
  1089.         genLineNumber (stmt, "FO");
  1090.         genForStmt ((ForStmt *) stmt);
  1091.         break;
  1092.       case SWITCH_STMT:
  1093.         // IRComment ("SWITCH STATEMENT...");
  1094.         // genLineNumber (stmt, "SW");
  1095.         genSwitchStmt ((SwitchStmt *) stmt);
  1096.         break;
  1097.       case TRY_STMT:
  1098.         IRComment ("TRY STATEMENT...");
  1099.         genLineNumber (stmt, "TR");
  1100.         genTryStmt ((TryStmt *) stmt);
  1101.         break;
  1102.       case THROW_STMT:
  1103.         IRComment ("THROW STATEMENT...");
  1104.         genLineNumber (stmt, "TH");
  1105.         genThrowStmt ((ThrowStmt *) stmt);
  1106.         break;
  1107.       case FREE_STMT:
  1108.         IRComment ("FREE STATEMENT...");
  1109.         genLineNumber (stmt, "FR");
  1110.         genFreeStmt ((FreeStmt *) stmt);
  1111.         break;
  1112.       case DEBUG_STMT:
  1113.         IRComment ("--------------------  DEBUG  --------------------");
  1114.         genLineNumber (stmt, "DE");
  1115.         IRDebug ();
  1116.         break;
  1117.       default:
  1118.         printf ("\nstmt->op = %s\n", symbolName (stmt->op));
  1119.         programLogicError ("Unknown op in genStmts");
  1120.     }
  1121.     stmt = stmt->next;
  1122.   }
  1123.  
  1124. }
  1125.  
  1126.  
  1127.  
  1128. //
  1129. // genIfStmt (ifStmt)
  1130. //
  1131. void genIfStmt (IfStmt * ifStmt) {
  1132.   char * trueLabel, * falseLabel, * endLabel;
  1133.   trueLabel = newLabel ();
  1134.   falseLabel = newLabel ();
  1135.   genExprInto (NULL, ifStmt->expr, trueLabel, falseLabel);
  1136.   IRLabel (trueLabel);
  1137.   if (ifStmt->thenStmts) {
  1138.     IRComment ("THEN...");
  1139.     genLineNumber (ifStmt->thenStmts, "TN");
  1140.     genStmts (ifStmt->thenStmts);
  1141.   }
  1142.   if (ifStmt->elseStmts) {
  1143.     endLabel = newLabel ();
  1144.     IRGoto (endLabel);
  1145.     IRLabel (falseLabel);
  1146.     IRComment ("ELSE...");
  1147.     genLineNumber (ifStmt->elseStmts, "EL");
  1148.     genStmts (ifStmt->elseStmts);
  1149.     IRComment ("END IF...");
  1150.     IRLabel (endLabel);
  1151.   } else {
  1152.     IRComment ("END IF...");
  1153.     IRLabel (falseLabel);
  1154.   }
  1155. }
  1156.  
  1157.  
  1158.  
  1159. //
  1160. // genAssignStmt (assignStmt)
  1161. //
  1162. void genAssignStmt (AssignStmt * assignStmt) {
  1163.   AstNode * temp;
  1164.   Expression * lvalue;
  1165.   VariableExpr * var;
  1166.   VarDecl * varDecl, * varDecl2;
  1167.   Expression * arg1, * arg2;
  1168.  
  1169.   // Look at the L-Value...
  1170.   lvalue = assignStmt->lvalue;
  1171.  
  1172.   // printf ("ASSIGNMENT STMT (assignStmt->dynamicCheck = %d):\n    ",
  1173.   //         assignStmt->dynamicCheck);
  1174.   // pretty (assignStmt);
  1175.  
  1176.   // Case 0: NORMAL ASSIGNMENT: x = y...
  1177.   if (assignStmt->dynamicCheck == 0) {
  1178.  
  1179.     if (assignStmt->sizeInBytes < 1) {
  1180.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt");
  1181.     }
  1182.  
  1183.     // If it is a LOCAL, GLOBAL, CLASS_FIELD, or PARAMETER...
  1184.     if (lvalue->op == VARIABLE_EXPR) {
  1185.       var = (VariableExpr *) lvalue;
  1186.       varDecl = (VarDecl *) var->myDef;
  1187.       if (varDecl == NULL) {
  1188.         programLogicError ("In genAssignStmt, lvalue->myDef == NULL");
  1189.       }
  1190.       if ((varDecl->op == LOCAL) ||
  1191.           (varDecl->op == GLOBAL) ||
  1192.           (varDecl->op == CLASS_FIELD) ||
  1193.           (varDecl->op == PARAMETER)) {
  1194.         // Call GenExprInto to do the work...
  1195.         genExprInto (varDecl, assignStmt->expr, NULL, NULL);
  1196.         return;
  1197.       }
  1198.     }
  1199.  
  1200.     // Else, we have something such as "x.field = y"...
  1201.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the data area
  1202.     temp = genExpr (assignStmt->expr, assignStmt->sizeInBytes);
  1203.     IRMove (NULL,  varDecl, temp, NULL, assignStmt->sizeInBytes);
  1204.  
  1205.  
  1206.   // Case 1: OBJECT ASSIGNMENT: *objPtr = *objPtr...
  1207.   } else if (assignStmt->dynamicCheck == 1) {
  1208.     //   printf ("Case 1: OBJECT ASSIGNMENT: *objPtr = *objPtr:\n    ");
  1209.     //   pretty (assignStmt);
  1210.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1211.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1212.     IRDynamicObjectMove (varDecl, varDecl2);
  1213.  
  1214.  
  1215.   // Case 2: OBJECT ASSIGNMENT: *objPtr = x...
  1216.   } else if (assignStmt->dynamicCheck == 2) {
  1217.     //   printf ("Case 2: OBJECT ASSIGNMENT: *objPtr = x:\n    ");
  1218.     //   pretty (assignStmt);
  1219.     if (assignStmt->sizeInBytes < 1) {
  1220.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt, case 2");
  1221.     }
  1222.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1223.     temp = genExpr (assignStmt->expr, assignStmt->sizeInBytes);
  1224.     IRCheckDPT (varDecl, assignStmt->classDef);
  1225.     IRMove (NULL,  varDecl, temp, NULL, assignStmt->sizeInBytes);
  1226.  
  1227.  
  1228.   // Case 3: OBJECT ASSIGNMENT: x = *objPtr...
  1229.   } else if (assignStmt->dynamicCheck == 3) {
  1230.     //   printf ("Case 3: OBJECT ASSIGNMENT: x = *objPtr:\n    ");
  1231.     //   pretty (assignStmt);
  1232.     if (assignStmt->sizeInBytes < 1) {
  1233.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt, case 3");
  1234.     }
  1235.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1236.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1237.     IRCheckDPT2 (varDecl2, assignStmt->classDef);
  1238.     IRMove (NULL,  varDecl, NULL, varDecl2, assignStmt->sizeInBytes);
  1239.  
  1240.  
  1241.   // Case 4: ARRAY ASSIGNMENT: arr[10] = arr[10]...
  1242.   } else if (assignStmt->dynamicCheck == 4) {
  1243.     //   printf ("Case 4: ARRAY ASSIGNMENT: arr[10] = arr[10]:\n    ");
  1244.     //   pretty (assignStmt);
  1245.     if (assignStmt->sizeInBytes < 1) {
  1246.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt, case 4");
  1247.     }
  1248.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1249.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1250.     IRCheckArraySizeInt2 (varDecl, assignStmt->arraySize);   // arraySize=number of elts
  1251.     IRCheckArraySizeInt (varDecl2, assignStmt->arraySize);  // arraySize=number of elts
  1252.     IRMove (NULL,  varDecl, NULL, varDecl2, assignStmt->sizeInBytes);
  1253.  
  1254.  
  1255.   // Case 5: ARRAY ASSIGNMENT: arr[10] = arr[*]...
  1256.   } else if (assignStmt->dynamicCheck == 5) {
  1257.     //   printf ("Case 5: ARRAY ASSIGNMENT: arr[10] = arr[*]:\n    ");
  1258.     //   pretty (assignStmt);
  1259.     if (assignStmt->sizeInBytes < 1) {
  1260.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt, case 5");
  1261.     }
  1262.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1263.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1264.     IRCheckArraySizeInt2 (varDecl, assignStmt->arraySize);  // arraySize=number of elts
  1265.     IRCheckArraySizeInt (varDecl2, assignStmt->arraySize);  // arraySize=number of elts
  1266.     IRMove (NULL,  varDecl, NULL, varDecl2, assignStmt->sizeInBytes);
  1267.  
  1268.  
  1269.   // Case 6: ARRAY ASSIGNMENT: arr[*] = arr[10]...
  1270.   } else if (assignStmt->dynamicCheck == 6) {
  1271.     //   printf ("Case 6: ARRAY ASSIGNMENT: arr[*] = arr[10]:\n    ");
  1272.     //   pretty (assignStmt);
  1273.     if (assignStmt->sizeInBytes < 1) {
  1274.       programLogicError ("Error: sizeInBytes < 1 in genAssignStmt, case 6");
  1275.     }
  1276.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1277.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1278.     IRCheckArraySizeInt (varDecl, assignStmt->arraySize);   // arraySize=number of elts
  1279.     IRCheckArraySizeInt (varDecl2, assignStmt->arraySize);  // arraySize=number of elts
  1280.     IRMove (NULL,  varDecl, NULL, varDecl2, assignStmt->sizeInBytes);
  1281.  
  1282.  
  1283.   // Case 7: ARRAY ASSIGNMENT: arr[*] = arr[*]...
  1284.   } else if (assignStmt->dynamicCheck == 7) {
  1285.     //   printf ("Case 7: ARRAY ASSIGNMENT: arr[*] = arr[*]:\n    ");
  1286.     //   pretty (assignStmt);
  1287.     if (assignStmt->arraySize < 1) {
  1288.       programLogicError ("Error: arraySize < 1 in genAssignStmt, case 7");
  1289.     }
  1290.     varDecl = genAddressOf (assignStmt->lvalue);  // this new temp points to the dest area
  1291.     varDecl2 = genAddressOf (assignStmt->expr);   // this new temp points to the src area
  1292.     IRCopyArrays (varDecl, varDecl2, assignStmt->arraySize);  // arraySize=size of elts
  1293.  
  1294.   } else {
  1295.     programLogicError ("Unknown value for dynamicCheck, in genAssignStmt");
  1296.   }
  1297. }
  1298.  
  1299.  
  1300.  
  1301. //
  1302. // genCallStmt (callStmt)
  1303. //
  1304. void genCallStmt (CallStmt * callStmt) {
  1305.   genCallExpr (NULL, callStmt->expr, NULL, NULL);
  1306. }
  1307.  
  1308.  
  1309.  
  1310. //
  1311. // genCallExpr (target, callExpr, trueLabel, falseLabel)
  1312. // 
  1313. // This routine is called to generate code for a call expr.  It is passed
  1314. // a variable ("target") or labels ("trueLabel" and "falseLabel").
  1315. // This routine will generate code to perform the function call and move
  1316. // the result (if any) into target, or will generate code to branch to the labels.
  1317. //
  1318. // Case 1: The function returns "void".  In this case, "target", "trueLabel",
  1319. // and "falseLabel" will be all NULL.  The generated code will simply fall thru.
  1320. //
  1321. // Case 2: The function returns a value.  Either "target" will be a variable,
  1322. // or "trueLabel" and "falseLabel" will tell where to jump to.  If one label
  1323. // is present, both will be present.  If target is non-NULL, the labels will
  1324. // be NULL.  If the target is NULL, then the labels will be non-NULL.
  1325. //
  1326. void genCallExpr (VarDecl * target,
  1327.                   CallExpr * callExpr,
  1328.                   char * trueLabel,
  1329.                   char * falseLabel) {
  1330.   FunctionProto * funProto;
  1331.   VarDecl * resultVar, * varDecl;
  1332.   Expression * arg1, * arg2;
  1333.   AstNode * x, * y;
  1334.   char * lab1, * lab2;
  1335.   Argument * arg;
  1336.   Parameter * parm;
  1337.  
  1338.   switch (callExpr->primitiveSymbol) {
  1339.  
  1340.     case 0:            // I.e., not a primitive...
  1341.  
  1342.       break;
  1343.  
  1344.     case PRIMITIVE_INT_TO_DOUBLE:                              // in genCallExpr
  1345.  
  1346.       arg1 = callExpr->argList->expr;
  1347.       x = genExpr (arg1, 4);
  1348.       IRItoF (target, x);      
  1349.       return;
  1350.  
  1351.     case PRIMITIVE_DOUBLE_TO_INT:                              // in genCallExpr
  1352.  
  1353.       arg1 = callExpr->argList->expr;
  1354.       x = genExpr (arg1, 8);
  1355.       IRFtoI (target, x);      
  1356.       return;
  1357.  
  1358.     case PRIMITIVE_INT_TO_CHAR:                                // in genCallExpr
  1359.  
  1360.       arg1 = callExpr->argList->expr;
  1361.       x = genExpr (arg1, 4);
  1362.       IRItoC (target, x);      
  1363.       return;
  1364.  
  1365.     case PRIMITIVE_CHAR_TO_INT:                                // in genCallExpr
  1366.  
  1367.       arg1 = callExpr->argList->expr;
  1368.       x = genExpr (arg1, 1);
  1369.       IRCtoI (target, x);      
  1370.       return;
  1371.  
  1372.     case PRIMITIVE_POS_INF:                                    // in genCallExpr
  1373.  
  1374.       IRPosInf (target);
  1375.       return;
  1376.  
  1377.     case PRIMITIVE_NEG_INF:                                    // in genCallExpr
  1378.  
  1379.       IRNegInf (target);
  1380.       return;
  1381.  
  1382.     case PRIMITIVE_NEG_ZERO:                                   // in genCallExpr
  1383.  
  1384.       IRNegZero (target);
  1385.       return;
  1386.  
  1387.     case PRIMITIVE_PTR_TO_BOOL:                                // in genCallExpr
  1388.  
  1389.       arg1 = callExpr->argList->expr;
  1390.       x = genExpr (arg1, 4);
  1391.       if (trueLabel) {
  1392.         IRIntEQGoto (x, constantIntZero, falseLabel);
  1393.         IRGoto (trueLabel);
  1394.       } else {
  1395.         lab1 = newLabel ();
  1396.         lab2 = newLabel ();
  1397.         IRIntEQGoto (x, constantIntZero, lab1);
  1398.         IRAssign1 (target, constantTrue);
  1399.         IRGoto (lab2);
  1400.         IRLabel (lab1);
  1401.         IRAssign1 (target, constantFalse);
  1402.         IRLabel (lab2);
  1403.       }
  1404.       return;
  1405.  
  1406.     case PRIMITIVE_I_IS_ZERO:                                  // in genCallExpr
  1407.  
  1408.       arg1 = callExpr->argList->expr;
  1409.       x = genExpr (arg1, 4);
  1410.       if (trueLabel) {
  1411.         IRIntEqZero (x, trueLabel);
  1412.         IRGoto (falseLabel);
  1413.       } else {
  1414.         lab1 = newLabel ();
  1415.         lab2 = newLabel ();
  1416.         IRIntEqZero (x, lab1);
  1417.         IRAssign1 (target, constantFalse);
  1418.         IRGoto (lab2);
  1419.         IRLabel (lab1);
  1420.         IRAssign1 (target, constantTrue);
  1421.         IRLabel (lab2);
  1422.       }
  1423.       return;
  1424.  
  1425.     case PRIMITIVE_I_NOT_ZERO:                                 // in genCallExpr
  1426.  
  1427.       arg1 = callExpr->argList->expr;
  1428.       x = genExpr (arg1, 4);
  1429.       if (trueLabel) {
  1430.         IRIntEqZero (x, falseLabel);
  1431.         IRGoto (trueLabel);
  1432.       } else {
  1433.         lab1 = newLabel ();
  1434.         lab2 = newLabel ();
  1435.         IRIntEqZero (x, lab1);
  1436.         IRAssign1 (target, constantTrue);
  1437.         IRGoto (lab2);
  1438.         IRLabel (lab1);
  1439.         IRAssign1 (target, constantFalse);
  1440.         IRLabel (lab2);
  1441.       }
  1442.       return;
  1443.  
  1444.     default:                                                   // in genCallExpr
  1445.  
  1446.       printf ("primitiveSymbol = %s\n", symbolName (callExpr->primitiveSymbol));
  1447.       programLogicError ("In genCallExpr, unexpected primitiveSymbol");
  1448.   }
  1449.  
  1450.   if (callExpr->myDef == NULL) {
  1451.     programLogicError ("In genCallExpr, if not PRIMITIVE, myDef should be filled in");
  1452.   }
  1453.  
  1454.   // If we have a normal call...
  1455.   if (callExpr->myDef->op == FUNCTION_PROTO) {
  1456.     funProto = (FunctionProto *) callExpr->myDef;
  1457.  
  1458.     // Run through the arguments and evaluate each of them...
  1459.     parm = funProto->parmList;
  1460.     for (arg = callExpr->argList; arg; arg = arg->next) {
  1461.       if (parm == NULL) {
  1462.         programLogicError ("Should have same number of parms as args");
  1463.       }
  1464.       arg->tempName = genExpr (arg->expr, arg->sizeInBytes);
  1465.       parm = (Parameter *) parm->next;
  1466.     }
  1467.  
  1468.     // Run through the arguments and move each into its position in the frame...
  1469.     parm = funProto->parmList;
  1470.     for (arg = callExpr->argList; arg; arg = arg->next) {
  1471.       IRPrepareArg (arg->offset, arg->tempName, arg->sizeInBytes);
  1472.       parm = (Parameter *) parm->next;
  1473.     }
  1474.  
  1475.     // Call the function...
  1476.     IRComment ("  Call the function");
  1477.     if (funProto->isExternal) {
  1478.       genLineNumber (callExpr, "CE");
  1479.     } else {
  1480.       genLineNumber (callExpr, "CA");
  1481.     }
  1482.     IRCall (funProto->newName);
  1483.  
  1484.     // If this function returns a result...
  1485.     if (funProto->retSize > 0) {
  1486.       if (trueLabel) {
  1487.         // Generate branches...
  1488.         IRBoolTest2 (trueLabel, falseLabel);
  1489.       } else {
  1490.         // Move the result into "target"...
  1491.         IRRetrieveResult (target, funProto->retSize);
  1492.       }
  1493.     }
  1494.     return;
  1495.  
  1496.   }
  1497.  
  1498.   // Otherwise, we have something like "f(x)" where "f: ptr to function"...
  1499.   //   printf ("In genCallExpr, indirect call: ");
  1500.   //   pretty (callExpr);
  1501.  
  1502.   if ((callExpr->myDef->op != LOCAL) &&
  1503.       (callExpr->myDef->op != GLOBAL) &&
  1504.       (callExpr->myDef->op != PARAMETER) &&
  1505.       (callExpr->myDef->op != CLASS_FIELD)) {
  1506.     programLogicError ("callExpr->myDef->op is wrong");
  1507.   }
  1508.  
  1509.   varDecl = (VarDecl *) callExpr->myDef;
  1510.  
  1511.   // Run through the arguments and evaluate each of them...
  1512.   for (arg = callExpr->argList; arg; arg = arg->next) {
  1513.     arg->tempName = genExpr (arg->expr, arg->sizeInBytes);
  1514.   }
  1515.  
  1516.   // Run through the arguments and move each into its position in the frame...
  1517.   for (arg = callExpr->argList; arg; arg = arg->next) {
  1518.     IRPrepareArg (arg->offset, arg->tempName, arg->sizeInBytes);
  1519.   }
  1520.  
  1521.   // Call the function...
  1522.   IRComment2 ("  call indirectly through variable ", varDecl->id->chars, "");
  1523.   genLineNumber (callExpr, "CF");
  1524.   IRCallIndirect (varDecl);
  1525.  
  1526.   // If this function returns a result...
  1527.   if (callExpr->retSize > 0) {
  1528.     if (trueLabel) {
  1529.       // Generate branches...
  1530.       IRBoolTest2 (trueLabel, falseLabel);
  1531.     } else {
  1532.       // Move the result into "target"...
  1533.       IRRetrieveResult (target, callExpr->retSize);
  1534.     }
  1535.   }
  1536.  
  1537. }
  1538.  
  1539.  
  1540.  
  1541. //
  1542. // genSendStmt (sendStmt)
  1543. //
  1544. void genSendStmt (SendStmt * sendStmt) {
  1545.   genSendExpr (NULL, sendStmt->expr, NULL, NULL);
  1546. }
  1547.  
  1548.  
  1549.  
  1550. //
  1551. // genSendExpr (target, sendExpr, trueLabel, falseLabel)
  1552. //
  1553. // This routine is called to generate code for a send expr.  It is passed
  1554. // a variable ("target") or labels ("trueLabel" and "falseLabel").
  1555. // This routine will generate code to perform the method invocation and move
  1556. // the result (if any) into target, or will generate code to branch to the labels.
  1557. //
  1558. // Case 1: The method returns "void".  In this case, "target", "trueLabel",
  1559. // and "falseLabel" will be all NULL.  The generated code will simply fall thru.
  1560. //
  1561. // Case 2: The method returns a value.  Either "target" will be a variable,
  1562. // or "trueLabel" and "falseLabel" will tell where to jump to.  If one label
  1563. // is present, both will be present.  If target is non-NULL, the labels will
  1564. // be NULL.  If the target is NULL, then the labels will be non-NULL.
  1565. // 
  1566. void genSendExpr (VarDecl * target,
  1567.                   SendExpr * sendExpr,
  1568.                   char * trueLabel,
  1569.                   char * falseLabel) {
  1570.   MethodProto * methProto;
  1571.   VarDecl * resultVar, * tempVar, * ptr1, * ptr2;
  1572.   Expression * arg1, * arg2;
  1573.   AstNode * x, * y;
  1574.   Local * temp;
  1575.   char * lab1, * lab2, * lab3;
  1576.   Parameter * parm;
  1577.   Argument * arg;
  1578.  
  1579.   //   printf ("SEND EXPR = ");
  1580.   //   pretty (sendExpr);
  1581.  
  1582.   // If we have a non-primitive message-send...
  1583.   if (sendExpr->myProto != NULL) {
  1584.     genLineNumber (sendExpr, "SE");
  1585.     methProto = (MethodProto *) sendExpr->myProto;
  1586.  
  1587.     // Run through the arguments and evaluate each of them...
  1588.     parm = methProto->parmList;
  1589.     for (arg = sendExpr->argList; arg; arg = arg->next) {
  1590.       if (parm == NULL) {
  1591.         programLogicError ("Should have same number of parms as args");
  1592.       }
  1593.       arg->tempName = genExpr (arg->expr, arg->sizeInBytes);
  1594.       parm = (Parameter *) parm->next;
  1595.     }
  1596.  
  1597.     // Figure out the address of the receiver object...
  1598.     tempVar = genAddressOf (sendExpr->receiver);
  1599.  
  1600.     // Run through the arguments and move each into its position in the frame...
  1601.     parm = methProto->parmList;
  1602.     for (arg = sendExpr->argList; arg; arg = arg->next) {
  1603.       IRPrepareArg (arg->offset, arg->tempName, arg->sizeInBytes);
  1604.       parm = (Parameter *) parm->next;
  1605.     }
  1606.  
  1607.     // Do the send...
  1608.     IRSend (tempVar, methProto);
  1609.  
  1610.     // If this method returns a result...
  1611.     if (methProto->retSize > 0) {
  1612.       if (trueLabel) {
  1613.         IRBoolTest2 (trueLabel, falseLabel);
  1614.       } else {
  1615.         // Move the result into the target location...
  1616.         IRRetrieveResult (target, methProto->retSize);
  1617.       }
  1618.     }
  1619.  
  1620.     return;
  1621.   }
  1622.  
  1623.   // Otherwise, it must be a primitive.  See which primitive...
  1624.   switch (sendExpr->primitiveSymbol) {
  1625.  
  1626.     case PRIMITIVE_I_ADD:                          // in genSendExpr
  1627.  
  1628.       arg1 = sendExpr->receiver;
  1629.       arg2 = sendExpr->argList->expr;
  1630.       x = genExpr (arg1, 4);
  1631.       y = genExpr (arg2, 4);
  1632.       IRIAdd (target, x, y);      
  1633.       return;
  1634.  
  1635.     case PRIMITIVE_I_SUB:                          // in genSendExpr
  1636.  
  1637.       arg1 = sendExpr->receiver;
  1638.       arg2 = sendExpr->argList->expr;
  1639.       x = genExpr (arg1, 4);
  1640.       y = genExpr (arg2, 4);
  1641.       IRISub (target, x, y);      
  1642.       return;
  1643.  
  1644.     case PRIMITIVE_I_MUL:                          // in genSendExpr
  1645.  
  1646.       arg1 = sendExpr->receiver;
  1647.       arg2 = sendExpr->argList->expr;
  1648.       x = genExpr (arg1, 4);
  1649.       y = genExpr (arg2, 4);
  1650.       IRIMul (target, x, y);      
  1651.       return;
  1652.  
  1653.     case PRIMITIVE_I_DIV:                          // in genSendExpr
  1654.  
  1655.       arg1 = sendExpr->receiver;
  1656.       arg2 = sendExpr->argList->expr;
  1657.       x = genExpr (arg1, 4);
  1658.       y = genExpr (arg2, 4);
  1659.       IRIDiv (target, x, y);      
  1660.       return;
  1661.  
  1662.     case PRIMITIVE_I_REM:                          // in genSendExpr
  1663.  
  1664.       arg1 = sendExpr->receiver;
  1665.       arg2 = sendExpr->argList->expr;
  1666.       x = genExpr (arg1, 4);
  1667.       y = genExpr (arg2, 4);
  1668.       IRIRem (target, x, y);      
  1669.       return;
  1670.  
  1671.     case PRIMITIVE_I_SLL:                          // in genSendExpr
  1672.  
  1673.       arg1 = sendExpr->receiver;
  1674.       arg2 = sendExpr->argList->expr;
  1675.       x = genExpr (arg1, 4);
  1676.       y = genExpr (arg2, 4);
  1677.       IRSll (target, x, y);      
  1678.       return;
  1679.  
  1680.     case PRIMITIVE_I_SRA:                          // in genSendExpr
  1681.  
  1682.       arg1 = sendExpr->receiver;
  1683.       arg2 = sendExpr->argList->expr;
  1684.       x = genExpr (arg1, 4);
  1685.       y = genExpr (arg2, 4);
  1686.       IRSra (target, x, y);      
  1687.       return;
  1688.  
  1689.     case PRIMITIVE_I_SRL:                          // in genSendExpr
  1690.  
  1691.       arg1 = sendExpr->receiver;
  1692.       arg2 = sendExpr->argList->expr;
  1693.       x = genExpr (arg1, 4);
  1694.       y = genExpr (arg2, 4);
  1695.       IRSrl (target, x, y);      
  1696.       return;
  1697.  
  1698.     case PRIMITIVE_I_AND:                          // in genSendExpr
  1699.  
  1700.       arg1 = sendExpr->receiver;
  1701.       arg2 = sendExpr->argList->expr;
  1702.       x = genExpr (arg1, 4);
  1703.       y = genExpr (arg2, 4);
  1704.       IRAnd (target, x, y);      
  1705.       return;
  1706.  
  1707.     case PRIMITIVE_I_OR:                           // in genSendExpr
  1708.  
  1709.       arg1 = sendExpr->receiver;
  1710.       arg2 = sendExpr->argList->expr;
  1711.       x = genExpr (arg1, 4);
  1712.       y = genExpr (arg2, 4);
  1713.       IROr (target, x, y);      
  1714.       return;
  1715.  
  1716.     case PRIMITIVE_I_XOR:                          // in genSendExpr
  1717.  
  1718.       arg1 = sendExpr->receiver;
  1719.       arg2 = sendExpr->argList->expr;
  1720.       x = genExpr (arg1, 4);
  1721.       y = genExpr (arg2, 4);
  1722.       IRXor (target, x, y);      
  1723.       return;
  1724.  
  1725.     case PRIMITIVE_I_NOT:                          // in genSendExpr
  1726.  
  1727.       arg1 = sendExpr->receiver;
  1728.       x = genExpr (arg1, 4);
  1729.       IRNot (target, x);      
  1730.       return;
  1731.  
  1732.     case PRIMITIVE_I_NEG:                          // in genSendExpr
  1733.  
  1734.       arg1 = sendExpr->receiver;
  1735.       x = genExpr (arg1, 4);
  1736.       IRINeg (target, x);      
  1737.       return;
  1738.  
  1739.     case PRIMITIVE_D_ADD:                          // in genSendExpr
  1740.  
  1741.       arg1 = sendExpr->receiver;
  1742.       arg2 = sendExpr->argList->expr;
  1743.       x = genExpr (arg1, 8);
  1744.       y = genExpr (arg2, 8);
  1745.       IRFAdd (target, x, y);      
  1746.       return;
  1747.  
  1748.     case PRIMITIVE_D_SUB:                          // in genSendExpr
  1749.  
  1750.       arg1 = sendExpr->receiver;
  1751.       arg2 = sendExpr->argList->expr;
  1752.       x = genExpr (arg1, 8);
  1753.       y = genExpr (arg2, 8);
  1754.       IRFSub (target, x, y);      
  1755.       return;
  1756.  
  1757.     case PRIMITIVE_D_MUL:                          // in genSendExpr
  1758.  
  1759.       arg1 = sendExpr->receiver;
  1760.       arg2 = sendExpr->argList->expr;
  1761.       x = genExpr (arg1, 8);
  1762.       y = genExpr (arg2, 8);
  1763.       IRFMul (target, x, y);      
  1764.       return;
  1765.  
  1766.     case PRIMITIVE_D_DIV:                          // in genSendExpr
  1767.  
  1768.       arg1 = sendExpr->receiver;
  1769.       arg2 = sendExpr->argList->expr;
  1770.       x = genExpr (arg1, 8);
  1771.       y = genExpr (arg2, 8);
  1772.       IRFDiv (target, x, y);      
  1773.       return;
  1774.  
  1775.     case PRIMITIVE_D_NEG:                          // in genSendExpr
  1776.  
  1777.       arg1 = sendExpr->receiver;
  1778.       x = genExpr (arg1, 8);
  1779.       IRFNeg (target, x);      
  1780.       return;
  1781.  
  1782.     case PRIMITIVE_I_LT:                           // in genSendExpr
  1783.  
  1784.       if (trueLabel) {
  1785.         arg1 = sendExpr->receiver;
  1786.         arg2 = sendExpr->argList->expr;
  1787.         x = genExpr (arg1, 4);
  1788.         y = genExpr (arg2, 4);
  1789.         IRIntGEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1790.         IRGoto (trueLabel);              // goto that can often be optimized
  1791.       } else {
  1792.         lab1 = newLabel ();
  1793.         lab2 = newLabel ();
  1794.         lab3 = newLabel ();
  1795.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1796.         IRLabel (lab1);
  1797.         IRAssign1 (target, constantTrue);
  1798.         IRGoto (lab3);
  1799.         IRLabel (lab2);
  1800.         IRAssign1 (target, constantFalse);
  1801.         IRLabel (lab3);
  1802.       }     
  1803.       return;
  1804.  
  1805.     case PRIMITIVE_I_LE:                           // in genSendExpr
  1806.  
  1807.       if (trueLabel) {
  1808.         arg1 = sendExpr->receiver;
  1809.         arg2 = sendExpr->argList->expr;
  1810.         x = genExpr (arg1, 4);
  1811.         y = genExpr (arg2, 4);
  1812.         IRIntGTGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1813.         IRGoto (trueLabel);              // goto that can often be optimized
  1814.       } else {
  1815.         lab1 = newLabel ();
  1816.         lab2 = newLabel ();
  1817.         lab3 = newLabel ();
  1818.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1819.         IRLabel (lab1);
  1820.         IRAssign1 (target, constantTrue);
  1821.         IRGoto (lab3);
  1822.         IRLabel (lab2);
  1823.         IRAssign1 (target, constantFalse);
  1824.         IRLabel (lab3);
  1825.       }     
  1826.       return;
  1827.  
  1828.     case PRIMITIVE_I_GT:                           // in genSendExpr
  1829.  
  1830.       if (trueLabel) {
  1831.         arg1 = sendExpr->receiver;
  1832.         arg2 = sendExpr->argList->expr;
  1833.         x = genExpr (arg1, 4);
  1834.         y = genExpr (arg2, 4);
  1835.         IRIntLEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1836.         IRGoto (trueLabel);              // goto that can often be optimized
  1837.       } else {
  1838.         lab1 = newLabel ();
  1839.         lab2 = newLabel ();
  1840.         lab3 = newLabel ();
  1841.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1842.         IRLabel (lab1);
  1843.         IRAssign1 (target, constantTrue);
  1844.         IRGoto (lab3);
  1845.         IRLabel (lab2);
  1846.         IRAssign1 (target, constantFalse);
  1847.         IRLabel (lab3);
  1848.       }     
  1849.       return;
  1850.  
  1851.     case PRIMITIVE_I_GE:                           // in genSendExpr
  1852.  
  1853.       if (trueLabel) {
  1854.         arg1 = sendExpr->receiver;
  1855.         arg2 = sendExpr->argList->expr;
  1856.         x = genExpr (arg1, 4);
  1857.         y = genExpr (arg2, 4);
  1858.         IRIntLTGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1859.         IRGoto (trueLabel);              // goto that can often be optimized
  1860.       } else {
  1861.         lab1 = newLabel ();
  1862.         lab2 = newLabel ();
  1863.         lab3 = newLabel ();
  1864.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1865.         IRLabel (lab1);
  1866.         IRAssign1 (target, constantTrue);
  1867.         IRGoto (lab3);
  1868.         IRLabel (lab2);
  1869.         IRAssign1 (target, constantFalse);
  1870.         IRLabel (lab3);
  1871.       }     
  1872.       return;
  1873.  
  1874.     case PRIMITIVE_I_EQ:                           // in genSendExpr
  1875.  
  1876.       if (trueLabel) {
  1877.         arg1 = sendExpr->receiver;
  1878.         arg2 = sendExpr->argList->expr;
  1879.         x = genExpr (arg1, 4);
  1880.         y = genExpr (arg2, 4);
  1881.         IRIntNEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1882.         IRGoto (trueLabel);              // goto that can often be optimized
  1883.       } else {
  1884.         lab1 = newLabel ();
  1885.         lab2 = newLabel ();
  1886.         lab3 = newLabel ();
  1887.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1888.         IRLabel (lab1);
  1889.         IRAssign1 (target, constantTrue);
  1890.         IRGoto (lab3);
  1891.         IRLabel (lab2);
  1892.         IRAssign1 (target, constantFalse);
  1893.         IRLabel (lab3);
  1894.       }     
  1895.       return;
  1896.  
  1897.     case PRIMITIVE_I_NE:                           // in genSendExpr
  1898.  
  1899.       if (trueLabel) {
  1900.         arg1 = sendExpr->receiver;
  1901.         arg2 = sendExpr->argList->expr;
  1902.         x = genExpr (arg1, 4);
  1903.         y = genExpr (arg2, 4);
  1904.         IRIntEQGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1905.         IRGoto (trueLabel);              // goto that can often be optimized
  1906.       } else {
  1907.         lab1 = newLabel ();
  1908.         lab2 = newLabel ();
  1909.         lab3 = newLabel ();
  1910.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1911.         IRLabel (lab1);
  1912.         IRAssign1 (target, constantTrue);
  1913.         IRGoto (lab3);
  1914.         IRLabel (lab2);
  1915.         IRAssign1 (target, constantFalse);
  1916.         IRLabel (lab3);
  1917.       }     
  1918.       return;
  1919.  
  1920.     case PRIMITIVE_D_LT:                           // in genSendExpr
  1921.  
  1922.       if (trueLabel) {
  1923.         arg1 = sendExpr->receiver;
  1924.         arg2 = sendExpr->argList->expr;
  1925.         x = genExpr (arg1, 8);
  1926.         y = genExpr (arg2, 8);
  1927.         IRFloatGEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1928.         IRGoto (trueLabel);                // goto that can often be optimized
  1929.       } else {
  1930.         lab1 = newLabel ();
  1931.         lab2 = newLabel ();
  1932.         lab3 = newLabel ();
  1933.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1934.         IRLabel (lab1);
  1935.         IRAssign1 (target, constantTrue);
  1936.         IRGoto (lab3);
  1937.         IRLabel (lab2);
  1938.         IRAssign1 (target, constantFalse);
  1939.         IRLabel (lab3);
  1940.       }     
  1941.       return;
  1942.  
  1943.     case PRIMITIVE_D_LE:                           // in genSendExpr
  1944.  
  1945.       if (trueLabel) {
  1946.         arg1 = sendExpr->receiver;
  1947.         arg2 = sendExpr->argList->expr;
  1948.         x = genExpr (arg1, 8);
  1949.         y = genExpr (arg2, 8);
  1950.         IRFloatGTGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1951.         IRGoto (trueLabel);                // goto that can often be optimized
  1952.       } else {
  1953.         lab1 = newLabel ();
  1954.         lab2 = newLabel ();
  1955.         lab3 = newLabel ();
  1956.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1957.         IRLabel (lab1);
  1958.         IRAssign1 (target, constantTrue);
  1959.         IRGoto (lab3);
  1960.         IRLabel (lab2);
  1961.         IRAssign1 (target, constantFalse);
  1962.         IRLabel (lab3);
  1963.       }     
  1964.       return;
  1965.  
  1966.     case PRIMITIVE_D_GT:                           // in genSendExpr
  1967.  
  1968.       if (trueLabel) {
  1969.         arg1 = sendExpr->receiver;
  1970.         arg2 = sendExpr->argList->expr;
  1971.         x = genExpr (arg1, 8);
  1972.         y = genExpr (arg2, 8);
  1973.         IRFloatLEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1974.         IRGoto (trueLabel);                // goto that can often be optimized
  1975.       } else {
  1976.         lab1 = newLabel ();
  1977.         lab2 = newLabel ();
  1978.         lab3 = newLabel ();
  1979.         genSendExpr (NULL, sendExpr, lab1, lab2);
  1980.         IRLabel (lab1);
  1981.         IRAssign1 (target, constantTrue);
  1982.         IRGoto (lab3);
  1983.         IRLabel (lab2);
  1984.         IRAssign1 (target, constantFalse);
  1985.         IRLabel (lab3);
  1986.       }     
  1987.       return;
  1988.  
  1989.     case PRIMITIVE_D_GE:                           // in genSendExpr
  1990.  
  1991.       if (trueLabel) {
  1992.         arg1 = sendExpr->receiver;
  1993.         arg2 = sendExpr->argList->expr;
  1994.         x = genExpr (arg1, 8);
  1995.         y = genExpr (arg2, 8);
  1996.         IRFloatLTGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  1997.         IRGoto (trueLabel);                // goto that can often be optimized
  1998.       } else {
  1999.         lab1 = newLabel ();
  2000.         lab2 = newLabel ();
  2001.         lab3 = newLabel ();
  2002.         genSendExpr (NULL, sendExpr, lab1, lab2);
  2003.         IRLabel (lab1);
  2004.         IRAssign1 (target, constantTrue);
  2005.         IRGoto (lab3);
  2006.         IRLabel (lab2);
  2007.         IRAssign1 (target, constantFalse);
  2008.         IRLabel (lab3);
  2009.       }     
  2010.       return;
  2011.  
  2012.     case PRIMITIVE_D_EQ:                           // in genSendExpr
  2013.  
  2014.       if (trueLabel) {
  2015.         arg1 = sendExpr->receiver;
  2016.         arg2 = sendExpr->argList->expr;
  2017.         x = genExpr (arg1, 8);
  2018.         y = genExpr (arg2, 8);
  2019.         IRFloatNEGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  2020.         IRGoto (trueLabel);                // goto that can often be optimized
  2021.       } else {
  2022.         lab1 = newLabel ();
  2023.         lab2 = newLabel ();
  2024.         lab3 = newLabel ();
  2025.         genSendExpr (NULL, sendExpr, lab1, lab2);
  2026.         IRLabel (lab1);
  2027.         IRAssign1 (target, constantTrue);
  2028.         IRGoto (lab3);
  2029.         IRLabel (lab2);
  2030.         IRAssign1 (target, constantFalse);
  2031.         IRLabel (lab3);
  2032.       }     
  2033.       return;
  2034.  
  2035.     case PRIMITIVE_D_NE:                           // in genSendExpr
  2036.  
  2037.       if (trueLabel) {
  2038.         arg1 = sendExpr->receiver;
  2039.         arg2 = sendExpr->argList->expr;
  2040.         x = genExpr (arg1, 8);
  2041.         y = genExpr (arg2, 8);
  2042.         IRFloatEQGoto (x, y, falseLabel);  // Reverse test so we can end w/ a
  2043.         IRGoto (trueLabel);                // goto that can often be optimized
  2044.       } else {
  2045.         lab1 = newLabel ();
  2046.         lab2 = newLabel ();
  2047.         lab3 = newLabel ();
  2048.         genSendExpr (NULL, sendExpr, lab1, lab2);
  2049.         IRLabel (lab1);
  2050.         IRAssign1 (target, constantTrue);
  2051.         IRGoto (lab3);
  2052.         IRLabel (lab2);
  2053.         IRAssign1 (target, constantFalse);
  2054.         IRLabel (lab3);
  2055.       }     
  2056.       return;
  2057.  
  2058.     case PRIMITIVE_B_AND:                          // in genSendExpr
  2059.  
  2060.       if (trueLabel) {
  2061.         arg1 = sendExpr->receiver;
  2062.         arg2 = sendExpr->argList->expr;
  2063.         lab1 = newLabel ();
  2064.         genExprInto (NULL, arg1, lab1, falseLabel);
  2065.         IRLabel (lab1);
  2066.         genExprInto (NULL, arg2, trueLabel, falseLabel);
  2067.       } else {
  2068.         lab1 = newLabel ();
  2069.         lab2 = newLabel ();
  2070.         lab3 = newLabel ();
  2071.         genSendExpr (NULL, sendExpr, lab1, lab2);
  2072.         IRLabel (lab1);
  2073.         IRAssign1 (target, constantTrue);
  2074.         IRGoto (lab3);
  2075.         IRLabel (lab2);
  2076.         IRAssign1 (target, constantFalse);
  2077.         IRLabel (lab3);
  2078.       }     
  2079.       return;
  2080.  
  2081.     case PRIMITIVE_B_OR:                           // in genSendExpr
  2082.  
  2083.       if (trueLabel) {
  2084.         arg1 = sendExpr->receiver;
  2085.         arg2 = sendExpr->argList->expr;
  2086.         lab1 = newLabel ();
  2087.         genExprInto (NULL, arg1, trueLabel, lab1);
  2088.         IRLabel (lab1);
  2089.         genExprInto (NULL, arg2, trueLabel, falseLabel);
  2090.       } else {
  2091.         lab1 = newLabel ();
  2092.         lab2 = newLabel ();
  2093.         lab3 = newLabel ();
  2094.         genSendExpr (NULL, sendExpr, lab1, lab2);
  2095.         IRLabel (lab1);
  2096.         IRAssign1 (target, constantTrue);
  2097.         IRGoto (lab3);
  2098.         IRLabel (lab2);
  2099.         IRAssign1 (target, constantFalse);
  2100.         IRLabel (lab3);
  2101.       }     
  2102.       return;
  2103.  
  2104.     case PRIMITIVE_B_EQ:                           // in genSendExpr
  2105.  
  2106.       arg1 = sendExpr->receiver;
  2107.       arg2 = sendExpr->argList->expr;
  2108.       x = genExpr (arg1, 1);
  2109.       y = genExpr (arg2, 1);
  2110.       if (trueLabel) {
  2111.         temp = newTemp (1);
  2112.         IRBXor (temp, x, y);
  2113.         IRBoolTest (temp, falseLabel, trueLabel);
  2114.       } else {
  2115.         IRBEq (target, x, y);
  2116.       }     
  2117.       return;
  2118.  
  2119.     case PRIMITIVE_B_NE:                           // in genSendExpr
  2120.  
  2121.       arg1 = sendExpr->receiver;
  2122.       arg2 = sendExpr->argList->expr;
  2123.       x = genExpr (arg1, 1);
  2124.       y = genExpr (arg2, 1);
  2125.       if (trueLabel) {
  2126.         temp = newTemp (1);
  2127.         IRBXor (temp, x, y);
  2128.         IRBoolTest (temp, trueLabel, falseLabel);
  2129.       } else {
  2130.         IRBXor (target, x, y);
  2131.       }     
  2132.       return;
  2133.  
  2134.     case PRIMITIVE_B_NOT:                          // in genSendExpr
  2135.  
  2136.       arg1 = sendExpr->receiver;
  2137.       x = genExpr (arg1, 1);
  2138.       if (trueLabel) {
  2139.         IRBoolTest (x, falseLabel, trueLabel);
  2140.       } else {
  2141.         IRBNot (target, x);
  2142.       }     
  2143.       return;
  2144.  
  2145.     case PRIMITIVE_ADDRESS_OF:                     // in genSendExpr
  2146.  
  2147.       //   printf ("Address-of in genSendExpr... sub-expr = ");
  2148.       //   pretty (sendExpr->receiver);
  2149.       if (target == NULL) {
  2150.         programLogicError ("Should never have, e.g., 'if &x ...'");
  2151.       }
  2152.  
  2153.       // If this is a simple variable, then handle it immediately...
  2154.       if (sendExpr->receiver->op == VARIABLE_EXPR) {
  2155.         tempVar = (VarDecl *) (((VariableExpr *) (sendExpr->receiver))->myDef);
  2156.         if (tempVar->op == LOCAL ||
  2157.             tempVar->op == GLOBAL ||
  2158.             tempVar->op == PARAMETER ||
  2159.             tempVar->op == CLASS_FIELD) {
  2160.           IRLoadAddr2 (target, tempVar);
  2161.           return;
  2162.         }
  2163.       }
  2164.  
  2165.       // Else, call "genAddressOf" to do the work...
  2166.       //   printf ("Calling genAddressOf = ");
  2167.       //   pretty (sendExpr->receiver);
  2168.       IRAssign4 (target, genAddressOf (sendExpr->receiver));
  2169.       return;
  2170.  
  2171.     case PRIMITIVE_DEREF:                          // in genSendExpr
  2172.  
  2173.       if (trueLabel) {
  2174.         tempVar = (VarDecl *) genExpr (sendExpr->receiver, 4);
  2175.         if ((tempVar->op != LOCAL) &&
  2176.             (tempVar->op != GLOBAL) &&
  2177.             (tempVar->op != PARAMETER) &&
  2178.             (tempVar->op != INT_CONST) &&
  2179.             (tempVar->op != CLASS_FIELD)) {
  2180.           printf ("In genSendExpr with deref = ");
  2181.           pretty (sendExpr);
  2182.           printf ("tempVar = ");
  2183.           pretty (tempVar);
  2184.           programLogicError ("genExpr should return a 32-bit quantity for xxx in *xxx -- 1");
  2185.         }
  2186.         IRBoolEqZeroIndirect (tempVar, falseLabel);
  2187.         IRGoto (trueLabel);
  2188.         return;
  2189.       } else {
  2190.         //   printf ("In genSendExpr with deref = ");
  2191.         //   pretty (sendExpr);
  2192.         int sz = target->sizeInBytes;
  2193.         if (sz < 1) {
  2194.           printf ("size = %d\n", sz);
  2195.           programLogicError ("In genSendExpr, the size is missing");
  2196.         }
  2197.         // We have the target variable and an expression which will yield a ptr.
  2198.         tempVar = (VarDecl *) genExpr (sendExpr->receiver, 4);
  2199.         if ((tempVar->op != LOCAL) &&
  2200.             (tempVar->op != GLOBAL) &&
  2201.             (tempVar->op != PARAMETER) &&
  2202.             (tempVar->op != INT_CONST) &&
  2203.             (tempVar->op != CLASS_FIELD)) {
  2204.           printf ("In genSendExpr with deref = ");
  2205.           pretty (sendExpr);
  2206.           printf ("tempVar = ");
  2207.           pretty (tempVar);
  2208.           programLogicError ("genExpr should return a 32-bit quantity for xxx in *xxx -- 2");
  2209.         }
  2210.         IRIntEqZero (tempVar, "_runtimeErrorNullPointer");
  2211.         IRMove (target, NULL, NULL, tempVar, sz);   // tempVar is "srcPtr"
  2212.         return;
  2213.       }
  2214.  
  2215.     case PRIMITIVE_OBJECT_EQ:                      // in genSendExpr
  2216.  
  2217.       ptr1 = genAddressOf (sendExpr->receiver);
  2218.       ptr2 = genAddressOf (sendExpr->argList->expr);
  2219.       if (trueLabel) {
  2220.         lab1 = newLabel ();
  2221.         IRTestObjEq (ptr1, ptr2, trueLabel, falseLabel);
  2222.         return;
  2223.       } else {
  2224.         lab1 = newLabel ();
  2225.         lab2 = newLabel ();
  2226.         lab3 = newLabel ();
  2227.         IRTestObjEq (ptr1, ptr2, lab1, lab2);
  2228.         IRLabel (lab1);
  2229.         IRAssign1 (target, constantTrue);
  2230.         IRGoto (lab3);
  2231.         IRLabel (lab2);
  2232.         IRAssign1 (target, constantFalse);
  2233.         IRLabel (lab3);
  2234.         return;
  2235.       }
  2236.  
  2237.     case PRIMITIVE_OBJECT_NE:                      // in genSendExpr
  2238.  
  2239.       ptr1 = genAddressOf (sendExpr->receiver);
  2240.       ptr2 = genAddressOf (sendExpr->argList->expr);
  2241.       if (trueLabel) {
  2242.         lab1 = newLabel ();
  2243.         IRTestObjEq (ptr1, ptr2, falseLabel, trueLabel);
  2244.         return;
  2245.       } else {
  2246.         lab1 = newLabel ();
  2247.         lab2 = newLabel ();
  2248.         lab3 = newLabel ();
  2249.         IRTestObjEq (ptr1, ptr2, lab1, lab2);
  2250.         IRLabel (lab1);
  2251.         IRAssign1 (target, constantFalse);
  2252.         IRGoto (lab3);
  2253.         IRLabel (lab2);
  2254.         IRAssign1 (target, constantTrue);
  2255.         IRLabel (lab3);
  2256.         return;
  2257.       }
  2258.  
  2259.     default:                                       // in genSendExpr
  2260.       printf ("primitiveSymbol = %s\n", symbolName (sendExpr->primitiveSymbol));
  2261.       programLogicError ("In genSendExpr, unexpected primitiveSymbol");
  2262.   }
  2263.  
  2264. }
  2265.  
  2266.  
  2267.  
  2268. //
  2269. // genWhileStmt (whileStmt)
  2270. //
  2271. void genWhileStmt (WhileStmt * whileStmt) {
  2272.   char * continueLabel;
  2273.   whileStmt->topLabel = newLabel ();
  2274.   continueLabel = newLabel ();
  2275.   whileStmt->exitLabel = newLabel ();
  2276.   genLineNumber (whileStmt, "WH");
  2277.   IRLabel (whileStmt->topLabel);
  2278.   genExprInto (NULL, whileStmt->expr, continueLabel, whileStmt->exitLabel);
  2279.   IRLabel (continueLabel);
  2280.   genLineNumber (whileStmt, "WB");
  2281.   genStmts (whileStmt->stmts);
  2282.   IRComment ("END WHILE...");
  2283.   IRGoto (whileStmt->topLabel);
  2284.   IRLabel (whileStmt->exitLabel);
  2285. }
  2286.  
  2287.  
  2288.  
  2289. //
  2290. // genDoStmt (doStmt)
  2291. //
  2292. void genDoStmt (DoStmt * doStmt) {
  2293.   char * topLabel;
  2294.   topLabel = newLabel ();
  2295.   doStmt->testLabel = newLabel ();
  2296.   doStmt->exitLabel = newLabel ();
  2297.   IRLabel (topLabel);
  2298.   genLineNumber (doStmt, "DO");
  2299.   genStmts (doStmt->stmts);
  2300.   IRComment ("UNTIL...");
  2301.   IRLabel (doStmt->testLabel);
  2302.   genLineNumber (doStmt->expr, "DU");
  2303.   genExprInto (NULL, doStmt->expr, doStmt->exitLabel, topLabel);
  2304.   IRLabel (doStmt->exitLabel);
  2305. }
  2306.  
  2307.  
  2308.  
  2309. //
  2310. // genBreakStmt (breakStmt)
  2311. //
  2312. void genBreakStmt (BreakStmt * breakStmt) {
  2313.   ForStmt * forStmt;
  2314.   DoStmt * doStmt;
  2315.   WhileStmt * whileStmt;
  2316.   SwitchStmt * switchStmt;
  2317.  
  2318.   switch (breakStmt->enclosingStmt->op) {
  2319.     case FOR_STMT:
  2320.       forStmt = (ForStmt *) breakStmt->enclosingStmt;
  2321.       IRGoto (forStmt->exitLabel);
  2322.       return;
  2323.     case DO_STMT:
  2324.       doStmt = (DoStmt *) breakStmt->enclosingStmt;
  2325.       IRGoto (doStmt->exitLabel);
  2326.       return;
  2327.     case WHILE_STMT:
  2328.       whileStmt = (WhileStmt *) breakStmt->enclosingStmt;
  2329.       IRGoto (whileStmt->exitLabel);
  2330.       return;
  2331.     case SWITCH_STMT:
  2332.       switchStmt = (SwitchStmt *) breakStmt->enclosingStmt;
  2333.       IRGoto (switchStmt->exitLabel);
  2334.       return;
  2335.     default:
  2336.       programLogicError ("Unexected enclosingStmt in BreakStmt");
  2337.   }
  2338. }
  2339.  
  2340.  
  2341.  
  2342. //
  2343. // genContinueStmt (continueStmt)
  2344. //
  2345. void genContinueStmt (ContinueStmt * continueStmt) {
  2346.   ForStmt * forStmt;
  2347.   DoStmt * doStmt;
  2348.   WhileStmt * whileStmt;
  2349.  
  2350.   switch (continueStmt->enclosingStmt->op) {
  2351.     case FOR_STMT:
  2352.       forStmt = (ForStmt *) continueStmt->enclosingStmt;
  2353.       IRGoto (forStmt->incrLabel);
  2354.       return;
  2355.     case DO_STMT:
  2356.       doStmt = (DoStmt *) continueStmt->enclosingStmt;
  2357.       IRGoto (doStmt->testLabel);
  2358.       return;
  2359.     case WHILE_STMT:
  2360.       whileStmt = (WhileStmt *) continueStmt->enclosingStmt;
  2361.       IRGoto (whileStmt->topLabel);
  2362.       return;
  2363.     default:
  2364.       programLogicError ("Unexected enclosingStmt in ContinueStmt");
  2365.   }
  2366. }
  2367.  
  2368.  
  2369.  
  2370. //
  2371. // genReturnStmt (returnStmt)
  2372. //
  2373. void genReturnStmt (ReturnStmt * returnStmt) {
  2374.   AstNode * x;
  2375.   MethOrFunction * methOrFun;
  2376.  
  2377.   // If there is a return expression, generate code to compute and save it.
  2378.   if (returnStmt->expr) {
  2379.     // printf ("----------In genReturnStmt...  retSize = %d\n", returnStmt->retSize);
  2380.     x = genExpr (returnStmt->expr, returnStmt->retSize);
  2381.     IRReturnResult (x, returnStmt->retSize);
  2382.   }
  2383.  
  2384.   // Identify the enclosing method or function...
  2385.   methOrFun = returnStmt->enclosingMethOrFunction;
  2386.   if (methOrFun == NULL) {
  2387.     programLogicError ("returnStmt->enclosingMethOrFunction is NULL");
  2388.   }
  2389.  
  2390.   // If this method or function contained any "try" statements...
  2391.   if (methOrFun->containsTry) {
  2392.     if (methOrFun->catchStackSave == NULL) {
  2393.       programLogicError ("methOrFun->catchStackSave in NULL in genReturnStmt");
  2394.     }
  2395.     IRRestoreCatchStack (methOrFun->catchStackSave);
  2396.   }
  2397.  
  2398.   // Generate the return code...
  2399.   if (methOrFun->op == METHOD) {
  2400.     IRMethodReturn ((Method *) methOrFun);
  2401.   } else {
  2402.     IRFunctionReturn ((Function *) methOrFun);
  2403.   }
  2404.  
  2405. }
  2406.  
  2407.  
  2408.  
  2409. //
  2410. // genForStmt (forStmt)
  2411. //
  2412. // For a stmt such as:
  2413. //      FOR LValue = InitExpr TO FinalExpr BY StepExpr
  2414. //        ...Statements...
  2415. //      ENDFOR
  2416. // this routine generates the following code:
  2417. //
  2418. //         tempPtr = & LValue
  2419. //         tempStart = InitExpr
  2420. //         tempStop = FinalExpr
  2421. //         tempIncr = StepExpr
  2422. //         * tempPtr = tempStart
  2423. //     TOP_LABEL:
  2424. //             IF * tempPtr > tempStop GOTO EXIT_LABEL
  2425. //     CONTINUE_LABEL:
  2426. //             ...Statements...
  2427. //     INCR_LABEL:
  2428. //             * tempPtr = * tempPtr + tempIncr
  2429. //             goto TOP_LABEL
  2430. //     EXIT_LABEL:
  2431. //
  2432. // The "Continue" stmt will branch to INCR_LABEL.
  2433. // The "Break" stmt will branch to EXIT_LABEL.
  2434. //
  2435. // If the LValue is a LOCAL or PARAMETER, then we will not use "tempPtr"
  2436. // and will use the variable directly.
  2437. //
  2438. // Also, if the incr is an integer within 16 bits, we'll avoid "tempIncr".
  2439. //
  2440. void genForStmt (ForStmt * forStmt) {
  2441.  
  2442.   VarDecl * tempPtr, * tempStart, * tempStop, * tempIncr;
  2443.   char * topLabel, * continueLabel;
  2444.   int incrInteger;
  2445.   IntConst * intConst;
  2446.   VarDecl * localIndexVar, * def;
  2447.  
  2448.   topLabel = newLabel ();
  2449.   continueLabel = newLabel ();
  2450.   forStmt->incrLabel = newLabel ();
  2451.   forStmt->exitLabel = newLabel ();
  2452.  
  2453.   localIndexVar = NULL;
  2454.   if (forStmt->lvalue->op == VARIABLE_EXPR) {
  2455.     def = (VarDecl *) (((VariableExpr *) (forStmt->lvalue)) -> myDef);
  2456.     if ((def->op == LOCAL) ||
  2457.         (def->op == PARAMETER)) {
  2458.       localIndexVar = def;
  2459.     }
  2460.   }
  2461.  
  2462.   if (localIndexVar == NULL) {
  2463.     IRComment ("  Calculate and save the address of the FOR-LOOP index variable");
  2464.     tempPtr = newTemp (4);
  2465.     IRMove (tempPtr, NULL, genAddressOf (forStmt->lvalue), NULL, 4);
  2466.   }
  2467.  
  2468.   IRComment ("  Calculate and save the FOR-LOOP starting value");
  2469.   tempStart = newTemp (4);
  2470.   genExprInto (tempStart, forStmt->expr1, NULL, NULL);
  2471.  
  2472.   IRComment ("  Calculate and save the FOR-LOOP ending value");
  2473.   tempStop = newTemp (4);
  2474.   genExprInto (tempStop, forStmt->expr2, NULL, NULL);
  2475.  
  2476.   if (forStmt->expr3) {
  2477.     intConst = (IntConst *) forStmt->expr3;
  2478.     if (intConst->op == INT_CONST) {
  2479.       tempIncr = NULL;
  2480.       incrInteger = intConst->ivalue;
  2481.     } else {
  2482.       IRComment ("  Calculate and save the FOR-LOOP increment value");
  2483.       tempIncr = newTemp (4);
  2484.       genExprInto (tempIncr, forStmt->expr3, NULL, NULL);
  2485.     }
  2486.   } else {
  2487.     tempIncr = NULL;
  2488.     incrInteger = 1;
  2489.   }
  2490.  
  2491.   IRComment ("  Initialize FOR-LOOP index variable");
  2492.   if (localIndexVar) {
  2493.     IRMove (localIndexVar, NULL, tempStart, NULL, 4);
  2494.   } else {
  2495.     IRMove (NULL, tempPtr, tempStart, NULL, 4);
  2496.   }
  2497.   IRLabel (topLabel);
  2498.  
  2499.   // Perform the termination test...
  2500.   if (localIndexVar) {
  2501.     IRForTest2 (localIndexVar, tempStop, forStmt->exitLabel);
  2502.   } else {
  2503.     IRForTest (tempPtr, tempStop, forStmt->exitLabel);
  2504.   }
  2505.   IRLabel (continueLabel);
  2506.  
  2507.   // Here is the loop body...
  2508.   genLineNumber (forStmt, "FB");
  2509.   genStmts (forStmt->stmts);
  2510.  
  2511.   IRComment ("  Increment the FOR-LOOP index variable and jump back");
  2512.   IRLabel (forStmt->incrLabel);
  2513.   if (localIndexVar) {
  2514.     IRIncrVarDirect (localIndexVar, localIndexVar, tempIncr, incrInteger, 1);
  2515.                                                          // wantOverflowTest = 1
  2516.   } else {
  2517.     IRIncrVarIndirect (tempPtr, tempIncr, incrInteger);
  2518.   }
  2519.   IRGoto (topLabel);
  2520.   IRComment ("END FOR");
  2521.   IRLabel (forStmt->exitLabel);
  2522. }
  2523.  
  2524.  
  2525.  
  2526. //
  2527. // genSwitchStmt (switchStmt)
  2528. //
  2529. void genSwitchStmt (SwitchStmt * switchStmt) {
  2530.   Case * cas;
  2531.   char * defaultLabel, * tableName;
  2532.   int numberOfCases = 0, range;
  2533.   AstNode * expr;
  2534.   double density;
  2535.   char * * a;
  2536.   int * valueArray;
  2537.   int i, highValue, lowValue, tableSize;
  2538.  
  2539.   defaultLabel = newLabel ();
  2540.   switchStmt->exitLabel = newLabel ();
  2541.   highValue = switchStmt->highValue;
  2542.   lowValue = switchStmt->lowValue;
  2543.  
  2544.   // Run throught the cases and give each a label.
  2545.   for (cas = switchStmt->caseList; cas; cas = cas->next) {
  2546.     cas->label = newLabel ();
  2547.     numberOfCases++;
  2548.   }
  2549.  
  2550.   // Determine the range of values and the density a direct table would have...
  2551.   if (numberOfCases > 0) {
  2552.     range = (highValue - lowValue) + 1;
  2553.     if (range < 1) {
  2554.       programLogicError ("highValue and lowValue are invalid");
  2555.     }
  2556.     density = ((double) (numberOfCases)) / ((double) range);
  2557.   } else {
  2558.     density = 0.0;
  2559.   }
  2560.   //   printf ("SWITCH STMT: density = %g\n", density);
  2561.  
  2562.   // If the number of cases is <= 7, then generate a sequence of tests...
  2563.   if (numberOfCases <= 7) {
  2564.  
  2565.     IRComment ("SWITCH STATEMENT (using series of tests)...");
  2566.     genLineNumber (switchStmt, "SW");
  2567.     IRComment ("  Evaluate the switch expression...");
  2568.     expr = genExpr (switchStmt->expr, 4);
  2569.  
  2570.     // Run throught the cases and generate a test for each.
  2571.     IRComment ("  Branch to the right case label");
  2572.     IRSwitchReg1 (expr);
  2573.     for (cas = switchStmt->caseList; cas; cas = cas->next) {
  2574.       IRSwitchTestReg1 (cas->ivalue, cas->label);
  2575.     }
  2576.     IRGoto (defaultLabel);
  2577.  
  2578.   // If the density of cases is > .5 or the table would be fairly small,
  2579.   // then generate a direct-jump table...
  2580.   } else if (((density > 0.5) || (range <= 300)) &&
  2581.              (within16Bits (lowValue)) &&
  2582.              (within16Bits (highValue))) {
  2583.  
  2584.     IRComment ("SWITCH STATEMENT (using an indirect jump table)...");
  2585.     genLineNumber (switchStmt, "SW");
  2586.     IRComment ("  Evaluate the switch expression...");
  2587.     expr = genExpr (switchStmt->expr, 4);
  2588.  
  2589.     // Generate code to test the expr and make a jump into the direct table...
  2590.     tableName = newLabel ();
  2591.     IRSwitchDirect (expr, tableName, defaultLabel, lowValue, highValue);
  2592.     // Create an array of labels of the right size...
  2593.     //     printf ("lowValue = %d\n", lowValue);
  2594.     //     printf ("highValue = %d\n", highValue);
  2595.     //     printf ("range = %d\n", range);
  2596.     a = (char * *) calloc (4, range); 
  2597.     if (a == NULL) {
  2598.       fatalError ("Calloc failed in genSwitchStmt; out of memory perhaps???");
  2599.     }
  2600.     // Initialize the array so all entries are the default label...
  2601.     for (i = 0; i < range; i++) {
  2602.       a[i] = defaultLabel;
  2603.     }
  2604.     // Modify all entries for which we have a case...
  2605.     for (cas = switchStmt->caseList; cas; cas = cas->next) {
  2606.       a[cas->ivalue-lowValue] = cas->label;
  2607.     }
  2608.     IRComment ("  Jump table");
  2609.     IRLabel (tableName);
  2610.     for (i = 0; i < range; i++) {
  2611.       if (a[i] == defaultLabel) {
  2612.         IRGoto2 (a[i], i+lowValue, "missing - goto default code");
  2613.       } else {
  2614.         IRGoto2 (a[i], i+lowValue, "");
  2615.       }
  2616.     }
  2617.  
  2618.   // Generate a hash table lookup table and code to search it.
  2619.   } else {
  2620.  
  2621.     IRComment ("SWITCH STATEMENT (using a hash table)...");
  2622.     genLineNumber (switchStmt, "SW");
  2623.     IRComment ("  Evaluate the switch expression...");
  2624.     expr = genExpr (switchStmt->expr, 4);
  2625.  
  2626.     tableSize = roundUpToPrime (numberOfCases * 2);
  2627.     if (! within16Bits (tableSize)) {
  2628.       programLogicError ("IMPLEMENTATION RESTRICTION: In a Switch statement, there are too many cases (more than about 16000 cannot be handled)");
  2629.     }
  2630.     //      printf ("table size = %d\n", tableSize);
  2631.     tableName = newLabel ();
  2632.  
  2633.     // Create an array of labels of the right size...
  2634.     a = (char * *) calloc (4, tableSize); 
  2635.     if (a == NULL) {
  2636.       fatalError ("Calloc failed in genSwitchStmt; out of memory perhaps???");
  2637.     }
  2638.     // Initialize the array so all entries are NULL...
  2639.     for (i = 0; i < tableSize; i++) {
  2640.       a[i] = NULL;
  2641.     }
  2642.  
  2643.     // Create an array of values of the right size...
  2644.     valueArray = (int *) calloc (4, tableSize); 
  2645.     if (valueArray == NULL) {
  2646.       fatalError ("Calloc failed in genSwitchStmt; out of memory perhaps???");
  2647.     }
  2648.     // Initialize the array so all entries are zero...
  2649.     for (i = 0; i < tableSize; i++) {
  2650.       valueArray[i] = 0;
  2651.     }
  2652.  
  2653.     // Go through each case...
  2654.     for (cas = switchStmt->caseList; cas; cas = cas->next) {
  2655.       i = hashForSwitchStmt (cas->ivalue, tableSize);
  2656.       //   printf ("ivalue = %d    hash = %d\n", cas->ivalue, i);
  2657.       while (a[i] != NULL) {
  2658.         //    printf ("  i = %d already contains value = %d... incrementing...\n",
  2659.         //            i, valueArray[i]);
  2660.         i++;
  2661.         if (i == tableSize) {
  2662.           i = 0;
  2663.         }
  2664.       }
  2665.       //    printf ("  Updating i = %d\n", i);
  2666.       valueArray [i] = cas->ivalue;
  2667.       a [i] = cas->label;
  2668.     }
  2669.  
  2670.     IRSwitchHashJump (expr, tableName, defaultLabel, tableSize);
  2671.  
  2672.     IRComment ("  Hash table");
  2673.     IRLabel (tableName);
  2674.     for (i = 0; i < tableSize; i++) {
  2675.       IRComment3 ("Table entry ", i);
  2676.       IRWord (valueArray[i]);
  2677.       if (valueArray[i] == 0) {
  2678.         IRWord (0);
  2679.       } else {
  2680.         IRWord2 (a[i]);
  2681.       }
  2682.     }
  2683.  
  2684.   }
  2685.  
  2686.   // Run throught the cases and generate code for each.
  2687.   for (cas = switchStmt->caseList; cas; cas=cas->next) {
  2688.     IRComment3 ("CASE ", cas->ivalue); 
  2689.     IRLabel (cas->label);
  2690.     genStmts (cas->stmts);
  2691.   }
  2692.  
  2693.   // Generate code for the default stmt list, if any.
  2694.   IRComment ("DEFAULT CASE..."); 
  2695.   IRLabel (defaultLabel);
  2696.   genStmts (switchStmt->defaultStmts);
  2697.  
  2698.   // Generate the exit label, which is used by break stmts.
  2699.   IRComment ("END SWITCH..."); 
  2700.   IRLabel (switchStmt->exitLabel);
  2701.  
  2702. }
  2703.  
  2704.  
  2705.  
  2706. // roundUpToPrime (int) --> int
  2707. //
  2708. // This routine rounds the given number up to a prime number.
  2709. // With numbers larger than 200, it simply returns a prime number
  2710. // that is as big.  For switch statements with more than 30,000 cases--
  2711. // which are presumably machine generated and not expected to occur
  2712. // often--this routine will fail with a program logic error.
  2713. //
  2714. int roundUpToPrime (int i) {
  2715.   if (i <= 2) return 2;
  2716.   if (i <= 3) return 3;
  2717.   if (i <= 5) return 5;
  2718.   if (i <= 7) return 7;
  2719.   if (i <= 11) return 11;
  2720.   if (i <= 13) return 13;
  2721.   if (i <= 17) return 17;
  2722.   if (i <= 19) return 19;
  2723.   if (i <= 23) return 23;
  2724.   if (i <= 29) return 29;
  2725.   if (i <= 31) return 31;
  2726.   if (i <= 37) return 37;
  2727.   if (i <= 41) return 41;
  2728.   if (i <= 43) return 43;
  2729.   if (i <= 47) return 47;
  2730.   if (i <= 53) return 53;
  2731.   if (i <= 59) return 59;
  2732.   if (i <= 61) return 61;
  2733.   if (i <= 67) return 67;
  2734.   if (i <= 71) return 71;
  2735.   if (i <= 73) return 73;
  2736.   if (i <= 79) return 79;
  2737.   if (i <= 83) return 83;
  2738.   if (i <= 89) return 89;
  2739.   if (i <= 97) return 97;
  2740.   if (i <= 101) return 101;
  2741.   if (i <= 103) return 103;
  2742.   if (i <= 107) return 107;
  2743.   if (i <= 109) return 109;
  2744.   if (i <= 113) return 113;
  2745.   if (i <= 127) return 127;
  2746.   if (i <= 131) return 131;
  2747.   if (i <= 137) return 137;
  2748.   if (i <= 139) return 139;
  2749.   if (i <= 149) return 149;
  2750.   if (i <= 151) return 151;
  2751.   if (i <= 157) return 157;
  2752.   if (i <= 163) return 163;
  2753.   if (i <= 167) return 167;
  2754.   if (i <= 173) return 173;
  2755.   if (i <= 179) return 179;
  2756.   if (i <= 181) return 181;
  2757.   if (i <= 191) return 191;
  2758.   if (i <= 193) return 193;
  2759.   if (i <= 197) return 197;
  2760.   if (i <= 199) return 199;
  2761.   if (i <= 211) return 211;
  2762. //...
  2763.   if (i <= 307) return 307;
  2764. //...
  2765.   if (i <= 401) return 401;
  2766. //...
  2767.   if (i <= 503) return 503;
  2768. //...
  2769.   if (i <= 601) return 601;
  2770. //...
  2771.   if (i <= 701) return 701;
  2772. //...
  2773.   if (i <= 809) return 809;
  2774. //...
  2775.   if (i <= 907) return 907;
  2776. //...
  2777.   if (i <= 1009) return 1009;
  2778. //...
  2779.   if (i <= 2003) return 2003;
  2780. //...
  2781.   if (i <= 3001) return 3001;
  2782. //...
  2783.   if (i <= 4001) return 4001;
  2784. //...
  2785.   if (i <= 5003) return 5003;
  2786. //...
  2787.   if (i <= 10007) return 10007;
  2788. //...
  2789.   if (i <= 15013) return 15013;
  2790. //...
  2791.   if (i <= 20011) return 20011;
  2792. //...
  2793.   if (i <= 25013) return 25013;
  2794. //...
  2795.   if (i <= 30011) return 30011;
  2796.  
  2797.   programLogicError ("IMPLEMENTATION RESTRICTION: More than 30,000 cases encountered in some switch statement");
  2798.  
  2799. }
  2800.  
  2801.  
  2802.  
  2803. // hashForSwitchStmt (int, hashMax) --> int
  2804. //
  2805. // This routine takes a 32-bit integer and returns a hashed value between
  2806. // 0 and hashMax-1.   It is very important that this hash function performs
  2807. // exactly the same as the compiled code to compute the hash function for a
  2808. // switch statement.  This code is generated in IRSwitchHashJump.
  2809. // Both pieces of code must deal with overflow in the exact same way, to
  2810. // yield the same result.
  2811. //
  2812. int hashForSwitchStmt (int i, int hashMax) {
  2813.   // The following set "quo" and "rem".  It will only fail when
  2814.   // i = a = -2147483648 and hashMax = b = -1.  HashMax should be the
  2815.   // hash table size, which should be positive, so we are okay.  The
  2816.   // "rem" will be a non-negative number, less than the divisor, hashMax.
  2817.   if (hashMax <= 0) {
  2818.     programLogicError ("In hashForSwitchStmt, hashMax is <= 0");
  2819.   }
  2820.   divide (i, hashMax);
  2821.   return rem;
  2822. }
  2823.  
  2824.  
  2825.  
  2826. //
  2827. // genTryStmt (tryStmt)
  2828. //
  2829. void genTryStmt (TryStmt * tryStmt) {
  2830.   char * tryEnd = newLabel ();
  2831.   Catch * cat;
  2832.   VarDecl * saveStack = newTemp (4);
  2833.   Parameter * parm;
  2834.  
  2835.   // Generate code to save the current catch-stack value...
  2836.   IRSaveCatchStack (saveStack);
  2837.  
  2838.   // Run thru the catch clauses.  Assign them labels and generate
  2839.   // code to create and push a new record on the catch-stack...
  2840.   for (cat = tryStmt->catchList; cat; cat=cat->next) {
  2841.     cat->label = newLabel ();
  2842.     IRPushCatchRecord (cat);
  2843.   }
  2844.  
  2845.   // Generate the body code...
  2846.   IRComment ("BODY STMTS...");
  2847.   genStmts (tryStmt->stmts);
  2848.  
  2849.   // Generate code to restore the catch-stack and jump to end...
  2850.   IRRestoreCatchStack (saveStack);
  2851.   IRGoto (tryEnd);
  2852.  
  2853.   // Run through the catch clauses and generate code for each...
  2854.   for (cat = tryStmt->catchList; cat; cat=cat->next) {
  2855.     IRComment2 ("CATCH CLAUSE for ", cat->myDef->newName, "...");
  2856.     IRLabel (cat->label);
  2857.     genLineNumber (cat, "CC");
  2858.     for (parm = cat->parmList; parm; parm = (Parameter *) (parm->next)) {
  2859.       IRCopyCatchParm (parm);
  2860.     }
  2861.     IRResetStack ();
  2862.     IRRestoreCatchStack (saveStack);
  2863.     genStmts (cat->stmts);
  2864.     IRGoto (tryEnd);
  2865.   }
  2866.  
  2867.   // Generate the label at the end...
  2868.   IRComment ("END TRY...");
  2869.   IRLabel (tryEnd);
  2870.  
  2871. }
  2872.  
  2873.  
  2874.  
  2875. //
  2876. // genThrowStmt (throwStmt)
  2877. //
  2878. void genThrowStmt (ThrowStmt * throwStmt) {
  2879.   Argument * arg;
  2880.   ErrorDecl * errorDecl;
  2881.  
  2882.     // Run through the arguments and evaluate each of them...
  2883.     for (arg = throwStmt->argList; arg; arg = arg->next) {
  2884.       arg->tempName = genExpr (arg->expr, arg->sizeInBytes);
  2885.     }
  2886.  
  2887.     // Run through the arguments and move each into its position in the frame...
  2888.     for (arg = throwStmt->argList; arg; arg = arg->next) {
  2889.       IRPrepareArg (arg->offset, arg->tempName, arg->sizeInBytes);
  2890.     }
  2891.  
  2892.     // Perform the throw...
  2893.     errorDecl = throwStmt->myDef;
  2894.     IRComment2 ("  Throw '", errorDecl->id->chars, "'...");
  2895.     // IRDebug ();
  2896.     IRThrow (errorDecl);
  2897.  
  2898. }
  2899.  
  2900.  
  2901.  
  2902. //
  2903. // genFreeStmt (freeStmt)
  2904. //
  2905. void genFreeStmt (FreeStmt * freeStmt) {
  2906.   AstNode * temp;
  2907.   temp = genExpr (freeStmt->expr, 4);
  2908.   IRFree (temp);
  2909. }
  2910.  
  2911.  
  2912.  
  2913. // genExpr (expr, targetSize) --> node
  2914. //
  2915. // This routine generates IR code for an expression.  It returns one of:
  2916. //    Local
  2917. //    Global
  2918. //    Parameter
  2919. //    ClassField
  2920. //    IntConst
  2921. //    RealConst
  2922. //    BoolConst
  2923. //    CharConst
  2924. //
  2925. // In many cases, it will allocate a temp, generate code to move the value
  2926. // into that temp, and return the temp.  This routine is passed "targetSize",
  2927. // which is how big to make the temp.  It calls "genExprInto" to do the work.
  2928. //
  2929. // In other cases (when the expr is a constant or simple variable), it will
  2930. // just return it, as is.
  2931. //
  2932. // In simpler cases (i.e., the expr is a constant value), it simply returns
  2933. // the node itself.
  2934. //
  2935. AstNode * genExpr (Expression * node, int targetSize) {
  2936.     StringConst * stringConst;
  2937.     NullConst * nullConst;
  2938.     CallExpr * callExpr;
  2939.     VariableExpr * var;
  2940.     VarDecl * varDecl;
  2941.     Local * temp;
  2942.     FunctionProto * funProto;
  2943.  
  2944.   if (node==NULL) {
  2945.     programLogicError ("genExpr called with node == NULL");
  2946.   }
  2947.  
  2948.   //   printf ("=== genExpr: ");
  2949.   //   pretty (node);
  2950.  
  2951.   switch (node->op) {
  2952.  
  2953.     case INT_CONST:                                    // in genExpr
  2954.     case DOUBLE_CONST:
  2955.     case CHAR_CONST:
  2956.     case BOOL_CONST:
  2957.  
  2958.       return node;
  2959.  
  2960.     case NULL_CONST:                                   // in genExpr
  2961.  
  2962.       return constantIntZero;
  2963.  
  2964.     case VARIABLE_EXPR:                                // in genExpr
  2965.  
  2966.       var = (VariableExpr *) node;
  2967.       if (var->myDef == NULL) {
  2968.         programLogicError ("var->myDef == NULL in genExpr");
  2969.       }
  2970.       varDecl = (VarDecl *) var->myDef;
  2971.       if ((varDecl->op == LOCAL) ||
  2972.           (varDecl->op == GLOBAL) ||
  2973.           (varDecl->op == CLASS_FIELD) ||
  2974.           (varDecl->op == PARAMETER)) {
  2975.         return varDecl;
  2976.       } else if (varDecl->op == FUNCTION_PROTO) {
  2977.         funProto = (FunctionProto *) varDecl;
  2978.         if (targetSize != 4) {
  2979.           programLogicError ("targetSize is not 4 in case VARIABLE_EXPR in genExpr");
  2980.         }
  2981.         temp = newTemp (4);
  2982.         IRLoadAddr (temp, funProto->newName);
  2983.         return temp;
  2984.       } else {
  2985.         programLogicError ("varDecl->myDef is wrong in genExpr");
  2986.       }
  2987.  
  2988.     case STRING_CONST:                                 // in genExpr
  2989.     case CALL_EXPR:
  2990.     case SEND_EXPR:
  2991.     case SELF_EXPR:
  2992.     case SUPER_EXPR:
  2993.     case FIELD_ACCESS:
  2994.     case ARRAY_ACCESS:
  2995.     case CONSTRUCTOR:
  2996.     case CLOSURE_EXPR:
  2997.     case AS_INTEGER_EXPR:
  2998.     case ARRAY_SIZE_EXPR:
  2999.     case IS_INSTANCE_OF_EXPR:
  3000.     case IS_KIND_OF_EXPR:
  3001.     case SIZE_OF_EXPR:
  3002.  
  3003.       temp = newTemp (targetSize);
  3004.       genExprInto (temp, node, NULL, NULL);
  3005.       return temp;
  3006.  
  3007.     case AS_PTR_TO_EXPR:                                // in genExpr
  3008.       return genExpr (((AsPtrToExpr *) node)->expr, targetSize);
  3009.  
  3010.     case DYNAMIC_CHECK:                                // in genExpr
  3011.  
  3012.       //    printf ("DYNAMIC_CHECK in genExpr, node = ");
  3013.       //    pretty (node);
  3014.       varDecl = genAddressOf (node);  // This will perform the dynamic check...
  3015.       temp = newTemp (targetSize);
  3016.       IRMove (temp,  NULL, NULL, varDecl, targetSize);
  3017.       return temp;
  3018.  
  3019.     default:                                           // in genExpr
  3020.  
  3021.       printf ("\nnode->op = %s\n", symbolName (node->op));
  3022.       programLogicError ("Unknown op in genExpr");
  3023.   }
  3024.  
  3025.   programLogicError ("All cases should have returned in genExpr");
  3026.   return NULL;
  3027.  
  3028. }
  3029.  
  3030.  
  3031.  
  3032. // genExprInto (target, expr, trueLabel, falseLabel)
  3033. //
  3034. // This routine generates IR code to evaluate the expression and to move
  3035. // a value into the target variable.  The "target" will be either:
  3036. //    Local
  3037. //    Global
  3038. //    Parameter
  3039. //    ClassField
  3040. //
  3041. // If the expr is a boolean expression, the target may be null, in which case
  3042. // "trueLabel" and "falseLabel" tell where to jump to and will not be null.
  3043. // Either we will have a target OR trueLabel/falseLabel, BUT never both.
  3044. // (However, if one label is present, both will be present.)  If the expression
  3045. // has type "void", then target and trueLabel/falseLabel will be null.
  3046. //
  3047. // If trueLabel and falseLabel are present, then this routine will generate code
  3048. // to evaluate the expression and jump to the appropriate label.  The boolean value
  3049. // will be used in test-and-branch instructions instead of being saved.  For example,
  3050. //        if (...expr...)
  3051. // will invoke this routine with labels for the then-stmts and the else-stmts, while
  3052. //        b = (...expr...)
  3053. // will invoke this routine with a target (namely, "b").
  3054. //
  3055. void genExprInto (VarDecl * target,
  3056.                   Expression * node,
  3057.                   char * trueLabel,
  3058.                   char * falseLabel) {
  3059.     BoolConst * boolConst;
  3060.     CallExpr * callExpr;
  3061.     SendExpr * sendExpr;
  3062.     SelfExpr * selfExpr;
  3063.     SuperExpr * superExpr;
  3064.     FieldAccess * fieldAccess;
  3065.     ArrayAccess * arrayAccess;
  3066.     Constructor * constructor;
  3067.     ClosureExpr * closureExpr;
  3068.     VariableExpr * var;
  3069.     AsPtrToExpr * asPtrToExpr;
  3070.     AsIntegerExpr * asIntegerExpr;
  3071.     ArraySizeExpr * arraySizeExpr;
  3072.     IsInstanceOfExpr * isInstanceOfExpr;
  3073.     IsKindOfExpr * isKindOfExpr;
  3074.     SizeOfExpr * sizeOfExpr;
  3075.     DynamicCheck * dynamicCheck;
  3076.     FunctionProto * funProto;
  3077.     VarDecl * varDecl, * tempVar, * temp;
  3078.     char * descriptorLabel;
  3079.  
  3080.   if (node==NULL) {
  3081.     programLogicError ("genExprInto called with node==NULL");
  3082.   }
  3083.   if (trueLabel!=NULL && target!=NULL) {
  3084.     programLogicError ("genExprInto called with trueLabel!=NULL && target!=NULL");
  3085.   }
  3086.   if ((trueLabel==NULL) != (falseLabel==NULL)) {
  3087.     programLogicError ("genExprInto called with (trueLabel==NULL) != (falseLabel==NULL)");
  3088.   }
  3089.  
  3090.   //   printf ("=== genExprInto: ");
  3091.   //   pretty (node);
  3092.  
  3093.   switch (node->op) {
  3094.  
  3095.     case INT_CONST:                                      // in genExprInto
  3096.  
  3097.       if (target == NULL) {
  3098.         programLogicError ("target is NULL, in case INT_CONST in genExprInto");
  3099.       }
  3100.       IRAssign4 (target, node);
  3101.       return;
  3102.  
  3103.     case DOUBLE_CONST:                                   // in genExprInto
  3104.  
  3105.       if (target == NULL) {
  3106.         programLogicError ("target is NULL, in case DOUBLE_CONST in genExprInto");
  3107.       }
  3108.       IRAssign8 (target, node);
  3109.       return;
  3110.  
  3111.     case CHAR_CONST:                                     // in genExprInto
  3112.  
  3113.       if (target == NULL) {
  3114.         programLogicError ("target is NULL, in case CHAR_CONST in genExprInto");
  3115.       }
  3116.       IRAssign1 (target, node);
  3117.       return;
  3118.  
  3119.     case STRING_CONST:                                   // in genExprInto
  3120.  
  3121.       if (target == NULL) {
  3122.         programLogicError ("target is NULL, in case STRING_CONST in genExprInto");
  3123.       }
  3124.       IRLoadAddr (target, ((StringConst *) node)->nameOfConstant);
  3125.       return;
  3126.  
  3127.     case BOOL_CONST:                                     // in genExprInto
  3128.  
  3129.       if (trueLabel) {
  3130.         boolConst = (BoolConst *) node;
  3131.         if (boolConst->ivalue == 0) {
  3132.           IRGoto (falseLabel);
  3133.         } else {
  3134.           IRGoto (trueLabel);
  3135.         }
  3136.       } else {
  3137.         IRAssign1 (target, node);
  3138.       }
  3139.       return;
  3140.  
  3141.     case NULL_CONST:                                     // in genExprInto
  3142.  
  3143.       if (target == NULL) {
  3144.         programLogicError ("target is NULL, in case NULL_CONST in genExprInto");
  3145.       }
  3146.       IRAssign4 (target, constantIntZero);
  3147.       return;
  3148.  
  3149.     case CALL_EXPR:                                      // in genExprInto
  3150.  
  3151.       genCallExpr (target, (CallExpr *) node, trueLabel, falseLabel);
  3152.       return;
  3153.  
  3154.     case SEND_EXPR:                                      // in genExprInto
  3155.  
  3156.       genSendExpr (target, (SendExpr *) node, trueLabel, falseLabel);
  3157.       return;
  3158.  
  3159.     case SELF_EXPR:                                      // in genExprInto
  3160.     case SUPER_EXPR:                                     // in genExprInto
  3161.  
  3162.       if (target == NULL) {
  3163.         programLogicError ("target is NULL, in case SELF_EXPR / SUPER_EXPR in genExprInto");
  3164.       }
  3165.       IRLoadSelfPtr (target);
  3166.       return;
  3167.  
  3168.     case FIELD_ACCESS:                                   // in genExprInto
  3169.  
  3170.       //    printf ("Processing FIELD_ACCESS in genExprInto\n");
  3171.       fieldAccess = (FieldAccess *) node;
  3172.       tempVar = genAddressOf (fieldAccess->expr);
  3173.       temp = newTemp (4);
  3174.       IRIncrVarDirect (temp, tempVar, NULL, fieldAccess->offset, 0);
  3175.                                            // wantOverflowTest = 0
  3176.       if (trueLabel) {
  3177.         IRBoolEqZeroIndirect (temp, falseLabel);
  3178.         IRGoto (trueLabel);
  3179.       } else {
  3180.         IRMove (target, NULL, NULL, temp, target->sizeInBytes);
  3181.       }
  3182.       return;
  3183.  
  3184.     case ARRAY_ACCESS:                                   // in genExprInto
  3185.  
  3186.       arrayAccess = (ArrayAccess *) node;
  3187.       //   printf ("case ARRAY_ACCESS in genExprInto: ");
  3188.       //   pretty (arrayAccess);
  3189.       tempVar = genAddressOf (arrayAccess);
  3190.       if (trueLabel) {
  3191.         IRBoolEqZeroIndirect (tempVar, falseLabel);
  3192.         IRGoto (trueLabel);
  3193.       } else {
  3194.         IRMove (target, NULL, NULL, tempVar, target->sizeInBytes);
  3195.       }
  3196.       return;
  3197.  
  3198.     case CONSTRUCTOR:                                    // in genExprInto
  3199.  
  3200.       if (target == NULL) {
  3201.         programLogicError ("target is NULL, in case CONSTRUCTOR in genExprInto");
  3202.       }
  3203.       constructor = (Constructor *) node;
  3204.       tempVar = genConstructor (constructor, target);
  3205.       return;
  3206.  
  3207.     case CLOSURE_EXPR:                                   // in genExprInto
  3208.  
  3209.       if (target == NULL) {
  3210.         programLogicError ("Target is NULL, in case CLOSURE_EXPR in genExprInto");
  3211.       }
  3212.       closureExpr = (ClosureExpr *) node;
  3213.       //   printf ("CLOSURE EXPR in genExprInto: ");
  3214.       //   pretty (closureExpr);
  3215.       IRLoadAddr (target, closureExpr->function->newName);
  3216.       return;
  3217.  
  3218.     case VARIABLE_EXPR:                                  // in genExprInto
  3219.  
  3220.       var = (VariableExpr *) node;
  3221.       if (var->myDef == NULL) {
  3222.         programLogicError ("var->myDef == NULL in genExprInto");
  3223.       }
  3224.       varDecl = (VarDecl *) var->myDef;
  3225.       if ((varDecl->op == LOCAL) ||
  3226.           (varDecl->op == GLOBAL) ||
  3227.           (varDecl->op == CLASS_FIELD) ||
  3228.           (varDecl->op == PARAMETER)) {
  3229.         if (varDecl->sizeInBytes == 1) {
  3230.           if (trueLabel) {
  3231.             IRBoolTest (varDecl, trueLabel, falseLabel);
  3232.           } else {
  3233.             IRAssign1 (target, varDecl);
  3234.           }
  3235.         } else if (varDecl->sizeInBytes == 4) {
  3236.           IRAssign4 (target, varDecl);
  3237.         } else if (varDecl->sizeInBytes == 8) {
  3238.           IRAssign8 (target, varDecl);
  3239.         } else {
  3240.           IRMove (target, NULL, varDecl, NULL, varDecl->sizeInBytes);
  3241.         }
  3242.         return;
  3243.       } else if (varDecl->op == FUNCTION_PROTO) {
  3244.         funProto = (FunctionProto *) varDecl;
  3245.         IRLoadAddr (target, funProto->newName);
  3246.         return;
  3247.       } else {
  3248.         programLogicError ("varDecl->myDef is wrong in genExprInto");
  3249.       }
  3250.  
  3251.     case AS_PTR_TO_EXPR:                                 // in genExprInto
  3252.  
  3253.       asPtrToExpr = (AsPtrToExpr *) node;
  3254.       genExprInto (target, asPtrToExpr->expr, trueLabel, falseLabel);
  3255.       return;
  3256.  
  3257.     case AS_INTEGER_EXPR:                                // in genExprInto
  3258.  
  3259.       asIntegerExpr = (AsIntegerExpr *) node;
  3260.       genExprInto (target, asIntegerExpr->expr, trueLabel, falseLabel);
  3261.       return;
  3262.  
  3263.     case ARRAY_SIZE_EXPR:                                // in genExprInto
  3264.  
  3265.       arraySizeExpr = (ArraySizeExpr *) node;
  3266.       tempVar = genAddressOf (arraySizeExpr->expr);
  3267.       if (trueLabel) {
  3268.         programLogicError ("Unexpected trueLabel in ARRAY_SIZE_EXPR in genExprInto");
  3269.       }
  3270.       if (target->sizeInBytes != 4) {
  3271.         programLogicError ("sizeInBytes is not 4 in ARRAY_SIZE_EXPR in genExprInto");
  3272.       }
  3273.       IRMove (target, NULL, NULL, tempVar, 4);
  3274.       return;
  3275.  
  3276.     case IS_INSTANCE_OF_EXPR:                            // in genExprInto
  3277.  
  3278.       isInstanceOfExpr = (IsInstanceOfExpr *) node;
  3279.       if (isInstanceOfExpr->classDef == NULL) {
  3280.         programLogicError ("classDef is NULL in IS_INSTANCE_OF_EXPR");
  3281.       }
  3282.       tempVar = genAddressOf (isInstanceOfExpr->expr);
  3283.       if (trueLabel) {
  3284.         IRIsInstanceOf (NULL, tempVar, isInstanceOfExpr->classDef->newName, falseLabel);
  3285.         IRGoto (trueLabel);
  3286.       } else {
  3287.         IRIsInstanceOf (target, tempVar, isInstanceOfExpr->classDef->newName, NULL);
  3288.       }
  3289.       return;
  3290.  
  3291.     case IS_KIND_OF_EXPR:                                // in genExprInto
  3292.  
  3293.       isKindOfExpr = (IsKindOfExpr *) node;
  3294.       if (isKindOfExpr->classOrInterface == NULL) {
  3295.         programLogicError ("isKindOfExpr->classOrInterface is NULL in IS_KIND_OF_EXPR");
  3296.       }
  3297.       descriptorLabel = isKindOfExpr->classOrInterface->newName;
  3298.       tempVar = genAddressOf (isKindOfExpr->expr);
  3299.       if (trueLabel) {
  3300.         IRIsKindOf (NULL, tempVar, descriptorLabel, falseLabel);
  3301.         IRGoto (trueLabel);
  3302.       } else {
  3303.         IRIsKindOf (target, tempVar, descriptorLabel, NULL);
  3304.       }
  3305.       return;
  3306.  
  3307.     case SIZE_OF_EXPR:                                   // in genExprInto
  3308.  
  3309.       programLogicError ("SIZE_OF_EXPR should have been eliminated in check, in genExprInto");
  3310.       return;
  3311.  
  3312.     case DYNAMIC_CHECK:                                  // in genExprInto
  3313.  
  3314.       dynamicCheck = (DynamicCheck *) node;
  3315.       //   printf ("=== In genExprInto, node = ");
  3316.       //   pretty (node);
  3317.       if (trueLabel) {
  3318.         programLogicError ("Objects and arrays are never booleans");
  3319.       }
  3320.  
  3321.       // NOTE: In the approach taken here, we call "genAddressOf" to do the work.
  3322.       // In some cases (e.g., "new" constructors), genAddressOf will create the
  3323.       // object, place it in a temporary, and return the address of this temp.
  3324.       // Then, we immediately do a "move", copying the object.  This results
  3325.       // in an extra temporary and move, which may be significant if the item in
  3326.       // question is a large array or large object.  This approach may generate
  3327.       // some unnecessary tests.  For example, we always know the size of a "new"
  3328.       // at compile time, yet we will generate a dynamic test.
  3329.       //
  3330.       // Another approach would be to do something like this:
  3331.       //      genExprInto (target, dynamicCheck->expr);
  3332.       //      gen code to do the check on "target"
  3333.       // However, the problem is that "target" might be too small and the code
  3334.       // to move in the object might overwrite some stuff before the check can
  3335.       // be done.
  3336.  
  3337.       //  Case 8: OBJECT COPY: ... := *objPtr
  3338.       if (dynamicCheck->kind == 8) {
  3339.         varDecl = genAddressOf (node);    // This will perform the dynamic check...
  3340.         //   IRCheckDPT2 (varDecl, dynamicCheck->expectedClassDef);
  3341.         IRMove (target,  NULL, NULL, varDecl, target->sizeInBytes);
  3342.         return;
  3343.  
  3344.       //  Case 9: ARRAY COPY: arr[10] := arr[10]
  3345.       } else if (dynamicCheck->kind == 9) {
  3346.         varDecl = genAddressOf (node);    // This will perform the dynamic check...
  3347.         //   IRCheckArraySizeInt (varDecl, dynamicCheck->expectedArraySize);
  3348.         IRMove (target,  NULL, NULL, varDecl, dynamicCheck->arraySizeInBytes);
  3349.         return;
  3350.  
  3351.       //  Case 10: ARRAY COPY: arr[10] := arr[*]
  3352.       } else if (dynamicCheck->kind == 10) {
  3353.         varDecl = genAddressOf (node);    // This will perform the dynamic check...
  3354.         //   IRCheckArraySizeInt (varDecl, dynamicCheck->expectedArraySize);
  3355.         IRMove (target,  NULL, NULL, varDecl, dynamicCheck->arraySizeInBytes);
  3356.         return;
  3357.  
  3358.       } else {
  3359.         programLogicError ("Unexpected kind in DYNAMIC_CHECK in genExprInto");
  3360.       }
  3361.       return;
  3362.  
  3363.  
  3364.     default:                                             // in genExprInto
  3365.  
  3366.       printf ("\nnode->op = %s\n", symbolName (node->op));
  3367.       programLogicError ("Unknown op in genExprInto");
  3368.  
  3369.   }
  3370.  
  3371.   programLogicError ("All cases should have returned in genExprInto");
  3372.   return;
  3373.  
  3374. }
  3375.  
  3376.  
  3377.  
  3378. // genAddressOf (expr) --> VarDecl
  3379. //
  3380. // This routine generates IR code to compute the address of the data.
  3381. // It returns one of:
  3382. //    Local
  3383. //    Global
  3384. //    Parameter
  3385. //    ClassField
  3386. //
  3387. // In most cases, it will allocate a temp, generate code to move the address
  3388. // into that temp, and return the temp.
  3389. //
  3390. // In some cases (e.g., "*p"), it will return a variable directly (e.g., "p").
  3391. //
  3392. // Note: we will only call this routine on objects or arrays; we should never
  3393. // call it on other sorts of values.  We will also call it for the LValue in
  3394. // a FOR_STMT, which may be any integer-valued expression of the form:
  3395. //       LValue --> Expr [ Expr ]
  3396. //              --> Expr . ID
  3397. //              --> * Expr           Where the expr has type ptr
  3398. //              --> ID               Where id is either a local, global,
  3399. //                                     parameter or classField
  3400. //
  3401. // (It might be nice to pass in a target var, which will eliminate the creation
  3402. // of some unnecessary temps...)
  3403. //
  3404. VarDecl * genAddressOf (Expression * node) {
  3405.     CallExpr * callExpr;
  3406.     VariableExpr * var;
  3407.     VarDecl * varDecl;
  3408.     Local * temp;
  3409.     FunctionProto * funProto;
  3410.     SendExpr * sendExpr;
  3411.     AstNode * x;
  3412.     FieldAccess * fieldAccess;
  3413.     ArrayAccess * arrayAccess;
  3414.     DynamicCheck * dynamicCheck;
  3415.     Constructor * constructor;
  3416.     int i, n;
  3417.     CountValue * countValue;
  3418.     IntConst * intConst;
  3419.  
  3420.   if (node==NULL) {
  3421.     programLogicError ("genAddressOf called with node == NULL");
  3422.   }
  3423.  
  3424.   //   printf ("=== genAddressOf: ");
  3425.   //   pretty (node);
  3426.  
  3427.   switch (node->op) {
  3428.  
  3429.     case INT_CONST:                                 // in genAddressOf
  3430.     case DOUBLE_CONST:
  3431.     case CHAR_CONST:
  3432.     case BOOL_CONST:
  3433.     case NULL_CONST:
  3434.     case STRING_CONST:
  3435.     case IS_INSTANCE_OF_EXPR:
  3436.     case IS_KIND_OF_EXPR:
  3437.     case CLOSURE_EXPR:
  3438.     case AS_PTR_TO_EXPR:
  3439.     case AS_INTEGER_EXPR:
  3440.     case ARRAY_SIZE_EXPR:
  3441.  
  3442.       printf ("\nnode->op = %s\n", symbolName (node->op));
  3443.       printf ("node = ");
  3444.       pretty (node);
  3445.       programLogicError ("In genAddressOf, we should not be asking for the address of this value");
  3446.  
  3447.     case SIZE_OF_EXPR:
  3448.       programLogicError ("SIZE_OF_EXPR should have been eliminated in check, in genAddressOf");
  3449.  
  3450.     case VARIABLE_EXPR:                             // in genAddressOf
  3451.  
  3452.       var = (VariableExpr *) node;
  3453.       if (var->myDef == NULL) {
  3454.         programLogicError ("var->myDef == NULL in genAddressOf");
  3455.       }
  3456.       varDecl = (VarDecl *) var->myDef;
  3457.       if ((varDecl->op == LOCAL) ||
  3458.           (varDecl->op == GLOBAL) ||
  3459.           (varDecl->op == PARAMETER) ||
  3460.           (varDecl->op == CLASS_FIELD)) {
  3461.         temp = newTemp (4);
  3462.         IRLoadAddr2 (temp, varDecl);
  3463.         return temp;
  3464.       } else if (varDecl->op == FUNCTION_PROTO) {
  3465.         funProto = (FunctionProto *) varDecl;
  3466.         programLogicError ("Should have only arrays and objects, in FUNCTION_PROTO in genAddressOf");
  3467.       } else {
  3468.         programLogicError ("varDecl->myDef is wrong in genAddressOf");
  3469.       }
  3470.  
  3471.     case SEND_EXPR:                                 // in genAddressOf
  3472.  
  3473.       sendExpr = (SendExpr *) node;
  3474.       //   printf ("In genAddressOf, processing ");
  3475.       //   pretty (sendExpr);
  3476.  
  3477.       // If this is an expression of the form "*expr"...
  3478.       if (sendExpr->primitiveSymbol == PRIMITIVE_DEREF) {
  3479.         x = genExpr (sendExpr->receiver, 4);  // It should be a ptr, so size==4
  3480.         if (x->op != LOCAL &&
  3481.             x->op != GLOBAL &&
  3482.             x->op != PARAMETER &&
  3483.             x->op != CLASS_FIELD &&
  3484.             x->op != INT_CONST) {
  3485.           programLogicError ("Will not be RealConst, BoolConst, or CharConst");
  3486.         }
  3487.         IRIntEqZero (x, "_runtimeErrorNullPointer");
  3488.         return (VarDecl *) x;
  3489.       }
  3490.  
  3491.       // If this is another primitive
  3492.       if (sendExpr->primitiveSymbol != 0) {
  3493.         programLogicError ("Unexpected primitive in SEND_EXPR in genAddressOf");
  3494.       }
  3495.  
  3496.       // Else, we need to evaluate the expression into a temporary and return the
  3497.       // address of that temporary.  For example, consider
  3498.       //       genAddressOf ("x.foo()")
  3499.       // Assume foo returns an object; we'd need its address when we call bar in
  3500.       //       (x.foo()) . bar()
  3501.       x = genExpr (sendExpr, sendExpr->myProto->retSize);
  3502.       if (x->op == LOCAL) {
  3503.         temp = newTemp (4);
  3504.         IRLoadAddr2 (temp, x);
  3505.         return temp;
  3506.       } else {
  3507.         programLogicError ("GenExpr when applied to non-primitive sendExpr will always return new temp var");
  3508. //    } else if ((x->op == INT_CONST) ||
  3509. //               (x->op == DOUBLE_CONST) ||
  3510. //               (x->op == CHAR_CONST) ||
  3511. //               (x->op == BOOL_CONST)) {
  3512. //      return genAddressOf ((Expression *) x);
  3513. //    } else {
  3514. //      programLogicError ("x is unexpected kind in SEND_EXPR in genAddressOf");
  3515.       }
  3516.  
  3517.     case CALL_EXPR:                                 // in genAddressOf
  3518.       callExpr = (CallExpr *) node;
  3519.       //     printf ("CALL_EXPR in genAddressOf: ");
  3520.       //     pretty (callExpr);
  3521.       //     printf ("  retSize = %d\n", callExpr->retSize);
  3522.       x = genExpr (callExpr, callExpr->retSize);
  3523.       temp = newTemp (4);
  3524.       IRLoadAddr2 (temp, x);
  3525.       return temp;
  3526.  
  3527.     case SELF_EXPR:                                 // in genAddressOf
  3528.     case SUPER_EXPR:                                // in genAddressOf
  3529.       programLogicError ("SELF_EXPR / SUPER_EXPR is a ptr, not an object, so we should never have it in genAddressOf");
  3530.  
  3531.     case FIELD_ACCESS:                              // in genAddressOf
  3532.       fieldAccess = (FieldAccess *) node;
  3533.       varDecl = genAddressOf (fieldAccess->expr);
  3534.       temp = newTemp (4);
  3535.       IRIncrVarDirect (temp, varDecl, NULL, fieldAccess->offset, 0);
  3536.       return temp;
  3537.  
  3538.     case ARRAY_ACCESS:                              // in genAddressOf
  3539.       arrayAccess = (ArrayAccess *) node;
  3540.       varDecl = genAddressOf (arrayAccess->arrayExpr);
  3541.       x = genExpr (arrayAccess->indexExpr, 4);
  3542.       temp = newTemp (4);
  3543.       if (arrayAccess->sizeOfElements <= 0) {
  3544.         // printf ("DEBUGGING....   In genAddressOf>ARRAY_ACCESS: ");
  3545.         // pretty (node);
  3546.         // printAst (5, node);
  3547.         programLogicError ("In genAddressOf>ARRAY_ACCESS, elementSize is zero or less");
  3548.       }
  3549.       IRArrayIndex (varDecl, x, temp, arrayAccess->sizeOfElements);
  3550.       return temp;
  3551.  
  3552.     case CONSTRUCTOR:                               // in genAddressOf
  3553.  
  3554.       constructor = (Constructor *) node;
  3555.       varDecl = genConstructor (constructor, NULL);
  3556.       temp = newTemp (4);
  3557.       IRLoadAddr2 (temp, varDecl);
  3558.       return temp;
  3559.  
  3560.     case DYNAMIC_CHECK:                             // in genAddressOf
  3561.       //   printf ("DYNAMIC_CHECK in genAddressOf, node = ");
  3562.       //   pretty (node);
  3563.       dynamicCheck = (DynamicCheck *) node;
  3564.       varDecl = genAddressOf (dynamicCheck->expr);
  3565.  
  3566.       //  Case 8: OBJECT COPY: ... := *objPtr
  3567.       if (dynamicCheck->kind == 8) {
  3568.         //   printf ("  Dynamic check 8 in genAddressOf\n");
  3569.         IRCheckDPT2 (varDecl, dynamicCheck->expectedClassDef);
  3570.  
  3571.       //  Case 9: ARRAY COPY: arr[10] := arr[10]
  3572.       } else if (dynamicCheck->kind == 9) {
  3573.         //   printf ("  Dynamic check 9 in genAddressOf\n");
  3574.         IRCheckArraySizeInt (varDecl, dynamicCheck->expectedArraySize);
  3575.  
  3576.       //  Case 10: ARRAY COPY: arr[10] := arr[*]
  3577.       } else if (dynamicCheck->kind == 10) {
  3578.         //   printf ("  Dynamic check 10 in genAddressOf\n");
  3579.         IRCheckArraySizeInt (varDecl, dynamicCheck->expectedArraySize);
  3580.  
  3581.       } else {
  3582.         programLogicError ("Unexpected kind in DYNAMIC_CHECK in genExprInto");
  3583.       }
  3584.       return varDecl;
  3585.  
  3586.     default:
  3587.       printf ("\nnode->op = %s\n", symbolName (node->op));
  3588.       programLogicError ("Unknown op in genAddressOf");
  3589.  
  3590.   }
  3591.  
  3592.   programLogicError ("All cases should have returned in genAddressOf");
  3593.   return NULL;
  3594.  
  3595. }
  3596.  
  3597.  
  3598.  
  3599. // genConstructor (expr, target) -> VarDecl
  3600. //
  3601. // This routine is passed a constructor expression and a "target" variable,
  3602. // which will be a LOCAL, GLOBAL, PARM, or CLASS_FIELD or may be null.
  3603. // If "target" is NULL, this routine will allocate a temp of the correct size.
  3604. // This routine will generate the code to setup a new array, record, or object.
  3605. // This routine will return "target". 
  3606. //
  3607. // In the case of a NEW, this routine will move an initialized array, record,
  3608. // or object into "target".
  3609. //
  3610. // In the case of ALLOC, this routine will allocate the memory,
  3611. // initialize the array, record, or object and move a pointer to the new thing
  3612. // into "target".
  3613. //
  3614. VarDecl * genConstructor (Constructor * constructor, VarDecl * target) {
  3615.   int n, elementSize, numberOfElements, size;
  3616.   CountValue * countValue;
  3617.   IntConst * intConst;
  3618.   VarDecl * tempPtr, * counter, * byteCount, * loopCounter;
  3619.   ArrayType * aType;
  3620.   AstNode * value;
  3621.   char * label;
  3622.   FieldInit * f;
  3623.  
  3624.   switch (constructor->allocKind) {
  3625.  
  3626.     case NEW:
  3627.  
  3628.       switch (constructor->kind) {
  3629.  
  3630.         case ARRAY:              // genConstructor: NEW ARRAY
  3631.  
  3632.           IRComment ("  NEW ARRAY Constructor...");
  3633.           //    printf ("======= NEW ARRAY: ");  pretty (constructor);
  3634.           //    printf ("  constructor->sizeInBytes = %d\n", constructor->sizeInBytes);
  3635.           aType = (ArrayType *) constructor->type;
  3636.           if (aType->op != ARRAY_TYPE) {
  3637.             programLogicError ("In genConstructor, expecting array type");
  3638.           }
  3639.           elementSize = aType->sizeOfElements;
  3640.           //    printf ("  elementSize = %d\n", elementSize);
  3641.           intConst = (IntConst *) aType->sizeExpr;
  3642.           if ((intConst == NULL) || (intConst->op != INT_CONST)) {
  3643.             programLogicError ("In genConstructor, arrayType-sizeExpr is not IntConst");
  3644.           }
  3645.           numberOfElements = intConst->ivalue;
  3646.           //    printf ("  numberOfElements = %d\n", numberOfElements);
  3647.  
  3648.           if (target == NULL) {
  3649.             target = newTemp (constructor->sizeInBytes);
  3650.           }
  3651.           tempPtr = newTemp (4);
  3652.           IRLoadAddr2 (tempPtr, target);
  3653.           IRIncrVarDirect (tempPtr, tempPtr, NULL, 4, 0);
  3654.                          // wantOverflowTest = 0
  3655.           counter = newTemp (4);
  3656.  
  3657.           // Run through the count-value pairs and generate code for each...
  3658.           n = 0;
  3659.           for (countValue = constructor->countValueList;
  3660.                countValue;
  3661.                countValue = countValue->next) {
  3662.             IRComment ("  Next value...");
  3663.             value = genExpr (countValue->value, elementSize);
  3664.             if (countValue->count == NULL) {
  3665.               n++;
  3666.               IRMove (NULL, tempPtr, value, NULL, elementSize);
  3667.               IRIncrVarDirect (tempPtr, tempPtr, NULL, elementSize, 0);
  3668.                          // wantOverflowTest = 0
  3669.             } else {
  3670.               intConst = (IntConst *) countValue->count;
  3671.               if (intConst->op == INT_CONST) {
  3672.                 // IRComment ("  Fixed count...");
  3673.                 n += intConst->ivalue;
  3674.                 // Generate this code:
  3675.                 //    counter := ivalue
  3676.                 //    loop:
  3677.                 //       tempPtr = value
  3678.                 //       tempPtr := tempPtr + elementSize
  3679.                 //       counter :- counter - 1
  3680.                 //       if counter > 0 goto loop
  3681.                 label = newLabel ();
  3682.                 IRSet (counter, intConst->ivalue);
  3683.                 IRLabel (label);
  3684.                 IRMove (NULL, tempPtr, value, NULL, elementSize);
  3685.                 IRIncrVarDirect (tempPtr, tempPtr, NULL, elementSize, 0);
  3686.                          // wantOverflowTest = 0
  3687.                 IRIncrVarDirect (counter, counter, NULL, -1, 0);
  3688.                          // wantOverflowTest = 0
  3689.                 IRIntNeZero (counter,label);
  3690. //              } else {
  3691. //                programLogicError ("For NEW ARRAY, we should have only fixed counts (and they should be within 16 bits limitation)");
  3692. //                IRComment ("  Compute count...");
  3693. //                countValue->countTemp = genExpr (countValue->count, 4);
  3694.               }
  3695.             }
  3696.           }
  3697.  
  3698.           //    printf ("  n = %d\n", n);
  3699.           if (n != numberOfElements) {
  3700.             programLogicError ("In genConstructor, n != numberOfElements");
  3701.           }
  3702.           IRComment ("  Initialize the array size...");
  3703.           IRSet (target, numberOfElements);
  3704.           return target;
  3705.  
  3706.         case CLASS:               // genConstructor: NEW CLASS
  3707.         case RECORD:              // genConstructor: NEW RECORD
  3708.  
  3709.           if (constructor->kind == RECORD) {
  3710.             IRComment ("  NEW RECORD Constructor...");
  3711.           } else {
  3712.             IRComment ("  NEW CLASS Constructor...");
  3713.           }
  3714.           size = constructor->sizeInBytes;
  3715.           //      printf ("new CLASS/RECORD = ");
  3716.           //      pretty (constructor);
  3717.           //      printf ("size = %d\n", size);
  3718.           if (target == NULL) {
  3719.             target = newTemp (size);
  3720.           }
  3721.  
  3722.           // If this is an object initialization with missing field inits...
  3723.           if ((constructor->kind == CLASS) &&
  3724.               (size > 4) &&
  3725.               (constructor->fieldInits == NULL)) {
  3726.             IRZeroMemory (target, NULL, size);
  3727.           }
  3728.  
  3729.           // If this is an object, fill in dispatch table pointer...
  3730.           if (constructor->kind == CLASS) {
  3731.             IRLoadAddr (target, constructor->myClass->newName);
  3732.           }
  3733.  
  3734.           // Run thru fieldInits and generate code to initialize each...
  3735.           constructor->fieldInits = sortFieldInits (constructor->fieldInits);
  3736.           tempPtr = newTemp (4);
  3737.           for (f = constructor->fieldInits; f; f = f->next) {
  3738.             value = genExpr (f->expr, f->sizeInBytes);
  3739.             IRLoadAddrWithIncr (tempPtr, target, f);
  3740.             IRMove (NULL, tempPtr, value, NULL, f->sizeInBytes);
  3741.           }
  3742.  
  3743.           return target;
  3744.  
  3745.         default:
  3746.           printf ("\nconstructor->kind = %s\n", symbolName (constructor->kind));
  3747.           programLogicError ("Unexpected kind in genConstructor");
  3748.       }
  3749.  
  3750.     case ALLOC:
  3751.  
  3752.       switch (constructor->kind) {
  3753.  
  3754.         case ARRAY:              // genConstructor: ALLOC ARRAY
  3755.  
  3756.           IRComment ("  ALLOC ARRAY Constructor...");
  3757.           //     printf ("======= ALLOC ARRAY: ");  pretty (constructor);
  3758.           //     printf ("  constructor->sizeInBytes = %d\n", constructor->sizeInBytes);
  3759.           aType = (ArrayType *) constructor->type;
  3760.           if (aType->op != ARRAY_TYPE) {
  3761.             programLogicError ("In genConstructor, expecting array type");
  3762.           }
  3763.           elementSize = aType->sizeOfElements;
  3764.           //     printf ("  elementSize = %d\n", elementSize);
  3765.           counter = newTemp (4);
  3766.           IRSet (counter, 0);
  3767.  
  3768.           // Run through the count-value pairs and generate code for each...
  3769.           IRComment ("  Evaluate any count and value expressions...");
  3770.           n = 0;
  3771.           for (countValue = constructor->countValueList;
  3772.                countValue;
  3773.                countValue = countValue->next) {
  3774.             if (countValue->count == NULL) {
  3775.               // IRComment ("  Missing count, 1 assumed...");
  3776.               n++;
  3777.             } else {
  3778.               intConst = (IntConst *) countValue->count;
  3779.               if ((intConst->op == INT_CONST) &&
  3780.                   within16Bits (intConst->ivalue) &&
  3781.                   within16Bits (n + (intConst->ivalue))) {
  3782.                 // IRComment ("  Fixed count...");
  3783.                 n += intConst->ivalue;
  3784.                 countValue->countTemp = countValue->count;
  3785.               } else {
  3786.                 // IRComment ("  Evaluate this count expr and add to running sum...");
  3787.                 countValue->countTemp = genExpr (countValue->count, 4);
  3788.                 IRIAdd (counter, counter, countValue->countTemp);
  3789.               }
  3790.             }
  3791.             // IRComment ("  Evaluate next value expression...");
  3792.             countValue->valueTemp = genExpr (countValue->value, elementSize);
  3793.           }
  3794.           if (n != 0) {
  3795.             IRIncrVarDirect (counter, counter, NULL, n, 0);
  3796.                          // wantOverflowTest = 0
  3797.           }
  3798.           byteCount = newTemp (4);
  3799.           if (target == NULL) {
  3800.             target = newTemp (4);
  3801.           }
  3802.           IRComment ("  Compute size in bytes and call alloc...");
  3803.           IRMultiplyVarImmed (byteCount, counter, elementSize);
  3804.           IRIncrVarDirect (byteCount, byteCount, NULL, 4, 1);  // wantOverflowTest = 1
  3805.           IRAlloc (target, byteCount);
  3806.           tempPtr = newTemp (4);
  3807.           IRMove (tempPtr, NULL, target, NULL, 4);
  3808.           IRMove (NULL, tempPtr, counter, NULL, 4);
  3809.           IRIncrVarDirect (tempPtr, tempPtr, NULL, 4, 0);  // wantOverflowTest = 0
  3810.           loopCounter = newTemp (4);
  3811.  
  3812.           // Run through the count-value pairs and generate code to initialize array...
  3813.           for (countValue = constructor->countValueList;
  3814.                countValue;
  3815.                countValue = countValue->next) {
  3816.             if (countValue->count == NULL) {
  3817.               IRComment ("  Initialize 1 element...");
  3818.               IRMove (NULL, tempPtr, countValue->valueTemp, NULL, elementSize);
  3819.               IRIncrVarDirect (tempPtr, tempPtr, NULL, elementSize, 0);
  3820.                                                    // wantOverflowTest = 0
  3821.             } else {
  3822.               intConst = (IntConst *) countValue->count;
  3823.               IRComment ("  Initialize many entries in a loop...");
  3824.               // Generate the following code:
  3825.               //      loopCounter = count
  3826.               //      if loopCounter <= 0 goto runtimeError
  3827.               //      loop:
  3828.               //        *tempPtr = value
  3829.               //        tempPtr = tempPtr + elementSize
  3830.               //        loopCounter = loopCounter - 1
  3831.               //        if loopCount != 0 goto loop
  3832.               IRMove (loopCounter, NULL, countValue->countTemp, NULL, 4);
  3833.               IRIntLeZero (loopCounter, "_runtimeErrorArrayCountNotPositive");
  3834.               label = newLabel ();
  3835.               IRLabel (label);
  3836.               IRMove (NULL, tempPtr, countValue->valueTemp, NULL, elementSize);
  3837.               IRIncrVarDirect (tempPtr, tempPtr, NULL, elementSize, 0);
  3838.                                                    // wantOverflowTest = 0
  3839.               IRIncrVarDirect (loopCounter, loopCounter, NULL, -1, 0);
  3840.                                                    // wantOverflowTest = 0
  3841.               IRIntNeZero (loopCounter, label);
  3842.             }
  3843.           }
  3844.           return target;
  3845.  
  3846.         case CLASS:              // genConstructor: ALLOC CLASS
  3847.         case RECORD:             // genConstructor: ALLOC RECORD
  3848.  
  3849.           if (constructor->kind == RECORD) {
  3850.             IRComment ("  ALLOC RECORD Constructor...");
  3851.           } else {
  3852.             IRComment ("  ALLOC CLASS Constructor...");
  3853.           }
  3854.           size = constructor->sizeInBytes;
  3855.           //    printf ("alloc CLASS/RECORD = ");
  3856.           //    pretty (constructor);
  3857.           //    printf ("size = %d\n", size);
  3858.  
  3859.           IRComment ("  Call alloc...");
  3860.           byteCount = newTemp (4);
  3861.           IRSet (byteCount, size);
  3862.           if (target == NULL) {
  3863.             target = newTemp (4);
  3864.           }
  3865.           IRAlloc (target, byteCount);
  3866.  
  3867.           // If this is an object initialization with missing field inits...
  3868.           if ((constructor->kind == CLASS) &&
  3869.               (size > 4) &&
  3870.               (constructor->fieldInits == NULL)) {
  3871.             IRZeroMemory (NULL, target, size);
  3872.           }
  3873.  
  3874.           // If it is a class, then save ptr to dispatch table...
  3875.           if (constructor->kind == CLASS) {
  3876.             IRLoadAddrIndirect (target, constructor->myClass->newName);
  3877.           }
  3878.  
  3879.           // Run through the fields and initialize them...
  3880.           constructor->fieldInits = sortFieldInits (constructor->fieldInits);
  3881.           tempPtr = newTemp (4);
  3882.           for (f = constructor->fieldInits; f; f = f->next) {
  3883.             value = genExpr (f->expr, f->sizeInBytes);
  3884.             IRLoadAddrWithIncr2 (tempPtr, target, f);
  3885.             IRMove (NULL, tempPtr, value, NULL, f->sizeInBytes);
  3886.           }
  3887.           return target;
  3888.  
  3889.  
  3890.         default:
  3891.           printf ("\nconstructor->kind = %s\n", symbolName (constructor->kind));
  3892.           programLogicError ("Unexpected kind in genConstructor");
  3893.       }
  3894.  
  3895.     default:
  3896.       printf ("\nconstructor->allocKind = %s\n", symbolName (constructor->allocKind));
  3897.       programLogicError ("Unexpected allocKind in genConstructor");
  3898.   }
  3899. }
  3900.  
  3901.  
  3902.  
  3903. // newLabel ()
  3904. //
  3905. // This function returns a newly created string of the form "_Label_43".
  3906. //
  3907. char * newLabel () {
  3908.   return newName ("Label");
  3909. }
  3910.  
  3911.  
  3912.  
  3913. // newName (char*) --> char*
  3914. //
  3915. // This function returns a newly created string of the form "_xxxx_43".  The
  3916. // integer part is incremented on each call, making the returned string unique
  3917. // from all previous strings returned by this function.  The "xxxx" part is
  3918. // from the "str" argument.
  3919. //
  3920. char * newName (char * str) {
  3921.   static int next = 1;
  3922.   char * p = (char *) calloc (1, strlen (str) + 12);
  3923.   if (p==0) {
  3924.     programLogicError ("Calloc failed in newName; out of memory perhaps???");
  3925.   }
  3926.   sprintf (p, "_%s_%d", str, next++);
  3927.   return p;
  3928. }
  3929.  
  3930.  
  3931.  
  3932. // sanitizedPackageName (packageName) --> newPackName
  3933. //
  3934. // This routine takes a String such as
  3935. //    MyPack
  3936. // and returns something like
  3937. //    _P_MyPack_
  3938. //
  3939. // If the package name contains underscore characters, then each is
  3940. // replaced with __.  For example, the package name:
  3941. //    MyPack_10_5
  3942. // is translated into:
  3943. //    _P_MyPack__10__5_
  3944. //
  3945. // We use two underscores instead of one to make sure no name-collisions
  3946. // occur.  This is necessary since we will concatenate package names
  3947. // with other names, such as variable names.
  3948. //
  3949. // As an example, consider two different package names and two variables;
  3950. // without doubling, the sanitized version of the variable names might
  3951. // end up being identical:
  3952. //
  3953. //    Package   Variable   Name, no doubling   Name, with doubling
  3954. //    =======   ========   =================   ===================
  3955. //    xx        yy_zz      _P_xx_yy_zz         _P_xx_yy_zz
  3956. //    xx_yy     zz         _P_xx_yy_zz         _P_xx__yy_zz
  3957. //
  3958. char * sanitizedPackageName (String * packageName) {
  3959.   char * result = (char *) calloc (1, 2 * packageName->length + 5);
  3960.   char * p = result;
  3961.   char * from = packageName->chars;
  3962.   int i;
  3963.   *(p++) = '_';
  3964.   *(p++) = 'P';
  3965.   *(p++) = '_';
  3966.   for (i = packageName->length; i>0; i--) {
  3967.     if (isalpha (*from) || isdigit (*from)) {
  3968.       *(p++) = *(from);
  3969.     } else {
  3970.       *(p++) = '_';
  3971.       *(p++) = '_';
  3972.     }
  3973.     from++;
  3974.   }
  3975.   *(p++) = '_';
  3976.   *(p++) = '\0';
  3977.   return result;
  3978. }
  3979.  
  3980.  
  3981.  
  3982. // newMethodName (sanitizedClassName, i) --> char*
  3983. //
  3984. // This routine is passed a sanitizedClassName such as "_P_MyPackageName_MyClass",
  3985. // and an integer.  It returns a newly created string, such as
  3986. //        _Method_P_MyPackageName_MyClass_43
  3987. // This is composed of 3 parts:
  3988. //        _Method   _P_MyPackageName_MyClass_    43
  3989. //
  3990. // The integer part is normally incremented for each method in the class.
  3991. // Thus, the methods in "MyClass" in "MyPackageName" will be given the names:
  3992. //        _Method_P_MyPackageName_MyClass_1
  3993. //        _Method_P_MyPackageName_MyClass_2
  3994. //        _Method_P_MyPackageName_MyClass_3
  3995. //        ...
  3996. //
  3997. char * newMethodName (char * sanitizedClassName, int i) {
  3998.   char * p = (char *) calloc (1, strlen (sanitizedClassName) + 20);
  3999.   if (p==0) {
  4000.     programLogicError ("Calloc failed in newName; out of memory perhaps???");
  4001.   }
  4002.   sprintf (p, "_Method%s_%d", sanitizedClassName, i);
  4003.   return p;
  4004. }
  4005.  
  4006.  
  4007.  
  4008. //
  4009. // genLineNumber (node, stmtCode)
  4010. //
  4011. // This routine generates a "setLineNumber" instruction.  It is passed an
  4012. // AstNode, from which it extracts the current source code line number.
  4013. // It is also passed a 2 character code indicating what sort of a statement
  4014. // this is.  Later, we'll generate an instruction to move this code into r10.
  4015. //
  4016. void genLineNumber (AstNode * node, char * stmtCode) {
  4017.   if (node == NULL) {
  4018.     programLogicError ("node is NULL in genLineNumber");
  4019.   }
  4020.   IRSetLineNumber (extractLineNumber (node->tokn), stmtCode);
  4021. }
  4022.  
  4023.  
  4024.  
  4025. // newTemp (sizeInBytes) --> Local
  4026. //
  4027. // This routine creates a new temp variable and returns a pointer to it.  It is
  4028. // passed the size of the temp in bytes.  It assumes that the global variable
  4029. // "currentFunOrMeth" points to a function or method.  A new LOCAL is added to
  4030. // this function or method.
  4031. //
  4032. Local * newTemp (int sizeInBytes) {
  4033.   Local * local;
  4034.   Function * fun;
  4035.   Method * meth;
  4036.  
  4037.   if (sizeInBytes < 0) {
  4038.     programLogicError ("sizeInBytes < 0 within newTemp");
  4039.   }
  4040.  
  4041.   if (currentFunOrMeth == NULL) {
  4042.     programLogicError ("currentFunOrMeth is NULL within newTemp");
  4043.   }
  4044.   local = new Local ();
  4045.   local->positionAt (currentFunOrMeth);
  4046.   local->id = lookupAndAdd (newName("temp"), ID);
  4047.   // local->type==NULL signals a temp.
  4048.   // local->offset was initialized to -1
  4049.   local->sizeInBytes = sizeInBytes;
  4050.   // local->varDescLabel was initialized to NULL
  4051.   // local->initExpr was initialized to NULL
  4052.   // local->wasUsed was only needed during checking
  4053.  
  4054.   // Add this Local to the front of the "locals" list.
  4055.   if (currentFunOrMeth->op == FUNCTION) {
  4056.     fun = (Function *) currentFunOrMeth;
  4057.     local->next = fun->locals;
  4058.     fun->locals = local;
  4059.   } else {
  4060.     meth = (Method *) currentFunOrMeth;
  4061.     local->next = meth->locals;
  4062.     meth->locals = local;
  4063.   }
  4064.   return local;  
  4065. }
  4066.