{ $Id$ Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe Generate PowerPC assembler for in 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 nppcmem; {$i fpcdefs.inc} interface uses node,nmem,ncgmem; type tppcvecnode = class(tcgvecnode) procedure pass_2;override; end; implementation uses {$ifdef delphi} sysutils, {$endif} globtype,systems, cutils,verbose,globals, symconst,symtype,symdef,symsym,symtable,defbase,paramgr, aasmbase,aasmtai,aasmcpu, cginfo,cgbase,pass_2, pass_1,nld,ncon,nadd, cpubase, cgobj,tgobj,rgobj,ncgutil; {***************************************************************************** TPPCVECNODE *****************************************************************************} procedure tppcvecnode.pass_2; var extraoffset : longint; { rl stores the resulttype.def of the left node, this is necessary } { to detect if it is an ansistring } { because in constant nodes which constant index } { the left tree is removed } t : tnode; href : treference; srsym : tsym; pushed : tpushedsaved; hightree : tnode; isjump : boolean; otl,ofl : tasmlabel; newsize : tcgsize; pushedregs : tmaybesave; begin newsize:=def_cgsize(resulttype.def); location_reset(location,LOC_REFERENCE,newsize); secondpass(left); { we load the array reference to location } { an ansistring needs to be dereferenced } if is_ansistring(left.resulttype.def) or is_widestring(left.resulttype.def) then begin if nf_callunique in flags then begin if left.location.loc<>LOC_REFERENCE then begin CGMessage(cg_e_illegal_expression); exit; end; rg.saveusedregisters(exprasmlist,pushed,all_registers); cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1)); rg.saveregvars(exprasmlist,all_registers); cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE'); cg.g_maybe_loadself(exprasmlist); rg.restoreusedregisters(exprasmlist,pushed); end; case left.location.loc of LOC_REGISTER, LOC_CREGISTER : location.reference.base:=left.location.register; LOC_CREFERENCE, LOC_REFERENCE : begin location_release(exprasmlist,left.location); location.reference.base:=rg.getregisterint(exprasmlist); cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.reference.base); end; else internalerror(2002032218); end; { check for a zero length string, we can use the ansistring routine here } if (cs_check_range in aktlocalswitches) then begin rg.saveusedregisters(exprasmlist,pushed,all_registers); cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1)); rg.saveregvars(exprasmlist,all_registers); cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO'); cg.g_maybe_loadself(exprasmlist); rg.restoreusedregisters(exprasmlist,pushed); end; { in ansistrings/widestrings S[1] is pchar(S)[0] !! } if is_ansistring(left.resulttype.def) then dec(location.reference.offset) else dec(location.reference.offset,2); { we've also to keep left up-to-date, because it is used } { if a constant array index occurs, subject to change (FK) } location_copy(left.location,location); end else if is_dynamic_array(left.resulttype.def) then { ... also a dynamic string } begin case left.location.loc of LOC_REGISTER, LOC_CREGISTER : location.reference.base:=left.location.register; LOC_REFERENCE, LOC_CREFERENCE : begin location_release(exprasmlist,left.location); location.reference.base:=rg.getaddressregister(exprasmlist); cg.a_load_ref_reg(exprasmlist,OS_ADDR, left.location.reference,location.reference.base); end; else internalerror(2002032219); end; {$warning FIXME} { check for a zero length string, we can use the ansistring routine here } if (cs_check_range in aktlocalswitches) then begin rg.saveusedregisters(exprasmlist,pushed,all_registers); cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1)); rg.saveregvars(exprasmlist,all_registers); cg.a_call_name(exprasmlist,'FPC_ANSISTR_CHECKZERO'); cg.g_maybe_loadself(exprasmlist); rg.restoreusedregisters(exprasmlist,pushed); end; { we've also to keep left up-to-date, because it is used } { if a constant array index occurs, subject to change (FK) } location_copy(left.location,location); end else location_copy(location,left.location); { offset can only differ from 0 if arraydef } if (left.resulttype.def.deftype=arraydef) and not(is_dynamic_array(left.resulttype.def)) then dec(location.reference.offset, get_mul_size*tarraydef(left.resulttype.def).lowrange); if right.nodetype=ordconstn then begin { offset can only differ from 0 if arraydef } if (left.resulttype.def.deftype=arraydef) then begin if not(is_open_array(left.resulttype.def)) and not(is_array_of_const(left.resulttype.def)) and not(is_dynamic_array(left.resulttype.def)) then begin if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or (tordconstnode(right).value