summaryrefslogtreecommitdiff
path: root/compiler/nmat.pas
diff options
context:
space:
mode:
authorflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2011-10-30 15:14:21 +0000
committerflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2011-10-30 15:14:21 +0000
commit0b3649822f563bd0e0f5f1269e48e6a2086fb50e (patch)
tree868d883074e0d7069abde0c44b889664b4037a0d /compiler/nmat.pas
parentf7352503f562e801a31320a511c7a9248a77f93d (diff)
downloadfpc-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.pas62
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;