ncgmem.pas 46 KB

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