fpc/compiler/ncgld.pas
Jonas Maebe c13ff3729b * Merged 2.3 branch changes:
+ 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 -
2007-03-04 20:16:57 +00:00

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.