diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-10-30 15:14:21 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-10-30 15:14:21 +0000 |
commit | 0b3649822f563bd0e0f5f1269e48e6a2086fb50e (patch) | |
tree | 868d883074e0d7069abde0c44b889664b4037a0d /compiler/nmat.pas | |
parent | f7352503f562e801a31320a511c7a9248a77f93d (diff) | |
download | fpc-0b3649822f563bd0e0f5f1269e48e6a2086fb50e.tar.gz |
* factored load node flags out of node flags to gain space
+ implemented iso mode mod, resolves #17685
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@19558 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/nmat.pas')
-rw-r--r-- | compiler/nmat.pas | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/compiler/nmat.pas b/compiler/nmat.pas index 3efd33e482..3a87271ad5 100644 --- a/compiler/nmat.pas +++ b/compiler/nmat.pas @@ -102,7 +102,7 @@ implementation defutil, htypechk,pass_1, cgbase, - ncon,ncnv,ncal,nadd, + ncon,ncnv,ncal,nadd,nld,nbas,nflw, nutils; {**************************************************************************** @@ -133,6 +133,13 @@ implementation { recover } tordconstnode(right).value := 1; end; + if (nf_isomod in flags) and + (rv<=0) then + begin + Message(cg_e_mod_only_defined_for_pos_quotient); + { recover } + tordconstnode(right).value := 1; + end; end; if is_constintnode(right) and is_constintnode(left) then @@ -142,7 +149,18 @@ implementation case nodetype of modn: - result:=create_simplified_ord_const(lv mod rv,resultdef,forinline); + if nf_isomod in flags then + begin + if lv>=0 then + result:=create_simplified_ord_const(lv mod rv,resultdef,forinline) + else + if ((-lv) mod rv)=0 then + result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline) + else + result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline); + end + else + result:=create_simplified_ord_const(lv mod rv,resultdef,forinline); divn: result:=create_simplified_ord_const(lv div rv,resultdef,forinline); end; @@ -152,8 +170,12 @@ implementation function tmoddivnode.pass_typecheck:tnode; var + else_block, hp,t : tnode; rd,ld : torddef; + else_statements, + statements : tstatementnode; + result_data : ttempcreatenode; begin result:=nil; typecheckpass(left); @@ -287,6 +309,42 @@ implementation include(hp.flags,nf_is_currency); result:=hp; end; + + if (nodetype=modn) and (nf_isomod in flags) then + begin + result:=internalstatements(statements); + else_block:=internalstatements(else_statements); + result_data:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true); + + { right <=0? } + addstatement(statements,cifnode.create(caddnode.create(lten,right.getcopy,cordconstnode.create(0,resultdef,false)), + { then: result:=left mod right } + ccallnode.createintern('fpc_divbyzero',nil), + nil + )); + + { prepare else block } + { result:=(-left) mod right } + addstatement(else_statements,cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,cunaryminusnode.create(left.getcopy),right.getcopy))); + { result<>0? } + addstatement(else_statements,cifnode.create(caddnode.create(unequaln,ctemprefnode.create(result_data),cordconstnode.create(0,resultdef,false)), + { then: result:=right-result } + cassignmentnode.create(ctemprefnode.create(result_data),caddnode.create(subn,right.getcopy,ctemprefnode.create(result_data))), + nil + )); + + addstatement(statements,result_data); + { if left>=0 } + addstatement(statements,cifnode.create(caddnode.create(gten,left.getcopy,cordconstnode.create(0,resultdef,false)), + { then: result:=left mod right } + cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,left.getcopy,right.getcopy)), + { else block } + else_block + )); + + addstatement(statements,ctempdeletenode.create_normal_temp(result_data)); + addstatement(statements,ctemprefnode.create(result_data)); + end; end; |