nmat.pas 47 KB

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