Generated code for FOR-loops was wrong
This commit is contained in:
parent
e5af61151e
commit
abf9c71fa9
5 changed files with 73 additions and 27 deletions
|
@ -123,7 +123,7 @@ GetString(upto)
|
|||
}
|
||||
*p++ = ch;
|
||||
if (p - str->s_str == len) {
|
||||
str->s_str = Srealloc(str->s_str,
|
||||
str->s_str = Realloc(str->s_str,
|
||||
(unsigned int) len + RSTRSIZE);
|
||||
p = str->s_str + len;
|
||||
len += RSTRSIZE;
|
||||
|
|
|
@ -1001,6 +1001,7 @@ CodeDAddress(nd)
|
|||
|
||||
register struct desig *designator = new_desig();
|
||||
|
||||
ChkForFOR(nd);
|
||||
CodeDesig(nd, designator);
|
||||
CodeAddress(designator);
|
||||
free_desig(designator);
|
||||
|
@ -1015,6 +1016,7 @@ CodeDStore(nd)
|
|||
|
||||
register struct desig *designator = new_desig();
|
||||
|
||||
ChkForFOR(nd);
|
||||
CodeDesig(nd, designator);
|
||||
CodeStore(designator, nd->nd_type);
|
||||
free_desig(designator);
|
||||
|
|
|
@ -113,6 +113,7 @@ struct def { /* list of definitions for a name */
|
|||
#define D_BUSY 0x80 /* set if busy reading this definition module */
|
||||
#define D_FOREIGN 0x100 /* set for foreign language modules */
|
||||
#define D_ADDRGIVEN 0x200 /* set if address given for variable */
|
||||
#define D_FORLOOP 0x400 /* set if busy in for-loop */
|
||||
struct type *df_type;
|
||||
union {
|
||||
struct module df_module;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "scope.h"
|
||||
#include "desig.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
|
||||
extern int proclevel;
|
||||
|
||||
|
@ -165,6 +166,21 @@ CodeValue(ds, tp)
|
|||
ds->dsg_kind = DSG_LOADED;
|
||||
}
|
||||
|
||||
ChkForFOR(nd)
|
||||
struct node *nd;
|
||||
{
|
||||
if (nd->nd_class == Def) {
|
||||
register struct def *df = nd->nd_def;
|
||||
|
||||
if (df->df_flags & D_FORLOOP) {
|
||||
node_warning(nd,
|
||||
W_ORDINARY,
|
||||
"assignment to FOR-loop control variable");
|
||||
df->df_flags &= ~D_FORLOOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodeStore(ds, tp)
|
||||
register struct desig *ds;
|
||||
register struct type *tp;
|
||||
|
@ -175,6 +191,7 @@ CodeStore(ds, tp)
|
|||
struct desig save;
|
||||
|
||||
save = *ds;
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_FIXED:
|
||||
if (DoStore(ds, tp->tp_size)) break;
|
||||
|
@ -233,6 +250,7 @@ CodeMove(rhs, left, rtp)
|
|||
generated.
|
||||
*/
|
||||
|
||||
ChkForFOR(left);
|
||||
switch(rhs->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
CodeDesig(left, lhs);
|
||||
|
|
|
@ -482,42 +482,66 @@ WalkStat(nd, exit_label)
|
|||
label l1 = ++text_label;
|
||||
label l2 = ++text_label;
|
||||
int uns = 0;
|
||||
arith stepsize;
|
||||
|
||||
good_forvar = DoForInit(nd, left);
|
||||
good_forvar = DoForInit(nd);
|
||||
if ((stepsize = left->nd_INT) == 0) {
|
||||
node_warning(left,
|
||||
W_ORDINARY,
|
||||
"zero stepsize in FOR loop");
|
||||
}
|
||||
if (stepsize < 0) {
|
||||
stepsize = -stepsize;
|
||||
}
|
||||
fnd = left->nd_right;
|
||||
if (good_forvar) {
|
||||
uns = BaseType(nd->nd_type)->tp_fund != T_INTEGER;
|
||||
if (fnd->nd_class != Value) {
|
||||
/* Upperbound not constant.
|
||||
The expression may only be evaluated
|
||||
once, so generate a temporary for it
|
||||
*/
|
||||
CodePExpr(fnd);
|
||||
tmp = NewInt();
|
||||
C_stl(tmp);
|
||||
}
|
||||
C_df_ilb(l1);
|
||||
uns = BaseType(nd->nd_type)->tp_fund !=
|
||||
T_INTEGER;
|
||||
C_dup(int_size);
|
||||
if (tmp) C_lol(tmp); else C_loc(fnd->nd_INT);
|
||||
CodePExpr(fnd);
|
||||
tmp = NewInt();
|
||||
C_stl(tmp);
|
||||
C_lol(tmp);
|
||||
if (uns) C_cmu(int_size);
|
||||
else C_cmi(int_size);
|
||||
if (left->nd_INT > 0) {
|
||||
if (left->nd_INT >= 0) {
|
||||
C_zgt(l2);
|
||||
CodeDStore(nd);
|
||||
C_lol(tmp);
|
||||
CodePExpr(nd);
|
||||
}
|
||||
else C_zlt(l2);
|
||||
CodeDStore(nd);
|
||||
else {
|
||||
C_zlt(l2);
|
||||
CodeDStore(nd);
|
||||
CodePExpr(nd);
|
||||
C_lol(tmp);
|
||||
}
|
||||
C_sbu(int_size);
|
||||
if (stepsize) {
|
||||
C_loc(stepsize);
|
||||
C_dvu(int_size);
|
||||
C_loc((arith) 1);
|
||||
C_adu(int_size);
|
||||
}
|
||||
nd->nd_def->df_flags |= D_FORLOOP;
|
||||
C_df_ilb(l1);
|
||||
}
|
||||
WalkNode(right, exit_label);
|
||||
if (good_forvar) {
|
||||
CodePExpr(nd);
|
||||
nd->nd_def->df_flags &= ~D_FORLOOP;
|
||||
if (stepsize && good_forvar) {
|
||||
C_loc((arith) 1);
|
||||
C_sbu(int_size);
|
||||
C_dup(int_size);
|
||||
C_zeq(l2);
|
||||
C_loc(left->nd_INT);
|
||||
if (uns) C_adu(int_size);
|
||||
else C_adi(int_size);
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_asp(int_size);
|
||||
CodePExpr(nd);
|
||||
C_adu(int_size);
|
||||
CodeDStore(nd);
|
||||
}
|
||||
if (tmp) FreeInt(tmp);
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_asp(int_size);
|
||||
FreeInt(tmp);
|
||||
#ifdef DEBUG
|
||||
nd->nd_left = left;
|
||||
nd->nd_right = right;
|
||||
|
@ -642,9 +666,10 @@ WalkDesignator(nd, ds)
|
|||
return 1;
|
||||
}
|
||||
|
||||
DoForInit(nd, left)
|
||||
register struct node *nd, *left;
|
||||
DoForInit(nd)
|
||||
register struct node *nd;
|
||||
{
|
||||
register struct node *left = nd->nd_left;
|
||||
register struct def *df;
|
||||
struct type *tpl, *tpr;
|
||||
|
||||
|
|
Loading…
Reference in a new issue