ncgmem.pas 46 KB

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