mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-16 05:30:37 +01:00
* moved ncgutil.maybechangeloadnodereg() to hlcg.maybe_change_load_node_reg()
and moved ifdef'd jvm code to overridden method git-svn-id: trunk@27153 -
This commit is contained in:
parent
dab8754bb6
commit
73a3f5ced4
@ -37,12 +37,22 @@ unit hlcgobj;
|
||||
cclasses,globtype,constexp,
|
||||
cpubase,cgbase,cgutils,parabase,
|
||||
aasmbase,aasmtai,aasmdata,aasmcpu,
|
||||
symconst,symtype,symdef,
|
||||
node
|
||||
symconst,symtype,symsym,symdef,
|
||||
node,nutils
|
||||
;
|
||||
|
||||
type
|
||||
tsubsetloadopt = (SL_REG,SL_REGNOSRCMASK,SL_SETZERO,SL_SETMAX);
|
||||
|
||||
preplaceregrec = ^treplaceregrec;
|
||||
treplaceregrec = record
|
||||
old, new: tregister;
|
||||
oldhi, newhi: tregister;
|
||||
ressym: tsym;
|
||||
{ moved sym }
|
||||
sym : tabstractnormalvarsym;
|
||||
end;
|
||||
|
||||
{# @abstract(Abstract high level code generator)
|
||||
This class implements an abstract instruction generator. All
|
||||
methods of this class are generic and are mapped to low level code
|
||||
@ -477,6 +487,13 @@ unit hlcgobj;
|
||||
procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);virtual;
|
||||
|
||||
procedure maketojumpbool(list:TAsmList; p : tnode);virtual;
|
||||
{ if the result of n is a LOC_C(..)REGISTER, try to find the corresponding
|
||||
loadn and change its location to a new register (= SSA). In case reload
|
||||
is true, transfer the old to the new register }
|
||||
procedure maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean); virtual;
|
||||
private
|
||||
function do_replace_node_regs(var n: tnode; para: pointer): foreachnoderesult; virtual;
|
||||
public
|
||||
|
||||
procedure gen_proc_symbol(list:TAsmList);virtual;
|
||||
procedure gen_proc_symbol_end(list:TAsmList);virtual;
|
||||
@ -555,9 +572,12 @@ implementation
|
||||
globals,systems,
|
||||
fmodule,export,
|
||||
verbose,defutil,paramgr,
|
||||
symbase,symsym,symtable,
|
||||
ncon,nld,ncgrtti,pass_1,pass_2,
|
||||
symbase,symtable,
|
||||
nbas,ncon,nld,ncgrtti,pass_1,pass_2,
|
||||
cpuinfo,cgobj,tgobj,cutils,procinfo,
|
||||
{$ifdef x86}
|
||||
cgx86,
|
||||
{$endif x86}
|
||||
ncgutil,ngenutil;
|
||||
|
||||
|
||||
@ -3863,6 +3883,225 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure thlcgobj.maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
var
|
||||
rr: treplaceregrec;
|
||||
varloc : tai_varloc;
|
||||
begin
|
||||
if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
|
||||
([fc_inflowcontrol,fc_gotolabel,fc_lefthandled] * flowcontrol <> []) then
|
||||
exit;
|
||||
rr.old := n.location.register;
|
||||
rr.ressym := nil;
|
||||
rr.sym := nil;
|
||||
rr.oldhi := NR_NO;
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
begin
|
||||
rr.oldhi := n.location.register128.reghi;
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
end
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
rr.oldhi := n.location.register64.reghi;
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
else
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ self is implicitly returned from constructors, even if there are no
|
||||
references to it; additionally, funcretsym is not set for constructor
|
||||
procdefs }
|
||||
if (current_procinfo.procdef.proctypeoption=potype_constructor) then
|
||||
rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
|
||||
else if not is_void(current_procinfo.procdef.returndef) and
|
||||
assigned(current_procinfo.procdef.funcretsym) and
|
||||
(tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
|
||||
rr.ressym:=current_procinfo.procdef.funcretsym;
|
||||
|
||||
if not foreachnode(n,@do_replace_node_regs,@rr) then
|
||||
exit;
|
||||
|
||||
if reload then
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
cg128.a_load128_reg_reg(list,n.location.register128,joinreg128(rr.new,rr.newhi))
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
cg.a_loadfpu_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new,nil);
|
||||
else
|
||||
internalerror(2006090920);
|
||||
end;
|
||||
|
||||
{ now that we've change the loadn/temp, also change the node result location }
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
begin
|
||||
n.location.register128.reglo := rr.new;
|
||||
n.location.register128.reghi := rr.newhi;
|
||||
if assigned(rr.sym) and
|
||||
((rr.sym.currentregloc.register<>rr.new) or
|
||||
(rr.sym.currentregloc.registerhi<>rr.newhi)) then
|
||||
begin
|
||||
varloc:=tai_varloc.create128(rr.sym,rr.new,rr.newhi);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
rr.sym.currentregloc.registerHI:=rr.newhi;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
n.location.register64.reglo := rr.new;
|
||||
n.location.register64.reghi := rr.newhi;
|
||||
if assigned(rr.sym) and
|
||||
((rr.sym.currentregloc.register<>rr.new) or
|
||||
(rr.sym.currentregloc.registerhi<>rr.newhi)) then
|
||||
begin
|
||||
varloc:=tai_varloc.create64(rr.sym,rr.new,rr.newhi);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
rr.sym.currentregloc.registerHI:=rr.newhi;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
begin
|
||||
n.location.register := rr.new;
|
||||
if assigned(rr.sym) and (rr.sym.currentregloc.register<>rr.new) then
|
||||
begin
|
||||
varloc:=tai_varloc.create(rr.sym,rr.new);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function thlcgobj.do_replace_node_regs(var n: tnode; para: pointer): foreachnoderesult;
|
||||
var
|
||||
rr: preplaceregrec absolute para;
|
||||
begin
|
||||
result := fen_false;
|
||||
if (nf_is_funcret in n.flags) and (fc_exit in flowcontrol) then
|
||||
exit;
|
||||
case n.nodetype of
|
||||
loadn:
|
||||
begin
|
||||
if (tloadnode(n).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) and
|
||||
(tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
|
||||
not assigned(tloadnode(n).left) and
|
||||
((tloadnode(n).symtableentry <> rr^.ressym) or
|
||||
not(fc_exit in flowcontrol)
|
||||
) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
{ it's possible a 128 bit location was shifted and/xor typecasted }
|
||||
{ in a 64 bit value, so only 1 register was left in the location }
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_128,OS_S128]) then
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi = rr^.oldhi) then
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$else cpu64bitalu}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bitalu}
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
|
||||
rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
|
||||
result := fen_norecurse_true;
|
||||
end;
|
||||
end;
|
||||
temprefn:
|
||||
begin
|
||||
if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
|
||||
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(ttemprefnode(n).tempinfo^.location.register = rr^.old) then
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
{ it's possible a 128 bit location was shifted and/xor typecasted }
|
||||
{ in a 64 bit value, so only 1 register was left in the location }
|
||||
if (ttemprefnode(n).tempinfo^.location.size in [OS_128,OS_S128]) then
|
||||
if (ttemprefnode(n).tempinfo^.location.register128.reghi = rr^.oldhi) then
|
||||
ttemprefnode(n).tempinfo^.location.register128.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$else cpu64bitalu}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
|
||||
if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
|
||||
ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bitalu}
|
||||
ttemprefnode(n).tempinfo^.location.register := 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;
|
||||
|
||||
|
||||
procedure thlcgobj.gen_proc_symbol(list: TAsmList);
|
||||
var
|
||||
item,
|
||||
|
||||
@ -111,7 +111,7 @@ implementation
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
begin
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,true);
|
||||
location.reference.base := left.location.register;
|
||||
location.reference.segment := GetNextReg(left.location.register);
|
||||
end;
|
||||
|
||||
@ -30,6 +30,7 @@ uses
|
||||
globtype,
|
||||
aasmbase,aasmdata,
|
||||
symbase,symconst,symtype,symdef,symsym,
|
||||
node,
|
||||
cpubase, hlcgobj, cgbase, cgutils, parabase;
|
||||
|
||||
type
|
||||
@ -103,6 +104,7 @@ uses
|
||||
procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation); override;
|
||||
|
||||
procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);override;
|
||||
procedure maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean); override;
|
||||
procedure g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister); override;
|
||||
procedure g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation); override;
|
||||
|
||||
@ -1814,6 +1816,11 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
begin
|
||||
{ don't do anything, all registers become stack locations anyway }
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
|
||||
var
|
||||
localref: treference;
|
||||
|
||||
@ -263,7 +263,7 @@ implementation
|
||||
secondpass(fparainit);
|
||||
secondpass(left);
|
||||
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,true);
|
||||
|
||||
{ release memory for refcnt out parameters }
|
||||
if (parasym.varspez=vs_out) and
|
||||
|
||||
@ -508,7 +508,7 @@ implementation
|
||||
current_procinfo.CurrFalseLabel:=ofl;
|
||||
end;
|
||||
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
|
||||
oldflowcontrol:=flowcontrol;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
{ produce start assignment }
|
||||
|
||||
@ -750,8 +750,8 @@ implementation
|
||||
else
|
||||
begin
|
||||
{ SSA support }
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,right,true);
|
||||
case right.location.loc of
|
||||
LOC_CONSTANT :
|
||||
begin
|
||||
|
||||
@ -258,7 +258,7 @@ implementation
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
begin
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
|
||||
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,true);
|
||||
{$ifdef cpu_uses_separate_address_registers}
|
||||
if getregtype(left.location.register)<>R_ADDRESSREGISTER then
|
||||
begin
|
||||
|
||||
@ -97,11 +97,6 @@ interface
|
||||
// procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
|
||||
procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
|
||||
|
||||
{ if the result of n is a LOC_C(..)REGISTER, try to find the corresponding
|
||||
loadn and change its location to a new register (= SSA). In case reload
|
||||
is true, transfer the old to the new register }
|
||||
procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
|
||||
{ Allocate the buffers for exception management and setjmp environment.
|
||||
Return a pointer to these buffers, send them to the utility routine
|
||||
so they are registered, and then call setjmp.
|
||||
@ -571,12 +566,12 @@ implementation
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
{ Note: for withs of records (and maybe objects, classes, etc.) an
|
||||
{ Note: for widths of records (and maybe objects, classes, etc.) an
|
||||
address register could be set here, but that is later
|
||||
changed to an intregister neverthless when in the
|
||||
tcgassignmentnode maybechangeloadnodereg is called for the
|
||||
temporary node; so the workaround for now is to fix the
|
||||
symptoms... }
|
||||
tcgassignmentnode thlcgobj.maybe_change_load_node_reg is
|
||||
called for the temporary node; so the workaround for now is
|
||||
to fix the symptoms... }
|
||||
l.register:=cg.getintregister(list,l.size);
|
||||
end;
|
||||
end;
|
||||
@ -1789,243 +1784,6 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
SSA support
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
preplaceregrec = ^treplaceregrec;
|
||||
treplaceregrec = record
|
||||
old, new: tregister;
|
||||
oldhi, newhi: tregister;
|
||||
ressym: tsym;
|
||||
{ moved sym }
|
||||
sym : tabstractnormalvarsym;
|
||||
end;
|
||||
|
||||
|
||||
function doreplace(var n: tnode; para: pointer): foreachnoderesult;
|
||||
var
|
||||
rr: preplaceregrec absolute para;
|
||||
begin
|
||||
result := fen_false;
|
||||
if (nf_is_funcret in n.flags) and (fc_exit in flowcontrol) then
|
||||
exit;
|
||||
case n.nodetype of
|
||||
loadn:
|
||||
begin
|
||||
if (tloadnode(n).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) and
|
||||
(tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
|
||||
not assigned(tloadnode(n).left) and
|
||||
((tloadnode(n).symtableentry <> rr^.ressym) or
|
||||
not(fc_exit in flowcontrol)
|
||||
) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
{ it's possible a 128 bit location was shifted and/xor typecasted }
|
||||
{ in a 64 bit value, so only 1 register was left in the location }
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_128,OS_S128]) then
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi = rr^.oldhi) then
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$else cpu64bitalu}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bitalu}
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
|
||||
rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
|
||||
result := fen_norecurse_true;
|
||||
end;
|
||||
end;
|
||||
temprefn:
|
||||
begin
|
||||
if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
|
||||
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(ttemprefnode(n).tempinfo^.location.register = rr^.old) then
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
{ it's possible a 128 bit location was shifted and/xor typecasted }
|
||||
{ in a 64 bit value, so only 1 register was left in the location }
|
||||
if (ttemprefnode(n).tempinfo^.location.size in [OS_128,OS_S128]) then
|
||||
if (ttemprefnode(n).tempinfo^.location.register128.reghi = rr^.oldhi) then
|
||||
ttemprefnode(n).tempinfo^.location.register128.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$else cpu64bitalu}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
|
||||
if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
|
||||
ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bitalu}
|
||||
ttemprefnode(n).tempinfo^.location.register := 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;
|
||||
|
||||
|
||||
procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
var
|
||||
rr: treplaceregrec;
|
||||
varloc : tai_varloc;
|
||||
begin
|
||||
{$ifdef jvm}
|
||||
exit;
|
||||
{$endif}
|
||||
if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
|
||||
([fc_inflowcontrol,fc_gotolabel,fc_lefthandled] * flowcontrol <> []) then
|
||||
exit;
|
||||
rr.old := n.location.register;
|
||||
rr.ressym := nil;
|
||||
rr.sym := nil;
|
||||
rr.oldhi := NR_NO;
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
begin
|
||||
rr.oldhi := n.location.register128.reghi;
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
end
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
rr.oldhi := n.location.register64.reghi;
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
else
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ self is implicitly returned from constructors, even if there are no
|
||||
references to it; additionally, funcretsym is not set for constructor
|
||||
procdefs }
|
||||
if (current_procinfo.procdef.proctypeoption=potype_constructor) then
|
||||
rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
|
||||
else if not is_void(current_procinfo.procdef.returndef) and
|
||||
assigned(current_procinfo.procdef.funcretsym) and
|
||||
(tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
|
||||
rr.ressym:=current_procinfo.procdef.funcretsym;
|
||||
|
||||
if not foreachnodestatic(n,@doreplace,@rr) then
|
||||
exit;
|
||||
|
||||
if reload then
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
cg128.a_load128_reg_reg(list,n.location.register128,joinreg128(rr.new,rr.newhi))
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
cg.a_loadfpu_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new,nil);
|
||||
else
|
||||
internalerror(2006090920);
|
||||
end;
|
||||
|
||||
{ now that we've change the loadn/temp, also change the node result location }
|
||||
{$ifdef cpu64bitalu}
|
||||
if (n.location.size in [OS_128,OS_S128]) then
|
||||
begin
|
||||
n.location.register128.reglo := rr.new;
|
||||
n.location.register128.reghi := rr.newhi;
|
||||
if assigned(rr.sym) and
|
||||
((rr.sym.currentregloc.register<>rr.new) or
|
||||
(rr.sym.currentregloc.registerhi<>rr.newhi)) then
|
||||
begin
|
||||
varloc:=tai_varloc.create128(rr.sym,rr.new,rr.newhi);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
rr.sym.currentregloc.registerHI:=rr.newhi;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end
|
||||
else
|
||||
{$else cpu64bitalu}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
n.location.register64.reglo := rr.new;
|
||||
n.location.register64.reghi := rr.newhi;
|
||||
if assigned(rr.sym) and
|
||||
((rr.sym.currentregloc.register<>rr.new) or
|
||||
(rr.sym.currentregloc.registerhi<>rr.newhi)) then
|
||||
begin
|
||||
varloc:=tai_varloc.create64(rr.sym,rr.new,rr.newhi);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
rr.sym.currentregloc.registerHI:=rr.newhi;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitalu}
|
||||
begin
|
||||
n.location.register := rr.new;
|
||||
if assigned(rr.sym) and (rr.sym.currentregloc.register<>rr.new) then
|
||||
begin
|
||||
varloc:=tai_varloc.create(rr.sym,rr.new);
|
||||
varloc.oldlocation:=rr.sym.currentregloc.register;
|
||||
rr.sym.currentregloc.register:=rr.new;
|
||||
list.concat(varloc);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_free_symtable(list:TAsmList;st:TSymtable);
|
||||
var
|
||||
i : longint;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user