nmat.pas 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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. {$ifndef cpu64bitalu}
  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}
  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,
  83. globtype,constexp,
  84. symconst,symtype,symdef,symtable,
  85. 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. end;
  109. exit;
  110. end;
  111. if rv = 0 then
  112. begin
  113. Message(parser_e_division_by_zero);
  114. { recover }
  115. tordconstnode(right).value := 1;
  116. end;
  117. if (nf_isomod in flags) and
  118. (rv<=0) then
  119. begin
  120. Message(cg_e_mod_only_defined_for_pos_quotient);
  121. { recover }
  122. tordconstnode(right).value := 1;
  123. end;
  124. end;
  125. if is_constintnode(right) and is_constintnode(left) then
  126. begin
  127. rv:=tordconstnode(right).value;
  128. lv:=tordconstnode(left).value;
  129. case nodetype of
  130. modn:
  131. if nf_isomod in flags then
  132. begin
  133. if lv>=0 then
  134. result:=create_simplified_ord_const(lv mod rv,resultdef,forinline)
  135. else
  136. if ((-lv) mod rv)=0 then
  137. result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline)
  138. else
  139. result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline);
  140. end
  141. else
  142. result:=create_simplified_ord_const(lv mod rv,resultdef,forinline);
  143. divn:
  144. result:=create_simplified_ord_const(lv div rv,resultdef,forinline);
  145. end;
  146. end;
  147. end;
  148. function tmoddivnode.use_moddiv64bitint_helper: boolean;
  149. begin
  150. { not with an ifdef around the call to this routine, because e.g. the
  151. Java VM has a signed 64 bit division opcode, but not an unsigned
  152. one }
  153. {$ifdef cpu64bitalu}
  154. result:=false;
  155. {$else cpu64bitalu}
  156. result:=
  157. (left.resultdef.typ=orddef) and
  158. (right.resultdef.typ=orddef) and
  159. (is_64bitint(left.resultdef) or is_64bitint(right.resultdef));
  160. {$endif cpu64bitaly}
  161. end;
  162. function tmoddivnode.pass_typecheck:tnode;
  163. var
  164. else_block,
  165. hp,t : tnode;
  166. rd,ld : torddef;
  167. else_statements,
  168. statements : tstatementnode;
  169. result_data : ttempcreatenode;
  170. begin
  171. result:=nil;
  172. typecheckpass(left);
  173. typecheckpass(right);
  174. set_varstate(left,vs_read,[vsf_must_be_valid]);
  175. set_varstate(right,vs_read,[vsf_must_be_valid]);
  176. if codegenerror then
  177. exit;
  178. { tp procvar support }
  179. maybe_call_procvar(left,true);
  180. maybe_call_procvar(right,true);
  181. { allow operator overloading }
  182. t:=self;
  183. if isbinaryoverloaded(t) then
  184. begin
  185. result:=t;
  186. exit;
  187. end;
  188. { we need 2 orddefs always }
  189. if (left.resultdef.typ<>orddef) then
  190. inserttypeconv(left,sinttype);
  191. if (right.resultdef.typ<>orddef) then
  192. inserttypeconv(right,sinttype);
  193. if codegenerror then
  194. exit;
  195. { Try only now to simply constant
  196. as otherwise you might create
  197. tconstnode with return type that are
  198. not compatible with tconst node
  199. as in bug report 21566 PM }
  200. result:=simplify(false);
  201. if assigned(result) then
  202. exit;
  203. rd:=torddef(right.resultdef);
  204. ld:=torddef(left.resultdef);
  205. { if one operand is a cardinal and the other is a positive constant, convert the }
  206. { constant to a cardinal as well so we don't have to do a 64bit division (JM) }
  207. { Do the same for qwords and positive constants as well, otherwise things like }
  208. { "qword mod 10" are evaluated with int64 as result, which is wrong if the }
  209. { "qword" was > high(int64) (JM) }
  210. { Additionally, do the same for cardinal/qwords and other positive types, but }
  211. { always in a way that a smaller type is converted to a bigger type }
  212. { (webtbs/tw8870) }
  213. if (rd.ordtype in [u32bit,u64bit]) and
  214. ((is_constintnode(left) and
  215. (tordconstnode(left).value >= 0)) or
  216. (not is_signed(ld) and
  217. (rd.size >= ld.size))) then
  218. begin
  219. inserttypeconv(left,right.resultdef);
  220. ld:=torddef(left.resultdef);
  221. end;
  222. if (ld.ordtype in [u32bit,u64bit]) and
  223. ((is_constintnode(right) and
  224. (tordconstnode(right).value >= 0)) or
  225. (not is_signed(rd) and
  226. (ld.size >= rd.size))) then
  227. begin
  228. inserttypeconv(right,left.resultdef);
  229. rd:=torddef(right.resultdef);
  230. end;
  231. { when there is one currency value, everything is done
  232. using currency }
  233. if (ld.ordtype=scurrency) or
  234. (rd.ordtype=scurrency) then
  235. begin
  236. if (ld.ordtype<>scurrency) then
  237. inserttypeconv(left,s64currencytype);
  238. if (rd.ordtype<>scurrency) then
  239. inserttypeconv(right,s64currencytype);
  240. resultdef:=left.resultdef;
  241. end
  242. else
  243. {$ifndef cpu64bitaddr}
  244. { when there is one 64bit value, everything is done
  245. in 64bit }
  246. if (is_64bitint(left.resultdef) or
  247. is_64bitint(right.resultdef)) then
  248. begin
  249. if is_signed(rd) or is_signed(ld) then
  250. begin
  251. if (ld.ordtype<>s64bit) then
  252. inserttypeconv(left,s64inttype);
  253. if (rd.ordtype<>s64bit) then
  254. inserttypeconv(right,s64inttype);
  255. end
  256. else
  257. begin
  258. if (ld.ordtype<>u64bit) then
  259. inserttypeconv(left,u64inttype);
  260. if (rd.ordtype<>u64bit) then
  261. inserttypeconv(right,u64inttype);
  262. end;
  263. resultdef:=left.resultdef;
  264. end
  265. else
  266. { when mixing cardinals and signed numbers, convert everythign to 64bit (JM) }
  267. if ((rd.ordtype = u32bit) and
  268. is_signed(ld)) or
  269. ((ld.ordtype = u32bit) and
  270. is_signed(rd)) then
  271. begin
  272. CGMessage(type_h_mixed_signed_unsigned);
  273. if (ld.ordtype<>s64bit) then
  274. inserttypeconv(left,s64inttype);
  275. if (rd.ordtype<>s64bit) then
  276. inserttypeconv(right,s64inttype);
  277. resultdef:=left.resultdef;
  278. end
  279. else
  280. {$endif not cpu64bitaddr}
  281. begin
  282. { Make everything always default singed int }
  283. if not(rd.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  284. inserttypeconv(right,sinttype);
  285. if not(ld.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  286. inserttypeconv(left,sinttype);
  287. resultdef:=right.resultdef;
  288. end;
  289. { when the result is currency we need some extra code for
  290. division. this should not be done when the divn node is
  291. created internally }
  292. if (nodetype=divn) and
  293. not(nf_is_currency in flags) and
  294. is_currency(resultdef) then
  295. begin
  296. hp:=caddnode.create(muln,getcopy,cordconstnode.create(10000,s64currencytype,false));
  297. include(hp.flags,nf_is_currency);
  298. result:=hp;
  299. end;
  300. if (nodetype=modn) and (nf_isomod in flags) then
  301. begin
  302. result:=internalstatements(statements);
  303. else_block:=internalstatements(else_statements);
  304. result_data:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  305. { right <=0? }
  306. addstatement(statements,cifnode.create(caddnode.create(lten,right.getcopy,cordconstnode.create(0,resultdef,false)),
  307. { then: result:=left mod right }
  308. ccallnode.createintern('fpc_divbyzero',nil),
  309. nil
  310. ));
  311. { prepare else block }
  312. { result:=(-left) mod right }
  313. addstatement(else_statements,cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,cunaryminusnode.create(left.getcopy),right.getcopy)));
  314. { result<>0? }
  315. addstatement(else_statements,cifnode.create(caddnode.create(unequaln,ctemprefnode.create(result_data),cordconstnode.create(0,resultdef,false)),
  316. { then: result:=right-result }
  317. cassignmentnode.create(ctemprefnode.create(result_data),caddnode.create(subn,right.getcopy,ctemprefnode.create(result_data))),
  318. nil
  319. ));
  320. addstatement(statements,result_data);
  321. { if left>=0 }
  322. addstatement(statements,cifnode.create(caddnode.create(gten,left.getcopy,cordconstnode.create(0,resultdef,false)),
  323. { then: result:=left mod right }
  324. cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,left.getcopy,right.getcopy)),
  325. { else block }
  326. else_block
  327. ));
  328. addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
  329. addstatement(statements,ctemprefnode.create(result_data));
  330. end;
  331. end;
  332. function tmoddivnode.first_moddivint: tnode;
  333. {$ifdef cpuneedsdiv32helper}
  334. var
  335. procname: string[31];
  336. begin
  337. result := nil;
  338. { otherwise create a call to a helper }
  339. if nodetype = divn then
  340. procname := 'fpc_div_'
  341. else
  342. procname := 'fpc_mod_';
  343. { only qword needs the unsigned code, the
  344. signed code is also used for currency }
  345. if is_signed(resultdef) then
  346. procname := procname + 'longint'
  347. else
  348. procname := procname + 'dword';
  349. result := ccallnode.createintern(procname,ccallparanode.create(left,
  350. ccallparanode.create(right,nil)));
  351. left := nil;
  352. right := nil;
  353. firstpass(result);
  354. end;
  355. {$else cpuneedsdiv32helper}
  356. begin
  357. result:=nil;
  358. end;
  359. {$endif cpuneedsdiv32helper}
  360. function tmoddivnode.first_moddiv64bitint: tnode;
  361. var
  362. procname: string[31];
  363. begin
  364. result := nil;
  365. { when currency is used set the result of the
  366. parameters to s64bit, so they are not converted }
  367. if is_currency(resultdef) then
  368. begin
  369. left.resultdef:=s64inttype;
  370. right.resultdef:=s64inttype;
  371. end;
  372. { otherwise create a call to a helper }
  373. if nodetype = divn then
  374. procname := 'fpc_div_'
  375. else
  376. procname := 'fpc_mod_';
  377. { only qword needs the unsigned code, the
  378. signed code is also used for currency }
  379. if is_signed(resultdef) then
  380. procname := procname + 'int64'
  381. else
  382. procname := procname + 'qword';
  383. result := ccallnode.createintern(procname,ccallparanode.create(left,
  384. ccallparanode.create(right,nil)));
  385. left := nil;
  386. right := nil;
  387. firstpass(result);
  388. end;
  389. function tmoddivnode.firstoptimize: tnode;
  390. var
  391. power,shiftval : longint;
  392. statements : tstatementnode;
  393. temp : ttempcreatenode;
  394. begin
  395. result := nil;
  396. { divide/mod a number by a constant which is a power of 2? }
  397. if (right.nodetype = ordconstn) and
  398. {$ifdef cpu64bitalu}
  399. { for 64 bit, we leave the optimization to the cg }
  400. (not is_signed(resultdef)) and
  401. {$else cpu64bitalu}
  402. ((nodetype=divn) and (is_64bit(resultdef)) or
  403. not is_signed(resultdef)) and
  404. {$endif cpu64bitalu}
  405. ispowerof2(tordconstnode(right).value,power) then
  406. begin
  407. if nodetype=divn then
  408. begin
  409. if is_signed(resultdef) then
  410. begin
  411. if is_64bitint(left.resultdef) then
  412. if not (cs_opt_size in current_settings.optimizerswitches) then
  413. shiftval:=63
  414. else
  415. { the shift code is a lot bigger than the call to }
  416. { the divide helper }
  417. exit
  418. else
  419. shiftval:=31;
  420. result:=internalstatements(statements);
  421. temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  422. addstatement(statements,temp);
  423. addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),
  424. left));
  425. left:=nil;
  426. addstatement(statements,ccallnode.createintern('fpc_sarint64',
  427. ccallparanode.create(cordconstnode.create(power,u8inttype,false),
  428. ccallparanode.create(caddnode.create(addn,ctemprefnode.create(temp),
  429. caddnode.create(andn,
  430. ccallnode.createintern('fpc_sarint64',
  431. ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
  432. ccallparanode.create(ctemprefnode.create(temp),nil))
  433. ),
  434. cordconstnode.create(tordconstnode(right).value-1,
  435. right.resultdef,false)
  436. )),nil
  437. )))
  438. );
  439. end
  440. else
  441. begin
  442. tordconstnode(right).value:=power;
  443. result:=cshlshrnode.create(shrn,left,right)
  444. end;
  445. end
  446. else
  447. begin
  448. dec(tordconstnode(right).value.uvalue);
  449. result := caddnode.create(andn,left,right);
  450. end;
  451. { left and right are reused }
  452. left := nil;
  453. right := nil;
  454. firstpass(result);
  455. exit;
  456. end;
  457. end;
  458. function tmoddivnode.pass_1 : tnode;
  459. begin
  460. result:=nil;
  461. firstpass(left);
  462. firstpass(right);
  463. if codegenerror then
  464. exit;
  465. { Try to optimize mod/div }
  466. result := firstoptimize;
  467. if assigned(result) then
  468. exit;
  469. { 64bit }
  470. if use_moddiv64bitint_helper then
  471. begin
  472. result := first_moddiv64bitint;
  473. if assigned(result) then
  474. exit;
  475. expectloc:=LOC_REGISTER;
  476. end
  477. else
  478. begin
  479. result := first_moddivint;
  480. if assigned(result) then
  481. exit;
  482. end;
  483. expectloc:=LOC_REGISTER;
  484. end;
  485. {****************************************************************************
  486. TSHLSHRNODE
  487. ****************************************************************************}
  488. function tshlshrnode.simplify(forinline : boolean):tnode;
  489. begin
  490. result:=nil;
  491. { constant folding }
  492. if is_constintnode(left) and is_constintnode(right) then
  493. begin
  494. case nodetype of
  495. shrn:
  496. result:=create_simplified_ord_const(tordconstnode(left).value shr tordconstnode(right).value,resultdef,forinline);
  497. shln:
  498. result:=create_simplified_ord_const(tordconstnode(left).value shl tordconstnode(right).value,resultdef,forinline);
  499. end;
  500. end;
  501. end;
  502. function tshlshrnode.pass_typecheck:tnode;
  503. var
  504. t : tnode;
  505. {$ifdef cpunodefaultint}
  506. nd : tdef;
  507. {$endif cpunodefaultint}
  508. begin
  509. result:=nil;
  510. typecheckpass(left);
  511. typecheckpass(right);
  512. set_varstate(right,vs_read,[vsf_must_be_valid]);
  513. set_varstate(left,vs_read,[vsf_must_be_valid]);
  514. if codegenerror then
  515. exit;
  516. { tp procvar support }
  517. maybe_call_procvar(left,true);
  518. maybe_call_procvar(right,true);
  519. { allow operator overloading }
  520. t:=self;
  521. if isbinaryoverloaded(t) then
  522. begin
  523. result:=t;
  524. exit;
  525. end;
  526. {$ifdef cpunodefaultint}
  527. { for small cpus we use the smallest common type }
  528. if (left.resultdef.typ=orddef) and (right.resultdef.typ=orddef) then
  529. nd:=get_common_intdef(torddef(left.resultdef),torddef(right.resultdef),false)
  530. else
  531. nd:=s32inttype;
  532. {$endif cpunodefaultint}
  533. { calculations for ordinals < 32 bit have to be done in
  534. 32 bit for backwards compatibility. That way 'shl 33' is
  535. the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
  536. if (not is_64bit(left.resultdef)) and
  537. (torddef(left.resultdef).ordtype<>u32bit) then
  538. begin
  539. { keep singness of orignal type }
  540. if is_signed(left.resultdef) then
  541. begin
  542. {$if defined(cpunodefaultint)}
  543. inserttypeconv(left,nd)
  544. {$elseif defined(cpu64bitalu) or defined(cpu32bitalu)}
  545. inserttypeconv(left,s32inttype)
  546. {$elseif defined(cpu16bitalu)}
  547. if left.resultdef.size > 2 then
  548. inserttypeconv(left,s32inttype)
  549. else
  550. inserttypeconv(left,sinttype);
  551. {$else}
  552. internalerror(2013031301);
  553. {$endif}
  554. end
  555. else
  556. begin
  557. {$if defined(cpunodefaultint)}
  558. inserttypeconv(left,nd)
  559. {$elseif defined(cpu64bitalu) or defined(cpu32bitalu)}
  560. inserttypeconv(left,u32inttype);
  561. {$elseif defined(cpu16bitalu)}
  562. if left.resultdef.size > 2 then
  563. inserttypeconv(left,u32inttype)
  564. else
  565. inserttypeconv(left,uinttype);
  566. {$else}
  567. internalerror(2013031301);
  568. {$endif}
  569. end
  570. end;
  571. {$ifdef cpunodefaultint}
  572. inserttypeconv(right,nd);
  573. {$else cpunodefaultint}
  574. inserttypeconv(right,sinttype);
  575. {$endif cpunodefaultint}
  576. resultdef:=left.resultdef;
  577. result:=simplify(false);
  578. if assigned(result) then
  579. exit;
  580. end;
  581. {$ifndef cpu64bitalu}
  582. function tshlshrnode.first_shlshr64bitint: tnode;
  583. var
  584. procname: string[31];
  585. begin
  586. result := nil;
  587. { Normally already done below, but called again,
  588. just in case it is called directly }
  589. firstpass(left);
  590. { otherwise create a call to a helper }
  591. if is_signed(left.resultdef) then
  592. procname:='int64'
  593. else
  594. procname:='qword';
  595. if nodetype = shln then
  596. procname := 'fpc_shl_'+procname
  597. else
  598. procname := 'fpc_shr_'+procname;
  599. { this order of parameters works at least for the arm,
  600. however it should work for any calling conventions (FK) }
  601. result := ccallnode.createintern(procname,ccallparanode.create(right,
  602. ccallparanode.create(left,nil)));
  603. left := nil;
  604. right := nil;
  605. firstpass(result);
  606. end;
  607. {$endif not cpu64bitalu}
  608. function tshlshrnode.pass_1 : tnode;
  609. var
  610. regs : longint;
  611. begin
  612. result:=nil;
  613. firstpass(left);
  614. firstpass(right);
  615. if codegenerror then
  616. exit;
  617. {$ifndef cpu64bitalu}
  618. { 64 bit ints have their own shift handling }
  619. if is_64bit(left.resultdef) then
  620. begin
  621. result := first_shlshr64bitint;
  622. if assigned(result) then
  623. exit;
  624. regs:=2;
  625. end
  626. else
  627. {$endif not cpu64bitalu}
  628. begin
  629. regs:=1
  630. end;
  631. if (right.nodetype<>ordconstn) then
  632. inc(regs);
  633. expectloc:=LOC_REGISTER;
  634. end;
  635. {****************************************************************************
  636. TUNARYMINUSNODE
  637. ****************************************************************************}
  638. constructor tunaryminusnode.create(expr : tnode);
  639. begin
  640. inherited create(unaryminusn,expr);
  641. end;
  642. function tunaryminusnode.simplify(forinline : boolean):tnode;
  643. begin
  644. result:=nil;
  645. { constant folding }
  646. if is_constintnode(left) then
  647. begin
  648. result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline);
  649. exit;
  650. end;
  651. if is_constrealnode(left) then
  652. begin
  653. trealconstnode(left).value_real:=-trealconstnode(left).value_real;
  654. trealconstnode(left).value_currency:=-trealconstnode(left).value_currency;
  655. result:=left;
  656. left:=nil;
  657. exit;
  658. end;
  659. end;
  660. function tunaryminusnode.pass_typecheck : tnode;
  661. var
  662. t : tnode;
  663. begin
  664. result:=nil;
  665. typecheckpass(left);
  666. set_varstate(left,vs_read,[vsf_must_be_valid]);
  667. if codegenerror then
  668. exit;
  669. result:=simplify(false);
  670. if assigned(result) then
  671. exit;
  672. resultdef:=left.resultdef;
  673. if (left.resultdef.typ=floatdef) or
  674. is_currency(left.resultdef) then
  675. begin
  676. end
  677. {$ifdef SUPPORT_MMX}
  678. else if (cs_mmx in current_settings.localswitches) and
  679. is_mmx_able_array(left.resultdef) then
  680. begin
  681. { if saturation is on, left.resultdef isn't
  682. "mmx able" (FK)
  683. if (cs_mmx_saturation in current_settings.localswitches^) and
  684. (torddef(tarraydef(resultdef).definition).typ in
  685. [s32bit,u32bit]) then
  686. CGMessage(type_e_mismatch);
  687. }
  688. end
  689. {$endif SUPPORT_MMX}
  690. {$ifndef cpu64bitaddr}
  691. else if is_64bit(left.resultdef) then
  692. begin
  693. inserttypeconv(left,s64inttype);
  694. resultdef:=left.resultdef
  695. end
  696. {$endif not cpu64bitaddr}
  697. {$if defined(cpu16bitalu) or defined(cpu8bitalu)}
  698. else if is_32bitint(left.resultdef) then
  699. begin
  700. inserttypeconv(left,s32inttype);
  701. resultdef:=left.resultdef
  702. end
  703. {$endif cpu16bitalu or cpu8bitalu}
  704. else if (left.resultdef.typ=orddef) then
  705. begin
  706. {$ifndef cpunodefaultint}
  707. inserttypeconv(left,sinttype);
  708. {$endif cpunodefaultint}
  709. resultdef:=left.resultdef
  710. end
  711. else
  712. begin
  713. { allow operator overloading }
  714. t:=self;
  715. if isunaryoverloaded(t) then
  716. begin
  717. result:=t;
  718. exit;
  719. end;
  720. CGMessage(type_e_mismatch);
  721. end;
  722. end;
  723. { generic code }
  724. { overridden by: }
  725. { i386 }
  726. function tunaryminusnode.pass_1 : tnode;
  727. var
  728. procname: string[31];
  729. fdef : tdef;
  730. begin
  731. result:=nil;
  732. firstpass(left);
  733. if codegenerror then
  734. exit;
  735. if (cs_fp_emulation in current_settings.moduleswitches) and (left.resultdef.typ=floatdef) then
  736. begin
  737. if not(target_info.system in systems_wince) then
  738. begin
  739. case tfloatdef(resultdef).floattype of
  740. s32real:
  741. begin
  742. procname:='float32_sub';
  743. fdef:=search_system_type('FLOAT32REC').typedef;
  744. end;
  745. s64real:
  746. begin
  747. procname:='float64_sub';
  748. fdef:=search_system_type('FLOAT64').typedef;
  749. end;
  750. {!!! not yet implemented
  751. s128real:
  752. }
  753. else
  754. internalerror(2005082801);
  755. end;
  756. result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
  757. ctypeconvnode.create_internal(left,fDef),
  758. ccallparanode.create(ctypeconvnode.create_internal(crealconstnode.create(0,resultdef),fdef),nil))),resultdef);
  759. end
  760. else
  761. begin
  762. case tfloatdef(resultdef).floattype of
  763. s32real:
  764. procname:='NEGS';
  765. s64real:
  766. procname:='NEGD';
  767. {!!! not yet implemented
  768. s128real:
  769. }
  770. else
  771. internalerror(2005082802);
  772. end;
  773. result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
  774. end;
  775. left:=nil;
  776. end
  777. else
  778. begin
  779. if (left.resultdef.typ=floatdef) then
  780. expectloc:=LOC_FPUREGISTER
  781. {$ifdef SUPPORT_MMX}
  782. else if (cs_mmx in current_settings.localswitches) and
  783. is_mmx_able_array(left.resultdef) then
  784. expectloc:=LOC_MMXREGISTER
  785. {$endif SUPPORT_MMX}
  786. else if (left.resultdef.typ=orddef) then
  787. expectloc:=LOC_REGISTER;
  788. end;
  789. end;
  790. {****************************************************************************
  791. TUNARYPLUSNODE
  792. ****************************************************************************}
  793. constructor tunaryplusnode.create(expr: tnode);
  794. begin
  795. inherited create(unaryplusn,expr);
  796. end;
  797. function tunaryplusnode.pass_1: tnode;
  798. begin
  799. result:=nil;
  800. { can never happen because all the conversions happen
  801. in pass_typecheck }
  802. internalerror(201012250);
  803. end;
  804. function tunaryplusnode.pass_typecheck: tnode;
  805. var
  806. t:tnode;
  807. begin
  808. result:=nil;
  809. typecheckpass(left);
  810. set_varstate(left,vs_read,[vsf_must_be_valid]);
  811. if codegenerror then
  812. exit;
  813. if is_constintnode(left) or
  814. is_constrealnode(left) or
  815. (left.resultdef.typ=floatdef) or
  816. is_currency(left.resultdef)
  817. {$ifdef SUPPORT_MMX}
  818. or ((cs_mmx in current_settings.localswitches) and
  819. is_mmx_able_array(left.resultdef))
  820. {$endif SUPPORT_MMX}
  821. then
  822. begin
  823. result:=left;
  824. left:=nil;
  825. end
  826. {$ifndef cpu64bitaddr}
  827. else if is_64bit(left.resultdef) then
  828. begin
  829. inserttypeconv(left,s64inttype);
  830. result:=left;
  831. left:=nil;
  832. end
  833. {$endif not cpu64bitaddr}
  834. {$if defined(cpu16bitalu) or defined(cpu8bitalu)}
  835. else if is_32bitint(left.resultdef) then
  836. begin
  837. inserttypeconv(left,s32inttype);
  838. result:=left;
  839. left:=nil;
  840. end
  841. {$endif cpu16bitalu or cpu8bitalu}
  842. else if (left.resultdef.typ=orddef) then
  843. begin
  844. inserttypeconv(left,sinttype);
  845. result:=left;
  846. left:=nil;
  847. end
  848. else
  849. begin
  850. { allow operator overloading }
  851. t:=self;
  852. if isunaryoverloaded(t) then
  853. begin
  854. result:=t;
  855. exit;
  856. end;
  857. CGMessage(type_e_mismatch);
  858. end;
  859. end;
  860. {****************************************************************************
  861. TNOTNODE
  862. ****************************************************************************}
  863. const
  864. boolean_reverse:array[ltn..unequaln] of Tnodetype=(
  865. gten,gtn,lten,ltn,unequaln,equaln
  866. );
  867. constructor tnotnode.create(expr : tnode);
  868. begin
  869. inherited create(notn,expr);
  870. end;
  871. function tnotnode.simplify(forinline : boolean):tnode;
  872. var
  873. v : tconstexprint;
  874. t : tnode;
  875. def : tdef;
  876. begin
  877. result:=nil;
  878. { Try optmimizing ourself away }
  879. if left.nodetype=notn then
  880. begin
  881. { Double not. Remove both }
  882. result:=Tnotnode(left).left;
  883. tnotnode(left).left:=nil;
  884. exit;
  885. end;
  886. if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
  887. begin
  888. { Not of boolean expression. Turn around the operator and remove
  889. the not. This is not allowed for sets with the gten/lten,
  890. because there is no ltn/gtn support }
  891. if (taddnode(left).left.resultdef.typ<>setdef) or
  892. (left.nodetype in [equaln,unequaln]) then
  893. begin
  894. result:=left;
  895. left.nodetype:=boolean_reverse[left.nodetype];
  896. left:=nil;
  897. exit;
  898. end;
  899. end;
  900. { constant folding }
  901. if (left.nodetype=ordconstn) then
  902. begin
  903. v:=tordconstnode(left).value;
  904. def:=left.resultdef;
  905. case torddef(left.resultdef).ordtype of
  906. pasbool8,
  907. pasbool16,
  908. pasbool32,
  909. pasbool64,
  910. bool8bit,
  911. bool16bit,
  912. bool32bit,
  913. bool64bit:
  914. begin
  915. v:=byte(not(boolean(int64(v))));
  916. if is_cbool(left.resultdef) then
  917. v:=-v;
  918. end;
  919. uchar,
  920. uwidechar,
  921. u8bit,
  922. s8bit,
  923. u16bit,
  924. s16bit,
  925. s32bit,
  926. {$ifdef cpu64bitaddr}
  927. u32bit,
  928. {$endif cpu64bitaddr}
  929. s64bit:
  930. begin
  931. v:=int64(not int64(v));
  932. if (torddef(left.resultdef).ordtype<>s64bit) then
  933. def:=sinttype
  934. else
  935. def:=s64inttype;
  936. end;
  937. {$ifndef cpu64bitaddr}
  938. u32bit,
  939. {$endif not cpu64bitaddr}
  940. u64bit :
  941. begin
  942. { Delphi-compatible: not dword = dword (not word = longint) }
  943. { Extension: not qword = qword }
  944. v:=qword(not qword(v));
  945. { will be truncated by the ordconstnode for u32bit }
  946. end;
  947. else
  948. CGMessage(type_e_mismatch);
  949. end;
  950. { not-nodes are not range checked by the code generator -> also
  951. don't range check while inlining; the resultdef is a bit tricky
  952. though: the node's resultdef gets changed in most cases compared
  953. to left, but the not-operation itself is caried out in the code
  954. generator using the size of left
  955. }
  956. if not(forinline) then
  957. t:=cordconstnode.create(v,def,false)
  958. else
  959. begin
  960. { cut off the value if necessary }
  961. t:=cordconstnode.create(v,left.resultdef,false);
  962. { now convert to node's resultdef }
  963. inserttypeconv_explicit(t,def);
  964. end;
  965. result:=t;
  966. exit;
  967. end;
  968. end;
  969. function tnotnode.pass_typecheck : tnode;
  970. var
  971. t : tnode;
  972. begin
  973. result:=nil;
  974. typecheckpass(left);
  975. set_varstate(left,vs_read,[vsf_must_be_valid]);
  976. if codegenerror then
  977. exit;
  978. { tp procvar support }
  979. maybe_call_procvar(left,true);
  980. resultdef:=left.resultdef;
  981. result:=simplify(false);
  982. if assigned(result) then
  983. exit;
  984. if is_boolean(resultdef) then
  985. begin
  986. end
  987. else
  988. {$ifdef SUPPORT_MMX}
  989. if (cs_mmx in current_settings.localswitches) and
  990. is_mmx_able_array(left.resultdef) then
  991. begin
  992. end
  993. else
  994. {$endif SUPPORT_MMX}
  995. {$ifndef cpu64bitaddr}
  996. if is_64bitint(left.resultdef) then
  997. begin
  998. end
  999. else
  1000. {$endif not cpu64bitaddr}
  1001. if is_integer(left.resultdef) then
  1002. begin
  1003. end
  1004. else
  1005. begin
  1006. { allow operator overloading }
  1007. t:=self;
  1008. if isunaryoverloaded(t) then
  1009. begin
  1010. result:=t;
  1011. exit;
  1012. end;
  1013. CGMessage(type_e_mismatch);
  1014. end;
  1015. end;
  1016. function tnotnode.pass_1 : tnode;
  1017. begin
  1018. result:=nil;
  1019. firstpass(left);
  1020. if codegenerror then
  1021. exit;
  1022. expectloc:=left.expectloc;
  1023. if is_boolean(resultdef) then
  1024. begin
  1025. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1026. expectloc:=LOC_REGISTER;
  1027. { before loading it into flags we need to load it into
  1028. a register thus 1 register is need PM }
  1029. {$ifdef cpuflags}
  1030. if left.expectloc<>LOC_JUMP then
  1031. expectloc:=LOC_FLAGS;
  1032. {$endif def cpuflags}
  1033. end
  1034. else
  1035. {$ifdef SUPPORT_MMX}
  1036. if (cs_mmx in current_settings.localswitches) and
  1037. is_mmx_able_array(left.resultdef) then
  1038. expectloc:=LOC_MMXREGISTER
  1039. else
  1040. {$endif SUPPORT_MMX}
  1041. {$ifndef cpu64bitalu}
  1042. if is_64bit(left.resultdef) then
  1043. begin
  1044. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1045. expectloc:=LOC_REGISTER;
  1046. end
  1047. else
  1048. {$endif not cpu64bitalu}
  1049. if is_integer(left.resultdef) then
  1050. expectloc:=LOC_REGISTER;
  1051. end;
  1052. {$ifdef state_tracking}
  1053. function Tnotnode.track_state_pass(exec_known:boolean):boolean;
  1054. begin
  1055. track_state_pass:=true;
  1056. if left.track_state_pass(exec_known) then
  1057. begin
  1058. left.resultdef:=nil;
  1059. do_typecheckpass(left);
  1060. end;
  1061. end;
  1062. {$endif}
  1063. end.