ncgld.pas 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that handle loads and assignments which
  5. are 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. unit ncgld;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nld;
  24. type
  25. tcgloadnode = class(tloadnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgarrayconstructornode = class(tarrayconstructornode)
  32. procedure pass_2;override;
  33. end;
  34. implementation
  35. uses
  36. systems,
  37. verbose,globtype,globals,
  38. symconst,symtype,symdef,symsym,symtable,defutil,paramgr,
  39. ncnv,ncon,nmem,
  40. aasmbase,aasmtai,aasmcpu,regvars,
  41. cginfo,cgbase,pass_2,
  42. cpubase,cpuinfo,
  43. tgobj,ncgutil,cgobj,rgobj;
  44. {*****************************************************************************
  45. SecondLoad
  46. *****************************************************************************}
  47. procedure tcgloadnode.pass_2;
  48. var
  49. r,hregister : tregister;
  50. supreg:Tsuperregister;
  51. symtabletype : tsymtabletype;
  52. i : longint;
  53. href : treference;
  54. newsize : tcgsize;
  55. {$ifndef newra}
  56. pushed : tpushedsavedint;
  57. {$endif}
  58. dorelocatelab,
  59. norelocatelab : tasmlabel;
  60. begin
  61. { we don't know the size of all arrays }
  62. newsize:=def_cgsize(resulttype.def);
  63. location_reset(location,LOC_REFERENCE,newsize);
  64. case symtableentry.typ of
  65. absolutesym :
  66. begin
  67. { this is only for toasm and toaddr }
  68. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  69. begin
  70. {$ifdef i386}
  71. if tabsolutesym(symtableentry).absseg then
  72. location.reference.segment.enum:=R_FS;
  73. {$endif i386}
  74. location.reference.offset:=tabsolutesym(symtableentry).address;
  75. end
  76. else
  77. location.reference.symbol:=objectlibrary.newasmsymboldata(tabsolutesym(symtableentry).mangledname);
  78. end;
  79. constsym:
  80. begin
  81. if tconstsym(symtableentry).consttyp=constresourcestring then
  82. begin
  83. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  84. location.reference.symbol:=objectlibrary.newasmsymboldata(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  85. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  86. end
  87. else
  88. internalerror(22798);
  89. end;
  90. varsym :
  91. begin
  92. if (tvarsym(symtableentry).varspez=vs_const) then
  93. location_reset(location,LOC_CREFERENCE,newsize);
  94. symtabletype:=symtable.symtabletype;
  95. hregister.enum:=R_NO;
  96. { C variable }
  97. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  98. begin
  99. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  100. end
  101. { DLL variable }
  102. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  103. begin
  104. hregister:=rg.getaddressregister(exprasmlist);
  105. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  106. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
  107. reference_reset_base(location.reference,hregister,0);
  108. end
  109. { external variable }
  110. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  111. begin
  112. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  113. end
  114. { thread variable }
  115. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  116. begin
  117. objectlibrary.getlabel(dorelocatelab);
  118. objectlibrary.getlabel(norelocatelab);
  119. { we've to allocate the register before we save the used registers }
  120. hregister:=rg.getaddressregister(exprasmlist);
  121. reference_reset_symbol(href,objectlibrary.newasmsymboldata('FPC_THREADVAR_RELOCATE'),0);
  122. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  123. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_NE,0,hregister,dorelocatelab);
  124. { no relocation needed, load the address of the variable only, the
  125. layout of a threadvar is (4 bytes pointer):
  126. 0 - Threadvar index
  127. 4 - Threadvar value in single threading }
  128. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),POINTER_SIZE);
  129. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  130. cg.a_jmp_always(exprasmlist,norelocatelab);
  131. cg.a_label(exprasmlist,dorelocatelab);
  132. { don't save the allocated register else the result will be destroyed later }
  133. {$ifndef newra}
  134. rg.saveusedintregisters(exprasmlist,pushed,[RS_FUNCTION_RESULT_REG]-[hregister.number shr 8]);
  135. {$endif}
  136. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
  137. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  138. {$ifdef newra}
  139. rg.ungetregisterint(exprasmlist,hregister);
  140. r:=rg.getexplicitregisterint(exprasmlist,NR_EAX);
  141. {$endif}
  142. { the called procedure isn't allowed to change }
  143. { any register except EAX }
  144. cg.a_call_reg(exprasmlist,hregister);
  145. {$ifdef newra}
  146. rg.ungetregisterint(exprasmlist,r);
  147. hregister:=rg.getregisterint(exprasmlist,OS_ADDR);
  148. {$else}
  149. r.enum:=R_INTREGISTER;
  150. r.number:=NR_FUNCTION_RESULT_REG;
  151. {$endif}
  152. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
  153. {$ifndef newra}
  154. rg.restoreusedintregisters(exprasmlist,pushed);
  155. {$endif}
  156. cg.a_label(exprasmlist,norelocatelab);
  157. location.reference.base:=hregister;
  158. end
  159. { normal variable }
  160. else
  161. begin
  162. { in case it is a register variable: }
  163. if tvarsym(symtableentry).reg.enum<>R_NO then
  164. begin
  165. if tvarsym(symtableentry).reg.enum in fpuregs then
  166. begin
  167. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  168. location.register:=tvarsym(symtableentry).reg;
  169. end
  170. else if Tvarsym(symtableentry).reg.enum=R_INTREGISTER then
  171. begin
  172. supreg:=Tvarsym(symtableentry).reg.number shr 8;
  173. if (supreg in general_superregisters) and
  174. not (supreg in rg.regvar_loaded_int) then
  175. load_regvar(exprasmlist,tvarsym(symtableentry));
  176. location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
  177. location.register:=tvarsym(symtableentry).reg;
  178. exclude(rg.unusedregsint,supreg);
  179. end
  180. else
  181. internalerror(200301172);
  182. end
  183. else
  184. begin
  185. case symtabletype of
  186. localsymtable,
  187. parasymtable,
  188. inlinelocalsymtable,
  189. inlineparasymtable :
  190. begin
  191. location.reference.base:=current_procinfo.framepointer;
  192. location.reference.offset:=tvarsym(symtableentry).adjusted_address;
  193. if (current_procdef.parast.symtablelevel>symtable.symtablelevel) then
  194. begin
  195. hregister:=rg.getaddressregister(exprasmlist);
  196. { make a reference }
  197. reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
  198. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  199. { walk parents }
  200. i:=current_procdef.parast.symtablelevel-1;
  201. while (i>symtable.symtablelevel) do
  202. begin
  203. { make a reference }
  204. {$ifdef powerpc}
  205. reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
  206. {$else powerpc}
  207. reference_reset_base(href,hregister,target_info.first_parm_offset);
  208. {$endif powerpc}
  209. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  210. dec(i);
  211. end;
  212. location.reference.base:=hregister;
  213. end;
  214. end;
  215. globalsymtable,
  216. staticsymtable :
  217. begin
  218. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  219. end;
  220. stt_exceptsymtable:
  221. begin
  222. location.reference.base:=current_procinfo.framepointer;
  223. location.reference.offset:=tvarsym(symtableentry).address;
  224. end;
  225. else
  226. internalerror(200305102);
  227. end;
  228. end;
  229. end;
  230. { handle call by reference variables, ignore the reference
  231. when we need to load the self pointer for objects }
  232. if (symtabletype in [parasymtable,inlineparasymtable]) and
  233. not(nf_load_self_pointer in flags) and
  234. (
  235. (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  236. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption)
  237. ) then
  238. begin
  239. if hregister.enum=R_NO then
  240. hregister:=rg.getaddressregister(exprasmlist);
  241. { we need to load only an address }
  242. location.size:=OS_ADDR;
  243. cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
  244. if tvarsym(symtableentry).varspez=vs_const then
  245. location_reset(location,LOC_CREFERENCE,newsize)
  246. else
  247. location_reset(location,LOC_REFERENCE,newsize);
  248. location.reference.base:=hregister;
  249. end;
  250. end;
  251. procsym:
  252. begin
  253. if assigned(left) then
  254. begin
  255. {
  256. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  257. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  258. CONSISTS OF TWO OS_ADDR, so you cannot set it
  259. to OS_64 - how to solve?? Carl
  260. }
  261. if (sizeof(aword) = 4) then
  262. location_reset(location,LOC_CREFERENCE,OS_64)
  263. else
  264. internalerror(20020520);
  265. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  266. secondpass(left);
  267. { load class instance address }
  268. case left.location.loc of
  269. LOC_CREGISTER,
  270. LOC_REGISTER:
  271. begin
  272. { this is not possible for objects }
  273. if is_object(left.resulttype.def) then
  274. internalerror(200304234);
  275. hregister:=left.location.register;
  276. end;
  277. LOC_CREFERENCE,
  278. LOC_REFERENCE:
  279. begin
  280. hregister:=rg.getaddressregister(exprasmlist);
  281. if is_class_or_interface(left.resulttype.def) then
  282. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  283. else
  284. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  285. location_release(exprasmlist,left.location);
  286. location_freetemp(exprasmlist,left.location);
  287. end;
  288. else
  289. internalerror(26019);
  290. end;
  291. { store the class instance address }
  292. href:=location.reference;
  293. inc(href.offset,POINTER_SIZE);
  294. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,href);
  295. { virtual method ? }
  296. if (po_virtualmethod in procdef.procoptions) then
  297. begin
  298. { load vmt pointer }
  299. reference_reset_base(href,hregister,0);
  300. reference_release(exprasmlist,href);
  301. hregister:=rg.getaddressregister(exprasmlist);
  302. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  303. reference_reset_base(href,hregister,
  304. procdef._class.vmtmethodoffset(procdef.extnumber));
  305. reference_release(exprasmlist,href);
  306. { load method address }
  307. hregister:=rg.getaddressregister(exprasmlist);
  308. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  309. { ... and store it }
  310. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  311. rg.ungetaddressregister(exprasmlist,hregister);
  312. end
  313. else
  314. begin
  315. { we don't use the hregister }
  316. rg.ungetregisterint(exprasmlist,hregister);
  317. { load address of the function }
  318. reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname),0);
  319. {$ifdef newra}
  320. hregister:=rg.getaddressregister(exprasmlist);
  321. {$else}
  322. hregister:=cg.get_scratch_reg_address(exprasmlist);
  323. {$endif}
  324. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  325. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  326. {$ifdef newra}
  327. rg.ungetregisterint(exprasmlist,hregister);
  328. {$else newra}
  329. cg.free_scratch_reg(exprasmlist,hregister);
  330. {$endif}
  331. end;
  332. end
  333. else
  334. begin
  335. {!!!!! Be aware, work on virtual methods too }
  336. location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname);
  337. end;
  338. end;
  339. typedconstsym :
  340. begin
  341. location.reference.symbol:=objectlibrary.newasmsymboldata(ttypedconstsym(symtableentry).mangledname);
  342. end;
  343. else internalerror(4);
  344. end;
  345. end;
  346. {*****************************************************************************
  347. SecondAssignment
  348. *****************************************************************************}
  349. procedure tcgassignmentnode.pass_2;
  350. var
  351. otlabel,hlabel,oflabel : tasmlabel;
  352. fputyp : tfloattype;
  353. href : treference;
  354. old_allow_multi_pass2,
  355. releaseright : boolean;
  356. pushedregs : tmaybesave;
  357. cgsize : tcgsize;
  358. r:Tregister;
  359. begin
  360. location_reset(location,LOC_VOID,OS_NO);
  361. otlabel:=truelabel;
  362. oflabel:=falselabel;
  363. objectlibrary.getlabel(truelabel);
  364. objectlibrary.getlabel(falselabel);
  365. {
  366. in most cases we can process first the right node which contains
  367. the most complex code. But not when the result is in the flags, then
  368. loading the left node afterwards can destroy the flags.
  369. when the right node returns as LOC_JUMP then we will generate
  370. the following code:
  371. rightnode
  372. true:
  373. leftnode
  374. assign 1
  375. false:
  376. leftnode
  377. assign 0
  378. }
  379. { Try to determine which side to calculate first, }
  380. if (right.expectloc<>LOC_FLAGS) and
  381. ((right.expectloc=LOC_JUMP) or
  382. (right.nodetype=calln) or
  383. (right.registers32>=left.registers32)) then
  384. begin
  385. secondpass(right);
  386. { increment source reference counter, this is
  387. useless for string constants}
  388. if (right.resulttype.def.needs_inittable) and
  389. (right.nodetype<>stringconstn) then
  390. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
  391. if codegenerror then
  392. exit;
  393. { We skip the generation of the left node when it's a jump, see
  394. explanation above }
  395. if (right.location.loc<>LOC_JUMP) and
  396. not(nf_concat_string in flags) then
  397. begin
  398. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  399. { can be false }
  400. {$ifndef newra}
  401. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  402. {$endif}
  403. secondpass(left);
  404. { decrement destination reference counter }
  405. if (left.resulttype.def.needs_inittable) then
  406. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
  407. {$ifndef newra}
  408. maybe_restore(exprasmlist,right.location,pushedregs);
  409. {$endif newra}
  410. if codegenerror then
  411. exit;
  412. end;
  413. end
  414. else
  415. begin
  416. { calculate left sides }
  417. { don't do it yet if it's a crgister (JM) }
  418. if not(nf_concat_string in flags) then
  419. begin
  420. secondpass(left);
  421. { decrement destination reference counter }
  422. if (left.resulttype.def.needs_inittable) then
  423. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
  424. if codegenerror then
  425. exit;
  426. end;
  427. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  428. { can be false }
  429. {$ifndef newra}
  430. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  431. {$endif newra}
  432. secondpass(right);
  433. { increment source reference counter, this is
  434. useless for string constants}
  435. if (right.resulttype.def.needs_inittable) and
  436. (right.nodetype<>stringconstn) then
  437. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
  438. {$ifndef newra}
  439. maybe_restore(exprasmlist,left.location,pushedregs);
  440. {$endif}
  441. if codegenerror then
  442. exit;
  443. end;
  444. releaseright:=true;
  445. { shortstring assignments are handled separately }
  446. if is_shortstring(left.resulttype.def) then
  447. begin
  448. {
  449. we can get here only in the following situations
  450. for the right node:
  451. - empty constant string
  452. - char
  453. }
  454. { empty constant string }
  455. if (right.nodetype=stringconstn) and
  456. (tstringconstnode(right).len=0) then
  457. begin
  458. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  459. end
  460. { char loading }
  461. else if is_char(right.resulttype.def) then
  462. begin
  463. if right.nodetype=ordconstn then
  464. begin
  465. if (target_info.endian = endian_little) then
  466. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  467. left.location.reference)
  468. else
  469. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  470. left.location.reference);
  471. end
  472. else
  473. begin
  474. href:=left.location.reference;
  475. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  476. inc(href.offset,1);
  477. case right.location.loc of
  478. LOC_REGISTER,
  479. LOC_CREGISTER :
  480. begin
  481. r:=rg.makeregsize(right.location.register,OS_8);
  482. cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
  483. end;
  484. LOC_REFERENCE,
  485. LOC_CREFERENCE :
  486. cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
  487. else
  488. internalerror(200205111);
  489. end;
  490. end;
  491. end
  492. else
  493. internalerror(200204249);
  494. end
  495. else
  496. begin
  497. case right.location.loc of
  498. LOC_CONSTANT :
  499. begin
  500. if right.location.size in [OS_64,OS_S64] then
  501. cg64.a_load64_const_loc(exprasmlist,
  502. right.location.valueqword,left.location)
  503. else
  504. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  505. end;
  506. LOC_REFERENCE,
  507. LOC_CREFERENCE :
  508. begin
  509. case left.location.loc of
  510. LOC_CREGISTER :
  511. begin
  512. cgsize:=def_cgsize(left.resulttype.def);
  513. if cgsize in [OS_64,OS_S64] then
  514. cg64.a_load64_ref_reg(exprasmlist,
  515. right.location.reference,left.location.register64{$ifdef newra},false{$endif})
  516. else
  517. cg.a_load_ref_reg(exprasmlist,cgsize,cgsize,
  518. right.location.reference,left.location.register);
  519. location_release(exprasmlist,right.location);
  520. end;
  521. LOC_CFPUREGISTER :
  522. begin
  523. cg.a_loadfpu_ref_reg(exprasmlist,
  524. def_cgsize(right.resulttype.def),
  525. right.location.reference,
  526. left.location.register);
  527. end;
  528. LOC_REFERENCE,
  529. LOC_CREFERENCE :
  530. begin
  531. cg.g_concatcopy(exprasmlist,right.location.reference,
  532. left.location.reference,left.resulttype.def.size,true,false);
  533. { right.location is already released by concatcopy }
  534. releaseright:=false;
  535. end;
  536. else
  537. internalerror(200203284);
  538. end;
  539. end;
  540. {$ifdef SUPPORT_MMX}
  541. LOC_CMMXREGISTER,
  542. LOC_MMXREGISTER:
  543. begin
  544. if left.location.loc=LOC_CMMXREGISTER then
  545. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  546. else
  547. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  548. end;
  549. {$endif SUPPORT_MMX}
  550. LOC_REGISTER,
  551. LOC_CREGISTER :
  552. begin
  553. cgsize:=def_cgsize(left.resulttype.def);
  554. if cgsize in [OS_64,OS_S64] then
  555. cg64.a_load64_reg_loc(exprasmlist,
  556. right.location.register64,left.location)
  557. else
  558. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  559. end;
  560. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  561. begin
  562. if (left.resulttype.def.deftype=floatdef) then
  563. fputyp:=tfloatdef(left.resulttype.def).typ
  564. else
  565. if (right.resulttype.def.deftype=floatdef) then
  566. fputyp:=tfloatdef(right.resulttype.def).typ
  567. else
  568. if (right.nodetype=typeconvn) and
  569. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  570. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  571. else
  572. fputyp:=s32real;
  573. cg.a_loadfpu_reg_loc(exprasmlist,
  574. tfloat2tcgsize[fputyp],
  575. right.location.register,left.location);
  576. end;
  577. LOC_JUMP :
  578. begin
  579. cgsize:=def_cgsize(left.resulttype.def);
  580. objectlibrary.getlabel(hlabel);
  581. { generate the leftnode for the true case, and
  582. release the location }
  583. cg.a_label(exprasmlist,truelabel);
  584. {$ifndef newra}
  585. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  586. {$endif newra}
  587. secondpass(left);
  588. {$ifndef newra}
  589. maybe_restore(exprasmlist,right.location,pushedregs);
  590. {$endif newra}
  591. if codegenerror then
  592. exit;
  593. cg.a_load_const_loc(exprasmlist,1,left.location);
  594. location_release(exprasmlist,left.location);
  595. cg.a_jmp_always(exprasmlist,hlabel);
  596. { generate the leftnode for the false case }
  597. cg.a_label(exprasmlist,falselabel);
  598. {$ifndef newra}
  599. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  600. {$endif}
  601. old_allow_multi_pass2:=allow_multi_pass2;
  602. allow_multi_pass2:=true;
  603. secondpass(left);
  604. allow_multi_pass2:=old_allow_multi_pass2;
  605. {$ifndef newra}
  606. maybe_restore(exprasmlist,right.location,pushedregs);
  607. {$endif newra}
  608. if codegenerror then
  609. exit;
  610. cg.a_load_const_loc(exprasmlist,0,left.location);
  611. cg.a_label(exprasmlist,hlabel);
  612. end;
  613. {$ifdef cpuflags}
  614. LOC_FLAGS :
  615. begin
  616. {This can be a wordbool or longbool too, no?}
  617. if left.location.loc=LOC_CREGISTER then
  618. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  619. else
  620. begin
  621. if not(left.location.loc = LOC_REFERENCE) then
  622. internalerror(200203273);
  623. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  624. end;
  625. end;
  626. {$endif cpuflags}
  627. end;
  628. end;
  629. if releaseright then
  630. location_release(exprasmlist,right.location);
  631. location_release(exprasmlist,left.location);
  632. truelabel:=otlabel;
  633. falselabel:=oflabel;
  634. end;
  635. {*****************************************************************************
  636. SecondArrayConstruct
  637. *****************************************************************************}
  638. const
  639. vtInteger = 0;
  640. vtBoolean = 1;
  641. vtChar = 2;
  642. vtExtended = 3;
  643. vtString = 4;
  644. vtPointer = 5;
  645. vtPChar = 6;
  646. vtObject = 7;
  647. vtClass = 8;
  648. vtWideChar = 9;
  649. vtPWideChar = 10;
  650. vtAnsiString = 11;
  651. vtCurrency = 12;
  652. vtVariant = 13;
  653. vtInterface = 14;
  654. vtWideString = 15;
  655. vtInt64 = 16;
  656. vtQWord = 17;
  657. procedure tcgarrayconstructornode.pass_2;
  658. var
  659. hp : tarrayconstructornode;
  660. href : treference;
  661. lt : tdef;
  662. vaddr : boolean;
  663. vtype : longint;
  664. freetemp,
  665. dovariant : boolean;
  666. elesize : longint;
  667. tmpreg : tregister;
  668. begin
  669. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  670. if dovariant then
  671. elesize:=8
  672. else
  673. elesize:=tarraydef(resulttype.def).elesize;
  674. if nf_cargs in flags then
  675. location_reset(location,LOC_VOID,OS_NO)
  676. else
  677. location_reset(location,LOC_CREFERENCE,OS_NO);
  678. if not(nf_cargs in flags) then
  679. begin
  680. { Allocate always a temp, also if no elements are required, to
  681. be sure that location is valid (PFV) }
  682. if tarraydef(resulttype.def).highrange=-1 then
  683. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  684. else
  685. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  686. href:=location.reference;
  687. end;
  688. hp:=self;
  689. while assigned(hp) do
  690. begin
  691. if assigned(hp.left) then
  692. begin
  693. freetemp:=true;
  694. secondpass(hp.left);
  695. if codegenerror then
  696. exit;
  697. { Move flags and jump in register }
  698. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  699. location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  700. if dovariant then
  701. begin
  702. { find the correct vtype value }
  703. vtype:=$ff;
  704. vaddr:=false;
  705. lt:=hp.left.resulttype.def;
  706. case lt.deftype of
  707. enumdef,
  708. orddef :
  709. begin
  710. if is_64bit(lt) then
  711. begin
  712. case torddef(lt).typ of
  713. s64bit:
  714. vtype:=vtInt64;
  715. u64bit:
  716. vtype:=vtQWord;
  717. end;
  718. if not(nf_cargs in flags) then
  719. begin
  720. freetemp:=false;
  721. vaddr:=true;
  722. end;
  723. end
  724. else if (lt.deftype=enumdef) or
  725. is_integer(lt) then
  726. vtype:=vtInteger
  727. else
  728. if is_boolean(lt) then
  729. vtype:=vtBoolean
  730. else
  731. if (lt.deftype=orddef) then
  732. begin
  733. case torddef(lt).typ of
  734. uchar:
  735. vtype:=vtChar;
  736. uwidechar:
  737. vtype:=vtWideChar;
  738. end;
  739. end;
  740. end;
  741. floatdef :
  742. begin
  743. vtype:=vtExtended;
  744. if not(nf_cargs in flags) then
  745. begin
  746. freetemp:=false;
  747. vaddr:=true;
  748. end;
  749. end;
  750. procvardef,
  751. pointerdef :
  752. begin
  753. if is_pchar(lt) then
  754. vtype:=vtPChar
  755. else
  756. vtype:=vtPointer;
  757. end;
  758. variantdef :
  759. begin
  760. vtype:=vtVariant;
  761. vaddr:=true;
  762. freetemp:=false;
  763. end;
  764. classrefdef :
  765. vtype:=vtClass;
  766. objectdef :
  767. vtype:=vtObject;
  768. stringdef :
  769. begin
  770. if is_shortstring(lt) then
  771. begin
  772. vtype:=vtString;
  773. vaddr:=true;
  774. freetemp:=false;
  775. end
  776. else
  777. if is_ansistring(lt) then
  778. begin
  779. vtype:=vtAnsiString;
  780. freetemp:=false;
  781. end
  782. else
  783. if is_widestring(lt) then
  784. begin
  785. vtype:=vtWideString;
  786. freetemp:=false;
  787. end;
  788. end;
  789. end;
  790. if vtype=$ff then
  791. internalerror(14357);
  792. { write C style pushes or an pascal array }
  793. if nf_cargs in flags then
  794. begin
  795. if vaddr then
  796. begin
  797. location_force_mem(exprasmlist,hp.left.location);
  798. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  799. location_release(exprasmlist,hp.left.location);
  800. if freetemp then
  801. location_freetemp(exprasmlist,hp.left.location);
  802. inc(pushedparasize,pointer_size);
  803. end
  804. else
  805. if vtype in [vtInt64,vtQword,vtExtended] then
  806. push_value_para(exprasmlist,hp.left,pocall_cdecl,0,4,paralocdummy)
  807. else
  808. begin
  809. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  810. inc(pushedparasize,pointer_size);
  811. end;
  812. end
  813. else
  814. begin
  815. { write changing field update href to the next element }
  816. inc(href.offset,4);
  817. if vaddr then
  818. begin
  819. location_force_mem(exprasmlist,hp.left.location);
  820. {$ifdef newra}
  821. tmpreg:=rg.getaddressregister(exprasmlist);
  822. {$else}
  823. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  824. {$endif}
  825. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  826. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  827. {$ifdef newra}
  828. rg.ungetregisterint(exprasmlist,tmpreg);
  829. {$else}
  830. cg.free_scratch_reg(exprasmlist,tmpreg);
  831. {$endif}
  832. location_release(exprasmlist,hp.left.location);
  833. if freetemp then
  834. location_freetemp(exprasmlist,hp.left.location);
  835. end
  836. else
  837. begin
  838. location_release(exprasmlist,hp.left.location);
  839. cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
  840. end;
  841. { update href to the vtype field and write it }
  842. dec(href.offset,4);
  843. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  844. { goto next array element }
  845. inc(href.offset,8);
  846. end;
  847. end
  848. else
  849. { normal array constructor of the same type }
  850. begin
  851. if is_ansistring(left.resulttype.def) or
  852. is_widestring(left.resulttype.def) or
  853. (left.resulttype.def.deftype=variantdef) then
  854. freetemp:=false;
  855. location_release(exprasmlist,hp.left.location);
  856. case hp.left.location.loc of
  857. LOC_FPUREGISTER,
  858. LOC_CFPUREGISTER :
  859. begin
  860. location_release(exprasmlist,hp.left.location);
  861. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  862. end;
  863. LOC_REFERENCE,
  864. LOC_CREFERENCE :
  865. begin
  866. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  867. end;
  868. else
  869. begin
  870. if hp.left.location.size in [OS_64,OS_S64] then
  871. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  872. else
  873. cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
  874. end;
  875. end;
  876. inc(href.offset,elesize);
  877. end;
  878. end;
  879. { load next entry }
  880. hp:=tarrayconstructornode(hp.right);
  881. end;
  882. end;
  883. begin
  884. cloadnode:=tcgloadnode;
  885. cassignmentnode:=tcgassignmentnode;
  886. carrayconstructornode:=tcgarrayconstructornode;
  887. end.
  888. {
  889. $Log$
  890. Revision 1.66 2003-06-03 21:11:09 peter
  891. * cg.a_load_* get a from and to size specifier
  892. * makeregsize only accepts newregister
  893. * i386 uses generic tcgnotnode,tcgunaryminus
  894. Revision 1.65 2003/06/03 13:01:59 daniel
  895. * Register allocator finished
  896. Revision 1.64 2003/05/30 23:57:08 peter
  897. * more sparc cleanup
  898. * accumulator removed, splitted in function_return_reg (called) and
  899. function_result_reg (caller)
  900. Revision 1.63 2003/05/30 23:54:08 jonas
  901. * forgot to commit, a_load_loc_reg change
  902. Revision 1.62 2003/05/26 19:38:28 peter
  903. * generic fpc_shorstr_concat
  904. + fpc_shortstr_append_shortstr optimization
  905. Revision 1.61 2003/05/24 11:47:27 jonas
  906. * fixed framepointer storage: it's now always stored at r1+12, which is
  907. a place in the link area reserved for compiler use.
  908. Revision 1.60 2003/05/23 14:27:35 peter
  909. * remove some unit dependencies
  910. * current_procinfo changes to store more info
  911. Revision 1.59 2003/05/15 18:58:53 peter
  912. * removed selfpointer_offset, vmtpointer_offset
  913. * tvarsym.adjusted_address
  914. * address in localsymtable is now in the real direction
  915. * removed some obsolete globals
  916. Revision 1.58 2003/05/12 17:22:00 jonas
  917. * fixed (last?) remaining -tvarsym(X).address to
  918. tg.direction*tvarsym(X).address...
  919. Revision 1.57 2003/05/11 21:37:03 peter
  920. * moved implicit exception frame from ncgutil to psub
  921. * constructor/destructor helpers moved from cobj/ncgutil to psub
  922. Revision 1.56 2003/05/11 14:45:12 peter
  923. * tloadnode does not support objectsymtable,withsymtable anymore
  924. * withnode cleanup
  925. * direct with rewritten to use temprefnode
  926. Revision 1.55 2003/04/29 07:29:14 michael
  927. + Patch from peter to fix wrong pushing of ansistring function results in open array
  928. Revision 1.54 2003/04/27 11:21:33 peter
  929. * aktprocdef renamed to current_procdef
  930. * procinfo renamed to current_procinfo
  931. * procinfo will now be stored in current_module so it can be
  932. cleaned up properly
  933. * gen_main_procsym changed to create_main_proc and release_main_proc
  934. to also generate a tprocinfo structure
  935. * fixed unit implicit initfinal
  936. Revision 1.53 2003/04/27 07:29:50 peter
  937. * current_procdef cleanup, current_procdef is now always nil when parsing
  938. a new procdef declaration
  939. * aktprocsym removed
  940. * lexlevel removed, use symtable.symtablelevel instead
  941. * implicit init/final code uses the normal genentry/genexit
  942. * funcret state checking updated for new funcret handling
  943. Revision 1.52 2003/04/25 20:59:33 peter
  944. * removed funcretn,funcretsym, function result is now in varsym
  945. and aliases for result and function name are added using absolutesym
  946. * vs_hidden parameter for funcret passed in parameter
  947. * vs_hidden fixes
  948. * writenode changed to printnode and released from extdebug
  949. * -vp option added to generate a tree.log with the nodetree
  950. * nicer printnode for statements, callnode
  951. Revision 1.51 2003/04/23 20:16:04 peter
  952. + added currency support based on int64
  953. + is_64bit for use in cg units instead of is_64bitint
  954. * removed cgmessage from n386add, replace with internalerrors
  955. Revision 1.50 2003/04/23 10:12:14 peter
  956. * allow multi pass2 changed to global boolean instead of node flag
  957. Revision 1.49 2003/04/22 23:50:22 peter
  958. * firstpass uses expectloc
  959. * checks if there are differences between the expectloc and
  960. location.loc from secondpass in EXTDEBUG
  961. Revision 1.48 2003/04/22 10:09:35 daniel
  962. + Implemented the actual register allocator
  963. + Scratch registers unavailable when new register allocator used
  964. + maybe_save/maybe_restore unavailable when new register allocator used
  965. Revision 1.47 2003/04/06 21:11:23 olle
  966. * changed newasmsymbol to newasmsymboldata for data symbols
  967. Revision 1.46 2003/03/28 19:16:56 peter
  968. * generic constructor working for i386
  969. * remove fixed self register
  970. * esi added as address register for i386
  971. Revision 1.45 2003/02/19 22:00:14 daniel
  972. * Code generator converted to new register notation
  973. - Horribily outdated todo.txt removed
  974. Revision 1.44 2003/01/08 18:43:56 daniel
  975. * Tregister changed into a record
  976. Revision 1.43 2003/01/05 22:44:14 peter
  977. * remove a lot of code to support typen in loadn-procsym
  978. Revision 1.42 2002/12/20 18:13:46 peter
  979. * fixes for fpu values in arrayconstructor
  980. Revision 1.41 2002/11/27 20:04:39 peter
  981. * cdecl array of const fixes
  982. Revision 1.40 2002/11/25 17:43:18 peter
  983. * splitted defbase in defutil,symutil,defcmp
  984. * merged isconvertable and is_equal into compare_defs(_ext)
  985. * made operator search faster by walking the list only once
  986. Revision 1.39 2002/11/22 16:22:45 jonas
  987. * fixed error in my previous commit (the size of the location of the
  988. funcretnode must be based on the current resulttype of the node and not
  989. the resulttype defined by the function; these can be different in case
  990. of "absolute" declarations)
  991. Revision 1.38 2002/11/18 17:31:54 peter
  992. * pass proccalloption to ret_in_xxx and push_xxx functions
  993. Revision 1.37 2002/11/15 21:16:39 jonas
  994. * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
  995. function was handled wrong inside nested functions/procedures)
  996. Revision 1.36 2002/11/15 01:58:51 peter
  997. * merged changes from 1.0.7 up to 04-11
  998. - -V option for generating bug report tracing
  999. - more tracing for option parsing
  1000. - errors for cdecl and high()
  1001. - win32 import stabs
  1002. - win32 records<=8 are returned in eax:edx (turned off by default)
  1003. - heaptrc update
  1004. - more info for temp management in .s file with EXTDEBUG
  1005. Revision 1.35 2002/10/14 19:44:13 peter
  1006. * (hacked) new threadvar relocate code
  1007. Revision 1.34 2002/10/13 11:22:06 florian
  1008. * fixed threadvars
  1009. Revision 1.33 2002/10/03 21:32:02 carl
  1010. * bugfix for 2110 (without -Or), wrong checking was done in returntype
  1011. Revision 1.32 2002/09/30 07:00:46 florian
  1012. * fixes to common code to get the alpha compiler compiled applied
  1013. Revision 1.31 2002/09/26 15:02:05 florian
  1014. + support of passing variants to "array of const"
  1015. Revision 1.30 2002/09/17 18:54:02 jonas
  1016. * a_load_reg_reg() now has two size parameters: source and dest. This
  1017. allows some optimizations on architectures that don't encode the
  1018. register size in the register name.
  1019. Revision 1.29 2002/09/07 15:25:03 peter
  1020. * old logs removed and tabs fixed
  1021. Revision 1.28 2002/09/01 19:26:32 peter
  1022. * fixed register variable loading from parasymtable, the call by
  1023. reference code was moved wrong
  1024. Revision 1.27 2002/09/01 12:15:40 peter
  1025. * fixed loading of procvar of object when the object is initialized
  1026. with 0
  1027. Revision 1.26 2002/08/25 19:25:18 peter
  1028. * sym.insert_in_data removed
  1029. * symtable.insertvardata/insertconstdata added
  1030. * removed insert_in_data call from symtable.insert, it needs to be
  1031. called separatly. This allows to deref the address calculation
  1032. * procedures now calculate the parast addresses after the procedure
  1033. directives are parsed. This fixes the cdecl parast problem
  1034. * push_addr_param has an extra argument that specifies if cdecl is used
  1035. or not
  1036. Revision 1.25 2002/08/23 16:14:48 peter
  1037. * tempgen cleanup
  1038. * tt_noreuse temp type added that will be used in genentrycode
  1039. Revision 1.24 2002/08/17 09:23:35 florian
  1040. * first part of procinfo rewrite
  1041. Revision 1.23 2002/08/14 18:13:28 jonas
  1042. * adapted previous fix to Peter's asmsymbol patch
  1043. Revision 1.22 2002/08/14 18:00:42 jonas
  1044. * fixed tb0403
  1045. Revision 1.21 2002/08/13 21:40:56 florian
  1046. * more fixes for ppc calling conventions
  1047. Revision 1.20 2002/08/11 14:32:26 peter
  1048. * renamed current_library to objectlibrary
  1049. Revision 1.19 2002/08/11 13:24:12 peter
  1050. * saving of asmsymbols in ppu supported
  1051. * asmsymbollist global is removed and moved into a new class
  1052. tasmlibrarydata that will hold the info of a .a file which
  1053. corresponds with a single module. Added librarydata to tmodule
  1054. to keep the library info stored for the module. In the future the
  1055. objectfiles will also be stored to the tasmlibrarydata class
  1056. * all getlabel/newasmsymbol and friends are moved to the new class
  1057. Revision 1.18 2002/08/06 20:55:21 florian
  1058. * first part of ppc calling conventions fix
  1059. Revision 1.17 2002/07/28 09:25:37 carl
  1060. + correct size of parameter (64-bit portability)
  1061. Revision 1.16 2002/07/27 19:53:51 jonas
  1062. + generic implementation of tcg.g_flags2ref()
  1063. * tcg.flags2xxx() now also needs a size parameter
  1064. Revision 1.15 2002/07/20 11:57:54 florian
  1065. * types.pas renamed to defbase.pas because D6 contains a types
  1066. unit so this would conflicts if D6 programms are compiled
  1067. + Willamette/SSE2 instructions to assembler added
  1068. Revision 1.14 2002/07/16 09:17:44 florian
  1069. * threadvar relocation result wasn't handled properly, it could cause
  1070. a crash
  1071. Revision 1.13 2002/07/11 14:41:28 florian
  1072. * start of the new generic parameter handling
  1073. Revision 1.12 2002/07/07 09:52:32 florian
  1074. * powerpc target fixed, very simple units can be compiled
  1075. * some basic stuff for better callparanode handling, far from being finished
  1076. Revision 1.11 2002/07/01 18:46:23 peter
  1077. * internal linker
  1078. * reorganized aasm layer
  1079. Revision 1.10 2002/07/01 16:23:53 peter
  1080. * cg64 patch
  1081. * basics for currency
  1082. * asnode updates for class and interface (not finished)
  1083. Revision 1.9 2002/05/20 13:30:40 carl
  1084. * bugfix of hdisponen (base must be set, not index)
  1085. * more portability fixes
  1086. }