diff --git a/compiler/ncal.pas b/compiler/ncal.pas index 5d493b30a7..c242d6916c 100644 --- a/compiler/ncal.pas +++ b/compiler/ncal.pas @@ -2307,7 +2307,7 @@ implementation exit; { remove possible typecasts } - realassignmenttarget:=aktassignmentnode.left.actualtargetnode; + realassignmenttarget:=actualtargetnode(@aktassignmentnode.left)^; { when it is not passed in a parameter it will only be used after the function call } @@ -2327,7 +2327,7 @@ implementation point } if assigned(methodpointer) and - realassignmenttarget.isequal(methodpointer.actualtargetnode) then + realassignmenttarget.isequal(actualtargetnode(@methodpointer)^) then exit; { when we substitute a function result inside an inlined function, @@ -3169,7 +3169,7 @@ implementation { skip (absolute and other simple) type conversions -- only now, because the checks above have to take type conversions into e.g. class reference types account } - hpt:=hpt.actualtargetnode; + hpt:=actualtargetnode(@hpt)^; { R.Init then R will be initialized by the constructor, Also allow it for simple loads } diff --git a/compiler/ncgmem.pas b/compiler/ncgmem.pas index aa2993f52f..ae659a0ff1 100644 --- a/compiler/ncgmem.pas +++ b/compiler/ncgmem.pas @@ -803,7 +803,7 @@ implementation var offsetdec, extraoffset : aint; - t : tnode; + rightp : pnode; otl,ofl : tasmlabel; newsize : tcgsize; mulsize, @@ -981,34 +981,26 @@ implementation not is_packed_array(left.resultdef) then begin extraoffset:=0; - if (right.nodetype=addn) then + rightp:=actualtargetnode(@right); + if rightp^.nodetype=addn then begin - if taddnode(right).right.nodetype=ordconstn then + if taddnode(rightp^).right.nodetype=ordconstn then begin - extraoffset:=tordconstnode(taddnode(right).right).value.svalue; - t:=taddnode(right).left; - taddnode(right).left:=nil; - right.free; - right:=t; + extraoffset:=tordconstnode(taddnode(rightp^).right).value.svalue; + replacenode(rightp^,taddnode(rightp^).left); end - else if taddnode(right).left.nodetype=ordconstn then + else if taddnode(rightp^).left.nodetype=ordconstn then begin - extraoffset:=tordconstnode(taddnode(right).left).value.svalue; - t:=taddnode(right).right; - taddnode(right).right:=nil; - right.free; - right:=t; + extraoffset:=tordconstnode(taddnode(rightp^).left).value.svalue; + replacenode(rightp^,taddnode(rightp^).right); end; end - else if (right.nodetype=subn) then + else if rightp^.nodetype=subn then begin - if taddnode(right).right.nodetype=ordconstn then + if taddnode(rightp^).right.nodetype=ordconstn then begin - extraoffset:=-tordconstnode(taddnode(right).right).value.svalue; - t:=taddnode(right).left; - taddnode(right).left:=nil; - right.free; - right:=t; + extraoffset:=-tordconstnode(taddnode(rightp^).right).value.svalue; + replacenode(rightp^,taddnode(rightp^).left); end; end; inc(location.reference.offset, diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index 6a8a6acd57..98c1018c14 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -48,7 +48,6 @@ interface procedure buildderefimpl;override; procedure derefimpl;override; function dogetcopy : tnode;override; - function actualtargetnode: tnode;override; procedure printnodeinfo(var t : text);override; function pass_1 : tnode;override; function pass_typecheck:tnode;override; @@ -2101,15 +2100,6 @@ implementation end; - function ttypeconvnode.actualtargetnode: tnode; - begin - result:=self; - while (result.nodetype=typeconvn) and - ttypeconvnode(result).retains_value_location do - result:=ttypeconvnode(result).left; - end; - - function ttypeconvnode.pass_typecheck:tnode; var diff --git a/compiler/node.pas b/compiler/node.pas index 896006a9e8..4d61900d61 100644 --- a/compiler/node.pas +++ b/compiler/node.pas @@ -367,10 +367,6 @@ interface { does the real copying of a node } function dogetcopy : tnode;virtual; - { returns the real loadn/temprefn a node refers to, - skipping (absolute) equal type conversions } - function actualtargetnode: tnode;virtual; - procedure insertintolist(l : tnodelist);virtual; { writes a node for debugging purpose, shouldn't be called } { direct, because there is no test for nil, use printnode } @@ -952,12 +948,6 @@ implementation end; - function tnode.actualtargetnode: tnode; - begin - result:=self; - end; - - procedure tnode.insertintolist(l : tnodelist); begin end; diff --git a/compiler/nutils.pas b/compiler/nutils.pas index 9b07c3c8cc..4560d03827 100644 --- a/compiler/nutils.pas +++ b/compiler/nutils.pas @@ -82,6 +82,7 @@ interface { tries to simplify the given node after inlining } procedure doinlinesimplify(var n : tnode); + { creates an ordinal constant, optionally based on the result from a simplify operation: normally the type is the smallest integer type that can hold the value, but when inlining the "def" will be used instead, @@ -122,6 +123,18 @@ interface if no dirty tricks like buffer overflows or pointer magic are used } function is_const(node : tnode) : boolean; + { returns a pointer to the real node a node refers to, + skipping (absolute) equal type conversions. Returning + a pointer allows the caller to move/remove/replace this + node + } + function actualtargetnode(n : pnode) : pnode; + + { moves src into dest, before doing so, right is set to nil and dest is freed. + Because dest and src are var parameters, this can be done inline in an existing + node tree } + procedure replacenode(var dest,src : tnode); + implementation uses @@ -1144,4 +1157,30 @@ implementation result:=(node.nodetype=temprefn) and (ti_const in ttemprefnode(node).tempinfo^.flags) end; + + function actualtargetnode(n : pnode) : pnode; + begin + result:=n; + case n^.nodetype of + typeconvn: + if ttypeconvnode(n^).retains_value_location then + result:=actualtargetnode(@ttypeconvnode(n^).left); + end; + end; + + + procedure replacenode(var dest,src : tnode); + var + t : tnode; + begin + t:=src; + { set src nil before free'ing dest because + src could be part of dest } + src:=nil; + dest.Free; + dest:=t; + end; + + + end. diff --git a/compiler/optcse.pas b/compiler/optcse.pas index 18dd70d191..1aff48ba70 100644 --- a/compiler/optcse.pas +++ b/compiler/optcse.pas @@ -151,7 +151,7 @@ unit optcse; assigned(n.resultdef) and ( { regable expressions } - (n.actualtargetnode.flags*[nf_write,nf_modify]=[]) and + (actualtargetnode(@n)^.flags*[nf_write,nf_modify]=[]) and ((tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) and { is_int/fpuregable allows arrays and records to be in registers, cse cannot handle this } (not(n.resultdef.typ in [arraydef,recorddef])) and