nmat.pas 48 KB

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