nmat.pas 37 KB

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