ncgmem.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for memory related nodes which are
  4. the same for all (most?) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgmem;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cgbase,cpuinfo,cpubase,
  23. node,nmem;
  24. type
  25. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  26. procedure pass_generate_code;override;
  27. end;
  28. tcgloadparentfpnode = class(tloadparentfpnode)
  29. procedure pass_generate_code;override;
  30. end;
  31. tcgaddrnode = class(taddrnode)
  32. procedure pass_generate_code;override;
  33. end;
  34. tcgderefnode = class(tderefnode)
  35. procedure pass_generate_code;override;
  36. end;
  37. tcgsubscriptnode = class(tsubscriptnode)
  38. procedure pass_generate_code;override;
  39. end;
  40. tcgwithnode = class(twithnode)
  41. procedure pass_generate_code;override;
  42. end;
  43. tcgvecnode = class(tvecnode)
  44. function get_mul_size : aint;
  45. private
  46. procedure rangecheck_array;
  47. protected
  48. {# This routine is used to calculate the address of the reference.
  49. On entry reg contains the index in the array,
  50. and l contains the size of each element in the array.
  51. This routine should update location.reference correctly,
  52. so it points to the correct address.
  53. }
  54. procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);virtual;
  55. procedure update_reference_reg_packed(maybe_const_reg:tregister;l:aint);virtual;
  56. procedure second_wideansistring;virtual;
  57. procedure second_dynamicarray;virtual;
  58. public
  59. procedure pass_generate_code;override;
  60. end;
  61. implementation
  62. uses
  63. systems,
  64. cutils,cclasses,verbose,globals,constexp,
  65. symconst,symdef,symsym,symtable,defutil,paramgr,
  66. aasmbase,aasmtai,aasmdata,
  67. procinfo,pass_2,parabase,
  68. pass_1,nld,ncon,nadd,nutils,
  69. cgutils,cgobj,
  70. tgobj,ncgutil,objcgutl
  71. ;
  72. {*****************************************************************************
  73. TCGLOADVMTADDRNODE
  74. *****************************************************************************}
  75. procedure tcgloadvmtaddrnode.pass_generate_code;
  76. var
  77. href : treference;
  78. pool : THashSet;
  79. entry : PHashSetItem;
  80. begin
  81. location_reset(location,LOC_REGISTER,OS_ADDR);
  82. if (left.nodetype=typen) then
  83. begin
  84. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  85. if not is_objcclass(left.resultdef) then
  86. begin
  87. reference_reset_symbol(href,
  88. current_asmdata.RefAsmSymbol(tobjectdef(tclassrefdef(resultdef).pointeddef).vmt_mangledname),0,
  89. sizeof(pint));
  90. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  91. end
  92. else
  93. begin
  94. if current_asmdata.ConstPools[sp_objcclassnamerefs]=nil then
  95. current_asmdata.ConstPools[sp_objcclassnamerefs]:=THashSet.Create(64, True, False);
  96. pool:=current_asmdata.ConstPools[sp_objcclassnamerefs];
  97. entry:=pool.FindOrAdd(@tobjectdef(left.resultdef).objextname^[1],length(tobjectdef(left.resultdef).objextname^));
  98. if (target_info.system in systems_objc_nfabi) then
  99. begin
  100. { find/add necessary classref/classname pool entries }
  101. objcfinishclassrefnfpoolentry(entry,tobjectdef(left.resultdef));
  102. end
  103. else
  104. begin
  105. { find/add necessary classref/classname pool entries }
  106. objcfinishstringrefpoolentry(entry,sp_objcclassnames,sec_objc_cls_refs,sec_objc_class_names);
  107. end;
  108. reference_reset_symbol(href,tasmlabel(entry^.Data),0,sizeof(pint));
  109. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  110. end;
  111. end
  112. else
  113. begin
  114. { left contains self, load vmt from self }
  115. secondpass(left);
  116. gen_load_vmt_register(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),left.location,location.register);
  117. end;
  118. end;
  119. {*****************************************************************************
  120. TCGLOADPARENTFPNODE
  121. *****************************************************************************}
  122. procedure tcgloadparentfpnode.pass_generate_code;
  123. var
  124. currpi : tprocinfo;
  125. hsym : tparavarsym;
  126. href : treference;
  127. begin
  128. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  129. begin
  130. location_reset(location,LOC_REGISTER,OS_ADDR);
  131. location.register:=current_procinfo.framepointer;
  132. end
  133. else
  134. begin
  135. currpi:=current_procinfo;
  136. location_reset(location,LOC_REGISTER,OS_ADDR);
  137. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  138. { load framepointer of current proc }
  139. hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
  140. if not assigned(hsym) then
  141. internalerror(200309281);
  142. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,hsym.localloc,location.register);
  143. { walk parents }
  144. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  145. begin
  146. currpi:=currpi.parent;
  147. if not assigned(currpi) then
  148. internalerror(200311201);
  149. hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
  150. if not assigned(hsym) then
  151. internalerror(200309282);
  152. if hsym.localloc.loc<>LOC_REFERENCE then
  153. internalerror(200309283);
  154. reference_reset_base(href,location.register,hsym.localloc.reference.offset,sizeof(pint));
  155. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  156. end;
  157. end;
  158. end;
  159. {*****************************************************************************
  160. TCGADDRNODE
  161. *****************************************************************************}
  162. procedure tcgaddrnode.pass_generate_code;
  163. begin
  164. secondpass(left);
  165. location_reset(location,LOC_REGISTER,OS_ADDR);
  166. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  167. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  168. { on x86_64-win64, array of chars can be returned in registers, however,
  169. when passing these arrays to other functions, the compiler wants to take
  170. the address of the array so when the addrnode has been created internally,
  171. we have to force the data into memory, see also tw14388.pp
  172. }
  173. if nf_internal in flags then
  174. location_force_mem(current_asmdata.CurrAsmList,left.location)
  175. else
  176. internalerror(2006111510);
  177. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  178. end;
  179. {*****************************************************************************
  180. TCGDEREFNODE
  181. *****************************************************************************}
  182. procedure tcgderefnode.pass_generate_code;
  183. var
  184. paraloc1 : tcgpara;
  185. begin
  186. secondpass(left);
  187. { assume natural alignment, except for packed records }
  188. if not(resultdef.typ in [recorddef,objectdef]) or
  189. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  190. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),resultdef.alignment)
  191. else
  192. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),1);
  193. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE,LOC_CONSTANT]) then
  194. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,true);
  195. case left.location.loc of
  196. LOC_CREGISTER,
  197. LOC_REGISTER:
  198. begin
  199. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
  200. {$ifdef cpu_uses_separate_address_registers}
  201. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  202. begin
  203. location.reference.base := cg.getaddressregister(current_asmdata.CurrAsmList);
  204. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,
  205. location.reference.base);
  206. end
  207. else
  208. {$endif}
  209. location.reference.base := left.location.register;
  210. end;
  211. LOC_CREFERENCE,
  212. LOC_REFERENCE:
  213. begin
  214. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  215. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  216. end;
  217. LOC_CONSTANT:
  218. begin
  219. location.reference.offset:=left.location.value;
  220. end;
  221. else
  222. internalerror(200507031);
  223. end;
  224. if (cs_use_heaptrc in current_settings.globalswitches) and
  225. (cs_checkpointer in current_settings.localswitches) and
  226. not(cs_compilesystem in current_settings.moduleswitches) and
  227. not(tpointerdef(left.resultdef).is_far) and
  228. not(nf_no_checkpointer in flags) and
  229. { can be NR_NO in case of LOC_CONSTANT }
  230. (location.reference.base<>NR_NO) then
  231. begin
  232. paraloc1.init;
  233. paramanager.getintparaloc(pocall_default,1,paraloc1);
  234. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  235. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  236. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  237. paraloc1.done;
  238. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  239. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  240. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  241. end;
  242. end;
  243. {*****************************************************************************
  244. TCGSUBSCRIPTNODE
  245. *****************************************************************************}
  246. procedure tcgsubscriptnode.pass_generate_code;
  247. var
  248. sym: tasmsymbol;
  249. paraloc1 : tcgpara;
  250. hreg : tregister;
  251. tmpref: treference;
  252. sref: tsubsetreference;
  253. begin
  254. secondpass(left);
  255. if codegenerror then
  256. exit;
  257. paraloc1.init;
  258. { classes and interfaces must be dereferenced implicitly }
  259. if is_class_or_interface_or_dispinterface_or_objc(left.resultdef) then
  260. begin
  261. { the contents of a class are aligned to a sizeof(pointer) }
  262. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),sizeof(pint));
  263. case left.location.loc of
  264. LOC_CREGISTER,
  265. LOC_REGISTER:
  266. begin
  267. {$ifdef cpu_uses_separate_address_registers}
  268. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  269. begin
  270. location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
  271. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  272. left.location.register,location.reference.base);
  273. end
  274. else
  275. {$endif}
  276. location.reference.base := left.location.register;
  277. end;
  278. LOC_CREFERENCE,
  279. LOC_REFERENCE:
  280. begin
  281. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  282. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  283. end;
  284. LOC_CONSTANT:
  285. begin
  286. { can happen with @classtype(pointerconst).field }
  287. location.reference.offset:=left.location.value;
  288. end;
  289. else
  290. internalerror(2009092401);
  291. end;
  292. { implicit deferencing }
  293. if (cs_use_heaptrc in current_settings.globalswitches) and
  294. (cs_checkpointer in current_settings.localswitches) and
  295. not(cs_compilesystem in current_settings.moduleswitches) then
  296. begin
  297. paramanager.getintparaloc(pocall_default,1,paraloc1);
  298. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  299. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  300. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  301. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  302. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  303. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  304. end;
  305. end
  306. else if is_interfacecom(left.resultdef) then
  307. begin
  308. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),sizeof(pint));
  309. tg.GetTempTyped(current_asmdata.CurrAsmList,left.resultdef,tt_normal,location.reference);
  310. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference);
  311. { implicit deferencing also for interfaces }
  312. if (cs_use_heaptrc in current_settings.globalswitches) and
  313. (cs_checkpointer in current_settings.localswitches) and
  314. not(cs_compilesystem in current_settings.moduleswitches) then
  315. begin
  316. paramanager.getintparaloc(pocall_default,1,paraloc1);
  317. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  318. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  319. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  320. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  321. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  322. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  323. end;
  324. end
  325. else
  326. begin
  327. location_copy(location,left.location);
  328. { some abi's require that functions return (some) records in }
  329. { registers }
  330. case location.loc of
  331. LOC_REFERENCE,
  332. LOC_CREFERENCE:
  333. ;
  334. LOC_REGISTER,
  335. LOC_CREGISTER:
  336. begin
  337. // in case the result is not something that can be put
  338. // into an integer register (e.g.
  339. // function_returning_record().non_regable_field, or
  340. // a function returning a value > sizeof(intreg))
  341. // -> force to memory
  342. if not tstoreddef(left.resultdef).is_intregable or
  343. not tstoreddef(resultdef).is_intregable then
  344. location_force_mem(current_asmdata.CurrAsmList,location)
  345. else
  346. begin
  347. if (left.location.loc = LOC_REGISTER) then
  348. location.loc := LOC_SUBSETREG
  349. else
  350. location.loc := LOC_CSUBSETREG;
  351. location.size:=def_cgsize(resultdef);
  352. location.sreg.subsetreg := left.location.register;
  353. location.sreg.subsetregsize := left.location.size;
  354. if not is_packed_record_or_object(left.resultdef) then
  355. begin
  356. if (target_info.endian = ENDIAN_BIG) then
  357. location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize] - tcgsize2size[location.size] - vs.fieldoffset) * 8
  358. else
  359. location.sreg.startbit := (vs.fieldoffset * 8);
  360. location.sreg.bitlen := tcgsize2size[location.size] * 8;
  361. end
  362. else
  363. begin
  364. location.sreg.bitlen := resultdef.packedbitsize;
  365. if (target_info.endian = ENDIAN_BIG) then
  366. location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize]*8 - location.sreg.bitlen) - vs.fieldoffset
  367. else
  368. location.sreg.startbit := vs.fieldoffset;
  369. end;
  370. end;
  371. end;
  372. LOC_SUBSETREG,
  373. LOC_CSUBSETREG:
  374. begin
  375. location.size:=def_cgsize(resultdef);
  376. if not is_packed_record_or_object(left.resultdef) then
  377. begin
  378. if (target_info.endian = ENDIAN_BIG) then
  379. inc(location.sreg.startbit, (left.resultdef.size - tcgsize2size[location.size] - vs.fieldoffset) * 8)
  380. else
  381. inc(location.sreg.startbit, vs.fieldoffset * 8);
  382. location.sreg.bitlen := tcgsize2size[location.size] * 8;
  383. end
  384. else
  385. begin
  386. location.sreg.bitlen := resultdef.packedbitsize;
  387. if (target_info.endian = ENDIAN_BIG) then
  388. inc(location.sreg.startbit, left.location.sreg.bitlen - location.sreg.bitlen - vs.fieldoffset)
  389. else
  390. inc(location.sreg.startbit, vs.fieldoffset);
  391. end;
  392. end;
  393. else
  394. internalerror(2006031901);
  395. end;
  396. end;
  397. if is_objc_class_or_protocol(left.resultdef) and
  398. (target_info.system in systems_objc_nfabi) then
  399. begin
  400. if (location.loc<>LOC_REFERENCE) or
  401. (location.reference.index<>NR_NO) then
  402. internalerror(2009092402);
  403. { the actual field offset is stored in memory (to solve the
  404. "fragile base class" problem: this way the layout of base
  405. classes can be changed without breaking programs compiled against
  406. earlier versions)
  407. }
  408. hreg:=cg.g_indirect_sym_load(current_asmdata.CurrAsmList,vs.mangledname,false);
  409. { TODO: clean up. g_indirect_sym_load cannot perform
  410. a plain load for targets that don't need an indirect load
  411. because it's also used in ncgld, but this is not very nice...
  412. }
  413. if (hreg=NR_NO) then
  414. begin
  415. sym:=current_asmdata.RefAsmSymbol(vs.mangledname);
  416. reference_reset_symbol(tmpref,sym,0,sizeof(pint));
  417. location.reference.index:=cg.getaddressregister(current_asmdata.CurrAsmList);
  418. end
  419. else
  420. begin
  421. reference_reset_base(tmpref,hreg,0,sizeof(pint));
  422. location.reference.index:=hreg;
  423. end;
  424. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,location.reference.index);
  425. { always packrecords C -> natural alignment }
  426. location.reference.alignment:=vs.vardef.alignment;
  427. end
  428. else if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  429. begin
  430. if not is_packed_record_or_object(left.resultdef) then
  431. begin
  432. inc(location.reference.offset,vs.fieldoffset);
  433. location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset);
  434. end
  435. else if (vs.fieldoffset mod 8 = 0) and
  436. (resultdef.packedbitsize mod 8 = 0) and
  437. { is different in case of e.g. packenum 2 and an enum }
  438. { which fits in 8 bits }
  439. (resultdef.size*8 = resultdef.packedbitsize) then
  440. begin
  441. inc(location.reference.offset,vs.fieldoffset div 8);
  442. location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset div 8);
  443. end
  444. else
  445. begin
  446. sref.ref:=location.reference;
  447. sref.ref.alignment:=1;
  448. sref.bitindexreg:=NR_NO;
  449. inc(sref.ref.offset,vs.fieldoffset div 8);
  450. sref.startbit:=vs.fieldoffset mod 8;
  451. sref.bitlen:=resultdef.packedbitsize;
  452. if (left.location.loc=LOC_REFERENCE) then
  453. location.loc:=LOC_SUBSETREF
  454. else
  455. location.loc:=LOC_CSUBSETREF;
  456. location.sref:=sref;
  457. end;
  458. { also update the size of the location }
  459. location.size:=def_cgsize(resultdef);
  460. end;
  461. paraloc1.done;
  462. end;
  463. {*****************************************************************************
  464. TCGWITHNODE
  465. *****************************************************************************}
  466. procedure tcgwithnode.pass_generate_code;
  467. begin
  468. location_reset(location,LOC_VOID,OS_NO);
  469. if assigned(left) then
  470. secondpass(left);
  471. end;
  472. {*****************************************************************************
  473. TCGVECNODE
  474. *****************************************************************************}
  475. function tcgvecnode.get_mul_size : aint;
  476. begin
  477. if nf_memindex in flags then
  478. get_mul_size:=1
  479. else
  480. begin
  481. if (left.resultdef.typ=arraydef) then
  482. if not is_packed_array(left.resultdef) then
  483. get_mul_size:=tarraydef(left.resultdef).elesize
  484. else
  485. get_mul_size:=tarraydef(left.resultdef).elepackedbitsize
  486. else
  487. get_mul_size:=resultdef.size;
  488. end
  489. end;
  490. { this routine must, like any other routine, not change the contents }
  491. { of base/index registers of references, as these may be regvars. }
  492. { The register allocator can coalesce one LOC_REGISTER being moved }
  493. { into another (as their live ranges won't overlap), but not a }
  494. { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as }
  495. { the live range of the LOC_CREGISTER will most likely overlap the }
  496. { the live range of the target LOC_(C)REGISTER) }
  497. { The passed register may be a LOC_CREGISTER as well. }
  498. procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
  499. var
  500. hreg: tregister;
  501. begin
  502. if l<>1 then
  503. begin
  504. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  505. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
  506. maybe_const_reg:=hreg;
  507. end;
  508. if location.reference.base=NR_NO then
  509. location.reference.base:=maybe_const_reg
  510. else if location.reference.index=NR_NO then
  511. location.reference.index:=maybe_const_reg
  512. else
  513. begin
  514. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  515. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
  516. reference_reset_base(location.reference,hreg,0,location.reference.alignment);
  517. { insert new index register }
  518. location.reference.index:=maybe_const_reg;
  519. end;
  520. { update alignment }
  521. if (location.reference.alignment=0) then
  522. internalerror(2009020704);
  523. location.reference.alignment:=newalignment(location.reference.alignment,l);
  524. end;
  525. { see remarks for tcgvecnode.update_reference_reg_mul above }
  526. procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg:tregister;l:aint);
  527. var
  528. sref: tsubsetreference;
  529. offsetreg, hreg: tregister;
  530. alignpower: aint;
  531. temp : longint;
  532. begin
  533. { only orddefs are bitpacked. Even then we only need special code in }
  534. { case the bitpacked *byte size* is not a power of two, otherwise }
  535. { everything can be handled using the the regular array code. }
  536. if ((l mod 8) = 0) and
  537. (ispowerof2(l div 8,temp) or
  538. not is_ordinal(resultdef)
  539. {$ifndef cpu64bitalu}
  540. or is_64bitint(resultdef)
  541. {$endif not cpu64bitalu}
  542. ) then
  543. begin
  544. update_reference_reg_mul(maybe_const_reg,l div 8);
  545. exit;
  546. end;
  547. if (l > 8*sizeof(aint)) then
  548. internalerror(200608051);
  549. sref.ref := location.reference;
  550. hreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  551. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,tarraydef(left.resultdef).lowrange,maybe_const_reg,hreg);
  552. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_INT,l,hreg);
  553. { keep alignment for index }
  554. sref.ref.alignment := left.resultdef.alignment;
  555. if not ispowerof2(sref.ref.alignment,temp) then
  556. internalerror(2006081201);
  557. alignpower:=temp;
  558. offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  559. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_ADDR,3+alignpower,hreg,offsetreg);
  560. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,alignpower,offsetreg);
  561. if (sref.ref.base = NR_NO) then
  562. sref.ref.base := offsetreg
  563. else if (sref.ref.index = NR_NO) then
  564. sref.ref.index := offsetreg
  565. else
  566. begin
  567. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,sref.ref.base,offsetreg);
  568. sref.ref.base := offsetreg;
  569. end;
  570. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,(1 shl (3+alignpower))-1,hreg);
  571. sref.bitindexreg := hreg;
  572. sref.startbit := 0;
  573. sref.bitlen := resultdef.packedbitsize;
  574. if (left.location.loc = LOC_REFERENCE) then
  575. location.loc := LOC_SUBSETREF
  576. else
  577. location.loc := LOC_CSUBSETREF;
  578. location.sref := sref;
  579. end;
  580. procedure tcgvecnode.second_wideansistring;
  581. begin
  582. end;
  583. procedure tcgvecnode.second_dynamicarray;
  584. begin
  585. end;
  586. procedure tcgvecnode.rangecheck_array;
  587. var
  588. hightree : tnode;
  589. poslabel,
  590. neglabel : tasmlabel;
  591. hreg : tregister;
  592. paraloc1,paraloc2 : tcgpara;
  593. begin
  594. paraloc1.init;
  595. paraloc2.init;
  596. if is_open_array(left.resultdef) or
  597. is_array_of_const(left.resultdef) then
  598. begin
  599. { cdecl functions don't have high() so we can not check the range }
  600. { (can't use current_procdef, since it may be a nested procedure) }
  601. if not(tprocdef(tparasymtable(tparavarsym(tloadnode(left).symtableentry).owner).defowner).proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  602. begin
  603. { Get high value }
  604. hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
  605. { it must be available }
  606. if not assigned(hightree) then
  607. internalerror(200212201);
  608. firstpass(hightree);
  609. secondpass(hightree);
  610. { generate compares }
  611. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  612. hreg:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_INT)
  613. else
  614. begin
  615. hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  616. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,hreg);
  617. end;
  618. current_asmdata.getjumplabel(neglabel);
  619. current_asmdata.getjumplabel(poslabel);
  620. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_LT,0,hreg,poslabel);
  621. cg.a_cmp_loc_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  622. cg.a_label(current_asmdata.CurrAsmList,poslabel);
  623. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RANGEERROR',false);
  624. cg.a_label(current_asmdata.CurrAsmList,neglabel);
  625. { release hightree }
  626. hightree.free;
  627. end;
  628. end
  629. else
  630. if is_dynamic_array(left.resultdef) then
  631. begin
  632. paramanager.getintparaloc(pocall_default,1,paraloc1);
  633. paramanager.getintparaloc(pocall_default,2,paraloc2);
  634. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  635. cg.a_param_loc(current_asmdata.CurrAsmList,right.location,paraloc2);
  636. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  637. cg.a_param_loc(current_asmdata.CurrAsmList,left.location,paraloc1);
  638. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  639. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  640. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  641. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DYNARRAY_RANGECHECK',false);
  642. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  643. end
  644. else
  645. cg.g_rangecheck(current_asmdata.CurrAsmList,right.location,right.resultdef,left.resultdef);
  646. paraloc1.done;
  647. paraloc2.done;
  648. end;
  649. procedure tcgvecnode.pass_generate_code;
  650. var
  651. offsetdec,
  652. extraoffset : aint;
  653. t : tnode;
  654. href : treference;
  655. otl,ofl : tasmlabel;
  656. newsize : tcgsize;
  657. mulsize,
  658. bytemulsize,
  659. alignpow : aint;
  660. isjump : boolean;
  661. paraloc1,
  662. paraloc2 : tcgpara;
  663. subsetref : tsubsetreference;
  664. temp : longint;
  665. begin
  666. paraloc1.init;
  667. paraloc2.init;
  668. mulsize:=get_mul_size;
  669. if not is_packed_array(left.resultdef) then
  670. bytemulsize:=mulsize
  671. else
  672. bytemulsize:=mulsize div 8;
  673. newsize:=def_cgsize(resultdef);
  674. secondpass(left);
  675. if left.location.loc=LOC_CREFERENCE then
  676. location_reset_ref(location,LOC_CREFERENCE,newsize,left.location.reference.alignment)
  677. else
  678. location_reset_ref(location,LOC_REFERENCE,newsize,left.location.reference.alignment);
  679. { an ansistring needs to be dereferenced }
  680. if is_ansistring(left.resultdef) or
  681. is_widestring(left.resultdef) or
  682. is_unicodestring(left.resultdef) then
  683. begin
  684. if nf_callunique in flags then
  685. internalerror(200304236);
  686. {DM!!!!!}
  687. case left.location.loc of
  688. LOC_REGISTER,
  689. LOC_CREGISTER :
  690. begin
  691. {$ifdef m68k}
  692. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  693. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,location.reference.base);
  694. {$else m68k}
  695. location.reference.base:=left.location.register;
  696. {$endif m68k}
  697. end;
  698. LOC_CREFERENCE,
  699. LOC_REFERENCE :
  700. begin
  701. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  702. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  703. end;
  704. else
  705. internalerror(2002032218);
  706. end;
  707. { check for a zero length string,
  708. we can use the ansistring routine here }
  709. if (cs_check_range in current_settings.localswitches) then
  710. begin
  711. paramanager.getintparaloc(pocall_default,1,paraloc1);
  712. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  713. cg.a_param_reg(current_asmdata.CurrAsmList,OS_ADDR,location.reference.base,paraloc1);
  714. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  715. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  716. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_CHECKZERO',false);
  717. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  718. end;
  719. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  720. if is_ansistring(left.resultdef) then
  721. offsetdec:=1
  722. else
  723. offsetdec:=2;
  724. location.reference.alignment:=offsetdec;
  725. dec(location.reference.offset,offsetdec);
  726. end
  727. else if is_dynamic_array(left.resultdef) then
  728. begin
  729. case left.location.loc of
  730. LOC_REGISTER,
  731. LOC_CREGISTER :
  732. location.reference.base:=left.location.register;
  733. LOC_REFERENCE,
  734. LOC_CREFERENCE :
  735. begin
  736. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  737. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  738. left.location.reference,location.reference.base);
  739. end;
  740. else
  741. internalerror(2002032219);
  742. end;
  743. { a dynarray points to the start of a memory block, which
  744. we assume to be always aligned to a multiple of the
  745. pointer size
  746. }
  747. location.reference.alignment:=sizeof(pint);
  748. end
  749. else
  750. location_copy(location,left.location);
  751. { location must be memory }
  752. if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  753. internalerror(200411013);
  754. { offset can only differ from 0 if arraydef }
  755. if (left.resultdef.typ=arraydef) and
  756. not(is_dynamic_array(left.resultdef)) and
  757. (not(is_packed_array(left.resultdef)) or
  758. ((mulsize mod 8 = 0) and
  759. ispowerof2(mulsize div 8,temp)) or
  760. { only orddefs are bitpacked }
  761. not is_ordinal(resultdef)
  762. {$ifndef cpu64bitalu}
  763. or is_64bitint(resultdef)
  764. {$endif not cpu64bitalu}
  765. ) then
  766. dec(location.reference.offset,bytemulsize*tarraydef(left.resultdef).lowrange);
  767. if right.nodetype=ordconstn then
  768. begin
  769. { offset can only differ from 0 if arraydef }
  770. case left.resultdef.typ of
  771. arraydef :
  772. begin
  773. { do not do any range checking when this is an array access to a pointer which has been
  774. typecasted from an array }
  775. if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
  776. begin
  777. if not(is_open_array(left.resultdef)) and
  778. not(is_array_of_const(left.resultdef)) and
  779. not(is_dynamic_array(left.resultdef)) then
  780. begin
  781. if (tordconstnode(right).value.svalue>tarraydef(left.resultdef).highrange) or
  782. (tordconstnode(right).value.svalue<tarraydef(left.resultdef).lowrange) then
  783. begin
  784. { this should be caught in the typecheckpass! (JM) }
  785. if (cs_check_range in current_settings.localswitches) then
  786. CGMessage(parser_e_range_check_error)
  787. else
  788. CGMessage(parser_w_range_check_error);
  789. end;
  790. end
  791. else
  792. begin
  793. { range checking for open and dynamic arrays needs
  794. runtime code }
  795. secondpass(right);
  796. if (cs_check_range in current_settings.localswitches) then
  797. rangecheck_array;
  798. end;
  799. end;
  800. end;
  801. stringdef :
  802. begin
  803. if (cs_check_range in current_settings.localswitches) then
  804. begin
  805. case tstringdef(left.resultdef).stringtype of
  806. { it's the same for ansi- and wide strings }
  807. st_unicodestring,
  808. st_widestring,
  809. st_ansistring:
  810. begin
  811. paramanager.getintparaloc(pocall_default,1,paraloc1);
  812. paramanager.getintparaloc(pocall_default,2,paraloc2);
  813. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  814. cg.a_param_const(current_asmdata.CurrAsmList,OS_INT,tordconstnode(right).value.svalue,paraloc2);
  815. href:=location.reference;
  816. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  817. if not(tf_winlikewidestring in target_info.flags) or
  818. (tstringdef(left.resultdef).stringtype<>st_widestring) then
  819. begin
  820. dec(href.offset,sizeof(pint)-offsetdec);
  821. cg.a_param_ref(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
  822. end
  823. else
  824. begin
  825. { winlike widestrings have a 4 byte length }
  826. dec(href.offset,4-offsetdec);
  827. cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  828. end;
  829. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  830. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  831. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  832. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
  833. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  834. end;
  835. st_shortstring:
  836. begin
  837. {!!!!!!!!!!!!!!!!!}
  838. { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
  839. end;
  840. st_longstring:
  841. begin
  842. {!!!!!!!!!!!!!!!!!}
  843. end;
  844. end;
  845. end;
  846. end;
  847. end;
  848. if not(is_packed_array(left.resultdef)) or
  849. ((mulsize mod 8 = 0) and
  850. (ispowerof2(mulsize div 8,temp) or
  851. { only orddefs are bitpacked }
  852. not is_ordinal(resultdef))) then
  853. begin
  854. extraoffset:=bytemulsize*tordconstnode(right).value.svalue;
  855. inc(location.reference.offset,extraoffset);
  856. { adjust alignment after to this change }
  857. location.reference.alignment:=newalignment(location.reference.alignment,extraoffset);
  858. { don't do this for floats etc.; needed to properly set the }
  859. { size for bitpacked arrays (e.g. a bitpacked array of }
  860. { enums who are size 2 but fit in one byte -> in the array }
  861. { they will be one byte and have to be stored like that) }
  862. if is_packed_array(left.resultdef) and
  863. (tcgsize2size[newsize] <> bytemulsize) then
  864. newsize:=int_cgsize(bytemulsize);
  865. end
  866. else
  867. begin
  868. subsetref.ref := location.reference;
  869. subsetref.ref.alignment := left.resultdef.alignment;
  870. if not ispowerof2(subsetref.ref.alignment,temp) then
  871. internalerror(2006081212);
  872. alignpow:=temp;
  873. inc(subsetref.ref.offset,((mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow)) shl alignpow);
  874. subsetref.bitindexreg := NR_NO;
  875. subsetref.startbit := (mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) and ((1 shl (3+alignpow))-1);
  876. subsetref.bitlen := resultdef.packedbitsize;
  877. if (left.location.loc = LOC_REFERENCE) then
  878. location.loc := LOC_SUBSETREF
  879. else
  880. location.loc := LOC_CSUBSETREF;
  881. location.sref := subsetref;
  882. end;
  883. end
  884. else
  885. { not nodetype=ordconstn }
  886. begin
  887. if (cs_opt_level1 in current_settings.optimizerswitches) and
  888. { if we do range checking, we don't }
  889. { need that fancy code (it would be }
  890. { buggy) }
  891. not(cs_check_range in current_settings.localswitches) and
  892. (left.resultdef.typ=arraydef) and
  893. not is_packed_array(left.resultdef) then
  894. begin
  895. extraoffset:=0;
  896. if (right.nodetype=addn) then
  897. begin
  898. if taddnode(right).right.nodetype=ordconstn then
  899. begin
  900. extraoffset:=tordconstnode(taddnode(right).right).value.svalue;
  901. t:=taddnode(right).left;
  902. taddnode(right).left:=nil;
  903. right.free;
  904. right:=t;
  905. end
  906. else if taddnode(right).left.nodetype=ordconstn then
  907. begin
  908. extraoffset:=tordconstnode(taddnode(right).left).value.svalue;
  909. t:=taddnode(right).right;
  910. taddnode(right).right:=nil;
  911. right.free;
  912. right:=t;
  913. end;
  914. end
  915. else if (right.nodetype=subn) then
  916. begin
  917. if taddnode(right).right.nodetype=ordconstn then
  918. begin
  919. extraoffset:=-tordconstnode(taddnode(right).right).value.svalue;
  920. t:=taddnode(right).left;
  921. taddnode(right).left:=nil;
  922. right.free;
  923. right:=t;
  924. end;
  925. end;
  926. inc(location.reference.offset,
  927. mulsize*extraoffset);
  928. end;
  929. { calculate from left to right }
  930. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  931. internalerror(200304237);
  932. isjump:=(right.expectloc=LOC_JUMP);
  933. if isjump then
  934. begin
  935. otl:=current_procinfo.CurrTrueLabel;
  936. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  937. ofl:=current_procinfo.CurrFalseLabel;
  938. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  939. end;
  940. secondpass(right);
  941. { if mulsize = 1, we won't have to modify the index }
  942. location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,true);
  943. if isjump then
  944. begin
  945. current_procinfo.CurrTrueLabel:=otl;
  946. current_procinfo.CurrFalseLabel:=ofl;
  947. end
  948. else if (right.location.loc = LOC_JUMP) then
  949. internalerror(2006010801);
  950. { produce possible range check code: }
  951. if cs_check_range in current_settings.localswitches then
  952. begin
  953. if left.resultdef.typ=arraydef then
  954. begin
  955. { do not do any range checking when this is an array access to a pointer which has been
  956. typecasted from an array }
  957. if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
  958. rangecheck_array
  959. end
  960. else if (left.resultdef.typ=stringdef) then
  961. begin
  962. case tstringdef(left.resultdef).stringtype of
  963. { it's the same for ansi- and wide strings }
  964. st_unicodestring,
  965. st_widestring,
  966. st_ansistring:
  967. begin
  968. paramanager.getintparaloc(pocall_default,1,paraloc1);
  969. paramanager.getintparaloc(pocall_default,2,paraloc2);
  970. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  971. cg.a_param_reg(current_asmdata.CurrAsmList,OS_INT,right.location.register,paraloc2);
  972. href:=location.reference;
  973. dec(href.offset,sizeof(pint)-offsetdec);
  974. href:=location.reference;
  975. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  976. if not(tf_winlikewidestring in target_info.flags) or
  977. (tstringdef(left.resultdef).stringtype<>st_widestring) then
  978. begin
  979. dec(href.offset,sizeof(pint)-offsetdec);
  980. cg.a_param_ref(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
  981. end
  982. else
  983. begin
  984. { winlike widestrings have a 4 byte length }
  985. dec(href.offset,4-offsetdec);
  986. cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  987. end;
  988. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  989. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  990. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  991. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
  992. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  993. end;
  994. st_shortstring:
  995. begin
  996. {!!!!!!!!!!!!!!!!!}
  997. end;
  998. st_longstring:
  999. begin
  1000. {!!!!!!!!!!!!!!!!!}
  1001. end;
  1002. end;
  1003. end;
  1004. end;
  1005. { insert the register and the multiplication factor in the
  1006. reference }
  1007. if not is_packed_array(left.resultdef) then
  1008. update_reference_reg_mul(right.location.register,mulsize)
  1009. else
  1010. update_reference_reg_packed(right.location.register,mulsize);
  1011. end;
  1012. location.size:=newsize;
  1013. paraloc1.done;
  1014. paraloc2.done;
  1015. end;
  1016. begin
  1017. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  1018. cloadparentfpnode:=tcgloadparentfpnode;
  1019. caddrnode:=tcgaddrnode;
  1020. cderefnode:=tcgderefnode;
  1021. csubscriptnode:=tcgsubscriptnode;
  1022. cwithnode:=tcgwithnode;
  1023. cvecnode:=tcgvecnode;
  1024. end.