ncgcon.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate assembler for constant nodes which are the same for
  5. all (most) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgcon;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,ncon;
  24. type
  25. tcgrealconstnode = class(trealconstnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgordconstnode = class(tordconstnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgpointerconstnode = class(tpointerconstnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgstringconstnode = class(tstringconstnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgsetconstnode = class(tsetconstnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgnilnode = class(tnilnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgguidconstnode = class(tguidconstnode)
  44. procedure pass_2;override;
  45. end;
  46. implementation
  47. uses
  48. globtype,widestr,systems,
  49. verbose,globals,
  50. symconst,symdef,aasm,types,
  51. cpuinfo,cpubase,
  52. cginfo,cgbase,tgobj,rgobj;
  53. {*****************************************************************************
  54. TCGREALCONSTNODE
  55. *****************************************************************************}
  56. procedure tcgrealconstnode.pass_2;
  57. { I suppose the parser/pass_1 must make sure the generated real }
  58. { constants are actually supported by the target processor? (JM) }
  59. const
  60. floattype2ait:array[tfloattype] of tait=
  61. (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit);
  62. var
  63. hp1 : tai;
  64. lastlabel : tasmlabel;
  65. realait : tait;
  66. begin
  67. location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
  68. lastlabel:=nil;
  69. realait:=floattype2ait[tfloatdef(resulttype.def).typ];
  70. { const already used ? }
  71. if not assigned(lab_real) then
  72. begin
  73. { tries to find an old entry }
  74. hp1:=tai(Consts.first);
  75. while assigned(hp1) do
  76. begin
  77. if hp1.typ=ait_label then
  78. lastlabel:=tai_label(hp1).l
  79. else
  80. begin
  81. if (hp1.typ=realait) and (lastlabel<>nil) then
  82. begin
  83. if(
  84. ((realait=ait_real_32bit) and (tai_real_32bit(hp1).value=value_real)) or
  85. ((realait=ait_real_64bit) and (tai_real_64bit(hp1).value=value_real)) or
  86. ((realait=ait_real_80bit) and (tai_real_80bit(hp1).value=value_real)) or
  87. ((realait=ait_comp_64bit) and (tai_comp_64bit(hp1).value=value_real))
  88. ) then
  89. begin
  90. { found! }
  91. lab_real:=lastlabel;
  92. break;
  93. end;
  94. end;
  95. lastlabel:=nil;
  96. end;
  97. hp1:=tai(hp1.next);
  98. end;
  99. { :-(, we must generate a new entry }
  100. if not assigned(lab_real) then
  101. begin
  102. getdatalabel(lastlabel);
  103. lab_real:=lastlabel;
  104. if (cs_create_smart in aktmoduleswitches) then
  105. Consts.concat(Tai_cut.Create);
  106. Consts.concat(Tai_label.Create(lastlabel));
  107. case realait of
  108. ait_real_32bit :
  109. Consts.concat(Tai_real_32bit.Create(value_real));
  110. ait_real_64bit :
  111. Consts.concat(Tai_real_64bit.Create(value_real));
  112. ait_real_80bit :
  113. Consts.concat(Tai_real_80bit.Create(value_real));
  114. ait_comp_64bit :
  115. Consts.concat(Tai_comp_64bit.Create(value_real));
  116. else
  117. internalerror(10120);
  118. end;
  119. end;
  120. end;
  121. location.reference.symbol:=lab_real;
  122. end;
  123. {*****************************************************************************
  124. TCGORDCONSTNODE
  125. *****************************************************************************}
  126. procedure tcgordconstnode.pass_2;
  127. begin
  128. location_reset(location,LOC_CONSTANT,def_cgsize(resulttype.def));
  129. location.valuelow:=AWord(value);
  130. location.valuehigh:=AWord(value shr 32);
  131. end;
  132. {*****************************************************************************
  133. TCGPOINTERCONSTNODE
  134. *****************************************************************************}
  135. procedure tcgpointerconstnode.pass_2;
  136. begin
  137. { an integer const. behaves as a memory reference }
  138. location_reset(location,LOC_CONSTANT,OS_ADDR);
  139. location.value:=AWord(value);
  140. end;
  141. {*****************************************************************************
  142. TCGSTRINGCONSTNODE
  143. *****************************************************************************}
  144. procedure tcgstringconstnode.pass_2;
  145. var
  146. hp1 : tai;
  147. l1,l2,
  148. lastlabel : tasmlabel;
  149. pc : pchar;
  150. same_string : boolean;
  151. l,j,
  152. i,mylength : longint;
  153. begin
  154. { for empty ansistrings we could return a constant 0 }
  155. if (st_type in [st_ansistring,st_widestring]) and
  156. (len=0) then
  157. begin
  158. location_reset(location,LOC_CONSTANT,OS_ADDR);
  159. location.value:=0;
  160. exit;
  161. end;
  162. { return a constant reference in memory }
  163. location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
  164. { const already used ? }
  165. lastlabel:=nil;
  166. if not assigned(lab_str) then
  167. begin
  168. if is_shortstring(resulttype.def) then
  169. mylength:=len+2
  170. else
  171. mylength:=len+1;
  172. { widestrings can't be reused yet }
  173. if not(is_widestring(resulttype.def)) then
  174. begin
  175. { tries to found an old entry }
  176. hp1:=tai(Consts.first);
  177. while assigned(hp1) do
  178. begin
  179. if hp1.typ=ait_label then
  180. lastlabel:=tai_label(hp1).l
  181. else
  182. begin
  183. { when changing that code, be careful that }
  184. { you don't use typed consts, which are }
  185. { are also written to consts }
  186. { currently, this is no problem, because }
  187. { typed consts have no leading length or }
  188. { they have no trailing zero }
  189. if (hp1.typ=ait_string) and (lastlabel<>nil) and
  190. (tai_string(hp1).len=mylength) then
  191. begin
  192. same_string:=true;
  193. { if shortstring then check the length byte first and
  194. set the start index to 1 }
  195. if is_shortstring(resulttype.def) then
  196. begin
  197. if len<>ord(tai_string(hp1).str[0]) then
  198. same_string:=false;
  199. j:=1;
  200. end
  201. else
  202. j:=0;
  203. { don't check if the length byte was already wrong }
  204. if same_string then
  205. begin
  206. for i:=0 to len do
  207. begin
  208. if tai_string(hp1).str[j]<>value_str[i] then
  209. begin
  210. same_string:=false;
  211. break;
  212. end;
  213. inc(j);
  214. end;
  215. end;
  216. { found ? }
  217. if same_string then
  218. begin
  219. lab_str:=lastlabel;
  220. { create a new entry for ansistrings, but reuse the data }
  221. if (st_type in [st_ansistring,st_widestring]) then
  222. begin
  223. getdatalabel(l2);
  224. Consts.concat(Tai_label.Create(l2));
  225. Consts.concat(Tai_const_symbol.Create(lab_str));
  226. { return the offset of the real string }
  227. lab_str:=l2;
  228. end;
  229. break;
  230. end;
  231. end;
  232. lastlabel:=nil;
  233. end;
  234. hp1:=tai(hp1.next);
  235. end;
  236. end;
  237. { :-(, we must generate a new entry }
  238. if not assigned(lab_str) then
  239. begin
  240. getdatalabel(lastlabel);
  241. lab_str:=lastlabel;
  242. if (cs_create_smart in aktmoduleswitches) then
  243. Consts.concat(Tai_cut.Create);
  244. Consts.concat(Tai_label.Create(lastlabel));
  245. { generate an ansi string ? }
  246. case st_type of
  247. st_ansistring:
  248. begin
  249. { an empty ansi string is nil! }
  250. if len=0 then
  251. Consts.concat(Tai_const.Create_32bit(0))
  252. else
  253. begin
  254. getdatalabel(l1);
  255. getdatalabel(l2);
  256. Consts.concat(Tai_label.Create(l2));
  257. Consts.concat(Tai_const_symbol.Create(l1));
  258. Consts.concat(Tai_const.Create_32bit(len));
  259. Consts.concat(Tai_const.Create_32bit(len));
  260. Consts.concat(Tai_const.Create_32bit(-1));
  261. Consts.concat(Tai_label.Create(l1));
  262. getmem(pc,len+2);
  263. move(value_str^,pc^,len);
  264. pc[len]:=#0;
  265. { to overcome this problem we set the length explicitly }
  266. { with the ending null char }
  267. Consts.concat(Tai_string.Create_length_pchar(pc,len+1));
  268. { return the offset of the real string }
  269. lab_str:=l2;
  270. end;
  271. end;
  272. st_widestring:
  273. begin
  274. { an empty wide string is nil! }
  275. if len=0 then
  276. Consts.concat(Tai_const.Create_32bit(0))
  277. else
  278. begin
  279. getdatalabel(l1);
  280. getdatalabel(l2);
  281. Consts.concat(Tai_label.Create(l2));
  282. Consts.concat(Tai_const_symbol.Create(l1));
  283. { we use always UTF-16 coding for constants }
  284. { at least for now }
  285. { Consts.concat(Tai_const.Create_8bit(2)); }
  286. Consts.concat(Tai_const.Create_32bit(len));
  287. Consts.concat(Tai_const.Create_32bit(len));
  288. Consts.concat(Tai_const.Create_32bit(-1));
  289. Consts.concat(Tai_label.Create(l1));
  290. for i:=0 to len-1 do
  291. Consts.concat(Tai_const.Create_16bit(pcompilerwidestring(value_str)^.data[i]));
  292. { return the offset of the real string }
  293. lab_str:=l2;
  294. end;
  295. end;
  296. st_shortstring:
  297. begin
  298. { truncate strings larger than 255 chars }
  299. if len>255 then
  300. l:=255
  301. else
  302. l:=len;
  303. { also length and terminating zero }
  304. getmem(pc,l+3);
  305. move(value_str^,pc[1],l+1);
  306. pc[0]:=chr(l);
  307. { to overcome this problem we set the length explicitly }
  308. { with the ending null char }
  309. pc[l+1]:=#0;
  310. Consts.concat(Tai_string.Create_length_pchar(pc,l+2));
  311. end;
  312. end;
  313. end;
  314. end;
  315. location.reference.symbol:=lab_str;
  316. end;
  317. {*****************************************************************************
  318. TCGSETCONSTNODE
  319. *****************************************************************************}
  320. procedure tcgsetconstnode.pass_2;
  321. var
  322. hp1 : tai;
  323. lastlabel : tasmlabel;
  324. i : longint;
  325. neededtyp : tait;
  326. begin
  327. { small sets are loaded as constants }
  328. if tsetdef(resulttype.def).settype=smallset then
  329. begin
  330. location_reset(location,LOC_CONSTANT,OS_32);
  331. location.value:=PAWord(value_set)^;
  332. exit;
  333. end;
  334. location_reset(location,LOC_CREFERENCE,OS_NO);
  335. neededtyp:=ait_const_8bit;
  336. lastlabel:=nil;
  337. { const already used ? }
  338. if not assigned(lab_set) then
  339. begin
  340. { tries to found an old entry }
  341. hp1:=tai(Consts.first);
  342. while assigned(hp1) do
  343. begin
  344. if hp1.typ=ait_label then
  345. lastlabel:=tai_label(hp1).l
  346. else
  347. begin
  348. if (lastlabel<>nil) and (hp1.typ=neededtyp) then
  349. begin
  350. if (hp1.typ=ait_const_8bit) then
  351. begin
  352. { compare normal set }
  353. i:=0;
  354. while assigned(hp1) and (i<32) do
  355. begin
  356. if tai_const(hp1).value<>value_set^[i] then
  357. break;
  358. inc(i);
  359. hp1:=tai(hp1.next);
  360. end;
  361. if i=32 then
  362. begin
  363. { found! }
  364. lab_set:=lastlabel;
  365. break;
  366. end;
  367. { leave when the end of consts is reached, so no
  368. hp1.next is done }
  369. if not assigned(hp1) then
  370. break;
  371. end
  372. else
  373. begin
  374. { compare small set }
  375. if plongint(value_set)^=tai_const(hp1).value then
  376. begin
  377. { found! }
  378. lab_set:=lastlabel;
  379. break;
  380. end;
  381. end;
  382. end;
  383. lastlabel:=nil;
  384. end;
  385. hp1:=tai(hp1.next);
  386. end;
  387. { :-(, we must generate a new entry }
  388. if not assigned(lab_set) then
  389. begin
  390. getdatalabel(lastlabel);
  391. lab_set:=lastlabel;
  392. if (cs_create_smart in aktmoduleswitches) then
  393. Consts.concat(Tai_cut.Create);
  394. Consts.concat(Tai_label.Create(lastlabel));
  395. if tsetdef(resulttype.def).settype=smallset then
  396. begin
  397. move(value_set^,i,sizeof(longint));
  398. Consts.concat(Tai_const.Create_32bit(i));
  399. end
  400. else
  401. begin
  402. for i:=0 to 31 do
  403. Consts.concat(Tai_const.Create_8bit(value_set^[i]));
  404. end;
  405. end;
  406. end;
  407. location.reference.symbol:=lab_set;
  408. end;
  409. {*****************************************************************************
  410. TCGNILNODE
  411. *****************************************************************************}
  412. procedure tcgnilnode.pass_2;
  413. begin
  414. location_reset(location,LOC_CONSTANT,OS_ADDR);
  415. location.value:=0;
  416. end;
  417. {*****************************************************************************
  418. TCGPOINTERCONSTNODE
  419. *****************************************************************************}
  420. procedure tcgguidconstnode.pass_2;
  421. var
  422. tmplabel : TAsmLabel;
  423. i : integer;
  424. begin
  425. location_reset(location,LOC_CREFERENCE,OS_NO);
  426. { label for GUID }
  427. getdatalabel(tmplabel);
  428. consts.concat(Tai_label.Create(tmplabel));
  429. consts.concat(Tai_const.Create_32bit(value.D1));
  430. consts.concat(Tai_const.Create_16bit(value.D2));
  431. consts.concat(Tai_const.Create_16bit(value.D3));
  432. for i:=Low(value.D4) to High(value.D4) do
  433. consts.concat(Tai_const.Create_8bit(value.D4[i]));
  434. location.reference.symbol:=tmplabel;
  435. end;
  436. begin
  437. crealconstnode:=tcgrealconstnode;
  438. cordconstnode:=tcgordconstnode;
  439. cpointerconstnode:=tcgpointerconstnode;
  440. cstringconstnode:=tcgstringconstnode;
  441. csetconstnode:=tcgsetconstnode;
  442. cnilnode:=tcgnilnode;
  443. cguidconstnode:=tcgguidconstnode;
  444. end.
  445. {
  446. $Log$
  447. Revision 1.9 2002-05-16 19:46:37 carl
  448. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  449. + try to fix temp allocation (still in ifdef)
  450. + generic constructor calls
  451. + start of tassembler / tmodulebase class cleanup
  452. Revision 1.7 2002/04/04 19:05:57 peter
  453. * removed unused units
  454. * use tlocation.size in cg.a_*loc*() routines
  455. Revision 1.6 2002/04/02 17:11:28 peter
  456. * tlocation,treference update
  457. * LOC_CONSTANT added for better constant handling
  458. * secondadd splitted in multiple routines
  459. * location_force_reg added for loading a location to a register
  460. of a specified size
  461. * secondassignment parses now first the right and then the left node
  462. (this is compatible with Kylix). This saves a lot of push/pop especially
  463. with string operations
  464. * adapted some routines to use the new cg methods
  465. Revision 1.5 2002/03/31 20:26:34 jonas
  466. + a_loadfpu_* and a_loadmm_* methods in tcg
  467. * register allocation is now handled by a class and is mostly processor
  468. independent (+rgobj.pas and i386/rgcpu.pas)
  469. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  470. * some small improvements and fixes to the optimizer
  471. * some register allocation fixes
  472. * some fpuvaroffset fixes in the unary minus node
  473. * push/popusedregisters is now called rg.save/restoreusedregisters and
  474. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  475. also better optimizable)
  476. * fixed and optimized register saving/restoring for new/dispose nodes
  477. * LOC_FPU locations now also require their "register" field to be set to
  478. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  479. - list field removed of the tnode class because it's not used currently
  480. and can cause hard-to-find bugs
  481. Revision 1.4 2002/02/26 09:12:39 jonas
  482. * fixed problem when compiling the compiler with Delphi (reported by
  483. "Luc Langlois" <[email protected]>) (lo/hi don't work as in FPC
  484. when used with int64's under Delphi)
  485. Revision 1.3 2001/12/31 09:52:02 jonas
  486. * empty widestrings can also be optimized to the constant '0'
  487. Revision 1.2 2001/10/20 19:28:37 peter
  488. * interface 2 guid support
  489. * guid constants support
  490. Revision 1.1 2001/09/30 16:17:17 jonas
  491. * made most constant and mem handling processor independent
  492. }