ncgmem.pas 45 KB

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