mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-27 04:03:43 +02:00

+ darwin/ppc64 support + val/str/read(ln)/write(ln) support for enums + simple cse at the node tree level + if-node simplify support + simple ssa support for memory locations + support for optional overflow/rangecheck boolean parameters for operators * a lot of unification of the ppc32/ppc64 code generators ........ r6380 | jonas | 2007-02-08 21:25:36 +0100 (Thu, 08 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/tgobj.pas A /branches/fpc_2_3/tests/webtbs/tw8283.pp + support for replacing the memory location of a temp (including local variables) with that of another temp to avoid unnecessary copies (mantis #8283) ........ r6381 | jonas | 2007-02-08 22:53:36 +0100 (Thu, 08 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/nflw.pas A /branches/fpc_2_3/tests/webtbs/tw8282.pp + simplify support for ifn (based on patch by Florian) ........ r6386 | peter | 2007-02-09 13:48:53 +0100 (Fri, 09 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/htypechk.pas M /branches/fpc_2_3/compiler/ncal.pas M /branches/fpc_2_3/compiler/symconst.pas * overflow,rangecheck optional parameters for operators, patch from 8281 ........ r6391 | jonas | 2007-02-09 23:52:13 +0100 (Fri, 09 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas M /branches/fpc_2_3/compiler/powerpc64/cpunode.pas D /branches/fpc_2_3/compiler/powerpc64/nppcinl.pas M /branches/fpc_2_3/compiler/ppcgen/ngppcinl.pas * merged fsqrt(s) support to common powerpc unit, activate for ppc32 if -Op970 is used (still default for ppc64, since default cpu there is already ppc970) ........ r6394 | jonas | 2007-02-10 18:58:47 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * adapted a_jmp_name for darwin/ppc64 * merged g_intf_wrapper for ppc32 and ppc64, and added darwin/ppc64 support to it ........ r6396 | jonas | 2007-02-10 20:16:06 +0100 (Sat, 10 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/cgobj.pas + darwin/ppc64 support for g_indirect_sym_load ........ r6397 | jonas | 2007-02-10 20:22:49 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas + darwin/ppc64 support to ppc64's fixref * moved ppc32 a_load_store to cgppc and use it for darwin/ppc64 as well (its relocatable symbols are only 32 bits large) ........ r6399 | jonas | 2007-02-10 22:02:37 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/systems.pas + system_x86_64_darwin identifier + set default source system for system_x86_64_darwin and system_powerpc64_darwin ........ r6404 | jonas | 2007-02-10 23:01:23 +0100 (Sat, 10 Feb 2007) | 5 lines Changed paths: M /branches/fpc_2_3/compiler/aasmdata.pas M /branches/fpc_2_3/compiler/aggas.pas M /branches/fpc_2_3/compiler/cgobj.pas M /branches/fpc_2_3/compiler/cgutils.pas M /branches/fpc_2_3/compiler/cresstr.pas M /branches/fpc_2_3/compiler/dbgdwarf.pas M /branches/fpc_2_3/compiler/dbgstabs.pas M /branches/fpc_2_3/compiler/ncgutil.pas M /branches/fpc_2_3/compiler/ogelf.pas M /branches/fpc_2_3/compiler/pdecvar.pas M /branches/fpc_2_3/compiler/pmodules.pas M /branches/fpc_2_3/compiler/symdef.pas M /branches/fpc_2_3/compiler/systems.pas + system_x86_64_darwin identifier + systems_darwin set which collects all darwin variants + added support for darwin/ppc64 and darwin/x86_64 where needed in the generic code ........ r6406 | jonas | 2007-02-10 23:24:32 +0100 (Sat, 10 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/cgobj.pas * ifdef cpu64 -> ifdef cpu64bit ........ r6409 | jonas | 2007-02-11 00:34:04 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/pdecvar.pas * fixed ppc64 compilation ........ r6413 | jonas | 2007-02-11 12:41:27 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/bsd/system.pp M /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc M /branches/fpc_2_3/rtl/darwin/signal.inc + darwin/ppc64 support for signal routines ........ r6415 | jonas | 2007-02-11 13:54:53 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_linux.pas * set abi of linux/ppc64 to abi_powerpc_sysv ........ r6416 | jonas | 2007-02-11 13:55:51 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas M /branches/fpc_2_3/compiler/systems/i_bsd.pas M /branches/fpc_2_3/compiler/systems/t_bsd.pas + darwin/ppc64 source and target information ........ r6418 | jonas | 2007-02-11 14:19:55 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/powerpc64/math.inc * darwin/ppc64 compilation fixes ........ r6419 | jonas | 2007-02-11 14:22:22 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * darwin/ppc64 needs the 32 bit version of a_loadaddr_ref_reg ........ r6420 | jonas | 2007-02-11 14:22:55 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/utils/fpcm/fpcmmain.pp + darwin/ppc64 support ........ r6426 | jonas | 2007-02-11 16:13:19 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/rappcgas.pas * fixed refaddr parsing for darwin/ppc64 ........ r6427 | jonas | 2007-02-11 16:14:21 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas M /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas A /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas * moved ppc32/ppc64 assembler writer helpers to a common unit ........ r6430 | jonas | 2007-02-11 17:53:23 +0100 (Sun, 11 Feb 2007) | 4 lines Changed paths: D /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc D /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc A /branches/fpc_2_3/rtl/darwin/powerpc64 A /branches/fpc_2_3/rtl/darwin/powerpc64/sig_cpu.inc A /branches/fpc_2_3/rtl/darwin/powerpc64/sighnd.inc A /branches/fpc_2_3/rtl/darwin/ppcgen A /branches/fpc_2_3/rtl/darwin/ppcgen/ppchnd.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc:6422) A /branches/fpc_2_3/rtl/darwin/ppcgen/sig_ppc.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc:6422) M /branches/fpc_2_3/rtl/darwin/signal.inc * fixed ppc/ppc64 signal include handling (both real files are in ppcgen, dummies in powerpc and powerpc64 which include those files) (1st step because pre-commit filter can't handle replaced files) ........ r6431 | jonas | 2007-02-11 17:53:47 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: A /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc A /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc * second step of signal include patch ........ r6432 | jonas | 2007-02-11 19:00:12 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/t_bsd.pas * changed darwin checks to use systems_darwin constant ........ r6433 | jonas | 2007-02-11 19:05:38 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas * handle non-multiple-of-4 offsets with 64 bit loads/stores for darwin/ppc64 ........ r6434 | jonas | 2007-02-11 19:05:56 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: D /branches/fpc_2_3/compiler/powerpc/agppcgas.pas D /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas A /branches/fpc_2_3/compiler/ppcgen/agppcgas.pas (from /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas:6427) D /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas * completely merged ppc assembler writers ........ r6435 | jonas | 2007-02-11 19:06:40 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/darwin/console.pp M /branches/fpc_2_3/rtl/darwin/termiosproc.inc * fixed 64 bit compilation ........ r6436 | jonas | 2007-02-11 19:09:28 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/packages/extra/Makefile.fpc * universal interfaces aren't 64 bit ready yet -> only compile for darwin/ppc and darwin/i386 ........ r6438 | jonas | 2007-02-11 19:22:34 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64 A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/ctest.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext3.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext4.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext5.o + compiled for darwin/ppc64 ........ r6439 | jonas | 2007-02-11 20:24:42 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * patch from Thomas to fix linux/ppc64 ........ r6440 | jonas | 2007-02-11 20:25:15 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems.pas * fixed setting source OS for darwin/ppc64 ........ r6444 | florian | 2007-02-11 22:24:20 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/globtype.pas M /branches/fpc_2_3/compiler/nopt.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/optcse.pas M /branches/fpc_2_3/compiler/psub.pas + first node cse implementation ........ r6445 | jonas | 2007-02-11 22:30:07 +0100 (Sun, 11 Feb 2007) | 6 lines Changed paths: M /branches/fpc_2_3/compiler/cresstr.pas * hack to work around strange darwin/ppc64 linker bug: it seems to have problems if you put a global symbol at the end of a section without any data following (at least in case of the resource strings section) -> add dummy byte at the end for darwin/ppc64 (otherwise it messes up the address of the first symbol stub entry) ........ r6449 | jonas | 2007-02-11 23:23:44 +0100 (Sun, 11 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * cpupowerpc is defined for both ppc32 and ppc64 -> changed to cpupowerpc32 to avoid defining source wrongly on ppc64 ........ r6450 | jonas | 2007-02-11 23:26:34 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/ppcgen/ngppcset.pas * disable jump tables for darwin/ppc64 for now, don't work yet for some reason ........ r6451 | florian | 2007-02-11 23:54:37 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/ncal.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/optcse.pas * improved cse * better complexity calculation for subscript nodes with classes or interfaces ........ r6456 | jonas | 2007-02-12 19:33:22 +0100 (Mon, 12 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/nutils.pas + support for notn,shln,shrn,equaln,unequaln,gtn,gten,ltn,lten in node_cplexity() * mark muln,divn,modn as more complex ........ r6469 | jonas | 2007-02-13 15:56:01 +0100 (Tue, 13 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/optcse.pas * fixed when cross-compiling a 64 bit compiler from a 32 bit platform ........ r6471 | jonas | 2007-02-13 16:17:16 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas * include stabs support (can work on darwin/ppc64, but doesn't work yet) ........ r6473 | jonas | 2007-02-13 16:45:48 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cpupara.pas * R2 is a volatile and usable register under darwin/ppc64 * R13 is a reserved non-volatile register under darwin/ppc64 (tls) ........ r6479 | jonas | 2007-02-13 20:40:50 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * maxCrecordalign seems to have to be 8 rather 4, in spite of what the ABI docs say (although they are contradictory to some extent) ........ r6487 | jonas | 2007-02-14 15:57:40 +0100 (Wed, 14 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/tests/webtbs/tw8153a.pp * fixed for darwin/ppc64 ........ r6488 | jonas | 2007-02-14 15:58:56 +0100 (Wed, 14 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/tests/webtbs/tw7851a.pp * fixed for darwin/ppc64 ........ r6494 | jonas | 2007-02-15 19:36:55 +0100 (Thu, 15 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * set default debug info for darwin/ppc64 to dwarf2 since it works better than stabs currently ........ r6500 | jonas | 2007-02-15 21:38:16 +0100 (Thu, 15 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/version.pas * updated version to 2.3.0 ........ r6505 | jonas | 2007-02-15 22:39:28 +0100 (Thu, 15 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/version.pas * changed version to 2.3.1 ........ r6511 | jonas | 2007-02-16 15:17:24 +0100 (Fri, 16 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/itcpugas.pas * system_powerpc_darwin -> system_powerpc64_darwin ........ r6546 | daniel | 2007-02-18 15:48:54 +0100 (Sun, 18 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncginl.pas M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/ncgrtti.pas M /branches/fpc_2_3/compiler/ncnv.pas M /branches/fpc_2_3/compiler/ninl.pas M /branches/fpc_2_3/compiler/nld.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/pinline.pas M /branches/fpc_2_3/rtl/inc/astrings.inc M /branches/fpc_2_3/rtl/inc/compproc.inc M /branches/fpc_2_3/rtl/inc/sstrings.inc M /branches/fpc_2_3/rtl/inc/text.inc M /branches/fpc_2_3/rtl/inc/wstrings.inc + Val/str/read/write support for enumeration types. ........ r6547 | daniel | 2007-02-18 17:01:20 +0100 (Sun, 18 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/sstrings.inc * Fix val code that I broke. ........ r6571 | daniel | 2007-02-20 09:27:44 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/astrings.inc M /branches/fpc_2_3/rtl/inc/sstrings.inc M /branches/fpc_2_3/rtl/inc/text.inc M /branches/fpc_2_3/rtl/inc/wstrings.inc * o2s -> ord2str, s2o -> str2ord ........ r6572 | daniel | 2007-02-20 09:33:30 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/ncgrtti.pas M /branches/fpc_2_3/compiler/ninl.pas M /branches/fpc_2_3/compiler/nld.pas * o2s -> ord2str, s2o -> str2ord ........ r6574 | daniel | 2007-02-20 12:07:58 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/compproc.inc * o2s -> ord2str, s2o -> str2ord ........ r6578 | daniel | 2007-02-20 22:18:49 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/text.inc * Change longint to valsint. ........ r6579 | daniel | 2007-02-20 22:29:09 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * Handle ordinal currency types. ........ r6580 | jonas | 2007-02-20 22:29:11 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncgrtti.pas * fixed compilation for cpurequiresproperalignment ........ r6581 | jonas | 2007-02-20 22:30:21 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * fixed typo ........ r6582 | daniel | 2007-02-20 22:36:19 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * Set is_real to true. ........ r6590 | jonas | 2007-02-21 20:23:54 +0100 (Wed, 21 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * set tf_dwarf_only_local_labels for darwin/ppc64 git-svn-id: trunk@6720 -
1080 lines
48 KiB
ObjectPascal
1080 lines
48 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2002 by Florian Klaempfl
|
|
|
|
Generate assembler for nodes that handle loads and assignments which
|
|
are the same for all (most) processors
|
|
|
|
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 ncgld;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
node,nld,cgutils;
|
|
|
|
type
|
|
tcgloadnode = class(tloadnode)
|
|
procedure pass_generate_code;override;
|
|
procedure generate_picvaraccess;virtual;
|
|
procedure changereflocation(const ref: treference);
|
|
end;
|
|
|
|
tcgassignmentnode = class(tassignmentnode)
|
|
procedure pass_generate_code;override;
|
|
end;
|
|
|
|
tcgarrayconstructornode = class(tarrayconstructornode)
|
|
procedure pass_generate_code;override;
|
|
end;
|
|
|
|
tcgrttinode = class(trttinode)
|
|
procedure pass_generate_code;override;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
cutils,
|
|
systems,
|
|
verbose,globtype,globals,
|
|
nutils,
|
|
symconst,symtype,symdef,symsym,defutil,paramgr,
|
|
ncnv,ncon,nmem,nbas,ncgrtti,
|
|
aasmbase,aasmtai,aasmdata,aasmcpu,
|
|
cgbase,pass_2,
|
|
procinfo,
|
|
cpubase,parabase,
|
|
tgobj,ncgutil,
|
|
cgobj,
|
|
ncgbas,ncgflw;
|
|
|
|
{*****************************************************************************
|
|
SSA (for memory temps) support
|
|
*****************************************************************************}
|
|
|
|
type
|
|
preplacerefrec = ^treplacerefrec;
|
|
treplacerefrec = record
|
|
old, new: preference;
|
|
ressym: tsym;
|
|
end;
|
|
|
|
function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
|
|
var
|
|
rr: preplacerefrec absolute para;
|
|
begin
|
|
result := fen_false;
|
|
case n.nodetype of
|
|
loadn:
|
|
begin
|
|
{ regular variable }
|
|
if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
|
|
not assigned(tloadnode(n).left) and
|
|
{ not function result, or no exit in function }
|
|
(((tloadnode(n).symtableentry <> rr^.ressym) and
|
|
not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
|
|
not(fc_exit in flowcontrol)) and
|
|
{ stored in memory... }
|
|
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
|
|
{ ... at the place we are looking for }
|
|
references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) then
|
|
begin
|
|
{ relocate variable }
|
|
tcgloadnode(n).changereflocation(rr^.new^);
|
|
result := fen_norecurse_true;
|
|
end;
|
|
end;
|
|
temprefn:
|
|
begin
|
|
if (ttemprefnode(n).tempinfo^.valid) and
|
|
{ memory temp... }
|
|
(ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
|
|
{ ... at the place we are looking for }
|
|
references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) then
|
|
begin
|
|
{ relocate the temp }
|
|
tcgtemprefnode(n).changelocation(rr^.new^);
|
|
result := fen_norecurse_true;
|
|
end;
|
|
end;
|
|
{ optimize the searching a bit }
|
|
derefn,addrn,
|
|
calln,inlinen,casen,
|
|
addn,subn,muln,
|
|
andn,orn,xorn,
|
|
ltn,lten,gtn,gten,equaln,unequaln,
|
|
slashn,divn,shrn,shln,notn,
|
|
inn,
|
|
asn,isn:
|
|
result := fen_norecurse_false;
|
|
end;
|
|
end;
|
|
|
|
|
|
function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
|
|
var
|
|
rr: treplacerefrec;
|
|
begin
|
|
result := false;
|
|
|
|
{ only do for -O2 or higher (breaks debugging since }
|
|
{ variables move to different memory locations) }
|
|
if not(cs_opt_level2 in current_settings.optimizerswitches) or
|
|
{ must be a copy to a memory location ... }
|
|
(n.location.loc <> LOC_REFERENCE) or
|
|
{ not inside a control flow statement and no goto's in sight }
|
|
([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
|
|
{ source and destination are temps (= not global variables) }
|
|
not tg.istemp(n.location.reference) or
|
|
not tg.istemp(newref) or
|
|
{ and both point to the start of a temp, and the source is a }
|
|
{ non-persistent temp (otherwise we need some kind of copy- }
|
|
{ on-write support in case later on both are still used) }
|
|
(tg.gettypeoftemp(newref) <> tt_normal) or
|
|
not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
|
|
{ and both have the same size }
|
|
(tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
|
|
exit;
|
|
|
|
{ find the source of the old reference (loadnode or tempnode) }
|
|
{ and replace it with the new reference }
|
|
rr.old := @n.location.reference;
|
|
rr.new := @newref;
|
|
rr.ressym := nil;
|
|
|
|
if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
|
|
assigned(current_procinfo.procdef.funcretsym) and
|
|
(tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
|
|
if (current_procinfo.procdef.proctypeoption=potype_constructor) then
|
|
rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
|
|
else
|
|
rr.ressym:=current_procinfo.procdef.funcretsym;
|
|
|
|
{ if source not found, don't do anything }
|
|
if not foreachnodestatic(n,@doreplaceref,@rr) then
|
|
exit;
|
|
|
|
n.location.reference := newref;
|
|
result:=true;
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
SecondLoad
|
|
*****************************************************************************}
|
|
|
|
procedure tcgloadnode.generate_picvaraccess;
|
|
begin
|
|
{$ifndef sparc}
|
|
location.reference.base:=current_procinfo.got;
|
|
location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname+'@GOT');
|
|
{$endif sparc}
|
|
end;
|
|
|
|
|
|
procedure tcgloadnode.changereflocation(const ref: treference);
|
|
var
|
|
oldtemptype: ttemptype;
|
|
begin
|
|
if (location.loc<>LOC_REFERENCE) then
|
|
internalerror(2007020812);
|
|
if not tg.istemp(location.reference) then
|
|
internalerror(2007020813);
|
|
oldtemptype:=tg.gettypeoftemp(location.reference);
|
|
if (oldtemptype = tt_persistent) then
|
|
tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
|
|
tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
|
|
location.reference:=ref;
|
|
tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
|
|
tabstractnormalvarsym(symtableentry).localloc:=location;
|
|
end;
|
|
|
|
|
|
procedure tcgloadnode.pass_generate_code;
|
|
var
|
|
hregister : tregister;
|
|
vs : tabstractnormalvarsym;
|
|
gvs : tstaticvarsym;
|
|
pd : tprocdef;
|
|
href : treference;
|
|
newsize : tcgsize;
|
|
endrelocatelab,
|
|
norelocatelab : tasmlabel;
|
|
paraloc1 : tcgpara;
|
|
begin
|
|
|
|
{ we don't know the size of all arrays }
|
|
newsize:=def_cgsize(resultdef);
|
|
location_reset(location,LOC_REFERENCE,newsize);
|
|
case symtableentry.typ of
|
|
absolutevarsym :
|
|
begin
|
|
{ this is only for toasm and toaddr }
|
|
case tabsolutevarsym(symtableentry).abstyp of
|
|
toaddr :
|
|
begin
|
|
{$ifdef i386}
|
|
if tabsolutevarsym(symtableentry).absseg then
|
|
location.reference.segment:=NR_FS;
|
|
{$endif i386}
|
|
location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
|
|
end;
|
|
toasm :
|
|
location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
|
|
else
|
|
internalerror(200310283);
|
|
end;
|
|
end;
|
|
constsym:
|
|
begin
|
|
if tconstsym(symtableentry).consttyp=constresourcestring then
|
|
begin
|
|
location_reset(location,LOC_CREFERENCE,OS_ADDR);
|
|
location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
|
|
{ Resourcestring layout:
|
|
TResourceStringRecord = Packed Record
|
|
Name,
|
|
CurrentValue,
|
|
DefaultValue : AnsiString;
|
|
HashValue : LongWord;
|
|
end;
|
|
}
|
|
location.reference.offset:=sizeof(aint);
|
|
end
|
|
else
|
|
internalerror(22798);
|
|
end;
|
|
staticvarsym :
|
|
begin
|
|
gvs:=tstaticvarsym(symtableentry);
|
|
if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
|
|
begin
|
|
location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname);
|
|
if (location.reference.base <> NR_NO) then
|
|
exit;
|
|
end;
|
|
|
|
if (vo_is_dll_var in gvs.varoptions) then
|
|
{ DLL variable }
|
|
begin
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
|
|
reference_reset_base(location.reference,hregister,0);
|
|
end
|
|
{ Thread variable }
|
|
else if (vo_is_thread_var in gvs.varoptions) and
|
|
not(tf_section_threadvars in target_info.flags) then
|
|
begin
|
|
if (tf_section_threadvars in target_info.flags) then
|
|
begin
|
|
if gvs.localloc.loc=LOC_INVALID then
|
|
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
|
else
|
|
location:=gvs.localloc;
|
|
{$ifdef i386}
|
|
case target_info.system of
|
|
system_i386_linux:
|
|
location.reference.segment:=NR_GS;
|
|
system_i386_win32:
|
|
location.reference.segment:=NR_FS;
|
|
end;
|
|
{$endif i386}
|
|
end
|
|
else
|
|
begin
|
|
{
|
|
Thread var loading is optimized to first check if
|
|
a relocate function is available. When the function
|
|
is available it is called to retrieve the address.
|
|
Otherwise the address is loaded with the symbol
|
|
|
|
The code needs to be in the order to first handle the
|
|
call and then the address load to be sure that the
|
|
register that is used for returning is the same (PFV)
|
|
}
|
|
current_asmdata.getjumplabel(norelocatelab);
|
|
current_asmdata.getjumplabel(endrelocatelab);
|
|
{ make sure hregister can't allocate the register necessary for the parameter }
|
|
paraloc1.init;
|
|
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
|
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
|
|
{ don't save the allocated register else the result will be destroyed later }
|
|
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),0);
|
|
paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
|
|
cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
|
paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
|
|
paraloc1.done;
|
|
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
|
cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
|
|
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
|
cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
|
|
cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
|
|
cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
|
|
{ no relocation needed, load the address of the variable only, the
|
|
layout of a threadvar is (4 bytes pointer):
|
|
0 - Threadvar index
|
|
4 - Threadvar value in single threading }
|
|
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),sizeof(aint));
|
|
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
|
|
cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
|
|
location.reference.base:=hregister;
|
|
end;
|
|
end
|
|
{ Normal (or external) variable }
|
|
else
|
|
begin
|
|
if gvs.localloc.loc=LOC_INVALID then
|
|
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
|
else
|
|
location:=gvs.localloc;
|
|
end;
|
|
|
|
{ make const a LOC_CREFERENCE }
|
|
if (gvs.varspez=vs_const) and
|
|
(location.loc=LOC_REFERENCE) then
|
|
location.loc:=LOC_CREFERENCE;
|
|
end;
|
|
paravarsym,
|
|
localvarsym :
|
|
begin
|
|
vs:=tabstractnormalvarsym(symtableentry);
|
|
{ Nested variable }
|
|
if assigned(left) then
|
|
begin
|
|
secondpass(left);
|
|
if left.location.loc<>LOC_REGISTER then
|
|
internalerror(200309286);
|
|
if vs.localloc.loc<>LOC_REFERENCE then
|
|
internalerror(200409241);
|
|
reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
|
|
end
|
|
else
|
|
location:=vs.localloc;
|
|
|
|
{ handle call by reference variables when they are not
|
|
alreayd copied to local copies. Also ignore the reference
|
|
when we need to load the self pointer for objects }
|
|
if is_addr_param_load then
|
|
begin
|
|
if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
|
|
hregister:=location.register
|
|
else
|
|
begin
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
{ we need to load only an address }
|
|
location.size:=OS_ADDR;
|
|
cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
|
|
end;
|
|
location_reset(location,LOC_REFERENCE,newsize);
|
|
location.reference.base:=hregister;
|
|
end;
|
|
|
|
{ make const a LOC_CREFERENCE }
|
|
if (vs.varspez=vs_const) and
|
|
(location.loc=LOC_REFERENCE) then
|
|
location.loc:=LOC_CREFERENCE;
|
|
end;
|
|
procsym:
|
|
begin
|
|
if not assigned(procdef) then
|
|
internalerror(200312011);
|
|
if assigned(left) then
|
|
begin
|
|
if (sizeof(aint) = 4) then
|
|
location_reset(location,LOC_CREFERENCE,OS_64)
|
|
else if (sizeof(aint) = 8) then
|
|
location_reset(location,LOC_CREFERENCE,OS_128)
|
|
else
|
|
internalerror(20020520);
|
|
tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(aint),tt_normal,location.reference);
|
|
secondpass(left);
|
|
|
|
{ load class instance address }
|
|
if left.location.loc=LOC_CONSTANT then
|
|
location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
|
|
case left.location.loc of
|
|
LOC_CREGISTER,
|
|
LOC_REGISTER:
|
|
begin
|
|
{ this is not possible for objects }
|
|
if is_object(left.resultdef) then
|
|
internalerror(200304234);
|
|
hregister:=left.location.register;
|
|
end;
|
|
LOC_CREFERENCE,
|
|
LOC_REFERENCE:
|
|
begin
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
if is_class_or_interface(left.resultdef) then
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
|
|
else
|
|
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
|
|
location_freetemp(current_asmdata.CurrAsmList,left.location);
|
|
end;
|
|
else
|
|
internalerror(200610311);
|
|
end;
|
|
|
|
{ store the class instance address }
|
|
href:=location.reference;
|
|
inc(href.offset,sizeof(aint));
|
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
|
|
|
|
{ virtual method ? }
|
|
if (po_virtualmethod in procdef.procoptions) and
|
|
not(nf_inherited in flags) then
|
|
begin
|
|
{ load vmt pointer }
|
|
reference_reset_base(href,hregister,0);
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
|
{ load method address }
|
|
reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
|
{ ... and store it }
|
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
|
end
|
|
else
|
|
begin
|
|
{ load address of the function }
|
|
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
|
|
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
|
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
|
|
if (po_external in pd.procoptions) then
|
|
location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname);
|
|
{!!!!! Be aware, work on virtual methods too }
|
|
if (location.reference.base = NR_NO) then
|
|
location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
|
|
end;
|
|
end;
|
|
labelsym :
|
|
location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
|
|
else internalerror(200510032);
|
|
end;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
SecondAssignment
|
|
*****************************************************************************}
|
|
|
|
procedure tcgassignmentnode.pass_generate_code;
|
|
var
|
|
otlabel,hlabel,oflabel : tasmlabel;
|
|
href : treference;
|
|
releaseright : boolean;
|
|
len : aint;
|
|
r:Tregister;
|
|
|
|
begin
|
|
location_reset(location,LOC_VOID,OS_NO);
|
|
|
|
otlabel:=current_procinfo.CurrTrueLabel;
|
|
oflabel:=current_procinfo.CurrFalseLabel;
|
|
current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
|
|
current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
|
|
|
|
{
|
|
in most cases we can process first the right node which contains
|
|
the most complex code. Exceptions for this are:
|
|
- result is in flags, loading left will then destroy the flags
|
|
- result is a jump, loading left must be already done before the jump is made
|
|
- result need reference count, when left points to a value used in
|
|
right then decreasing the refcnt on left can possibly release
|
|
the memory before right increased the refcnt, result is that an
|
|
empty value is assigned
|
|
- calln, call destroys most registers and is therefor 'complex'
|
|
|
|
But not when the result is in the flags, then
|
|
loading the left node afterwards can destroy the flags.
|
|
}
|
|
if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
|
|
((right.nodetype=calln) or
|
|
(right.resultdef.needs_inittable) or
|
|
(right.registersint>=left.registersint)) then
|
|
begin
|
|
secondpass(right);
|
|
{ increment source reference counter, this is
|
|
useless for string constants}
|
|
if (right.resultdef.needs_inittable) and
|
|
(right.nodetype<>stringconstn) then
|
|
begin
|
|
location_force_mem(current_asmdata.CurrAsmList,right.location);
|
|
location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
|
|
cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
|
|
end;
|
|
if codegenerror then
|
|
exit;
|
|
|
|
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
|
{ can be false }
|
|
secondpass(left);
|
|
{ decrement destination reference counter }
|
|
if (left.resultdef.needs_inittable) then
|
|
begin
|
|
location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
|
|
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
|
end;
|
|
if codegenerror then
|
|
exit;
|
|
end
|
|
else
|
|
begin
|
|
{ calculate left sides }
|
|
secondpass(left);
|
|
{ decrement destination reference counter }
|
|
if (left.resultdef.needs_inittable) then
|
|
begin
|
|
location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
|
|
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
|
end;
|
|
if codegenerror then
|
|
exit;
|
|
|
|
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
|
{ can be false }
|
|
secondpass(right);
|
|
{ increment source reference counter, this is
|
|
useless for string constants}
|
|
if (right.resultdef.needs_inittable) and
|
|
(right.nodetype<>stringconstn) then
|
|
begin
|
|
location_force_mem(current_asmdata.CurrAsmList,right.location);
|
|
location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
|
|
cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
|
|
end;
|
|
|
|
if codegenerror then
|
|
exit;
|
|
end;
|
|
|
|
releaseright:=true;
|
|
|
|
{ shortstring assignments are handled separately }
|
|
if is_shortstring(left.resultdef) then
|
|
begin
|
|
{
|
|
we can get here only in the following situations
|
|
for the right node:
|
|
- empty constant string
|
|
- char
|
|
}
|
|
|
|
{ The addn is replaced by a blockn or calln }
|
|
if right.nodetype in [blockn,calln] then
|
|
begin
|
|
{ nothing to do }
|
|
end
|
|
{ empty constant string }
|
|
else if (right.nodetype=stringconstn) and
|
|
(tstringconstnode(right).len=0) then
|
|
begin
|
|
cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
|
|
end
|
|
{ char loading }
|
|
else if is_char(right.resultdef) then
|
|
begin
|
|
if right.nodetype=ordconstn then
|
|
begin
|
|
if (target_info.endian = endian_little) then
|
|
cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value shl 8) or 1,
|
|
left.location.reference)
|
|
else
|
|
cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value or (1 shl 8),
|
|
left.location.reference);
|
|
end
|
|
else
|
|
begin
|
|
href:=left.location.reference;
|
|
cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
|
|
inc(href.offset,1);
|
|
case right.location.loc of
|
|
LOC_REGISTER,
|
|
LOC_CREGISTER :
|
|
begin
|
|
r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
|
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
|
|
end;
|
|
LOC_REFERENCE,
|
|
LOC_CREFERENCE :
|
|
cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
|
|
else
|
|
internalerror(200205111);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
internalerror(200204249);
|
|
end
|
|
{ try to reuse memory locations instead of copying }
|
|
{ copy to a memory location ... }
|
|
else if (right.location.loc = LOC_REFERENCE) and
|
|
maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
|
|
begin
|
|
{ if it worked, we're done }
|
|
end
|
|
else
|
|
begin
|
|
{ SSA support }
|
|
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
|
|
maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
|
|
case right.location.loc of
|
|
LOC_CONSTANT :
|
|
begin
|
|
{$ifndef cpu64bit}
|
|
if right.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
|
|
end;
|
|
LOC_REFERENCE,
|
|
LOC_CREFERENCE :
|
|
begin
|
|
case left.location.loc of
|
|
LOC_REGISTER,
|
|
LOC_CREGISTER :
|
|
begin
|
|
{$ifndef cpu64bit}
|
|
if left.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
|
|
end;
|
|
LOC_FPUREGISTER,
|
|
LOC_CFPUREGISTER :
|
|
begin
|
|
cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
|
|
right.location.size,left.location.size,
|
|
right.location.reference,
|
|
left.location.register);
|
|
end;
|
|
LOC_REFERENCE,
|
|
LOC_CREFERENCE :
|
|
begin
|
|
{$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
|
|
{ Use unaligned copy when the offset is not aligned }
|
|
len:=left.resultdef.size;
|
|
if (right.location.reference.offset mod sizeof(aint)<>0) or
|
|
(left.location.reference.offset mod sizeof(aint)<>0) or
|
|
(right.resultdef.alignment<sizeof(aint)) then
|
|
cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
|
|
else
|
|
cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
|
|
end;
|
|
LOC_MMREGISTER,
|
|
LOC_CMMREGISTER:
|
|
cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
|
|
right.location.size,
|
|
left.location.size,
|
|
right.location.reference,
|
|
left.location.register,mms_movescalar);
|
|
LOC_SUBSETREG,
|
|
LOC_CSUBSETREG:
|
|
cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
|
|
LOC_SUBSETREF,
|
|
LOC_CSUBSETREF:
|
|
{$ifndef cpu64bit}
|
|
if right.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
|
|
else
|
|
internalerror(200203284);
|
|
end;
|
|
end;
|
|
{$ifdef SUPPORT_MMX}
|
|
LOC_CMMXREGISTER,
|
|
LOC_MMXREGISTER:
|
|
begin
|
|
if left.location.loc=LOC_CMMXREGISTER then
|
|
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
|
|
else
|
|
cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
|
|
end;
|
|
{$endif SUPPORT_MMX}
|
|
LOC_MMREGISTER,
|
|
LOC_CMMREGISTER:
|
|
begin
|
|
if left.resultdef.typ=arraydef then
|
|
begin
|
|
end
|
|
else
|
|
begin
|
|
if left.location.loc=LOC_CMMREGISTER then
|
|
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
|
|
else
|
|
cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
|
|
end;
|
|
end;
|
|
LOC_REGISTER,
|
|
LOC_CREGISTER :
|
|
begin
|
|
{$ifndef cpu64bit}
|
|
if left.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
|
|
right.location.register64,left.location)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
|
|
end;
|
|
LOC_FPUREGISTER,
|
|
LOC_CFPUREGISTER :
|
|
begin
|
|
{ we can't do direct moves between fpu and mm registers }
|
|
if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
|
|
begin
|
|
location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
|
|
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
|
|
right.location.size,left.location.size,
|
|
right.location.register,left.location.register,mms_movescalar);
|
|
end
|
|
else
|
|
cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
|
|
right.location.size,
|
|
right.location.register,left.location);
|
|
end;
|
|
LOC_SUBSETREG,
|
|
LOC_CSUBSETREG:
|
|
begin
|
|
cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
|
|
right.location.size,right.location.sreg,left.location);
|
|
end;
|
|
LOC_SUBSETREF,
|
|
LOC_CSUBSETREF:
|
|
begin
|
|
{$ifndef cpu64bit}
|
|
if right.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
|
|
right.location.size,right.location.sref,left.location);
|
|
end;
|
|
LOC_JUMP :
|
|
begin
|
|
current_asmdata.getjumplabel(hlabel);
|
|
cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
|
|
cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location);
|
|
cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
|
|
cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
|
|
cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
|
|
cg.a_label(current_asmdata.CurrAsmList,hlabel);
|
|
end;
|
|
{$ifdef cpuflags}
|
|
LOC_FLAGS :
|
|
begin
|
|
{This can be a wordbool or longbool too, no?}
|
|
case left.location.loc of
|
|
LOC_REGISTER,LOC_CREGISTER:
|
|
cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.register);
|
|
LOC_REFERENCE:
|
|
cg.g_flags2ref(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.reference);
|
|
LOC_SUBSETREG,LOC_SUBSETREF:
|
|
begin
|
|
r:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
|
|
cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,r);
|
|
cg.a_load_reg_loc(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),r,left.location);
|
|
end;
|
|
else
|
|
internalerror(200203273);
|
|
end;
|
|
end;
|
|
{$endif cpuflags}
|
|
end;
|
|
end;
|
|
|
|
if releaseright then
|
|
location_freetemp(current_asmdata.CurrAsmList,right.location);
|
|
|
|
current_procinfo.CurrTrueLabel:=otlabel;
|
|
current_procinfo.CurrFalseLabel:=oflabel;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
SecondArrayConstruct
|
|
*****************************************************************************}
|
|
|
|
const
|
|
vtInteger = 0;
|
|
vtBoolean = 1;
|
|
vtChar = 2;
|
|
vtExtended = 3;
|
|
vtString = 4;
|
|
vtPointer = 5;
|
|
vtPChar = 6;
|
|
vtObject = 7;
|
|
vtClass = 8;
|
|
vtWideChar = 9;
|
|
vtPWideChar = 10;
|
|
vtAnsiString32 = 11;
|
|
vtCurrency = 12;
|
|
vtVariant = 13;
|
|
vtInterface = 14;
|
|
vtWideString = 15;
|
|
vtInt64 = 16;
|
|
vtQWord = 17;
|
|
vtAnsiString16 = 18;
|
|
vtAnsiString64 = 19;
|
|
|
|
procedure tcgarrayconstructornode.pass_generate_code;
|
|
var
|
|
hp : tarrayconstructornode;
|
|
href : treference;
|
|
lt : tdef;
|
|
vaddr : boolean;
|
|
vtype : longint;
|
|
freetemp,
|
|
dovariant : boolean;
|
|
elesize : longint;
|
|
tmpreg : tregister;
|
|
paraloc : tcgparalocation;
|
|
begin
|
|
if is_packed_array(resultdef) then
|
|
internalerror(200608042);
|
|
dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
|
|
if dovariant then
|
|
elesize:=sizeof(aint)+sizeof(aint)
|
|
else
|
|
elesize:=tarraydef(resultdef).elesize;
|
|
location_reset(location,LOC_CREFERENCE,OS_NO);
|
|
fillchar(paraloc,sizeof(paraloc),0);
|
|
{ Allocate always a temp, also if no elements are required, to
|
|
be sure that location is valid (PFV) }
|
|
if tarraydef(resultdef).highrange=-1 then
|
|
tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
|
|
else
|
|
tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
|
|
href:=location.reference;
|
|
{ Process nodes in array constructor }
|
|
hp:=self;
|
|
while assigned(hp) do
|
|
begin
|
|
if assigned(hp.left) then
|
|
begin
|
|
freetemp:=true;
|
|
secondpass(hp.left);
|
|
if codegenerror then
|
|
exit;
|
|
{ Move flags and jump in register }
|
|
if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
|
location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
|
|
if dovariant then
|
|
begin
|
|
{ find the correct vtype value }
|
|
vtype:=$ff;
|
|
vaddr:=false;
|
|
lt:=hp.left.resultdef;
|
|
case lt.typ of
|
|
enumdef,
|
|
orddef :
|
|
begin
|
|
if is_64bit(lt) then
|
|
begin
|
|
case torddef(lt).ordtype of
|
|
scurrency:
|
|
vtype:=vtCurrency;
|
|
s64bit:
|
|
vtype:=vtInt64;
|
|
u64bit:
|
|
vtype:=vtQWord;
|
|
end;
|
|
freetemp:=false;
|
|
vaddr:=true;
|
|
end
|
|
else if (lt.typ=enumdef) or
|
|
is_integer(lt) then
|
|
vtype:=vtInteger
|
|
else
|
|
if is_boolean(lt) then
|
|
vtype:=vtBoolean
|
|
else
|
|
if (lt.typ=orddef) then
|
|
begin
|
|
case torddef(lt).ordtype of
|
|
uchar:
|
|
vtype:=vtChar;
|
|
uwidechar:
|
|
vtype:=vtWideChar;
|
|
end;
|
|
end;
|
|
end;
|
|
floatdef :
|
|
begin
|
|
if is_currency(lt) then
|
|
vtype:=vtCurrency
|
|
else
|
|
vtype:=vtExtended;
|
|
freetemp:=false;
|
|
vaddr:=true;
|
|
end;
|
|
procvardef,
|
|
pointerdef :
|
|
begin
|
|
if is_pchar(lt) then
|
|
vtype:=vtPChar
|
|
else if is_pwidechar(lt) then
|
|
vtype:=vtPWideChar
|
|
else
|
|
vtype:=vtPointer;
|
|
end;
|
|
variantdef :
|
|
begin
|
|
vtype:=vtVariant;
|
|
vaddr:=true;
|
|
freetemp:=false;
|
|
end;
|
|
classrefdef :
|
|
vtype:=vtClass;
|
|
objectdef :
|
|
if is_interface(lt) then
|
|
vtype:=vtInterface
|
|
{ vtObject really means a class based on TObject }
|
|
else if is_class(lt) then
|
|
vtype:=vtObject
|
|
else
|
|
internalerror(200505171);
|
|
stringdef :
|
|
begin
|
|
if is_shortstring(lt) then
|
|
begin
|
|
vtype:=vtString;
|
|
vaddr:=true;
|
|
freetemp:=false;
|
|
end
|
|
else
|
|
if is_ansistring(lt) then
|
|
begin
|
|
vtype:=vtAnsiString;
|
|
freetemp:=false;
|
|
end
|
|
else
|
|
if is_widestring(lt) then
|
|
begin
|
|
vtype:=vtWideString;
|
|
freetemp:=false;
|
|
end;
|
|
end;
|
|
end;
|
|
if vtype=$ff then
|
|
internalerror(14357);
|
|
{ write changing field update href to the next element }
|
|
inc(href.offset,sizeof(aint));
|
|
if vaddr then
|
|
begin
|
|
location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
|
|
tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
|
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
|
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
|
|
end
|
|
else
|
|
cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
|
|
{ update href to the vtype field and write it }
|
|
dec(href.offset,sizeof(aint));
|
|
cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
|
|
{ goto next array element }
|
|
inc(href.offset,sizeof(aint)*2);
|
|
end
|
|
else
|
|
{ normal array constructor of the same type }
|
|
begin
|
|
if resultdef.needs_inittable then
|
|
freetemp:=false;
|
|
case hp.left.location.loc of
|
|
LOC_MMREGISTER,
|
|
LOC_CMMREGISTER:
|
|
cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
|
|
hp.left.location.register,href,mms_movescalar);
|
|
LOC_FPUREGISTER,
|
|
LOC_CFPUREGISTER :
|
|
cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
|
|
LOC_REFERENCE,
|
|
LOC_CREFERENCE :
|
|
begin
|
|
if is_shortstring(hp.left.resultdef) then
|
|
cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
|
|
Tstringdef(hp.left.resultdef).len)
|
|
else
|
|
cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
|
|
end;
|
|
else
|
|
begin
|
|
{$ifndef cpu64bit}
|
|
if hp.left.location.size in [OS_64,OS_S64] then
|
|
cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
|
|
else
|
|
{$endif cpu64bit}
|
|
cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
|
|
end;
|
|
end;
|
|
inc(href.offset,elesize);
|
|
end;
|
|
if freetemp then
|
|
location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
|
|
end;
|
|
{ load next entry }
|
|
hp:=tarrayconstructornode(hp.right);
|
|
end;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
SecondRTTI
|
|
*****************************************************************************}
|
|
|
|
procedure tcgrttinode.pass_generate_code;
|
|
begin
|
|
location_reset(location,LOC_CREFERENCE,OS_NO);
|
|
case rttidatatype of
|
|
rdt_normal:
|
|
location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
|
|
rdt_ord2str:
|
|
location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
|
|
rdt_str2ord:
|
|
location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
begin
|
|
cloadnode:=tcgloadnode;
|
|
cassignmentnode:=tcgassignmentnode;
|
|
carrayconstructornode:=tcgarrayconstructornode;
|
|
crttinode:=tcgrttinode;
|
|
end.
|