nmat.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. {
  2. Copyright (c) 2000-2005 by Florian Klaempfl
  3. Type checking and register allocation for math nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nmat;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node;
  22. type
  23. tmoddivnode = class(tbinopnode)
  24. function pass_1 : tnode;override;
  25. function pass_typecheck:tnode;override;
  26. function simplify(forinline : boolean) : tnode;override;
  27. protected
  28. { override the following if you want to implement }
  29. { parts explicitely in the code generator (JM) }
  30. function use_moddiv64bitint_helper: boolean; virtual;
  31. function first_moddiv64bitint: tnode; virtual;
  32. function firstoptimize: tnode; virtual;
  33. function first_moddivint: tnode; virtual;
  34. end;
  35. tmoddivnodeclass = class of tmoddivnode;
  36. tshlshrnode = class(tbinopnode)
  37. function pass_1 : tnode;override;
  38. function pass_typecheck:tnode;override;
  39. function simplify(forinline : boolean) : tnode;override;
  40. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  41. { override the following if you want to implement }
  42. { parts explicitely in the code generator (CEC)
  43. Should return nil, if everything will be handled
  44. in the code generator
  45. }
  46. function first_shlshr64bitint: tnode; virtual;
  47. {$endif not cpu64bitalu and not cpuhighleveltarget}
  48. end;
  49. tshlshrnodeclass = class of tshlshrnode;
  50. tunaryminusnode = class(tunarynode)
  51. constructor create(expr : tnode);virtual;
  52. function pass_1 : tnode;override;
  53. function pass_typecheck:tnode;override;
  54. function simplify(forinline : boolean) : tnode;override;
  55. end;
  56. tunaryminusnodeclass = class of tunaryminusnode;
  57. tunaryplusnode = class(tunarynode)
  58. constructor create(expr : tnode);virtual;
  59. function pass_1 : tnode;override;
  60. function pass_typecheck:tnode;override;
  61. end;
  62. tunaryplusnodeclass = class of tunaryplusnode;
  63. tnotnode = class(tunarynode)
  64. constructor create(expr : tnode);virtual;
  65. function pass_1 : tnode;override;
  66. function pass_typecheck:tnode;override;
  67. function simplify(forinline : boolean) : tnode;override;
  68. {$ifdef state_tracking}
  69. function track_state_pass(exec_known:boolean):boolean;override;
  70. {$endif}
  71. end;
  72. tnotnodeclass = class of tnotnode;
  73. var
  74. cmoddivnode : tmoddivnodeclass = tmoddivnode;
  75. cshlshrnode : tshlshrnodeclass = tshlshrnode;
  76. cunaryminusnode : tunaryminusnodeclass = tunaryminusnode;
  77. cunaryplusnode : tunaryplusnodeclass = tunaryplusnode;
  78. cnotnode : tnotnodeclass = tnotnode;
  79. implementation
  80. uses
  81. systems,
  82. verbose,globals,cutils,compinnr,
  83. globtype,constexp,
  84. symconst,symtype,symdef,
  85. defcmp,defutil,
  86. htypechk,pass_1,
  87. cgbase,
  88. ncon,ncnv,ncal,nadd,nld,nbas,nflw,ninl,
  89. nutils;
  90. {****************************************************************************
  91. TMODDIVNODE
  92. ****************************************************************************}
  93. function tmoddivnode.simplify(forinline : boolean):tnode;
  94. var
  95. rv,lv : tconstexprint;
  96. begin
  97. result:=nil;
  98. if is_constintnode(right) then
  99. begin
  100. rv:=tordconstnode(right).value;
  101. if rv = 1 then
  102. begin
  103. case nodetype of
  104. modn:
  105. result := cordconstnode.create(0,left.resultdef,true);
  106. divn:
  107. result := left.getcopy;
  108. else
  109. internalerror(2019050518);
  110. end;
  111. exit;
  112. end;
  113. if rv = 0 then
  114. begin
  115. { if the node is derived from a generic const parameter
  116. then don't issue an error }
  117. if not (nf_generic_para in flags) then
  118. Message(parser_e_division_by_zero);
  119. { recover }
  120. tordconstnode(right).value := 1;
  121. end;
  122. { the following simplification is also required for correctness
  123. on x86, as its transformation of divisions by constants to
  124. multiplications and shifts does not handle -1 correctly }
  125. if (rv=-1) and
  126. (nodetype=divn) then
  127. begin
  128. result:=cunaryminusnode.create(left);
  129. left:=nil;
  130. exit;
  131. end;
  132. if (nf_isomod in flags) and
  133. (rv<=0) then
  134. begin
  135. Message(cg_e_mod_only_defined_for_pos_quotient);
  136. { recover }
  137. tordconstnode(right).value := 1;
  138. end
  139. else if (rv=-1) and
  140. (nodetype=modn) then
  141. begin
  142. result:=cordconstnode.create(0,left.resultdef,true);
  143. left:=nil;
  144. exit;
  145. end;
  146. end;
  147. if is_constintnode(right) and is_constintnode(left) then
  148. begin
  149. rv:=tordconstnode(right).value;
  150. lv:=tordconstnode(left).value;
  151. case nodetype of
  152. modn:
  153. if nf_isomod in flags then
  154. begin
  155. if lv>=0 then
  156. result:=create_simplified_ord_const(lv mod rv,resultdef,forinline,false)
  157. else
  158. if ((-lv) mod rv)=0 then
  159. result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline,false)
  160. else
  161. result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline,false);
  162. end
  163. else
  164. result:=create_simplified_ord_const(lv mod rv,resultdef,forinline,false);
  165. divn:
  166. result:=create_simplified_ord_const(lv div rv,resultdef,forinline,cs_check_overflow in localswitches);
  167. else
  168. internalerror(2019050519);
  169. end;
  170. end;
  171. end;
  172. function tmoddivnode.use_moddiv64bitint_helper: boolean;
  173. begin
  174. { not with an ifdef around the call to this routine, because e.g. the
  175. Java VM has a signed 64 bit division opcode, but not an unsigned
  176. one }
  177. {$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
  178. result:=false;
  179. {$else cpu64bitalu or cpuhighleveltarget}
  180. result:=
  181. (left.resultdef.typ=orddef) and
  182. (right.resultdef.typ=orddef) and
  183. { include currency as well }
  184. (is_64bit(left.resultdef) or is_64bit(right.resultdef));
  185. {$endif cpu64bitalu or cpuhighleveltarget}
  186. end;
  187. function tmoddivnode.pass_typecheck:tnode;
  188. var
  189. else_block,
  190. hp,t : tnode;
  191. rd,ld : torddef;
  192. else_statements,
  193. statements : tstatementnode;
  194. result_data : ttempcreatenode;
  195. nd : torddef;
  196. begin
  197. result:=nil;
  198. typecheckpass(left);
  199. typecheckpass(right);
  200. { avoid any problems with type parameters later on }
  201. if is_typeparam(left.resultdef) or is_typeparam(right.resultdef) then
  202. begin
  203. resultdef:=cundefinedtype;
  204. exit;
  205. end;
  206. set_varstate(left,vs_read,[vsf_must_be_valid]);
  207. set_varstate(right,vs_read,[vsf_must_be_valid]);
  208. if codegenerror then
  209. exit;
  210. { tp procvar support }
  211. maybe_call_procvar(left,true);
  212. maybe_call_procvar(right,true);
  213. { allow operator overloading }
  214. t:=self;
  215. if isbinaryoverloaded(t,[]) then
  216. begin
  217. result:=t;
  218. exit;
  219. end;
  220. { we need 2 orddefs always }
  221. if (left.resultdef.typ<>orddef) then
  222. inserttypeconv(left,sinttype);
  223. if (right.resultdef.typ<>orddef) then
  224. inserttypeconv(right,sinttype);
  225. if codegenerror then
  226. exit;
  227. { Try only now to simply constant
  228. as otherwise you might create
  229. tconstnode with return type that are
  230. not compatible with tconst node
  231. as in bug report 21566 PM }
  232. result:=simplify(false);
  233. if assigned(result) then
  234. exit;
  235. rd:=torddef(right.resultdef);
  236. ld:=torddef(left.resultdef);
  237. { if one operand is a cardinal and the other is a positive constant, convert the }
  238. { constant to a cardinal as well so we don't have to do a 64bit division (JM) }
  239. { Do the same for qwords and positive constants as well, otherwise things like }
  240. { "qword mod 10" are evaluated with int64 as result, which is wrong if the }
  241. { "qword" was > high(int64) (JM) }
  242. { Additionally, do the same for cardinal/qwords and other positive types, but }
  243. { always in a way that a smaller type is converted to a bigger type }
  244. { (webtbs/tw8870) }
  245. if (rd.ordtype in [u8bit,u16bit,u32bit,u64bit]) and
  246. ((is_constintnode(left) and
  247. (tordconstnode(left).value >= 0) and
  248. (tordconstnode(left).value <= get_max_value(rd))) or
  249. (not is_signed(ld) and
  250. (rd.size >= ld.size))) then
  251. begin
  252. inserttypeconv(left,right.resultdef);
  253. ld:=torddef(left.resultdef);
  254. end;
  255. if (ld.ordtype in [u8bit,u16bit,u32bit,u64bit]) and
  256. ((is_constintnode(right) and
  257. (tordconstnode(right).value >= 0) and
  258. (tordconstnode(right).value <= get_max_value(ld))) or
  259. (not is_signed(rd) and
  260. (ld.size >= rd.size))) then
  261. begin
  262. inserttypeconv(right,left.resultdef);
  263. rd:=torddef(right.resultdef);
  264. end;
  265. { when there is one currency value, everything is done
  266. using currency }
  267. if (ld.ordtype=scurrency) or
  268. (rd.ordtype=scurrency) then
  269. begin
  270. if (ld.ordtype<>scurrency) then
  271. inserttypeconv(left,s64currencytype);
  272. if (rd.ordtype<>scurrency) then
  273. inserttypeconv(right,s64currencytype);
  274. resultdef:=left.resultdef;
  275. end
  276. else
  277. { when there is one 64bit value, everything is done
  278. in 64bit }
  279. if (is_64bitint(left.resultdef) or
  280. is_64bitint(right.resultdef)) then
  281. begin
  282. if is_signed(rd) or is_signed(ld) then
  283. begin
  284. if (ld.ordtype<>s64bit) then
  285. inserttypeconv(left,s64inttype);
  286. if (rd.ordtype<>s64bit) then
  287. inserttypeconv(right,s64inttype);
  288. end
  289. else
  290. begin
  291. if (ld.ordtype<>u64bit) then
  292. inserttypeconv(left,u64inttype);
  293. if (rd.ordtype<>u64bit) then
  294. inserttypeconv(right,u64inttype);
  295. end;
  296. resultdef:=left.resultdef;
  297. end
  298. else
  299. { is there a larger than the native int? }
  300. if is_oversizedint(ld) or is_oversizedint(rd) then
  301. begin
  302. nd:=get_common_intdef(ld,rd,false);
  303. if (ld.ordtype<>nd.ordtype) then
  304. inserttypeconv(left,nd);
  305. if (rd.ordtype<>nd.ordtype) then
  306. inserttypeconv(right,nd);
  307. resultdef:=left.resultdef;
  308. end
  309. else
  310. { when mixing unsigned and signed native ints, convert everything to a larger signed type (JM) }
  311. if (is_nativeuint(rd) and
  312. is_signed(ld)) or
  313. (is_nativeuint(ld) and
  314. is_signed(rd)) then
  315. begin
  316. CGMessage(type_h_mixed_signed_unsigned);
  317. { get a signed int, larger than the native int }
  318. nd:=get_common_intdef(torddef(sinttype),torddef(uinttype),false);
  319. if (ld.ordtype<>nd.ordtype) then
  320. inserttypeconv(left,nd);
  321. if (rd.ordtype<>nd.ordtype) then
  322. inserttypeconv(right,nd);
  323. resultdef:=left.resultdef;
  324. end
  325. else
  326. begin
  327. { Make everything always default singed int }
  328. if not(rd.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  329. inserttypeconv(right,sinttype);
  330. if not(ld.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  331. inserttypeconv(left,sinttype);
  332. resultdef:=right.resultdef;
  333. end;
  334. { when the result is currency we need some extra code for
  335. division. this should not be done when the divn node is
  336. created internally }
  337. if (nodetype=divn) and
  338. not(nf_is_currency in flags) and
  339. is_currency(resultdef) then
  340. begin
  341. hp:=caddnode.create(muln,getcopy,cordconstnode.create(10000,s64currencytype,false));
  342. include(hp.flags,nf_is_currency);
  343. result:=hp;
  344. end;
  345. if (nodetype=modn) and (nf_isomod in flags) then
  346. begin
  347. result:=internalstatements(statements);
  348. else_block:=internalstatements(else_statements);
  349. result_data:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  350. { right <=0? }
  351. addstatement(statements,cifnode.create_internal(caddnode.create_internal(lten,right.getcopy,cordconstnode.create(0,resultdef,false)),
  352. { then: result:=left mod right }
  353. ccallnode.createintern('fpc_divbyzero',nil),
  354. nil
  355. ));
  356. { prepare else block }
  357. { result:=(-left) mod right }
  358. addstatement(else_statements,cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,cunaryminusnode.create(left.getcopy),right.getcopy)));
  359. { result<>0? }
  360. addstatement(else_statements,cifnode.create_internal(caddnode.create_internal(unequaln,ctemprefnode.create(result_data),cordconstnode.create(0,resultdef,false)),
  361. { then: result:=right-result }
  362. cassignmentnode.create_internal(ctemprefnode.create(result_data),caddnode.create_internal(subn,right.getcopy,ctemprefnode.create(result_data))),
  363. nil
  364. ));
  365. addstatement(statements,result_data);
  366. { if left>=0 }
  367. addstatement(statements,cifnode.create_internal(caddnode.create_internal(gten,left.getcopy,cordconstnode.create(0,resultdef,false)),
  368. { then: result:=left mod right }
  369. cassignmentnode.create_internal(ctemprefnode.create(result_data),cmoddivnode.create(modn,left.getcopy,right.getcopy)),
  370. { else block }
  371. else_block
  372. ));
  373. addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
  374. addstatement(statements,ctemprefnode.create(result_data));
  375. end;
  376. end;
  377. function tmoddivnode.first_moddivint: tnode;
  378. {$ifdef cpuneedsdivhelper}
  379. var
  380. procname: string[31];
  381. begin
  382. result := nil;
  383. { otherwise create a call to a helper }
  384. if nodetype = divn then
  385. procname := 'fpc_div_'
  386. else
  387. procname := 'fpc_mod_';
  388. { only qword needs the unsigned code, the
  389. signed code is also used for currency }
  390. case torddef(resultdef).ordtype of
  391. u8bit:
  392. procname := procname + 'byte';
  393. s8bit:
  394. procname := procname + 'shortint';
  395. u16bit:
  396. procname := procname + 'word';
  397. s16bit:
  398. procname := procname + 'smallint';
  399. u32bit:
  400. procname := procname + 'dword';
  401. s32bit:
  402. procname := procname + 'longint';
  403. scurrency:
  404. procname := procname + 'currency';
  405. else
  406. internalerror(2015070501);
  407. end;
  408. result := ccallnode.createintern(procname,ccallparanode.create(left,
  409. ccallparanode.create(right,nil)));
  410. left := nil;
  411. right := nil;
  412. firstpass(result);
  413. if result.resultdef.typ<>orddef then
  414. internalerror(2013031701);
  415. if resultdef.typ<>orddef then
  416. internalerror(2013031701);
  417. if torddef(result.resultdef).ordtype <> torddef(resultdef).ordtype then
  418. inserttypeconv(result,resultdef);
  419. end;
  420. {$else cpuneedsdivhelper}
  421. begin
  422. result:=nil;
  423. end;
  424. {$endif cpuneedsdiv32helper}
  425. function tmoddivnode.first_moddiv64bitint: tnode;
  426. var
  427. procname: string[31];
  428. begin
  429. result := nil;
  430. { when currency is used set the result of the
  431. parameters to s64bit, so they are not converted }
  432. if is_currency(resultdef) then
  433. begin
  434. left.resultdef:=s64inttype;
  435. right.resultdef:=s64inttype;
  436. end;
  437. { otherwise create a call to a helper }
  438. if nodetype = divn then
  439. procname := 'fpc_div_'
  440. else
  441. procname := 'fpc_mod_';
  442. { only qword needs the unsigned code, the
  443. signed code is also used for currency }
  444. if is_signed(resultdef) then
  445. procname := procname + 'int64'
  446. else
  447. procname := procname + 'qword';
  448. result := ccallnode.createintern(procname,ccallparanode.create(left,
  449. ccallparanode.create(right,nil)));
  450. left := nil;
  451. right := nil;
  452. firstpass(result);
  453. end;
  454. function tmoddivnode.firstoptimize: tnode;
  455. var
  456. power,shiftval : longint;
  457. statements : tstatementnode;
  458. temp,resulttemp : ttempcreatenode;
  459. masknode : tnode;
  460. invertsign: Boolean;
  461. begin
  462. result := nil;
  463. { divide/mod a number by a constant which is a power of 2? }
  464. if (right.nodetype = ordconstn) and
  465. isabspowerof2(tordconstnode(right).value,power) and
  466. {$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
  467. { for 64 bit, we leave the optimization to the cg }
  468. (not is_signed(resultdef)) then
  469. {$else cpu64bitalu or cpuhighleveltarget}
  470. (((nodetype=divn) and is_oversizedord(resultdef)) or
  471. (nodetype=modn) or
  472. not is_signed(resultdef)) then
  473. {$endif cpu64bitalu or cpuhighleveltarget}
  474. begin
  475. if nodetype=divn then
  476. begin
  477. if is_signed(resultdef) then
  478. begin
  479. invertsign:=tordconstnode(right).value<0;
  480. if is_64bitint(left.resultdef) then
  481. if not (cs_opt_size in current_settings.optimizerswitches) then
  482. shiftval:=63
  483. else
  484. { the shift code is a lot bigger than the call to }
  485. { the divide helper }
  486. exit
  487. else
  488. shiftval:=left.resultdef.size*8-1;
  489. result:=internalstatements(statements);
  490. temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  491. resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  492. addstatement(statements,resulttemp);
  493. addstatement(statements,temp);
  494. addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),
  495. left));
  496. left:=nil;
  497. { masknode is (sar(temp,shiftval) and ((1 shl power)-1))
  498. for power=1 (i.e. division by 2), masknode is simply (temp shr shiftval)}
  499. if power=1 then
  500. masknode:=
  501. cshlshrnode.create(shrn,
  502. ctemprefnode.create(temp),
  503. cordconstnode.create(shiftval,u8inttype,false)
  504. )
  505. else
  506. masknode:=
  507. caddnode.create(andn,
  508. cinlinenode.create(in_sar_x_y,false,
  509. ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
  510. ccallparanode.create(ctemprefnode.create(temp),nil))
  511. ),
  512. cordconstnode.create(tcgint((qword(1) shl power)-1),
  513. right.resultdef,false)
  514. );
  515. if invertsign then
  516. addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),
  517. cunaryminusnode.create(
  518. cinlinenode.create(in_sar_x_y,false,
  519. ccallparanode.create(cordconstnode.create(power,u8inttype,false),
  520. ccallparanode.create(caddnode.create(addn,ctemprefnode.create(temp),
  521. masknode),nil
  522. )))))
  523. )
  524. else
  525. addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),
  526. cinlinenode.create(in_sar_x_y,false,
  527. ccallparanode.create(cordconstnode.create(power,u8inttype,false),
  528. ccallparanode.create(caddnode.create(addn,ctemprefnode.create(temp),
  529. masknode),nil
  530. ))))
  531. );
  532. addstatement(statements,ctempdeletenode.create(temp));
  533. addstatement(statements,ctempdeletenode.create_normal_temp(resulttemp));
  534. addstatement(statements,ctemprefnode.create(resulttemp));
  535. right.Free;
  536. end
  537. else
  538. begin
  539. tordconstnode(right).value:=power;
  540. result:=cshlshrnode.create(shrn,left,right)
  541. end;
  542. end
  543. else if is_signed(resultdef) then { signed modulus }
  544. begin
  545. if (cs_opt_size in current_settings.optimizerswitches) then
  546. exit;
  547. shiftval:=left.resultdef.size*8-1;
  548. tordconstnode(right).value.uvalue:=qword((qword(1) shl power)-1);
  549. result:=internalstatements(statements);
  550. temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  551. resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  552. addstatement(statements,resulttemp);
  553. addstatement(statements,temp);
  554. addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),left));
  555. { mask:=sar(left,sizeof(left)*8-1) and ((1 shl power)-1); }
  556. if power=1 then
  557. masknode:=
  558. cshlshrnode.create(shrn,
  559. ctemprefnode.create(temp),
  560. cordconstnode.create(shiftval,u8inttype,false)
  561. )
  562. else
  563. masknode:=
  564. caddnode.create(andn,
  565. cinlinenode.create(in_sar_x_y,false,
  566. ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
  567. ccallparanode.create(ctemprefnode.create(temp),nil))
  568. ),
  569. cordconstnode.create(tcgint((qword(1) shl power)-1),
  570. right.resultdef,false)
  571. );
  572. addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),masknode));
  573. { result:=((left+mask) and right)-mask; }
  574. addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),
  575. caddnode.create(subn,
  576. caddnode.create(andn,
  577. right,
  578. caddnode.create(addn,
  579. ctemprefnode.create(temp),
  580. ctemprefnode.create(resulttemp))),
  581. ctemprefnode.create(resulttemp))
  582. ));
  583. addstatement(statements,ctempdeletenode.create(temp));
  584. addstatement(statements,ctempdeletenode.create_normal_temp(resulttemp));
  585. addstatement(statements,ctemprefnode.create(resulttemp));
  586. end
  587. else
  588. begin
  589. tordconstnode(right).value.uvalue:=qword((qword(1) shl power)-1);
  590. result := caddnode.create(andn,left,right);
  591. end;
  592. { left and right are reused }
  593. left := nil;
  594. right := nil;
  595. firstpass(result);
  596. exit;
  597. end;
  598. end;
  599. function tmoddivnode.pass_1 : tnode;
  600. begin
  601. result:=nil;
  602. firstpass(left);
  603. firstpass(right);
  604. if codegenerror then
  605. exit;
  606. { Try to optimize mod/div }
  607. result := firstoptimize;
  608. if assigned(result) then
  609. exit;
  610. { 64bit }
  611. if use_moddiv64bitint_helper then
  612. begin
  613. result := first_moddiv64bitint;
  614. if assigned(result) then
  615. exit;
  616. expectloc:=LOC_REGISTER;
  617. end
  618. else
  619. begin
  620. result := first_moddivint;
  621. if assigned(result) then
  622. exit;
  623. end;
  624. expectloc:=LOC_REGISTER;
  625. end;
  626. {****************************************************************************
  627. TSHLSHRNODE
  628. ****************************************************************************}
  629. function tshlshrnode.simplify(forinline : boolean):tnode;
  630. var
  631. lvalue, rvalue, mask : Tconstexprint;
  632. rangedef: tdef;
  633. size: longint;
  634. begin
  635. result:=nil;
  636. { constant folding }
  637. if is_constintnode(right) then
  638. begin
  639. if forinline then
  640. begin
  641. case resultdef.size of
  642. 1,2,4:
  643. rvalue:=tordconstnode(right).value and byte($1f);
  644. 8:
  645. rvalue:=tordconstnode(right).value and byte($3f);
  646. else
  647. internalerror(2013122302);
  648. end;
  649. end
  650. else
  651. rvalue:=tordconstnode(right).value;
  652. if is_constintnode(left) then
  653. begin
  654. lvalue:=tordconstnode(left).value;
  655. getrangedefmasksize(resultdef, rangedef, mask, size);
  656. { shr is an unsigned operation, so cut off upper bits }
  657. if forinline then
  658. lvalue:=lvalue and mask;
  659. case nodetype of
  660. shrn:
  661. lvalue:=lvalue shr rvalue;
  662. shln:
  663. lvalue:=lvalue shl rvalue;
  664. else
  665. internalerror(2019050517);
  666. end;
  667. { discard shifted-out bits (shl never triggers overflow/range errors) }
  668. if forinline and
  669. (nodetype=shln) then
  670. lvalue:=lvalue and mask;
  671. result:=create_simplified_ord_const(lvalue,resultdef,forinline,false);
  672. end
  673. else if rvalue=0 then
  674. begin
  675. result:=left;
  676. left:=nil;
  677. end;
  678. end
  679. else if is_constintnode(left) then
  680. begin
  681. lvalue:=tordconstnode(left).value;
  682. if forinline then
  683. begin
  684. getrangedefmasksize(resultdef, rangedef, mask, size);
  685. lvalue:=lvalue and mask;
  686. end;
  687. { '0 shl x' and '0 shr x' are 0 }
  688. if (lvalue=0) and
  689. ((cs_opt_level4 in current_settings.optimizerswitches) or
  690. not might_have_sideeffects(right)) then
  691. result:=cordconstnode.create(0,resultdef,true);
  692. end;
  693. end;
  694. function tshlshrnode.pass_typecheck:tnode;
  695. var
  696. t : tnode;
  697. begin
  698. result:=nil;
  699. typecheckpass(left);
  700. typecheckpass(right);
  701. { avoid any problems with type parameters later on }
  702. if is_typeparam(left.resultdef) or is_typeparam(right.resultdef) then
  703. begin
  704. resultdef:=cundefinedtype;
  705. exit;
  706. end;
  707. set_varstate(right,vs_read,[vsf_must_be_valid]);
  708. set_varstate(left,vs_read,[vsf_must_be_valid]);
  709. if codegenerror then
  710. exit;
  711. { tp procvar support }
  712. maybe_call_procvar(left,true);
  713. maybe_call_procvar(right,true);
  714. { allow operator overloading }
  715. t:=self;
  716. if isbinaryoverloaded(t,[]) then
  717. begin
  718. result:=t;
  719. exit;
  720. end;
  721. {$ifdef SUPPORT_MMX}
  722. if (cs_mmx in current_settings.localswitches) and
  723. is_mmx_able_array(left.resultdef) and
  724. ((is_mmx_able_array(right.resultdef) and
  725. equal_defs(left.resultdef,right.resultdef)
  726. ) or is_constintnode(right)) then
  727. begin
  728. if not(mmx_type(left.resultdef) in [mmxu16bit,mmxs16bit,mmxfixed16,mmxu32bit,mmxs32bit,mmxu64bit,mmxs64bit]) then
  729. CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resultdef.typename,right.resultdef.typename);
  730. if not(is_mmx_able_array(right.resultdef)) then
  731. inserttypeconv(right,sinttype);
  732. end
  733. else
  734. {$endif SUPPORT_MMX}
  735. begin
  736. { calculations for ordinals < 32 bit have to be done in
  737. 32 bit for backwards compatibility. That way 'shl 33' is
  738. the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
  739. if (not is_64bit(left.resultdef)) and
  740. (torddef(left.resultdef).ordtype<>u32bit) then
  741. begin
  742. { keep singness of orignal type }
  743. if is_signed(left.resultdef) then
  744. begin
  745. {$if defined(cpu64bitalu) or defined(cpu32bitalu)}
  746. inserttypeconv(left,s32inttype)
  747. {$elseif defined(cpu16bitalu) or defined(cpu8bitalu)}
  748. inserttypeconv(left,get_common_intdef(torddef(left.resultdef),torddef(sinttype),true));
  749. {$else}
  750. internalerror(2013031301);
  751. {$endif}
  752. end
  753. else
  754. begin
  755. {$if defined(cpu64bitalu) or defined(cpu32bitalu)}
  756. inserttypeconv(left,u32inttype);
  757. {$elseif defined(cpu16bitalu) or defined(cpu8bitalu)}
  758. inserttypeconv(left,get_common_intdef(torddef(left.resultdef),torddef(uinttype),true));
  759. {$else}
  760. internalerror(2013031301);
  761. {$endif}
  762. end
  763. end;
  764. inserttypeconv(right,sinttype);
  765. end;
  766. resultdef:=left.resultdef;
  767. result:=simplify(false);
  768. if assigned(result) then
  769. exit;
  770. end;
  771. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  772. function tshlshrnode.first_shlshr64bitint: tnode;
  773. var
  774. procname: string[31];
  775. begin
  776. result := nil;
  777. { Normally already done below, but called again,
  778. just in case it is called directly }
  779. firstpass(left);
  780. { otherwise create a call to a helper }
  781. if is_signed(left.resultdef) then
  782. procname:='int64'
  783. else
  784. procname:='qword';
  785. if nodetype = shln then
  786. procname := 'fpc_shl_'+procname
  787. else
  788. procname := 'fpc_shr_'+procname;
  789. { this order of parameters works at least for the arm,
  790. however it should work for any calling conventions (FK) }
  791. result := ccallnode.createintern(procname,ccallparanode.create(right,
  792. ccallparanode.create(left,nil)));
  793. left := nil;
  794. right := nil;
  795. firstpass(result);
  796. end;
  797. {$endif not cpu64bitalu and not cpuhighleveltarget}
  798. function tshlshrnode.pass_1 : tnode;
  799. begin
  800. result:=nil;
  801. firstpass(left);
  802. firstpass(right);
  803. if codegenerror then
  804. exit;
  805. expectloc:=LOC_REGISTER;
  806. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  807. { 64 bit ints have their own shift handling }
  808. if is_64bit(left.resultdef) then
  809. result := first_shlshr64bitint;
  810. {$endif not cpu64bitalu and not cpuhighleveltarget}
  811. end;
  812. {****************************************************************************
  813. TUNARYMINUSNODE
  814. ****************************************************************************}
  815. constructor tunaryminusnode.create(expr : tnode);
  816. begin
  817. inherited create(unaryminusn,expr);
  818. end;
  819. function tunaryminusnode.simplify(forinline : boolean):tnode;
  820. begin
  821. result:=nil;
  822. { constant folding }
  823. if is_constintnode(left) then
  824. begin
  825. result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline,cs_check_overflow in localswitches);
  826. exit;
  827. end;
  828. if is_constrealnode(left) then
  829. begin
  830. trealconstnode(left).value_real:=-trealconstnode(left).value_real;
  831. { Avoid integer overflow on x86_64 CPU for currency value }
  832. { i386 uses fildll/fchs/fistll instructions which never seem
  833. to raise any coprocessor flags .. }
  834. {$push}{$Q-}
  835. trealconstnode(left).value_currency:=-trealconstnode(left).value_currency;
  836. result:=left;
  837. {$pop}
  838. left:=nil;
  839. exit;
  840. end;
  841. end;
  842. function tunaryminusnode.pass_typecheck : tnode;
  843. var
  844. t : tnode;
  845. begin
  846. result:=nil;
  847. typecheckpass(left);
  848. { avoid any problems with type parameters later on }
  849. if is_typeparam(left.resultdef) then
  850. begin
  851. resultdef:=cundefinedtype;
  852. exit;
  853. end;
  854. set_varstate(left,vs_read,[vsf_must_be_valid]);
  855. if codegenerror then
  856. exit;
  857. result:=simplify(false);
  858. if assigned(result) then
  859. exit;
  860. resultdef:=left.resultdef;
  861. if (left.resultdef.typ=floatdef) or
  862. is_currency(left.resultdef) then
  863. begin
  864. end
  865. {$ifdef SUPPORT_MMX}
  866. else if (cs_mmx in current_settings.localswitches) and
  867. is_mmx_able_array(left.resultdef) then
  868. begin
  869. { if saturation is on, left.resultdef isn't
  870. "mmx able" (FK)
  871. if (cs_mmx_saturation in current_settings.localswitches^) and
  872. (torddef(tarraydef(resultdef).definition).typ in
  873. [s32bit,u32bit]) then
  874. CGMessage(type_e_mismatch);
  875. }
  876. end
  877. {$endif SUPPORT_MMX}
  878. else if is_oversizedord(left.resultdef) then
  879. begin
  880. if is_64bit(left.resultdef) then
  881. inserttypeconv(left,s64inttype)
  882. else if is_32bit(left.resultdef) then
  883. inserttypeconv(left,s32inttype)
  884. else if is_16bit(left.resultdef) then
  885. inserttypeconv(left,s16inttype)
  886. else
  887. internalerror(2013040701);
  888. resultdef:=left.resultdef;
  889. end
  890. else if (left.resultdef.typ=orddef) then
  891. begin
  892. inserttypeconv(left,sinttype);
  893. resultdef:=left.resultdef
  894. end
  895. else
  896. begin
  897. { allow operator overloading }
  898. t:=self;
  899. if isunaryoverloaded(t,[]) then
  900. begin
  901. result:=t;
  902. exit;
  903. end;
  904. CGMessage(type_e_mismatch);
  905. end;
  906. end;
  907. { generic code }
  908. { overridden by: }
  909. { i386 }
  910. function tunaryminusnode.pass_1 : tnode;
  911. var
  912. procname: string[31];
  913. begin
  914. result:=nil;
  915. firstpass(left);
  916. if codegenerror then
  917. exit;
  918. if (cs_fp_emulation in current_settings.moduleswitches) and (left.resultdef.typ=floatdef) then
  919. begin
  920. if not(target_info.system in systems_wince) then
  921. begin
  922. expectloc:=LOC_REGISTER;
  923. exit;
  924. end
  925. else
  926. begin
  927. case tfloatdef(resultdef).floattype of
  928. s32real:
  929. procname:='negs';
  930. s64real:
  931. procname:='negd';
  932. {!!! not yet implemented
  933. s128real:
  934. }
  935. else
  936. internalerror(2005082802);
  937. end;
  938. result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
  939. end;
  940. left:=nil;
  941. end
  942. else
  943. begin
  944. if (left.resultdef.typ=floatdef) then
  945. expectloc:=LOC_FPUREGISTER
  946. {$ifdef SUPPORT_MMX}
  947. else if (cs_mmx in current_settings.localswitches) and
  948. is_mmx_able_array(left.resultdef) then
  949. expectloc:=LOC_MMXREGISTER
  950. {$endif SUPPORT_MMX}
  951. else if (left.resultdef.typ=orddef) then
  952. expectloc:=LOC_REGISTER;
  953. end;
  954. end;
  955. {****************************************************************************
  956. TUNARYPLUSNODE
  957. ****************************************************************************}
  958. constructor tunaryplusnode.create(expr: tnode);
  959. begin
  960. inherited create(unaryplusn,expr);
  961. end;
  962. function tunaryplusnode.pass_1: tnode;
  963. begin
  964. result:=nil;
  965. { can never happen because all the conversions happen
  966. in pass_typecheck }
  967. internalerror(201012250);
  968. end;
  969. function tunaryplusnode.pass_typecheck: tnode;
  970. var
  971. t:tnode;
  972. begin
  973. result:=nil;
  974. typecheckpass(left);
  975. { avoid any problems with type parameters later on }
  976. if is_typeparam(left.resultdef) then
  977. begin
  978. resultdef:=cundefinedtype;
  979. exit;
  980. end;
  981. set_varstate(left,vs_read,[vsf_must_be_valid]);
  982. if codegenerror then
  983. exit;
  984. if is_constintnode(left) or
  985. is_constrealnode(left) or
  986. (left.resultdef.typ=floatdef) or
  987. is_currency(left.resultdef)
  988. {$ifdef SUPPORT_MMX}
  989. or ((cs_mmx in current_settings.localswitches) and
  990. is_mmx_able_array(left.resultdef))
  991. {$endif SUPPORT_MMX}
  992. then
  993. begin
  994. result:=left;
  995. left:=nil;
  996. end
  997. else if is_oversizedord(left.resultdef) then
  998. begin
  999. if is_64bit(left.resultdef) then
  1000. inserttypeconv(left,s64inttype)
  1001. else if is_32bit(left.resultdef) then
  1002. inserttypeconv(left,s32inttype)
  1003. else if is_16bit(left.resultdef) then
  1004. inserttypeconv(left,s16inttype)
  1005. else
  1006. internalerror(2013040702);
  1007. result:=left;
  1008. left:=nil;
  1009. end
  1010. else if (left.resultdef.typ=orddef) then
  1011. begin
  1012. inserttypeconv(left,sinttype);
  1013. result:=left;
  1014. left:=nil;
  1015. end
  1016. else
  1017. begin
  1018. { allow operator overloading }
  1019. t:=self;
  1020. if isunaryoverloaded(t,[]) then
  1021. begin
  1022. result:=t;
  1023. exit;
  1024. end;
  1025. CGMessage(type_e_mismatch);
  1026. end;
  1027. end;
  1028. {****************************************************************************
  1029. TNOTNODE
  1030. ****************************************************************************}
  1031. const
  1032. boolean_reverse:array[ltn..unequaln] of Tnodetype=(
  1033. gten,gtn,lten,ltn,unequaln,equaln
  1034. );
  1035. constructor tnotnode.create(expr : tnode);
  1036. begin
  1037. inherited create(notn,expr);
  1038. end;
  1039. function tnotnode.simplify(forinline : boolean):tnode;
  1040. var
  1041. v : tconstexprint;
  1042. t : tnode;
  1043. def : tdef;
  1044. begin
  1045. result:=nil;
  1046. { Try optmimizing ourself away }
  1047. if left.nodetype=notn then
  1048. begin
  1049. { Double not. Remove both }
  1050. result:=Tnotnode(left).left;
  1051. tnotnode(left).left:=nil;
  1052. exit;
  1053. end;
  1054. if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
  1055. begin
  1056. { Not of boolean expression. Turn around the operator and remove
  1057. the not. This is not allowed for sets with the gten/lten,
  1058. because there is no ltn/gtn support }
  1059. if (taddnode(left).left.resultdef.typ<>setdef) or
  1060. (left.nodetype in [equaln,unequaln]) then
  1061. begin
  1062. result:=left;
  1063. left.nodetype:=boolean_reverse[left.nodetype];
  1064. left:=nil;
  1065. exit;
  1066. end;
  1067. end;
  1068. { constant folding }
  1069. if (left.nodetype=ordconstn) and
  1070. (left.resultdef.typ=orddef) then
  1071. begin
  1072. v:=tordconstnode(left).value;
  1073. def:=left.resultdef;
  1074. if not calc_not_ordvalue(v,def) then
  1075. CGMessage(type_e_mismatch);
  1076. { not-nodes are not range checked by the code generator -> also
  1077. don't range check while inlining; the resultdef is a bit tricky
  1078. though: the node's resultdef gets changed in most cases compared
  1079. to left, but the not-operation itself is caried out in the code
  1080. generator using the size of left
  1081. }
  1082. if not(forinline) then
  1083. t:=cordconstnode.create(v,def,false)
  1084. else
  1085. begin
  1086. { cut off the value if necessary }
  1087. t:=cordconstnode.create(v,left.resultdef,false);
  1088. { now convert to node's resultdef }
  1089. inserttypeconv_explicit(t,def);
  1090. end;
  1091. result:=t;
  1092. exit;
  1093. end;
  1094. end;
  1095. function tnotnode.pass_typecheck : tnode;
  1096. var
  1097. t : tnode;
  1098. begin
  1099. result:=nil;
  1100. typecheckpass(left);
  1101. { avoid any problems with type parameters later on }
  1102. if is_typeparam(left.resultdef) then
  1103. begin
  1104. resultdef:=cundefinedtype;
  1105. exit;
  1106. end;
  1107. set_varstate(left,vs_read,[vsf_must_be_valid]);
  1108. if codegenerror then
  1109. exit;
  1110. { tp procvar support }
  1111. maybe_call_procvar(left,true);
  1112. resultdef:=left.resultdef;
  1113. result:=simplify(false);
  1114. if assigned(result) then
  1115. exit;
  1116. if is_boolean(resultdef) then
  1117. begin
  1118. end
  1119. else
  1120. {$ifdef SUPPORT_MMX}
  1121. if (cs_mmx in current_settings.localswitches) and
  1122. is_mmx_able_array(left.resultdef) then
  1123. begin
  1124. end
  1125. else
  1126. {$endif SUPPORT_MMX}
  1127. {$ifndef cpu64bitaddr}
  1128. if is_64bitint(left.resultdef) then
  1129. begin
  1130. end
  1131. else
  1132. {$endif not cpu64bitaddr}
  1133. if is_integer(left.resultdef) then
  1134. begin
  1135. end
  1136. else
  1137. begin
  1138. { allow operator overloading }
  1139. t:=self;
  1140. if isunaryoverloaded(t,[]) then
  1141. begin
  1142. result:=t;
  1143. exit;
  1144. end;
  1145. CGMessage(type_e_mismatch);
  1146. end;
  1147. end;
  1148. function tnotnode.pass_1 : tnode;
  1149. begin
  1150. result:=nil;
  1151. firstpass(left);
  1152. if codegenerror then
  1153. exit;
  1154. expectloc:=left.expectloc;
  1155. if is_boolean(resultdef) then
  1156. begin
  1157. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1158. expectloc:=LOC_REGISTER;
  1159. { xtensa has boolean registers which are treateed as flags but they
  1160. are not used for boolean expressions }
  1161. {$if defined(cpuflags) and not(defined(xtensa))}
  1162. if left.expectloc<>LOC_JUMP then
  1163. expectloc:=LOC_FLAGS;
  1164. {$endif defined(cpuflags) and not(defined(xtensa)}
  1165. end
  1166. else
  1167. {$ifdef SUPPORT_MMX}
  1168. if (cs_mmx in current_settings.localswitches) and
  1169. is_mmx_able_array(left.resultdef) then
  1170. expectloc:=LOC_MMXREGISTER
  1171. else
  1172. {$endif SUPPORT_MMX}
  1173. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  1174. if is_64bit(left.resultdef) then
  1175. begin
  1176. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1177. expectloc:=LOC_REGISTER;
  1178. end
  1179. else
  1180. {$endif not cpu64bitalu and not cpuhighleveltarget}
  1181. if is_integer(left.resultdef) then
  1182. expectloc:=LOC_REGISTER;
  1183. end;
  1184. {$ifdef state_tracking}
  1185. function Tnotnode.track_state_pass(exec_known:boolean):boolean;
  1186. begin
  1187. track_state_pass:=true;
  1188. if left.track_state_pass(exec_known) then
  1189. begin
  1190. left.resultdef:=nil;
  1191. do_typecheckpass(left);
  1192. end;
  1193. end;
  1194. {$endif}
  1195. end.