nmat.pas 53 KB

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