2
0

nmat.pas 48 KB

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