nmat.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  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 [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 [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. begin
  282. { Make everything always default singed int }
  283. if not(rd.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  284. inserttypeconv(right,sinttype);
  285. if not(ld.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
  286. inserttypeconv(left,sinttype);
  287. resultdef:=right.resultdef;
  288. end;
  289. { when the result is currency we need some extra code for
  290. division. this should not be done when the divn node is
  291. created internally }
  292. if (nodetype=divn) and
  293. not(nf_is_currency in flags) and
  294. is_currency(resultdef) then
  295. begin
  296. hp:=caddnode.create(muln,getcopy,cordconstnode.create(10000,s64currencytype,false));
  297. include(hp.flags,nf_is_currency);
  298. result:=hp;
  299. end;
  300. if (nodetype=modn) and (nf_isomod in flags) then
  301. begin
  302. result:=internalstatements(statements);
  303. else_block:=internalstatements(else_statements);
  304. result_data:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  305. { right <=0? }
  306. addstatement(statements,cifnode.create(caddnode.create(lten,right.getcopy,cordconstnode.create(0,resultdef,false)),
  307. { then: result:=left mod right }
  308. ccallnode.createintern('fpc_divbyzero',nil),
  309. nil
  310. ));
  311. { prepare else block }
  312. { result:=(-left) mod right }
  313. addstatement(else_statements,cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,cunaryminusnode.create(left.getcopy),right.getcopy)));
  314. { result<>0? }
  315. addstatement(else_statements,cifnode.create(caddnode.create(unequaln,ctemprefnode.create(result_data),cordconstnode.create(0,resultdef,false)),
  316. { then: result:=right-result }
  317. cassignmentnode.create(ctemprefnode.create(result_data),caddnode.create(subn,right.getcopy,ctemprefnode.create(result_data))),
  318. nil
  319. ));
  320. addstatement(statements,result_data);
  321. { if left>=0 }
  322. addstatement(statements,cifnode.create(caddnode.create(gten,left.getcopy,cordconstnode.create(0,resultdef,false)),
  323. { then: result:=left mod right }
  324. cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,left.getcopy,right.getcopy)),
  325. { else block }
  326. else_block
  327. ));
  328. addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
  329. addstatement(statements,ctemprefnode.create(result_data));
  330. end;
  331. end;
  332. function tmoddivnode.first_moddivint: tnode;
  333. {$ifdef cpuneedsdiv32helper}
  334. var
  335. procname: string[31];
  336. begin
  337. result := nil;
  338. { otherwise create a call to a helper }
  339. if nodetype = divn then
  340. procname := 'fpc_div_'
  341. else
  342. procname := 'fpc_mod_';
  343. { only qword needs the unsigned code, the
  344. signed code is also used for currency }
  345. if is_signed(resultdef) then
  346. procname := procname + 'longint'
  347. else
  348. procname := procname + 'dword';
  349. result := ccallnode.createintern(procname,ccallparanode.create(left,
  350. ccallparanode.create(right,nil)));
  351. left := nil;
  352. right := nil;
  353. firstpass(result);
  354. end;
  355. {$else cpuneedsdiv32helper}
  356. begin
  357. result:=nil;
  358. end;
  359. {$endif cpuneedsdiv32helper}
  360. function tmoddivnode.first_moddiv64bitint: tnode;
  361. var
  362. procname: string[31];
  363. begin
  364. result := nil;
  365. { when currency is used set the result of the
  366. parameters to s64bit, so they are not converted }
  367. if is_currency(resultdef) then
  368. begin
  369. left.resultdef:=s64inttype;
  370. right.resultdef:=s64inttype;
  371. end;
  372. { otherwise create a call to a helper }
  373. if nodetype = divn then
  374. procname := 'fpc_div_'
  375. else
  376. procname := 'fpc_mod_';
  377. { only qword needs the unsigned code, the
  378. signed code is also used for currency }
  379. if is_signed(resultdef) then
  380. procname := procname + 'int64'
  381. else
  382. procname := procname + 'qword';
  383. result := ccallnode.createintern(procname,ccallparanode.create(left,
  384. ccallparanode.create(right,nil)));
  385. left := nil;
  386. right := nil;
  387. firstpass(result);
  388. end;
  389. function tmoddivnode.firstoptimize: tnode;
  390. var
  391. power,shiftval : longint;
  392. newtype: tnodetype;
  393. statements : tstatementnode;
  394. temp : ttempcreatenode;
  395. begin
  396. result := nil;
  397. { divide/mod a number by a constant which is a power of 2? }
  398. if (right.nodetype = ordconstn) and
  399. {$ifdef cpu64bitalu}
  400. { for 64 bit, we leave the optimization to the cg }
  401. (not is_signed(resultdef)) and
  402. {$else cpu64bitalu}
  403. ((nodetype=divn) and (is_64bit(resultdef)) or
  404. not is_signed(resultdef)) and
  405. {$endif cpu64bitalu}
  406. ispowerof2(tordconstnode(right).value,power) then
  407. begin
  408. if nodetype=divn then
  409. begin
  410. if is_signed(resultdef) then
  411. begin
  412. if is_64bitint(left.resultdef) then
  413. if not (cs_opt_size in current_settings.optimizerswitches) then
  414. shiftval:=63
  415. else
  416. { the shift code is a lot bigger than the call to }
  417. { the divide helper }
  418. exit
  419. else
  420. shiftval:=31;
  421. result:=internalstatements(statements);
  422. temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  423. addstatement(statements,temp);
  424. addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),
  425. left));
  426. left:=nil;
  427. addstatement(statements,ccallnode.createintern('fpc_sarint64',
  428. ccallparanode.create(cordconstnode.create(power,u8inttype,false),
  429. ccallparanode.create(caddnode.create(addn,ctemprefnode.create(temp),
  430. caddnode.create(andn,
  431. ccallnode.createintern('fpc_sarint64',
  432. ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
  433. ccallparanode.create(ctemprefnode.create(temp),nil))
  434. ),
  435. cordconstnode.create(tordconstnode(right).value-1,
  436. right.resultdef,false)
  437. )),nil
  438. )))
  439. );
  440. end
  441. else
  442. begin
  443. tordconstnode(right).value:=power;
  444. result:=cshlshrnode.create(shrn,left,right)
  445. end;
  446. end
  447. else
  448. begin
  449. dec(tordconstnode(right).value.uvalue);
  450. result := caddnode.create(andn,left,right);
  451. end;
  452. { left and right are reused }
  453. left := nil;
  454. right := nil;
  455. firstpass(result);
  456. exit;
  457. end;
  458. end;
  459. function tmoddivnode.pass_1 : tnode;
  460. begin
  461. result:=nil;
  462. firstpass(left);
  463. firstpass(right);
  464. if codegenerror then
  465. exit;
  466. { Try to optimize mod/div }
  467. result := firstoptimize;
  468. if assigned(result) then
  469. exit;
  470. { 64bit }
  471. if use_moddiv64bitint_helper then
  472. begin
  473. result := first_moddiv64bitint;
  474. if assigned(result) then
  475. exit;
  476. expectloc:=LOC_REGISTER;
  477. end
  478. else
  479. begin
  480. result := first_moddivint;
  481. if assigned(result) then
  482. exit;
  483. end;
  484. expectloc:=LOC_REGISTER;
  485. end;
  486. {****************************************************************************
  487. TSHLSHRNODE
  488. ****************************************************************************}
  489. function tshlshrnode.simplify(forinline : boolean):tnode;
  490. begin
  491. result:=nil;
  492. { constant folding }
  493. if is_constintnode(left) and is_constintnode(right) then
  494. begin
  495. case nodetype of
  496. shrn:
  497. result:=create_simplified_ord_const(tordconstnode(left).value shr tordconstnode(right).value,resultdef,forinline);
  498. shln:
  499. result:=create_simplified_ord_const(tordconstnode(left).value shl tordconstnode(right).value,resultdef,forinline);
  500. end;
  501. end;
  502. end;
  503. function tshlshrnode.pass_typecheck:tnode;
  504. var
  505. t : tnode;
  506. {$ifdef cpunodefaultint}
  507. nd : tdef;
  508. {$endif cpunodefaultint}
  509. begin
  510. result:=nil;
  511. typecheckpass(left);
  512. typecheckpass(right);
  513. set_varstate(right,vs_read,[vsf_must_be_valid]);
  514. set_varstate(left,vs_read,[vsf_must_be_valid]);
  515. if codegenerror then
  516. exit;
  517. { tp procvar support }
  518. maybe_call_procvar(left,true);
  519. maybe_call_procvar(right,true);
  520. { allow operator overloading }
  521. t:=self;
  522. if isbinaryoverloaded(t) then
  523. begin
  524. result:=t;
  525. exit;
  526. end;
  527. {$ifdef cpunodefaultint}
  528. { for small cpus we use the smallest common type }
  529. if (left.resultdef.typ=orddef) and (right.resultdef.typ=orddef) then
  530. nd:=get_common_intdef(torddef(left.resultdef),torddef(right.resultdef),false)
  531. else
  532. nd:=s32inttype;
  533. {$endif cpunodefaultint}
  534. { calculations for ordinals < 32 bit have to be done in
  535. 32 bit for backwards compatibility. That way 'shl 33' is
  536. the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
  537. if (not is_64bit(left.resultdef)) and
  538. (torddef(left.resultdef).ordtype<>u32bit) then
  539. begin
  540. { keep singness of orignal type }
  541. if is_signed(left.resultdef) then
  542. {$ifdef cpunodefaultint}
  543. inserttypeconv(left,nd)
  544. {$else cpunodefaultint}
  545. inserttypeconv(left,s32inttype)
  546. {$endif cpunodefaultint}
  547. else
  548. begin
  549. {$ifdef cpunodefaultint}
  550. inserttypeconv(left,nd)
  551. {$else cpunodefaultint}
  552. inserttypeconv(left,u32inttype);
  553. {$endif cpunodefaultint}
  554. end
  555. end;
  556. {$ifdef cpunodefaultint}
  557. inserttypeconv(right,nd);
  558. {$else cpunodefaultint}
  559. inserttypeconv(right,sinttype);
  560. {$endif cpunodefaultint}
  561. resultdef:=left.resultdef;
  562. result:=simplify(false);
  563. if assigned(result) then
  564. exit;
  565. end;
  566. {$ifndef cpu64bitalu}
  567. function tshlshrnode.first_shlshr64bitint: tnode;
  568. var
  569. procname: string[31];
  570. begin
  571. result := nil;
  572. { Normally already done below, but called again,
  573. just in case it is called directly }
  574. firstpass(left);
  575. { otherwise create a call to a helper }
  576. if is_signed(left.resultdef) then
  577. procname:='int64'
  578. else
  579. procname:='qword';
  580. if nodetype = shln then
  581. procname := 'fpc_shl_'+procname
  582. else
  583. procname := 'fpc_shr_'+procname;
  584. { this order of parameters works at least for the arm,
  585. however it should work for any calling conventions (FK) }
  586. result := ccallnode.createintern(procname,ccallparanode.create(right,
  587. ccallparanode.create(left,nil)));
  588. left := nil;
  589. right := nil;
  590. firstpass(result);
  591. end;
  592. {$endif not cpu64bitalu}
  593. function tshlshrnode.pass_1 : tnode;
  594. var
  595. regs : longint;
  596. begin
  597. result:=nil;
  598. firstpass(left);
  599. firstpass(right);
  600. if codegenerror then
  601. exit;
  602. {$ifndef cpu64bitalu}
  603. { 64 bit ints have their own shift handling }
  604. if is_64bit(left.resultdef) then
  605. begin
  606. result := first_shlshr64bitint;
  607. if assigned(result) then
  608. exit;
  609. regs:=2;
  610. end
  611. else
  612. {$endif not cpu64bitalu}
  613. begin
  614. regs:=1
  615. end;
  616. if (right.nodetype<>ordconstn) then
  617. inc(regs);
  618. expectloc:=LOC_REGISTER;
  619. end;
  620. {****************************************************************************
  621. TUNARYMINUSNODE
  622. ****************************************************************************}
  623. constructor tunaryminusnode.create(expr : tnode);
  624. begin
  625. inherited create(unaryminusn,expr);
  626. end;
  627. function tunaryminusnode.simplify(forinline : boolean):tnode;
  628. begin
  629. result:=nil;
  630. { constant folding }
  631. if is_constintnode(left) then
  632. begin
  633. result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline);
  634. exit;
  635. end;
  636. if is_constrealnode(left) then
  637. begin
  638. trealconstnode(left).value_real:=-trealconstnode(left).value_real;
  639. trealconstnode(left).value_currency:=-trealconstnode(left).value_currency;
  640. result:=left;
  641. left:=nil;
  642. exit;
  643. end;
  644. end;
  645. function tunaryminusnode.pass_typecheck : tnode;
  646. var
  647. t : tnode;
  648. begin
  649. result:=nil;
  650. typecheckpass(left);
  651. set_varstate(left,vs_read,[vsf_must_be_valid]);
  652. if codegenerror then
  653. exit;
  654. result:=simplify(false);
  655. if assigned(result) then
  656. exit;
  657. resultdef:=left.resultdef;
  658. if (left.resultdef.typ=floatdef) or
  659. is_currency(left.resultdef) then
  660. begin
  661. end
  662. {$ifdef SUPPORT_MMX}
  663. else if (cs_mmx in current_settings.localswitches) and
  664. is_mmx_able_array(left.resultdef) then
  665. begin
  666. { if saturation is on, left.resultdef isn't
  667. "mmx able" (FK)
  668. if (cs_mmx_saturation in current_settings.localswitches^) and
  669. (torddef(tarraydef(resultdef).definition).typ in
  670. [s32bit,u32bit]) then
  671. CGMessage(type_e_mismatch);
  672. }
  673. end
  674. {$endif SUPPORT_MMX}
  675. {$ifndef cpu64bitaddr}
  676. else if is_64bit(left.resultdef) then
  677. begin
  678. inserttypeconv(left,s64inttype);
  679. resultdef:=left.resultdef
  680. end
  681. {$endif not cpu64bitaddr}
  682. else if (left.resultdef.typ=orddef) then
  683. begin
  684. inserttypeconv(left,sinttype);
  685. resultdef:=left.resultdef
  686. end
  687. else
  688. begin
  689. { allow operator overloading }
  690. t:=self;
  691. if isunaryoverloaded(t) then
  692. begin
  693. result:=t;
  694. exit;
  695. end;
  696. CGMessage(type_e_mismatch);
  697. end;
  698. end;
  699. { generic code }
  700. { overridden by: }
  701. { i386 }
  702. function tunaryminusnode.pass_1 : tnode;
  703. var
  704. procname: string[31];
  705. fdef : tdef;
  706. begin
  707. result:=nil;
  708. firstpass(left);
  709. if codegenerror then
  710. exit;
  711. if (cs_fp_emulation in current_settings.moduleswitches) and (left.resultdef.typ=floatdef) then
  712. begin
  713. if not(target_info.system in systems_wince) then
  714. begin
  715. case tfloatdef(resultdef).floattype of
  716. s32real:
  717. begin
  718. procname:='float32_sub';
  719. fdef:=search_system_type('FLOAT32REC').typedef;
  720. end;
  721. s64real:
  722. begin
  723. procname:='float64_sub';
  724. fdef:=search_system_type('FLOAT64').typedef;
  725. end;
  726. {!!! not yet implemented
  727. s128real:
  728. }
  729. else
  730. internalerror(2005082801);
  731. end;
  732. result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
  733. ctypeconvnode.create_internal(left,fDef),
  734. ccallparanode.create(ctypeconvnode.create_internal(crealconstnode.create(0,resultdef),fdef),nil))),resultdef);
  735. end
  736. else
  737. begin
  738. case tfloatdef(resultdef).floattype of
  739. s32real:
  740. procname:='NEGS';
  741. s64real:
  742. procname:='NEGD';
  743. {!!! not yet implemented
  744. s128real:
  745. }
  746. else
  747. internalerror(2005082802);
  748. end;
  749. result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
  750. end;
  751. left:=nil;
  752. end
  753. else
  754. begin
  755. if (left.resultdef.typ=floatdef) then
  756. expectloc:=LOC_FPUREGISTER
  757. {$ifdef SUPPORT_MMX}
  758. else if (cs_mmx in current_settings.localswitches) and
  759. is_mmx_able_array(left.resultdef) then
  760. expectloc:=LOC_MMXREGISTER
  761. {$endif SUPPORT_MMX}
  762. else if (left.resultdef.typ=orddef) then
  763. expectloc:=LOC_REGISTER;
  764. end;
  765. end;
  766. {****************************************************************************
  767. TUNARYPLUSNODE
  768. ****************************************************************************}
  769. constructor tunaryplusnode.create(expr: tnode);
  770. begin
  771. inherited create(unaryplusn,expr);
  772. end;
  773. function tunaryplusnode.pass_1: tnode;
  774. begin
  775. result:=nil;
  776. { can never happen because all the conversions happen
  777. in pass_typecheck }
  778. internalerror(201012250);
  779. end;
  780. function tunaryplusnode.pass_typecheck: tnode;
  781. var
  782. t:tnode;
  783. begin
  784. result:=nil;
  785. typecheckpass(left);
  786. set_varstate(left,vs_read,[vsf_must_be_valid]);
  787. if codegenerror then
  788. exit;
  789. if is_constintnode(left) or
  790. is_constrealnode(left) or
  791. (left.resultdef.typ=floatdef) or
  792. is_currency(left.resultdef)
  793. {$ifdef SUPPORT_MMX}
  794. or ((cs_mmx in current_settings.localswitches) and
  795. is_mmx_able_array(left.resultdef))
  796. {$endif SUPPORT_MMX}
  797. then
  798. begin
  799. result:=left;
  800. left:=nil;
  801. end
  802. {$ifndef cpu64bitaddr}
  803. else if is_64bit(left.resultdef) then
  804. begin
  805. inserttypeconv(left,s64inttype);
  806. result:=left;
  807. left:=nil;
  808. end
  809. {$endif not cpu64bitaddr}
  810. else if (left.resultdef.typ=orddef) then
  811. begin
  812. inserttypeconv(left,sinttype);
  813. result:=left;
  814. left:=nil;
  815. end
  816. else
  817. begin
  818. { allow operator overloading }
  819. t:=self;
  820. if isunaryoverloaded(t) then
  821. begin
  822. result:=t;
  823. exit;
  824. end;
  825. CGMessage(type_e_mismatch);
  826. end;
  827. end;
  828. {****************************************************************************
  829. TNOTNODE
  830. ****************************************************************************}
  831. const
  832. boolean_reverse:array[ltn..unequaln] of Tnodetype=(
  833. gten,gtn,lten,ltn,unequaln,equaln
  834. );
  835. constructor tnotnode.create(expr : tnode);
  836. begin
  837. inherited create(notn,expr);
  838. end;
  839. function tnotnode.simplify(forinline : boolean):tnode;
  840. var
  841. v : tconstexprint;
  842. t : tnode;
  843. def : tdef;
  844. begin
  845. result:=nil;
  846. { Try optmimizing ourself away }
  847. if left.nodetype=notn then
  848. begin
  849. { Double not. Remove both }
  850. result:=Tnotnode(left).left;
  851. tnotnode(left).left:=nil;
  852. exit;
  853. end;
  854. if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
  855. begin
  856. { Not of boolean expression. Turn around the operator and remove
  857. the not. This is not allowed for sets with the gten/lten,
  858. because there is no ltn/gtn support }
  859. if (taddnode(left).left.resultdef.typ<>setdef) or
  860. (left.nodetype in [equaln,unequaln]) then
  861. begin
  862. result:=left;
  863. left.nodetype:=boolean_reverse[left.nodetype];
  864. left:=nil;
  865. exit;
  866. end;
  867. end;
  868. { constant folding }
  869. if (left.nodetype=ordconstn) then
  870. begin
  871. v:=tordconstnode(left).value;
  872. def:=left.resultdef;
  873. case torddef(left.resultdef).ordtype of
  874. pasbool8,
  875. pasbool16,
  876. pasbool32,
  877. pasbool64,
  878. bool8bit,
  879. bool16bit,
  880. bool32bit,
  881. bool64bit:
  882. begin
  883. v:=byte(not(boolean(int64(v))));
  884. if is_cbool(left.resultdef) then
  885. v:=-v;
  886. end;
  887. uchar,
  888. uwidechar,
  889. u8bit,
  890. s8bit,
  891. u16bit,
  892. s16bit,
  893. s32bit,
  894. {$ifdef cpu64bitaddr}
  895. u32bit,
  896. {$endif cpu64bitaddr}
  897. s64bit:
  898. begin
  899. v:=int64(not int64(v));
  900. if (torddef(left.resultdef).ordtype<>s64bit) then
  901. def:=sinttype
  902. else
  903. def:=s64inttype;
  904. end;
  905. {$ifndef cpu64bitaddr}
  906. u32bit,
  907. {$endif not cpu64bitaddr}
  908. u64bit :
  909. begin
  910. { Delphi-compatible: not dword = dword (not word = longint) }
  911. { Extension: not qword = qword }
  912. v:=qword(not qword(v));
  913. { will be truncated by the ordconstnode for u32bit }
  914. end;
  915. else
  916. CGMessage(type_e_mismatch);
  917. end;
  918. { not-nodes are not range checked by the code generator -> also
  919. don't range check while inlining; the resultdef is a bit tricky
  920. though: the node's resultdef gets changed in most cases compared
  921. to left, but the not-operation itself is caried out in the code
  922. generator using the size of left
  923. }
  924. if not(forinline) then
  925. t:=cordconstnode.create(v,def,false)
  926. else
  927. begin
  928. { cut off the value if necessary }
  929. t:=cordconstnode.create(v,left.resultdef,false);
  930. { now convert to node's resultdef }
  931. inserttypeconv_explicit(t,def);
  932. end;
  933. result:=t;
  934. exit;
  935. end;
  936. end;
  937. function tnotnode.pass_typecheck : tnode;
  938. var
  939. t : tnode;
  940. begin
  941. result:=nil;
  942. typecheckpass(left);
  943. set_varstate(left,vs_read,[vsf_must_be_valid]);
  944. if codegenerror then
  945. exit;
  946. { tp procvar support }
  947. maybe_call_procvar(left,true);
  948. resultdef:=left.resultdef;
  949. result:=simplify(false);
  950. if assigned(result) then
  951. exit;
  952. if is_boolean(resultdef) then
  953. begin
  954. end
  955. else
  956. {$ifdef SUPPORT_MMX}
  957. if (cs_mmx in current_settings.localswitches) and
  958. is_mmx_able_array(left.resultdef) then
  959. begin
  960. end
  961. else
  962. {$endif SUPPORT_MMX}
  963. {$ifndef cpu64bitaddr}
  964. if is_64bitint(left.resultdef) then
  965. begin
  966. end
  967. else
  968. {$endif not cpu64bitaddr}
  969. if is_integer(left.resultdef) then
  970. begin
  971. end
  972. else
  973. begin
  974. { allow operator overloading }
  975. t:=self;
  976. if isunaryoverloaded(t) then
  977. begin
  978. result:=t;
  979. exit;
  980. end;
  981. CGMessage(type_e_mismatch);
  982. end;
  983. end;
  984. function tnotnode.pass_1 : tnode;
  985. begin
  986. result:=nil;
  987. firstpass(left);
  988. if codegenerror then
  989. exit;
  990. expectloc:=left.expectloc;
  991. if is_boolean(resultdef) then
  992. begin
  993. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  994. expectloc:=LOC_REGISTER;
  995. { before loading it into flags we need to load it into
  996. a register thus 1 register is need PM }
  997. {$ifdef cpuflags}
  998. if left.expectloc<>LOC_JUMP then
  999. expectloc:=LOC_FLAGS;
  1000. {$endif def cpuflags}
  1001. end
  1002. else
  1003. {$ifdef SUPPORT_MMX}
  1004. if (cs_mmx in current_settings.localswitches) and
  1005. is_mmx_able_array(left.resultdef) then
  1006. expectloc:=LOC_MMXREGISTER
  1007. else
  1008. {$endif SUPPORT_MMX}
  1009. {$ifndef cpu64bitalu}
  1010. if is_64bit(left.resultdef) then
  1011. begin
  1012. if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1013. expectloc:=LOC_REGISTER;
  1014. end
  1015. else
  1016. {$endif not cpu64bitalu}
  1017. if is_integer(left.resultdef) then
  1018. expectloc:=LOC_REGISTER;
  1019. end;
  1020. {$ifdef state_tracking}
  1021. function Tnotnode.track_state_pass(exec_known:boolean):boolean;
  1022. begin
  1023. track_state_pass:=true;
  1024. if left.track_state_pass(exec_known) then
  1025. begin
  1026. left.resultdef:=nil;
  1027. do_typecheckpass(left);
  1028. end;
  1029. end;
  1030. {$endif}
  1031. end.