diff options
Diffstat (limited to 'compiler/ninl.pas')
-rw-r--r-- | compiler/ninl.pas | 207 |
1 files changed, 109 insertions, 98 deletions
diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 1185675d9f..a81bdfe459 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -66,6 +66,7 @@ interface function first_trunc_real: tnode; virtual; function first_int_real: tnode; virtual; function first_abs_long: tnode; virtual; + function first_IncDec: tnode; virtual; function first_IncludeExclude: tnode; virtual; function first_get_frame: tnode; virtual; function first_setlength: tnode; virtual; @@ -2075,7 +2076,7 @@ implementation in_const_swap_long : hp:=cordconstnode.create((vl and $ffff) shl 16+(vl shr 16),left.resultdef,true); in_const_swap_qword : - hp:=cordconstnode.create((vl and $ffff) shl 32+(vl shr 32),left.resultdef,true); + hp:=cordconstnode.create((vl and $ffffffff) shl 32+(vl shr 32),left.resultdef,true); in_const_ptr: begin {Don't construct pointers from negative values.} @@ -3280,11 +3281,8 @@ implementation function tinlinenode.pass_1 : tnode; var - hp,hpp,resultnode : tnode; + hp: tnode; shiftconst: longint; - tempnode: ttempcreatenode; - newstatement: tstatementnode; - newblock: tblocknode; begin result:=nil; @@ -3419,99 +3417,7 @@ implementation in_inc_x, in_dec_x: begin - expectloc:=LOC_VOID; - - { range/overflow checking doesn't work properly } - { with the inc/dec code that's generated (JM) } - if ((current_settings.localswitches * [cs_check_overflow,cs_check_range] <> []) and - { No overflow check for pointer operations, because inc(pointer,-1) will always - trigger an overflow. For uint32 it works because then the operation is done - in 64bit. Range checking is not applicable to pointers either } - (tcallparanode(left).left.resultdef.typ<>pointerdef)) -{$ifdef jvm} - { enums are class instances on the JVM -> special treatment } - or (tcallparanode(left).left.resultdef.typ=enumdef) -{$endif} - then - { convert to simple add (JM) } - begin - newblock := internalstatements(newstatement); - { extra parameter? } - if assigned(tcallparanode(left).right) then - begin - { Yes, use for add node } - hpp := tcallparanode(tcallparanode(left).right).left; - tcallparanode(tcallparanode(left).right).left := nil; - if assigned(tcallparanode(tcallparanode(left).right).right) then - CGMessage(parser_e_illegal_expression); - end - else - begin - { no, create constant 1 } - hpp := cordconstnode.create(1,tcallparanode(left).left.resultdef,false); - end; - typecheckpass(hpp); - - { make sure we don't call functions part of the left node twice (and generally } - { optimize the code generation) } - { Storing address is not always an optimization: alignment of left is not known - at this point, so we must assume the worst and use an unaligned pointer. - This results in larger and slower code on alignment-sensitive targets. - Therefore the complexity condition below is questionable, maybe just filtering - out calls with "= NODE_COMPLEXITY_INF" is sufficient. - Value of 3 corresponds to subscript nodes, i.e. record field. } - if node_complexity(tcallparanode(left).left) > 3 then - begin - tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true); - addstatement(newstatement,tempnode); - addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode), - caddrnode.create_internal(tcallparanode(left).left.getcopy))); - hp := cderefnode.create(ctemprefnode.create(tempnode)); - inserttypeconv_internal(hp,tcallparanode(left).left.resultdef); - end - else - begin - hp := tcallparanode(left).left.getcopy; - tempnode := nil; - end; - - resultnode := hp.getcopy; - { avoid type errors from the addn/subn } - if not is_integer(resultnode.resultdef) then - begin - inserttypeconv_internal(hp,sinttype); - inserttypeconv_internal(hpp,sinttype); - end; - - { addition/substraction depending on inc/dec } - if inlinenumber = in_inc_x then - hpp := caddnode.create(addn,hp,hpp) - else - hpp := caddnode.create(subn,hp,hpp); - { assign result of addition } - if not(is_integer(resultnode.resultdef)) then - inserttypeconv(hpp,corddef.create( -{$ifdef cpu64bitaddr} - s64bit, -{$else cpu64bitaddr} - s32bit, -{$endif cpu64bitaddr} - get_min_value(resultnode.resultdef), - get_max_value(resultnode.resultdef))) - else - inserttypeconv(hpp,resultnode.resultdef); - { avoid any possible warnings } - inserttypeconv_internal(hpp,resultnode.resultdef); - - addstatement(newstatement,cassignmentnode.create(resultnode,hpp)); - { deallocate the temp } - if assigned(tempnode) then - addstatement(newstatement,ctempdeletenode.create(tempnode)); - { firstpass it } - firstpass(tnode(newblock)); - { return new node } - result := newblock; - end; + result:=first_IncDec; end; in_include_x_y, @@ -3853,6 +3759,110 @@ implementation end; + function tinlinenode.first_IncDec: tnode; + var + hp,hpp,resultnode : tnode; + tempnode: ttempcreatenode; + newstatement: tstatementnode; + newblock: tblocknode; + begin + expectloc:=LOC_VOID; + result:=nil; + + { range/overflow checking doesn't work properly } + { with the inc/dec code that's generated (JM) } + if ((current_settings.localswitches * [cs_check_overflow,cs_check_range] <> []) and + { No overflow check for pointer operations, because inc(pointer,-1) will always + trigger an overflow. For uint32 it works because then the operation is done + in 64bit. Range checking is not applicable to pointers either } + (tcallparanode(left).left.resultdef.typ<>pointerdef)) +{$ifdef jvm} + { enums are class instances on the JVM -> special treatment } + or (tcallparanode(left).left.resultdef.typ=enumdef) +{$endif} + then + { convert to simple add (JM) } + begin + newblock := internalstatements(newstatement); + { extra parameter? } + if assigned(tcallparanode(left).right) then + begin + { Yes, use for add node } + hpp := tcallparanode(tcallparanode(left).right).left; + tcallparanode(tcallparanode(left).right).left := nil; + if assigned(tcallparanode(tcallparanode(left).right).right) then + CGMessage(parser_e_illegal_expression); + end + else + begin + { no, create constant 1 } + hpp := cordconstnode.create(1,tcallparanode(left).left.resultdef,false); + end; + typecheckpass(hpp); + + { make sure we don't call functions part of the left node twice (and generally } + { optimize the code generation) } + { Storing address is not always an optimization: alignment of left is not known + at this point, so we must assume the worst and use an unaligned pointer. + This results in larger and slower code on alignment-sensitive targets. + Therefore the complexity condition below is questionable, maybe just filtering + out calls with "= NODE_COMPLEXITY_INF" is sufficient. + Value of 3 corresponds to subscript nodes, i.e. record field. } + if node_complexity(tcallparanode(left).left) > 3 then + begin + tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true); + addstatement(newstatement,tempnode); + addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode), + caddrnode.create_internal(tcallparanode(left).left.getcopy))); + hp := cderefnode.create(ctemprefnode.create(tempnode)); + inserttypeconv_internal(hp,tcallparanode(left).left.resultdef); + end + else + begin + hp := tcallparanode(left).left.getcopy; + tempnode := nil; + end; + + resultnode := hp.getcopy; + { avoid type errors from the addn/subn } + if not is_integer(resultnode.resultdef) then + begin + inserttypeconv_internal(hp,sinttype); + inserttypeconv_internal(hpp,sinttype); + end; + + { addition/substraction depending on inc/dec } + if inlinenumber = in_inc_x then + hpp := caddnode.create(addn,hp,hpp) + else + hpp := caddnode.create(subn,hp,hpp); + { assign result of addition } + if not(is_integer(resultnode.resultdef)) then + inserttypeconv(hpp,corddef.create( +{$ifdef cpu64bitaddr} + s64bit, +{$else cpu64bitaddr} + s32bit, +{$endif cpu64bitaddr} + get_min_value(resultnode.resultdef), + get_max_value(resultnode.resultdef))) + else + inserttypeconv(hpp,resultnode.resultdef); + { avoid any possible warnings } + inserttypeconv_internal(hpp,resultnode.resultdef); + + addstatement(newstatement,cassignmentnode.create(resultnode,hpp)); + { deallocate the temp } + if assigned(tempnode) then + addstatement(newstatement,ctempdeletenode.create(tempnode)); + { firstpass it } + firstpass(tnode(newblock)); + { return new node } + result := newblock; + end; + end; + + function tinlinenode.first_IncludeExclude: tnode; begin result:=nil; @@ -4107,6 +4117,7 @@ implementation {$endif} result:=cifnode.create(cnotnode.create(tcallparanode(left).left), ccallnode.createintern('fpc_assert',paras),nil); + include(result.flags,nf_internal); tcallparanode(left).left:=nil; tcallparanode(left).right:=nil; end; |