nmat.pas 36 KB

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