ncgmem.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for memory related nodes which are
  5. the same for 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. { This unit generate assembler for memory related nodes.
  20. }
  21. unit ncgmem;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cgbase,cpuinfo,cpubase,
  26. node,nmem;
  27. type
  28. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgloadparentfpnode = class(tloadparentfpnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgaddrnode = class(taddrnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgderefnode = class(tderefnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgsubscriptnode = class(tsubscriptnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgwithnode = class(twithnode)
  44. procedure pass_2;override;
  45. end;
  46. tcgvecnode = class(tvecnode)
  47. private
  48. procedure rangecheck_array;
  49. protected
  50. function get_mul_size : longint;
  51. {# This routine is used to calculate the address of the reference.
  52. On entry reg contains the index in the array,
  53. and l contains the size of each element in the array.
  54. This routine should update location.reference correctly,
  55. so it points to the correct address.
  56. }
  57. procedure update_reference_reg_mul(reg:tregister;l:aword);virtual;
  58. procedure second_wideansistring;virtual;
  59. procedure second_dynamicarray;virtual;
  60. public
  61. procedure pass_2;override;
  62. end;
  63. implementation
  64. uses
  65. {$ifdef delphi}
  66. sysutils,
  67. {$else}
  68. strings,
  69. {$endif}
  70. {$ifdef GDB}
  71. gdb,
  72. {$endif GDB}
  73. globtype,systems,
  74. cutils,verbose,globals,
  75. symconst,symdef,symsym,symtable,defutil,paramgr,
  76. aasmbase,aasmtai,
  77. procinfo,pass_2,
  78. pass_1,nld,ncon,nadd,
  79. cgobj,tgobj,rgobj,ncgutil,symbase
  80. ;
  81. {*****************************************************************************
  82. TCGLOADVMTADDRNODE
  83. *****************************************************************************}
  84. procedure tcgloadvmtaddrnode.pass_2;
  85. var
  86. href : treference;
  87. begin
  88. location_reset(location,LOC_REGISTER,OS_ADDR);
  89. if (left.nodetype<>typen) then
  90. begin
  91. { left contains self, load vmt from self }
  92. secondpass(left);
  93. if is_object(left.resulttype.def) then
  94. begin
  95. case left.location.loc of
  96. LOC_CREFERENCE,
  97. LOC_REFERENCE:
  98. begin
  99. location_release(exprasmlist,left.location);
  100. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  101. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,href.base);
  102. end;
  103. else
  104. internalerror(200305056);
  105. end;
  106. end
  107. else
  108. begin
  109. case left.location.loc of
  110. LOC_REGISTER:
  111. begin
  112. if not rg.isaddressregister(left.location.register) then
  113. begin
  114. location_release(exprasmlist,left.location);
  115. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  116. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,href.base);
  117. end
  118. else
  119. reference_reset_base(href,left.location.register,tobjectdef(left.resulttype.def).vmt_offset);
  120. end;
  121. LOC_CREGISTER,
  122. LOC_CREFERENCE,
  123. LOC_REFERENCE:
  124. begin
  125. location_release(exprasmlist,left.location);
  126. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  127. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,href.base);
  128. end;
  129. else
  130. internalerror(200305057);
  131. end;
  132. end;
  133. reference_release(exprasmlist,href);
  134. location.register:=rg.getaddressregister(exprasmlist);
  135. cg.g_maybe_testself(exprasmlist,href.base);
  136. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  137. end
  138. else
  139. begin
  140. reference_reset_symbol(href,
  141. objectlibrary.newasmsymboldata(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),0);
  142. location.register:=rg.getaddressregister(exprasmlist);
  143. cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
  144. end;
  145. end;
  146. {*****************************************************************************
  147. TCGLOADPARENTFPNODE
  148. *****************************************************************************}
  149. procedure tcgloadparentfpnode.pass_2;
  150. var
  151. currpi : tprocinfo;
  152. hsym : tvarsym;
  153. href : treference;
  154. begin
  155. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  156. begin
  157. location_reset(location,LOC_REGISTER,OS_ADDR);
  158. location.register:=current_procinfo.framepointer;
  159. end
  160. else
  161. begin
  162. currpi:=current_procinfo;
  163. location_reset(location,LOC_REGISTER,OS_ADDR);
  164. location.register:=rg.getaddressregister(exprasmlist);
  165. { load framepointer of current proc }
  166. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  167. if not assigned(hsym) then
  168. internalerror(200309281);
  169. case hsym.localloc.loc of
  170. LOC_REFERENCE :
  171. begin
  172. reference_reset_base(href,hsym.localloc.reference.index,hsym.localloc.reference.offset);
  173. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  174. end;
  175. LOC_REGISTER :
  176. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,hsym.localloc.register,location.register);
  177. end;
  178. { walk parents }
  179. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  180. begin
  181. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  182. if not assigned(hsym) then
  183. internalerror(200309282);
  184. if hsym.localloc.loc<>LOC_REFERENCE then
  185. internalerror(200309283);
  186. reference_reset_base(href,location.register,hsym.localloc.reference.offset);
  187. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  188. currpi:=currpi.parent;
  189. end;
  190. end;
  191. end;
  192. {*****************************************************************************
  193. TCGADDRNODE
  194. *****************************************************************************}
  195. procedure tcgaddrnode.pass_2;
  196. begin
  197. secondpass(left);
  198. { when loading procvar we do nothing with this node, so load the
  199. location of left }
  200. if nf_procvarload in flags then
  201. begin
  202. location_copy(location,left.location);
  203. exit;
  204. end;
  205. location_release(exprasmlist,left.location);
  206. location_reset(location,LOC_REGISTER,OS_ADDR);
  207. location.register:=rg.getaddressregister(exprasmlist);
  208. { @ on a procvar means returning an address to the procedure that
  209. is stored in it }
  210. if (m_tp_procvar in aktmodeswitches) and
  211. (left.nodetype=loadn) and
  212. (tloadnode(left).resulttype.def.deftype=procvardef) and
  213. assigned(tloadnode(left).symtableentry) and
  214. (tloadnode(left).symtableentry.typ=varsym) then
  215. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register)
  216. else
  217. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  218. end;
  219. {*****************************************************************************
  220. TCGDEREFNODE
  221. *****************************************************************************}
  222. procedure tcgderefnode.pass_2;
  223. var
  224. paraloc1 : tparalocation;
  225. begin
  226. secondpass(left);
  227. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  228. case left.location.loc of
  229. LOC_REGISTER:
  230. begin
  231. if not rg.isaddressregister(left.location.register) then
  232. begin
  233. location_release(exprasmlist,left.location);
  234. location.reference.base := rg.getaddressregister(exprasmlist);
  235. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
  236. location.reference.base);
  237. end
  238. else
  239. location.reference.base := left.location.register;
  240. end;
  241. LOC_CREGISTER,
  242. LOC_CREFERENCE,
  243. LOC_REFERENCE:
  244. begin
  245. location_release(exprasmlist,left.location);
  246. location.reference.base:=rg.getaddressregister(exprasmlist);
  247. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  248. end;
  249. end;
  250. if (cs_gdb_heaptrc in aktglobalswitches) and
  251. (cs_checkpointer in aktglobalswitches) and
  252. not(cs_compilesystem in aktmoduleswitches) and
  253. (not tpointerdef(left.resulttype.def).is_far) then
  254. begin
  255. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  256. paramanager.allocparaloc(exprasmlist,paraloc1);
  257. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  258. paramanager.freeparaloc(exprasmlist,paraloc1);
  259. { FPC_CHECKPOINTER uses saveregisters }
  260. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  261. end;
  262. end;
  263. {*****************************************************************************
  264. TCGSUBSCRIPTNODE
  265. *****************************************************************************}
  266. procedure tcgsubscriptnode.pass_2;
  267. var
  268. paraloc1 : tparalocation;
  269. begin
  270. secondpass(left);
  271. if codegenerror then
  272. exit;
  273. { classes and interfaces must be dereferenced implicit }
  274. if is_class_or_interface(left.resulttype.def) then
  275. begin
  276. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  277. case left.location.loc of
  278. LOC_CREGISTER,
  279. LOC_REGISTER:
  280. begin
  281. if not rg.isaddressregister(left.location.register) then
  282. begin
  283. location_release(exprasmlist,left.location);
  284. location.reference.base:=rg.getaddressregister(exprasmlist);
  285. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  286. left.location.register,location.reference.base);
  287. end
  288. else
  289. location.reference.base := left.location.register;
  290. end;
  291. LOC_CREFERENCE,
  292. LOC_REFERENCE:
  293. begin
  294. location_release(exprasmlist,left.location);
  295. location.reference.base:=rg.getaddressregister(exprasmlist);
  296. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  297. end;
  298. end;
  299. { implicit deferencing }
  300. if (cs_gdb_heaptrc in aktglobalswitches) and
  301. (cs_checkpointer in aktglobalswitches) and
  302. not(cs_compilesystem in aktmoduleswitches) then
  303. begin
  304. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  305. paramanager.allocparaloc(exprasmlist,paraloc1);
  306. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  307. paramanager.freeparaloc(exprasmlist,paraloc1);
  308. { FPC_CHECKPOINTER uses saveregisters }
  309. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  310. end;
  311. end
  312. else if is_interfacecom(left.resulttype.def) then
  313. begin
  314. tg.GetTemp(exprasmlist,pointer_size,tt_interfacecom,location.reference);
  315. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,location.reference);
  316. { implicit deferencing also for interfaces }
  317. if (cs_gdb_heaptrc in aktglobalswitches) and
  318. (cs_checkpointer in aktglobalswitches) and
  319. not(cs_compilesystem in aktmoduleswitches) then
  320. begin
  321. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  322. paramanager.allocparaloc(exprasmlist,paraloc1);
  323. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  324. paramanager.freeparaloc(exprasmlist,paraloc1);
  325. { FPC_CHECKPOINTER uses saveregisters }
  326. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  327. end;
  328. end
  329. else
  330. location_copy(location,left.location);
  331. inc(location.reference.offset,vs.fieldoffset);
  332. { also update the size of the location }
  333. location.size:=def_cgsize(resulttype.def);
  334. end;
  335. {*****************************************************************************
  336. TCGWITHNODE
  337. *****************************************************************************}
  338. procedure tcgwithnode.pass_2;
  339. {$ifdef GDB}
  340. const
  341. withlevel : longint = 0;
  342. var
  343. withstartlabel,withendlabel : tasmlabel;
  344. pp : pchar;
  345. mangled_length : longint;
  346. refnode : tnode;
  347. {$endif GDB}
  348. begin
  349. location_reset(location,LOC_VOID,OS_NO);
  350. {$ifdef GDB}
  351. if (cs_debuginfo in aktmoduleswitches) then
  352. begin
  353. { load reference }
  354. if (withrefnode.nodetype=derefn) and
  355. (tderefnode(withrefnode).left.nodetype=temprefn) then
  356. refnode:=tderefnode(withrefnode).left
  357. else
  358. refnode:=withrefnode;
  359. secondpass(refnode);
  360. location_release(exprasmlist,refnode.location);
  361. location_freetemp(exprasmlist,refnode.location);
  362. if not(refnode.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  363. internalerror(2003092810);
  364. inc(withlevel);
  365. objectlibrary.getaddrlabel(withstartlabel);
  366. objectlibrary.getaddrlabel(withendlabel);
  367. cg.a_label(exprasmlist,withstartlabel);
  368. withdebugList.concat(Tai_stabs.Create(strpnew(
  369. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  370. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  371. tostr(N_LSYM)+',0,0,'+tostr(refnode.location.reference.offset))));
  372. mangled_length:=length(current_procinfo.procdef.mangledname);
  373. getmem(pp,mangled_length+50);
  374. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  375. if (target_info.use_function_relative_addresses) then
  376. begin
  377. strpcopy(strend(pp),'-');
  378. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  379. end;
  380. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  381. end;
  382. {$endif GDB}
  383. if assigned(left) then
  384. secondpass(left);
  385. {$ifdef GDB}
  386. if (cs_debuginfo in aktmoduleswitches) then
  387. begin
  388. cg.a_label(exprasmlist,withendlabel);
  389. strpcopy(pp,'224,0,0,'+withendlabel.name);
  390. if (target_info.use_function_relative_addresses) then
  391. begin
  392. strpcopy(strend(pp),'-');
  393. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  394. end;
  395. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  396. freemem(pp,mangled_length+50);
  397. dec(withlevel);
  398. end;
  399. {$endif GDB}
  400. end;
  401. {*****************************************************************************
  402. TCGVECNODE
  403. *****************************************************************************}
  404. function tcgvecnode.get_mul_size : longint;
  405. begin
  406. if nf_memindex in flags then
  407. get_mul_size:=1
  408. else
  409. begin
  410. if (left.resulttype.def.deftype=arraydef) then
  411. get_mul_size:=tarraydef(left.resulttype.def).elesize
  412. else
  413. get_mul_size:=resulttype.def.size;
  414. end
  415. end;
  416. procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aword);
  417. var
  418. hreg: tregister;
  419. begin
  420. if location.reference.base=NR_NO then
  421. begin
  422. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  423. location.reference.base:=reg;
  424. end
  425. else if location.reference.index=NR_NO then
  426. begin
  427. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  428. location.reference.index:=reg;
  429. end
  430. else
  431. begin
  432. rg.ungetreference(exprasmlist,location.reference);
  433. hreg := rg.getaddressregister(exprasmlist);
  434. cg.a_loadaddr_ref_reg(exprasmlist,location.reference,hreg);
  435. reference_reset_base(location.reference,hreg,0);
  436. { insert new index register }
  437. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  438. location.reference.index:=reg;
  439. end;
  440. end;
  441. procedure tcgvecnode.second_wideansistring;
  442. begin
  443. end;
  444. procedure tcgvecnode.second_dynamicarray;
  445. begin
  446. end;
  447. procedure tcgvecnode.rangecheck_array;
  448. var
  449. freereg : boolean;
  450. hightree : tnode;
  451. poslabel,
  452. neglabel : tasmlabel;
  453. hreg : tregister;
  454. paraloc1,paraloc2 : tparalocation;
  455. begin
  456. if is_open_array(left.resulttype.def) or
  457. is_array_of_const(left.resulttype.def) then
  458. begin
  459. { cdecl functions don't have high() so we can not check the range }
  460. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  461. begin
  462. { Get high value }
  463. hightree:=load_high_value_node(tvarsym(tloadnode(left).symtableentry));
  464. { it must be available }
  465. if not assigned(hightree) then
  466. internalerror(200212201);
  467. firstpass(hightree);
  468. secondpass(hightree);
  469. { generate compares }
  470. freereg:=false;
  471. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  472. hreg:=right.location.register
  473. else
  474. begin
  475. hreg:=rg.getregisterint(exprasmlist,OS_INT);
  476. freereg:=true;
  477. cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hreg);
  478. end;
  479. objectlibrary.getlabel(neglabel);
  480. objectlibrary.getlabel(poslabel);
  481. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
  482. location_release(exprasmlist,hightree.location);
  483. cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  484. if freereg then
  485. rg.ungetregisterint(exprasmlist,hreg);
  486. cg.a_label(exprasmlist,poslabel);
  487. cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
  488. cg.a_label(exprasmlist,neglabel);
  489. { release hightree }
  490. hightree.free;
  491. end;
  492. end
  493. else
  494. if is_dynamic_array(left.resulttype.def) then
  495. begin
  496. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  497. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  498. paramanager.allocparaloc(exprasmlist,paraloc2);
  499. cg.a_param_loc(exprasmlist,right.location,paraloc2);
  500. paramanager.allocparaloc(exprasmlist,paraloc1);
  501. cg.a_param_loc(exprasmlist,left.location,paraloc1);
  502. paramanager.freeparaloc(exprasmlist,paraloc1);
  503. paramanager.freeparaloc(exprasmlist,paraloc2);
  504. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  505. cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
  506. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  507. end
  508. else
  509. cg.g_rangecheck(exprasmlist,right.location,right.resulttype.def,left.resulttype.def);
  510. end;
  511. procedure tcgvecnode.pass_2;
  512. var
  513. extraoffset : longint;
  514. t : tnode;
  515. href : treference;
  516. otl,ofl : tasmlabel;
  517. newsize : tcgsize;
  518. mulsize: longint;
  519. isjump : boolean;
  520. paraloc1,paraloc2 : tparalocation;
  521. begin
  522. mulsize := get_mul_size;
  523. newsize:=def_cgsize(resulttype.def);
  524. secondpass(left);
  525. if left.location.loc=LOC_CREFERENCE then
  526. location_reset(location,LOC_CREFERENCE,newsize)
  527. else
  528. location_reset(location,LOC_REFERENCE,newsize);
  529. { an ansistring needs to be dereferenced }
  530. if is_ansistring(left.resulttype.def) or
  531. is_widestring(left.resulttype.def) then
  532. begin
  533. if nf_callunique in flags then
  534. internalerror(200304236);
  535. case left.location.loc of
  536. LOC_REGISTER,
  537. LOC_CREGISTER :
  538. location.reference.base:=left.location.register;
  539. LOC_CREFERENCE,
  540. LOC_REFERENCE :
  541. begin
  542. location_release(exprasmlist,left.location);
  543. location.reference.base:=rg.getaddressregister(exprasmlist);
  544. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  545. end;
  546. else
  547. internalerror(2002032218);
  548. end;
  549. { check for a zero length string,
  550. we can use the ansistring routine here }
  551. if (cs_check_range in aktlocalswitches) then
  552. begin
  553. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  554. paramanager.allocparaloc(exprasmlist,paraloc1);
  555. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paraloc1);
  556. paramanager.freeparaloc(exprasmlist,paraloc1);
  557. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  558. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  559. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  560. end;
  561. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  562. if is_ansistring(left.resulttype.def) then
  563. dec(location.reference.offset)
  564. else
  565. dec(location.reference.offset,2);
  566. end
  567. else if is_dynamic_array(left.resulttype.def) then
  568. begin
  569. case left.location.loc of
  570. LOC_REGISTER,
  571. LOC_CREGISTER :
  572. location.reference.base:=left.location.register;
  573. LOC_REFERENCE,
  574. LOC_CREFERENCE :
  575. begin
  576. location_release(exprasmlist,left.location);
  577. location.reference.base:=rg.getaddressregister(exprasmlist);
  578. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,
  579. left.location.reference,location.reference.base);
  580. end;
  581. else
  582. internalerror(2002032219);
  583. end;
  584. end
  585. else
  586. location_copy(location,left.location);
  587. { offset can only differ from 0 if arraydef }
  588. if (left.resulttype.def.deftype=arraydef) and
  589. not(is_dynamic_array(left.resulttype.def)) then
  590. dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
  591. if right.nodetype=ordconstn then
  592. begin
  593. { offset can only differ from 0 if arraydef }
  594. case left.resulttype.def.deftype of
  595. arraydef :
  596. begin
  597. if not(is_open_array(left.resulttype.def)) and
  598. not(is_array_of_const(left.resulttype.def)) and
  599. not(is_dynamic_array(left.resulttype.def)) then
  600. begin
  601. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  602. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  603. begin
  604. { this should be caught in the resulttypepass! (JM) }
  605. if (cs_check_range in aktlocalswitches) then
  606. CGMessage(parser_e_range_check_error)
  607. else
  608. CGMessage(parser_w_range_check_error);
  609. end;
  610. end
  611. else
  612. begin
  613. { range checking for open and dynamic arrays needs
  614. runtime code }
  615. secondpass(right);
  616. if (cs_check_range in aktlocalswitches) then
  617. rangecheck_array;
  618. end;
  619. end;
  620. stringdef :
  621. begin
  622. if (cs_check_range in aktlocalswitches) then
  623. begin
  624. case tstringdef(left.resulttype.def).string_typ of
  625. { it's the same for ansi- and wide strings }
  626. st_widestring,
  627. st_ansistring:
  628. begin
  629. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  630. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  631. paramanager.allocparaloc(exprasmlist,paraloc2);
  632. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paraloc2);
  633. href:=location.reference;
  634. dec(href.offset,7);
  635. paramanager.allocparaloc(exprasmlist,paraloc1);
  636. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  637. paramanager.freeparaloc(exprasmlist,paraloc1);
  638. paramanager.freeparaloc(exprasmlist,paraloc2);
  639. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  640. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  641. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  642. end;
  643. st_shortstring:
  644. begin
  645. {!!!!!!!!!!!!!!!!!}
  646. end;
  647. st_longstring:
  648. begin
  649. {!!!!!!!!!!!!!!!!!}
  650. end;
  651. end;
  652. end;
  653. end;
  654. end;
  655. inc(location.reference.offset,
  656. mulsize*tordconstnode(right).value);
  657. end
  658. else
  659. { not nodetype=ordconstn }
  660. begin
  661. if (cs_regvars in aktglobalswitches) and
  662. { if we do range checking, we don't }
  663. { need that fancy code (it would be }
  664. { buggy) }
  665. not(cs_check_range in aktlocalswitches) and
  666. (left.resulttype.def.deftype=arraydef) then
  667. begin
  668. extraoffset:=0;
  669. if (right.nodetype=addn) then
  670. begin
  671. if taddnode(right).right.nodetype=ordconstn then
  672. begin
  673. extraoffset:=tordconstnode(taddnode(right).right).value;
  674. t:=taddnode(right).left;
  675. { First pass processed this with the assumption }
  676. { that there was an add node which may require an }
  677. { extra register. Fake it or die with IE10 (JM) }
  678. t.registers32 := taddnode(right).registers32;
  679. taddnode(right).left:=nil;
  680. right.free;
  681. right:=t;
  682. end
  683. else if taddnode(right).left.nodetype=ordconstn then
  684. begin
  685. extraoffset:=tordconstnode(taddnode(right).left).value;
  686. t:=taddnode(right).right;
  687. t.registers32 := right.registers32;
  688. taddnode(right).right:=nil;
  689. right.free;
  690. right:=t;
  691. end;
  692. end
  693. else if (right.nodetype=subn) then
  694. begin
  695. if taddnode(right).right.nodetype=ordconstn then
  696. begin
  697. extraoffset:=-tordconstnode(taddnode(right).right).value;
  698. t:=taddnode(right).left;
  699. t.registers32 := right.registers32;
  700. taddnode(right).left:=nil;
  701. right.free;
  702. right:=t;
  703. end
  704. { You also have to negate right.right in this case! I can't add an
  705. unaryminusn without causing a crash, so I've disabled it (JM)
  706. else if right.left.nodetype=ordconstn then
  707. begin
  708. extraoffset:=right.left.value;
  709. t:=right.right;
  710. t^.registers32 := right.registers32;
  711. putnode(right);
  712. putnode(right.left);
  713. right:=t;
  714. end;}
  715. end;
  716. inc(location.reference.offset,
  717. mulsize*extraoffset);
  718. end;
  719. { calculate from left to right }
  720. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  721. internalerror(200304237);
  722. isjump:=(right.location.loc=LOC_JUMP);
  723. if isjump then
  724. begin
  725. otl:=truelabel;
  726. objectlibrary.getlabel(truelabel);
  727. ofl:=falselabel;
  728. objectlibrary.getlabel(falselabel);
  729. end;
  730. secondpass(right);
  731. if cs_check_range in aktlocalswitches then
  732. begin
  733. if left.resulttype.def.deftype=arraydef then
  734. rangecheck_array;
  735. end;
  736. { if mulsize = 1, we won't have to modify the index }
  737. location_force_reg(exprasmlist,right.location,OS_32,mulsize = 1);
  738. if isjump then
  739. begin
  740. truelabel:=otl;
  741. falselabel:=ofl;
  742. end;
  743. { produce possible range check code: }
  744. if cs_check_range in aktlocalswitches then
  745. begin
  746. if left.resulttype.def.deftype=arraydef then
  747. begin
  748. { done defore (PM) }
  749. end
  750. else if (left.resulttype.def.deftype=stringdef) then
  751. begin
  752. case tstringdef(left.resulttype.def).string_typ of
  753. { it's the same for ansi- and wide strings }
  754. st_widestring,
  755. st_ansistring:
  756. begin
  757. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  758. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  759. paramanager.allocparaloc(exprasmlist,paraloc2);
  760. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paraloc2);
  761. href:=location.reference;
  762. dec(href.offset,7);
  763. paramanager.allocparaloc(exprasmlist,paraloc1);
  764. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  765. paramanager.freeparaloc(exprasmlist,paraloc1);
  766. paramanager.freeparaloc(exprasmlist,paraloc2);
  767. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  768. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  769. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  770. end;
  771. st_shortstring:
  772. begin
  773. {!!!!!!!!!!!!!!!!!}
  774. end;
  775. st_longstring:
  776. begin
  777. {!!!!!!!!!!!!!!!!!}
  778. end;
  779. end;
  780. end;
  781. end;
  782. { insert the register and the multiplication factor in the
  783. reference }
  784. update_reference_reg_mul(right.location.register,mulsize);
  785. end;
  786. location.size:=newsize;
  787. end;
  788. begin
  789. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  790. cloadparentfpnode:=tcgloadparentfpnode;
  791. caddrnode:=tcgaddrnode;
  792. cderefnode:=tcgderefnode;
  793. csubscriptnode:=tcgsubscriptnode;
  794. cwithnode:=tcgwithnode;
  795. cvecnode:=tcgvecnode;
  796. end.
  797. {
  798. $Log$
  799. Revision 1.77 2003-10-01 20:34:48 peter
  800. * procinfo unit contains tprocinfo
  801. * cginfo renamed to cgbase
  802. * moved cgmessage to verbose
  803. * fixed ppc and sparc compiles
  804. Revision 1.76 2003/09/29 20:58:56 peter
  805. * optimized releasing of registers
  806. Revision 1.75 2003/09/28 21:45:52 peter
  807. * fix register leak in with debug
  808. Revision 1.74 2003/09/28 17:55:03 peter
  809. * parent framepointer changed to hidden parameter
  810. * tloadparentfpnode added
  811. Revision 1.73 2003/09/23 17:56:05 peter
  812. * locals and paras are allocated in the code generation
  813. * tvarsym.localloc contains the location of para/local when
  814. generating code for the current procedure
  815. Revision 1.72 2003/09/10 08:31:47 marco
  816. * Patch from Peter for paraloc
  817. Revision 1.71 2003/09/07 22:09:35 peter
  818. * preparations for different default calling conventions
  819. * various RA fixes
  820. Revision 1.70 2003/09/03 15:55:00 peter
  821. * NEWRA branch merged
  822. Revision 1.69.2.1 2003/08/29 17:28:59 peter
  823. * next batch of updates
  824. Revision 1.69 2003/08/10 17:25:23 peter
  825. * fixed some reported bugs
  826. Revision 1.68 2003/08/09 18:56:54 daniel
  827. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  828. allocator
  829. * Some preventive changes to i386 spillinh code
  830. Revision 1.67 2003/07/23 11:01:14 jonas
  831. * several rg.allocexplicitregistersint/rg.deallocexplicitregistersint
  832. pairs round calls to helpers
  833. Revision 1.66 2003/07/06 21:50:33 jonas
  834. * fixed ppc compilation problems and changed VOLATILE_REGISTERS for x86
  835. so that it doesn't include ebp and esp anymore
  836. Revision 1.65 2003/07/06 15:31:20 daniel
  837. * Fixed register allocator. *Lots* of fixes.
  838. Revision 1.64 2003/06/17 19:24:08 jonas
  839. * fixed conversion of fpc_*str_unique to compilerproc
  840. Revision 1.63 2003/06/17 16:34:44 jonas
  841. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  842. * renamed all_intregisters to paramanager.get_volatile_registers_int(pocall_default) and made it
  843. processor dependent
  844. Revision 1.62 2003/06/13 21:19:30 peter
  845. * current_procdef removed, use current_procinfo.procdef instead
  846. Revision 1.61 2003/06/09 16:45:41 jonas
  847. * fixed update_reference_reg_mul() so that it won't modify CREGISTERs
  848. in a reference
  849. * cache value of get_mul_size()
  850. * if get_mul_size = 1, the index can be a CREGISTER since it won't be
  851. modified
  852. Revision 1.60 2003/06/07 18:57:04 jonas
  853. + added freeintparaloc
  854. * ppc get/freeintparaloc now check whether the parameter regs are
  855. properly allocated/deallocated (and get an extra list para)
  856. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  857. * fixed lot of missing pi_do_call's
  858. Revision 1.59 2003/06/03 21:11:09 peter
  859. * cg.a_load_* get a from and to size specifier
  860. * makeregsize only accepts newregister
  861. * i386 uses generic tcgnotnode,tcgunaryminus
  862. Revision 1.58 2003/06/03 13:01:59 daniel
  863. * Register allocator finished
  864. Revision 1.57 2003/06/02 22:35:45 florian
  865. * better handling of CREGISTER in subscript nodes
  866. Revision 1.56 2003/06/01 21:38:06 peter
  867. * getregisterfpu size parameter added
  868. * op_const_reg size parameter added
  869. * sparc updates
  870. Revision 1.55 2003/05/30 23:49:18 jonas
  871. * a_load_loc_reg now has an extra size parameter for the destination
  872. register (properly fixes what I worked around in revision 1.106 of
  873. ncgutil.pas)
  874. Revision 1.54 2003/05/15 16:10:37 florian
  875. * fixed getintparaloc call for ansi- and widestring range checking
  876. Revision 1.53 2003/05/11 21:37:03 peter
  877. * moved implicit exception frame from ncgutil to psub
  878. * constructor/destructor helpers moved from cobj/ncgutil to psub
  879. Revision 1.52 2003/05/11 14:45:12 peter
  880. * tloadnode does not support objectsymtable,withsymtable anymore
  881. * withnode cleanup
  882. * direct with rewritten to use temprefnode
  883. Revision 1.51 2003/05/09 17:47:02 peter
  884. * self moved to hidden parameter
  885. * removed hdisposen,hnewn,selfn
  886. Revision 1.50 2003/05/07 09:16:23 mazen
  887. - non used units removed from uses clause
  888. Revision 1.49 2003/04/27 11:21:33 peter
  889. * aktprocdef renamed to current_procinfo.procdef
  890. * procinfo renamed to current_procinfo
  891. * procinfo will now be stored in current_module so it can be
  892. cleaned up properly
  893. * gen_main_procsym changed to create_main_proc and release_main_proc
  894. to also generate a tprocinfo structure
  895. * fixed unit implicit initfinal
  896. Revision 1.48 2003/04/22 23:50:22 peter
  897. * firstpass uses expectloc
  898. * checks if there are differences between the expectloc and
  899. location.loc from secondpass in EXTDEBUG
  900. Revision 1.47 2003/04/22 13:47:08 peter
  901. * fixed C style array of const
  902. * fixed C array passing
  903. * fixed left to right with high parameters
  904. Revision 1.46 2003/04/22 10:09:35 daniel
  905. + Implemented the actual register allocator
  906. + Scratch registers unavailable when new register allocator used
  907. + maybe_save/maybe_restore unavailable when new register allocator used
  908. Revision 1.45 2003/04/06 21:11:23 olle
  909. * changed newasmsymbol to newasmsymboldata for data symbols
  910. Revision 1.44 2003/03/28 19:16:56 peter
  911. * generic constructor working for i386
  912. * remove fixed self register
  913. * esi added as address register for i386
  914. Revision 1.43 2003/03/12 22:43:38 jonas
  915. * more powerpc and generic fixes related to the new register allocator
  916. Revision 1.42 2003/02/19 22:00:14 daniel
  917. * Code generator converted to new register notation
  918. - Horribily outdated todo.txt removed
  919. Revision 1.41 2003/01/30 21:46:57 peter
  920. * self fixes for static methods (merged)
  921. Revision 1.40 2003/01/08 18:43:56 daniel
  922. * Tregister changed into a record
  923. Revision 1.39 2002/12/20 18:13:19 peter
  924. * no rangecheck for openarrays with cdecl
  925. Revision 1.38 2002/12/17 22:19:33 peter
  926. * fixed pushing of records>8 bytes with stdcall
  927. * simplified hightree loading
  928. Revision 1.37 2002/12/08 13:39:03 carl
  929. + some documentation added
  930. Revision 1.36 2002/12/07 14:14:19 carl
  931. * bugfix on invalid typecast
  932. Revision 1.35 2002/11/25 17:43:18 peter
  933. * splitted defbase in defutil,symutil,defcmp
  934. * merged isconvertable and is_equal into compare_defs(_ext)
  935. * made operator search faster by walking the list only once
  936. Revision 1.34 2002/11/24 18:19:20 carl
  937. + checkpointer for interfaces also
  938. Revision 1.33 2002/11/23 22:50:06 carl
  939. * some small speed optimizations
  940. + added several new warnings/hints
  941. Revision 1.32 2002/11/15 01:58:51 peter
  942. * merged changes from 1.0.7 up to 04-11
  943. - -V option for generating bug report tracing
  944. - more tracing for option parsing
  945. - errors for cdecl and high()
  946. - win32 import stabs
  947. - win32 records<=8 are returned in eax:edx (turned off by default)
  948. - heaptrc update
  949. - more info for temp management in .s file with EXTDEBUG
  950. Revision 1.31 2002/10/09 20:24:47 florian
  951. + range checking for dyn. arrays
  952. Revision 1.30 2002/10/07 21:30:45 peter
  953. * rangecheck for open arrays added
  954. Revision 1.29 2002/10/05 12:43:25 carl
  955. * fixes for Delphi 6 compilation
  956. (warning : Some features do not work under Delphi)
  957. Revision 1.28 2002/09/17 18:54:02 jonas
  958. * a_load_reg_reg() now has two size parameters: source and dest. This
  959. allows some optimizations on architectures that don't encode the
  960. register size in the register name.
  961. Revision 1.27 2002/09/07 15:25:03 peter
  962. * old logs removed and tabs fixed
  963. Revision 1.26 2002/09/01 18:46:01 peter
  964. * fixed generic tcgvecnode
  965. * move code that updates a reference with index register and multiplier
  966. to separate method so it can be overriden for scaled indexing
  967. * i386 uses generic tcgvecnode
  968. Revision 1.25 2002/08/23 16:14:48 peter
  969. * tempgen cleanup
  970. * tt_noreuse temp type added that will be used in genentrycode
  971. Revision 1.24 2002/08/15 08:13:54 carl
  972. - a_load_sym_ofs_reg removed
  973. * loadvmt now calls loadaddr_ref_reg instead
  974. Revision 1.23 2002/08/11 14:32:26 peter
  975. * renamed current_library to objectlibrary
  976. Revision 1.22 2002/08/11 13:24:12 peter
  977. * saving of asmsymbols in ppu supported
  978. * asmsymbollist global is removed and moved into a new class
  979. tasmlibrarydata that will hold the info of a .a file which
  980. corresponds with a single module. Added librarydata to tmodule
  981. to keep the library info stored for the module. In the future the
  982. objectfiles will also be stored to the tasmlibrarydata class
  983. * all getlabel/newasmsymbol and friends are moved to the new class
  984. Revision 1.21 2002/08/11 11:36:57 jonas
  985. * always first try to use base and only then index
  986. Revision 1.20 2002/08/11 06:14:40 florian
  987. * fixed powerpc compilation problems
  988. Revision 1.19 2002/08/10 14:46:29 carl
  989. + moved target_cpu_string to cpuinfo
  990. * renamed asmmode enum.
  991. * assembler reader has now less ifdef's
  992. * move from nppcmem.pas -> ncgmem.pas vec. node.
  993. Revision 1.18 2002/07/28 21:34:31 florian
  994. * more powerpc fixes
  995. + dummy tcgvecnode
  996. Revision 1.17 2002/07/11 14:41:28 florian
  997. * start of the new generic parameter handling
  998. Revision 1.16 2002/07/07 09:52:32 florian
  999. * powerpc target fixed, very simple units can be compiled
  1000. * some basic stuff for better callparanode handling, far from being finished
  1001. Revision 1.15 2002/07/01 18:46:23 peter
  1002. * internal linker
  1003. * reorganized aasm layer
  1004. Revision 1.14 2002/07/01 16:23:53 peter
  1005. * cg64 patch
  1006. * basics for currency
  1007. * asnode updates for class and interface (not finished)
  1008. Revision 1.13 2002/05/20 13:30:40 carl
  1009. * bugfix of hdisponen (base must be set, not index)
  1010. * more portability fixes
  1011. Revision 1.12 2002/05/18 13:34:09 peter
  1012. * readded missing revisions
  1013. Revision 1.11 2002/05/16 19:46:37 carl
  1014. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1015. + try to fix temp allocation (still in ifdef)
  1016. + generic constructor calls
  1017. + start of tassembler / tmodulebase class cleanup
  1018. Revision 1.9 2002/05/12 16:53:07 peter
  1019. * moved entry and exitcode to ncgutil and cgobj
  1020. * foreach gets extra argument for passing local data to the
  1021. iterator function
  1022. * -CR checks also class typecasts at runtime by changing them
  1023. into as
  1024. * fixed compiler to cycle with the -CR option
  1025. * fixed stabs with elf writer, finally the global variables can
  1026. be watched
  1027. * removed a lot of routines from cga unit and replaced them by
  1028. calls to cgobj
  1029. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1030. u32bit then the other is typecasted also to u32bit without giving
  1031. a rangecheck warning/error.
  1032. * fixed pascal calling method with reversing also the high tree in
  1033. the parast, detected by tcalcst3 test
  1034. Revision 1.8 2002/04/20 21:32:23 carl
  1035. + generic FPC_CHECKPOINTER
  1036. + first parameter offset in stack now portable
  1037. * rename some constants
  1038. + move some cpu stuff to other units
  1039. - remove unused constents
  1040. * fix stacksize for some targets
  1041. * fix generic size problems which depend now on EXTEND_SIZE constant
  1042. Revision 1.7 2002/04/15 18:58:47 carl
  1043. + target_info.size_of_pointer -> pointer_Size
  1044. Revision 1.6 2002/04/04 19:05:57 peter
  1045. * removed unused units
  1046. * use tlocation.size in cg.a_*loc*() routines
  1047. }