nmat.pas 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  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. {$ifdef cpunodefaultint}
  542. inserttypeconv(left,nd)
  543. {$else cpunodefaultint}
  544. inserttypeconv(left,s32inttype)
  545. {$endif cpunodefaultint}
  546. else
  547. begin
  548. {$ifdef cpunodefaultint}
  549. inserttypeconv(left,nd)
  550. {$else cpunodefaultint}
  551. inserttypeconv(left,u32inttype);
  552. {$endif cpunodefaultint}
  553. end
  554. end;
  555. {$ifdef cpunodefaultint}
  556. inserttypeconv(right,nd);
  557. {$else cpunodefaultint}
  558. inserttypeconv(right,sinttype);
  559. {$endif cpunodefaultint}
  560. resultdef:=left.resultdef;
  561. result:=simplify(false);
  562. if assigned(result) then
  563. exit;
  564. end;
  565. {$ifndef cpu64bitalu}
  566. function tshlshrnode.first_shlshr64bitint: tnode;
  567. var
  568. procname: string[31];
  569. begin
  570. result := nil;
  571. { Normally already done below, but called again,
  572. just in case it is called directly }
  573. firstpass(left);
  574. { otherwise create a call to a helper }
  575. if is_signed(left.resultdef) then
  576. procname:='int64'
  577. else
  578. procname:='qword';
  579. if nodetype = shln then
  580. procname := 'fpc_shl_'+procname
  581. else
  582. procname := 'fpc_shr_'+procname;
  583. { this order of parameters works at least for the arm,
  584. however it should work for any calling conventions (FK) }
  585. result := ccallnode.createintern(procname,ccallparanode.create(right,
  586. ccallparanode.create(left,nil)));
  587. left := nil;
  588. right := nil;
  589. firstpass(result);
  590. end;
  591. {$endif not cpu64bitalu}
  592. function tshlshrnode.pass_1 : tnode;
  593. var
  594. regs : longint;
  595. begin
  596. result:=nil;
  597. firstpass(left);
  598. firstpass(right);
  599. if codegenerror then
  600. exit;
  601. {$ifndef cpu64bitalu}
  602. { 64 bit ints have their own shift handling }
  603. if is_64bit(left.resultdef) then
  604. begin
  605. result := first_shlshr64bitint;
  606. if assigned(result) then
  607. exit;
  608. regs:=2;
  609. end
  610. else
  611. {$endif not cpu64bitalu}
  612. begin
  613. regs:=1
  614. end;
  615. if (right.nodetype<>ordconstn) then
  616. inc(regs);
  617. expectloc:=LOC_REGISTER;
  618. end;
  619. {****************************************************************************
  620. TUNARYMINUSNODE
  621. ****************************************************************************}
  622. constructor tunaryminusnode.create(expr : tnode);
  623. begin
  624. inherited create(unaryminusn,expr);
  625. end;
  626. function tunaryminusnode.simplify(forinline : boolean):tnode;
  627. begin
  628. result:=nil;
  629. { constant folding }
  630. if is_constintnode(left) then
  631. begin
  632. result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline);
  633. exit;
  634. end;
  635. if is_constrealnode(left) then
  636. begin
  637. trealconstnode(left).value_real:=-trealconstnode(left).value_real;
  638. trealconstnode(left).value_currency:=-trealconstnode(left).value_currency;
  639. result:=left;
  640. left:=nil;
  641. exit;
  642. end;
  643. end;
  644. function tunaryminusnode.pass_typecheck : tnode;
  645. var
  646. t : tnode;
  647. begin
  648. result:=nil;
  649. typecheckpass(left);
  650. set_varstate(left,vs_read,[vsf_must_be_valid]);
  651. if codegenerror then
  652. exit;
  653. result:=simplify(false);
  654. if assigned(result) then
  655. exit;
  656. resultdef:=left.resultdef;
  657. if (left.resultdef.typ=floatdef) or
  658. is_currency(left.resultdef) then
  659. begin
  660. end
  661. {$ifdef SUPPORT_MMX}
  662. else if (cs_mmx in current_settings.localswitches) and
  663. is_mmx_able_array(left.resultdef) then
  664. begin
  665. { if saturation is on, left.resultdef isn't
  666. "mmx able" (FK)
  667. if (cs_mmx_saturation in current_settings.localswitches^) and
  668. (torddef(tarraydef(resultdef).definition).typ in
  669. [s32bit,u32bit]) then
  670. CGMessage(type_e_mismatch);
  671. }
  672. end
  673. {$endif SUPPORT_MMX}
  674. {$ifndef cpu64bitaddr}
  675. else if is_64bit(left.resultdef) then
  676. begin
  677. inserttypeconv(left,s64inttype);
  678. resultdef:=left.resultdef
  679. end
  680. {$endif not cpu64bitaddr}
  681. else if (left.resultdef.typ=orddef) then
  682. begin
  683. {$ifndef cpunodefaultint}
  684. inserttypeconv(left,sinttype);
  685. {$endif cpunodefaultint}
  686. resultdef:=left.resultdef
  687. end
  688. else
  689. begin
  690. { allow operator overloading }
  691. t:=self;
  692. if isunaryoverloaded(t) then
  693. begin
  694. result:=t;
  695. exit;
  696. end;
  697. CGMessage(type_e_mismatch);
  698. end;
  699. end;
  700. { generic code }
  701. { overridden by: }
  702. { i386 }
  703. function tunaryminusnode.pass_1 : tnode;
  704. var
  705. procname: string[31];
  706. fdef : tdef;
  707. begin
  708. result:=nil;
  709. firstpass(left);
  710. if codegenerror then
  711. exit;
  712. if (cs_fp_emulation in current_settings.moduleswitches) and (left.resultdef.typ=floatdef) then
  713. begin
  714. if not(target_info.system in systems_wince) then
  715. begin
  716. case tfloatdef(resultdef).floattype of
  717. s32real:
  718. begin
  719. procname:='float32_sub';
  720. fdef:=search_system_type('FLOAT32REC').typedef;
  721. end;
  722. s64real:
  723. begin
  724. procname:='float64_sub';
  725. fdef:=search_system_type('FLOAT64').typedef;
  726. end;
  727. {!!! not yet implemented
  728. s128real:
  729. }
  730. else
  731. internalerror(2005082801);
  732. end;
  733. result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
  734. ctypeconvnode.create_internal(left,fDef),
  735. ccallparanode.create(ctypeconvnode.create_internal(crealconstnode.create(0,resultdef),fdef),nil))),resultdef);
  736. end
  737. else
  738. begin
  739. case tfloatdef(resultdef).floattype of
  740. s32real:
  741. procname:='NEGS';
  742. s64real:
  743. procname:='NEGD';
  744. {!!! not yet implemented
  745. s128real:
  746. }
  747. else
  748. internalerror(2005082802);
  749. end;
  750. result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
  751. end;
  752. left:=nil;
  753. end
  754. else
  755. begin
  756. if (left.resultdef.typ=floatdef) then
  757. expectloc:=LOC_FPUREGISTER
  758. {$ifdef SUPPORT_MMX}
  759. else if (cs_mmx in current_settings.localswitches) and
  760. is_mmx_able_array(left.resultdef) then
  761. expectloc:=LOC_MMXREGISTER
  762. {$endif SUPPORT_MMX}
  763. else if (left.resultdef.typ=orddef) then
  764. expectloc:=LOC_REGISTER;
  765. end;
  766. end;
  767. {****************************************************************************
  768. TUNARYPLUSNODE
  769. ****************************************************************************}
  770. constructor tunaryplusnode.create(expr: tnode);
  771. begin
  772. inherited create(unaryplusn,expr);
  773. end;
  774. function tunaryplusnode.pass_1: tnode;
  775. begin
  776. result:=nil;
  777. { can never happen because all the conversions happen
  778. in pass_typecheck }
  779. internalerror(201012250);
  780. end;
  781. function tunaryplusnode.pass_typecheck: tnode;
  782. var
  783. t:tnode;
  784. begin
  785. result:=nil;
  786. typecheckpass(left);
  787. set_varstate(left,vs_read,[vsf_must_be_valid]);
  788. if codegenerror then
  789. exit;
  790. if is_constintnode(left) or
  791. is_constrealnode(left) or
  792. (left.resultdef.typ=floatdef) or
  793. is_currency(left.resultdef)
  794. {$ifdef SUPPORT_MMX}
  795. or ((cs_mmx in current_settings.localswitches) and
  796. is_mmx_able_array(left.resultdef))
  797. {$endif SUPPORT_MMX}
  798. then
  799. begin
  800. result:=left;
  801. left:=nil;
  802. end
  803. {$ifndef cpu64bitaddr}
  804. else if is_64bit(left.resultdef) then
  805. begin
  806. inserttypeconv(left,s64inttype);
  807. result:=left;
  808. left:=nil;
  809. end
  810. {$endif not cpu64bitaddr}
  811. else if (left.resultdef.typ=orddef) then
  812. begin
  813. inserttypeconv(left,sinttype);
  814. result:=left;
  815. left:=nil;
  816. end
  817. else
  818. begin
  819. { allow operator overloading }
  820. t:=self;
  821. if isunaryoverloaded(t) then
  822. begin
  823. result:=t;
  824. exit;
  825. end;
  826. CGMessage(type_e_mismatch);
  827. end;
  828. end;
  829. {****************************************************************************
  830. TNOTNODE
  831. ****************************************************************************}
  832. const
  833. boolean_reverse:array[ltn..unequaln] of Tnodetype=(
  834. gten,gtn,lten,ltn,unequaln,equaln
  835. );
  836. constructor tnotnode.create(expr : tnode);
  837. begin
  838. inherited create(notn,expr);
  839. end;
  840. function tnotnode.simplify(forinline : boolean):tnode;
  841. var
  842. v : tconstexprint;
  843. t : tnode;
  844. def : tdef;
  845. begin
  846. result:=nil;
  847. { Try optmimizing ourself away }
  848. if left.nodetype=notn then
  849. begin
  850. { Double not. Remove both }
  851. result:=Tnotnode(left).left;
  852. tnotnode(left).left:=nil;
  853. exit;
  854. end;
  855. if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
  856. begin
  857. { Not of boolean expression. Turn around the operator and remove
  858. the not. This is not allowed for sets with the gten/lten,
  859. because there is no ltn/gtn support }
  860. if (taddnode(left).left.resultdef.typ<>setdef) or
  861. (left.nodetype in [equaln,unequaln]) then
  862. begin
  863. result:=left;
  864. left.nodetype:=boolean_reverse[left.nodetype];
  865. left:=nil;
  866. exit;
  867. end;
  868. end;
  869. { constant folding }
  870. if (left.nodetype=ordconstn) then
  871. begin
  872. v:=tordconstnode(left).value;
  873. def:=left.resultdef;
  874. case torddef(left.resultdef).ordtype of
  875. pasbool8,
  876. pasbool16,
  877. pasbool32,
  878. pasbool64,
  879. bool8bit,
  880. bool16bit,
  881. bool32bit,
  882. bool64bit:
  883. begin
  884. v:=byte(not(boolean(int64(v))));
  885. if is_cbool(left.resultdef) then
  886. v:=-v;
  887. end;
  888. uchar,
  889. uwidechar,
  890. u8bit,
  891. s8bit,
  892. u16bit,
  893. s16bit,
  894. s32bit,
  895. {$ifdef cpu64bitaddr}
  896. u32bit,
  897. {$endif cpu64bitaddr}
  898. s64bit:
  899. begin
  900. v:=int64(not int64(v));
  901. if (torddef(left.resultdef).ordtype<>s64bit) then
  902. def:=sinttype
  903. else
  904. def:=s64inttype;
  905. end;
  906. {$ifndef cpu64bitaddr}
  907. u32bit,
  908. {$endif not cpu64bitaddr}
  909. u64bit :
  910. begin
  911. { Delphi-compatible: not dword = dword (not word = longint) }
  912. { Extension: not qword = qword }
  913. v:=qword(not qword(v));
  914. { will be truncated by the ordconstnode for u32bit }
  915. end;
  916. else
  917. CGMessage(type_e_mismatch);
  918. end;
  919. { not-nodes are not range checked by the code generator -> also
  920. don't range check while inlining; the resultdef is a bit tricky
  921. though: the node's resultdef gets changed in most cases compared
  922. to left, but the not-operation itself is caried out in the code
  923. generator using the size of left
  924. }
  925. if not(forinline) then
  926. t:=cordconstnode.create(v,def,false)
  927. else
  928. begin
  929. { cut off the value if necessary }
  930. t:=cordconstnode.create(v,left.resultdef,false);
  931. { now convert to node's resultdef }
  932. inserttypeconv_explicit(t,def);
  933. end;
  934. result:=t;
  935. exit;
  936. end;
  937. end;
  938. function tnotnode.pass_typecheck : tnode;
  939. var
  940. t : tnode;
  941. begin
  942. result:=nil;
  943. typecheckpass(left);
  944. set_varstate(left,vs_read,[vsf_must_be_valid]);
  945. if codegenerror then
  946. exit;
  947. { tp procvar support }
  948. maybe_call_procvar(left,true);
  949. resultdef:=left.resultdef;
  950. result:=simplify(false);
  951. if assigned(result) then
  952. exit;
  953. if is_boolean(resultdef) then
  954. begin
  955. end
  956. else
  957. {$ifdef SUPPORT_MMX}
  958. if (cs_mmx in current_settings.localswitches) and
  959. is_mmx_able_array(left.resultdef) then
  960. begin
  961. end
  962. else
  963. {$endif SUPPORT_MMX}
  964. {$ifndef cpu64bitaddr}
  965. if is_64bitint(left.resultdef) then
  966. begin
  967. end
  968. else
  969. {$endif not cpu64bitaddr}
  970. if is_integer(left.resultdef) then
  971. begin
  972. end
  973. else
  974. begin
  975. { allow operator overloading }
  976. t:=self;
  977. if isunaryoverloaded(t) then
  978. begin
  979. result:=t;
  980. exit;
  981. end;
  982. CGMessage(type_e_mismatch);
  983. end;
  984. end;
  985. function tnotnode.pass_1 : tnode;
  986. begin
  987. result:=nil;
  988. firstpass(left);
  989. if codegenerror then
  990. exit;
  991. expectloc:=left.expectloc;
  992. if is_boolean(resultdef) then
  993. begin
  994. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  995. expectloc:=LOC_REGISTER;
  996. { before loading it into flags we need to load it into
  997. a register thus 1 register is need PM }
  998. {$ifdef cpuflags}
  999. if left.expectloc<>LOC_JUMP then
  1000. expectloc:=LOC_FLAGS;
  1001. {$endif def cpuflags}
  1002. end
  1003. else
  1004. {$ifdef SUPPORT_MMX}
  1005. if (cs_mmx in current_settings.localswitches) and
  1006. is_mmx_able_array(left.resultdef) then
  1007. expectloc:=LOC_MMXREGISTER
  1008. else
  1009. {$endif SUPPORT_MMX}
  1010. {$ifndef cpu64bitalu}
  1011. if is_64bit(left.resultdef) then
  1012. begin
  1013. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1014. expectloc:=LOC_REGISTER;
  1015. end
  1016. else
  1017. {$endif not cpu64bitalu}
  1018. if is_integer(left.resultdef) then
  1019. expectloc:=LOC_REGISTER;
  1020. end;
  1021. {$ifdef state_tracking}
  1022. function Tnotnode.track_state_pass(exec_known:boolean):boolean;
  1023. begin
  1024. track_state_pass:=true;
  1025. if left.track_state_pass(exec_known) then
  1026. begin
  1027. left.resultdef:=nil;
  1028. do_typecheckpass(left);
  1029. end;
  1030. end;
  1031. {$endif}
  1032. end.