nmat.pas 39 KB

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