nmat.pas 41 KB

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