nmat.pas 53 KB

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