123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632 |
- {
- $Id$
- Copyright (c) 1993-98 by Florian Klaempfl
- Type checking and register allocation for memory related nodes
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit tcmem;
- interface
- uses
- tree;
- procedure firstloadvmt(var p : ptree);
- procedure firsthnew(var p : ptree);
- procedure firstnew(var p : ptree);
- procedure firsthdispose(var p : ptree);
- procedure firstsimplenewdispose(var p : ptree);
- procedure firstaddr(var p : ptree);
- procedure firstdoubleaddr(var p : ptree);
- procedure firstderef(var p : ptree);
- procedure firstsubscript(var p : ptree);
- procedure firstvec(var p : ptree);
- procedure firstself(var p : ptree);
- procedure firstwith(var p : ptree);
- implementation
- uses
- globtype,systems,
- cobjects,verbose,globals,
- symtable,aasm,types,
- hcodegen,htypechk,pass_1
- {$ifdef i386}
- ,i386base
- {$endif}
- {$ifdef m68k}
- ,m68k
- {$endif}
- ;
- {*****************************************************************************
- FirstLoadVMT
- *****************************************************************************}
- procedure firstloadvmt(var p : ptree);
- begin
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- {*****************************************************************************
- FirstHNew
- *****************************************************************************}
- procedure firsthnew(var p : ptree);
- begin
- end;
- {*****************************************************************************
- FirstNewN
- *****************************************************************************}
- procedure firstnew(var p : ptree);
- begin
- { Standardeinleitung }
- if assigned(p^.left) then
- firstpass(p^.left);
- if codegenerror then
- exit;
- if assigned(p^.left) then
- begin
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- { result type is already set }
- procinfo.flags:=procinfo.flags or pi_do_call;
- if assigned(p^.left) then
- p^.location.loc:=LOC_REGISTER
- else
- p^.location.loc:=LOC_REFERENCE;
- end;
- {*****************************************************************************
- FirstDispose
- *****************************************************************************}
- procedure firsthdispose(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- {
- if p^.left^.location.loc<>LOC_REFERENCE then
- CGMessage(cg_e_illegal_expression);
- }
- p^.location.loc:=LOC_REFERENCE;
- p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
- end;
- {*****************************************************************************
- FirstSimpleNewDispose
- *****************************************************************************}
- procedure firstsimplenewdispose(var p : ptree);
- begin
- { this cannot be in a register !! }
- make_not_regable(p^.left);
- firstpass(p^.left);
- if codegenerror then
- exit;
- { check the type }
- if (p^.left^.resulttype=nil) or (p^.left^.resulttype^.deftype<>pointerdef) then
- CGMessage(type_e_pointer_type_expected);
- if (p^.left^.location.loc<>LOC_REFERENCE) {and
- (p^.left^.location.loc<>LOC_CREGISTER)} then
- CGMessage(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- p^.resulttype:=voiddef;
- procinfo.flags:=procinfo.flags or pi_do_call;
- end;
- {*****************************************************************************
- FirstAddr
- *****************************************************************************}
- procedure firstaddr(var p : ptree);
- var
- hp : ptree;
- hp2 : pdefcoll;
- store_valid : boolean;
- hp3 : pabstractprocdef;
- begin
- make_not_regable(p^.left);
- if not(assigned(p^.resulttype)) then
- begin
- { proc/procvar 2 procvar ? }
- if p^.left^.treetype=calln then
- begin
- { it could also be a procvar, not only pprocsym ! }
- if p^.left^.symtableprocentry^.typ=varsym then
- hp:=genloadnode(pvarsym(p^.left^.symtableprocentry),p^.left^.symtableproc)
- else
- begin
- if assigned(p^.left^.methodpointer) and
- (p^.left^.methodpointer^.resulttype^.deftype=objectdef) and
- (pobjectdef(p^.left^.methodpointer^.resulttype)^.isclass) then
- begin
- hp:=genloadmethodcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc,
- getcopy(p^.left^.methodpointer));
- disposetree(p);
- firstpass(hp);
- p:=hp;
- exit;
- end
- else
- hp:=genloadcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc);
- end;
- { result is a procedure variable }
- { No, to be TP compatible, you must return a pointer to
- the procedure that is stored in the procvar.}
- if not(m_tp_procvar in aktmodeswitches) then
- begin
- p^.resulttype:=new(pprocvardef,init);
- { it could also be a procvar, not only pprocsym ! }
- if p^.left^.symtableprocentry^.typ=varsym then
- hp3:=pabstractprocdef(pvarsym(p^.left^.symtableprocentry)^.definition)
- else
- hp3:=pabstractprocdef(pprocsym(p^.left^.symtableprocentry)^.definition);
- pprocvardef(p^.resulttype)^.options:=hp3^.options;
- pprocvardef(p^.resulttype)^.retdef:=hp3^.retdef;
- hp2:=hp3^.para1;
- while assigned(hp2) do
- begin
- pprocvardef(p^.resulttype)^.concatdef(hp2^.data,hp2^.paratyp);
- hp2:=hp2^.next;
- end;
- end
- else
- p^.resulttype:=voidpointerdef;
- disposetree(p^.left);
- p^.left:=hp;
- end
- else
- begin
- { what are we getting the address from an absolute sym? }
- hp:=p^.left;
- while assigned(hp) and (hp^.treetype in [vecn,subscriptn]) do
- hp:=hp^.left;
- if assigned(hp) and (hp^.treetype=loadn) and
- ((hp^.symtableentry^.typ=absolutesym) and
- pabsolutesym(hp^.symtableentry)^.absseg) then
- begin
- if not(cs_typed_addresses in aktlocalswitches) then
- p^.resulttype:=voidfarpointerdef
- else
- p^.resulttype:=new(ppointerdef,initfar(p^.left^.resulttype));
- end
- else
- begin
- if not(cs_typed_addresses in aktlocalswitches) then
- p^.resulttype:=voidpointerdef
- else
- p^.resulttype:=new(ppointerdef,init(p^.left^.resulttype));
- end;
- end;
- end;
- store_valid:=must_be_valid;
- must_be_valid:=false;
- firstpass(p^.left);
- must_be_valid:=store_valid;
- if codegenerror then
- exit;
- { we should allow loc_mem for @string }
- if not(p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
- CGMessage(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- {*****************************************************************************
- FirstDoubleAddr
- *****************************************************************************}
- procedure firstdoubleaddr(var p : ptree);
- begin
- make_not_regable(p^.left);
- firstpass(p^.left);
- if p^.resulttype=nil then
- p^.resulttype:=voidpointerdef;
- if codegenerror then
- exit;
- if (p^.left^.resulttype^.deftype)<>procvardef then
- CGMessage(cg_e_illegal_expression);
- if (p^.left^.location.loc<>LOC_REFERENCE) then
- CGMessage(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- {*****************************************************************************
- FirstDeRef
- *****************************************************************************}
- procedure firstderef(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- begin
- p^.resulttype:=generrordef;
- exit;
- end;
- p^.registers32:=max(p^.left^.registers32,1);
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.left^.resulttype^.deftype<>pointerdef then
- CGMessage(cg_e_invalid_qualifier);
- p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
- p^.location.loc:=LOC_REFERENCE;
- end;
- {*****************************************************************************
- FirstSubScript
- *****************************************************************************}
- procedure firstsubscript(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- begin
- p^.resulttype:=generrordef;
- exit;
- end;
- p^.resulttype:=p^.vs^.definition;
- { this must be done in the parser
- if count_ref and not must_be_valid then
- if (p^.vs^.properties and sp_protected)<>0 then
- CGMessage(parser_e_cant_write_protected_member);
- }
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { classes must be dereferenced implicit }
- if (p^.left^.resulttype^.deftype=objectdef) and
- pobjectdef(p^.left^.resulttype)^.isclass then
- begin
- if p^.registers32=0 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REFERENCE;
- end
- else
- begin
- if (p^.left^.location.loc<>LOC_MEM) and
- (p^.left^.location.loc<>LOC_REFERENCE) then
- CGMessage(cg_e_illegal_expression);
- set_location(p^.location,p^.left^.location);
- end;
- end;
- {*****************************************************************************
- FirstVec
- *****************************************************************************}
- procedure firstvec(var p : ptree);
- var
- harr : pdef;
- ct : tconverttype;
- {$ifdef consteval}
- tcsym : ptypedconstsym;
- {$endif}
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- { range check only for arrays }
- if (p^.left^.resulttype^.deftype=arraydef) then
- begin
- if (isconvertable(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef,
- ct,ordconstn,false)=0) and
- not(is_equal(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef)) then
- CGMessage(type_e_mismatch);
- end;
- { Never convert a boolean or a char !}
- { maybe type conversion }
- if (p^.right^.resulttype^.deftype<>enumdef) and
- not(is_char(p^.right^.resulttype)) and
- not(is_boolean(p^.right^.resulttype)) then
- begin
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- firstpass(p^.right);
- if codegenerror then
- exit;
- end;
- { determine return type }
- if not assigned(p^.resulttype) then
- if p^.left^.resulttype^.deftype=arraydef then
- p^.resulttype:=parraydef(p^.left^.resulttype)^.definition
- else if (p^.left^.resulttype^.deftype=pointerdef) then
- begin
- { convert pointer to array }
- harr:=new(parraydef,init(0,$7fffffff,s32bitdef));
- parraydef(harr)^.definition:=ppointerdef(p^.left^.resulttype)^.definition;
- p^.left:=gentypeconvnode(p^.left,harr);
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.resulttype:=parraydef(harr)^.definition
- end
- else if p^.left^.resulttype^.deftype=stringdef then
- begin
- { indexed access to strings }
- case pstringdef(p^.left^.resulttype)^.string_typ of
- {
- st_widestring : p^.resulttype:=cwchardef;
- }
- st_ansistring : p^.resulttype:=cchardef;
- st_longstring : p^.resulttype:=cchardef;
- st_shortstring : p^.resulttype:=cchardef;
- end;
- end
- else
- CGMessage(type_e_mismatch);
- { the register calculation is easy if a const index is used }
- if p^.right^.treetype=ordconstn then
- begin
- {$ifdef consteval}
- { constant evaluation }
- if (p^.left^.treetype=loadn) and
- (p^.left^.symtableentry^.typ=typedconstsym) then
- begin
- tcsym:=ptypedconstsym(p^.left^.symtableentry);
- if tcsym^.defintion^.typ=stringdef then
- begin
- end;
- end;
- {$endif}
- p^.registers32:=p^.left^.registers32;
- { for ansi/wide strings, we need at least one register }
- if is_ansistring(p^.left^.resulttype) or
- is_widestring(p^.left^.resulttype) then
- p^.registers32:=max(p^.registers32,1);
- end
- else
- begin
- { this rules are suboptimal, but they should give }
- { good results }
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- { for ansi/wide strings, we need at least one register }
- if is_ansistring(p^.left^.resulttype) or
- is_widestring(p^.left^.resulttype) then
- p^.registers32:=max(p^.registers32,1);
- { need we an extra register when doing the restore ? }
- if (p^.left^.registers32<=p^.right^.registers32) and
- { only if the node needs less than 3 registers }
- { two for the right node and one for the }
- { left address }
- (p^.registers32<3) then
- inc(p^.registers32);
- { need we an extra register for the index ? }
- if (p^.right^.location.loc<>LOC_REGISTER)
- { only if the right node doesn't need a register }
- and (p^.right^.registers32<1) then
- inc(p^.registers32);
- { not correct, but what works better ?
- if p^.left^.registers32>0 then
- p^.registers32:=max(p^.registers32,2)
- else
- min. one register
- p^.registers32:=max(p^.registers32,1);
- }
- end;
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- if p^.left^.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
- p^.location.loc:=LOC_REFERENCE
- else
- p^.location.loc:=LOC_MEM;
- end;
- {*****************************************************************************
- FirstSelf
- *****************************************************************************}
- procedure firstself(var p : ptree);
- begin
- if (p^.resulttype^.deftype=classrefdef) or
- ((p^.resulttype^.deftype=objectdef)
- and pobjectdef(p^.resulttype)^.isclass
- ) then
- p^.location.loc:=LOC_CREGISTER
- else
- p^.location.loc:=LOC_REFERENCE;
- end;
- {*****************************************************************************
- FirstWithN
- *****************************************************************************}
- procedure firstwith(var p : ptree);
- var
- symtable : pwithsymtable;
- i : longint;
- begin
- if assigned(p^.left) and assigned(p^.right) then
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- symtable:=p^.withsymtable;
- for i:=1 to p^.tablecount do
- begin
- if (p^.left^.treetype=loadn) and
- (p^.left^.symtable=aktprocsym^.definition^.localst) then
- symtable^.direct_with:=true;
- symtable^.withnode:=p;
- symtable:=pwithsymtable(symtable^.next);
- end;
- firstpass(p^.right);
- if codegenerror then
- exit;
- left_right_max(p);
- p^.resulttype:=voiddef;
- end
- else
- begin
- { optimization }
- disposetree(p);
- p:=nil;
- end;
- end;
- end.
- {
- $Log$
- Revision 1.17 1999-05-27 19:45:24 peter
- * removed oldasm
- * plabel -> pasmlabel
- * -a switches to source writing automaticly
- * assembler readers OOPed
- * asmsymbol automaticly external
- * jumptables and other label fixes for asm readers
- Revision 1.16 1999/05/18 09:52:21 peter
- * procedure of object and addrn fixes
- Revision 1.15 1999/05/17 23:51:46 peter
- * with temp vars now use a reference with a persistant temp instead
- of setting datasize
- Revision 1.14 1999/05/01 13:24:57 peter
- * merged nasm compiler
- * old asm moved to oldasm/
- Revision 1.13 1999/04/26 18:30:05 peter
- * farpointerdef moved into pointerdef.is_far
- Revision 1.12 1999/03/02 18:24:24 peter
- * fixed overloading of array of char
- Revision 1.11 1999/02/22 02:15:54 peter
- * updates for ag386bin
- Revision 1.10 1999/02/04 11:44:47 florian
- * fixed indexed access of ansistrings to temp. ansistring, i.e.
- c:=(s1+s2)[i], the temp is now correctly remove and the generated
- code is also fixed
- Revision 1.9 1999/01/22 12:18:34 pierre
- * with bug introduced with DIRECTWITH removed
- Revision 1.8 1999/01/21 16:41:08 pierre
- * fix for constructor inside with statements
- Revision 1.7 1998/12/30 22:15:59 peter
- + farpointer type
- * absolutesym now also stores if its far
- Revision 1.6 1998/12/15 17:16:02 peter
- * fixed const s : ^string
- * first things for const pchar : @string[1]
- Revision 1.5 1998/12/11 00:03:57 peter
- + globtype,tokens,version unit splitted from globals
- Revision 1.4 1998/11/25 19:12:53 pierre
- * var:=new(pointer_type) support added
- Revision 1.3 1998/09/26 15:03:05 florian
- * small problems with DOM and excpetions fixed (code generation
- of raise was wrong and self was sometimes destroyed :()
- Revision 1.2 1998/09/24 23:49:24 peter
- + aktmodeswitches
- Revision 1.1 1998/09/23 20:42:24 peter
- * splitted pass_1
- }
|