nmat.pas 46 KB

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