home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / genstmt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  11.3 KB  |  359 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This file contains routines for 68k code generation.  These routines handle
  35.  * statements.
  36.  * 
  37.  * 
  38.  * 
  39.  */
  40.  
  41.  
  42. #include "conditcomp.h"
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include "structs.h"
  46.  
  47. #include "CHarvestDoc.h"
  48. #include "CHarvestOptions.h"
  49.  
  50. extern CHarvestDoc *gProject;
  51. extern SYMVia_t CurrentFunctionPascal;
  52. extern long CurrentPascalArgs;
  53.  
  54. #pragma segment GenStmt
  55.  
  56.  
  57. void
  58. GenCompound(ParseTreeVia_t stmt, InstListVia_t Codes)
  59. {
  60.     /* Allocate the locals for this block. */
  61.     Allocate2Locals((Via(GetTreeScopes(stmt))->Symbols), Codes);
  62.     if (stmt) {
  63.     GenExpression(Via(stmt)->a, Codes);
  64.     }
  65.     Free2Locals(Via(GetTreeScopes(stmt))->Symbols, Codes);
  66. }
  67.  
  68. void
  69. GenReturn(ParseTreeVia_t val, InstListVia_t Codes)
  70. {
  71.     LocAMVia_t                      temp;
  72.     LocAMVia_t                      bigresult;
  73.     SpillSlotVia_t                  slot;
  74.     temp = GenExpression(val, Codes);
  75.     if (temp) {
  76.     if (isStructUnionType(GetTreeTP(val))) {
  77.         LocAMVia_t                      tloc;
  78.         tloc = TempAddrReg(Codes);
  79.         Genmove(M68sz_long, StructDoubleReturnLoc, tloc, Codes);
  80.         bigresult = BuildARegIndirect(GetLocAReg(tloc));
  81.         Genmove(M68_TypeSize(GetTreeTP(val)), temp, bigresult, Codes);
  82.         FreeTemp(tloc);
  83.     } else if (isFloatingType(GetTreeTP(val))) {
  84.         /* Move the value into d0-d1-a0 */
  85.         if (gProject->itsOptions->useMC68881) {
  86.         LocAMVia_t                      half2;
  87.         slot = GetSpillSlot(SizeOfLongDouble);
  88.         Genmove(M68_TypeSize(GetTreeTP(val)), temp, Via(slot)->SlotLoc, Codes);
  89.         Genmove(M68sz_word, Via(slot)->SlotLoc, BuildDRegLocation(0),
  90.             Codes);
  91.         half2 = BuildARegDisplace(GetLocAReg(Via(slot)->SlotLoc),
  92.                     GetLocConstant(Via(slot)->SlotLoc) + 2);
  93.         Genmove(M68sz_long, half2, BuildDRegLocation(1), Codes);
  94.         half2 = BuildARegDisplace(GetLocAReg(Via(slot)->SlotLoc),
  95.                     GetLocConstant(Via(slot)->SlotLoc) + 6);
  96.         Genmove(M68sz_long, half2, BuildARegDirect(0), Codes);
  97.         FreeTemp(Via(slot)->SlotLoc);
  98.         } else {
  99.         LocAMVia_t                      half2;
  100.         LocAMVia_t                      val2;
  101.         if (GetLocAM(temp) == M68am_FSANEtemp) {
  102.             val2 = Via(slot)->SlotLoc;
  103.         } else
  104.             val2 = temp;
  105.         Genmove(M68sz_word, val2, BuildDRegLocation(0), Codes);
  106.         half2 = BuildARegDisplace(GetLocAReg(val2),
  107.                       GetLocConstant(val2) + 2);
  108.         Genmove(M68sz_long, half2, BuildDRegLocation(1), Codes);
  109.         half2 = BuildARegDisplace(GetLocAReg(val2),
  110.                       GetLocConstant(val2) + 6);
  111.         Genmove(M68sz_long, half2, BuildARegDirect(0), Codes);
  112.         FreeTemp(val2);
  113.         }
  114.     } else {
  115.         Genmove(M68_TypeSize(GetTreeTP(val)),
  116.             temp, BuildDRegLocation(0), Codes);
  117.         /* If the function is pascal, then we move.sz d0,X(a6) */
  118.         if (CurrentFunctionPascal) {
  119.             Genmove(M68_TypeSize(GetTreeTP(val)),BuildDRegLocation(0),
  120.                 BuildARegDisplace(6,CurrentPascalArgs+8),Codes);
  121.         }
  122.     }
  123.     }
  124.     GenInst(M68op_BRA, M68sz_none,
  125.         BuildLabelLoc(FunctionLastLabel), NULL, Codes);
  126. }
  127.  
  128. void
  129. GenIfThenElse(ParseTreeVia_t expr,
  130.           ParseTreeVia_t thenstmt,
  131.           ParseTreeVia_t elsestmt,
  132.           InstListVia_t Codes)
  133. {
  134.     LabSYMVia_t                     ElseLabel = NULL;
  135.     LabSYMVia_t                     EndLabel;
  136.     FreeAllRegs();
  137.     EndLabel = MakeEccLabel(NextEccLabel++);
  138.     if (elsestmt) {
  139.     ElseLabel = MakeEccLabel(NextEccLabel++);
  140.     GenCompareZero(expr, ElseLabel, Codes);
  141.     } else {
  142.     GenCompareZero(expr, EndLabel, Codes);
  143.     }
  144.     GenExpression(thenstmt, Codes);
  145.     if (elsestmt) {
  146.     GenInst(M68op_BRA, M68sz_none,
  147.         BuildLabelLoc(EndLabel), NULL, Codes);
  148.     GenLabel(ElseLabel, Codes);
  149.     GenExpression(elsestmt, Codes);
  150.     }
  151.     GenLabel(EndLabel, Codes);
  152. }
  153.  
  154. void
  155. GenDoWhile(ParseTreeVia_t stmt,
  156.        ParseTreeVia_t expr,
  157.        InstListVia_t Codes)
  158. {
  159.     LabSYMVia_t                     OldBreak;
  160.     LabSYMVia_t                     OldContinue;
  161.     LocAMVia_t                      exprloc;
  162.     FreeAllRegs();
  163.     OldBreak = BreakLabel;
  164.     OldContinue = ContinueLabel;
  165.     ContinueLabel = MakeEccLabel(NextEccLabel++);
  166.     BreakLabel = MakeEccLabel(NextEccLabel++);
  167.     GenLabel(ContinueLabel, Codes);
  168.     exprloc = GenExpression(stmt, Codes);
  169.     GenCompareNonZero(expr, ContinueLabel, Codes);
  170.     GenLabel(BreakLabel, Codes);
  171.     BreakLabel = OldBreak;
  172.     ContinueLabel = OldContinue;
  173. }
  174.  
  175. void
  176. Genforstmt(ParseTreeVia_t first,
  177.        ParseTreeVia_t cond,
  178.        ParseTreeVia_t each,
  179.        ParseTreeVia_t stmt,
  180.        InstListVia_t Codes)
  181. {
  182.     LabSYMVia_t                     OldBreak;
  183.     LabSYMVia_t                     OldContinue;
  184.     FreeAllRegs();
  185.     /* Save break and continue for nested loops */
  186.     OldBreak = BreakLabel;
  187.     OldContinue = ContinueLabel;
  188.     ContinueLabel = MakeEccLabel(NextEccLabel++);
  189.     BreakLabel = MakeEccLabel(NextEccLabel++);
  190.     GenExpression(first, Codes);
  191.     GenLabel(ContinueLabel, Codes);
  192.     if (cond)
  193.         GenCompareZero(cond, BreakLabel, Codes);
  194.     GenExpression(stmt, Codes);
  195.     GenExpression(each, Codes);
  196.     GenInst(M68op_BRA, M68sz_none,
  197.         BuildLabelLoc(ContinueLabel), NULL, Codes);
  198.     GenLabel(BreakLabel, Codes);
  199.     BreakLabel = OldBreak;
  200.     ContinueLabel = OldContinue;
  201. }
  202.  
  203. void
  204. GenWhile(ParseTreeVia_t expr,
  205.      ParseTreeVia_t stmt,
  206.      InstListVia_t Codes)
  207. {
  208.     /*
  209.      * Here, we generate a starting label.  Then, we generate code to
  210.      * evaluate the conditional expression.  Then, we generate a comparioson
  211.      * and a conditional branch.  If the expression is true, we do not
  212.      * branch.  Execution drops down. If it is false, we branch to the ending
  213.      * label.  These labels must be local variables, because loops may be
  214.      * nested.  We then generate code to evaluate the statement.  Then, a BRA
  215.      * to the starting label. The ending label goes on the instruction just
  216.      * after the bra.
  217.      */
  218.     LabSYMVia_t                     OldBreak;
  219.     LabSYMVia_t                     OldContinue;
  220.     FreeAllRegs();
  221.     OldBreak = BreakLabel;
  222.     OldContinue = ContinueLabel;
  223.     ContinueLabel = MakeEccLabel(NextEccLabel++);
  224.     BreakLabel = MakeEccLabel(NextEccLabel++);
  225.     GenLabel(ContinueLabel, Codes);
  226.     GenCompareZero(expr, BreakLabel, Codes);
  227.     GenExpression(stmt, Codes);
  228.     GenInst(M68op_BRA, M68sz_none,
  229.         BuildLabelLoc(ContinueLabel), NULL, Codes);
  230.     GenLabel(BreakLabel, Codes);
  231.     BreakLabel = OldBreak;
  232.     ContinueLabel = OldContinue;
  233. }
  234.  
  235. void
  236. GenLabelledStmt(ParseTreeVia_t expr, InstListVia_t Codes)
  237. {
  238.     LabSYMVia_t                     lab;
  239.     char                            nm[64];
  240.     GetAbsString(ParserStrings, Via(expr)->data.identifier, nm);
  241.     lab = AddLabel(nm);
  242.     GenLabel(lab, Codes);
  243.     GenExpression(Via(expr)->a, Codes);
  244. }
  245.  
  246. void
  247. GenGotoStmt(ParseTreeVia_t stmt, InstListVia_t Codes)
  248. {
  249.     LabSYMVia_t                     lab;
  250.     char                            nm[64];
  251.     GetAbsString(ParserStrings, Via(stmt)->data.identifier, nm);
  252.     lab = AddLabel(nm);
  253.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(lab), NULL, Codes);
  254. }
  255.  
  256. LabSYMVia_t                     LabTableGetNum(LabSymListVia_t, int);
  257.  
  258. void
  259. GenSWITCH(ParseTreeVia_t expr, ParseTreeVia_t stmt,
  260.       InstListVia_t Codes)
  261. {
  262.     /*
  263.      * Here we will generate a large set of if-elses. First we go through the
  264.      * stmt, counting labels.  This stmt has a set of case label: stmt;
  265.      * lines.  We must generate a test for every case in the group, but we
  266.      * only need to generate an assembler label for each actual statement.
  267.      * So, first, we generate a bra to the tests, a label to be defined
  268.      * later.  Then, we go through and generate code for each statement in
  269.      * stmt, with labels for every case.  The break label is set to the end
  270.      * of the switch.  After generating the cases, we generate the test and
  271.      * branch section, jumping to the labels already defined.
  272.      */
  273.  
  274.     LabSYMVia_t                     TestsLabel;
  275.     LabSYMVia_t                     OldBreak;
  276.     LabSymListVia_t                 OldCases;
  277.     LabSYMVia_t                     cur;
  278.     int                             ndx;
  279.     LocAMVia_t                      control;
  280.     OldCases = SwitchCases;
  281.     SwitchCases = RawLabTable();
  282.     OldBreak = BreakLabel;
  283.     BreakLabel = MakeEccLabel(NextEccLabel++);
  284.     TestsLabel = MakeEccLabel(NextEccLabel++);
  285.  
  286.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(TestsLabel), NULL, Codes);
  287.     GenExpression(stmt, Codes);
  288.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(BreakLabel), NULL, Codes);
  289.     /* Now we generate the tests. */
  290.     GenLabel(TestsLabel, Codes);
  291.  
  292.     control = GenExpression(expr, Codes);
  293.     if (isFloatingType(GetTreeTP(expr))) {
  294.     control = DictateTempFloat(control, Codes);
  295.     }
  296.     else {
  297.     control = DictateAnyDReg(control, Codes);
  298.     }
  299.  
  300.     ndx = Via(SwitchCases)->count;
  301.     ndx = 1;
  302.     while (ndx <= Via(SwitchCases)->count) {
  303.     cur = LabTableGetNum(SwitchCases, ndx);
  304.     ndx++;
  305.     if (Via(cur)->Definition.CaseConstant) {
  306.         GenCompareBranch2(control, Via(cur)->Definition.CaseConstant, M68op_BEQ,
  307.                   cur, Codes);
  308.     } else {
  309.         GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(cur), NULL, Codes);
  310.     }
  311.     }
  312.     FreeTemp(control);
  313.     GenLabel(BreakLabel, Codes);
  314.     BreakLabel = OldBreak;
  315.     RememberSwitch(SwitchCases);
  316.     SwitchCases = OldCases;
  317. }
  318.  
  319. void
  320. GenSwitchDefault(ParseTreeVia_t stmt, InstListVia_t Codes)
  321. {
  322.     /*
  323.      * Generate a label.  Then generate the statement.  Save the symbol
  324.      * record for the label, and store the constant expression from the case
  325.      * statement in that symbol record.  Add that symbol record to the table
  326.      * SwitchCases.
  327.      */
  328.     LabSYMVia_t                     caselabel;
  329.     caselabel = MakeEccLabel(NextEccLabel++);
  330. #ifdef OLDMEM
  331.     HLock((Handle) caselabel);
  332. #endif
  333.     caselabel = LabTableTailAdd(SwitchCases, Via(caselabel)->name);
  334. #ifdef OLDMEM
  335.     HUnlock((Handle) caselabel);
  336. #endif
  337.     Via(caselabel)->Definition.CaseConstant = NULL;
  338.     GenLabel(caselabel, Codes);
  339.     GenExpression(Via(stmt)->a, Codes);
  340. }
  341.  
  342. void
  343. GenSwitchCase(ParseTreeVia_t stmt, InstListVia_t Codes)
  344. {
  345.     /*
  346.      * Generate a label.  Then generate the statement.  Save the symbol
  347.      * record for the label, and store the constant expression from the case
  348.      * statement in that symbol record.  Add that symbol record to the table
  349.      * SwitchCases.
  350.      */
  351.     LabSYMVia_t                     caselabel;
  352.     caselabel = MakeEccLabel(NextEccLabel++);
  353.     caselabel = LabTableTailAdd(SwitchCases, Via(caselabel)->name);
  354.     Via(caselabel)->Definition.CaseConstant = Via(stmt)->a;
  355.     GenLabel(caselabel, Codes);
  356.     GenExpression(Via(stmt)->b, Codes);
  357. }
  358.  
  359.