nmat.pas 40 KB

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