ncgmem.pas 42 KB

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