ncgmem.pas 44 KB

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