nmat.pas 41 KB

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