ncgmem.pas 40 KB

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