nmat.pas 50 KB

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