123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- /* D E S I G N A T O R E V A L U A T I O N */
- /* Code generation for designators.
- This file contains some routines that generate code common to address
- as well as value computations, and leave a description in a "desig"
- structure. It also contains routines to load an address, load a value
- or perform a store.
- */
- #include "debug.h"
- #include <assert.h>
- #include <em.h>
- #include "LLlex.h"
- #include "def.h"
- #include "desig.h"
- #include "main.h"
- #include "node.h"
- #include "scope.h"
- #include "type.h"
- struct desig InitDesig = {DSG_INIT, 0, 0, NULLDEF, 0};
- struct withdesig *WithDesigs;
- STATIC int
- properly(ds, size, al)
- register struct desig *ds;
- arith size;
- {
- /* Check if it is allowed to load or store the value indicated
- by "ds" with LOI/STI.
- - if the size is not either a multiple or a dividor of the
- wordsize, then not.
- - if the alignment is at least "word" then OK.
- - if size is dividor of word_size and alignment >= size then OK.
- - otherwise check alignment of address. This can only be done
- with DSG_FIXED.
- */
- arith szmodword = size % word_size; /* 0 if multiple of wordsize */
- arith wordmodsz = word_size % size; /* 0 if dividor of wordsize */
- if( szmodword && wordmodsz ) return 0;
- if( al >= word_align ) return 1;
- if( szmodword && al >= szmodword ) return 1;
- return ds->dsg_kind == DSG_FIXED &&
- ((! szmodword && ds->dsg_offset % word_align == 0) ||
- (! wordmodsz && ds->dsg_offset % size == 0));
- }
- CodeCopy(lhs, rhs, sz, psize)
- register struct desig *lhs, *rhs;
- arith sz, *psize;
- {
- struct desig l, r;
- l = *lhs;
- r = *rhs;
- *psize -= sz;
- lhs->dsg_offset += sz;
- rhs->dsg_offset += sz;
- CodeAddress(&r);
- C_loi(sz);
- CodeAddress(&l);
- C_sti(sz);
- }
- CodeMove(rhs, left, rtp)
- register struct desig *rhs;
- register struct node *left;
- struct type *rtp;
- {
- struct desig dsl;
- register struct desig *lhs = &dsl;
- register struct type *ltp = left->nd_type;
- dsl = InitDesig;
- /* Generate code for an assignment. Testing of type
- compatibility and the like is already done.
- Go through some (considerable) trouble to see if
- a BLM can be generated.
- */
- switch( rhs->dsg_kind ) {
- case DSG_LOADED:
- CodeDesig(left, lhs);
- if( rtp->tp_fund == T_STRING ) {
- CodeAddress(lhs);
- C_blm(lhs->dsg_packed ? ltp->tp_psize : ltp->tp_size);
- return;
- }
- CodeStore(lhs, ltp);
- return;
- case DSG_PLOADED:
- case DSG_PFIXED:
- CodeAddress(rhs);
- CodeValue(rhs, rtp);
- CodeDStore(left);
- return;
- case DSG_FIXED: {
- arith tpsize;
- CodeDesig(left, lhs);
- tpsize = lhs->dsg_packed ? ltp->tp_psize : ltp->tp_size;
- if( lhs->dsg_kind == DSG_FIXED &&
- lhs->dsg_offset % word_size == rhs->dsg_offset % word_size
- ) {
- arith size = tpsize;
- if( size > 6 * word_size ) {
- /* Do a block move
- */
- struct desig l, r;
- l = *lhs;
- r = *rhs;
- CodeAddress(&r);
- CodeAddress(&l);
- C_blm(size);
- }
- else {
- register arith sz;
- for( sz = 2 * word_size; sz; sz -= word_size) {
- while( size >= sz )
- /* Then copy dwords, words.
- Depend on peephole optimizer
- */
- CodeCopy(lhs, rhs, sz, &size);
- }
- }
- return;
- }
- if( lhs->dsg_kind == DSG_PLOADED ||
- lhs->dsg_kind == DSG_INDEXED ) {
- CodeAddress(lhs);
- }
- }
- default:
- crash("(CodeMove)");
- /*NOTREACHED*/
- }
- }
- CodeValue(ds, tp)
- register struct desig *ds;
- register struct type *tp;
- {
- /* Generate code to load the value of the designator described
- in "ds"
- */
- arith size = ds->dsg_packed ? tp->tp_psize : tp->tp_size;
- int align = ds->dsg_packed ? tp->tp_palign : tp->tp_align;
- switch( ds->dsg_kind ) {
- case DSG_LOADED:
- break;
- case DSG_FIXED:
- if( ds->dsg_offset % word_size == 0 && size == word_size ) {
- if( ds->dsg_name )
- C_loe_dnam(ds->dsg_name, ds->dsg_offset);
- else
- C_lol(ds->dsg_offset);
- break;
- }
- /* Fall through */
- case DSG_PLOADED:
- case DSG_PFIXED:
- if( properly(ds, size, align) ) {
- CodeAddress(ds);
- C_loi(size);
- break;
- }
- printf("(CodeValue) : not properly");
- break;
- case DSG_INDEXED:
- C_lar(word_size);
- break;
- default:
- crash("(CodeValue)");
- /*NOTREACHED*/
- }
- ds->dsg_kind = DSG_LOADED;
- }
- CodeStore(ds, tp)
- register struct desig *ds;
- register struct type *tp;
- {
- /* Generate code to store the value on the stack in the designator
- described in "ds"
- */
- struct desig save;
- arith size = ds->dsg_packed ? tp->tp_psize : tp->tp_size;
- int align = ds->dsg_packed ? tp->tp_palign : tp->tp_align;
- save = *ds;
-
- switch( ds->dsg_kind ) {
- case DSG_FIXED:
- if( ds->dsg_offset % word_size == 0 && size == word_size ) {
- if( ds->dsg_name )
- C_ste_dnam(ds->dsg_name, ds->dsg_offset);
- else
- C_stl(ds->dsg_offset);
- break;
- }
- /* Fall through */
- case DSG_PLOADED:
- case DSG_PFIXED:
- CodeAddress(&save);
- if( properly(ds, size, align) ) {
- C_sti(size);
- break;
- }
- printf("(CodeStore) : not properly");
- break;
- case DSG_INDEXED:
- C_sar(word_size);
- break;
- default:
- crash("(CodeStore)");
- /*NOTREACHED*/
- }
- ds->dsg_kind = DSG_INIT;
- }
- CodeAddress(ds)
- register struct desig *ds;
- {
- /* Generate code to load the address of the designator described
- in "ds"
- */
- switch( ds->dsg_kind ) {
- case DSG_PLOADED:
- if( ds->dsg_offset )
- C_adp(ds->dsg_offset);
- break;
- case DSG_FIXED:
- if( ds->dsg_name ) {
- C_lae_dnam(ds->dsg_name, ds->dsg_offset);
- break;
- }
- C_lal(ds->dsg_offset);
- if( ds->dsg_def )
- ds->dsg_def->df_flags |= D_NOREG;
- break;
-
- case DSG_PFIXED:
- if( ds->dsg_name )
- C_loe_dnam(ds->dsg_name, ds->dsg_offset);
- else
- C_lol(ds->dsg_offset);
- break;
- case DSG_INDEXED:
- C_aar(word_size);
- break;
- default:
- crash("(CodeAddress)");
- /*NOTREACHED*/
- }
- ds->dsg_offset = 0;
- ds->dsg_kind = DSG_PLOADED;
- }
- CodeFieldDesig(df, ds)
- register struct def *df;
- register struct desig *ds;
- {
- /* Generate code for a field designator. Only the code common for
- address as well as value computation is generated, and the
- resulting information on where to find the designator is placed
- in "ds". "df" indicates the definition of the field.
- */
- if( ds->dsg_kind == DSG_INIT ) {
- /* In a WITH statement. We must find the designator in the
- WITH statement, and act as if the field is a selection
- of this designator.
- So, first find the right WITH statement, which is the
- first one of the proper record type, which is
- recognized by its scope indication.
- */
- register struct withdesig *wds = WithDesigs;
- assert(wds != 0);
- while( wds->w_scope != df->df_scope ) {
- wds = wds->w_next;
- assert(wds != 0);
- }
- /* Found it. Now, act like it was a selection.
- */
- *ds = wds->w_desig;
- assert(ds->dsg_kind == DSG_PFIXED);
- }
- switch( ds->dsg_kind ) {
- case DSG_PLOADED:
- case DSG_FIXED:
- ds->dsg_offset += df->fld_off;
- break;
- case DSG_PFIXED:
- case DSG_INDEXED:
- CodeAddress(ds);
- ds->dsg_kind = DSG_PLOADED;
- ds->dsg_offset = df->fld_off;
- break;
- default:
- crash("(CodeFieldDesig)");
- }
- ds->dsg_packed = df->fld_flags & F_PACKED;
- }
- CodeVarDesig(df, ds)
- register struct def *df;
- register struct desig *ds;
- {
- /* Generate code for a variable represented by a "def" structure.
- Of course, there are numerous cases: the variable is local,
- it is a value parameter, it is a var parameter, it is one of
- those of an enclosing procedure, or it is global.
- */
- register struct scope *sc = df->df_scope;
- assert(ds->dsg_kind == DSG_INIT);
- if( df->var_name ) {
- /* this variable has been given a name, so it is global.
- It is directly accessible.
- */
- ds->dsg_name = df->var_name;
- ds->dsg_offset = 0;
- ds->dsg_kind = DSG_FIXED;
- return;
- }
- if( sc->sc_level != proclevel ) {
- /* the variable is local to a statically enclosing procedure.
- */
- assert(proclevel > sc->sc_level);
- df->df_flags |= D_NOREG;
- if( df->df_flags & (D_VARPAR|D_VALPAR) ) {
- /* value or var parameter
- */
- C_lxa((arith) (proclevel - sc->sc_level));
- if( (df->df_flags & D_VARPAR) ||
- IsConformantArray(df->df_type) ) {
- /* var parameter or conformant array.
- For conformant array's, the address is
- passed.
- */
- C_adp(df->var_off);
- C_loi(pointer_size);
- ds->dsg_offset = 0;
- ds->dsg_kind = DSG_PLOADED;
- return;
- }
- }
- else
- C_lxl((arith) (proclevel - sc->sc_level));
- ds->dsg_kind = DSG_PLOADED;
- ds->dsg_offset = df->var_off;
- return;
- }
- /* Now, finally, we have a local variable or a local parameter
- */
- if( (df->df_flags & D_VARPAR) || IsConformantArray(df->df_type) )
- /* a var parameter; address directly accessible. */
- ds->dsg_kind = DSG_PFIXED;
- else
- ds->dsg_kind = DSG_FIXED;
- ds->dsg_offset = df->var_off;
- ds->dsg_def = df;
- }
- CodeBoundDesig(df, ds)
- register struct def *df;
- register struct desig *ds;
- {
- /* Generate code for the lower- and upperbound of a conformant array */
- assert(ds->dsg_kind == DSG_INIT);
- if( df->df_scope->sc_level < proclevel ) {
- C_lxa((arith) (proclevel - df->df_scope->sc_level));
- if( df->df_kind == D_UBOUND ) {
- C_ldf(df->bnd_type->arr_cfdescr);
- C_adi(word_size);
- }
- else
- C_lof(df->bnd_type->arr_cfdescr);
- }
- else {
- if( df->df_kind == D_UBOUND ) {
- C_ldl(df->bnd_type->arr_cfdescr);
- C_adi(word_size);
- }
- else
- C_lol(df->bnd_type->arr_cfdescr);
- }
- ds->dsg_kind = DSG_LOADED;
- }
- CodeFuncDesig(df, ds)
- register struct def *df;
- register struct desig *ds;
- {
- /* generate code to store the function result */
- if( df->df_scope->sc_level + 1 < proclevel ) {
- /* Assignment to function-identifier in the declaration-part of
- the function (i.e. in the statement-part of a nested function
- or procedure).
- */
- C_lxl((arith) (proclevel - df->df_scope->sc_level - 1));
- ds->dsg_kind = DSG_PLOADED;
- }
- else {
- /* Assignment to function-identifier in the statement-part of
- the function.
- */
- ds->dsg_kind = DSG_FIXED;
- }
- assert(df->prc_res < 0);
- ds->dsg_offset = df->prc_res;
- }
- CodeDesig(nd, ds)
- register struct node *nd;
- register struct desig *ds;
- {
- /* Generate code for a designator. Use divide and conquer
- principle
- */
- register struct def *df;
- switch( nd->nd_class ) { /* Divide */
- case Def:
- df = nd->nd_def;
- switch( df->df_kind ) {
- case D_FIELD:
- CodeFieldDesig(df, ds);
- break;
- case D_VARIABLE:
- CodeVarDesig(df, ds);
- break;
- case D_LBOUND:
- case D_UBOUND:
- CodeBoundDesig(df, ds);
- break;
- case D_FUNCTION:
- CodeFuncDesig(df, ds);
- break;
- default:
- crash("(CodeDesig) Def");
- }
- break;
- case LinkDef:
- assert(nd->nd_symb == '.');
- CodeDesig(nd->nd_left, ds);
- CodeFieldDesig(nd->nd_def, ds);
- break;
- case Arrsel: {
- struct type *tp;
- assert(nd->nd_symb == '[');
- CodeDesig(nd->nd_left, ds);
- CodeAddress(ds);
- CodePExpr(nd->nd_right);
- /* Now load address of descriptor
- */
- tp = nd->nd_left->nd_type;
- if( IsConformantArray(tp) ) {
- if( tp->arr_sclevel < proclevel ) {
- C_lxa((arith) (proclevel - tp->arr_sclevel));
- C_adp(tp->arr_cfdescr);
- }
- else
- C_lal(tp->arr_cfdescr);
- }
- else
- C_lae_dlb(tp->arr_ardescr, (arith) 0);
- ds->dsg_kind = DSG_INDEXED;
- ds->dsg_packed = IsPacked(tp);
- break;
- }
- case Arrow:
- assert(nd->nd_symb == '^');
- if( nd->nd_right->nd_type->tp_fund == T_FILE ) {
- CodeDAddress(nd->nd_right);
- C_cal("_wdw");
- C_asp(pointer_size);
- C_lfr(pointer_size);
- ds->dsg_kind = DSG_PLOADED;
- ds->dsg_packed = 1;
- break;
- }
- CodeDesig(nd->nd_right, ds);
- switch(ds->dsg_kind) {
- case DSG_LOADED:
- ds->dsg_kind = DSG_PLOADED;
- break;
- case DSG_INDEXED:
- case DSG_PLOADED:
- case DSG_PFIXED:
- CodeValue(ds, nd->nd_right->nd_type);
- ds->dsg_kind = DSG_PLOADED;
- ds->dsg_offset = 0;
- break;
- case DSG_FIXED:
- ds->dsg_kind = DSG_PFIXED;
- break;
- default:
- crash("(CodeDesig) Uoper");
- }
- break;
-
- default:
- crash("(CodeDesig) class");
- }
- }
|