nmat.pas 42 KB

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